summaryrefslogtreecommitdiff
path: root/macros/latex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex')
-rw-r--r--macros/latex/contrib/bnumexpr/README.md9
-rw-r--r--macros/latex/contrib/bnumexpr/bnumexpr.dtx277
-rw-r--r--macros/latex/contrib/bnumexpr/bnumexpr.pdfbin88616 -> 96634 bytes
-rw-r--r--macros/latex/contrib/changes/changes.drv2
-rw-r--r--macros/latex/contrib/changes/changes.dtx5
-rw-r--r--macros/latex/contrib/changes/changes.english.pdfbin368902 -> 368904 bytes
-rw-r--r--macros/latex/contrib/changes/changes.english.withcode.pdfbin453200 -> 452979 bytes
-rw-r--r--macros/latex/contrib/changes/changes.ins4
-rw-r--r--macros/latex/contrib/changes/changes.ngerman.pdfbin376311 -> 376315 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.bf.pdfbin85486 -> 85486 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.colored.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.dashuline.pdfbin82935 -> 82935 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.dotuline.pdfbin82553 -> 82553 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.em.pdfbin83749 -> 83749 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.it.pdfbin83749 -> 83749 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.sl.pdfbin84735 -> 84735 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.uline.pdfbin82746 -> 82746 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.uuline.pdfbin85371 -> 85371 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.uwave.pdfbin84759 -> 84759 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.addedmarkup.wrong.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkup.brackets.pdfbin74370 -> 74370 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkup.footnote.pdfbin99663 -> 99663 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkup.none.pdfbin73913 -> 73913 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkup.subscript.pdfbin82294 -> 82294 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkup.superscript.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkup.wrong.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkupposition.left.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkupposition.right.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkupposition.wrong.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkuptext.id.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkuptext.name.pdfbin83846 -> 83846 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.authormarkuptext.wrong.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.commandnameprefix.always.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.commandnameprefix.ifneeded.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.commandnameprefix.none.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.commandnameprefix.wrong.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.commentmarkup.footnote.pdfbin110514 -> 110514 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.commentmarkup.margin.pdfbin78953 -> 78953 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.commentmarkup.todo.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.commentmarkup.uwave.pdfbin81965 -> 81965 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.defaultcolor.pdfbin82299 -> 82299 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.bf.pdfbin84982 -> 84982 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.colored.pdfbin81125 -> 81125 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dashuline.pdfbin82590 -> 82590 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dotuline.pdfbin81687 -> 81687 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.em.pdfbin82891 -> 82891 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.it.pdfbin82891 -> 82891 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sl.pdfbin85110 -> 85110 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sout.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uline.pdfbin82291 -> 82291 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uuline.pdfbin88402 -> 88402 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uwave.pdfbin83877 -> 83877 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.wrong.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.deletedmarkup.xout.pdfbin81521 -> 81521 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.draft.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.final.pdfbin68141 -> 68141 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.highlightmarkup.background.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uuline.pdfbin82970 -> 82970 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uwave.pdfbin84357 -> 84357 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.listofchanges.all.pdfbin88820 -> 88820 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.listofchanges.compactsummary.pdfbin86749 -> 86749 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.listofchanges.list.pdfbin84993 -> 84993 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.listofchanges.show.pdfbin89121 -> 89121 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.listofchanges.summary.pdfbin97975 -> 97975 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.listofchanges.title.pdfbin88388 -> 88388 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.listofchanges.wrong.pdfbin84993 -> 84993 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.markup.bfit.pdfbin86058 -> 86058 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.markup.default.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.markup.nocolor.pdfbin84681 -> 84681 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.markup.underlined.pdfbin84812 -> 84812 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.markup.wrong.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.packageoptions.todonotes.pdfbin104166 -> 104166 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.packageoptions.truncate.pdfbin83517 -> 83517 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.packageoptions.ulem.pdfbin75270 -> 75270 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.packageoptions.xcolor.pdfbin84182 -> 84182 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.screenshot.pdfbin143191 -> 143191 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setaddedmarkup.pdfbin94860 -> 94860 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setauthormarkup.pdfbin85414 -> 85414 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setauthormarkupposition.pdfbin93585 -> 93585 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setauthormarkuptext.pdfbin94839 -> 94839 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setcommentmarkup.pdfbin94058 -> 94058 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setdeletedmarkup.pdfbin94091 -> 94091 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.sethighlightmarkup.pdfbin93929 -> 93929 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setsocextension.pdfbin82295 -> 82295 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setsummarytowidth.pdfbin98926 -> 98926 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.setsummarywidth.pdfbin97786 -> 97786 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.settruncatewidth.pdfbin96371 -> 96371 bytes
-rw-r--r--macros/latex/contrib/changes/examples/changes.example.simple.pdfbin92919 -> 92919 bytes
-rw-r--r--macros/latex/contrib/changes/regression.dtx187
-rw-r--r--macros/latex/contrib/huawei/README.md10
-rw-r--r--macros/latex/contrib/huawei/huawei.cls250
-rw-r--r--macros/latex/contrib/huawei/huawei.pdfbin362777 -> 362961 bytes
-rw-r--r--macros/latex/contrib/huawei/huawei.tex4
-rw-r--r--macros/latex/contrib/tabularray/README4
-rw-r--r--macros/latex/contrib/tabularray/tabularray.pdfbin0 -> 379316 bytes
-rw-r--r--macros/latex/contrib/tabularray/tabularray.sty3897
-rw-r--r--macros/latex/contrib/tabularray/tabularray.tex751
97 files changed, 5164 insertions, 236 deletions
diff --git a/macros/latex/contrib/bnumexpr/README.md b/macros/latex/contrib/bnumexpr/README.md
index bda6edef58..a7db8bf12c 100644
--- a/macros/latex/contrib/bnumexpr/README.md
+++ b/macros/latex/contrib/bnumexpr/README.md
@@ -1,5 +1,5 @@
| Source: bnumexpr.dtx
-| Version: v1.4, 2021/05/12 (doc: 2021/05/12)
+| Version: v1.4a, 2021/05/13 (doc: 2021/05/13)
| Author: Jean-Francois Burnol
| Info: Expressions with big integers
| License: LPPL 1.3c
@@ -35,13 +35,6 @@ the syntax elements to macros from an alternative big integer
expandable engine of the user own choosing,
and then [xintcore](http://ctan.org/pkg/xint) is not loaded.
-Note; the possibility not to use the xintcore macros might be
-removed in the future: perhaps a future release will maintain during
-computations a private internal representation (especially tailored
-either for the xintcore macros or new ones which would be included
-within `bnumexpr.sty` itself) and the constraints this implies may
-render optional use of other macros impossible.
-
Installation
============
diff --git a/macros/latex/contrib/bnumexpr/bnumexpr.dtx b/macros/latex/contrib/bnumexpr/bnumexpr.dtx
index 83e0ab6c38..23ead1e2e1 100644
--- a/macros/latex/contrib/bnumexpr/bnumexpr.dtx
+++ b/macros/latex/contrib/bnumexpr/bnumexpr.dtx
@@ -1,17 +1,17 @@
% -*- coding: utf-8-unix; time-stamp-format: "%02d-%02m-%:y %02H:%02M:%02S %Z"; sentence-end-double-space: t; -*-
%<*dtx>
-\def\bnedtxtimestamp {Time-stamp: <12-05-2021 22:05:26 CEST>}
+\def\bnedtxtimestamp {Time-stamp: <13-05-2021 12:37:08 CEST>}
\iffalse
%</dtx>
%<*drv>
%% ---------------------------------------------------------------
-\def\bnedocdate {2021/05/12}% package bnumexpr documentation date
-\def\bnepackdate{2021/05/12}% package bnumexpr date
-\def\bneversion {1.4} % package bnumexpr version
+\def\bnedocdate {2021/05/13}% package bnumexpr documentation date
+\def\bnepackdate{2021/05/13}% package bnumexpr date
+\def\bneversion {1.4a} % package bnumexpr version
%</drv>
%<*readme>--------------------------------------------------------
| Source: bnumexpr.dtx
-| Version: v1.4, 2021/05/12 (doc: 2021/05/12)
+| Version: v1.4a, 2021/05/13 (doc: 2021/05/13)
| Author: Jean-Francois Burnol
| Info: Expressions with big integers
| License: LPPL 1.3c
@@ -47,13 +47,6 @@ the syntax elements to macros from an alternative big integer
expandable engine of the user own choosing,
and then [xintcore](http://ctan.org/pkg/xint) is not loaded.
-Note; the possibility not to use the xintcore macros might be
-removed in the future: perhaps a future release will maintain during
-computations a private internal representation (especially tailored
-either for the xintcore macros or new ones which would be included
-within `bnumexpr.sty` itself) and the constraints this implies may
-render optional use of other macros impossible.
-
Installation
============
@@ -129,6 +122,17 @@ and the derived files
%%
%</!readme>
%<*changes>-------------------------------------------------------
+\item[1.4a (2021/05/13)]
+ \begin{itemize}
+ \item fix undefined control sequences errors encountered by the parser in
+ case of either extra or missing closing parenthesis (due to a problem
+ in technology transfer at |1.4| from upstream \xintexprname).
+ \item fix |\BNE_Op_opp| must now be f-expandable (also caused as a
+ collateral to the technology transfer).
+ \item fix user documentation regarding the constraints applying to the user
+ replacement macros for the core algebra, as they have changed at |1.4|.
+ \end{itemize}
+
\item[1.4 (2021/05/12)]
\begin{itemize}
\item technology transfer from \xintexprname |1.4| of
@@ -300,7 +304,7 @@ and the derived files
\PassOptionsToPackage{dvipdfm}{geometry}
\PassOptionsToPackage{bookmarks=true}{hyperref}
\PassOptionsToPackage{dvipdfmx-outline-open}{hyperref}
- \PassOptionsToPackage{dvipdfmx-outline-open}{bookmark}
+ %\PassOptionsToPackage{dvipdfmx-outline-open}{bookmark}
%
\def\pgfsysdriver{pgfsys-dvipdfm.def}
\else
@@ -476,12 +480,14 @@ pdfpagemode=UseOutlines}
{bnumexpr}%
\xspace }%
+\def\xintkernelname
+ {\href{http://www.ctan.org/pkg/xint}{xintkernel}\xspace }%
\def\xintname
{\href{http://www.ctan.org/pkg/xint}{xint}\xspace }%
\def\xintcorename
{\href{http://www.ctan.org/pkg/xint}{xintcore}\xspace }%
\def\xintexprname
- {\href{http://www.ctan.org/pkg/xint}{xintexpr}\xspace }%
+ {\href{http://www.ctan.org/pkg/xintexpr}{xintexpr}\xspace }%
\def\xintbinhexname
{\href{http://www.ctan.org/pkg/xint}{xintbinhex}\xspace }%
@@ -546,15 +552,10 @@ pdfpagemode=UseOutlines}
\etocsetnexttocdepth{section}
\tableofcontents
-\section{\csh{thebnumexpr}, \csh{bnumeval}, \csh{evaltohex}}
+\section{\csh{bnumeval} (\csh{thebnumexpr}), \csh{evaltohex}}
\label{sec:bnumexpr}
-\LaTeX\ Package \bnumname provides |\thebnumexpr|\meta{expression}|\relax|:%
-%
-\footnote{Since |1.4|, one can use |\bnumexpr...\relax| directly in
- typesetting context, it is not mandatory to prefix it with |\bnethe| or to
- use |\thebnumexpr|.}
-%
+\LaTeX\ Package \bnumname provides |\thebnumexpr|\meta{expression}|\relax|:
it is analogous to
|\the\numexpr|\meta{expression}|\relax|, with these extensions:
\begin{itemize}
@@ -569,11 +570,20 @@ it is analogous to
separator,
\item comma separated expressions are allowed.
\end{itemize}
-There is also an alternative interface |\bnumeval|\marg{expression}, where the
-expression is fetched as braced argument. And there is
-|\evaltohex|\marg{expression} which does the same as
-|\bnumeval|\marg{expression} but with a conversion to hexadecimal notation of
-the (possibly comma separated) output. Hexadecimal input uses the |"| prefix.
+There is also a more core-level |\bnumexpr...\relax| construct%
+\footnote{Since |1.4|, one can use |\bnumexpr...\relax| directly in
+ typesetting context, it is not mandatory to prefix it with |\bnethe| or to
+ use |\thebnumexpr|.}%
+, which expands
+to a self-contained unit, rather than to explicit digit tokens (and commas).
+See \autoref{sec:differences} for some related information.
+
+There is also the alternative interface |\bnumeval|\marg{expression}, where the
+expression is fetched as braced argument.
+
+And there is |\evaltohex|\marg{expression} which does the same as |\bnumeval|
+but with a conversion to hexadecimal notation of the (possibly comma
+separated) output. Hexadecimal input uses the |"| prefix.
This package parser is a scaled-down variant of |\xintiiexpr| from package
\xintexprname, dropping support for nested structures, functions, variables,
@@ -594,32 +604,27 @@ possible to replace them by expandable macros of a custom origin.
\noindent\bneshow {---1 208 637 867 * (2 187 917 891 - 3 109 197 072)}%
\bneshoweval {(13_8089_1090-300_1890_2902)*(1083_1908_3901-109_8290_3890)}%
-\bneshow{(92_874_927_979**5-31_9792_7979**6)/30!}%
+\bneshoweval {(92_874_927_979**5-31_9792_7979**6)/30!}%
\bneshoweval {30!/20!/21/22/23/24/25/(26*27*28*29)}%
-\bneshow {13^50//12^50, 13^50/:12^50}%
+\bneshoweval {13^50//12^50, 13^50/:12^50}%
\bneshoweval {13^50/12^50, 12^50}%
-\bneshow {(1^10+2^10+3^10+4^10+5^10+6^10+7^10+8^10+9^10)^3}%
+\bneshoweval {(1^10+2^10+3^10+4^10+5^10+6^10+7^10+8^10+9^10)^3}%
\bneshoweval {100!/36^100}%
\bneshoweval {"10*"100*"1000*"A0000, 16^(1+2+3+4)*10}%
\bneshowevaltohex{"7FFFFFFF+1, "400^3, "ABCDEF*"FEDCBA}%
\section{Differences from \csh{numexpr}}
+\label{sec:differences}
Apart from the extension to big integers (i.e. exceeding the \TeX{} limit at
\number"7FFFFFFF), and the added operators, there are a number of important
differences between |\bnumexpr| and |\numexpr|:
\begin{enumerate}
-\item one may embed directly |\bnumexpr...\relax| in another one (or in
- a |\xintexpr...\relax|), but not in a |\numexpr...\relax|: it must
- then be using |\thebnumexpr...| or |\bnethe\bnumexpr...| syntax; on
- the other hand a |\numexpr...\relax| does not need to be prefixed by
- |\the| or |\number| inside |\bnumexpr...\relax|.
-
\item contrarily to |\numexpr|, the |\bnumexpr| parser stops only after having
- found (and swallowed) a mandatory ending |\relax| token,
+ found (and swallowed) a mandatory ending |\relax| token (it can arise from expansion),
-\item in particular spaces between digits do not stop |\bnumexpr|, in contrast
+\item in particular note that spaces between digits do not stop |\bnumexpr|, in contrast
with |\numexpr|:
|\the\numexpr 3 5+79\relax| expands (in one step) to \expandafter|\the\numexpr 3 5+79\relax|
@@ -627,15 +632,23 @@ differences between |\bnumexpr| and |\numexpr|:
|\thebnumexpr 3 5+79\relax| expands (in two steps) to
\expandafter\expandafter\expandafter|\thebnumexpr 3 5+79\relax|
-\item one may do |\edef\variable{\bnumexpr 1+2\relax}|, and then either use
- |\variable| in another |\bnumexpr...\relax|, or print it via
- |\bnethe\variable| (or directly since |1.4|). The computation is done at the time of the |\edef|
- (and two expansion steps suffice). This is again in contrast with
- |\numexpr...\relax| which, without |\the| (or |\number| or
- |\romannumeral|) as prefix would not expand inside an |\edef|,
+\item with |\edef\myVar{\thebnumexpr1+2\relax}|, the computation is of course
+ done at time of the |\edef|. But one is also allowed to do
+ |\edef\myVar{\bnumexpr1+2\relax}| which prepares |\myVar| as a macro which
+ can be inserted in other \bnumname expressions and behave there as a
+ self-contained pre-computed unit triggering tacit multiplication, or be
+ typeset directly if inserted in the typesetting stream.%
+%
+\footnote{Prior to |1.4|, one would have had to use |\bnethe\myVar| for
+ typesetting, or |\bnumeval{\myVar}|.}
+%
+ There is no analog with |\numexpr| as |\edef\myVar{\numexpr1+2\relax}| does
+ not pre-compute anything and furthermore |\the\numexpr2\myVar\relax| in
+ typesetting flow then triggers the |You can't use `\numexpr' in horizontal
+ mode| error.
\item expressions may be comma separated. On input, spaces are ignored,
- naturally, and on output the values are comma separated with a space after
+ and on output the values are comma separated with a space after
each comma,
\item |\bnumexpr -(1+1)\relax| is legal contrarily to |\numexpr -(1+1)\relax|
@@ -644,9 +657,6 @@ differences between |\bnumexpr| and |\numexpr|:
\item |\numexpr 2\cnta\relax| is illegal (with |\cnta| a |\count|-variable.)
But |\bnumexpr 2\cnta\relax| is perfectly legal and will do the tacit
multiplication,
-% \newcount\cnta
-% \cnta 1111
-% \thebnumexpr 2\cnta\relax
\item more generally, tacit multiplication applies in front of parenthesized
sub-expressions, or sub |\bnumexpr...\relax| (or |\numexpr...\relax|), or
@@ -657,13 +667,34 @@ differences between |\bnumexpr| and |\numexpr|:
\end{enumerate}
+As hinted above |\bnumexpr...\relax| differs from |\thebnumexpr...\relax| as
+the latter expands to explicit digit tokens, but the former expands to a
+private self-contained format which can serve as sub-unit in other
+expressions, or be used inside |\edef|. Since |1.4| the former idiom can also
+be inserted directly inside the typesetting stream, or be written out to an
+external file where it will expand to some control sequences, braces, and
+character tokens, all with their standard catcodes.
+
+One can use |\numexpr...\relax| as a sub-unit in |\bnumexpr...\relax| but the
+reverse does not apply: it would either cause an error or an
+anticipated end to the |\numexpr| which will think having hit a |\relax|.
+
An important thing to keep in mind is that if one has a calculation
whose result is a small integer, acceptable by \TeX{} in |\ifnum| or
count assignments, this integer produced by |\thebnumexpr| is not
self-delimiting, contrarily to a |\numexpr...\relax| construct: the
situation is exactly as with a |\the\numexpr...\relax|, thus one may
need to terminate the number to avoid premature expansion of following
-tokens; for example with the |\space| token.
+tokens; for example with the |\space| control sequence. When using |\bnumeval{...}|
+syntax as in
+\begin{verbatim}
+\ifnum\bnumeval{...}
+...
+\fi
+\end{verbatim}
+the end of line will insert a terminating space token. Again, here
+|\bnumeval{...}| must produce an integer acceptable to \TeX, i.e. at most
+{\number"7FFFFFFF} in absolute value.
\section{Printing big numbers}
@@ -737,7 +768,8 @@ the following way:
\usepackage{xintcore}
\bnumexprsetup{add=\xintiiAdd, sub=\xintiiSub, mul=\xintiiMul,
divround=\xintiiDivRound, div=\xintiiDivFloor,
- mod=\xintiiMod, pow=\xintiiPow, fac=\xintiiFac}
+ mod=\xintiiMod, pow=\xintiiPow, fac=\xintiiFac,
+ opp=\xintiiOpp}%
\end{verbatim}
If
@@ -748,27 +780,22 @@ multiplication will be changed.
Naturally it is up to the user to load the appropriate package for
the alternative macros.
-As per the macros which are the key values, they must have the
-following properties:
-\begin{enumerate}
-\item they must be completely expandable (in the sense of an |\edef|
- or a |\csname...\endcsname|.)
-\item they must fully expand their arguments first (in the sense of
- |\romannumeral-`0|.)
-\item they must output a number with no leading zeros, at most one
- minus sign and no plus sign.
-\end{enumerate}
-The first two items are truly mandatory, the last one may be not
-obeyed if the extra key |opp| is used with \csa{bnumexprsetup} to
-specify a suitable macro for the opposite of a number. This macro will
-be presented not with a braced argument but directly with a sequence
-of digits (either as gathered by the parser which skips leading
-zeros, or as produced by the other arithmetic macros and then there
-could be a minus, or even a plus if macros others than the ones from
-\xintcorename have been used).
-Thus, |opp| could identify a plus sign |+| upfront and then act
-adequately.\footnote{see \csa{BNE_Op_opp} in the code for the
- default.}
+The macros serving as custom user replacements must be \emph{f}-expandable.%
+%
+\footnote{Prior to |1.4|, only \emph{x}-expandability was required. The author
+ could relax again the constraint, if asked to do so. Or perhaps simply add
+ an option for it.}
+%
+(except for the computation of factorials, which only has to be
+\emph{x}-expandable).
+
+They will by default receive arguments composed of explicit digit tokens, with
+no leading zeros, with at most one leading minus sign and no plus sign.
+
+The format of these arguments may depend on what the |opp=\foo| replacement
+macro does. If the custom |\foo| inserts a |+| when taking the opposite of a
+negative number, then the custom macros for arithmetic (and the |\foo| macro
+itself) must be able to handle arguments starting optionally with such a |+|.
Macro |\bnumexprsetup| can be used multiple times in the same document, thus
allowing to switch math engines or to remap operators to some other arithmetic
@@ -792,6 +819,8 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
\noindent\kern\parindent\input README.md
\endgroup }\x
+%\clearpage
+
\section{Changes}
%\small
\begin{description}
@@ -816,29 +845,65 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
% \label{sec:bnumexprcode}
% \etocdefaultlines
% \localtableofcontents
+% \etocmarkbothnouc{Package \bnumnameimp implementation}
%
% Comments are sparse. Actually at |1.4|, there are simply no comments. I
% transferred from \xintexprname its |\expanded| based infra-structure from
-% its own |1.4| release of January 2020. It is a possibility that, even
-% though I did remove very large chunks of unneeded macros, in the end, some
-% more simplifications could have been considered here.
+% its own |1.4| release of January 2020.
%
% Error handling by the parser is kept to a minimum; if something goes wrong,
% the offensive token gets discarded, and it is not even always the case that
% some expandable error message is issued.
%
+% A few comments at |1.4a|:
+% \begin{itemize}
+% \item It looked a bit costly and probably would have been mostly useless to
+% end users to integrate in \bnumname support for nested structures via
+% square brackets [, ], which is in \xintexprname since its January 2020
+% |1.4| release. But some underlying related architecture remains here; we
+% could make some micro-gains probably but diverging from upstream code
+% would make maintenance a nightmare.
+% \item The |\bnumexpr\relax| syntax creating an empty ople is by itself now
+% legal, and can be injected (comma separated) in an expression, keeping it
+% invariant, however |\bnumeval{}| ends in a |File ended while scanning use
+% of \BNE_print_c| error because |\BNEprint| makes the tacit requirement
+% that the 1D ople to output has at least one item.
+% \item Formerly, the |\csname...\endcsname| encapsulation technique had the
+% after-effect to allow the macros supporting the infix operators to be only
+% x-expandable. At |1.4|, I could have still allowed only x-expandable
+% macros, but, keeping in sync with upstream, I have used only a
+% |\romannumeral| trigger and did not insert an |\expanded|, so now the
+% support macros must be f-expandable. The |1.4a| release fixes the related
+% user documentation of |\bnumexprsetup| which was not updated at |1.4|.
+% The support macro for the factorial however needs only be x-expandable.
+% \item Also, I simply do not understand why the legacy user documentation
+% said that the support macros were supposed to f-expand their arguments, as
+% they are used only with arguments being explicit digit tokens (and
+% optional minus sign).
+% \item I hesitated a bit about making the decimal to hexadecimal and
+% hexadecimal to decimal support macros customizable, but dropped the
+% idea. Loading \xintbinhexname unconditionally has also the advantage to
+% not have to define some \xintkernelname provided helper macros; and it
+% still does not load \xintcorename, so is keeping dependencies somewhat low
+% and the |custom| option significant.
+% \item I had fleetingly consider a parser |\hexexpr| where input is
+% hexadecimal with no |"| prefix, but implementing this basically means
+% duplicating with new names a large chunk of the parser code to have parser
+% specific |"getnext"| macros for example. Not worth it.
+% \end{itemize}
+%
% \subsection{Package identification and catcode setup}
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}%
-\ProvidesPackage{bnumexpr}[2021/05/12 v1.4 Expressions with big integers (JFB)]%
+\ProvidesPackage{bnumexpr}[2021/05/13 v1.4a Expressions with big integers (JFB)]%
% \end{macrocode}
% \subsection{Load unconditionally xintbinhex}
% Newly done at |1.4|. Formerly, \bnumname had no dependency if loaded
% with option |custom|. But for |1.4| release I have decided to add
% unconditional support for hexadecimal notation.
%
-% Let's require the most recent xint date at time of
-% writing. We should check for availability of \string\expanded\space but well.
+% Let's require the most recent \xintname date at time of
+% writing. We should check for availability of |\expanded| but well.
%
% \begin{macrocode}
\RequirePackage{xintbinhex}[2021/05/10]%
@@ -858,6 +923,9 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
}%
% \end{macrocode}
% \subsection{Package options}
+% The keys should have been |Add|, |Sub|, \dots, not |add|, |sub|, \dots, so
+% internally macros |\BNE_Op_Add| etc\dots\ macro names would be used, but well,
+% let's simply leave with this.
% \begin{macrocode}
\def\BNEtmpa {0}%
\DeclareOption {custom}{\def\BNEtmpa {1}}%
@@ -869,7 +937,8 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
\RequirePackage{xintcore}[2021/05/10]%
\bnumexprsetup{add=\xintiiAdd, sub=\xintiiSub, mul=\xintiiMul,
divround=\xintiiDivRound, div=\xintiiDivFloor,
- mod=\xintiiMod, pow=\xintiiPow, fac=\xintiiFac}%
+ mod=\xintiiMod, pow=\xintiiPow, fac=\xintiiFac,
+ opp=\xintiiOpp}%
}%
% \end{macrocode}
% Strangely those three are not defined in xintkernel.sty, but only in xint.sty
@@ -1148,12 +1217,17 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
}%
}%
\let\BNE_done\space
+\def\BNE_getop_legacy #1%
+{%
+ \expanded{\unexpanded{{#1}}\expandafter}\romannumeral`&&@\BNE_getop
+}%
\expandafter\BNE_tmpa
\csname BNE_start\expandafter\endcsname
\csname BNE_check\expandafter\endcsname
\csname BNE_checkp\expandafter\endcsname
\csname BNE_op_-xii\expandafter\endcsname
\csname BNE_extra_)\endcsname
+\catcode`) 11
\def\BNE_tmpa #1#2#3#4#5#6%
{%
\def #1##1% op_(
@@ -1191,7 +1265,6 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
\csname BNE_check-_)\expandafter\endcsname
\csname BNE_checkp_)\expandafter\endcsname
\csname BNE_op_-xii\endcsname
-\catcode`) 11
\let\BNE_precedence_)\xint_c_i
\def\BNE_missing_)
{\XINT_expandableerror{Sorry to report a missing ) at the end of this journey.}%
@@ -1199,6 +1272,11 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
\catcode`) 12
% \end{macrocode}
% \subsection{The comma as binary operator}
+% At |1.4|, it is simply a union operator for 1D oples. Inserting directly
+% here a |<space><comma>| separator (as in earlier releases) in accumulated
+% result would avoid having to do it on output but to the cost of diverging
+% from \xintexprname upstream code, and to have to let the |\evaltohex| output
+% routine handle comma separated values rather than braced values.
% \begin{macrocode}
\def\BNE_tmpa #1#2#3#4#5%
{%
@@ -1234,6 +1312,15 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
\expandafter\let\csname BNE_precedence_,\endcsname\xint_c_iii
% \end{macrocode}
% \subsection{The minus as prefix operator of variable precedence level}
+% This |\BNE_Op_opp| causes trouble as at |1.4| it must be f-expandable,
+% whereas earlier it expanded inside |\csname...\endcsname| context, so I
+% could define it as {\catcode`\#12 |\if-#1\else\if0#10\else-#1\fi\fi|} where
+% {\catcode`\#12 |#1|} was the
+% first token of unbraced argument but this meant at |1.4| an added
+% |\xint_firstofone| here. Well let's return to sanity at |1.4a| and not add
+% the |\xint_firstofone| and simply default |\BNE_Op_opp| to |\xintiiOpp|,
+% which it should have been all along! And on this occasion let's trim user
+% documentation of irrelevant complications.
% \begin{macrocode}
\def\BNE_tmpb #1#2#3#4#5%
{%
@@ -1245,7 +1332,7 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
\def #2##1##2##3% \BNE_exec_-<level>
{%
\expandafter ##1\expandafter ##2\expandafter
- {\expandafter{\romannumeral`&&@\expandafter\BNE_Op_opp\xint_firstofone##3}}%
+ {\expandafter{\romannumeral`&&@\BNE_Op_opp##3}}%
}%
\def #3##1% \BNE_check-_-<level>
{%
@@ -1277,9 +1364,15 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
\BNE_tmpa {xiv}%
\BNE_tmpa {xvi}%
\BNE_tmpa {xviii}%
-\def\BNE_Op_opp #1{\if-#1\else\if0#10\else-#1\fi\fi }%
% \end{macrocode}
% \subsection{The infix operators.}
+% I could have at the |1.4| refactoring injected usage of |\expanded| here,
+% but kept in sync with upstream \xintexprname code.
+%
+% Macro names are somewhat bad and there is much risk of confusion in future
+% maintenance of |\BNE_Op_| prefix (used for |\BNE_Op_add| etc...; besides
+% this should have been |\BNE_Op_Add|) and |\BNE_op_| prefix (used for
+% {\catcode`+ 11 |\BNE_op_+|} etc...).
% \begin{macrocode}
\def\BNE_defbin_c #1#2#3#4#5#6#7%
{%
@@ -1337,6 +1430,7 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
\expandafter\let\csname BNE_precedence_***\endcsname \xint_c_xvi
% \end{macrocode}
% \subsection{! as postfix factorial operator}
+% This one uses |\expanded|.
% \begin{macrocode}
\catcode`! 11
\let\BNE_precedence_! \xint_c_xx
@@ -1354,23 +1448,8 @@ output is handled, it goes necessarily via the \xintbinhexname macros.
% \MakePercentComment
%</package>
%<*dtx>
-\DeleteShortVerb{\|}
-\CharacterTable
- {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
- Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
- Digits \0\1\2\3\4\5\6\7\8\9
- Exclamation \! Double quote \" Hash (number) \#
- Dollar \$ Percent \% Ampersand \&
- Acute accent \' Left paren \( Right paren \)
- Asterisk \* Plus \+ Comma \,
- Minus \- Point \. Solidus \/
- Colon \: Semicolon \; Less than \<
- Equals \= Greater than \> Question mark \?
- Commercial at \@ Left bracket \[ Backslash \\
- Right bracket \] Circumflex \^ Underscore \_
- Grave accent \` Left brace \{ Vertical bar \|
- Right brace \} Tilde \~}
-\CheckSum {949}
-\makeatletter\check@checksum\makeatother
-\Finale
+\DeleteShortVerb{\|}%
+\CheckSum {947}%
+\makeatletter\check@checksum\makeatother%
+\Finale%
%% End of file xint.dtx
diff --git a/macros/latex/contrib/bnumexpr/bnumexpr.pdf b/macros/latex/contrib/bnumexpr/bnumexpr.pdf
index d6fce09181..79f259f3f2 100644
--- a/macros/latex/contrib/bnumexpr/bnumexpr.pdf
+++ b/macros/latex/contrib/bnumexpr/bnumexpr.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/changes.drv b/macros/latex/contrib/changes/changes.drv
index cfb813e288..e8e7868fb1 100644
--- a/macros/latex/contrib/changes/changes.drv
+++ b/macros/latex/contrib/changes/changes.drv
@@ -1,6 +1,6 @@
%%%
% driver file of changes package
-\newcommand{\docversion}{4.0.3}
+\newcommand{\docversion}{4.0.4}
\documentclass[titlepage, parskip=half, toc=flat, cleardoublepage=empty, captions=nooneline, origlongtable, english]{scrartcl}
diff --git a/macros/latex/contrib/changes/changes.dtx b/macros/latex/contrib/changes/changes.dtx
index cf459852f9..cdb43d7d46 100644
--- a/macros/latex/contrib/changes/changes.dtx
+++ b/macros/latex/contrib/changes/changes.dtx
@@ -66,6 +66,7 @@
% \changes{v4.0.1}{2021/02/14}{bugfix: Command do undefined}
% \changes{v4.0.2}{2021/04/05}{bugfix: documentation with ifthenelse references}
% \changes{v4.0.3}{2021/05/09}{bugfix: compile error with cite command in change markup with final option}
+% \changes{v4.0.4}{2021/05/13}{bugfix: added missing regression.dtx to ctan archive; no code change}
% \GetFileInfo{changes.dtx}
% \RecordChanges
%
@@ -105,8 +106,8 @@
% Type some information to the console.
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{changes}[2021/05/09 v4.0.3 changes package]
-\typeout{*** changes package 2021/05/09 v4.0.3 ***}
+\ProvidesPackage{changes}[2021/05/13 v4.0.4 changes package]
+\typeout{*** changes package 2021/05/13 v4.0.4 ***}
% \end{macrocode}
%
% Package \docpackage{xkeyval} provides options with key-value-pairs.
diff --git a/macros/latex/contrib/changes/changes.english.pdf b/macros/latex/contrib/changes/changes.english.pdf
index 4b4e0b695b..3966c3b985 100644
--- a/macros/latex/contrib/changes/changes.english.pdf
+++ b/macros/latex/contrib/changes/changes.english.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/changes.english.withcode.pdf b/macros/latex/contrib/changes/changes.english.withcode.pdf
index b5f0ef869a..fb527586e1 100644
--- a/macros/latex/contrib/changes/changes.english.withcode.pdf
+++ b/macros/latex/contrib/changes/changes.english.withcode.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/changes.ins b/macros/latex/contrib/changes/changes.ins
index 33ca5ae772..537ecf5d1e 100644
--- a/macros/latex/contrib/changes/changes.ins
+++ b/macros/latex/contrib/changes/changes.ins
@@ -1,6 +1,6 @@
%% This file creates the needed files from changes.dtx
%%
-\def\filedate{2021/02/14}
+\def\filedate{2021/05/13}
\def\batchfile{changes.ins}
\input docstrip
@@ -153,7 +153,7 @@ Copyright 2007-2021 Ekkart Kleinod
%
\file{examples/changes.example.screenshot.tex}{\from{example-screenshot.dtx}{example:screenshot}}
%
- \file{regression/changes.regression.draft.tex}{\from{regression.dtx}{regression:draft}}
+ \file{regression/changes.regression.draft.tex}{\from{regression.dtx}{regression:draft}}
\file{regression/changes.regression.final.tex}{\from{regression.dtx}{regression:final}}
}
diff --git a/macros/latex/contrib/changes/changes.ngerman.pdf b/macros/latex/contrib/changes/changes.ngerman.pdf
index db7e686fad..d96ed9c052 100644
--- a/macros/latex/contrib/changes/changes.ngerman.pdf
+++ b/macros/latex/contrib/changes/changes.ngerman.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.bf.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.bf.pdf
index 55ca5987a4..dc0c3dd07a 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.bf.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.bf.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.colored.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.colored.pdf
index ec67a5c59b..9b20a91f4b 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.colored.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.colored.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.dashuline.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.dashuline.pdf
index 42755a29d0..997338b6fa 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.dashuline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.dashuline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.dotuline.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.dotuline.pdf
index 3d82022ab6..d22a436c8b 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.dotuline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.dotuline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.em.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.em.pdf
index 55c5d2326c..05fda41a2c 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.em.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.em.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.it.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.it.pdf
index 95eaa4da82..82efbcff69 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.it.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.it.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.sl.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.sl.pdf
index 60a30bdf1f..2d8e55c72e 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.sl.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.sl.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uline.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uline.pdf
index c5bd26700c..e42b78e69f 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uuline.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uuline.pdf
index 2778aa204e..cf0f7977ca 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uuline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uuline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uwave.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uwave.pdf
index 98ed53ebba..174d468e10 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uwave.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.uwave.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.wrong.pdf b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.wrong.pdf
index 7f5dea591a..b6afc108f3 100644
--- a/macros/latex/contrib/changes/examples/changes.example.addedmarkup.wrong.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.addedmarkup.wrong.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkup.brackets.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkup.brackets.pdf
index 471640cda0..04849c936c 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkup.brackets.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkup.brackets.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkup.footnote.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkup.footnote.pdf
index f850b6d45c..8307c1eb34 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkup.footnote.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkup.footnote.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkup.none.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkup.none.pdf
index f530551bb3..8526a878c9 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkup.none.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkup.none.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkup.subscript.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkup.subscript.pdf
index 87fca6e7b5..5722d29e3c 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkup.subscript.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkup.subscript.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkup.superscript.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkup.superscript.pdf
index cdaf9ae0f1..614753eae4 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkup.superscript.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkup.superscript.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkup.wrong.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkup.wrong.pdf
index 813ae0f2ed..f92a3815a6 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkup.wrong.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkup.wrong.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.left.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.left.pdf
index 41cc948b14..4baa2793e8 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.left.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.left.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.right.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.right.pdf
index 053b1a7108..bea03c7f39 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.right.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.right.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.wrong.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.wrong.pdf
index 637ab58f9c..5cc15530ea 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.wrong.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkupposition.wrong.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.id.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.id.pdf
index 54b6055a3a..e13fbc099e 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.id.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.id.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.name.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.name.pdf
index 73e03a81ab..09d2d962ba 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.name.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.name.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.wrong.pdf b/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.wrong.pdf
index c32978d197..8f9b11217c 100644
--- a/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.wrong.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.authormarkuptext.wrong.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.always.pdf b/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.always.pdf
index 56836d4869..34e44f4122 100644
--- a/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.always.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.always.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.ifneeded.pdf b/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.ifneeded.pdf
index 116bb6814e..755b71e7b6 100644
--- a/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.ifneeded.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.ifneeded.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.none.pdf b/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.none.pdf
index eadce526ac..61d3656b21 100644
--- a/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.none.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.none.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.wrong.pdf b/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.wrong.pdf
index 39e0441dd1..4ae72adfb5 100644
--- a/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.wrong.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.commandnameprefix.wrong.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.commentmarkup.footnote.pdf b/macros/latex/contrib/changes/examples/changes.example.commentmarkup.footnote.pdf
index b64d016ffe..a0c6078b41 100644
--- a/macros/latex/contrib/changes/examples/changes.example.commentmarkup.footnote.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.commentmarkup.footnote.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.commentmarkup.margin.pdf b/macros/latex/contrib/changes/examples/changes.example.commentmarkup.margin.pdf
index d0899372f6..da26c081e4 100644
--- a/macros/latex/contrib/changes/examples/changes.example.commentmarkup.margin.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.commentmarkup.margin.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.commentmarkup.todo.pdf b/macros/latex/contrib/changes/examples/changes.example.commentmarkup.todo.pdf
index 553d11bc50..c7df7d621f 100644
--- a/macros/latex/contrib/changes/examples/changes.example.commentmarkup.todo.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.commentmarkup.todo.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.commentmarkup.uwave.pdf b/macros/latex/contrib/changes/examples/changes.example.commentmarkup.uwave.pdf
index 72f1b090d8..9dcab9f153 100644
--- a/macros/latex/contrib/changes/examples/changes.example.commentmarkup.uwave.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.commentmarkup.uwave.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.defaultcolor.pdf b/macros/latex/contrib/changes/examples/changes.example.defaultcolor.pdf
index 3bcbbbd277..0927c66a56 100644
--- a/macros/latex/contrib/changes/examples/changes.example.defaultcolor.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.defaultcolor.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.bf.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.bf.pdf
index 5165d0142d..f7bc342800 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.bf.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.bf.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.colored.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.colored.pdf
index ab50ae7042..7bd79fce36 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.colored.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.colored.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dashuline.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dashuline.pdf
index cd3db0cff5..e41a79f0e1 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dashuline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dashuline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dotuline.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dotuline.pdf
index 8dbe2decd7..5996794da5 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dotuline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.dotuline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.em.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.em.pdf
index a1339f3f13..71d6ae63da 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.em.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.em.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.it.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.it.pdf
index 293abd5051..a7360c45e1 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.it.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.it.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sl.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sl.pdf
index 7ec00ac4be..52c8856fe5 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sl.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sl.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sout.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sout.pdf
index b14b88a92e..25da40e2a4 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sout.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.sout.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uline.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uline.pdf
index 9114b60379..0bc0bb96db 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uuline.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uuline.pdf
index de00241473..3b29e78138 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uuline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uuline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uwave.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uwave.pdf
index 36d0f9277c..a0b414f540 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uwave.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.uwave.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.wrong.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.wrong.pdf
index 17f59b5f0f..d5e92334b6 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.wrong.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.wrong.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.xout.pdf b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.xout.pdf
index df2ca6a4e8..7c88d36d25 100644
--- a/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.xout.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.deletedmarkup.xout.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.draft.pdf b/macros/latex/contrib/changes/examples/changes.example.draft.pdf
index 19604e3dc1..7487224028 100644
--- a/macros/latex/contrib/changes/examples/changes.example.draft.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.draft.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.final.pdf b/macros/latex/contrib/changes/examples/changes.example.final.pdf
index 8b220865d3..ba26534645 100644
--- a/macros/latex/contrib/changes/examples/changes.example.final.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.final.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.background.pdf b/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.background.pdf
index c15f9259b8..5454e5cb9e 100644
--- a/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.background.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.background.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uuline.pdf b/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uuline.pdf
index 5980796240..44660333cc 100644
--- a/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uuline.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uuline.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uwave.pdf b/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uwave.pdf
index 5c9b001fbd..b0dde8c21e 100644
--- a/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uwave.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.highlightmarkup.uwave.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.listofchanges.all.pdf b/macros/latex/contrib/changes/examples/changes.example.listofchanges.all.pdf
index 8c0cc20248..1d91a78803 100644
--- a/macros/latex/contrib/changes/examples/changes.example.listofchanges.all.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.listofchanges.all.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.listofchanges.compactsummary.pdf b/macros/latex/contrib/changes/examples/changes.example.listofchanges.compactsummary.pdf
index 26a11f1814..d4e2dc9286 100644
--- a/macros/latex/contrib/changes/examples/changes.example.listofchanges.compactsummary.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.listofchanges.compactsummary.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.listofchanges.list.pdf b/macros/latex/contrib/changes/examples/changes.example.listofchanges.list.pdf
index 02ba064853..bf123cce50 100644
--- a/macros/latex/contrib/changes/examples/changes.example.listofchanges.list.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.listofchanges.list.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.listofchanges.show.pdf b/macros/latex/contrib/changes/examples/changes.example.listofchanges.show.pdf
index 5d8bd6bf4c..65c702e413 100644
--- a/macros/latex/contrib/changes/examples/changes.example.listofchanges.show.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.listofchanges.show.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.listofchanges.summary.pdf b/macros/latex/contrib/changes/examples/changes.example.listofchanges.summary.pdf
index 59a489ead4..565a258ad9 100644
--- a/macros/latex/contrib/changes/examples/changes.example.listofchanges.summary.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.listofchanges.summary.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.listofchanges.title.pdf b/macros/latex/contrib/changes/examples/changes.example.listofchanges.title.pdf
index 378bc395c2..64ca9aa1af 100644
--- a/macros/latex/contrib/changes/examples/changes.example.listofchanges.title.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.listofchanges.title.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.listofchanges.wrong.pdf b/macros/latex/contrib/changes/examples/changes.example.listofchanges.wrong.pdf
index 2f0c65b9a9..302a98cfcd 100644
--- a/macros/latex/contrib/changes/examples/changes.example.listofchanges.wrong.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.listofchanges.wrong.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.markup.bfit.pdf b/macros/latex/contrib/changes/examples/changes.example.markup.bfit.pdf
index 335460ea5d..02216b7feb 100644
--- a/macros/latex/contrib/changes/examples/changes.example.markup.bfit.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.markup.bfit.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.markup.default.pdf b/macros/latex/contrib/changes/examples/changes.example.markup.default.pdf
index 5e19e72dad..e7808d8a3d 100644
--- a/macros/latex/contrib/changes/examples/changes.example.markup.default.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.markup.default.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.markup.nocolor.pdf b/macros/latex/contrib/changes/examples/changes.example.markup.nocolor.pdf
index f22f6b88bc..e9aa8961aa 100644
--- a/macros/latex/contrib/changes/examples/changes.example.markup.nocolor.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.markup.nocolor.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.markup.underlined.pdf b/macros/latex/contrib/changes/examples/changes.example.markup.underlined.pdf
index 69a6bafc59..4e857736ad 100644
--- a/macros/latex/contrib/changes/examples/changes.example.markup.underlined.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.markup.underlined.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.markup.wrong.pdf b/macros/latex/contrib/changes/examples/changes.example.markup.wrong.pdf
index ad081f72cb..92d173d497 100644
--- a/macros/latex/contrib/changes/examples/changes.example.markup.wrong.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.markup.wrong.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.packageoptions.todonotes.pdf b/macros/latex/contrib/changes/examples/changes.example.packageoptions.todonotes.pdf
index 0e00c4420f..e4b03e2b5d 100644
--- a/macros/latex/contrib/changes/examples/changes.example.packageoptions.todonotes.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.packageoptions.todonotes.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.packageoptions.truncate.pdf b/macros/latex/contrib/changes/examples/changes.example.packageoptions.truncate.pdf
index c98fb27a2e..dcc53cb087 100644
--- a/macros/latex/contrib/changes/examples/changes.example.packageoptions.truncate.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.packageoptions.truncate.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.packageoptions.ulem.pdf b/macros/latex/contrib/changes/examples/changes.example.packageoptions.ulem.pdf
index 880cadda7d..8505cb8df9 100644
--- a/macros/latex/contrib/changes/examples/changes.example.packageoptions.ulem.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.packageoptions.ulem.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.packageoptions.xcolor.pdf b/macros/latex/contrib/changes/examples/changes.example.packageoptions.xcolor.pdf
index 3089085f93..c14ec5b69d 100644
--- a/macros/latex/contrib/changes/examples/changes.example.packageoptions.xcolor.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.packageoptions.xcolor.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.screenshot.pdf b/macros/latex/contrib/changes/examples/changes.example.screenshot.pdf
index 2eb639c281..f160be560a 100644
--- a/macros/latex/contrib/changes/examples/changes.example.screenshot.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.screenshot.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setaddedmarkup.pdf b/macros/latex/contrib/changes/examples/changes.example.setaddedmarkup.pdf
index a83f2f1064..3bd6988e6f 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setaddedmarkup.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setaddedmarkup.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setauthormarkup.pdf b/macros/latex/contrib/changes/examples/changes.example.setauthormarkup.pdf
index c6d7119322..7daf91ae92 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setauthormarkup.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setauthormarkup.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setauthormarkupposition.pdf b/macros/latex/contrib/changes/examples/changes.example.setauthormarkupposition.pdf
index fa609d6a4d..a1d970adaf 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setauthormarkupposition.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setauthormarkupposition.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setauthormarkuptext.pdf b/macros/latex/contrib/changes/examples/changes.example.setauthormarkuptext.pdf
index 1780b0bb63..6d5b376fda 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setauthormarkuptext.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setauthormarkuptext.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setcommentmarkup.pdf b/macros/latex/contrib/changes/examples/changes.example.setcommentmarkup.pdf
index a0d62a22b6..95bb7d328e 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setcommentmarkup.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setcommentmarkup.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setdeletedmarkup.pdf b/macros/latex/contrib/changes/examples/changes.example.setdeletedmarkup.pdf
index 75d1f0b381..b41d6fad38 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setdeletedmarkup.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setdeletedmarkup.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.sethighlightmarkup.pdf b/macros/latex/contrib/changes/examples/changes.example.sethighlightmarkup.pdf
index 904094ba18..bad03fbfd1 100644
--- a/macros/latex/contrib/changes/examples/changes.example.sethighlightmarkup.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.sethighlightmarkup.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setsocextension.pdf b/macros/latex/contrib/changes/examples/changes.example.setsocextension.pdf
index c76adf1d00..985d432902 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setsocextension.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setsocextension.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setsummarytowidth.pdf b/macros/latex/contrib/changes/examples/changes.example.setsummarytowidth.pdf
index 1dd53cc870..35306c3ce1 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setsummarytowidth.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setsummarytowidth.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.setsummarywidth.pdf b/macros/latex/contrib/changes/examples/changes.example.setsummarywidth.pdf
index 3b4a6ae2a0..bb075da847 100644
--- a/macros/latex/contrib/changes/examples/changes.example.setsummarywidth.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.setsummarywidth.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.settruncatewidth.pdf b/macros/latex/contrib/changes/examples/changes.example.settruncatewidth.pdf
index e816f0dde8..62b2878df3 100644
--- a/macros/latex/contrib/changes/examples/changes.example.settruncatewidth.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.settruncatewidth.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/examples/changes.example.simple.pdf b/macros/latex/contrib/changes/examples/changes.example.simple.pdf
index 1a803ad07f..0c7385b600 100644
--- a/macros/latex/contrib/changes/examples/changes.example.simple.pdf
+++ b/macros/latex/contrib/changes/examples/changes.example.simple.pdf
Binary files differ
diff --git a/macros/latex/contrib/changes/regression.dtx b/macros/latex/contrib/changes/regression.dtx
new file mode 100644
index 0000000000..a3fe6c903a
--- /dev/null
+++ b/macros/latex/contrib/changes/regression.dtx
@@ -0,0 +1,187 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2007-2021
+% Ekkart Kleinod (ekleinod@edgesoft.de)
+% --------------------------------------------------------------------------
+%
+% This work may be distributed and/or modified under the
+% conditions of the \LaTeX\ Project Public License, either version~1.3
+% of this license or any later version.
+% The latest version of this license is in\\
+% \url{http://www.latex-project.org/lppl.txt}\\
+% and version~1.3 or later is part of all distributions of \LaTeX\
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status "maintained".
+% The current maintainer of this work is Ekkart Kleinod.
+% \fi
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+% \GetFileInfo{regression.dtx}
+%
+%^^A --------------------------------------------------------------------------
+%
+% Start the \LaTeX document the standard way.
+%
+% \begin{macrocode}
+\documentclass[11pt, a4paper, notitlepage, english]{article}
+\usepackage{babel}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*regression:draft>
+\usepackage[authormarkuptext=name]{changes}
+%</regression:draft>
+%<*regression:final>
+\usepackage[final]{changes}
+%</regression:final>
+%
+% Define some authors.
+%
+% \begin{macrocode}
+\definechangesauthor[color=green]{Green}
+\definechangesauthor[name={Mister Orange}, color=orange]{OA}
+\definechangesauthor{nochanges}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\begin{document}
+
+%<*regression:draft>
+ \section{Test empty string}
+
+ Anonymous author should have no space before the \added[comment=no space]{number} in the comment.
+
+ Author name should \added[id=OA]{appear here} but \added[id=Green]{id here}.
+
+ \listofchanges[title={List of changes should not contain empty author brackets}]
+
+ \listofchanges[style=compactsummary, title={Summary should not contain empty author brackets either}]
+%</regression:draft>
+
+%<*regression:final>
+ \section{Compile errors to avoid}
+
+ no compile error here (just a missing citation): --- \added{a cite inside added \cite{bibid}} ---
+
+ \section{Errors with empty replacement}
+
+ All corresponding lines should have the same width.
+
+ Text before deletion.
+ \deleted{Deleted text.}
+ Text after deletion.
+
+ Text before deletion. \deleted{Deleted text.} Text after deletion.
+
+ Text before deletion.
+ Text after deletion.
+
+
+ Text before replacement.
+ \replaced{}{Replaced text.}
+ Text after replacement.
+
+ Text before replacement. \replaced{}{Replaced text.} Text after replacement.
+
+ Text before replacement.
+ Text after replacement.
+
+
+ Text before replacement.
+ \replaced{}{}
+ Text after replacement.
+
+ Text before replacement. \replaced{}{} Text after replacement.
+
+ Text before replacement.
+ Text after replacement.
+
+
+ Text before addition.
+ \added{}
+ Text after addition.
+
+ Text before addition. \added{} Text after addition.
+
+ Text before addition.
+ Text after addition.
+
+ Text before comment.
+ \comment{Comment.}
+ Text after comment.
+
+ Text before comment. \comment{Comment.} Text after comment.
+
+ Text before comment.
+ Text after comment.
+
+ Text before empty comment.
+ \comment{}
+ Text after empty comment.
+
+ Text before empty comment. \comment{} Text after empty comment.
+
+ Text before empty comment.
+ Text after empty comment.
+
+ Text before highlight.
+ \highlight[comment={Highlight comment}]{Highlighted text.}
+ Text after highlight.
+
+ Text before highlight. \highlight[comment={Highlight comment}]{Highlighted text.} Text after highlight.
+
+ Text before highlight.
+ Highlighted text.
+ Text after highlight.
+
+ Text before empty highlight text.
+ \highlight[comment={Highlight comment}]{}
+ Text after empty highlight text.
+
+ Text before empty highlight text. \highlight[comment={Highlight comment}]{} Text after empty highlight text.
+
+ Text before empty highlight text.
+ Text after empty highlight text.
+
+ Text before empty highlight comment.
+ \highlight[comment={}]{Highlighted text.}
+ Text after empty highlight comment.
+
+ Text before empty highlight comment. \highlight[comment={}]{Highlighted text.} Text after empty highlight comment.
+
+ Text before empty highlight comment.
+ Highlighted text.
+ Text after empty highlight comment.
+
+ Text before empty highlight.
+ \highlight[comment={}]{}
+ Text after empty highlight.
+
+ Text before empty highlight. \highlight[comment={}]{} Text after empty highlight.
+
+ Text before empty highlight.
+ Text after empty highlight.
+
+%</regression:final>
+
+\end{document}
+% \end{macrocode}
+%
+%\Finale
+\endinput
diff --git a/macros/latex/contrib/huawei/README.md b/macros/latex/contrib/huawei/README.md
index ddb9d7db34..a6ae6ec72c 100644
--- a/macros/latex/contrib/huawei/README.md
+++ b/macros/latex/contrib/huawei/README.md
@@ -1,14 +1,16 @@
+[![make](https://github.com/yegor256/huawei.cls/actions/workflows/make.yml/badge.svg)](https://github.com/yegor256/huawei.cls/actions/workflows/make.yml)
+
Disclaimer: This is **NOT** a product of Huawei Technologies Co., Ltd.
This package is created in order to help some people working
with Huawei or inside Huawei to render some documents in LaTeX format.
You are welcome to use it at your own risk.
-You can use this [`huawei.cls`](huawei.cls) LaTeX style just by copying it to some local
-directory and then mentioning it in the preamble of all your documents
-(on my laptop it's called `/code/huawei.cls`):
+First, [install it](https://en.wikibooks.org/wiki/LaTeX/Installing_Extra_Packages)
+from [CTAN](https://ctan.org/pkg/huawei)
+and then use in the preamble:
```tex
-\documentclass[landscape]{/code/huawei}
+\documentclass[landscape]{huawei}
\author{Yegor Bugayenko}
\title{An Interesting Document About Something}
\begin{document}
diff --git a/macros/latex/contrib/huawei/huawei.cls b/macros/latex/contrib/huawei/huawei.cls
index 7ea0170c9c..1a8c9c2ef3 100644
--- a/macros/latex/contrib/huawei/huawei.cls
+++ b/macros/latex/contrib/huawei/huawei.cls
@@ -21,7 +21,7 @@
% SOFTWARE.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesClass{huawei}[17/4/2021 0.1.0 Template for Huawei documents]
+\ProvidesClass{huawei}[13/05/2021 0.2.0 Template for Huawei documents]
\newif\ifnosecurity
\DeclareOption{nosecurity}{\nosecuritytrue}
\newif\ifnobrand
@@ -75,15 +75,13 @@
\noexpand\setstretch{\fpeval{(#1)*(\baselinestretch)}}%
}\x%
}
+\RequirePackage[maxnames=1,minnames=1,natbib=true,style=ieee,doi=false,url=false,isbn=false,isbn=false]{biblatex}
\RequirePackage[table]{xcolor}
\definecolor{huawei-red}{HTML}{CF0A2C}
\definecolor{huawei-black}{HTML}{232527}
\RequirePackage{tikz}
\RequirePackage{tabularx}
\RequirePackage{titling}
-\RequirePackage{fancyhdr}
- \pagestyle{empty}
-\RequirePackage{everypage}
\RequirePackage{svg}
\RequirePackage[normalem]{ulem}
\RequirePackage[hidelinks]{hyperref}
@@ -97,12 +95,6 @@
\endgroup\makeatother
\RequirePackage[absolute]{textpos}\TPGrid{16}{16}
-\newcommand\LeftHuaweiBar{%
- \begin{textblock}{1}[0,0](0,0)%
- \tikz \node[fill=huawei-red,minimum width=\TPHorizModule,minimum height=16\TPVertModule] {};%
- \end{textblock}%
-}
-
% Our custom commands to redefine:
\renewcommand\title[1]{\renewcommand\thetitle{#1}}
\newcommand\thetitle{Untitled}
@@ -115,7 +107,7 @@
% Custom commands
\newcommand\nospell[1]{#1}
-\newcommand\headers[1]{{\small\sffamily\color{gray}#1}}
+\newcommand\headers[1]{\setrelativestretch{0.8}{\small\sffamily\color{gray}#1}}
\newcommand\tbd[1]{{\color{red}#1}}
\newcommand\crumb[2]{\begin{minipage}{\columnwidth}\raggedright\textsc{#1}:\\#2\end{minipage}\vspace{4pt}}
\RequirePackage{tcolorbox}
@@ -132,116 +124,111 @@
\def\arraystretch{1.5}%
}
-\newcommand\PrintFirstPage[1]{
- \LeftHuaweiBar{}
- \def\param{#1}%
- \ifx\param\empty
- % nothing
- \else
- \includegraphics[height=2in]{#1}
- \fi
- \vspace*{0.5in}
- \maketitle
+\newcommand\LeftHuaweiBar{%
+ \begin{textblock}{1}[0,0](0,0)%
+ \tikz \node[fill=huawei-red,minimum width=\TPHorizModule,minimum height=16\TPVertModule] {};%
+ \end{textblock}%
}
-\AddEverypageHook{%
- \LeftHuaweiBar{}
- \ifnobrand%
- % nothing here
- \else%
- \begin{textblock}{8}[0,0](1.2,0.2)%
- \begin{tikzpicture}[y=0.80pt, x=0.80pt, yscale=-1, inner sep=0pt, outer sep=0pt]
- \begin{scope}[even odd rule,line width=0.800pt]
- \begin{scope}[shift={(0,-0.00024)}]
- \path[fill=huawei-black] (10.9375,30.2240) -- (10.9375,33.6097) .. controls (10.9375,34.5713) and (10.4603,35.0845) .. (9.5932,35.0845) .. controls (8.7212,35.0845) and (8.2411,34.5565) .. (8.2411,33.5686) -- (8.2411,30.2278) -- (7.0415,30.2278) -- (7.0415,33.6097) .. controls (7.0415,35.2737) and (7.9658,36.2272) .. (9.5774,36.2272) .. controls (11.2041,36.2272) and (12.1371,35.2554) .. (12.1371,33.5609) -- (12.1371,30.2240) -- (10.9375,30.2240) -- cycle;
- \path[fill=huawei-black] (15.3511,30.2240) -- (12.7456,36.1351) -- (13.9702,36.1351) -- (14.4731,34.9903) -- (14.5091,34.9045) -- (17.2158,34.9045) -- (17.7467,36.1351) -- (19.0045,36.1351) -- (16.4233,30.2590) -- (16.4001,30.2240) -- cycle;
- \path[fill=huawei-black] (22.4840,30.2240) -- (21.1414,34.2912) -- (19.8344,30.2271) -- (18.5578,30.2271) -- (20.6186,36.1388) -- (21.6120,36.1388) -- (22.9573,32.2553) -- (24.3016,36.1388) -- (25.3034,36.1388) -- (27.3592,30.2271) -- (26.1152,30.2271) -- (24.8055,34.2912) -- (23.4626,30.2240) -- cycle;
- \path[fill=huawei-black] (34.2236,30.2240) -- (34.2236,36.1300) -- (35.4074,36.1300) -- (35.4074,30.2240) -- cycle;
- \path[fill=huawei-black] (0.2686,30.2244) -- (0.2686,36.1384) -- (1.4686,36.1384) -- (1.4686,33.7365) -- (4.1780,33.7365) -- (4.1780,36.1384) -- (5.3783,36.1384) -- (5.3783,30.2244) -- (4.1780,30.2244) -- (4.1780,32.6102) -- (1.4686,32.6102) -- (1.4686,30.2244) -- cycle;
- \path[fill=huawei-black] (28.3267,30.2284) -- (28.3267,36.1344) -- (32.7928,36.1344) -- (32.7928,35.0575) -- (29.5105,35.0575) -- (29.5105,33.5931) -- (31.6931,33.5931) -- (31.6931,32.5160) -- (29.5105,32.5160) -- (29.5105,31.3052) -- (32.6785,31.3052) -- (32.6785,30.2284) -- cycle;
- \path[fill=white] (15.8594,31.7207) -- (16.7149,33.7008) -- (16.7119,33.7008) -- (16.7701,33.8374) -- (14.9552,33.8374) -- (15.0127,33.7008) -- (15.0117,33.7008) -- cycle;
- \path[fill=huawei-red] (15.2113,0.0001) .. controls (14.7353,0.0422) and (13.4491,0.3349) .. (13.4491,0.3349) -- (13.4486,0.3349) .. controls (10.5495,1.0843) and (9.8643,3.7151) .. (9.8643,3.7151) .. controls (9.7227,4.1575) and (9.6584,4.6109) .. (9.6395,5.0380) -- (9.6395,5.6194) .. controls (9.6780,6.5176) and (9.8777,7.1883) .. (9.8777,7.1883) .. controls (10.8461,11.4823) and (15.6075,18.5379) .. (16.6308,20.0200) .. controls (16.7034,20.0920) and (16.7615,20.0660) .. (16.7615,20.0660) .. controls (16.8720,20.0355) and (16.8633,19.9296) .. (16.8633,19.9296) -- (16.8654,19.9301) .. controls (18.4416,4.1760) and (15.2113,0.0001) .. (15.2113,0.0001) -- (15.2113,0.0001) -- cycle;
- \path[fill=huawei-red] (20.4192,0.0000) .. controls (20.4192,0.0000) and (17.1748,4.1782) .. (18.7521,19.9415) -- (18.7542,19.9415) .. controls (18.7664,20.0416) and (18.8374,20.0624) .. (18.8374,20.0624) .. controls (18.9430,20.1033) and (18.9971,20.0019) .. (18.9971,20.0019) -- (18.9976,20.0029) .. controls (20.0472,18.4829) and (24.7814,11.4657) .. (25.7455,7.1882) .. controls (25.7455,7.1882) and (26.2683,5.1179) .. (25.7636,3.7150) .. controls (25.7636,3.7150) and (25.0470,1.0434) .. (22.1442,0.3375) .. controls (22.1442,0.3375) and (21.3077,0.1251) .. (20.4193,0.0000) -- (20.4192,0.0000) -- cycle;
- \path[fill=huawei-red] (5.4542,4.7294) .. controls (5.4542,4.7294) and (2.6920,7.3513) .. (2.5547,10.1307) -- (2.5558,10.1307) -- (2.5558,10.5519) .. controls (2.5579,10.5836) and (2.5595,10.6157) .. (2.5615,10.6480) .. controls (2.6804,12.8893) and (4.3665,14.2157) .. (4.3665,14.2157) .. controls (7.0831,16.8634) and (13.6611,20.2062) .. (15.1896,20.9647) .. controls (15.2110,20.9727) and (15.2900,20.9985) .. (15.3364,20.9399) .. controls (15.3364,20.9399) and (15.3605,20.9216) .. (15.3715,20.8887) -- (15.3715,20.8189) .. controls (15.3704,20.8149) and (15.3683,20.8109) .. (15.3663,20.8065) -- (15.3669,20.8065) .. controls (11.1809,11.6620) and (5.4543,4.7294) .. (5.4543,4.7294) -- (5.4542,4.7294) -- cycle;
- \path[fill=huawei-red] (30.1695,4.7294) .. controls (30.1695,4.7294) and (24.4602,11.6403) .. (20.2761,20.7662) -- (20.2777,20.7657) .. controls (20.2777,20.7657) and (20.2283,20.8715) .. (20.3082,20.9399) .. controls (20.3082,20.9399) and (20.3320,20.9579) .. (20.3650,20.9652) -- (20.4229,20.9652) .. controls (20.4333,20.9622) and (20.4444,20.9582) .. (20.4554,20.9507) -- (20.4554,20.9517) .. controls (22.0255,20.1724) and (28.5525,16.8516) .. (31.2563,14.2162) .. controls (31.2563,14.2162) and (32.9686,12.8412) .. (33.0583,10.6334) .. controls (33.2560,7.5672) and (30.1696,4.7294) .. (30.1696,4.7294) -- (30.1695,4.7294) -- cycle;
- \path[fill=huawei-red] (35.3082,13.8080) .. controls (35.3082,13.8080) and (26.0003,18.8031) .. (21.1876,22.0494) -- (21.1882,22.0499) -- (21.1893,22.0509) .. controls (21.1893,22.0509) and (21.1019,22.1081) .. (21.1324,22.2106) .. controls (21.1324,22.2106) and (21.1781,22.2933) .. (21.2446,22.2933) -- (21.2446,22.2938) .. controls (22.9684,22.2968) and (29.4914,22.3041) .. (29.6549,22.2736) .. controls (29.6549,22.2736) and (30.4983,22.2399) .. (31.5406,21.8395) .. controls (31.5406,21.8395) and (33.8608,21.1019) .. (35.0659,18.4677) .. controls (35.0659,18.4677) and (35.6166,17.3662) .. (35.6246,15.8187) -- (35.6246,15.7531) .. controls (35.6206,15.1563) and (35.5365,14.4957) .. (35.3083,13.8080) -- (35.3082,13.8080) -- cycle;
- \path[fill=huawei-red] (0.3129,13.8313) .. controls (-0.5339,16.4531) and (0.6062,18.5656) .. (0.6080,18.5690) .. controls (1.7962,21.0795) and (4.0641,21.8401) .. (4.0641,21.8401) .. controls (5.1112,22.2703) and (6.1586,22.3000) .. (6.1586,22.3000) .. controls (6.3221,22.3300) and (12.6713,22.3030) .. (14.3725,22.2950) .. controls (14.4445,22.2945) and (14.4842,22.2221) .. (14.4842,22.2221) .. controls (14.4892,22.2142) and (14.4936,22.2062) .. (14.4955,22.1989) -- (14.4955,22.1333) .. controls (14.4814,22.0893) and (14.4439,22.0584) .. (14.4439,22.0584) -- (14.4450,22.0578) .. controls (9.6347,18.8126) and (0.3130,13.8315) .. (0.3130,13.8315) -- (0.3129,13.8313) -- cycle;
- \path[fill=huawei-red] (14.1782,23.1010) -- (3.2285,23.4850) .. controls (4.4160,25.6018) and (6.4158,27.2469) .. (8.4990,26.7416) .. controls (9.9366,26.3822) and (13.1935,24.1105) .. (14.2687,23.3429) -- (14.2651,23.3399) .. controls (14.3487,23.2648) and (14.3188,23.2045) .. (14.3188,23.2045) .. controls (14.2913,23.1062) and (14.1783,23.1063) .. (14.1783,23.1063) -- (14.1782,23.1010) -- cycle;
- \path[fill=huawei-red] (21.4305,23.1090) -- (21.4294,23.1130) .. controls (21.4294,23.1130) and (21.3333,23.1252) .. (21.3064,23.1972) .. controls (21.3064,23.1972) and (21.2831,23.2956) .. (21.3478,23.3445) -- (21.3467,23.3455) .. controls (22.3950,24.0973) and (25.5729,26.3191) .. (27.1039,26.7505) .. controls (27.1039,26.7505) and (27.3359,26.8294) .. (27.7246,26.8435) -- (27.9581,26.8435) .. controls (28.9839,26.8075) and (30.7708,26.2805) .. (32.3946,23.4907) -- (21.4305,23.1090) -- cycle;
- \end{scope}%
- \end{scope}%
- \end{tikzpicture}%
- \end{textblock}%
- \fi%
- \begin{textblock}{8}[1,0](15.8,0.2)%
- \raggedleft\headers{%
- \ifnosecurity%
- % nothing here
- \else%
- \thesecurity
+\newcommand\HuaweiLogo{
+ \begin{tikzpicture}[y=0.80pt, x=0.80pt, yscale=-1, inner sep=0pt, outer sep=0pt]
+ \begin{scope}[even odd rule,line width=0.800pt]
+ \begin{scope}[shift={(0,-0.00024)}]
+ \path[fill=huawei-black] (10.9375,30.2240) -- (10.9375,33.6097) .. controls (10.9375,34.5713) and (10.4603,35.0845) .. (9.5932,35.0845) .. controls (8.7212,35.0845) and (8.2411,34.5565) .. (8.2411,33.5686) -- (8.2411,30.2278) -- (7.0415,30.2278) -- (7.0415,33.6097) .. controls (7.0415,35.2737) and (7.9658,36.2272) .. (9.5774,36.2272) .. controls (11.2041,36.2272) and (12.1371,35.2554) .. (12.1371,33.5609) -- (12.1371,30.2240) -- (10.9375,30.2240) -- cycle;
+ \path[fill=huawei-black] (15.3511,30.2240) -- (12.7456,36.1351) -- (13.9702,36.1351) -- (14.4731,34.9903) -- (14.5091,34.9045) -- (17.2158,34.9045) -- (17.7467,36.1351) -- (19.0045,36.1351) -- (16.4233,30.2590) -- (16.4001,30.2240) -- cycle;
+ \path[fill=huawei-black] (22.4840,30.2240) -- (21.1414,34.2912) -- (19.8344,30.2271) -- (18.5578,30.2271) -- (20.6186,36.1388) -- (21.6120,36.1388) -- (22.9573,32.2553) -- (24.3016,36.1388) -- (25.3034,36.1388) -- (27.3592,30.2271) -- (26.1152,30.2271) -- (24.8055,34.2912) -- (23.4626,30.2240) -- cycle;
+ \path[fill=huawei-black] (34.2236,30.2240) -- (34.2236,36.1300) -- (35.4074,36.1300) -- (35.4074,30.2240) -- cycle;
+ \path[fill=huawei-black] (0.2686,30.2244) -- (0.2686,36.1384) -- (1.4686,36.1384) -- (1.4686,33.7365) -- (4.1780,33.7365) -- (4.1780,36.1384) -- (5.3783,36.1384) -- (5.3783,30.2244) -- (4.1780,30.2244) -- (4.1780,32.6102) -- (1.4686,32.6102) -- (1.4686,30.2244) -- cycle;
+ \path[fill=huawei-black] (28.3267,30.2284) -- (28.3267,36.1344) -- (32.7928,36.1344) -- (32.7928,35.0575) -- (29.5105,35.0575) -- (29.5105,33.5931) -- (31.6931,33.5931) -- (31.6931,32.5160) -- (29.5105,32.5160) -- (29.5105,31.3052) -- (32.6785,31.3052) -- (32.6785,30.2284) -- cycle;
+ \path[fill=white] (15.8594,31.7207) -- (16.7149,33.7008) -- (16.7119,33.7008) -- (16.7701,33.8374) -- (14.9552,33.8374) -- (15.0127,33.7008) -- (15.0117,33.7008) -- cycle;
+ \path[fill=huawei-red] (15.2113,0.0001) .. controls (14.7353,0.0422) and (13.4491,0.3349) .. (13.4491,0.3349) -- (13.4486,0.3349) .. controls (10.5495,1.0843) and (9.8643,3.7151) .. (9.8643,3.7151) .. controls (9.7227,4.1575) and (9.6584,4.6109) .. (9.6395,5.0380) -- (9.6395,5.6194) .. controls (9.6780,6.5176) and (9.8777,7.1883) .. (9.8777,7.1883) .. controls (10.8461,11.4823) and (15.6075,18.5379) .. (16.6308,20.0200) .. controls (16.7034,20.0920) and (16.7615,20.0660) .. (16.7615,20.0660) .. controls (16.8720,20.0355) and (16.8633,19.9296) .. (16.8633,19.9296) -- (16.8654,19.9301) .. controls (18.4416,4.1760) and (15.2113,0.0001) .. (15.2113,0.0001) -- (15.2113,0.0001) -- cycle;
+ \path[fill=huawei-red] (20.4192,0.0000) .. controls (20.4192,0.0000) and (17.1748,4.1782) .. (18.7521,19.9415) -- (18.7542,19.9415) .. controls (18.7664,20.0416) and (18.8374,20.0624) .. (18.8374,20.0624) .. controls (18.9430,20.1033) and (18.9971,20.0019) .. (18.9971,20.0019) -- (18.9976,20.0029) .. controls (20.0472,18.4829) and (24.7814,11.4657) .. (25.7455,7.1882) .. controls (25.7455,7.1882) and (26.2683,5.1179) .. (25.7636,3.7150) .. controls (25.7636,3.7150) and (25.0470,1.0434) .. (22.1442,0.3375) .. controls (22.1442,0.3375) and (21.3077,0.1251) .. (20.4193,0.0000) -- (20.4192,0.0000) -- cycle;
+ \path[fill=huawei-red] (5.4542,4.7294) .. controls (5.4542,4.7294) and (2.6920,7.3513) .. (2.5547,10.1307) -- (2.5558,10.1307) -- (2.5558,10.5519) .. controls (2.5579,10.5836) and (2.5595,10.6157) .. (2.5615,10.6480) .. controls (2.6804,12.8893) and (4.3665,14.2157) .. (4.3665,14.2157) .. controls (7.0831,16.8634) and (13.6611,20.2062) .. (15.1896,20.9647) .. controls (15.2110,20.9727) and (15.2900,20.9985) .. (15.3364,20.9399) .. controls (15.3364,20.9399) and (15.3605,20.9216) .. (15.3715,20.8887) -- (15.3715,20.8189) .. controls (15.3704,20.8149) and (15.3683,20.8109) .. (15.3663,20.8065) -- (15.3669,20.8065) .. controls (11.1809,11.6620) and (5.4543,4.7294) .. (5.4543,4.7294) -- (5.4542,4.7294) -- cycle;
+ \path[fill=huawei-red] (30.1695,4.7294) .. controls (30.1695,4.7294) and (24.4602,11.6403) .. (20.2761,20.7662) -- (20.2777,20.7657) .. controls (20.2777,20.7657) and (20.2283,20.8715) .. (20.3082,20.9399) .. controls (20.3082,20.9399) and (20.3320,20.9579) .. (20.3650,20.9652) -- (20.4229,20.9652) .. controls (20.4333,20.9622) and (20.4444,20.9582) .. (20.4554,20.9507) -- (20.4554,20.9517) .. controls (22.0255,20.1724) and (28.5525,16.8516) .. (31.2563,14.2162) .. controls (31.2563,14.2162) and (32.9686,12.8412) .. (33.0583,10.6334) .. controls (33.2560,7.5672) and (30.1696,4.7294) .. (30.1696,4.7294) -- (30.1695,4.7294) -- cycle;
+ \path[fill=huawei-red] (35.3082,13.8080) .. controls (35.3082,13.8080) and (26.0003,18.8031) .. (21.1876,22.0494) -- (21.1882,22.0499) -- (21.1893,22.0509) .. controls (21.1893,22.0509) and (21.1019,22.1081) .. (21.1324,22.2106) .. controls (21.1324,22.2106) and (21.1781,22.2933) .. (21.2446,22.2933) -- (21.2446,22.2938) .. controls (22.9684,22.2968) and (29.4914,22.3041) .. (29.6549,22.2736) .. controls (29.6549,22.2736) and (30.4983,22.2399) .. (31.5406,21.8395) .. controls (31.5406,21.8395) and (33.8608,21.1019) .. (35.0659,18.4677) .. controls (35.0659,18.4677) and (35.6166,17.3662) .. (35.6246,15.8187) -- (35.6246,15.7531) .. controls (35.6206,15.1563) and (35.5365,14.4957) .. (35.3083,13.8080) -- (35.3082,13.8080) -- cycle;
+ \path[fill=huawei-red] (0.3129,13.8313) .. controls (-0.5339,16.4531) and (0.6062,18.5656) .. (0.6080,18.5690) .. controls (1.7962,21.0795) and (4.0641,21.8401) .. (4.0641,21.8401) .. controls (5.1112,22.2703) and (6.1586,22.3000) .. (6.1586,22.3000) .. controls (6.3221,22.3300) and (12.6713,22.3030) .. (14.3725,22.2950) .. controls (14.4445,22.2945) and (14.4842,22.2221) .. (14.4842,22.2221) .. controls (14.4892,22.2142) and (14.4936,22.2062) .. (14.4955,22.1989) -- (14.4955,22.1333) .. controls (14.4814,22.0893) and (14.4439,22.0584) .. (14.4439,22.0584) -- (14.4450,22.0578) .. controls (9.6347,18.8126) and (0.3130,13.8315) .. (0.3130,13.8315) -- (0.3129,13.8313) -- cycle;
+ \path[fill=huawei-red] (14.1782,23.1010) -- (3.2285,23.4850) .. controls (4.4160,25.6018) and (6.4158,27.2469) .. (8.4990,26.7416) .. controls (9.9366,26.3822) and (13.1935,24.1105) .. (14.2687,23.3429) -- (14.2651,23.3399) .. controls (14.3487,23.2648) and (14.3188,23.2045) .. (14.3188,23.2045) .. controls (14.2913,23.1062) and (14.1783,23.1063) .. (14.1783,23.1063) -- (14.1782,23.1010) -- cycle;
+ \path[fill=huawei-red] (21.4305,23.1090) -- (21.4294,23.1130) .. controls (21.4294,23.1130) and (21.3333,23.1252) .. (21.3064,23.1972) .. controls (21.3064,23.1972) and (21.2831,23.2956) .. (21.3478,23.3445) -- (21.3467,23.3455) .. controls (22.3950,24.0973) and (25.5729,26.3191) .. (27.1039,26.7505) .. controls (27.1039,26.7505) and (27.3359,26.8294) .. (27.7246,26.8435) -- (27.9581,26.8435) .. controls (28.9839,26.8075) and (30.7708,26.2805) .. (32.3946,23.4907) -- (21.4305,23.1090) -- cycle;
+ \end{scope}%
+ \end{scope}%
+ \end{tikzpicture}%
+}
+
+\RequirePackage{fancyhdr}
+ \pagestyle{fancy}
+ \renewcommand{\headrulewidth}{0pt}
+ \fancyhf{}
+ \fancyfoot[L]{
+ \LeftHuaweiBar{}
+ \ifnum\value{page}=1\else%
+ \ifnobrand\else%
+ \begin{textblock}{8}[0,0](1.2,0.2)%
+ \HuaweiLogo{}%
+ \end{textblock}%
\fi%
- }%
- \end{textblock}%
- \begin{textblock}{8}[0,1](1.2,15.8)%
- \headers{%
- \ifanonymous%
- % nothing here
- \else%
- \theauthor%
- \ifnosecurity%
- % nothing here
- \else,
- \theid
- \fi%
- \ifnobrand%
- % nothing here
- \else%
- \\[2pt]
+ \fi%
+ \begin{textblock}{8}[1,0](15.8,0.2)%
+ \raggedleft\headers{%
+ \ifnosecurity\else%
+ \thesecurity
\fi%
+ }%
+ \end{textblock}%
+ \begin{textblock}{8}[0,1](1.2,15.8)%
+ \ifnum\value{page}=1\else%
+ \headers{%
+ \ifanonymous\else%
+ \theauthor%
+ \ifnosecurity\else,
+ \theid
+ \fi%
+ \ifnobrand\else%
+ \newline
+ \fi%
+ \fi%
+ \ifnobrand\else%
+ \thecompany{}
+ \fi%
+ }%
\fi%
- \ifnobrand%
- % nothing here
- \else%
- \thecompany{}
- \fi%
- }%
- \end{textblock}%
- \begin{textblock}{8}[1,1](15.8,15.8)%
- \raggedleft\headers{%
- \ifnopaging%
- % nothing here
- \else%
- Page \#\thepage{} of \pageref*{LastPage}
- \ifnodate%
- % nothing here
- \else%
- \\[2pt]
+ \end{textblock}%
+ \begin{textblock}{8}[1,1](15.8,15.8)%
+ \raggedleft\headers{%
+ \ifnum\value{page}=1\else%
+ \ifnopaging\else%
+ Page \#\thepage{} of \pageref*{LastPage}%
+ \ifnodate\else%
+ \\
+ \fi%
+ \fi%
\fi%
- \fi%
- \ifnodate%
- % nothing here
- \else%
- \today{} \currenttime
- \fi%
- }%
- \end{textblock}%
-}
+ \ifnodate\else%
+ \today{} \currenttime
+ \fi%
+ }%
+ \end{textblock}%
+ }
\renewcommand\maketitle{%
-\vspace*{18pt}
-{\bfseries{\Huge\thetitle}}
-\\[6pt]
-\ifx\thesubtitle\empty\else%
- {\color{gray!50!black}\large\thesubtitle}
-\fi
-\\[18pt]
-\ifx\theauthor\empty\else%
- {\scshape\theauthor}\\
-\fi
-\ifx\theauthor\empty\else%
- {\theid}
-\fi
-\vspace{2em}
+ \vspace*{18pt}
+ {\bfseries{\Huge\thetitle}}
+ \\[6pt]
+ \ifx\thesubtitle\empty\else%
+ {\color{gray!50!black}\large\thesubtitle}
+ \fi
+ \\[18pt]
+ \ifanonymous\else%
+ \thecompany\newline
+ \fi
+ \ifx\theauthor\empty\else%
+ {\scshape\theauthor}%
+ \fi%
+ \ifx\theauthor\empty\else
+ \ifx\theid\empty\else
+ \;/ {\theid}
+ \fi
+ \fi\newline
+ \vspace{2em}
}
\newcommand\PrintThankYouPage{
@@ -274,6 +261,16 @@
cannot be held liable for the use of and reliance of the opinions, estimates, forecasts and
findings in these documents.}}}
+\newcommand\PrintFirstPage[1]{
+ \LeftHuaweiBar{}
+ \def\param{#1}%
+ \ifx\param\empty\else
+ \includegraphics[height=2in]{#1}
+ \fi
+ \vspace*{0.5in}
+ \maketitle
+}
+
\newcommand\PrintLastPage{
\newpage
\vspace*{1in}
@@ -285,15 +282,18 @@
\vspace{0.5in}
\begin{CJK}{UTF8}{gbsn}
- 把数字世界带入每个人、每个家庭、
每个组织,构建万物互联的智能世界。
+ 把数字世界带入每个人、每个家庭、
每个组织、构建万物互联的智能世界。
\end{CJK}
- Bring digital to every person, home and
- organization for a fully connected,
- intelligent world.
+ Bring digital to every person, home and organization
+ \newline
+ for a fully connected, intelligent world.
- \textbf{Copyright \copyright{} \the\year{} \thecompany{}\\
- All Rights Reserved.}
+ \textbf{%
+ Copyright \copyright{} \the\year{} \thecompany{}
+ \newline
+ All Rights Reserved.%
+ }
The information in this document may contain predictive
statements including, without limitation, statements regarding
@@ -308,4 +308,16 @@
\end{center}%
}
+\newcommand\PrintBibliography{
+ \setlength\bibitemsep{0pt}
+ \AtNextBibliography{\small}
+ \newpage
+ \raggedright
+ \iflandscape
+ \begin{multicols}{3}\setrelativestretch{1.0}{\printbibliography}\end{multicols}
+ \else
+ \begin{multicols}{2}\setrelativestretch{1.0}{\printbibliography}\end{multicols}
+ \fi
+}
+
\endinput \ No newline at end of file
diff --git a/macros/latex/contrib/huawei/huawei.pdf b/macros/latex/contrib/huawei/huawei.pdf
index d0341ad561..0c4cfd48e1 100644
--- a/macros/latex/contrib/huawei/huawei.pdf
+++ b/macros/latex/contrib/huawei/huawei.pdf
Binary files differ
diff --git a/macros/latex/contrib/huawei/huawei.tex b/macros/latex/contrib/huawei/huawei.tex
index adacc3b092..dc2d76e5cf 100644
--- a/macros/latex/contrib/huawei/huawei.tex
+++ b/macros/latex/contrib/huawei/huawei.tex
@@ -5,7 +5,9 @@
\begin{document}
\maketitle
-\ff{Version 0.1.0}
+\ff{Version: 0.2.0}
+\newline
+\ff{Date: 13/05/2021}
\section{Overview}
diff --git a/macros/latex/contrib/tabularray/README b/macros/latex/contrib/tabularray/README
new file mode 100644
index 0000000000..b4714bd0a7
--- /dev/null
+++ b/macros/latex/contrib/tabularray/README
@@ -0,0 +1,4 @@
+Package: Typeset tabulars and arrays with LaTeX3
+Author: Jianrui Lyu <tolvjr@163.com>
+Repository: https://github.com/lvjr/tabularray
+License: The LaTeX Project Public License 1.3
diff --git a/macros/latex/contrib/tabularray/tabularray.pdf b/macros/latex/contrib/tabularray/tabularray.pdf
new file mode 100644
index 0000000000..f367583b1b
--- /dev/null
+++ b/macros/latex/contrib/tabularray/tabularray.pdf
Binary files differ
diff --git a/macros/latex/contrib/tabularray/tabularray.sty b/macros/latex/contrib/tabularray/tabularray.sty
new file mode 100644
index 0000000000..dbd07ddc8e
--- /dev/null
+++ b/macros/latex/contrib/tabularray/tabularray.sty
@@ -0,0 +1,3897 @@
+%%% % -*- coding: utf-8 -*-
+%%% ----------------------------------------------------------------------------
+%%% Tabularray: Typeset tabulars and arrays with LaTeX3
+%%% Author : Jianrui Lyu <tolvjr@163.com>
+%%% Repository: https://github.com/lvjr/tabularray
+%%% License : The LaTeX Project Public License 1.3
+%%% ----------------------------------------------------------------------------
+
+%%% --------------------------------------------------------
+%% \section{Scratch Variables and Data Structures}
+%%% --------------------------------------------------------
+
+\NeedsTeXFormat{LaTeX2e}
+\RequirePackage{expl3}
+\ProvidesExplPackage{tabularray}{2021-05-13}{2021H}
+ {Typeset tabulars and arrays with LaTeX3}
+
+%\RequirePackage{xparse}
+\AtBeginDocument{\@ifpackageloaded{xcolor}{\RequirePackage{ninecolors}}{}}
+
+\ExplSyntaxOn
+
+\cs_if_exist:NF \vbox_set_top_to_ht:Nnn
+ {
+ \cs_new_protected:Npn \vbox_set_top_to_ht:Nnn #1 #2 #3
+ {
+ \tex_setbox:D #1 \tex_vtop:D to \dim_eval:n { #2 }
+ { \color_group_begin: #3 \par \color_group_end: }
+ }
+ }
+
+\cs_generate_variant:Nn \msg_error:nnnn { nnVn }
+\cs_generate_variant:Nn \prop_item:Nn { Ne, NV }
+\cs_generate_variant:Nn \prop_put:Nnn { Nxn, Nxx, NxV }
+\cs_generate_variant:Nn \regex_replace_all:NnN { NVN }
+\cs_generate_variant:Nn \seq_map_indexed_inline:Nn { cn }
+\cs_generate_variant:Nn \tl_gput_right:Nn { Nf }
+\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { Nx } { TF }
+\prg_generate_conditional_variant:Nnn \prop_if_in:Nn { c } { T }
+\prg_generate_conditional_variant:Nnn \str_if_eq:nn { xn } { TF }
+\prg_generate_conditional_variant:Nnn \tl_if_eq:nn { en } { T, TF }
+\prg_generate_conditional_variant:Nnn \tl_if_head_eq_meaning:nN { VN } { T, TF }
+
+\tl_new:N \l__tblr_a_tl
+\tl_new:N \l__tblr_b_tl
+\tl_new:N \l__tblr_c_tl
+\tl_new:N \l__tblr_d_tl
+\tl_new:N \l__tblr_e_tl
+\tl_new:N \l__tblr_f_tl
+\tl_new:N \l__tblr_h_tl
+\tl_new:N \l__tblr_i_tl % for row index
+\tl_new:N \l__tblr_j_tl % for column index
+\tl_new:N \l__tblr_k_tl
+\tl_new:N \l__tblr_n_tl
+\tl_new:N \l__tblr_o_tl
+\tl_new:N \l__tblr_r_tl
+\tl_new:N \l__tblr_s_tl
+\tl_new:N \l__tblr_t_tl
+\tl_new:N \l__tblr_u_tl
+\tl_new:N \l__tblr_v_tl
+\tl_new:N \l__tblr_w_tl
+\tl_new:N \l__tblr_x_tl
+\tl_new:N \l__tblr_y_tl
+\int_new:N \l__tblr_a_int
+\int_new:N \l__tblr_c_int % for column number
+\int_new:N \l__tblr_r_int % for row number
+\dim_new:N \l__tblr_d_dim % for depth
+\dim_new:N \l__tblr_h_dim % for height
+\dim_new:N \l__tblr_o_dim
+\dim_new:N \l__tblr_p_dim
+\dim_new:N \l__tblr_q_dim
+\dim_new:N \l__tblr_r_dim
+\dim_new:N \l__tblr_s_dim
+\dim_new:N \l__tblr_t_dim
+\dim_new:N \l__tblr_v_dim
+\dim_new:N \l__tblr_w_dim % for width
+\box_new:N \l__tblr_a_box
+\box_new:N \l__tblr_b_box
+\box_new:N \l__tblr_c_box % for cell box
+\box_new:N \l__tblr_d_box
+
+\int_new:N \g_tblr_level_int % store table nesting level
+
+\cs_new_protected:Npn \__tblr_prop_gput:nnn #1 #2 #3
+ {
+ \prop_gput:cnn
+ { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
+ }
+\cs_generate_variant:Nn \__tblr_prop_gput:nnn { nnx, nnV, nxn, nxx, nxV }
+
+\cs_new:Npn \__tblr_prop_item:nn #1 #2
+ {
+ \prop_item:cn { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 }
+ }
+\cs_generate_variant:Nn \__tblr_prop_item:nn { ne }
+
+\cs_new_protected:Npn \__tblr_prop_if_in:nnT #1
+ {
+ \prop_if_in:cnT { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop }
+ }
+\cs_new_protected:Npn \__tblr_prop_if_in:nnF #1
+ {
+ \prop_if_in:cnF { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop }
+ }
+\cs_new_protected:Npn \__tblr_prop_if_in:nnTF #1
+ {
+ \prop_if_in:cnTF { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop }
+ }
+\prg_generate_conditional_variant:Nnn \__tblr_prop_if_in:nn { nx } { T, F, TF }
+
+\cs_new_protected:Npn \__tblr_prop_log:n #1
+ {
+ \prop_log:c { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop }
+ }
+
+\cs_new_protected:Npn \__tblr_prop_map_inline:nn #1 #2
+ {
+ \prop_map_inline:cn { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop } {#2}
+ }
+
+\cs_new_protected:Npn \__tblr_prop_gput_if_larger:nnn #1 #2 #3
+ {
+ \__tblr_gput_if_larger:cnn
+ { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
+ }
+\cs_generate_variant:Nn \__tblr_prop_gput_if_larger:nnn { nnx, nnV, nxn, nxx, nxV }
+
+\cs_new_protected:Npn \__tblr_prop_gadd_dimen_value:nnn #1 #2 #3
+ {
+ \__tblr_gadd_dimen_value:cnn
+ { g_tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
+ }
+\cs_generate_variant:Nn \__tblr_prop_gadd_dimen_value:nnn { nnx, nnV, nxn, nxx }
+
+%% Put the dimension to the prop list only if it's larger than the old one
+
+\tl_new:N \l__tblr_put_if_larger_tl
+
+\cs_new_protected:Npn \__tblr_put_if_larger:Nnn #1 #2 #3
+ {
+ \tl_set:Nx \l__tblr_put_if_larger_tl { \prop_item:Nn #1 { #2 } }
+ \bool_lazy_or:nnT
+ { \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
+ { \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } }
+ { \prop_put:Nnn #1 { #2 } { #3 } }
+ }
+\cs_generate_variant:Nn \__tblr_put_if_larger:Nnn { Nnx, Nxn, Nxx }
+
+\cs_new_protected:Npn \__tblr_gput_if_larger:Nnn #1 #2 #3
+ {
+ \tl_set:Nx \l__tblr_put_if_larger_tl { \prop_item:Nn #1 { #2 } }
+ \bool_lazy_or:nnT
+ { \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
+ { \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } }
+ { \prop_gput:Nnn #1 { #2 } { #3 } }
+ }
+\cs_generate_variant:Nn \__tblr_gput_if_larger:Nnn { Nnx, Nxn, Nxx, cnn }
+
+%% Add the dimension to some key value of the prop list
+%% #1: the prop list, #2: the key, #3: the dimen to add
+
+\cs_new_protected:Npn \__tblr_add_dimen_value:Nnn #1 #2 #3
+ {
+ \prop_put:Nnx #1 { #2 } { \dim_eval:n { \prop_item:Nn #1 { #2 } + #3 } }
+ }
+\cs_generate_variant:Nn \__tblr_add_dimen_value:Nnn { cnn }
+
+\cs_new_protected:Npn \__tblr_gadd_dimen_value:Nnn #1 #2 #3
+ {
+ \prop_gput:Nnx #1 { #2 } { \dim_eval:n { \prop_item:Nn #1 { #2 } + #3 } }
+ }
+\cs_generate_variant:Nn \__tblr_gadd_dimen_value:Nnn { cnn }
+
+%% Some counters for row and column numbering
+\newcounter{rownum}
+\newcounter{colnum}
+\newcounter{rowcount}
+\newcounter{colcount}
+
+%%% --------------------------------------------------------
+%% \section{Child Selectors}
+%%% --------------------------------------------------------
+
+\clist_new:N \g_tblr_used_child_selectors_clist
+
+\tl_new:N \l__tblr_childs_arg_spec_tl
+
+\msg_new:nnn { tabularray } { used-child-selector }
+ { Child ~ selector ~ name ~ "#1" ~ has ~ been ~ used! }
+
+\NewDocumentCommand \NewChildSelector { m O{0} o m }
+ {
+ \__tblr_new_child_selector_aux:xnnn { \tl_trim_spaces:n {#1} } {#2} {#3} {#4}
+ }
+
+\cs_new_protected:Npn \__tblr_new_child_selector_aux:nnnn #1 #2 #3 #4
+ {
+ \clist_if_in:NnTF \g_tblr_used_child_selectors_clist { #1 }
+ {
+ \msg_error:nnn { tabularray } { used-child-selector } { #1 }
+ \clist_log:N \g_tblr_used_child_selectors_clist
+ }
+ {
+ \__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_childs_arg_spec_tl
+ \exp_args:NcV \NewDocumentCommand
+ { __tblr_child_selector_ #1 :w } \l__tblr_childs_arg_spec_tl { #4 }
+ \clist_gput_right:Nn \g_tblr_used_child_selectors_clist { #1 }
+ }
+ }
+\cs_generate_variant:Nn \__tblr_new_child_selector_aux:nnnn { xnnn }
+
+%% #1: argument number, #2: optional argument default, #3: result tl
+\cs_new_protected:Npn \__tblr_make_xparse_arg_spec:nnN #1 #2 #3
+ {
+ \tl_clear:N #3
+ \int_compare:nNnT { #1 } > { 0 }
+ {
+ \IfValueTF { #2 }
+ { \tl_set:Nn #3 { O{#2} } }
+ { \tl_set:Nn #3 { m } }
+ \tl_put_right:Nx #3 { \prg_replicate:nn { #1 - 1 } { m } }
+ }
+ }
+
+\clist_new:N \l_tblr_childs_clist
+\tl_new:N \l_tblr_childs_total_tl
+
+\NewChildSelector { odd }
+ {
+ \int_step_inline:nnnn {1} {2} { \l_tblr_childs_total_tl }
+ { \clist_put_right:Nn \l_tblr_childs_clist {##1} }
+ }
+
+\NewChildSelector { even }
+ {
+ \int_step_inline:nnnn {2} {2} { \l_tblr_childs_total_tl }
+ { \clist_put_right:Nn \l_tblr_childs_clist {##1} }
+ }
+
+\regex_const:Nn \c__tblr_split_selector_name_regex { ^ ( [A-Za-z] {2,} ) ( . * ) }
+\seq_new:N \l__tblr_childs_split_seq
+\seq_new:N \l__tblr_childs_regex_seq
+\tl_new:N \l__tblr_childs_end_tl
+\tl_new:N \l__tblr_childs_selector_tl
+
+%% #1, child specifications; #2, total number.
+%% The result will be put into \l_tblr_childs_clist
+\cs_new_protected:Npn \__tblr_get_childs:nn #1 #2
+ {
+ \clist_clear:N \l_tblr_childs_clist
+ \tl_set:Nx \l_tblr_childs_total_tl {#2}
+ \regex_extract_once:NnNTF \c__tblr_split_selector_name_regex {#1}
+ \l__tblr_childs_regex_seq
+ {
+ \tl_set:No \l__tblr_childs_selector_tl
+ {
+ \cs:w
+ __tblr_child_selector_ \seq_item:Nn \l__tblr_childs_regex_seq {2} :w
+ \cs_end:
+ }
+ \exp_args:Nx \l__tblr_childs_selector_tl
+ { \seq_item:Nn \l__tblr_childs_regex_seq{3} }
+ }
+ {
+ \tl_if_eq:nnTF {#1} {-}
+ { \__tblr_get_childs_normal:nn {1-#2} {#2} }
+ { \__tblr_get_childs_normal:nn {#1} {#2} }
+ }
+ %\clist_log:N \l_tblr_childs_clist
+ }
+\cs_generate_variant:Nn \__tblr_get_childs:nn { nx }
+
+\cs_new_protected:Npn \__tblr_get_childs_normal:nn #1 #2
+ {
+ \seq_set_split:Nnn \l__tblr_childs_split_seq {,} {#1}
+ \seq_map_inline:Nn \l__tblr_childs_split_seq
+ { \__tblr_get_childs_normal_aux:w ##1 - s \scan_stop }
+ }
+
+\cs_new_protected_nopar:Npn \__tblr_get_childs_normal_aux:w #1 - #2 #3 \scan_stop
+ {
+ \tl_if_eq:nnTF {#2} {s}
+ { \tl_set:Nn \l__tblr_childs_end_tl {#1} }
+ { \tl_set:Nn \l__tblr_childs_end_tl {#2} }
+ \int_step_inline:nnn {#1} { \l__tblr_childs_end_tl }
+ { \clist_put_right:Nn \l_tblr_childs_clist {##1} }
+ }
+
+%%% --------------------------------------------------------
+%% \section{New Table Commands}
+%%% --------------------------------------------------------
+
+%% We need some commands to modify table/row/column/cell specifications.
+%% These commands must be defined with \NewTableCommand command,
+%% so that we could extract them, execute them once, then disable them.
+
+\clist_new:N \g__tblr_table_commands_clist
+
+\msg_new:nnn { tabularray } { defined-table-command }
+ { Table ~ commnad ~ #1 has ~ been ~ defined! }
+
+\NewDocumentCommand \NewTableCommand { m O{0} o m }
+ {
+ \clist_if_in:NnTF \g__tblr_table_commands_clist { #1 }
+ {
+ \msg_error:nnn { tabularray } { defined-table-command } { #1 }
+ \clist_log:N \g__tblr_table_commands_clist
+ }
+ {
+ \__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_a_tl
+ \exp_args:NcV \NewDocumentCommand
+ { __tblr_table_command_ \cs_to_str:N #1 :w } \l__tblr_a_tl { #4 }
+ \exp_args:NcV \NewDocumentCommand
+ { __tblr_table_command_ \cs_to_str:N #1 _gobble :w } \l__tblr_a_tl { }
+ \IfValueTF { #3 }
+ {
+ \tl_gset:cn { g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl } {-#2}
+ }
+ {
+ \tl_gset:cn { g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl } {#2}
+ }
+ \clist_gput_right:Nn \g__tblr_table_commands_clist { #1 }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_enable_table_commands:
+ {
+ \clist_map_inline:Nn \g__tblr_table_commands_clist
+ { \cs_set_eq:Nc ##1 { __tblr_table_command_ \cs_to_str:N ##1 :w } }
+ }
+
+\cs_new_protected:Npn \__tblr_disable_table_commands:
+ {
+ \clist_map_inline:Nn \g__tblr_table_commands_clist
+ { \cs_set_eq:Nc ##1 { __tblr_table_command_ \cs_to_str:N ##1 _gobble:w } }
+ }
+
+\cs_new_protected:Npn \__tblr_execute_table_commands:
+ {
+ \__tblr_prop_map_inline:nn { command }
+ {
+ \__tblr_set_row_col_from_key_name:w ##1
+ ##2
+ }
+ \LogTblrTracing { cell }
+ }
+
+\cs_new_protected:Npn \__tblr_set_row_col_from_key_name:w [#1][#2]
+ {
+ \int_set:Nn \c@rownum {#1}
+ \int_set:Nn \c@colnum {#2}
+ }
+
+%%% --------------------------------------------------------
+%% \section{New Dash Styles}
+%%% --------------------------------------------------------
+
+%% \NewDashStyle commands
+
+\dim_zero_new:N \rulewidth
+\dim_set:Nn \rulewidth {0.4pt}
+
+\prop_gset_from_keyval:Nn \g__tblr_defined_hdash_styles_prop
+ { solid = \hrule height \rulewidth }
+\prop_gset_from_keyval:Nn \g__tblr_defined_vdash_styles_prop
+ { solid = \vrule width \rulewidth }
+
+\NewDocumentCommand \NewDashStyle { m m }
+ {
+ \seq_set_split:Nnn \l_tmpa_seq { ~ } {#2}
+ \tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {1} }
+ \tl_set:Nx \l__tblr_b_tl { \seq_item:Nn \l_tmpa_seq {2} }
+ \tl_set:Nx \l__tblr_c_tl { \seq_item:Nn \l_tmpa_seq {3} }
+ \tl_set:Nx \l__tblr_d_tl { \seq_item:Nn \l_tmpa_seq {4} }
+ \tl_if_eq:NnT \l__tblr_a_tl { on }
+ {
+ \tl_if_eq:NnT \l__tblr_c_tl { off }
+ {
+ \__tblr_dash_style_make_boxes:nxx {#1}
+ { \dim_eval:n {\l__tblr_b_tl} } { \dim_eval:n {\l__tblr_d_tl} }
+ }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_dash_style_make_boxes:nnn #1 #2 #3
+ {
+ \dim_set:Nn \l_tmpa_dim { #2 + #3 }
+ \tl_set:Nn \l__tblr_h_tl { \hbox_to_wd:nn }
+ \tl_put_right:Nx \l__tblr_h_tl { { \dim_use:N \l_tmpa_dim } }
+ \tl_put_right:Nn \l__tblr_h_tl
+ {
+ { \hss \vbox:n { \hbox_to_wd:nn {#2} {} \hrule height \rulewidth } \hss }
+ }
+ \prop_gput:NnV \g__tblr_defined_hdash_styles_prop {#1} \l__tblr_h_tl
+ %\prop_log:N \g__tblr_defined_hdash_styles_prop
+ \tl_set:Nn \l__tblr_v_tl { \vbox_to_ht:nn }
+ \tl_put_right:Nx \l__tblr_v_tl { { \dim_use:N \l_tmpa_dim } }
+ \tl_put_right:Nn \l__tblr_v_tl
+ {
+ { \vss \hbox:n { \vbox_to_ht:nn {#2} {} \vrule width \rulewidth } \vss }
+ }
+ \prop_gput:NnV \g__tblr_defined_vdash_styles_prop {#1} \l__tblr_v_tl
+ %\prop_log:N \g__tblr_defined_vdash_styles_prop
+ }
+\cs_generate_variant:Nn \__tblr_dash_style_make_boxes:nnn { nxx }
+
+\cs_new_protected:Npn \__tblr_get_hline_dash_style:N #1
+ {
+ \tl_set:Nx \l_tmpa_tl
+ { \prop_item:NV \g__tblr_defined_hdash_styles_prop #1 }
+ \tl_if_empty:NF \l_tmpa_tl { \tl_set_eq:NN #1 \l_tmpa_tl }
+ }
+
+\cs_new_protected:Npn \__tblr_get_vline_dash_style:N #1
+ {
+ \tl_set:Nx \l_tmpa_tl
+ { \prop_item:NV \g__tblr_defined_vdash_styles_prop #1 }
+ \tl_if_empty:NF \l_tmpa_tl { \tl_set_eq:NN #1 \l_tmpa_tl }
+ }
+
+\NewDashStyle {dashed} {on ~ 2pt ~ off ~ 2pt}
+\NewDashStyle {dotted} {on ~ 0.4pt ~ off ~ 1pt}
+
+%%% --------------------------------------------------------
+%% \section{Set Hlines and Vlines}
+%%% --------------------------------------------------------
+
+\tl_set:Nn \@tblr@dash { dash }
+\tl_set:Nn \@tblr@text { text }
+
+\regex_const:Nn \c__tblr_is_color_key_regex { ^[A-Za-z] }
+
+%% \SetHlines command for setting every hline in the table
+\NewTableCommand \SetHlines [3] [+]
+ {
+ \tblr_set_every_hline:nnn {#1} {#2} {#3}
+ }
+
+%% We put all code inside a group to avoid affecting other table commands
+\cs_new_protected:Npn \tblr_set_every_hline:nnn #1 #2 #3
+ {
+ \group_begin:
+ \int_step_inline:nn { \int_eval:n { \c@rowcount + 1 } }
+ {
+ \int_set:Nn \c@rownum {##1}
+ \tblr_set_hline:nnn {#1} {#2} {#3}
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_every_hline in different ways
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_every_hline_aux:n #1
+ {
+ \tl_if_head_is_group:nTF {#1}
+ {
+ \int_compare:nNnTF { \tl_count:n {#1} } = {3}
+ { \tblr_set_every_hline:nnn #1 }
+ { \tblr_set_every_hline:nnn {1} #1 }
+ }
+ { \tblr_set_every_hline:nnn {1} {-} {#1} }
+ }
+
+%% Add \SetHline, \hline and \cline commands
+
+\tl_new:N \l__tblr_hline_count_tl % the count of all hlines
+\tl_new:N \l__tblr_hline_num_tl % the index of the hline
+\tl_new:N \l__tblr_hline_cols_tl % the columns of the hline
+\tl_new:N \l__tblr_hline_dash_tl % dash style
+\tl_new:N \l__tblr_hline_fg_tl % dash foreground
+\tl_new:N \l__tblr_hline_wd_tl % dash width
+
+\NewTableCommand \cline [2] [] { \SetHline [=] {#2} {#1} }
+
+\NewTableCommand \hline [1] [] { \SetHline [+] {-} {#1} }
+
+%% #1: the index of the hline (may be + or =)
+%% #2: which columns of the hline, separate by commas
+%% #3: key=value pairs
+\NewTableCommand \SetHline [3] [+]
+ {
+ \tblr_set_hline:nnn {#1} {#2} {#3}
+ }
+
+%% We need to check "text" key first
+%% If it does exist and has empty value, then do nothing
+\cs_new_protected:Npn \tblr_set_hline:nnn #1 #2 #3
+ {
+ \group_begin:
+ \keys_set_groups:nnn { tblr-hline } { text } {#3}
+ \tl_if_eq:NnF \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text }
+ {
+ \__tblr_set_hline_num:n {#1}
+ \tl_clear:N \l__tblr_hline_dash_tl
+ \keys_set:nn { tblr-hline } { dash = solid, #3 }
+ \__tblr_set_hline_cmd:n {#2}
+ }
+ \group_end:
+ }
+
+\cs_new_protected:Npn \tblr_set_hline:nnnn #1 #2 #3 #4
+ {
+ \group_begin:
+ \__tblr_get_childs:nx {#1} { \int_eval:n { \c@rowcount + 1 } }
+ \clist_map_inline:Nn \l_tblr_childs_clist
+ {
+ \int_set:Nn \c@rownum {##1}
+ \tblr_set_hline:nnn {#2} {#3} {#4}
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_hline in different ways
+%% Note that #1 always includes an outer pair of braces
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_hline_aux:nn #1 #2
+ {
+ \tl_if_head_is_group:nTF {#2}
+ {
+ \int_compare:nNnTF { \tl_count:n {#2} } = {3}
+ { \tblr_set_hline:nnnn #1 #2 }
+ { \tblr_set_hline:nnnn #1 {1} #2 }
+ }
+ { \tblr_set_hline:nnnn #1 {1} {-} {#2} }
+ }
+\cs_generate_variant:Nn \__tblr_set_hline_aux:nn { Vn }
+
+%% #1: the index of hline to set (may be + or =)
+\cs_new_protected:Npn \__tblr_set_hline_num:n #1
+ {
+ \tl_clear:N \l__tblr_hline_num_tl
+ \tl_set:Nx \l__tblr_hline_count_tl
+ { \__tblr_prop_item:ne { hline } { [\int_use:N \c@rownum] / @hline-count } }
+ \tl_if_empty:NTF \l__tblr_hline_count_tl
+ {
+ \tl_set:Nx \l__tblr_hline_num_tl { 1 }
+ \__tblr_prop_gput:nxx { hline }
+ { [\int_use:N \c@rownum] / @hline-count } { 1 }
+ }
+ {
+ \tl_if_eq:nnTF {#1} {+}
+ { \__tblr_set_hline_num_incr: }
+ {
+ \tl_if_eq:nnTF {#1} {=}
+ { \tl_set_eq:NN \l__tblr_hline_num_tl \l__tblr_hline_count_tl }
+ {
+ \int_compare:nNnTF {#1} > { \l__tblr_hline_count_tl }
+ { \__tblr_set_hline_num_incr: }
+ { \tl_set:Nn \l__tblr_hline_num_tl {#1} }
+ }
+ }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_set_hline_num_incr:
+ {
+ \tl_set:Nx \l__tblr_hline_count_tl
+ { \int_eval:n { \l__tblr_hline_count_tl + 1 } }
+ \__tblr_prop_gput:nxx { hline }
+ { [\int_use:N \c@rownum] / @hline-count } { \l__tblr_hline_count_tl }
+ \tl_set_eq:NN \l__tblr_hline_num_tl \l__tblr_hline_count_tl
+ }
+
+\keys_define:nn { tblr-hline }
+ {
+ dash .code:n = \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@dash #1 },
+ text .code:n = \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text #1 },
+ text .groups:n = { text },
+ wd .code:n = \tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {#1} },
+ fg .code:n = \tl_set:Nn \l__tblr_hline_fg_tl {#1},
+ baseline .code:n = \__tblr_hline_set_baseline:n {#1},
+ unknown .code:n = \__tblr_hline_unknown_key:V \l_keys_key_str,
+ }
+
+\cs_new_protected:Npn \__tblr_hline_unknown_key:n #1
+ {
+ \prop_if_in:NnTF \g__tblr_defined_hdash_styles_prop {#1}
+ { \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@dash #1 } }
+ {
+ \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
+ { \tl_set:Nn \l__tblr_hline_fg_tl {#1} }
+ {
+ \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
+ \tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {\l__tblr_v_tl} }
+ }
+ }
+ }
+\cs_generate_variant:Nn \__tblr_hline_unknown_key:n { V }
+
+\cs_new_protected_nopar:Npn \__tblr_set_hline_cmd:n #1
+ {
+ \__tblr_get_childs:nx {#1} { \int_use:N \c@colcount }
+ \clist_map_inline:Nn \l_tblr_childs_clist
+ {
+ \__tblr_prop_gput:nxx { hline }
+ { [\int_use:N \c@rownum][##1](\l__tblr_hline_num_tl) / @dash }
+ { \l__tblr_hline_dash_tl }
+ \tl_if_empty:NF \l__tblr_hline_wd_tl
+ {
+ \__tblr_prop_gput:nxx { hline }
+ { [\int_use:N \c@rownum][##1](\l__tblr_hline_num_tl) / wd }
+ { \l__tblr_hline_wd_tl }
+ }
+ \tl_if_empty:NF \l__tblr_hline_fg_tl
+ {
+ \__tblr_prop_gput:nxx { hline }
+ { [\int_use:N \c@rownum][##1](\l__tblr_hline_num_tl) / fg }
+ { \l__tblr_hline_fg_tl }
+ }
+ }
+ }
+
+\NewTableCommand \firsthline [1] [] { \SetHline [+] {-} { #1, baseline=below } }
+\NewTableCommand \lasthline [1] [] { \SetHline [+] {-} { #1, baseline=above } }
+
+\cs_new_protected:Npn \__tblr_hline_set_baseline:n #1
+ {
+ \tl_if_eq:nnTF {#1} {above}
+ {
+ \__tblr_prop_gput:nnx { table }
+ { baseline } { \int_eval:n { \c@rownum - 1 } }
+ }
+ {
+ \tl_if_eq:nnT {#1} {below}
+ {
+ \__tblr_prop_gput:nnx { table } { baseline } { \int_use:N \c@rownum }
+ }
+ }
+ }
+
+%% \SetVlines command for setting every vline in the table
+\NewTableCommand \SetVlines [3] [+]
+ {
+ \tblr_set_every_vline:nnn {#1} {#2} {#3}
+ }
+
+%% We put all code inside a group to avoid affecting other table commands
+\cs_new_protected:Npn \tblr_set_every_vline:nnn #1 #2 #3
+ {
+ \group_begin:
+ \int_step_inline:nn { \int_eval:n { \c@colcount + 1 } }
+ {
+ \int_set:Nn \c@colnum {##1}
+ \tblr_set_vline:nnn {#1} {#2} {#3}
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_every_vline in different ways
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_every_vline_aux:n #1
+ {
+ \tl_if_head_is_group:nTF {#1}
+ {
+ \int_compare:nNnTF { \tl_count:n {#1} } = {3}
+ { \tblr_set_every_vline:nnn #1 }
+ { \tblr_set_every_vline:nnn {1} #1 }
+ }
+ { \tblr_set_every_vline:nnn {1} {-} {#1} }
+ }
+
+%% Add \SetVline, \vline and \rline commands
+
+\tl_new:N \l__tblr_vline_count_tl % the count of all vlines
+\tl_new:N \l__tblr_vline_num_tl % the index of the vline
+\tl_new:N \l__tblr_vline_rows_tl % the rows of the vline
+\tl_new:N \l__tblr_vline_dash_tl % dash style
+\tl_new:N \l__tblr_vline_fg_tl % dash foreground
+\tl_new:N \l__tblr_vline_wd_tl % dash width
+
+\NewTableCommand \rline [2] [] { \SetVline [=] {#2} {#1} }
+
+\NewTableCommand \vline [1] [] { \SetVline [+] {-} {#1} }
+
+%% #1: the index of the vline (may be + or =)
+%% #2: which rows of the vline, separate by commas
+%% #3: key=value pairs
+\NewTableCommand \SetVline [3] [+]
+ {
+ \tblr_set_vline:nnn {#1} {#2} {#3}
+ }
+
+%% We need to check "text" key first
+%% If it does exist and has empty value, then do nothing
+\cs_new_protected:Npn \tblr_set_vline:nnn #1 #2 #3
+ {
+ \group_begin:
+ \keys_set_groups:nnn { tblr-vline } { text } {#3}
+ \tl_if_eq:NnF \l__tblr_vline_dash_tl { \exp_not:N \@tblr@text }
+ {
+ \__tblr_set_vline_num:n {#1}
+ \tl_clear:N \l__tblr_vline_dash_tl
+ \keys_set:nn { tblr-vline } { dash = solid, #3 }
+ \__tblr_set_vline_cmd:n {#2}
+ }
+ \group_end:
+ }
+
+\cs_new_protected:Npn \tblr_set_vline:nnnn #1 #2 #3 #4
+ {
+ \group_begin:
+ \__tblr_get_childs:nx {#1} { \int_eval:n { \c@colcount + 1} }
+ \clist_map_inline:Nn \l_tblr_childs_clist
+ {
+ \int_set:Nn \c@colnum {##1}
+ \tblr_set_vline:nnn {#2} {#3} {#4}
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_vline in different ways
+%% Note that #1 always includes an outer pair of braces
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_vline_aux:nn #1 #2
+ {
+ \tl_if_head_is_group:nTF {#2}
+ {
+ \int_compare:nNnTF { \tl_count:n {#2} } = {3}
+ { \tblr_set_vline:nnnn #1 #2 }
+ { \tblr_set_vline:nnnn #1 {1} #2 }
+ }
+ { \tblr_set_vline:nnnn #1 {1} {-} {#2} }
+ }
+\cs_generate_variant:Nn \__tblr_set_vline_aux:nn { Vn }
+
+%% #1: the index of vline to set (may be + or =)
+\cs_new_protected:Npn \__tblr_set_vline_num:n #1
+ {
+ \tl_clear:N \l__tblr_vline_num_tl
+ \tl_set:Nx \l__tblr_vline_count_tl
+ { \__tblr_prop_item:ne { vline } { [\int_use:N \c@colnum] / @vline-count } }
+ \tl_if_empty:NTF \l__tblr_vline_count_tl
+ {
+ \tl_set:Nx \l__tblr_vline_num_tl { 1 }
+ \__tblr_prop_gput:nxx { vline }
+ { [\int_use:N \c@colnum] / @vline-count } { 1 }
+ }
+ {
+ \tl_if_eq:nnTF {#1} {+}
+ { \__tblr_set_vline_num_incr: }
+ {
+ \tl_if_eq:nnTF {#1} {=}
+ { \tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl }
+ {
+ \int_compare:nNnTF {#1} > { \l__tblr_vline_count_tl }
+ { \__tblr_set_vline_num_incr: }
+ { \tl_set:Nn \l__tblr_vline_num_tl {#1} }
+ }
+ }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_set_vline_num_incr:
+ {
+ \tl_set:Nx \l__tblr_vline_count_tl
+ { \int_eval:n { \l__tblr_vline_count_tl + 1 } }
+ \__tblr_prop_gput:nxx { vline }
+ { [\int_use:N \c@colnum] / @vline-count } { \l__tblr_vline_count_tl }
+ \tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl
+ }
+
+\keys_define:nn { tblr-vline }
+ {
+ dash .code:n = \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@dash #1 },
+ text .code:n = \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@text #1 },
+ text .groups:n = { text },
+ wd .code:n = \tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {#1} },
+ fg .code:n = \tl_set:Nn \l__tblr_vline_fg_tl {#1},
+ unknown .code:n = \__tblr_vline_unknown_key:V \l_keys_key_str,
+ }
+
+\cs_new_protected:Npn \__tblr_vline_unknown_key:n #1
+ {
+ \prop_if_in:NnTF \g__tblr_defined_vdash_styles_prop {#1}
+ { \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@dash #1 } }
+ {
+ \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
+ { \tl_set:Nn \l__tblr_vline_fg_tl {#1} }
+ {
+ \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
+ \tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {\l__tblr_v_tl} }
+ }
+ }
+ }
+\cs_generate_variant:Nn \__tblr_vline_unknown_key:n { V }
+
+\cs_new_protected_nopar:Npn \__tblr_set_vline_cmd:n #1
+ {
+ \__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
+ \clist_map_inline:Nn \l_tblr_childs_clist
+ {
+ \__tblr_prop_gput:nxx { vline }
+ { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / @dash }
+ { \l__tblr_vline_dash_tl }
+ \tl_if_empty:NF \l__tblr_vline_wd_tl
+ {
+ \__tblr_prop_gput:nxx { vline }
+ { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / wd }
+ { \l__tblr_vline_wd_tl }
+ }
+ \tl_if_empty:NF \l__tblr_vline_fg_tl
+ {
+ \__tblr_prop_gput:nxx { vline }
+ { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / fg }
+ { \l__tblr_vline_fg_tl }
+ }
+ }
+ }
+
+%%% --------------------------------------------------------
+%% \section{Set Cells}
+%%% --------------------------------------------------------
+
+%% \SetCells command for setting every cell in the table
+\NewTableCommand \SetCells [2] []
+ {
+ \tblr_set_every_cell:nn {#1} {#2}
+ }
+
+%% We put all code inside a group to avoid affecting other table commands
+\cs_new_protected:Npn \tblr_set_every_cell:nn #1 #2
+ {
+ \group_begin:
+ \int_step_inline:nn { \c@rowcount }
+ {
+ \int_set:Nn \c@rownum {##1}
+ \int_step_inline:nn { \c@colcount }
+ {
+ \int_set:Nn \c@colnum {####1}
+ \tblr_set_cell:nn {#1} {#2}
+ }
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_every_cell in different ways
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_every_cell_aux:n #1
+ {
+ \tl_if_head_is_group:nTF {#1}
+ { \tblr_set_every_cell:nn #1 }
+ { \tblr_set_every_cell:nn {} {#1} }
+ }
+
+%% \SetCell command for multirow and/or multicolumn cells
+
+\NewTableCommand \SetCell [2] []
+ {
+ \tblr_set_cell:nn { #1 } { #2 }
+ }
+
+\tl_new:N \l__tblr_row_span_num_tl
+\tl_new:N \l__tblr_col_span_num_tl
+
+\cs_new_protected:Npn \tblr_set_cell:nn #1 #2
+ {
+ \tl_set:Nn \l__tblr_row_span_num_tl { 1 }
+ \tl_set:Nn \l__tblr_col_span_num_tl { 1 }
+ \keys_set:nn { tblr-cell-span } { #1 }
+ \keys_set:nn { tblr-cell-spec } { #2 }
+ \__tblr_set_span_spec:VV \l__tblr_row_span_num_tl \l__tblr_col_span_num_tl
+ }
+\cs_generate_variant:Nn \tblr_set_cell:nn { nV }
+
+\cs_new_protected:Npn \tblr_set_cell:nnnn #1 #2 #3 #4
+ {
+ \group_begin:
+ \__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
+ \clist_set_eq:NN \l_tmpa_clist \l_tblr_childs_clist
+ \__tblr_get_childs:nx {#2} { \int_use:N \c@colcount }
+ \clist_set_eq:NN \l_tmpb_clist \l_tblr_childs_clist
+ \clist_map_inline:Nn \l_tmpa_clist
+ {
+ \int_set:Nn \c@rownum {##1}
+ \clist_map_inline:Nn \l_tmpb_clist
+ {
+ \int_set:Nn \c@colnum {####1}
+ \tblr_set_cell:nn {#3} {#4}
+ }
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_cell in different ways
+%% Note that #1 is always of the type {<i>}{<j>}
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_cell_aux:nn #1 #2
+ {
+ \tl_if_head_is_group:nTF {#2}
+ { \tblr_set_cell:nnnn #1 #2 }
+ { \tblr_set_cell:nnnn #1 {} {#2} }
+ }
+\cs_generate_variant:Nn \__tblr_set_cell_aux:nn { Vn }
+
+\keys_define:nn { tblr-cell-span }
+ {
+ r .tl_set:N = \l__tblr_row_span_num_tl,
+ c .tl_set:N = \l__tblr_col_span_num_tl,
+ }
+
+\keys_define:nn { tblr-cell-spec }
+ {
+ l .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / halign} {l},
+ c .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / halign} {c},
+ r .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / halign} {r},
+ t .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / valign} {t},
+ p .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / valign} {t},
+ m .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / valign} {m},
+ b .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / valign} {b},
+ h .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / valign} {h},
+ f .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / valign} {f},
+ wd .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / width} {#1},
+ bg .code:n = \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / background} {#1},
+ unknown .code:n = \__tblr_cell_unknown_key:V \l_keys_key_str,
+ }
+
+\cs_new_protected:Npn \__tblr_cell_unknown_key:n #1
+ {
+ \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
+ {
+ \__tblr_prop_gput:nxx {cell}
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum] / background} {#1}
+ }
+ {
+ \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
+ \__tblr_prop_gput:nxx {cell}
+ { [\int_use:N \c@rownum][\int_use:N \c@colnum] / width }
+ { \dim_eval:n { \l__tblr_v_tl } }
+ }
+ }
+\cs_generate_variant:Nn \__tblr_cell_unknown_key:n { V }
+
+\cs_new_protected:Npn \__tblr_set_span_spec:nn #1 #2
+ {
+ \int_compare:nNnT { #1 } > { 1 }
+ {
+ \__tblr_prop_gput:nnn {table} {rowspan} {true}
+ \__tblr_prop_gput:nxn {cell}
+ { [\int_use:N \c@rownum][\int_use:N \c@colnum] / rowspan } { #1 }
+ }
+ \int_compare:nNnT { #2 } > { 1 }
+ {
+ \__tblr_prop_gput:nnn {table} {colspan} {true}
+ \__tblr_prop_gput:nxn {cell}
+ { [\int_use:N \c@rownum][\int_use:N \c@colnum] / colspan } { #2 }
+ }
+ \int_step_variable:nnNn
+ { \int_use:N \c@rownum } { \int_eval:n { \c@rownum + #1 - 1 } } \l__tblr_i_tl
+ {
+ \int_step_variable:nnNn
+ { \int_use:N \c@colnum } { \int_eval:n { \c@colnum + #2 - 1 } }
+ \l__tblr_j_tl
+ {
+ \bool_lazy_and:nnF
+ { \int_compare_p:nNn { \l__tblr_i_tl } = { \c@rownum } }
+ { \int_compare_p:nNn { \l__tblr_j_tl } = { \c@colnum } }
+ {
+ \__tblr_prop_gput:nxx {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
+ }
+ \int_compare:nNnF { \l__tblr_i_tl } = { \c@rownum }
+ {
+ \__tblr_prop_gput:nxx {hline}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
+ }
+ \int_compare:nNnF { \l__tblr_j_tl } = { \c@colnum }
+ {
+ \__tblr_prop_gput:nxx {vline}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
+ }
+ }
+ }
+ }
+\cs_generate_variant:Nn \__tblr_set_span_spec:nn { VV }
+
+%% Legacy \multicolumn and \multirow commands
+%% Both of them could be replaced with \SetCell command
+%% Note that they don't have cell text as the last arguments
+
+%% If \multicolumn is followed by \multirow,
+%% We need to call \tblr_set_cell together
+%% in order to omit all hlines inside the span cell.
+\tl_new:N \g__tblr_multicolumn_num_tl
+\tl_new:N \g__tblr_multicolumn_spec_tl
+
+%% There maybe p{2em} inside #2 of \multicolumn command
+\NewTableCommand \multicolumn [2]
+ {
+ \tl_gclear:N \g__tblr_multicolumn_num_tl
+ \tl_gclear:N \g__tblr_multicolumn_spec_tl
+ \tl_map_inline:nn {#2}
+ {
+ \bool_lazy_and:nnF
+ { \tl_if_single_token_p:n {##1} }
+ { \token_if_eq_charcode_p:NN ##1 | }
+ { \tl_put_right:Nn \g__tblr_multicolumn_spec_tl {,##1} }
+ }
+ \peek_meaning:NTF \multirow
+ { \tl_gset:Nn \g__tblr_multicolumn_num_tl {#1} }
+ { \tblr_set_cell:nV { c = #1 } \g__tblr_multicolumn_spec_tl }
+ }
+
+\NewTableCommand \multirow [3] [m]
+ {
+ \tl_if_eq:nnTF {#1} {c}
+ { \tl_set:Nn \l_tmpa_tl {, m} }
+ {
+ \tl_if_eq:nnTF {#1} {t}
+ { \tl_set:Nn \l_tmpa_tl {, h} }
+ { \tl_if_eq:nnTF {#1} {b}
+ { \tl_set:Nn \l_tmpa_tl {, f} }
+ { \tl_set:Nn \l_tmpa_tl {, #1} }
+ }
+ }
+ \tl_if_eq:nnF {#3} {*}
+ { \tl_if_eq:nnF {#3} {=} { \tl_put_right:Nn \l_tmpa_tl {, wd=#3} } }
+ \tl_if_empty:NTF \g__tblr_multicolumn_num_tl
+ { \tblr_set_cell:nV { r = #2 } \l_tmpa_tl }
+ {
+ \tl_put_left:NV \l_tmpa_tl \g__tblr_multicolumn_spec_tl
+ \exp_args:Nx \tblr_set_cell:nV
+ { c = \g__tblr_multicolumn_num_tl, r = #2 } \l_tmpa_tl
+ \tl_gclear:N \g__tblr_multicolumn_num_tl
+ }
+ }
+
+%%% --------------------------------------------------------
+%% \section{Set Columns and Rows}
+%%% --------------------------------------------------------
+
+%% \SetColumns command for setting every column in the table
+\NewTableCommand \SetColumns [2] []
+ {
+ \tblr_set_every_column:nn {#1} {#2}
+ }
+
+%% We put all code inside a group to avoid affecting other table commands
+\cs_new_protected:Npn \tblr_set_every_column:nn #1 #2
+ {
+ \group_begin:
+ \int_step_inline:nn { \c@colcount }
+ {
+ \int_set:Nn \c@colnum {##1}
+ \tblr_set_column:nn {#1} {#2}
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_every_column in different ways
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_every_column_aux:n #1
+ {
+ \tl_if_head_is_group:nTF {#1}
+ { \tblr_set_every_column:nn #1 }
+ { \tblr_set_every_column:nn {} {#1} }
+ }
+
+%% \SetColumn command for current column or each cells in the column
+
+\NewTableCommand \SetColumn [2] []
+ {
+ \tblr_set_column:nn {#1} {#2}
+ }
+
+\cs_new_protected:Npn \tblr_set_column:nn #1 #2
+ {
+ \keys_set:nn { tblr-column } {#2}
+ }
+
+\cs_new_protected:Npn \tblr_set_column:nnn #1 #2 #3
+ {
+ \group_begin:
+ \__tblr_get_childs:nx {#1} { \int_use:N \c@colcount }
+ \clist_map_inline:Nn \l_tblr_childs_clist
+ {
+ \int_set:Nn \c@colnum {##1}
+ \tblr_set_column:nn {#2} {#3}
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_column in different ways
+%% Note that #1 always includes an outer pair of braces
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_column_aux:nn #1 #2
+ {
+ \tl_if_head_is_group:nTF {#2}
+ { \tblr_set_column:nnn #1 #2 }
+ { \tblr_set_column:nnn #1 {} {#2} }
+ }
+\cs_generate_variant:Nn \__tblr_set_column_aux:nn { Vn }
+
+\keys_define:nn { tblr-column }
+ {
+ l .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { halign } {l},
+ c .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { halign } {c},
+ r .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { halign } {r},
+ t .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { valign } {t},
+ p .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { valign } {t},
+ m .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { valign } {m},
+ b .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { valign } {b},
+ h .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { valign } {h},
+ f .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { valign } {f},
+ bg .code:n = \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { background } {#1},
+ wd .code:n = \__tblr_prop_gput:nxx { column }
+ { [\int_use:N \c@colnum] / width } { \dim_eval:n {#1} },
+ co .code:n = \__tblr_prop_gput:nxx { column }
+ { [\int_use:N \c@colnum] / coefficient } {#1},
+ leftsep .code:n = \__tblr_prop_gput:nxx { column }
+ { [\int_use:N \c@colnum] / leftsep } { \dim_eval:n {#1} },
+ rightsep .code:n = \__tblr_prop_gput:nxx { column }
+ { [\int_use:N \c@colnum] / rightsep } { \dim_eval:n {#1} },
+ colsep .meta:n = { leftsep = #1, rightsep = #1},
+ leftsep+ .code:n = \__tblr_prop_gadd_dimen_value:nxx { column }
+ { [\int_use:N \c@colnum] / leftsep } { \dim_eval:n {#1} },
+ rightsep+ .code:n = \__tblr_prop_gadd_dimen_value:nxx { column }
+ { [\int_use:N \c@colnum] / rightsep } { \dim_eval:n {#1} },
+ colsep+ .meta:n = { leftsep+ = #1, rightsep+ = #1},
+ unknown .code:n = \__tblr_column_unknown_key:V \l_keys_key_str,
+ }
+
+%% #1: column number; #2: key; #3: value
+\cs_new_protected:Npn \__tblr_set_key_for_every_column_cell:nnn #1 #2 #3
+ {
+ \int_step_inline:nn { \c@rowcount }
+ {
+ \__tblr_prop_gput:nxn {cell} { [##1][#1] / #2 } {#3}
+ }
+ }
+
+\regex_const:Nn \c__tblr_is_number_key_regex { ^[\+\-]? (\d+|\d*\.\d+)$ }
+
+\cs_new_protected:Npn \__tblr_column_unknown_key:n #1
+ {
+ \regex_match:NnTF \c__tblr_is_number_key_regex {#1}
+ {
+ \__tblr_prop_gput:nxx { column }
+ { [\int_use:N \c@colnum] / coefficient } {#1}
+ }
+ {
+ \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
+ {
+ \__tblr_set_key_for_every_column_cell:nnn
+ { \int_use:N \c@colnum } { background } {#1}
+ }
+ {
+ \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
+ \__tblr_prop_gput:nxx { column }
+ { [\int_use:N \c@colnum] / width } { \dim_eval:n { \l__tblr_v_tl } }
+ }
+ }
+ }
+\cs_generate_variant:Nn \__tblr_column_unknown_key:n { V }
+
+%% \SetRows command for setting every row in the table
+\NewTableCommand \SetRows [2] []
+ {
+ \tblr_set_every_row:nn {#1} {#2}
+ }
+
+%% We put all code inside a group to avoid affecting other table commands
+\cs_new_protected:Npn \tblr_set_every_row:nn #1 #2
+ {
+ \group_begin:
+ \int_step_inline:nn { \c@rowcount }
+ {
+ \int_set:Nn \c@rownum {##1}
+ \tblr_set_row:nn {#1} {#2}
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_every_row in different ways
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_every_row_aux:n #1
+ {
+ \tl_if_head_is_group:nTF {#1}
+ { \tblr_set_every_row:nn #1 }
+ { \tblr_set_every_row:nn {} {#1} }
+ }
+
+%% \SetRow command for current row or each cells in the row
+
+\NewTableCommand \SetRow [2] []
+ {
+ \tblr_set_row:nn {#1} {#2}
+ }
+
+\cs_new_protected:Npn \tblr_set_row:nn #1 #2
+ {
+ \keys_set:nn { tblr-row } {#2}
+ }
+
+\cs_new_protected:Npn \tblr_set_row:nnn #1 #2 #3
+ {
+ \group_begin:
+ \__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
+ \clist_map_inline:Nn \l_tblr_childs_clist
+ {
+ \int_set:Nn \c@rownum {##1}
+ \tblr_set_row:nn {#2} {#3}
+ }
+ \group_end:
+ }
+
+%% Check the number of arguments and call \tblr_set_row in different ways
+%% Note that #1 always includes an outer pair of braces
+%% This function is called when parsing table specifications
+\cs_new_protected:Npn \__tblr_set_row_aux:nn #1 #2
+ {
+ \tl_if_head_is_group:nTF {#2}
+ { \tblr_set_row:nnn #1 #2 }
+ { \tblr_set_row:nnn #1 {} {#2} }
+ }
+\cs_generate_variant:Nn \__tblr_set_row_aux:nn { Vn }
+
+\keys_define:nn { tblr-row }
+ {
+ l .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { halign } {l},
+ c .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { halign } {c},
+ r .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { halign } {r},
+ t .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { valign } {t},
+ p .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { valign } {t},
+ m .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { valign } {m},
+ b .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { valign } {b},
+ h .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { valign } {h},
+ f .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { valign } {f},
+ bg .code:n = \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { background } {#1},
+ ht .code:n = \__tblr_prop_gput:nxx { row }
+ { [\int_use:N \c@rownum] / height } { \dim_eval:n {#1} },
+ co .code:n = \__tblr_prop_gput:nxx { row }
+ { [\int_use:N \c@rownum] / coefficient } {#1},
+ abovesep .code:n = \__tblr_prop_gput:nxx { row }
+ { [\int_use:N \c@rownum] / abovesep } { \dim_eval:n {#1} },
+ belowsep .code:n = \__tblr_prop_gput:nxx { row }
+ { [\int_use:N \c@rownum] / belowsep } { \dim_eval:n {#1} },
+ rowsep .meta:n = { abovesep = #1, belowsep = #1},
+ abovesep+ .code:n = \__tblr_prop_gadd_dimen_value:nxx { row }
+ { [\int_use:N \c@rownum] / abovesep } { \dim_eval:n {#1} },
+ belowsep+ .code:n = \__tblr_prop_gadd_dimen_value:nxx { row }
+ { [\int_use:N \c@rownum] / belowsep } { \dim_eval:n {#1} },
+ rowsep+ .meta:n = { abovesep+ = #1, belowsep+ = #1},
+ nobreak .code:n = \__tblr_prop_gput:nxx { row }
+ { [\int_eval:n {\c@rownum - 1}] / nobreak } { true },
+ unknown .code:n = \__tblr_row_unknown_key:V \l_keys_key_str,
+ }
+
+%% #1: row number; #2: key; #3: value
+\cs_new_protected:Npn \__tblr_set_key_for_every_row_cell:nnn #1 #2 #3
+ {
+ \int_step_inline:nn { \c@colcount }
+ {
+ \__tblr_prop_gput:nxn {cell} { [#1][##1] / #2 } {#3}
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_row_unknown_key:n #1
+ {
+ \regex_match:NnTF \c__tblr_is_number_key_regex {#1}
+ {
+ \__tblr_prop_gput:nxx { row }
+ { [\int_use:N \c@rownum] / coefficient } {#1}
+ }
+ {
+ \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
+ {
+ \__tblr_set_key_for_every_row_cell:nnn
+ { \int_use:N \c@rownum } { background } {#1}
+ }
+ {
+ \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
+ \__tblr_prop_gput:nxx { row }
+ { [\int_use:N \c@rownum] / height } { \dim_eval:n { \l__tblr_v_tl } }
+ }
+ }
+ }
+\cs_generate_variant:Nn \__tblr_row_unknown_key:n { V }
+
+%%% --------------------------------------------------------
+%% \section{Column Types and Row Types}
+%%% --------------------------------------------------------
+
+%% Some primitive column/row types
+
+\str_const:Nn \c_tblr_primitive_colrow_types_str { Q | < > }
+\tl_new:N \g__tblr_expanded_colrow_spec_tl
+
+\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ Q } { O{} }
+ {
+ \keys_set:nn { tblr-column } { #1 }
+ \int_incr:N \c@colnum
+ \__tblr_execute_colrow_spec_next:N
+ }
+\exp_args:Nc \NewDocumentCommand { tblr_column_type_ Q } { O{} }
+ {
+ \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { Q[#1] }
+ \__tblr_expand_colrow_spec_next:N
+ }
+
+\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ Q } { O{} }
+ {
+ \keys_set:nn { tblr-row } { #1 }
+ \int_incr:N \c@rownum
+ \__tblr_execute_colrow_spec_next:N
+ }
+\exp_args:Nc \NewDocumentCommand { tblr_row_type_ Q } { O{} }
+ {
+ \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { Q[#1] }
+ \__tblr_expand_colrow_spec_next:N
+ }
+
+\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ | } { O{} }
+ {
+ \vline [#1]
+ \__tblr_execute_colrow_spec_next:N
+ }
+\exp_args:Nc \NewDocumentCommand { tblr_column_type_ | } { O{} }
+ {
+ \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { |[#1] }
+ \__tblr_expand_colrow_spec_next:N
+ }
+
+\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ | } { O{} }
+ {
+ \hline [#1]
+ \__tblr_execute_colrow_spec_next:N
+ }
+\exp_args:Nc \NewDocumentCommand { tblr_row_type_ | } { O{} }
+ {
+ \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { |[#1] }
+ \__tblr_expand_colrow_spec_next:N
+ }
+
+\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ > } { O{} m }
+ {
+ \tl_if_blank:nF { #1 }
+ {
+ \__tblr_prop_gput:nxx
+ { column }
+ { [\int_use:N \c@colnum] / leftsep}
+ { \dim_eval:n { #1 } }
+ }
+ \tl_if_blank:nF { #2 }
+ {
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \tl_set:Nx \l_tmpa_tl
+ {
+ \__tblr_prop_item:ne {text}
+ { [\l__tblr_i_tl][\int_use:N \c@colnum] }
+ }
+ \tl_put_left:Nn \l_tmpa_tl { #2 }
+ \__tblr_prop_gput:nxV {text}
+ { [\l__tblr_i_tl][\int_use:N \c@colnum] } \l_tmpa_tl
+ }
+ }
+ \__tblr_execute_colrow_spec_next:N
+ }
+\exp_args:Nc \NewDocumentCommand { tblr_column_type_ > } { O{} m }
+ {
+ \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { >[#1]{#2} }
+ \__tblr_expand_colrow_spec_next:N
+ }
+
+\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ > } { O{} m }
+ {
+ \tl_if_blank:nF { #1 }
+ {
+ \__tblr_prop_gput:nxx
+ { row }
+ { [\int_use:N \c@rownum] / abovesep }
+ { \dim_eval:n { #1 } }
+ }
+ \tl_if_blank:nF { #2 }
+ {
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \tl_set:Nx \l_tmpa_tl
+ {
+ \__tblr_prop_item:ne {text}
+ { [\int_use:N \c@rownum][\l__tblr_j_tl] }
+ }
+ \tl_put_left:Nn \l_tmpa_tl { #2 }
+ \__tblr_prop_gput:nxV {text}
+ { [\int_use:N \c@rownum][\l__tblr_j_tl] } \l_tmpa_tl
+ }
+ }
+ \__tblr_execute_colrow_spec_next:N
+ }
+\exp_args:Nc \NewDocumentCommand { tblr_row_type_ > } { O{} m }
+ {
+ \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { >[#1]{#2} }
+ \__tblr_expand_colrow_spec_next:N
+ }
+
+\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ < } { O{} m }
+ {
+ \tl_if_blank:nF { #1 }
+ {
+ \__tblr_prop_gput:nxx
+ { column }
+ { [\int_eval:n {\c@colnum - 1}] / rightsep }
+ { \dim_eval:n { #1 } }
+ }
+ \tl_if_blank:nF { #2 }
+ {
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \tl_set:Nx \l_tmpa_tl
+ {
+ \__tblr_prop_item:ne {text}
+ { [\l__tblr_i_tl][\int_eval:n {\c@colnum - 1}] }
+ }
+ \tl_put_right:Nn \l_tmpa_tl { #2 }
+ \__tblr_prop_gput:nxV {text}
+ { [\l__tblr_i_tl][\int_eval:n {\c@colnum - 1}] } \l_tmpa_tl
+ }
+ }
+ \__tblr_execute_colrow_spec_next:N
+ }
+\exp_args:Nc \NewDocumentCommand { tblr_column_type_ < } { O{} m }
+ {
+ \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { <[#1]{#2} }
+ \__tblr_expand_colrow_spec_next:N
+ }
+
+\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ < } { O{} m }
+ {
+ \tl_if_blank:nF { #1 }
+ {
+ \__tblr_prop_gput:nxx
+ { row }
+ { [\int_eval:n {\c@rownum - 1}] / belowsep }
+ { \dim_eval:n { #1 } }
+ }
+ \tl_if_blank:nF { #2 }
+ {
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \tl_set:Nx \l_tmpa_tl
+ {
+ \__tblr_prop_item:ne {text}
+ { [\int_eval:n {\c@rownum - 1}][\l__tblr_j_tl] }
+ }
+ \tl_put_right:Nn \l_tmpa_tl { #2 }
+ \__tblr_prop_gput:nxV {text}
+ { [\int_eval:n {\c@rownum - 1}][\l__tblr_j_tl] } \l_tmpa_tl
+ }
+ }
+ \__tblr_execute_colrow_spec_next:N
+ }
+\exp_args:Nc \NewDocumentCommand { tblr_row_type_ < } { O{} m }
+ {
+ \tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { <[#1]{#2} }
+ \__tblr_expand_colrow_spec_next:N
+ }
+
+%% \NewColumnType/\NewRowType command and predefined column/row types
+
+\str_new:N \g_tblr_used_column_types_str
+\str_gset_eq:NN \g_tblr_used_column_types_str \c_tblr_primitive_colrow_types_str
+
+\str_new:N \g_tblr_used_row_types_str
+\str_gset_eq:NN \g_tblr_used_row_types_str \c_tblr_primitive_colrow_types_str
+
+\bool_new:N \g__tblr_colrow_spec_expand_stop_bool
+\tl_new:N \g__tblr_column_or_row_tl
+
+\msg_new:nnn { tabularray } { used-colrow-type }
+ { #1 ~ type ~ name ~ #2 ~ has ~ been ~ used! }
+
+\NewDocumentCommand \NewColumnType { m O{0} o m }
+ {
+ \tl_set:Nn \g__tblr_column_or_row_tl { column }
+ \__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4}
+ }
+
+\NewDocumentCommand \NewRowType { m O{0} o m }
+ {
+ \tl_set:Nn \g__tblr_column_or_row_tl { row }
+ \__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4}
+ }
+
+\NewDocumentCommand \NewColumnRowType { m O{0} o m }
+ {
+ \tl_set:Nn \g__tblr_column_or_row_tl { column }
+ \__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4}
+ \tl_set:Nn \g__tblr_column_or_row_tl { row }
+ \__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4}
+ }
+
+\cs_new_protected:Npn \__tblr_new_column_or_row_type:nnnn #1 #2 #3 #4
+ {
+ \str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
+ {
+ \tl_if_eq:NnTF \g__tblr_column_or_row_tl { row }
+ { \msg_warning:nnnn { tabularray } { used-colrow-type } { Row } {#1} }
+ { \msg_warning:nnnn { tabularray } { used-colrow-type } { Column } {#1} }
+ \str_log:c { g_tblr_used_ \g__tblr_column_or_row_tl _types_str }
+ }
+ {
+ \__tblr_make_xparse_arg_spec:nnN {#2} {#3} \l__tblr_a_tl
+ \exp_args:NcV \NewDocumentCommand
+ { tblr_ \g__tblr_column_or_row_tl _type_ #1 } \l__tblr_a_tl
+ {
+ \bool_gset_false:N \g__tblr_colrow_spec_expand_stop_bool
+ \tl_gput_right:Nf \g__tblr_expanded_colrow_spec_tl {#4}
+ \__tblr_expand_colrow_spec_next:N
+ }
+ \str_gput_right:cn
+ { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
+ }
+ }
+
+\NewColumnRowType { l } { Q[l] }
+\NewColumnRowType { c } { Q[c] }
+\NewColumnRowType { r } { Q[r] }
+
+\NewColumnType { t } [1] { Q[t,wd=#1] }
+\NewColumnType { p } [1] { Q[p,wd=#1] }
+\NewColumnType { m } [1] { Q[m,wd=#1] }
+\NewColumnType { b } [1] { Q[b,wd=#1] }
+\NewColumnType { h } [1] { Q[h,wd=#1] }
+\NewColumnType { f } [1] { Q[f,wd=#1] }
+
+\NewRowType { t } [1] { Q[t,ht=#1] }
+\NewRowType { p } [1] { Q[p,ht=#1] }
+\NewRowType { m } [1] { Q[m,ht=#1] }
+\NewRowType { b } [1] { Q[b,ht=#1] }
+\NewRowType { h } [1] { Q[h,ht=#1] }
+\NewRowType { f } [1] { Q[f,ht=#1] }
+
+\NewColumnRowType { X } [1][] { Q[co=1,#1] }
+
+\NewColumnRowType { ! } [1] { |[text={#1}] }
+\NewColumnRowType { @ } [1] { <[0pt]{} |[text={#1}] >[0pt]{} }
+\NewColumnRowType { * } [2] { \prg_replicate:nn {#1} {#2} }
+
+\cs_new_protected:Npn \__tblr_parse_colrow_spec:nn #1 #2
+ {
+ \tl_gset:Nn \g__tblr_column_or_row_tl {#1}
+ \tl_gset:Nn \g__tblr_expanded_colrow_spec_tl {#2}
+ \__tblr_expand_colrow_spec:N \g__tblr_expanded_colrow_spec_tl
+ \__tblr_execute_colrow_spec:N \g__tblr_expanded_colrow_spec_tl
+ }
+
+%% Expand defined column/row types
+
+\cs_new_protected:Npn \__tblr_expand_colrow_spec:N #1
+ {
+ \bool_do_until:Nn \g__tblr_colrow_spec_expand_stop_bool
+ {
+ \LogTblrTracing { colspec, rowspec }
+ \bool_gset_true:N \g__tblr_colrow_spec_expand_stop_bool
+ \tl_set_eq:NN \l_tmpa_tl #1
+ \tl_gclear:N #1
+ \exp_last_unbraced:NV
+ \__tblr_expand_colrow_spec_next:N \l_tmpa_tl \scan_stop:
+ }
+ }
+
+\msg_new:nnn { tabularray } { unexpandable-colrow-type }
+ { Unexpandable ~ command ~ #2 inside ~ #1 ~ type! }
+
+\msg_new:nnn { tabularray } { unknown-colrow-type }
+ { Unknown ~ #1 ~ type ~ #2! }
+
+\cs_new_protected:Npn \__tblr_expand_colrow_spec_next:N #1
+ {
+ \token_if_eq_catcode:NNTF #1 \scan_stop:
+ {
+ \token_if_eq_meaning:NNF #1 \scan_stop:
+ {
+ \msg_error:nnVn { tabularray } { unexpandable-colrow-type }
+ \g__tblr_column_or_row_tl {#1}
+ }
+ }
+ {
+ \str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
+ { \cs:w tblr_ \g__tblr_column_or_row_tl _type_ #1 \cs_end: }
+ {
+ \msg_error:nnVn { tabularray } { unknown-colrow-type }
+ \g__tblr_column_or_row_tl {#1}
+ \str_log:c { g_tblr_used_ \g__tblr_column_or_row_tl _types_str }
+ }
+ }
+ }
+
+%% Execute primitive column/row types
+
+\cs_new_protected:Npn \__tblr_execute_colrow_spec:N #1
+ {
+ \tl_if_eq:NnTF \g__tblr_column_or_row_tl { row }
+ { \int_set:Nn \c@rownum {1} }
+ { \int_set:Nn \c@colnum {1} }
+ \exp_last_unbraced:NV \__tblr_execute_colrow_spec_next:N #1 \scan_stop:
+ }
+
+\cs_new_protected:Npn \__tblr_execute_colrow_spec_next:N #1
+ {
+ \token_if_eq_meaning:NNF #1 \scan_stop:
+ { \cs:w tblr_primitive_ \g__tblr_column_or_row_tl _type_ #1 \cs_end: }
+ }
+
+%%% --------------------------------------------------------
+%% \section{Tabularray Environments}
+%%% --------------------------------------------------------
+
+\tl_new:N \l__tblr_env_name_tl
+\bool_new:N \l__tblr_math_mode_bool
+
+\NewDocumentEnvironment { tblr } { O{c} m +b }
+ {
+ \tl_set:Nn \l__tblr_env_name_tl { tblr }
+ \mode_if_math:TF
+ { \bool_set_true:N \l__tblr_math_mode_bool }
+ { \bool_set_false:N \l__tblr_math_mode_bool }
+ \buildtblr {#1} {#2} {#3}
+ } { }
+
+%% Read, split and build the table
+
+\cs_new_protected:Npn \buildtblr #1 #2 #3
+ {
+ \mode_leave_vertical:
+ \int_gincr:N \g_tblr_level_int
+ \__tblr_clear_prop_lists:
+ \__tblr_enable_table_commands:
+ \__tblr_split_table:n { #3 }
+ \LogTblrTracing { command }
+ \__tblr_initial_table_spec:
+ \LogTblrTracing { table }
+ \__tblr_parse_table_spec:n { #2 }
+ \__tblr_execute_table_commands:
+ \__tblr_disable_table_commands:
+ \__tblr_calc_cell_and_line_sizes:
+ \__tblr_build_whole:n { #1 }
+ \int_gdecr:N \g_tblr_level_int
+ }
+
+\cs_new_protected:Npn \__tblr_clear_prop_lists:
+ {
+ \prop_gclear_new:c { g_tblr_text_ \int_use:N \g_tblr_level_int _prop }
+ \prop_gclear_new:c { g_tblr_command_ \int_use:N \g_tblr_level_int _prop }
+ \prop_gclear_new:c { g_tblr_table_ \int_use:N \g_tblr_level_int _prop }
+ \prop_gclear_new:c { g_tblr_row_ \int_use:N \g_tblr_level_int _prop }
+ \prop_gclear_new:c { g_tblr_column_ \int_use:N \g_tblr_level_int _prop }
+ \prop_gclear_new:c { g_tblr_cell_ \int_use:N \g_tblr_level_int _prop }
+ \prop_gclear_new:c { g_tblr_hline_ \int_use:N \g_tblr_level_int _prop }
+ \prop_gclear_new:c { g_tblr_vline_ \int_use:N \g_tblr_level_int _prop }
+ }
+
+%% Insert and remove braces for nesting environments inside cells
+%% These make line split and cell split workable
+%% We need to replace N times for N level nestings
+\regex_const:Nn \c__tblr_insert_braces_regex
+ {
+ \c{begin} \cB\{ (\c[^BE].*) \cE\} (.*?) \c{end} \cB\{ (\c[^BE].*) \cE\}
+ }
+\tl_const:Nn \c__tblr_insert_braces_tl
+ {
+ \c{begin} \cB\{ \cB\{ \1 \cE\} \2 \c{end} \cE\} \cB\{ \3 \cE\}
+ }
+\regex_const:Nn \c__tblr_remove_braces_regex
+ {
+ \c{begin} \cB\{ \cB\{ (.*?) \c{end} \cE\}
+ }
+\tl_const:Nn \c__tblr_remove_braces_tl
+ {
+ \c{begin} \cB\{ \1 \c{end}
+ }
+\cs_new_protected:Npn \__tblr_insert_braces:N #1
+ {
+ \regex_replace_all:NVN \c__tblr_insert_braces_regex \c__tblr_insert_braces_tl #1
+ \regex_replace_all:NVN \c__tblr_insert_braces_regex \c__tblr_insert_braces_tl #1
+ }
+\cs_new_protected:Npn \__tblr_remove_braces:N #1
+ {
+ \regex_replace_all:NVN \c__tblr_remove_braces_regex \c__tblr_remove_braces_tl #1
+ \regex_replace_all:NVN \c__tblr_remove_braces_regex \c__tblr_remove_braces_tl #1
+ }
+
+%% Split table content to cells and store them
+%% #1: table content
+
+\seq_new:N \l_tblr_lines_seq
+
+\cs_new_protected:Npn \__tblr_split_table:n #1
+ {
+ \int_zero:N \c@rowcount
+ \int_zero:N \c@colcount
+ \__tblr_split_table_to_lines:nN { #1 } \l_tblr_lines_seq
+ \__tblr_split_lines_to_cells:N \l_tblr_lines_seq
+ }
+
+%% Split table content to a sequence of lines
+%% #1: table content, #2: resulting sequence of lines
+\cs_new_protected:Npn \__tblr_split_table_to_lines:nN #1 #2
+ {
+ \tl_set:Nn \l_tmpa_tl { #1 }
+ \__tblr_insert_braces:N \l_tmpa_tl
+ \seq_set_split:NnV \l_tmpa_seq { \\ } \l_tmpa_tl
+ \seq_clear:N #2
+ \seq_map_inline:Nn \l_tmpa_seq
+ {
+ \tl_if_head_eq_meaning:nNTF {##1} *
+ {
+ \tl_set:Nn \l__tblr_b_tl { \SetRow{nobreak} }
+ \tl_set:Nx \l__tblr_c_tl { \tl_tail:n {##1} }
+ \tl_trim_spaces:N \l__tblr_c_tl %% Ignore spaces between * and [dimen]
+ \tl_log:N \l__tblr_c_tl
+ \tl_if_head_eq_meaning:VNT \l__tblr_c_tl [
+ {
+ \tl_put_right:Nn \l__tblr_b_tl { \RowBefore@AddBelowSep }
+ }
+ \tl_put_right:NV \l__tblr_b_tl \l__tblr_c_tl
+ \seq_put_right:NV #2 \l__tblr_b_tl
+ }
+ {
+ \tl_if_head_eq_meaning:nNTF { ##1 } [
+ { \seq_put_right:Nn #2 { \RowBefore@AddBelowSep ##1 } }
+ { \seq_put_right:Nn #2 { ##1 } }
+ }
+ }
+ \int_set:Nn \c@rowcount { \seq_count:N #2 }
+ }
+
+%% Treat \\[dimen] command
+\NewTableCommand \RowBefore@AddBelowSep [1] []
+ {
+ \IfValueT { #1 }
+ {
+ \__tblr_prop_gadd_dimen_value:nxx { row }
+ { [\int_eval:n {\c@rownum - 1}] / belowsep } { #1 }
+ }
+ }
+
+%% Split table lines to cells and store them
+%% #1: sequence of lines
+\cs_new_protected:Npn \__tblr_split_lines_to_cells:N #1
+ {
+ \seq_map_indexed_function:NN #1 \__tblr_split_one_line:nn
+ \LogTblrTracing { text }
+ }
+
+%% Split one line into cells and store them
+%% #1: row number, #2 the line text
+\cs_new_protected:Npn \__tblr_split_one_line:nn #1 #2
+ {
+ \seq_set_split:Nnn \l_tmpa_seq { & } { #2 }
+ \int_set:Nn \c@rownum {#1}
+ \int_zero:N \c@colnum
+ \seq_map_inline:Nn \l_tmpa_seq
+ {
+ \tl_set:Nn \l_tmpa_tl { ##1 }
+ \__tblr_remove_braces:N \l_tmpa_tl
+ \int_incr:N \c@colnum
+ \__tblr_extract_table_commands:N \l_tmpa_tl
+ \__tblr_prop_gput:nxV {text} { [#1][\int_use:N \c@colnum] } \l_tmpa_tl
+ \__tblr_add_multicolumn_empty_cell:
+ }
+ %% Decrease row count by 1 if the last row has only one empty cell text
+ %% We need to do it here since the > or < column type may add text to cells
+ \bool_lazy_and:nnTF
+ { \int_compare_p:nNn {\c@colnum} = {1} }
+ { \tl_if_empty_p:N \l_tmpa_tl }
+ { \int_decr:N \c@rowcount }
+ {
+ \__tblr_prop_gput:nnx
+ {row} { [#1] / cell-number } { \int_use:N \c@colnum }
+ \int_compare:nT { \c@colnum > \c@colcount }
+ {
+ \int_set_eq:NN \c@colcount \c@colnum
+ }
+ }
+ }
+
+%% Add empty cells after the \multicolumn span cell
+\cs_new_protected:Npn \__tblr_add_multicolumn_empty_cell:
+ {
+ \int_step_inline:nn { \l__multicolumn_cell_number_int - 1 }
+ {
+ \int_incr:N \c@colnum
+ \__tblr_prop_gput:nxn {text}
+ { [\int_use:N \c@rownum][\int_use:N \c@colnum] } { }
+ }
+ }
+
+%%% --------------------------------------------------------
+%% \section{Extract Table Commands from Cell Text}
+%%% --------------------------------------------------------
+
+%% Extract table commands defined with \NewTableCommand from cell text
+
+\clist_gset:Nn \g__tblr_table_commands_unbrace_next_clist {\multirow, \multicolumn}
+\bool_new:N \l__tblr_table_command_unbrace_next_bool
+\int_new:N \l__multicolumn_cell_number_int
+\tl_new:N \l__tblr_saved_table_commands_before_cell_text_tl
+\tl_new:N \l__tblr_saved_cell_text_after_table_commands_tl
+
+\cs_new_protected:Npn \__tblr_extract_table_commands:N #1
+ {
+ \tl_clear:N \l__tblr_saved_table_commands_before_cell_text_tl
+ \tl_clear:N \l__tblr_saved_cell_text_after_table_commands_tl
+ \int_set:Nn \l__multicolumn_cell_number_int {1}
+ \exp_last_unbraced:NV \__tblr_extract_table_commands_next:w #1 \scan_stop:
+ \tl_if_empty:NF \l__tblr_saved_table_commands_before_cell_text_tl
+ {
+ \__tblr_prop_gput:nxV { command }
+ {[\int_use:N \c@rownum][\int_use:N \c@colnum]}
+ \l__tblr_saved_table_commands_before_cell_text_tl
+ }
+ \tl_set_eq:NN #1 \l__tblr_saved_cell_text_after_table_commands_tl
+ }
+
+%% #1 maybe a single token or multiple tokens given in braces
+\cs_new_protected:Npn \__tblr_extract_table_commands_next:w #1
+ {
+ \clist_if_in:NnTF \g__tblr_table_commands_clist { #1 }
+ {
+ \clist_if_in:NnTF \g__tblr_table_commands_unbrace_next_clist { #1 }
+ { \bool_set_true:N \l__tblr_table_command_unbrace_next_bool }
+ { \bool_set_false:N \l__tblr_table_command_unbrace_next_bool }
+ \token_if_eq_meaning:NNTF #1 \multicolumn
+ { \__tblr_extract_multicolumn_command:Nn #1 }
+ { \__tblr_extract_one_table_command:N #1 }
+ }
+ {
+ \tl_if_single_token:nTF {#1}
+ {
+ \token_if_eq_meaning:NNF #1 \scan_stop:
+ { \__tblr_save_real_cell_text:w #1 }
+ }
+ { \__tblr_save_real_cell_text:w {#1} }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_extract_multicolumn_command:Nn #1 #2
+ {
+ \int_set:Nn \l__multicolumn_cell_number_int {#2}
+ \__tblr_extract_one_table_command:N #1 {#2}
+ }
+
+\cs_new_protected:Npn \__tblr_extract_one_table_command:N #1
+ {
+ \int_set:Nn \l__tblr_a_int
+ { \cs:w g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl \cs_end: }
+ \tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl {#1}
+ \int_compare:nNnTF {\l__tblr_a_int} < {0}
+ {
+ \int_set:Nn \l__tblr_a_int { \int_abs:n {\l__tblr_a_int} - 1 }
+ \peek_charcode:NTF [
+ { \__tblr_extract_table_command_arg_o:w }
+ { \__tblr_extract_table_command_arg_next: }
+ }
+ { \__tblr_extract_table_command_arg_next: }
+ }
+
+\cs_new_protected:Npn \__tblr_extract_table_command_arg_o:w [#1]
+ {
+ \tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl { [#1] }
+ \__tblr_extract_table_command_arg_next:
+ }
+
+\cs_new_protected:Npn \__tblr_extract_table_command_arg_m:n #1
+ {
+ \tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl { {#1} }
+ \__tblr_extract_table_command_arg_next:
+ }
+
+\cs_new_protected:Npn \__tblr_extract_table_command_arg_next:
+ {
+ \int_compare:nNnTF {\l__tblr_a_int} > {0}
+ {
+ \int_decr:N \l__tblr_a_int
+ \__tblr_extract_table_command_arg_m:n
+ }
+ {
+ \bool_if:NTF \l__tblr_table_command_unbrace_next_bool
+ { \__tblr_last_unbraced:Nn \__tblr_extract_table_commands_next:w }
+ { \__tblr_extract_table_commands_next:w }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_last_unbraced:Nn #1 #2 { #1 #2 }
+
+%% The outermost set of braces of cell text #1 will be removed
+\cs_new_protected:Npn \__tblr_save_real_cell_text:w #1 \scan_stop:
+ {
+ \tl_set:Nn \l__tblr_saved_cell_text_after_table_commands_tl {#1}
+ }
+
+%%% --------------------------------------------------------
+%% \section{Initial Table Specifications}
+%%% --------------------------------------------------------
+
+\prop_gset_from_keyval:Nn \g__tblr_default_tblr_table_prop
+ {
+ stretch = 1,
+ }
+
+\prop_gset_from_keyval:Nn \g__tblr_default_tblr_rows_prop
+ {
+ abovesep = 2pt,
+ belowsep = 2pt,
+ @row-height = 0pt,
+ @row-head = 0pt,
+ @row-foot = 0pt,
+ @row-upper = 0pt,
+ @row-lower = 0pt,
+ }
+
+\prop_gset_from_keyval:Nn \g__tblr_default_tblr_columns_prop
+ {
+ leftsep = 6pt,
+ rightsep = 6pt,
+ @col-width = 0pt,
+ }
+
+\prop_gset_from_keyval:Nn \g__tblr_default_tblr_cells_prop
+ {
+ halign = l,
+ valign = t,
+ }
+
+\prop_gset_from_keyval:Nn \g__tblr_default_tblr_hlines_prop
+ {
+ rulesep = 2pt,
+ }
+
+\prop_gset_from_keyval:Nn \g__tblr_default_tblr_vlines_prop
+ {
+ rulesep = 2pt,
+ }
+
+\cs_new_protected:Npn \__tblr_initial_table_spec:
+ {
+ \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _table_prop }
+ {
+ \__tblr_prop_gput:nxn { table } { ##1 } {##2}
+ }
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _rows_prop }
+ {
+ \__tblr_prop_gput:nxn { row } { [\l__tblr_i_tl] / ##1 } {##2}
+ }
+ \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _hlines_prop }
+ {
+ \__tblr_prop_gput:nxn { hline } { [\l__tblr_i_tl] / ##1 } {##2}
+ }
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \prop_map_inline:cn
+ { g__tblr_default_ \l__tblr_env_name_tl _cells_prop }
+ {
+ \__tblr_prop_gput:nxn { cell }
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / ##1 } {##2}
+ }
+ }
+ }
+ \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _hlines_prop }
+ {
+ \__tblr_prop_gput:nxn { hline }
+ { [\int_eval:n { \c@rowcount + 1}] / ##1 } {##2}
+ }
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _columns_prop }
+ {
+ \__tblr_prop_gput:nxn { column } { [\l__tblr_j_tl] / ##1 } {##2}
+ }
+ \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _vlines_prop }
+ {
+ \__tblr_prop_gput:nxn { vline } { [\l__tblr_j_tl] / ##1 } {##2}
+ }
+ }
+ \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _vlines_prop }
+ {
+ \__tblr_prop_gput:nxn { vline }
+ { [\int_eval:n { \c@colcount + 1}] / ##1 } {##2}
+ }
+ \keys_set:nv { tblr } { l__tblr_default_ \l__tblr_env_name_tl _tl }
+ }
+
+\tl_new:N \l__tblr_default_tblr_tl
+
+%% #1: env name; #2: options
+\NewDocumentCommand \SetTabularrayDefault { O{tblr} m }
+ {
+ \tl_put_right:cn { l__tblr_default_ #1 _tl } { , #2 }
+ }
+\cs_new_eq:NN \SetTblrDefault \SetTabularrayDefault
+
+%%% --------------------------------------------------------
+%% \section{Parse Table Specifications}
+%%% --------------------------------------------------------
+
+\clist_new:N \g__tblr_table_known_keys_clist
+\clist_gset:Nn \g__tblr_table_known_keys_clist
+ {
+ colspec, rowspec, width, hspan, stretch,
+ column, row, cell, vline, hline, columns, rows, cells, vlines, hlines,
+ leftsep, rightsep, colsep, abovesep, belowsep, rowsep,
+ }
+
+\keys_define:nn { tblr }
+ {
+ colspec .code:n = \__tblr_parse_colrow_spec:nn { column } {#1},
+ rowspec .code:n = \__tblr_parse_colrow_spec:nn { row } {#1},
+ width .code:n = \__tblr_keys_gput:nx { width } { \dim_eval:n {#1} },
+ hspan .code:n = \__tblr_keys_gput:nn { hspan } {#1},
+ stretch .code:n = \__tblr_keys_gput:nn { stretch } {#1},
+ columns .code:n = \__tblr_set_every_column_aux:n {#1},
+ rows .code:n = \__tblr_set_every_row_aux:n {#1},
+ cells .code:n = \__tblr_set_every_cell_aux:n {#1},
+ hlines .code:n = \__tblr_set_every_hline_aux:n {#1},
+ vlines .code:n = \__tblr_set_every_vline_aux:n {#1},
+ leftsep .code:n = \tblr_set_every_column:nn { } { leftsep = #1 },
+ rightsep .code:n = \tblr_set_every_column:nn { } { rightsep = #1 },
+ colsep .meta:n = { leftsep = #1, rightsep = #1 },
+ abovesep .code:n = \tblr_set_every_row:nn { } { abovesep = #1 },
+ belowsep .code:n = \tblr_set_every_row:nn { } { belowsep = #1 },
+ rowsep .meta:n = { abovesep = #1, belowsep = #1 },
+ unknown .code:n = \__tblr_table_special_key:Vn \l_keys_key_str {#1},
+ }
+
+\regex_const:Nn \c__tblr_split_key_name_regex { ^ ( [a-z] + ) ( . * ) }
+
+\cs_new_protected:Npn \__tblr_table_special_key:nn #1 #2
+ {
+ \regex_extract_once:NnNT \c__tblr_split_key_name_regex {#1} \l_tmpa_seq
+ {
+ \tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {2} }
+ \tl_set_rescan:Nnx \l__tblr_b_tl {} { \seq_item:Nn \l_tmpa_seq {3} }
+ \cs:w __tblr_set_ \l__tblr_a_tl _aux:Vn \cs_end: \l__tblr_b_tl {#2}
+ }
+ }
+\cs_generate_variant:Nn \__tblr_table_special_key:nn { Vn }
+
+%% If the first key name is known, treat #1 is the table spec;
+%% otherwise, treat #1 as colspec.
+
+\regex_const:Nn \c__tblr_first_key_name_regex { ^ \s * ( [A-Za-z\-] + ) }
+
+\cs_new_protected:Npn \__tblr_parse_table_spec:n #1
+ {
+ \regex_extract_once:NnNTF \c__tblr_first_key_name_regex {#1} \l_tmpa_seq
+ {
+ \clist_if_in:NxTF \g__tblr_table_known_keys_clist
+ { \seq_item:Nn \l_tmpa_seq {2} }
+ { \keys_set:nn { tblr } {#1} }
+ { \__tblr_parse_colrow_spec:nn { column } {#1} }
+ }
+ { \__tblr_parse_colrow_spec:nn { column } {#1} }
+ }
+
+\cs_new_protected:Npn \__tblr_keys_gput:nn #1 #2
+ {
+ \__tblr_prop_gput:nnn { table } {#1} {#2}
+ }
+\cs_generate_variant:Nn \__tblr_keys_gput:nn { nx }
+
+%%% --------------------------------------------------------
+%% \section{Typeset and Calculate Sizes}
+%%% --------------------------------------------------------
+
+%% Calculate the width and height for every cell and border
+
+\cs_new_protected:Npn \__tblr_calc_cell_and_line_sizes:
+ {
+ \__tblr_make_strut_box:
+ \__tblr_calculate_line_sizes:
+ \__tblr_calculate_cell_sizes:
+ \LogTblrTracing { cell, row, column, hline, vline }
+ \__tblr_compute_extendable_column_width:
+ \__tblr_adjust_sizes_for_span_cells:
+ }
+
+%% make strut box from stretch option of the table
+
+\box_new:N \l__tblr_strut_ht_box
+\box_new:N \l__tblr_strut_dp_box
+
+\cs_new_protected:Npn \__tblr_make_strut_box:
+ {
+ \tl_set:Nx \l__tblr_s_tl { \__tblr_prop_item:ne { table } { stretch } }
+ \hbox_set:Nn \l__tblr_strut_ht_box
+ { \vrule height \l__tblr_s_tl \box_ht:N \strutbox width ~ 0pt }
+ \hbox_set:Nn \l__tblr_strut_dp_box
+ { \vrule depth \l__tblr_s_tl \box_dp:N \strutbox width ~ 0pt }
+ }
+
+%% Calculate the thickness for every hline and vline
+\cs_new_protected:Npn \__tblr_calculate_line_sizes:
+ {
+ %% We need these two counters in executing hline and vline commands
+ \int_zero:N \c@rownum
+ \int_zero:N \c@colnum
+ \int_step_inline:nn { \c@rowcount + 1 }
+ {
+ \int_incr:N \c@rownum
+ \int_zero:N \c@colnum
+ \int_step_inline:nn { \c@colcount + 1 }
+ {
+ \int_incr:N \c@colnum
+ \int_compare:nNnT { ##1 } < { \c@rowcount + 1 }
+ {
+ \__tblr_measure_and_update_vline_size:nn { ##1 } { ####1 }
+ }
+ \int_compare:nNnT { ####1 } < { \c@colcount + 1 }
+ {
+ \__tblr_measure_and_update_hline_size:nn { ##1 } { ####1 }
+ }
+ }
+ }
+ }
+
+%% Measure and update thickness of the vline
+%% #1: row number, #2 column number
+\cs_new_protected:Npn \__tblr_measure_and_update_vline_size:nn #1 #2
+ {
+ \dim_zero:N \l__tblr_w_dim
+ \tl_set:Nx \l__tblr_n_tl
+ { \__tblr_prop_item:ne { vline } { [#2] / @vline-count } }
+ \tl_if_empty:NF \l__tblr_n_tl
+ {
+ \tl_set:Nx \l__tblr_s_tl
+ { \__tblr_prop_item:ne { vline } { [#2] / rulesep } }
+ \int_step_inline:nn { \l__tblr_n_tl }
+ {
+ \vbox_set_to_ht:Nnn \l__tblr_b_box {1pt}
+ {
+ \__tblr_get_vline_segment_child:nnnnn
+ {#1} {#2} {##1} {1pt} {1pt}
+ }
+ \tl_set:Nx \l__tblr_w_tl { \dim_eval:n { \box_wd:N \l__tblr_b_box } }
+ \__tblr_prop_gput_if_larger:nxx { vline }
+ { [#2](##1) / @vline-width } { \l__tblr_w_tl }
+ \dim_add:Nn \l__tblr_w_dim { \l__tblr_w_tl }
+ \dim_add:Nn \l__tblr_w_dim { \l__tblr_s_tl }
+ }
+ \dim_add:Nn \l__tblr_w_dim { - \l__tblr_s_tl }
+ }
+ \__tblr_prop_gput_if_larger:nxx { vline }
+ { [#2]/ @vline-width } { \dim_use:N \l__tblr_w_dim }
+ }
+
+%% Get text of a vline segment
+%% #1: row number, #2: column number; #3: index number; #4: height; #5: depth
+%% We put all code inside a group to avoid conflicts of local variables
+\cs_new_protected:Npn \__tblr_get_vline_segment_child:nnnnn #1 #2 #3 #4 #5
+ {
+ \group_begin:
+ \tl_set:Nx \l__tblr_w_tl
+ { \__tblr_prop_item:ne { vline } { [#1][#2](#3) / wd } }
+ \tl_if_empty:NF \l__tblr_w_tl { \dim_set:Nn \rulewidth { \l__tblr_w_tl } }
+ \tl_set:Nx \l__tblr_d_tl
+ { \__tblr_prop_item:ne { vline } { [#1][#2](#3) / @dash } }
+ \tl_set:Nx \l__tblr_a_tl { \tl_head:N \l__tblr_d_tl }
+ \tl_set:Nx \l__tblr_b_tl { \tl_tail:N \l__tblr_d_tl }
+ \exp_args:NV \tl_if_eq:NNTF \l__tblr_a_tl \@tblr@dash
+ {
+ \__tblr_get_vline_dash_style:N \l__tblr_b_tl
+ \xleaders \l__tblr_b_tl \vfil
+ }
+ {
+ \hbox_set:Nn \l__tblr_d_box { \l__tblr_b_tl }
+ \box_set_ht:Nn \l__tblr_d_box {#4}
+ \box_set_dp:Nn \l__tblr_d_box {#5}
+ \box_use:N \l__tblr_d_box
+ }
+ \group_end:
+ }
+\cs_generate_variant:Nn \__tblr_get_vline_segment_child:nnnnn { nnnxx }
+
+%% Measure and update thickness of the hline
+%% #1: row number, #2 column number
+\cs_new_protected:Npn \__tblr_measure_and_update_hline_size:nn #1 #2
+ {
+ \dim_zero:N \l__tblr_h_dim
+ \tl_set:Nx \l__tblr_n_tl
+ { \__tblr_prop_item:ne { hline } { [#1] / @hline-count } }
+ \tl_if_empty:NF \l__tblr_n_tl
+ {
+ \tl_set:Nx \l__tblr_s_tl
+ { \__tblr_prop_item:ne { hline } { [#1] / rulesep } }
+ \int_step_inline:nn { \l__tblr_n_tl }
+ {
+ \hbox_set_to_wd:Nnn \l__tblr_b_box {1pt}
+ { \__tblr_get_hline_segment_child:nnn {#1} {#2} {##1} }
+ \tl_set:Nx \l__tblr_h_tl
+ {
+ \dim_eval:n
+ { \box_ht:N \l__tblr_b_box + \box_dp:N \l__tblr_b_box }
+ }
+ \__tblr_prop_gput_if_larger:nxx { hline }
+ { [#1](##1) / @hline-height } { \l__tblr_h_tl }
+ \dim_add:Nn \l__tblr_h_dim { \l__tblr_h_tl }
+ \dim_add:Nn \l__tblr_h_dim { \l__tblr_s_tl }
+ }
+ \dim_add:Nn \l__tblr_h_dim { - \l__tblr_s_tl }
+ }
+ \__tblr_prop_gput_if_larger:nxx { hline }
+ { [#1] / @hline-height } { \dim_use:N \l__tblr_h_dim }
+ }
+
+%% Get text of a hline segment
+%% #1: row number, #2: column number; #3: index number
+\cs_new_protected:Npn \__tblr_get_hline_segment_child:nnn #1 #2 #3
+ {
+ \group_begin:
+ \tl_set:Nx \l__tblr_w_tl
+ { \__tblr_prop_item:ne { hline } { [#1][#2](#3) / wd } }
+ \tl_if_empty:NF \l__tblr_w_tl { \dim_set:Nn \rulewidth { \l__tblr_w_tl } }
+ \tl_set:Nx \l__tblr_d_tl
+ { \__tblr_prop_item:ne { hline } { [#1][#2](#3) / @dash } }
+ \tl_set:Nx \l__tblr_a_tl { \tl_head:N \l__tblr_d_tl }
+ \tl_set:Nx \l__tblr_b_tl { \tl_tail:N \l__tblr_d_tl }
+ \exp_args:NV \tl_if_eq:NNTF \l__tblr_a_tl \@tblr@dash
+ {
+ \__tblr_get_hline_dash_style:N \l__tblr_b_tl
+ \xleaders \l__tblr_b_tl \hfil
+ }
+ { \l__tblr_b_tl \hfil }
+ \group_end:
+ }
+
+%% current cell alignments
+\tl_new:N \g__tblr_cell_halign_tl
+\tl_new:N \g__tblr_cell_valign_tl
+\tl_new:N \g__tblr_cell_middle_tl
+
+\tl_const:Nn \c__tblr_valign_h_tl { h }
+\tl_const:Nn \c__tblr_valign_m_tl { m }
+\tl_const:Nn \c__tblr_valign_f_tl { f }
+\tl_const:Nn \c__tblr_valign_t_tl { t }
+\tl_const:Nn \c__tblr_valign_b_tl { b }
+
+\tl_const:Nn \c__tblr_middle_t_tl { t }
+\tl_const:Nn \c__tblr_middle_m_tl { m }
+\tl_const:Nn \c__tblr_middle_b_tl { b }
+
+%% #1: row number; #2: column number
+\cs_new_protected:Npn \__tblr_get_cell_alignments:nn #1 #2
+ {
+ \group_begin:
+ \tl_gset:Nx \g__tblr_cell_halign_tl
+ { \__tblr_prop_item:ne { cell } { [#1][#2] / halign } }
+ \tl_set:Nx \l__tblr_v_tl
+ { \__tblr_prop_item:ne { cell } { [#1][#2] / valign } }
+ \tl_case:NnF \l__tblr_v_tl
+ {
+ \c__tblr_valign_t_tl
+ {
+ \tl_gset:Nn \g__tblr_cell_valign_tl {m}
+ \tl_gset:Nn \g__tblr_cell_middle_tl {t}
+ }
+ \c__tblr_valign_m_tl
+ {
+ \tl_gset:Nn \g__tblr_cell_valign_tl {m}
+ \tl_gset:Nn \g__tblr_cell_middle_tl {m}
+ }
+ \c__tblr_valign_b_tl
+ {
+ \tl_gset:Nn \g__tblr_cell_valign_tl {m}
+ \tl_gset:Nn \g__tblr_cell_middle_tl {b}
+ }
+ }
+ {
+ \tl_gset_eq:NN \g__tblr_cell_valign_tl \l__tblr_v_tl
+ \tl_gclear:N \g__tblr_cell_middle_tl
+ }
+ \group_end:
+ }
+
+%% current cell dimensions
+\dim_new:N \g__tblr_cell_wd_dim
+\dim_new:N \g__tblr_cell_ht_dim
+\dim_new:N \g__tblr_cell_head_dim
+\dim_new:N \g__tblr_cell_foot_dim
+
+%% Calculate the width and height for every cell
+\cs_new_protected:Npn \__tblr_calculate_cell_sizes:
+ {
+ %% You can use these two counters in cell text
+ \int_zero:N \c@rownum
+ \int_zero:N \c@colnum
+ \int_step_inline:nn { \c@rowcount }
+ {
+ \int_incr:N \c@rownum
+ \int_zero:N \c@colnum
+ \tl_set:Nx \l__tblr_h_tl
+ { \__tblr_prop_item:ne { row } { [\int_use:N \c@rownum] / height } }
+ \tl_if_empty:NF \l__tblr_h_tl
+ {
+ \__tblr_prop_gput:nxV { row }
+ { [\int_use:N \c@rownum] / @row-height } \l__tblr_h_tl
+ }
+ \int_step_inline:nn { \c@colcount }
+ {
+ \int_incr:N \c@colnum
+ \__tblr_measure_cell_update_sizes:nnNNNN
+ { \int_use:N \c@rownum }
+ { \int_use:N \c@colnum }
+ \g__tblr_cell_wd_dim
+ \g__tblr_cell_ht_dim
+ \g__tblr_cell_head_dim
+ \g__tblr_cell_foot_dim
+ }
+ }
+ }
+
+%% Measure and update natural dimensions of the row/column/cell
+%% #1: row number; #2 column number; #3: width dimension;
+%% #4: total height dimension; #5: head dimension; #6: foot dimension
+\cs_new_protected:Npn \__tblr_measure_cell_update_sizes:nnNNNN #1 #2 #3 #4 #5 #6
+ {
+ \__tblr_get_cell_alignments:nn {#1} {#2}
+ \hbox_set:Nn \l_tmpa_box { \__tblr_get_cell_text:nn {#1} {#2} }
+ \__tblr_update_cell_size:nnNNNN {#1} {#2} #3 #4 #5 #6
+ \__tblr_update_row_size:nnNNN {#1} {#2} #4 #5 #6
+ \__tblr_update_col_size:nN {#2} #3
+ }
+
+%% #1: row number, #2: column number
+\cs_new_protected:Npn \__tblr_get_cell_text:nn #1 #2
+ {
+ \__tblr_prop_if_in:nxTF {cell} { [#1][#2] / omit }
+ {
+ \dim_gzero:N \g__tblr_cell_wd_dim
+ \dim_gzero:N \g__tblr_cell_ht_dim
+ \dim_gzero:N \g__tblr_cell_head_dim
+ \dim_gzero:N \g__tblr_cell_foot_dim
+ }
+ { \__tblr_get_cell_text_real:nn { #1 } { #2 } }
+ }
+
+%% Get cell text, #1: row number, #2: column number
+%% If the width of the cell is not set, split it with \\ and compute the width
+%% Therefore we always get a vbox for any cell
+\cs_new_protected:Npn \__tblr_get_cell_text_real:nn #1 #2
+ {
+ \group_begin:
+ \tl_set:Nx \l__tblr_c_tl { \__tblr_prop_item:ne {text} {[#1][#2]} }
+ \tl_set:Nx \l__tblr_w_tl
+ { \__tblr_prop_item:ne { cell } { [#1][#2] / width } }
+ \tl_if_empty:NT \l__tblr_w_tl
+ {
+ \__tblr_prop_if_in:nxF { cell } { [#1][#2] / colspan }
+ {
+ \tl_set:Nx \l__tblr_w_tl
+ { \__tblr_prop_item:ne { column } { [#2] / width } }
+ }
+ }
+ \tl_if_empty:NT \l__tblr_w_tl
+ {
+ \bool_if:NTF \l__tblr_math_mode_bool
+ {
+ \hbox_set:Nn \l_tmpa_box { $\l__tblr_c_tl$ }
+ \tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box }
+ }
+ {
+ \tl_set_eq:NN \l_tmpb_tl \l__tblr_c_tl
+ \__tblr_insert_braces:N \l_tmpb_tl
+ \seq_set_split:NnV \l_tmpa_seq { \\ } \l_tmpb_tl
+ \tl_set:Nn \l__tblr_w_tl { 0pt }
+ \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl
+ {
+ \__tblr_remove_braces:N \l_tmpa_tl
+ \hbox_set:Nn \l_tmpa_box { \l_tmpa_tl }
+ \tl_set:Nx \l__tblr_w_tl
+ { \dim_max:nn { \l__tblr_w_tl } { \box_wd:N \l_tmpa_box } }
+ }
+ }
+ }
+ \__tblr_get_vcell_and_sizes:NN \l__tblr_c_tl \l__tblr_w_tl
+ \group_end:
+ }
+
+%% #1: cell text; #2: box width
+\cs_new_protected:Npn \__tblr_get_vcell_and_sizes:NN #1 #2
+ {
+ \group_begin:
+ \vbox_set_top:Nn \l_tmpa_box { \__tblr_make_vcell_text:nN #1 #2 }
+ \vbox_set:Nn \l_tmpb_box { \__tblr_make_vcell_text:nN #1 #2 }
+ \dim_gset:Nn \g__tblr_cell_wd_dim { \box_wd:N \l_tmpb_box }
+ \dim_gset:Nn \g__tblr_cell_ht_dim
+ { \box_ht:N \l_tmpb_box + \box_dp:N \l_tmpb_box }
+ \dim_gset:Nn \g__tblr_cell_head_dim { \box_ht:N \l_tmpa_box }
+ \dim_gset:Nn \g__tblr_cell_foot_dim { \box_dp:N \l_tmpb_box }
+ \tl_case:Nn \g__tblr_cell_valign_tl
+ {
+ \c__tblr_valign_h_tl
+ { \box_use:N \l_tmpa_box }
+ \c__tblr_valign_m_tl
+ {
+ \tl_case:Nn \g__tblr_cell_middle_tl
+ {
+ \c__tblr_middle_t_tl
+ { \box_use:N \l_tmpa_box }
+ \c__tblr_middle_m_tl
+ {
+ \tl_set:Nx \l__tblr_b_tl
+ {
+ \dim_eval:n
+ {
+ ( \g__tblr_cell_ht_dim - \g__tblr_cell_head_dim
+ - \g__tblr_cell_foot_dim ) / 2
+ }
+ }
+ \box_set_ht:Nn \l_tmpb_box
+ { \g__tblr_cell_head_dim + \l__tblr_b_tl }
+ \box_set_dp:Nn \l_tmpb_box
+ { \g__tblr_cell_foot_dim + \l__tblr_b_tl }
+ \box_use:N \l_tmpb_box
+ }
+ \c__tblr_middle_b_tl
+ { \box_use:N \l_tmpb_box }
+ }
+ }
+ \c__tblr_valign_f_tl
+ { \box_use:N \l_tmpb_box }
+ }
+ \group_end:
+ }
+
+\cs_new_eq:NN \__tlbr_halign_l: \raggedright
+\cs_new_eq:NN \__tlbr_halign_c: \centering
+\cs_new_eq:NN \__tlbr_halign_r: \raggedleft
+
+%% #1: cell text; #2: box width
+\cs_new_protected:Npn \__tblr_make_vcell_text:nN #1 #2
+ {
+ \dim_set:Nn \tex_hsize:D { #2 }
+ \@arrayparboxrestore
+ \cs:w __tlbr_halign_ \g__tblr_cell_halign_tl : \cs_end:
+ \mode_leave_vertical:
+ \box_use:N \l__tblr_strut_ht_box
+ \bool_if:NTF \l__tblr_math_mode_bool { $#1$ } { #1 }
+ \box_use:N \l__tblr_strut_dp_box
+ }
+
+%% #1: total height dimension; #2: head dimension; #3: foot dimension;
+%% #4: tl for resulting upper size; #5: tl for resulting lower size
+
+\tl_new:N \l__tblr_middle_body_tl
+
+\cs_new_protected:Npn \__tblr_get_middle_cell_upper_lower:NNNNN #1 #2 #3 #4 #5
+ {
+ \tl_case:Nn \g__tblr_cell_middle_tl
+ {
+ \c__tblr_middle_t_tl
+ {
+ \tl_set:Nx #4 { \dim_use:N #2 }
+ \tl_set:Nx #5 { \dim_eval:n { #1 - #2 } }
+ }
+ \c__tblr_middle_m_tl
+ {
+ \tl_set:Nx \l__tblr_middle_body_tl { \dim_eval:n { #1 - #2 - #3 } }
+ \tl_set:Nx #4 { \dim_eval:n { #2 + \l__tblr_middle_body_tl / 2 } }
+ \tl_set:Nx #5 { \dim_eval:n { #3 + \l__tblr_middle_body_tl / 2 } }
+ }
+ \c__tblr_middle_b_tl
+ {
+ \tl_set:Nx #4 { \dim_eval:n { #1 - #3 } }
+ \tl_set:Nx #5 { \dim_use:N #3 }
+ }
+ }
+ }
+
+%% Update natural dimensions of the cell
+%% #1: row number; #2 column number; #3: width dimension;
+%% #4: total height dimension; #5: head dimension; #6: foot dimension
+\cs_new_protected:Npn \__tblr_update_cell_size:nnNNNN #1 #2 #3 #4 #5 #6
+ {
+ \group_begin:
+ \tl_set:Nx \l__tblr_c_tl
+ { \__tblr_prop_item:ne {cell} { [#1][#2] / colspan } }
+ \tl_if_empty:NF \l__tblr_c_tl
+ {
+ \__tblr_prop_gput:nxx {cell} { [#1][#2] / @cell-width } { \dim_use:N #3 }
+ \dim_gzero:N #3 % don't affect column width
+ }
+ \tl_set:Nx \l__tblr_r_tl
+ { \__tblr_prop_item:ne {cell} { [#1][#2] / rowspan } }
+ \tl_if_empty:NF \l__tblr_r_tl
+ {
+ \tl_case:Nn \g__tblr_cell_valign_tl
+ {
+ \c__tblr_valign_h_tl
+ {
+ \tl_set:Nx \l__tblr_u_tl { \dim_use:N #5 }
+ \tl_set:Nx \l__tblr_v_tl { \dim_eval:n { #4 - #5 } }
+ %% Update the head size of the first span row here
+ \__tblr_prop_gput_if_larger:nxx { row }
+ { [#1] / @row-head } { \dim_use:N #5 }
+ }
+ \c__tblr_valign_f_tl
+ {
+ \tl_set:Nx \l__tblr_u_tl { \dim_eval:n { #4 - #6 } }
+ \tl_set:Nx \l__tblr_v_tl { \dim_use:N #6 }
+ %% Update the foot size of the last span row here
+ \__tblr_prop_gput_if_larger:nxx { row }
+ { [\int_eval:n { #1 + \l__tblr_r_tl - 1 }] / @row-foot }
+ { \dim_use:N #6 }
+ }
+ \c__tblr_valign_m_tl
+ {
+ \__tblr_get_middle_cell_upper_lower:NNNNN
+ #4 #5 #6 \l__tblr_u_tl \l__tblr_v_tl
+ }
+ }
+ \__tblr_prop_gput:nxV {cell} { [#1][#2] / @cell-height } \l__tblr_u_tl
+ \__tblr_prop_gput:nxV {cell} { [#1][#2] / @cell-depth } \l__tblr_v_tl
+ %% Don't affect row sizes
+ \dim_gzero:N #4
+ \dim_gzero:N #5
+ \dim_gzero:N #6
+ }
+ \group_end:
+ }
+
+
+%% Update size of the row. #1: row number; #2: column number;
+%% #3: total height dimension; #4: head dimension; #5: foot dimension
+\cs_new_protected:Npn \__tblr_update_row_size:nnNNN #1 #2 #3 #4 #5
+ {
+ \group_begin:
+ %% Note that \l__tblr_h_tl may be empty
+ \tl_set:Nx \l__tblr_h_tl
+ { \__tblr_prop_item:ne { row } { [#1] / @row-height } }
+ \tl_if_eq:NNTF \g__tblr_cell_valign_tl \c__tblr_valign_m_tl
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ { \__tblr_prop_item:ne { row } { [#1] / @row-upper } }
+ \tl_set:Nx \l__tblr_b_tl
+ { \__tblr_prop_item:ne { row } { [#1] / @row-lower } }
+ \__tblr_get_middle_cell_upper_lower:NNNNN
+ #3 #4 #5 \l__tblr_u_tl \l__tblr_v_tl
+ \dim_compare:nNnT { \l__tblr_u_tl } > { \l__tblr_a_tl }
+ {
+ \tl_set_eq:NN \l__tblr_a_tl \l__tblr_u_tl
+ \__tblr_prop_gput:nxV { row }
+ { [#1] / @row-upper } \l__tblr_a_tl
+ }
+ \dim_compare:nNnT { \l__tblr_v_tl } > { \l__tblr_b_tl }
+ {
+ \tl_set_eq:NN \l__tblr_b_tl \l__tblr_v_tl
+ \__tblr_prop_gput:nxV { row }
+ { [#1] / @row-lower } \l__tblr_b_tl
+ }
+ \dim_compare:nNnT
+ { \l__tblr_a_tl + \l__tblr_b_tl } > { \l__tblr_h_tl + 0pt }
+ {
+ \__tblr_prop_gput:nxx { row } { [#1] / @row-height }
+ { \dim_eval:n { \l__tblr_a_tl + \l__tblr_b_tl } }
+ }
+ }
+ {
+ \tl_set:Nx \l__tblr_e_tl
+ { \__tblr_prop_item:ne { row } { [#1] / @row-head } }
+ \tl_set:Nx \l__tblr_f_tl
+ { \__tblr_prop_item:ne { row } { [#1] / @row-foot } }
+ \dim_compare:nNnT {#4} > {\l__tblr_e_tl}
+ {
+ \__tblr_prop_gput:nxx { row } { [#1] / @row-head } { \dim_use:N #4 }
+ }
+ \dim_compare:nNnT {#5} > {\l__tblr_f_tl}
+ {
+ \__tblr_prop_gput:nxx { row } { [#1] / @row-foot } { \dim_use:N #5 }
+ }
+ \tl_set:Nx \l__tblr_x_tl { \dim_max:nn {#4} { \l__tblr_e_tl } }
+ \tl_set:Nx \l__tblr_y_tl { \dim_max:nn {#5} { \l__tblr_f_tl } }
+ \dim_compare:nNnT
+ { #3 - #4 - #5 } > { \l__tblr_h_tl - \l__tblr_x_tl - \l__tblr_y_tl }
+ {
+ \__tblr_prop_gput:nxx { row } { [#1] / @row-height }
+ {
+ \dim_eval:n
+ {
+ \l__tblr_x_tl
+ + \dim_use:N #3 - \dim_use:N #4 - \dim_use:N #5
+ + \l__tblr_y_tl
+ }
+ }
+ }
+ }
+ \group_end:
+ }
+
+
+%% Update size of the column. #1: column number; #2: width dimension
+
+\cs_new_protected:Npn \__tblr_update_col_size:nN #1 #2
+ {
+ \tl_set:Nx \l_tmpb_tl
+ { \__tblr_prop_item:ne {column} { [#1] / @col-width } }
+ \bool_lazy_or:nnT
+ { \tl_if_empty_p:N \l_tmpb_tl }
+ { \dim_compare_p:nNn { \dim_use:N #2 } > { \l_tmpb_tl } }
+ {
+ \__tblr_prop_gput:nxx {column} { [#1] / @col-width } { \dim_use:N #2 }
+ }
+ }
+
+%%% --------------------------------------------------------
+%% \section{Calculate and Adjust Extendable Columns}
+%%% --------------------------------------------------------
+
+%% Compute column widths when there are some extendable columns
+
+\dim_new:N \l__column_target_dim
+\prop_new:N \l__column_coefficient_prop
+\prop_new:N \l__column_natural_width_prop
+\prop_new:N \l__column_computed_width_prop
+
+\msg_new:nnn { tabularray } { table-width-too-small }
+ { Table ~ width ~ is ~ too ~ small, need ~ #1 ~ more! }
+
+\cs_new_protected:Npn \__tblr_compute_extendable_column_width:
+ {
+ \__tblr_collect_extendable_column_width:
+ \dim_compare:nNnTF { \l__column_target_dim } > { 0pt }
+ {
+ \prop_if_empty:NF \l__column_coefficient_prop
+ { \__tblr_adjust_extendable_column_width: }
+ }
+ {
+ \msg_warning:nnx { tabularray } { table-width-too-small }
+ { \dim_abs:n { \l__column_target_dim } }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_collect_extendable_column_width:
+ {
+ \tl_set:Nx \l_tmpa_tl { \__tblr_prop_item:nn {table} {width} }
+ \tl_if_empty:NTF \l_tmpa_tl
+ { \dim_set_eq:NN \l__column_target_dim \linewidth }
+ { \dim_set:Nn \l__column_target_dim { \l_tmpa_tl } }
+ \prop_clear:N \l__column_coefficient_prop
+ \prop_clear:N \l__column_natural_width_prop
+ \prop_clear:N \l__column_computed_width_prop
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ { \__tblr_prop_item:ne {column} { [\l__tblr_j_tl] / width } }
+ \tl_set:Nx \l__tblr_b_tl
+ { \__tblr_prop_item:ne {column} { [\l__tblr_j_tl] / coefficient } }
+ \tl_set:Nx \l__tblr_c_tl
+ { \__tblr_prop_item:ne {column} { [\l__tblr_j_tl] / @col-width } }
+ \tl_if_empty:NTF \l__tblr_a_tl
+ {
+ \tl_if_empty:NTF \l__tblr_b_tl
+ { \dim_sub:Nn \l__column_target_dim { \l__tblr_c_tl } }
+ {
+ \prop_put:Nxx \l__column_coefficient_prop
+ { \l__tblr_j_tl } { \l__tblr_b_tl }
+ \prop_put:Nxn \l__column_computed_width_prop
+ { \l__tblr_j_tl } { 0pt }
+ \dim_compare:nNnF { \l__tblr_b_tl pt } > { 0pt }
+ {
+ \prop_put:Nxx \l__column_natural_width_prop
+ { \l__tblr_j_tl } { \l__tblr_c_tl }
+ }
+ }
+ }
+ { \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } }
+ \tl_set:Nx \l__tblr_a_tl
+ { \__tblr_prop_item:ne {vline} { [\l__tblr_j_tl] / @vline-width } }
+ \tl_set:Nx \l__tblr_b_tl
+ { \__tblr_prop_item:ne {column} { [\l__tblr_j_tl] / leftsep} }
+ \tl_set:Nx \l__tblr_c_tl
+ { \__tblr_prop_item:ne {column} { [\l__tblr_j_tl] / rightsep } }
+ \dim_set:Nn \l__column_target_dim
+ { \l__column_target_dim - \l__tblr_a_tl - \l__tblr_b_tl - \l__tblr_c_tl }
+ }
+ \tl_set:Nx \l__tblr_a_tl
+ {
+ \__tblr_prop_item:ne {vline}
+ { [\int_eval:n {\c@colcount + 1}] / @vline-width }
+ }
+ \tl_if_empty:NF \l__tblr_a_tl
+ { \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } }
+ \LogTblrTracing { target }
+ }
+
+%% If all columns have negative coefficients and small natural widths,
+%% \l__column_coefficient_prop will be empty after one or more rounds
+\cs_new_protected:Npn \__tblr_adjust_extendable_column_width:
+ {
+ \bool_while_do:nn
+ { \dim_compare_p:nNn { \l__column_target_dim } > { \hfuzz } }
+ {
+ \prop_if_empty:NTF \l__column_coefficient_prop
+ { \__tblr_adjust_extendable_column_width_negative: }
+ { \__tblr_adjust_extendable_column_width_once: }
+ }
+ \prop_map_inline:Nn \l__column_computed_width_prop
+ {
+ \__tblr_prop_gput:nnx {column} { [##1] / width } { ##2 }
+ \__tblr_prop_gput:nnn {column} { [##1] / @col-width } { 0pt }
+ }
+ \__tblr_calculate_cell_sizes:
+ }
+
+%% We use dimen register, since the coefficient may be a decimal number
+\cs_new_protected:Npn \__tblr_adjust_extendable_column_width_once:
+ {
+ \dim_zero:N \l_tmpa_dim
+ \prop_map_inline:Nn \l__column_coefficient_prop
+ {
+ \dim_add:Nn \l_tmpa_dim { \dim_abs:n { ##2 pt } }
+ }
+ \tl_set:Nx \l__tblr_w_tl
+ { \dim_ratio:nn { \l__column_target_dim } { \l_tmpa_dim } }
+ \dim_zero:N \l__column_target_dim
+ \prop_map_inline:Nn \l__column_coefficient_prop
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ { \dim_eval:n { \dim_abs:n { ##2 pt } * \l__tblr_w_tl } }
+ \dim_compare:nNnTF { ##2 pt } > { 0pt }
+ {
+ \__tblr_add_dimen_value:Nnn
+ \l__column_computed_width_prop { ##1 } { \l__tblr_a_tl }
+ }
+ {
+ \tl_set:Nx \l__tblr_b_tl
+ { \prop_item:Nn \l__column_natural_width_prop { ##1 } }
+ \tl_set:Nx \l__tblr_c_tl
+ { \prop_item:Nn \l__column_computed_width_prop { ##1 } }
+ \dim_compare:nNnTF { \l__tblr_a_tl + \l__tblr_c_tl } > { \l__tblr_b_tl }
+ {
+ \prop_put:Nnx \l__column_computed_width_prop
+ { ##1 } { \l__tblr_b_tl }
+ \dim_add:Nn \l__column_target_dim
+ { \l__tblr_a_tl + \l__tblr_c_tl - \l__tblr_b_tl }
+ \prop_remove:Nn \l__column_coefficient_prop { ##1 }
+ }
+ {
+ \__tblr_add_dimen_value:Nnn
+ \l__column_computed_width_prop { ##1 } { \l__tblr_a_tl }
+ }
+ }
+ }
+ \LogTblrTracing { target }
+ }
+
+\cs_new_protected:Npn \__tblr_adjust_extendable_column_width_negative:
+ {
+ \dim_zero:N \l_tmpa_dim
+ \prop_map_inline:Nn \l__column_natural_width_prop
+ { \dim_add:Nn \l_tmpa_dim { ##2 } }
+ \tl_set:Nx \l_tmpa_tl
+ { \dim_ratio:nn { \l__column_target_dim } { \l_tmpa_dim } }
+ \dim_zero:N \l__column_target_dim
+ \prop_map_inline:Nn \l__column_natural_width_prop
+ {
+ \tl_set:Nx \l_tmpb_tl { \dim_eval:n { ##2 * \l_tmpa_tl } }
+ \__tblr_add_dimen_value:Nnn
+ \l__column_computed_width_prop { ##1 } { \l_tmpb_tl }
+ }
+ \LogTblrTracing { target }
+ }
+
+%%% --------------------------------------------------------
+%% \section{Calculate and Adjust Multispan Cells}
+%%% --------------------------------------------------------
+
+%% Compute and adjust widths when there are some span cells.
+%% By default, we will compute column widths from span widths;
+%% but if we set table option "hspan = minimal",
+%% we will compute span widths from column widths.
+
+\cs_new_protected:Npn \__tblr_adjust_sizes_for_span_cells:
+ {
+ \__tblr_prop_if_in:nnT {table} {colspan}
+ {
+ \__tblr_collect_column_widths_skips:
+ \str_if_eq:xnTF
+ { \__tblr_prop_item:ne {table} {hspan} } {minimal}
+ {
+ \__tblr_set_span_widths_from_column_widths:
+ }
+ {
+ \__tblr_collect_span_widths:
+ \__tblr_set_column_widths_from_span_widths:
+ }
+ \LogTblrTracing {column}
+ \__tblr_calculate_cell_sizes:
+ }
+ \__tblr_prop_if_in:nnT {table} {rowspan}
+ {
+ \__tblr_collect_row_heights_skips:
+ \__tblr_collect_span_heights:
+ \__tblr_set_row_heights_from_span_heights:
+ \LogTblrTracing {row}
+ }
+ }
+
+\prop_new:N \l__tblr_col_item_skip_size_prop
+\prop_new:N \l__tblr_col_span_size_prop
+\prop_new:N \l__tblr_row_item_skip_size_prop
+\prop_new:N \l__tblr_row_span_size_prop
+
+\cs_new_protected:Npn \__tblr_collect_column_widths_skips:
+ {
+ \prop_clear:N \l__tblr_col_item_skip_size_prop
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \int_compare:nNnTF { \l__tblr_j_tl } > { 1 }
+ {
+ \prop_put:Nxx \l__tblr_col_item_skip_size_prop { skip[\l__tblr_j_tl] }
+ {
+ \dim_eval:n
+ {
+ \__tblr_prop_item:ne {column}
+ { [\int_eval:n { \l__tblr_j_tl - 1 }] / rightsep }
+ +
+ \__tblr_prop_item:ne {vline}
+ { [\l__tblr_j_tl] / @vline-width }
+ +
+ \__tblr_prop_item:ne {column}
+ { [\l__tblr_j_tl] / leftsep}
+ }
+ }
+ }
+ {
+ \prop_put:Nxn \l__tblr_col_item_skip_size_prop { skip[\l__tblr_j_tl] }
+ { 0pt }
+ }
+ \prop_put:Nxx \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] }
+ { \__tblr_prop_item:ne {column} { [\l__tblr_j_tl] / @col-width } }
+ }
+ \__tblr_do_if_tracing:nn { cellspan }
+ { \prop_log:N \l__tblr_col_item_skip_size_prop }
+ }
+
+\cs_new_protected:Npn \__tblr_collect_row_heights_skips:
+ {
+ \prop_clear:N \l__tblr_row_item_skip_size_prop
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \int_compare:nNnTF { \l__tblr_i_tl } > { 1 }
+ {
+ \prop_put:Nxx \l__tblr_row_item_skip_size_prop { skip[\l__tblr_i_tl] }
+ {
+ \dim_eval:n
+ {
+ \__tblr_prop_item:ne {row}
+ { [\int_eval:n {\l__tblr_i_tl - 1}] / belowsep }
+ +
+ \__tblr_prop_item:ne {hline}
+ { [\l__tblr_i_tl] / @hline-height }
+ +
+ \__tblr_prop_item:ne {row}
+ { [\l__tblr_i_tl] / abovesep }
+ }
+ }
+ }
+ {
+ \prop_put:Nxn \l__tblr_row_item_skip_size_prop { skip[\l__tblr_i_tl] }
+ { 0pt }
+ }
+ \__tblr_collect_one_row_height:NN \l__tblr_i_tl \l__tblr_h_tl
+ \prop_put:Nxx \l__tblr_row_item_skip_size_prop
+ { item[\l__tblr_i_tl] } { \l__tblr_h_tl }
+ }
+ \__tblr_do_if_tracing:nn { cellspan }
+ { \prop_log:N \l__tblr_row_item_skip_size_prop }
+ }
+
+%% #1: row number; #2: tl with result
+\cs_new_protected:Npn \__tblr_collect_one_row_height:NN #1 #2
+ {
+ \tl_set:Nx #2 { \__tblr_prop_item:ne { row } { [#1] / @row-height } }
+ }
+
+\cs_new_protected:Npn \__tblr_collect_span_widths:
+ {
+ \prop_clear:N \l__tblr_col_span_size_prop
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ {
+ \__tblr_prop_item:ne {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / colspan }
+ }
+ \tl_if_empty:NF \l__tblr_a_tl
+ {
+ \__tblr_put_if_larger:Nxx \l__tblr_col_span_size_prop
+ {
+ ( \l__tblr_j_tl -
+ \int_eval:n {\l__tblr_j_tl + \l__tblr_a_tl - 1} )
+ }
+ {
+ \__tblr_prop_item:ne {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / @cell-width }
+ }
+ }
+ }
+ }
+ \__tblr_do_if_tracing:nn { cellspan }
+ { \prop_log:N \l__tblr_col_span_size_prop }
+ }
+
+\prop_new:N \l__tblr_row_span_to_row_prop
+
+\cs_new_protected:Npn \__tblr_collect_span_heights:
+ {
+ \prop_clear:N \l__tblr_row_span_to_row_prop
+ \prop_clear:N \l__tblr_row_span_size_prop
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ {
+ \__tblr_prop_item:ne {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / rowspan }
+ }
+ \tl_if_empty:NF \l__tblr_a_tl
+ {
+ \tl_set:Nx \l__tblr_v_tl
+ {
+ \__tblr_prop_item:ne {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / valign }
+ }
+ \tl_if_eq:NnT \l__tblr_v_tl { h }
+ {
+ \tl_set:Nx \l__tblr_h_tl
+ {
+ \__tblr_prop_item:ne {row}
+ { [\l__tblr_i_tl] / @row-head }
+ }
+ \__tblr_prop_gput:nxV {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / @cell-height }
+ \l__tblr_h_tl
+ }
+ \tl_if_eq:NnT \l__tblr_v_tl { f }
+ {
+ \tl_set:Nx \l__tblr_d_tl
+ {
+ \__tblr_prop_item:ne {row}
+ {
+ [\int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1}]
+ / @row-foot
+ }
+ }
+ \__tblr_prop_gput:nxV {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / @cell-depth }
+ \l__tblr_d_tl
+ }
+ \__tblr_put_if_larger:Nxx \l__tblr_row_span_size_prop
+ {
+ ( \l__tblr_i_tl -
+ \int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1} )
+ }
+ {
+ \dim_eval:n
+ {
+ \__tblr_prop_item:ne {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / @cell-height }
+ +
+ \__tblr_prop_item:ne {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / @cell-depth }
+ }
+ }
+ \prop_put:Nxx \l__tblr_row_span_to_row_prop
+ { [\l__tblr_i_tl][\l__tblr_j_tl] }
+ { \int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1} }
+ }
+ }
+ }
+ \__tblr_do_if_tracing:nn { cellspan }
+ {
+ \prop_log:N \l__tblr_row_span_to_row_prop
+ \prop_log:N \l__tblr_row_span_size_prop
+ }
+ }
+
+%% Compute and set column widths from span widths
+\cs_new_protected:Npn \__tblr_set_column_widths_from_span_widths:
+ {
+ \__tblr_calc_item_sizes_from_span_sizes:xNN
+ { \int_use:N \c@colcount }
+ \l__tblr_col_item_skip_size_prop
+ \l__tblr_col_span_size_prop
+ \__tblr_set_all_column_widths:
+ }
+
+%% Compute and set row heights from span heights
+\cs_new_protected:Npn \__tblr_set_row_heights_from_span_heights:
+ {
+ \__tblr_calc_item_sizes_from_span_sizes:xNN
+ { \int_use:N \c@rowcount }
+ \l__tblr_row_item_skip_size_prop
+ \l__tblr_row_span_size_prop
+ \__tblr_set_all_row_heights:
+ }
+
+%% See page 245 in Chapter 22 of TeXbook
+%% #1: total number of items
+%% #2: prop list with item sizes and skip sizes; #3: prop list with span sizes
+\cs_new_protected:Npn \__tblr_calc_item_sizes_from_span_sizes:nNN #1 #2 #3
+ {
+ \int_step_variable:nNn { #1 } \l__tblr_j_tl
+ {
+ \dim_set:Nn \l__tblr_w_dim
+ {
+ \prop_item:Ne #2 { item[\l__tblr_j_tl] }
+ }
+ \int_step_variable:nNn { \l__tblr_j_tl - 1 } \l__tblr_i_tl
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ { \prop_item:Ne #3 { (\l__tblr_i_tl-\l__tblr_j_tl) } }
+ \tl_if_empty:NF \l__tblr_a_tl
+ {
+ \int_step_variable:nnNn
+ { \l__tblr_i_tl } { \l__tblr_j_tl - 1 } \l__tblr_k_tl
+ {
+ \__tblr_do_if_tracing:nn { cellspan }
+ {
+ \tl_log:x
+ { \l__tblr_j_tl : \l__tblr_i_tl -> \l__tblr_k_tl }
+ }
+ \tl_set:Nx \l_tmpa_tl
+ {
+ \prop_item:Ne #2 { itemskip[\l__tblr_k_tl] }
+ }
+ \tl_set:Nx \l__tblr_a_tl
+ { \dim_eval:n { \l__tblr_a_tl - \l_tmpa_tl } }
+ }
+ \dim_compare:nNnT { \l__tblr_a_tl } > { \l__tblr_w_dim }
+ {
+ \dim_set:Nn \l__tblr_w_dim { \l__tblr_a_tl }
+ }
+ }
+ }
+ \prop_put:Nxx #2
+ { item[\l__tblr_j_tl] } { \dim_use:N \l__tblr_w_dim }
+ \int_compare:nNnT { \l__tblr_j_tl } < { #1 }
+ {
+ \tl_set:Nx \l_tmpb_tl
+ {
+ \prop_item:Ne #2
+ { skip[\int_eval:n { \l__tblr_j_tl + 1} ] }
+ }
+ \dim_add:Nn \l__tblr_w_dim { \l_tmpb_tl }
+ \prop_put:Nxx #2
+ { itemskip[\l__tblr_j_tl] } { \dim_use:N \l__tblr_w_dim }
+ }
+ }
+ \__tblr_do_if_tracing:nn { cellspan } { \prop_log:N #2 }
+ }
+\cs_generate_variant:Nn \__tblr_calc_item_sizes_from_span_sizes:nNN { x }
+
+\cs_new_protected:Npn \__tblr_set_all_column_widths:
+ {
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \__tblr_prop_gput:nxx {column}
+ { [\l__tblr_j_tl] / @col-width }
+ { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] } }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_set_all_row_heights:
+ {
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \tl_set:Nx \l__tblr_h_tl
+ {
+ \__tblr_prop_item:ne {row} { [\l__tblr_i_tl] / @row-head }
+ }
+ \tl_set:Nx \l__tblr_d_tl
+ {
+ \__tblr_prop_item:ne {row} { [\l__tblr_i_tl] / @row-foot }
+ }
+ \tl_set:Nx \l__tblr_a_tl
+ {
+ \prop_item:Ne \l__tblr_row_item_skip_size_prop { item[\l__tblr_i_tl] }
+ }
+ \__tblr_collect_one_row_height:NN \l__tblr_i_tl \l__tblr_t_tl
+ \__tblr_prop_gput:nxx {row}
+ { [\l__tblr_i_tl] / @row-height } { \l__tblr_a_tl }
+ }
+ }
+
+\cs_new_protected:Npn \__tblr_get_span_key_row_col:w [#1][#2]
+ {
+ \tl_set:Nn \l__tblr_i_tl {#1}
+ \tl_set:Nn \l__tblr_j_tl {#2}
+ }
+
+%% Compute and set span widths from column widths
+\cs_new_protected:Npn \__tblr_set_span_widths_from_column_widths:
+ {
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ {
+ \__tblr_prop_item:ne {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / colspan }
+ }
+ \tl_if_empty:NF \l__tblr_a_tl
+ {
+ \__tblr_calc_span_widths:xxN
+ { \l__tblr_j_tl }
+ { \int_eval:n { \l__tblr_j_tl + \l__tblr_a_tl - 1 } }
+ \l__tblr_w_dim
+ \__tblr_prop_gput:nxx {cell}
+ { [\l__tblr_i_tl][\l__tblr_j_tl] / width }
+ { \dim_use:N \l__tblr_w_dim }
+ }
+ }
+ }
+ }
+
+%% Cell is spanned from col #1 to col #2, #3 is the return dim
+\cs_new_protected:Npn \__tblr_calc_span_widths:nnN #1 #2 #3
+ {
+ \dim_zero:N #3
+ \int_step_inline:nnn { #1 } { #2 }
+ {
+ \tl_set:Nx \l_tmpa_tl
+ { \prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] } }
+ \tl_set:Nx \l_tmpb_tl
+ { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] } }
+ \dim_add:Nn #3 { \dim_eval:n { \l_tmpa_tl + \l_tmpb_tl } }
+ }
+ }
+\cs_generate_variant:Nn \__tblr_calc_span_widths:nnN { xxN }
+
+%%% --------------------------------------------------------
+%% \section{Build the Whole Table}
+%%% --------------------------------------------------------
+
+\tl_new:N \__tlbr_vbox_align_tl
+\tl_const:Nn \__tlbr_vbox_t_tl {t}
+\tl_const:Nn \__tlbr_vbox_m_tl {m}
+\tl_const:Nn \__tlbr_vbox_c_tl {c}
+\tl_const:Nn \__tlbr_vbox_b_tl {b}
+
+\box_new:N \l__tblr_table_box
+
+\cs_new_protected:Npn \__tblr_build_whole:n #1
+ {
+ \vbox_set:Nn \l__tblr_table_box
+ {
+ \int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
+ {
+ \hbox:n { \__tblr_build_hline:V \l__tblr_i_tl }
+ \hrule height ~ 0pt % remove lineskip between hlines and rows
+ \hbox:n { \__tblr_build_row:N \l__tblr_i_tl }
+ \hrule height ~ 0pt
+ }
+ \hbox:n { \__tblr_build_hline:n { \int_eval:n {\c@rowcount + 1} } }
+ }
+ \__tblr_valign_whole:Nn \l__tblr_table_box #1
+ }
+
+\cs_new_protected:Npn \__tblr_valign_whole:Nn #1 #2
+ {
+ \group_begin:
+ \tl_set:Nn \__tlbr_vbox_align_tl {#2}
+ \dim_set:Nn \l__tblr_t_dim { \box_ht:N #1 + \box_dp:N #1 }
+ \tl_case:NnF \__tlbr_vbox_align_tl
+ {
+ \__tlbr_vbox_m_tl
+ { \__tblr_valign_whole_middle:N #1 }
+ \__tlbr_vbox_c_tl
+ { \__tblr_valign_whole_middle:N #1 }
+ \__tlbr_vbox_t_tl
+ { \__tblr_valign_whole_top:N #1 }
+ \__tlbr_vbox_b_tl
+ { \__tblr_valign_whole_bottom:N #1 }
+ }
+ { \__tblr_valign_whole_middle:N #1 }
+ \group_end:
+ }
+
+\cs_new_protected:Npn \__tblr_valign_whole_middle:N #1
+ {
+ \hbox:n { $ \m@th \tex_vcenter:D { \vbox_unpack_drop:N #1 } $ }
+ }
+
+\cs_new_protected:Npn \__tblr_valign_whole_top:N #1
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ { \__tblr_prop_item:ne { hline } { [1] / @hline-height } }
+ %% Note that \l__tblr_b_tl may be empty
+ \tl_set:Nx \l__tblr_b_tl
+ { \__tblr_prop_item:ne { table } { baseline } }
+ \bool_lazy_or:nnTF
+ { \dim_compare_p:nNn { \l__tblr_a_tl } = { 0pt } }
+ { \int_compare_p:nNn { \l__tblr_b_tl + 0 } = { 1 } }
+ {
+ \dim_set:Nn \l__tblr_h_dim
+ {
+ \__tblr_prop_item:ne { row } { [1] / abovesep }
+ +
+ ( \__tblr_prop_item:ne { row } { [1] / @row-height }
+ +
+ \__tblr_prop_item:ne { row } { [1] / @row-upper }
+ -
+ \__tblr_prop_item:ne { row } { [1] / @row-lower }
+ ) / 2
+ }
+ \dim_set:Nn \l__tblr_d_dim { \l__tblr_t_dim - \l__tblr_h_dim }
+ }
+ {
+ \dim_set:Nn \l__tblr_h_dim { 0pt }
+ \dim_set_eq:NN \l__tblr_d_dim \l__tblr_t_dim
+ }
+ \box_set_ht:Nn #1 { \l__tblr_h_dim }
+ \box_set_dp:Nn #1 { \l__tblr_d_dim }
+ \box_use_drop:N #1
+ }
+
+\cs_new_protected:Npn \__tblr_valign_whole_bottom:N #1
+ {
+ \tl_set:Nx \l__tblr_a_tl
+ {
+ \__tblr_prop_item:ne { hline }
+ { [\int_eval:n {\c@rowcount + 1}] / @hline-height }
+ }
+ %% Note that \l__tblr_b_tl may be empty
+ \tl_set:Nx \l__tblr_b_tl
+ { \__tblr_prop_item:ne { table } { baseline } }
+ \bool_lazy_or:nnTF
+ { \dim_compare_p:nNn { \l__tblr_a_tl } = { 0pt } }
+ { \int_compare_p:nNn { \l__tblr_b_tl + 0 } = { \c@rowcount } }
+ {
+ \dim_set:Nn \l__tblr_d_dim
+ {
+ ( \__tblr_prop_item:ne { row }
+ { [\int_use:N \c@rowcount] / @row-height }
+ -
+ \__tblr_prop_item:ne { row }
+ { [\int_use:N \c@rowcount] / @row-upper }
+ +
+ \__tblr_prop_item:ne { row }
+ { [\int_use:N \c@rowcount] / @row-lower }
+ ) / 2
+ +
+ \__tblr_prop_item:ne { row } { [1] / belowsep }
+ }
+ \dim_set:Nn \l__tblr_h_dim { \l__tblr_t_dim - \l__tblr_d_dim }
+ }
+ {
+ \dim_set:Nn \l__tblr_d_dim { 0pt }
+ \dim_set_eq:NN \l__tblr_h_dim \l__tblr_t_dim
+ }
+ \box_set_ht:Nn #1 { \l__tblr_h_dim }
+ \box_set_dp:Nn #1 { \l__tblr_d_dim }
+ \box_use_drop:N #1
+ }
+
+\dim_new:N \l__tblr_col_o_wd_dim
+\dim_new:N \l__tblr_col_b_wd_dim
+
+%% Build hline. #1: row number
+\cs_new_protected:Npn \__tblr_build_hline:n #1
+ {
+ \int_step_inline:nn { \c@colcount }
+ { \__tblr_build_hline_segment:nn { #1 } { ##1 } }
+ }
+\cs_generate_variant:Nn \__tblr_build_hline:n { x, V }
+
+%% #1: row number, #2: column number
+\cs_new_protected:Npn \__tblr_build_hline_segment:nn #1 #2
+ {
+ \tl_set:Nx \l__tblr_n_tl
+ { \__tblr_prop_item:ne { hline } { [#1] / @hline-count } }
+ \tl_set:Nx \l__tblr_o_tl
+ { \__tblr_prop_item:ne { hline } { [#1][#2] / omit } }
+ \__tblr_get_col_outer_width_border_width:nNN {#2}
+ \l__tblr_col_o_wd_dim \l__tblr_col_b_wd_dim
+ \tl_if_empty:NTF \l__tblr_o_tl
+ {
+ \tl_if_empty:NF \l__tblr_n_tl
+ { \__tblr_build_hline_segment_real:nn {#1} {#2} }
+ }
+ { \__tblr_build_hline_segment_omit:nn {#1} {#2} }
+ }
+
+%% #1: row number, #2: column number
+\cs_new_protected:Npn \__tblr_build_hline_segment_omit:nn #1 #2
+ {
+ \skip_horizontal:n { \l__tblr_col_o_wd_dim - \l__tblr_col_b_wd_dim }
+ }
+
+%% #1: row number, #2: column number
+\cs_new_protected:Npn \__tblr_build_hline_segment_real:nn #1 #2
+ {
+ \tl_set:Nx \l__tblr_s_tl
+ { \__tblr_prop_item:ne { hline } { [#1] / rulesep } }
+ \vbox_set:Nn \l__tblr_c_box
+ {
+ %% add an empty hbox to support vbox width
+ \tex_hbox:D to \l__tblr_col_o_wd_dim {}
+ \int_step_inline:nn { \l__tblr_n_tl }
+ {
+ \tl_set:Nx \l__tblr_h_tl
+ { \__tblr_prop_item:ne { hline } { [#1](##1) / @hline-height } }
+ \hrule height ~ 0pt % remove lineskip
+ \hbox_set_to_wd:Nnn \l__tblr_b_box { \l__tblr_col_o_wd_dim }
+ {
+ \tl_set:Nx \l__tblr_f_tl
+ { \__tblr_prop_item:ne { hline } { [#1][#2](##1) / fg } }
+ \tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} }
+ \__tblr_get_hline_segment_child:nnn {#1} {#2} {##1}
+ }
+ \box_set_ht:Nn \l__tblr_b_box { \l__tblr_h_tl }
+ \box_set_dp:Nn \l__tblr_b_box { 0pt }
+ \box_use:N \l__tblr_b_box
+ \skip_vertical:n { \l__tblr_s_tl }
+ }
+ \skip_vertical:n { - \l__tblr_s_tl }
+ }
+ \box_use:N \l__tblr_c_box
+ \skip_horizontal:n { - \l__tblr_col_b_wd_dim }
+ }
+
+%% Read from table specifications and calculate the widths of row and border
+%% column outer width = content width + colsep width + border width
+%% #1: the column number, #2: outer width, #3: border width
+\cs_new_protected:Npn \__tblr_get_col_outer_width_border_width:nNN #1 #2 #3
+ {
+ \dim_set:Nn #3
+ { \__tblr_prop_item:ne {vline} { [\int_eval:n {#1 + 1}] / @vline-width } }
+ \dim_set:Nn #2
+ {
+ \__tblr_prop_item:ne {vline} { [#1] / @vline-width }
+ +
+ \__tblr_prop_item:ne {column} { [#1] / leftsep }
+ +
+ \__tblr_prop_item:ne {column} { [#1] / @col-width }
+ +
+ \__tblr_prop_item:ne {column} { [#1] / rightsep }
+ +
+ #3
+ }
+ }
+
+\dim_new:N \l__tblr_row_ht_dim
+\dim_new:N \l__tblr_row_dp_dim
+\dim_new:N \l__tblr_row_abovesep_dim
+\dim_new:N \l__tblr_row_belowsep_dim
+
+%% Build current row, #1: row number
+\cs_new_protected:Npn \__tblr_build_row:N #1
+ {
+ \__tblr_get_row_inner_height_depth:VNNNN #1
+ \l__tblr_row_ht_dim \l__tblr_row_dp_dim
+ \l__tblr_row_abovesep_dim \l__tblr_row_belowsep_dim
+ \vrule width ~ 0pt ~ height ~ \l__tblr_row_ht_dim ~ depth ~ \l__tblr_row_dp_dim
+ \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
+ {
+ \__tblr_build_vline_segment:nn {#1} { \l__tblr_j_tl }
+ \__tblr_build_cell:NN #1 \l__tblr_j_tl
+ }
+ \__tblr_build_vline_segment:nn {#1} { \int_eval:n {\c@colcount + 1} }
+ }
+
+%% Read from table specifications and calculate inner height/depth of the row
+%% inner height = abovesep + above vspace + row upper
+%% inner depth = row lower + below vspace + belowsep
+%% #1: the row number; #2: resulting inner height; #3: resulting inner depth;
+%% #4: restulting abovesep; #5: restulting belowsep.
+
+\dim_new:N \l__row_upper_dim
+\dim_new:N \l__row_lower_dim
+\dim_new:N \l__row_vpace_dim
+
+\cs_new_protected:Npn \__tblr_get_row_inner_height_depth:nNNNN #1 #2 #3 #4 #5
+ {
+ \dim_set:Nn #4
+ { \__tblr_prop_item:ne { row } { [#1] / abovesep } }
+ \dim_set:Nn #5
+ { \__tblr_prop_item:ne { row } { [#1] / belowsep } }
+ \dim_set:Nn \l__row_upper_dim
+ { \__tblr_prop_item:ne { row } { [#1] / @row-upper } }
+ \dim_set:Nn \l__row_lower_dim
+ { \__tblr_prop_item:ne { row } { [#1] / @row-lower } }
+ \dim_set:Nn \l__row_vpace_dim
+ {
+ ( \__tblr_prop_item:ne { row } { [#1] / @row-height }
+ - \l__row_upper_dim - \l__row_lower_dim ) / 2
+ }
+ \dim_set:Nn #2 { #4 + \l__row_vpace_dim + \l__row_upper_dim }
+ \dim_set:Nn #3 { \l__row_lower_dim + \l__row_vpace_dim + #5 }
+ }
+\cs_generate_variant:Nn \__tblr_get_row_inner_height_depth:nNNNN { V }
+
+%% #1: row number, #2: column number
+\cs_new_protected:Npn \__tblr_build_vline_segment:nn #1 #2
+ {
+ \tl_set:Nx \l__tblr_n_tl
+ { \__tblr_prop_item:ne { vline } { [#2] / @vline-count } }
+ \tl_set:Nx \l__tblr_o_tl
+ { \__tblr_prop_item:ne { vline } { [#1][#2] / omit } }
+ \tl_if_empty:NTF \l__tblr_o_tl
+ {
+ \tl_if_empty:NF \l__tblr_n_tl
+ { \__tblr_build_vline_segment_real:nn {#1} {#2} }
+ }
+ { \__tblr_build_vline_segment_omit:nn {#1} {#2} }
+ }
+
+%% #1: row number, #2: column number
+\cs_new_protected:Npn \__tblr_build_vline_segment_omit:nn #1 #2
+ {
+ \tl_set:Nx \l__tblr_w_tl
+ { \__tblr_prop_item:ne { vline } { [#2] / @vline-width } }
+ \skip_horizontal:N \l__tblr_w_tl
+ }
+
+%% #1: row number, #2: column number
+%% We make every vline segment intersect with first hline below
+%% to remove gaps in vlines around multirow cells
+\cs_new_protected:Npn \__tblr_build_vline_segment_real:nn #1 #2
+ {
+ \tl_set:Nx \l__tblr_s_tl
+ { \__tblr_prop_item:ne { vline } { [#2] / rulesep } }
+ \tl_set:Nx \l__tblr_b_tl
+ {
+ \__tblr_prop_item:ne { hline }
+ { [\int_eval:n{#1 + 1}](1) / @hline-height }
+ }
+ \tl_if_empty:NT \l__tblr_b_tl { \tl_set:Nn \l__tblr_b_tl { 0pt } }
+ \hbox_set:Nn \l__tblr_a_box
+ {
+ \int_step_inline:nn { \l__tblr_n_tl }
+ {
+ \tl_set:Nx \l__tblr_w_tl
+ { \__tblr_prop_item:ne { vline } { [#2](##1) / @vline-width } }
+ \vbox_set_to_ht:Nnn \l__tblr_b_box
+ { \dim_eval:n { \l__tblr_row_ht_dim + \l__tblr_row_dp_dim } }
+ {
+ \tl_set:Nx \l__tblr_f_tl
+ { \__tblr_prop_item:ne { vline } { [#1][#2](##1) / fg } }
+ \tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} }
+ \__tblr_get_vline_segment_child:nnnxx {#1} {#2} {##1}
+ { \dim_eval:n { \l__tblr_row_ht_dim } }
+ { \dim_eval:n { \l__tblr_row_dp_dim + \l__tblr_b_tl } }
+ \skip_vertical:n { - \l__tblr_b_tl }
+ }
+ \box_set_wd:Nn \l__tblr_b_box { \l__tblr_w_tl }
+ \box_use:N \l__tblr_b_box
+ \skip_horizontal:n { \l__tblr_s_tl }
+ }
+ \skip_horizontal:n { - \l__tblr_s_tl }
+ }
+ \vbox_set:Nn \l__tblr_c_box { \box_use:N \l__tblr_a_box }
+ \box_set_ht:Nn \l__tblr_c_box { \dim_use:N \l__tblr_row_ht_dim }
+ \box_set_dp:Nn \l__tblr_c_box { \dim_use:N \l__tblr_row_dp_dim }
+ \box_use:N \l__tblr_c_box
+ }
+
+\tl_new:N \l__tblr_cell_rowspan_tl
+\tl_new:N \l__tblr_cell_colspan_tl
+\dim_new:N \l__tblr_cell_wd_dim
+\dim_new:N \l__tblr_cell_ht_dim
+
+\cs_new_protected:Npn \__tblr_build_cell:NN #1 #2
+ {
+ \int_set:Nn \c@rownum {#1}
+ \int_set:Nn \c@colnum {#2}
+ \group_begin:
+ \tl_set:Nx \l__tblr_w_tl
+ { \__tblr_prop_item:ne { column } { [#2] / @col-width } }
+ \tl_set:Nx \l__tblr_h_tl
+ { \__tblr_prop_item:ne { row } { [#1] / @row-height } }
+ \tl_set:Nx \l__tblr_x_tl
+ { \__tblr_prop_item:ne { column } { [#2] / leftsep} }
+ \tl_set:Nx \l__tblr_y_tl
+ { \__tblr_prop_item:ne { column } { [#2] / rightsep } }
+ \tl_set:Nx \l__tblr_cell_colspan_tl
+ { \__tblr_prop_item:ne { cell } { [#1][#2] / colspan } }
+ \tl_if_empty:NTF \l__tblr_cell_colspan_tl
+ { \dim_set:Nn \l__tblr_cell_wd_dim { \l__tblr_w_tl } }
+ {
+ \__tblr_get_span_horizontal_sizes:NNNNN #1 #2
+ \l__tblr_o_dim \l__tblr_cell_wd_dim \l__tblr_q_dim
+ }
+ \tl_set:Nx \l__tblr_cell_rowspan_tl
+ { \__tblr_prop_item:ne { cell } { [#1][#2] / rowspan } }
+ \tl_if_empty:NTF \l__tblr_cell_rowspan_tl
+ { \dim_set:Nn \l__tblr_cell_ht_dim { \l__tblr_h_tl } }
+ {
+ \__tblr_get_span_vertical_sizes:NNNNN #1 #2
+ \l__tblr_r_dim \l__tblr_cell_ht_dim \l__tblr_t_dim
+ }
+ \__tblr_get_cell_alignments:nn {#1} {#2}
+ \__tblr_build_cell_background:NN #1 #2
+ \__tblr_build_cell_content:NN #1 #2
+ \group_end:
+ }
+
+\cs_new_protected:Npn \__tblr_build_cell_content:NN #1 #2
+ {
+ \hbox_set_to_wd:Nnn \l__tblr_a_box { \l__tblr_cell_wd_dim }
+ {
+ \tl_if_eq:NnF \g__tblr_cell_halign_tl {l} { \hfil }
+ \__tblr_get_cell_text:nn {#1} {#2}
+ \tl_if_eq:NnF \g__tblr_cell_halign_tl {r} { \hfil }
+ }
+ \vbox_set_to_ht:Nnn \l__tblr_b_box { \l__tblr_cell_ht_dim }
+ {
+ \tl_case:Nn \g__tblr_cell_valign_tl
+ {
+ \c__tblr_valign_m_tl
+ {
+ \vfil
+ \tl_if_empty:NT \l__tblr_cell_rowspan_tl
+ {
+ \box_set_ht:Nn \l__tblr_a_box
+ { \__tblr_prop_item:ne { row } { [#1] / @row-upper } }
+ \box_set_dp:Nn \l__tblr_a_box
+ { \__tblr_prop_item:ne { row } { [#1] / @row-lower } }
+ }
+ \box_use:N \l__tblr_a_box
+ \vfil
+ }
+ \c__tblr_valign_h_tl
+ {
+ \box_set_ht:Nn \l__tblr_a_box
+ { \__tblr_prop_item:ne { row } { [#1] / @row-head } }
+ \box_use:N \l__tblr_a_box
+ \vfil
+ }
+ \c__tblr_valign_f_tl
+ {
+ \vfil
+ \tl_if_empty:NTF \l__tblr_cell_rowspan_tl
+ {
+ \box_set_dp:Nn \l__tblr_a_box
+ { \__tblr_prop_item:ne { row } { [#1] / @row-foot } }
+ }
+ {
+ \box_set_dp:Nn \l__tblr_a_box
+ {
+ \__tblr_prop_item:ne { row }
+ {
+ [\int_eval:n {#1 + \l__tblr_cell_rowspan_tl - 1}]
+ / @row-foot
+ }
+ }
+ }
+ \box_use:N \l__tblr_a_box
+ }
+ }
+ \hrule height ~ 0pt %% zero depth
+ }
+ \vbox_set_to_ht:Nnn \l__tblr_c_box
+ { \l__tblr_row_ht_dim - \l__tblr_row_abovesep_dim }
+ {
+ \box_use:N \l__tblr_b_box
+ \vss
+ }
+ \skip_horizontal:n { \l__tblr_x_tl }
+ \box_use:N \l__tblr_c_box
+ \skip_horizontal:n { \l__tblr_y_tl - \l__tblr_cell_wd_dim + \l__tblr_w_tl }
+ }
+
+\cs_new_protected:Npn \__tblr_build_cell_background:NN #1 #2
+ {
+ \__tblr_prop_if_in:nxF {cell} { [#1][#2] / omit }
+ {
+ \group_begin:
+ \tl_set:Nx \l__tblr_b_tl
+ { \__tblr_prop_item:ne { cell } { [#1][#2] / background } }
+ \tl_if_empty:NF \l__tblr_b_tl
+ {
+ \__tblr_get_cell_background_width:NNN #1 #2 \l_tmpa_dim
+ \__tblr_get_cell_background_depth:NNN #1 #2 \l_tmpb_dim
+ \__tblr_build_cell_background:nnnn
+ { \dim_use:N \l_tmpa_dim }
+ { \l__tblr_row_ht_dim }
+ { \dim_use:N \l_tmpb_dim }
+ { \l__tblr_b_tl }
+ }
+ \group_end:
+ }
+ }
+
+%% #1: row number; #2: column number; #3 resulting dimension
+\cs_new_protected:Npn \__tblr_get_cell_background_width:NNN #1 #2 #3
+ {
+ \tl_if_empty:NTF \l__tblr_cell_colspan_tl
+ { \dim_set:Nn #3 { \l__tblr_x_tl + \l__tblr_w_tl + \l__tblr_y_tl } }
+ {
+ \dim_set:Nn #3 { \l__tblr_o_dim + \l__tblr_cell_wd_dim + \l__tblr_q_dim }
+ }
+ }
+
+%% #1: row number; #2: column number; #3 resulting dimension
+\cs_new_protected:Npn \__tblr_get_cell_background_depth:NNN #1 #2 #3
+ {
+ \tl_if_empty:NTF \l__tblr_cell_rowspan_tl
+ { \dim_set_eq:NN #3 \l__tblr_row_dp_dim }
+ {
+ \dim_set:Nn #3
+ {
+ \l__tblr_r_dim + \l__tblr_cell_ht_dim
+ + \l__tblr_t_dim - \l__tblr_row_ht_dim
+ }
+ }
+ }
+
+%% #1: width, #2: height, #3: depth, #4: color
+\cs_new_protected:Npn \__tblr_build_cell_background:nnnn #1 #2 #3 #4
+ {
+ \hbox_set:Nn \l__tblr_a_box
+ {
+ \color {#4}
+ \vrule width ~ #1 ~ height ~ #2 ~ depth ~ #3
+ }
+ \box_set_dp:Nn \l__tblr_a_box { 0pt }
+ \box_use:N \l__tblr_a_box
+ \skip_horizontal:n { - #1 }
+ }
+
+%% #1: row number; #2: column number; #3: dimen register for rowsep above.
+%% #4: dimen register for total height; #5: dimen register for rowsep below.
+%% We can use \l__tblr_row_item_skip_size_prop which was made before
+\cs_new_protected:Npn \__tblr_get_span_vertical_sizes:NNNNN #1 #2 #3 #4 #5
+ {
+ \dim_set:Nn #3
+ { \__tblr_prop_item:ne { row } { [#1] / abovesep } }
+ \dim_zero:N #4
+ \int_step_inline:nnn { #1 } { #1 + \l__tblr_cell_rowspan_tl - 2 }
+ {
+ \dim_add:Nn #4
+ { \prop_item:Ne \l__tblr_row_item_skip_size_prop { itemskip[##1] } }
+ }
+ \dim_add:Nn #4
+ {
+ \prop_item:Ne \l__tblr_row_item_skip_size_prop
+ { item[\int_eval:n { #1 + \l__tblr_cell_rowspan_tl - 1 }] }
+ }
+ \dim_set:Nn #5
+ {
+ \__tblr_prop_item:ne { row }
+ { [\int_eval:n {#1 + \l__tblr_cell_rowspan_tl - 1}] / belowsep }
+ }
+ %\tl_log:x { cell[#1][#2] ~:~ \dim_use:N #3, \dim_use:N #4, \dim_use:N #5 }
+ }
+
+%% #1: row number; #2: column number; #3: dimen register for colsep left.
+%% #4: dimen register for total width; #5: dimen register for colsep right.
+%% We can use \l__tblr_col_item_skip_size_prop which was made before
+%% But when hspan=minimal, there are no itemskip in the prop list.
+%% Therefore we need to calculate them from the sizes of items and skips
+\cs_new_protected:Npn \__tblr_get_span_horizontal_sizes:NNNNN #1 #2 #3 #4 #5
+ {
+ \dim_set:Nn #3
+ { \__tblr_prop_item:ne { column } { [#2] / leftsep} }
+ \dim_zero:N #4
+ \int_step_inline:nnn { #2 } { #2 + \l__tblr_cell_colspan_tl - 2 }
+ {
+ \dim_add:Nn #4
+ { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] } }
+ \dim_add:Nn #4
+ {
+ \prop_item:Ne \l__tblr_col_item_skip_size_prop
+ { skip[\int_eval:n { ##1 + 1 }] }
+ }
+ }
+ \dim_add:Nn #4
+ {
+ \prop_item:Ne \l__tblr_col_item_skip_size_prop
+ { item[\int_eval:n { #2 + \l__tblr_cell_colspan_tl - 1 }] }
+ }
+ \dim_set:Nn #5
+ {
+ \__tblr_prop_item:ne { column }
+ { [\int_eval:n {#2 + \l__tblr_cell_colspan_tl - 1}] / rightsep }
+ }
+ %\tl_log:x { cell[#1][#2] ~:~ \dim_use:N #3, \dim_use:N #4, \dim_use:N #5 }
+ }
+
+%%% --------------------------------------------------------
+%% \section{Tracing Tabularray}
+%%% --------------------------------------------------------
+
+\NewDocumentCommand \SetTabularrayTracing { m }
+ {
+ \keys_set:nn { tblr-set-tracing } {#1}
+ }
+\cs_new_eq:NN \SetTblrTracing \SetTabularrayTracing
+
+\bool_new:N \g__tblr_tracing_text_bool
+\bool_new:N \g__tblr_tracing_command_bool
+\bool_new:N \g__tblr_tracing_table_bool
+\bool_new:N \g__tblr_tracing_column_bool
+\bool_new:N \g__tblr_tracing_row_bool
+\bool_new:N \g__tblr_tracing_cell_bool
+\bool_new:N \g__tblr_tracing_vline_bool
+\bool_new:N \g__tblr_tracing_hline_bool
+\bool_new:N \g__tblr_tracing_colspec_bool
+\bool_new:N \g__tblr_tracing_rowspec_bool
+\bool_new:N \g__tblr_tracing_target_bool
+\bool_new:N \g__tblr_tracing_cellspan_bool
+
+\keys_define:nn { tblr-set-tracing }
+ {
+ +text .code:n = \bool_gset_true:N \g__tblr_tracing_text_bool,
+ -text .code:n = \bool_gset_false:N \g__tblr_tracing_text_bool,
+ +command .code:n = \bool_gset_true:N \g__tblr_tracing_command_bool,
+ -command .code:n = \bool_gset_false:N \g__tblr_tracing_command_bool,
+ +table .code:n = \bool_gset_true:N \g__tblr_tracing_table_bool,
+ -table .code:n = \bool_gset_false:N \g__tblr_tracing_table_bool,
+ +column .code:n = \bool_gset_true:N \g__tblr_tracing_column_bool,
+ -column .code:n = \bool_gset_false:N \g__tblr_tracing_column_bool,
+ +row .code:n = \bool_gset_true:N \g__tblr_tracing_row_bool,
+ -row .code:n = \bool_gset_false:N \g__tblr_tracing_row_bool,
+ +cell .code:n = \bool_gset_true:N \g__tblr_tracing_cell_bool,
+ -cell .code:n = \bool_gset_false:N \g__tblr_tracing_cell_bool,
+ +vline .code:n = \bool_gset_true:N \g__tblr_tracing_vline_bool,
+ -vline .code:n = \bool_gset_false:N \g__tblr_tracing_vline_bool,
+ +hline .code:n = \bool_gset_true:N \g__tblr_tracing_hline_bool,
+ -hline .code:n = \bool_gset_false:N \g__tblr_tracing_hline_bool,
+ +colspec .code:n = \bool_gset_true:N \g__tblr_tracing_colspec_bool,
+ -colspec .code:n = \bool_gset_false:N \g__tblr_tracing_colspec_bool,
+ +rowspec .code:n = \bool_gset_true:N \g__tblr_tracing_rowspec_bool,
+ -rowspec .code:n = \bool_gset_false:N \g__tblr_tracing_rowspec_bool,
+ +target .code:n = \bool_gset_true:N \g__tblr_tracing_target_bool,
+ -target .code:n = \bool_gset_false:N \g__tblr_tracing_target_bool,
+ +cellspan .code:n = \bool_gset_true:N \g__tblr_tracing_cellspan_bool,
+ -cellspan .code:n = \bool_gset_false:N \g__tblr_tracing_cellspan_bool,
+ all .code:n = \__tblr_enable_all_tracings:,
+ none .code:n = \__tblr_disable_all_tracings:,
+ }
+
+\cs_new_protected_nopar:Npn \__tblr_enable_all_tracings:
+ {
+ \bool_gset_true:N \g__tblr_tracing_text_bool
+ \bool_gset_true:N \g__tblr_tracing_command_bool
+ \bool_gset_true:N \g__tblr_tracing_table_bool
+ \bool_gset_true:N \g__tblr_tracing_column_bool
+ \bool_gset_true:N \g__tblr_tracing_row_bool
+ \bool_gset_true:N \g__tblr_tracing_cell_bool
+ \bool_gset_true:N \g__tblr_tracing_vline_bool
+ \bool_gset_true:N \g__tblr_tracing_hline_bool
+ \bool_gset_true:N \g__tblr_tracing_colspec_bool
+ \bool_gset_true:N \g__tblr_tracing_rowspec_bool
+ \bool_gset_true:N \g__tblr_tracing_target_bool
+ \bool_gset_true:N \g__tblr_tracing_cellspan_bool
+ }
+
+\cs_new_protected_nopar:Npn \__tblr_disable_all_tracings:
+ {
+ \bool_gset_false:N \g__tblr_tracing_text_bool
+ \bool_gset_false:N \g__tblr_tracing_command_bool
+ \bool_gset_false:N \g__tblr_tracing_table_bool
+ \bool_gset_false:N \g__tblr_tracing_column_bool
+ \bool_gset_false:N \g__tblr_tracing_row_bool
+ \bool_gset_false:N \g__tblr_tracing_cell_bool
+ \bool_gset_false:N \g__tblr_tracing_vline_bool
+ \bool_gset_false:N \g__tblr_tracing_hline_bool
+ \bool_gset_false:N \g__tblr_tracing_colspec_bool
+ \bool_gset_false:N \g__tblr_tracing_rowspec_bool
+ \bool_gset_false:N \g__tblr_tracing_target_bool
+ \bool_gset_false:N \g__tblr_tracing_cellspan_bool
+ }
+
+\NewDocumentCommand \LogTabularrayTracing { m }
+ {
+ \keys_set:nn { tblr-log-tracing } {#1}
+ }
+\cs_new_eq:NN \LogTblrTracing \LogTabularrayTracing
+
+\keys_define:nn { tblr-log-tracing }
+ {
+ unknown .code:n = \__tblr_log_tracing:N \l_keys_key_str
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing:N #1
+ {
+ \bool_if:cT { g__tblr_tracing_ #1 _bool }
+ { \cs:w __tblr_log_tracing _ #1 : \cs_end: }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_text:
+ {
+ \__tblr_prop_log:n { text }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_command:
+ {
+ \__tblr_prop_log:n { command }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_table:
+ {
+ \__tblr_prop_log:n { table }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_column:
+ {
+ \__tblr_prop_log:n { column }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_row:
+ {
+ \__tblr_prop_log:n { row }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_cell:
+ {
+ \__tblr_prop_log:n { cell }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_vline:
+ {
+ \__tblr_prop_log:n { vline }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_hline:
+ {
+ \__tblr_prop_log:n { hline }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_colspec:
+ {
+ \tl_if_eq:NnT \g__tblr_column_or_row_tl { column }
+ { \tl_log:N \g__tblr_expanded_colrow_spec_tl }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_rowspec:
+ {
+ \tl_if_eq:NnT \g__tblr_column_or_row_tl { row }
+ { \tl_log:N \g__tblr_expanded_colrow_spec_tl }
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_target:
+ {
+ \dim_log:N \l__column_target_dim
+ \prop_log:N \l__column_coefficient_prop
+ \prop_log:N \l__column_natural_width_prop
+ \prop_log:N \l__column_computed_width_prop
+ }
+
+\cs_new_protected:Npn \__tblr_log_tracing_cellspan:
+ {
+ \prop_log:N \l__tblr_col_item_skip_size_prop
+ \prop_log:N \l__tblr_col_span_size_prop
+ \prop_log:N \l__tblr_row_item_skip_size_prop
+ \prop_log:N \l__tblr_row_span_size_prop
+ \prop_log:N \l__tblr_row_span_to_row_prop
+ }
+
+\cs_new_protected:Npn \__tblr_do_if_tracing:nn #1 #2
+ {
+ \bool_if:cT { g__tblr_tracing_ #1 _bool } {#2}
+ }
+
+\ExplSyntaxOff
+
diff --git a/macros/latex/contrib/tabularray/tabularray.tex b/macros/latex/contrib/tabularray/tabularray.tex
new file mode 100644
index 0000000000..41aa2ab9f6
--- /dev/null
+++ b/macros/latex/contrib/tabularray/tabularray.tex
@@ -0,0 +1,751 @@
+% -*- coding: utf-8 -*-
+\documentclass[oneside]{book}
+\usepackage[a4paper,margin=2.5cm]{geometry}
+
+\usepackage{codehigh} % https://github.com/lvjr/codehigh
+%\usepackage{arev}
+\usepackage{tabularray}
+\usepackage{array,multirow,amsmath}
+
+\usepackage{hyperref}
+\hypersetup{
+ colorlinks=true,
+ urlcolor=blue3,
+ linkcolor=red3,
+}
+\renewcommand*{\thefootnote}{*}
+
+\newcommand*{\myversion}{2021H}
+\newcommand*{\mydate}{Version \myversion\ (\the\year-\mylpad\month-\mylpad\day)\\\myrepo}
+\newcommand*{\myrepo}{\url{https://github.com/lvjr/tabularray}}
+\newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
+
+\colorlet{highback}{\ifcase\month\or
+ red9\or brown9\or yellow9\or cyan9\or azure9\or blue9\or
+ red9\or brown9\or yellow9\or cyan9\or azure9\or blue9\fi
+}
+\CodeHigh{language=latex/table,style/main=highback,style/code=highback}
+\NewCodeHighEnv{code}{style/main=gray9,style/code=gray9}
+\NewCodeHighEnv{demo}{style/main=gray9,style/code=gray9,demo}
+
+%\CodeHigh{lite}
+
+\begin{document}
+
+\title{\sffamily\color{red3}Tabularray: Typeset Tabulars and Arrays with \LaTeX3}
+\author{Jianrui Lyu (tolvjr@163.com)}
+\date{\mydate}
+\maketitle
+
+\tableofcontents
+
+\chapter{From Old to New}
+
+\section{Vertical Space}
+
+After loading \verb!tabularrray! package in the preamble,
+we can use \verb!tblr! environments to typeset tabulars and arrays.
+The name \verb!tblr! is short for \verb!tabularray! or \verb!top-bottom-left-right!.
+The following is our first example:
+
+\begin{demo}
+\begin{tabular}{lccr}
+\hline
+ Alpha & Beta & Gamma & Delta \\
+\hline
+ Epsilon & Zeta & Eta & Theta \\
+\hline
+ Iota & Kappa & Lambda & Mu \\
+\hline
+\end{tabular}
+\end{demo}
+
+\begin{demohigh}
+\begin{tblr}{lccr}
+\hline
+ Alpha & Beta & Gamma & Delta \\
+\hline
+ Epsilon & Zeta & Eta & Theta \\
+\hline
+ Iota & Kappa & Lambda & Mu \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+You may notice that there is extra space above and below the table rows with \verb!tblr! envirenment.
+This space makes the table look better.
+If you don't like it, you could use \verb!\SetTblrDefault! command:
+
+\begin{demohigh}
+\SetTblrDefault{rowsep=0pt}
+\begin{tblr}{lccr}
+\hline
+ Alpha & Beta & Gamma & Delta \\
+\hline
+ Epsilon & Zeta & Eta & Theta \\
+\hline
+ Iota & Kappa & Lambda & Mu \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+But in many cases, this rowsep is useful:
+
+\begin{demo}
+$\begin{array}{rrr}
+\hline
+ \dfrac{2}{3} & \dfrac{2}{3} & \dfrac{1}{3} \\
+ \dfrac{2}{3} & -\dfrac{1}{3} & -\dfrac{2}{3} \\
+ \dfrac{1}{3} & -\dfrac{2}{3} & \dfrac{2}{3} \\
+\hline
+\end{array}$
+\end{demo}
+
+\begin{demohigh}
+$\begin{tblr}{rrr}
+\hline
+ \dfrac{2}{3} & \dfrac{2}{3} & \dfrac{1}{3} \\
+ \dfrac{2}{3} & -\dfrac{1}{3} & -\dfrac{2}{3} \\
+ \dfrac{1}{3} & -\dfrac{2}{3} & \dfrac{2}{3} \\
+\hline
+\end{tblr}$
+\end{demohigh}
+
+Note that you can use \verb!tblr! in both text and math modes.
+
+\section{Multiline Cells}
+
+It's quite easy to write multiline cells without fixing the column width in \verb!tblr! environments:
+just enclose the cell text with braces and use \verb!\\! to break lines:
+
+\begin{demohigh}
+\begin{tblr}{|l|c|r|}
+\hline
+ Left & {Center \\ Cent \\ C} & {Right \\ R} \\
+\hline
+ {L \\ Left} & {C \\ Cent \\ Center} & R \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+\section{Cell Alignment}
+
+From time to time,
+you may want to specify the horizontal and vertical alignment of cells at the same time.
+\verb!Tabularray! package provides a \verb!Q! column for this
+(In fact, \verb!Q! column is the only primitive column,
+other columns are defined as \verb!Q! columns with some options):
+
+\begin{demohigh}
+\begin{tblr}{|Q[l,t]|Q[c,m]|Q[r,b]|}
+\hline
+ {Top Baseline \\ Left Left} & Middle Center & {Right Right \\ Bottom Baseline} \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+Note that you can use more meaningful \verb!t! instead of \verb!p! for top baseline alignment.
+For some users who are familiar with word processors,
+these \verb!t! and \verb!b! columns are counter-intuitive.
+In \verb!tabularray! package, there are another two column types \verb!h! and \verb!f!,
+which will align cell text at row head and row foot, respectively:
+
+\begin{demohigh}
+\begin{tblr}{Q[h,4em]Q[t,4em]Q[m,4em]Q[b,4em]Q[f,4em]}
+\hline
+ {row\\head} & {top\\line} & {middle} & {line\\bottom} & {row\\foot} \\
+\hline
+ {row\\head} & {top\\line} & {11\\22\\mid\\44\\55} & {line\\bottom} & {row\\foot} \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+\section{Multirow Cells}
+
+The above \verb!h! and \verb!f! columns are necessary for multirow cells.
+In \verb!tabularray!, the \verb!t! and \verb!b! in the optional argument of \verb!\multirow! commands
+will be treated as \verb!h! and \verb!f!, respectively:
+
+\begin{demo}
+\begin{tabular}{|l|l|l|l|}
+\hline
+ \multirow[t]{4}{1.5cm}{Multirow Cell One} & Alpha &
+ \multirow[b]{4}{1.5cm}{Multirow Cell Two} & Alpha \\
+ & Beta & & Beta \\
+ & Gamma & & Gamma \\
+ & Delta & & Delta \\
+\hline
+\end{tabular}
+\end{demo}
+
+\begin{demohigh}
+\begin{tblr}{|l|l|l|l|}
+\hline
+ \multirow[t]{4}{1.5cm}{Multirow Cell One} & Alpha &
+ \multirow[b]{4}{1.5cm}{Multirow Cell Two} & Alpha \\
+ & Beta & & Beta \\
+ & Gamma & & Gamma \\
+ & Delta & & Delta \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+Note that you don't need to load \verb!multirow! package first,
+since \verb!tabularrray! doesn't depend on it.
+Furthermore, \verb!tabularray! will always typeset descent multirow cells.
+First, it will set correct vertical \verb!c! alignment,
+even though some rows have large height:
+
+\begin{demo}
+\begin{tabular}{|l|m{4em}|}
+\hline
+ \multirow[c]{4}{1.5cm}{Multirow} & Alpha \\
+ & Beta \\
+ & Gamma \\
+ & Delta Delta Delta \\
+\hline
+\end{tabular}
+\end{demo}
+
+\begin{demohigh}
+\begin{tblr}{|l|m{4em}|}
+\hline
+ \multirow[c]{4}{1.5cm}{Multirow} & Alpha \\
+ & Beta \\
+ & Gamma \\
+ & Delta Delta Delta \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+Second, it will enlarge row heights if the multirow cells have large height,
+therefore it always avoids vertical overflow:
+
+\begin{demo}
+\begin{tabular}{|l|m{4em}|}
+\hline
+ \multirow[c]{2}{1cm}{Line \\ Line \\ Line \\ Line} & Alpha \\
+\cline{2-2}
+ & Beta \\
+\hline
+\end{tabular}
+\end{demo}
+
+\begin{demohigh}
+\begin{tblr}{|l|m{4em}|}
+\hline
+ \multirow[c]{2}{1cm}{Line \\ Line \\ Line \\ Line} & Alpha \\
+\cline{2}
+ & Beta \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+\section{Multi Rows and Columns}
+
+It was a hard job to typeset cells with multiple rows and multiple columns. For example:
+
+\begin{demo}
+\begin{tabular}{|c|c|c|c|c|}
+\hline
+ \multirow{2}{*}{2 Rows}
+ & \multicolumn{2}{c|}{2 Columns}
+ & \multicolumn{2}{c|}{\multirow{2}{*}{2 Rows 2 Columns}} \\
+\cline{2-3}
+  & 2-2 & 2-3 & \multicolumn{2}{c|}{} \\
+\hline
+ 3-1 & 3-2 & 3-3 & 3-4 & 3-5 \\
+\hline
+\end{tabular}
+\end{demo}
+
+With \verb!tabularray! package, you can set spanned cells with \verb!\SetCell! command:
+within the optional argument of \verb!\SetCell! command,
+option \verb!r! is for rowspan number, and \verb!c! for colspan number;
+within the mandatory argument of it, horizontal and vertical alignment options are accepted.
+Therefore it's much simpler to typeset spanned cells:
+
+\begin{demohigh}
+\begin{tblr}{|c|c|c|c|c|}
+\hline
+ \SetCell[r=2]{c} 2 Rows
+ & \SetCell[c=2]{c} 2 Columns
+ & & \SetCell[r=2,c=2]{c} 2 Rows 2 Columns & \\
+\hline
+  & 2-2 & 2-3 & & \\
+\hline
+ 3-1 & 3-2 & 3-3 & 3-4 & 3-5 \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+Using \verb!\multicolumn! command, the omitted cells \textcolor{red3}{must} be removed.
+On the contrary,
+using \verb!\multirow! command, the omitted cells \textcolor{red3}{must not} be removed.
+\verb!\SetCell! command behaves the same as \verb!\multirow! command in this aspect.
+
+With \verb!tblr! environment, any \verb!\hline! segments inside a spanned cell will be ignored,
+therefore we're free to use \verb!\hline! in the above example.
+Also, any omitted cell will definitely be ignored when typesetting,
+no matter it's empty or not.
+With this feature, we could put row and column numbers into the omitted cells,
+which will help us to locate cells when the tables are rather complex:
+
+\begin{demohigh}
+\begin{tblr}{|ll|c|rr|}
+\hline
+ \SetCell[r=3,c=2]{h} r=3 c=2 & 1-2 & \SetCell[r=2,c=3]{r} r=2 c=3 & 1-4 & 1-5 \\
+ 2-1 & 2-2 & 2-3 & 2-4 & 2-5 \\
+\hline
+ 3-1 & 3-2 & MIDDLE & \SetCell[r=3,c=2]{f} r=3 c=2 & 3-5 \\
+\hline
+ \SetCell[r=2,c=3]{l} r=2 c=3 & 4-2 & 4-3 & 4-4 & 4-5 \\
+ 5-1 & 5-2 & 5-3 & 5-4 & 5-5 \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+\section{Column Types}
+
+\verb!Tabularray! package supports all normal column types, as well as
+the extendable \verb!X! column type,
+which first occured in \verb!tabularx! package and was largely improved by \verb!tabu! package:
+
+\begin{demohigh}
+\begin{tblr}{|X[2,l]|X[3,l]|X[1,r]|X[r]|}
+\hline
+ Alpha & Beta & Gamma & Delta \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+Also, \verb!X! columns with negative coefficients are possible:
+
+\begin{demohigh}
+\begin{tblr}{|X[2,l]|X[3,l]|X[-1,r]|X[r]|}
+\hline
+ Alpha & Beta & Gamma & Delta \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+We need the width to typeset a table with \verb!X! columns.
+If unset, the default is \verb!\linewidth!.
+To change the width, we have to first put all column specifications into \verb!colspec={...}!:
+
+\begin{demohigh}
+\begin{tblr}{width=0.8\linewidth,colspec={|X[2,l]|X[3,l]|X[-1,r]|X[r]|}}
+\hline
+ Alpha & Beta & Gamma & Delta \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+You can define new column types with \verb!\NewColumnType! command.
+For example, in \verb!tabularray! package,
+\verb!b! and \verb!X! columns are defined as special \verb!Q! columns:
+\begin{codehigh}
+\NewColumnType{b}[1]{Q[b,wd=#1]}
+\NewColumnType{X}[1][]{Q[co=1,#1]}
+\end{codehigh}
+
+\section{Row Types}
+
+Now that we have column types and \verb!colspec! option,
+you may ask for row types and \verb!rowspec! option.
+Yes, they are here:
+
+\begin{demohigh}
+\begin{tblr}{colspec={Q[l]Q[c]Q[r]},rowspec={|Q[t]|Q[m]|Q[b]|}}
+ {Alpha \\ Alpha} & Beta & Gamma \\
+ Delta & Epsilon & {Zeta \\ Zeta} \\
+ Eta & {Theta \\ Theta} & Iota \\
+\end{tblr}
+\end{demohigh}
+
+Same as column types, \verb!Q! is the only primitive row type,
+and other row types are defined as \verb!Q! types with different options.
+It's better to specify horizontal alignment in \verb!colspec!,
+and vertical alignment in \verb!rowspec!, respectively.
+
+Inside \verb!rowspec!, \verb!|! is the hline type.
+Therefore we need not to write \verb!\hline! commnad, which makes table code cleaner.
+
+\section{Hlines and Vlines}
+
+Hlines and vlines have been improved too. You can specify the widths and styles of them:
+
+\begin{demohigh}
+\begin{tblr}{|l|[dotted]|[2pt]c|r|[solid]|[dashed]|}
+\hline
+One & Two & Three \\
+\hline\hline[dotted]\hline
+Four & Five & Six \\
+\hline[dashed]\hline[1pt]
+Seven & Eight & Nine \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+\section{Colorful Tables}
+
+To add colors to your tables, you need to load \verb!xcolor! package first.
+\verb!Tabularray! package will also load \verb!ninecolors! package for proper color contrast.
+First you can specify background option for \verb!Q! rows/columns inside \verb!rowspec!/\verb!colspec!:
+
+\begin{demohigh}
+\begin{tblr}{colspec={lcr},rowspec={|Q[cyan7]|Q[azure7]|Q[blue7]|}}
+ Alpha & Beta & Gamma \\
+ Epsilon & Zeta & Eta \\
+ Iota & Kappa & Lambda \\
+\end{tblr}
+\end{demohigh}
+
+\begin{demohigh}
+\begin{tblr}{colspec={Q[l,brown7]Q[c,yellow7]Q[r,olive7]},rowspec={|Q|Q|Q|}}
+ Alpha & Beta & Gamma \\
+ Epsilon & Zeta & Eta \\
+ Iota & Kappa & Lambda \\
+\end{tblr}
+\end{demohigh}
+
+Also you can use \verb!\SetRow! or \verb!\SetColumn! command to specify row or column colors:
+
+\begin{demohigh}
+\begin{tblr}{colspec={lcr},rowspec={|Q|Q|Q|}}
+ \SetRow{cyan7} Alpha & Beta & Gamma \\
+ \SetRow{azure7} Epsilon & Zeta & Eta \\
+ \SetRow{blue7} Iota & Kappa & Lambda \\
+\end{tblr}
+\end{demohigh}
+
+\begin{demohigh}
+\begin{tblr}{colspec={lcr},rowspec={|Q|Q|Q|}}
+ \SetColumn{brown7}
+ Alpha & \SetColumn{yellow7}
+ Beta & \SetColumn{olive7}
+ Gamma \\
+ Epsilon & Zeta & Eta \\
+ Iota & Kappa & Lambda \\
+\end{tblr}
+\end{demohigh}
+
+Hlines and vlines can also have colors:
+
+\begin{demohigh}
+\begin{tblr}{colspec={lcr},rowspec={|[2pt,green7]Q|[teal7]Q|[green7]Q|[3pt,teal7]}}
+ Alpha & Beta & Gamma \\
+ Epsilon & Zeta & Eta \\
+ Iota & Kappa & Lambda \\
+\end{tblr}
+\end{demohigh}
+
+\begin{demohigh}
+\begin{tblr}{colspec={|[2pt,violet5]l|[2pt,magenta5]c|[2pt,purple5]r|[2pt,red5]}}
+ Alpha & Beta & Gamma \\
+ Epsilon & Zeta & Eta \\
+ Iota & Kappa & Lambda \\
+\end{tblr}
+\end{demohigh}
+
+\section{New Table Commands}
+
+All commands which change the specifications of tables \textcolor{red3}{must} be defined with \verb!\NewTableCommand!.
+The following example demonstrates how to define similar rules as in \verb!booktabs! package:
+
+\begin{demohigh}
+\NewTableCommand\toprule{\hline[0.08em]}
+\NewTableCommand\midrule{\hline[0.05em]}
+\NewTableCommand\bottomrule{\hline[0.08em]}
+\begin{tblr}{llll}
+\toprule
+ Alpha & Beta & Gamma & Delta \\
+\midrule
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+\bottomrule
+\end{tblr}
+\end{demohigh}
+
+\chapter{New Interface}
+
+With \verb!tabularray! package, you can separate style and content totally in tables.
+
+\section{Hlines and Vlines}
+
+Options \verb!hlines! and \verb!vlines! are for setting all hlines and vlines, respectively.
+With empty value, all hlines/vlines will be solid.
+
+\begin{demohigh}
+\begin{tblr}{hlines,vlines}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+With values inside one pair of braces, all hlines/vlines will be styled.
+
+\begin{demohigh}
+\begin{tblr}{
+ hlines = {1pt,solid},
+ vlines = {red3,dashed},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+Another pair of braces before will select segments in all hlines/vlines.
+
+\begin{demohigh}
+\begin{tblr}{
+ vlines = {1,3,5}{dashed},
+ vlines = {2,4,6}{solid},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+The above example can be simplified with \verb!odd! and \verb!even! values.
+(More child selectors can be defined with \verb!\NewChildSelector! command.
+Advanced users could read the source code for this.)
+
+\begin{demohigh}
+\begin{tblr}{
+ vlines = {odd}{dashed},
+ vlines = {even}{solid},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+Another pair of braces before will draw more hlines/vlines (in which \verb!-! stands for all line segments).
+
+\begin{demohigh}
+\begin{tblr}{
+ hlines = {1}{-}{dashed},
+ hlines = {2}{-}{solid},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+Options \verb!hline{i}! and \verb!vline{j}! are for setting some hlines and vlines, respectively.
+
+\begin{demohigh}
+\begin{tblr}{
+ hline{1,7} = {1pt,solid},
+ hline{3-5} = {blue3,dashed},
+ vline{1,5} = {3-4}{dotted},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+\section{Cells and Spancells}
+
+Option \verb!cells! is for setting all cells.
+
+\begin{demohigh}
+\begin{tblr}{hlines={white},cells={c,blue7}}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+Option \verb!cell{i}{j}! is for setting some cells.
+
+\begin{demohigh}
+\begin{tblr}{
+ hlines = {white},
+ vlines = {white},
+ cell{1,6}{odd} = {teal7},
+ cell{1,6}{even} = {green7},
+ cell{2,4}{1,4} = {red7},
+ cell{3,5}{1,4} = {purple7},
+ cell{2}{2} = {r=4,c=2}{c,azure7},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+\section{Rows and Columns}
+
+Options \verb!rows! and \verb!columns! are for setting all rows and columns, respectively.
+
+\begin{demohigh}
+\begin{tblr}{
+ hlines,
+ vlines,
+ rows = {7mm},
+ columns = {15mm,c},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+\end{tblr}
+\end{demohigh}
+
+Options \verb!row{i}! and \verb!column{j}! are for setting some rows and columns, respectively.
+
+\begin{demohigh}
+\begin{tblr}{
+ hlines = {1pt,white},
+ row{odd} = {blue7},
+ row{even} = {azure7},
+ column{1} = {purple7,c},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+ Nu & Xi & Omicron & Pi \\
+ Rho & Sigma & Tau & Upsilon \\
+ Phi & Chi & Psi & Omega \\
+\end{tblr}
+\end{demohigh}
+
+\section{Space in Tables}
+
+Options \verb!rowsep! and \verb!colsep! are for setting padding for rows and columns, respectively.
+
+\begin{demohigh}
+\SetTblrDefault{rowsep=2pt,colsep=2pt}
+\begin{tblr}{hlines,vlines}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+\end{tblr}
+\end{demohigh}
+
+Also \verb!abovesep!, \verb!belowsep!, \verb!leftsep!, \verb!rightsep! options are available:
+
+\begin{demohigh}
+\begin{tblr}{
+ hlines,
+ vlines,
+ rows = {abovesep=1pt,belowsep=5pt},
+ columns = {leftsep=1pt,rightsep=5pt},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+\end{tblr}
+\end{demohigh}
+
+And \verb!\\[dimen]! can be replaced by \verb!belowsep+! option:
+
+\begin{demohigh}
+\begin{tblr}{
+ hlines, row{2} = {belowsep+=5pt},
+}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+\end{tblr}
+\end{demohigh}
+
+Also \verb!\arraystretch! parameter can be replaced by \verb!stretch! option:
+
+\begin{demohigh}
+\begin{tblr}{hlines,stretch=1.5}
+ Alpha & Beta & Gamma & Delta \\
+ Epsilon & Zeta & Eta & Theta \\
+ Iota & Kappa & Lambda & Mu \\
+\end{tblr}
+\end{demohigh}
+
+\section{Counters in Tables}
+
+Counters \verb!rownum!, \verb!colnum!, \verb!rowcount!, \verb!colcount! can be used in cell text:
+
+\begin{demohigh}
+\begin{tblr}{hlines}
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
+ Row=\arabic{rowcount}, Col=\arabic{colcount} &
+ Row=\arabic{rowcount}, Col=\arabic{colcount} &
+ Row=\arabic{rowcount}, Col=\arabic{colcount} &
+ Row=\arabic{rowcount}, Col=\arabic{colcount} \\
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
+\end{tblr}
+\end{demohigh}
+
+\section{Experimental Interface}
+
+Everything described in this section is in \underline{\textcolor{red3}{\textbf{experimental}}} status.
+Don’t use it in important documents, unless you have time
+to update them for the newer versions of \verb!tabularray! package in the future.
+
+By default \verb!tabularray! package will compute column widths from span widths.
+By setting option \verb!hspan=minimal!, it will compute span widths from column widths.
+The following two examples show this difference:
+
+\begin{demohigh}
+\SetTblrDefault{hlines,vlines}
+\begin{tblr}{cell{2}{1}={c=2}{l},cell{3}{1}={c=3}{l},cell{4}{2}={c=2}{l}}
+ 111 111 & 222 222 & 333 333 \\
+ 12 Multi Columns Multi Columns 12 & & 333 \\
+ 13 Multi Columns Multi Columns Multi Columns 13 & & \\
+ 111 & 23 Multi Columns Multi Columns 23 & \\
+\end{tblr}
+\end{demohigh}
+
+\begin{demohigh}
+\SetTblrDefault{hlines,vlines,hspan=minimal}
+\begin{tblr}{cell{2}{1}={c=2}{l},cell{3}{1}={c=3}{l},cell{4}{2}={c=2}{l}}
+ 111 111 & 222 222 & 333 333 \\
+ 12 Multi Columns Multi Columns 12 & & 333 \\
+ 13 Multi Columns Multi Columns Multi Columns 13 & & \\
+ 111 & 23 Multi Columns Multi Columns 23 & \\
+\end{tblr}
+\end{demohigh}
+
+\chapter{Source Code}
+
+%\CodeHigh{lite}
+\dochighinput[language=latex/latex3]{tabularray.sty}
+
+\end{document}