summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2024-06-02 20:26:39 +0000
committerKarl Berry <karl@freefriends.org>2024-06-02 20:26:39 +0000
commitb0c666dbd315af330424f5d34739d7d4134d0c17 (patch)
tree0b0a60149691348e9cea719bb797b2c1587adfc6 /Master/texmf-dist/source/latex
parent5634f0473d32ab71b4fbaaf0a6870737c2cc6dcb (diff)
latex2e (2jun24)
git-svn-id: svn://tug.org/texlive/trunk@71408 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex')
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsbsy.ins2
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amscd.dtx2
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amscd.ins4
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsgen.dtx2
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsgen.ins2
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsmath.dtx19
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsmath.ins4
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsopn.dtx2
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsopn.ins4
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amstext.dtx2
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amstext.ins4
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsxtra.dtx2
-rw-r--r--Master/texmf-dist/source/latex/amsmath/amsxtra.ins4
-rw-r--r--Master/texmf-dist/source/latex/base/alltt.dtx4
-rw-r--r--Master/texmf-dist/source/latex/base/classes.dtx12
-rw-r--r--Master/texmf-dist/source/latex/base/doc.dtx227
-rw-r--r--Master/texmf-dist/source/latex/base/docstrip.dtx14
-rw-r--r--Master/texmf-dist/source/latex/base/fontdef.dtx30
-rw-r--r--Master/texmf-dist/source/latex/base/format.ins6
-rw-r--r--Master/texmf-dist/source/latex/base/ifthen.dtx29
-rw-r--r--Master/texmf-dist/source/latex/base/inputenc.dtx6
-rw-r--r--Master/texmf-dist/source/latex/base/latexrelease.ins1
-rw-r--r--Master/texmf-dist/source/latex/base/ltboxes.dtx42
-rw-r--r--Master/texmf-dist/source/latex/base/ltclass.dtx160
-rw-r--r--Master/texmf-dist/source/latex/base/ltcmd.dtx241
-rw-r--r--Master/texmf-dist/source/latex/base/ltcmdhooks.dtx46
-rw-r--r--Master/texmf-dist/source/latex/base/ltcounts.dtx19
-rw-r--r--Master/texmf-dist/source/latex/base/ltdefns.dtx35
-rw-r--r--Master/texmf-dist/source/latex/base/ltdirchk.dtx31
-rw-r--r--Master/texmf-dist/source/latex/base/ltexpl.dtx16
-rw-r--r--Master/texmf-dist/source/latex/base/ltfilehook.dtx34
-rw-r--r--Master/texmf-dist/source/latex/base/ltfiles.dtx57
-rw-r--r--Master/texmf-dist/source/latex/base/ltfinal.dtx6
-rw-r--r--Master/texmf-dist/source/latex/base/ltfloat.dtx6
-rw-r--r--Master/texmf-dist/source/latex/base/ltfntcmd.dtx8
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssaxes.dtx10
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssbas.dtx4
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssini.dtx10
-rw-r--r--Master/texmf-dist/source/latex/base/ltfsstrc.dtx23
-rw-r--r--Master/texmf-dist/source/latex/base/lthooks.dtx405
-rw-r--r--Master/texmf-dist/source/latex/base/ltkeys.dtx2
-rw-r--r--Master/texmf-dist/source/latex/base/ltluatex.dtx26
-rw-r--r--Master/texmf-dist/source/latex/base/ltmarks.dtx811
-rw-r--r--Master/texmf-dist/source/latex/base/ltmeta.dtx20
-rw-r--r--Master/texmf-dist/source/latex/base/ltmiscen.dtx12
-rw-r--r--Master/texmf-dist/source/latex/base/ltoutenc.dtx25
-rw-r--r--Master/texmf-dist/source/latex/base/ltoutput.dtx4
-rw-r--r--Master/texmf-dist/source/latex/base/ltpara.dtx29
-rw-r--r--Master/texmf-dist/source/latex/base/ltplain.dtx20
-rw-r--r--Master/texmf-dist/source/latex/base/ltproperties.dtx75
-rw-r--r--Master/texmf-dist/source/latex/base/ltsect.dtx10
-rw-r--r--Master/texmf-dist/source/latex/base/ltshipout.dtx32
-rw-r--r--Master/texmf-dist/source/latex/base/ltsockets.dtx36
-rw-r--r--Master/texmf-dist/source/latex/base/ltspace.dtx12
-rw-r--r--Master/texmf-dist/source/latex/base/lttagging.dtx775
-rw-r--r--Master/texmf-dist/source/latex/base/lttemplates.dtx2634
-rw-r--r--Master/texmf-dist/source/latex/base/lttextcomp.dtx688
-rw-r--r--Master/texmf-dist/source/latex/base/ltthm.dtx38
-rw-r--r--Master/texmf-dist/source/latex/base/ltvers.dtx4
-rw-r--r--Master/texmf-dist/source/latex/base/ltxdoc.dtx9
-rw-r--r--Master/texmf-dist/source/latex/base/nfssfont.dtx6
-rw-r--r--Master/texmf-dist/source/latex/base/slifonts.fdd6
-rw-r--r--Master/texmf-dist/source/latex/base/syntonly.dtx6
-rw-r--r--Master/texmf-dist/source/latex/base/utf8ienc.dtx5
-rw-r--r--Master/texmf-dist/source/latex/cyrillic/cyoutenc.dtx11
-rw-r--r--Master/texmf-dist/source/latex/firstaid/firstaid.ins4
-rw-r--r--Master/texmf-dist/source/latex/firstaid/latex2e-first-aid-for-external-files.dtx92
-rw-r--r--Master/texmf-dist/source/latex/graphics/color.dtx34
-rw-r--r--Master/texmf-dist/source/latex/graphics/drivers.dtx2
-rw-r--r--Master/texmf-dist/source/latex/graphics/epsfig.dtx8
-rw-r--r--Master/texmf-dist/source/latex/graphics/graphics.dtx74
-rw-r--r--Master/texmf-dist/source/latex/graphics/graphicx.dtx2
-rw-r--r--Master/texmf-dist/source/latex/graphics/keyval.dtx2
-rw-r--r--Master/texmf-dist/source/latex/graphics/lscape.dtx2
-rw-r--r--Master/texmf-dist/source/latex/graphics/rotating.dtx2
-rw-r--r--Master/texmf-dist/source/latex/graphics/trig.dtx6
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/documentmetadata-support.dtx136
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-amsmath.dtx122
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx19
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-block.dtx187
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-firstaid.dtx194
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-float.dtx77
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx90
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-graphic.dtx20
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-marginpar.dtx259
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-math.dtx1561
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-mathpkg.dtx35
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-mathtools.dtx15
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-minipage.dtx4
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-namespace.dtx23
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-1.dtx2
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-2.dtx2
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-sec.dtx17
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-table.dtx1350
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-testphase.dtx9
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-text.dtx2
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-title.dtx518
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-hyperref-changes.dtx2
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-kernel-changes.dtx8
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-toc.dtx10
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab.ins8
-rw-r--r--Master/texmf-dist/source/latex/tools/afterpage.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/afterpage.ins4
-rw-r--r--Master/texmf-dist/source/latex/tools/array.dtx480
-rw-r--r--Master/texmf-dist/source/latex/tools/bm.dtx10
-rw-r--r--Master/texmf-dist/source/latex/tools/bm.ins4
-rw-r--r--Master/texmf-dist/source/latex/tools/calc.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/dcolumn.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/delarray.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/enumerate.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/fileerr.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/fontsmpl.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/ftnright.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/hhline.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/indentfirst.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/l3sys-query.dtx545
-rw-r--r--Master/texmf-dist/source/latex/tools/l3sys-query.ins76
-rw-r--r--Master/texmf-dist/source/latex/tools/layout.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/longtable.dtx371
-rw-r--r--Master/texmf-dist/source/latex/tools/longtable.ins4
-rw-r--r--Master/texmf-dist/source/latex/tools/multicol.dtx72
-rw-r--r--Master/texmf-dist/source/latex/tools/multicol.ins4
-rw-r--r--Master/texmf-dist/source/latex/tools/rawfonts.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/shellesc.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/showkeys.dtx15
-rw-r--r--Master/texmf-dist/source/latex/tools/somedefs.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/tabularx.dtx51
-rw-r--r--Master/texmf-dist/source/latex/tools/tabularx.ins4
-rw-r--r--Master/texmf-dist/source/latex/tools/theorem.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/tools.ins11
-rw-r--r--Master/texmf-dist/source/latex/tools/trace.dtx2
-rw-r--r--Master/texmf-dist/source/latex/tools/varioref.dtx96
-rw-r--r--Master/texmf-dist/source/latex/tools/varioref.ins4
-rw-r--r--Master/texmf-dist/source/latex/tools/verbatim.dtx15
-rw-r--r--Master/texmf-dist/source/latex/tools/xr.dtx231
-rw-r--r--Master/texmf-dist/source/latex/tools/xspace.dtx2
136 files changed, 11006 insertions, 2754 deletions
diff --git a/Master/texmf-dist/source/latex/amsmath/amsbsy.ins b/Master/texmf-dist/source/latex/amsmath/amsbsy.ins
index 62b4e9a67c7..2d0cdd7be32 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsbsy.ins
+++ b/Master/texmf-dist/source/latex/amsmath/amsbsy.ins
@@ -26,7 +26,7 @@
\preamble
Copyright (C) 1995, 1999 American Mathematical Society.
-Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amscd.dtx b/Master/texmf-dist/source/latex/amsmath/amscd.dtx
index 85475708cc3..e1eba3aec28 100644
--- a/Master/texmf-dist/source/latex/amsmath/amscd.dtx
+++ b/Master/texmf-dist/source/latex/amsmath/amscd.dtx
@@ -2,7 +2,7 @@
% \iffalse meta-comment
%
% Copyright (C) 1995, 1999 American Mathematical Society.
-% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amscd.ins b/Master/texmf-dist/source/latex/amsmath/amscd.ins
index 56aedca3757..8f2e5decd42 100644
--- a/Master/texmf-dist/source/latex/amsmath/amscd.ins
+++ b/Master/texmf-dist/source/latex/amsmath/amscd.ins
@@ -1,6 +1,6 @@
%%
%% Copyright (C) 2010 American Mathematical Society.
-%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+%% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3c
@@ -25,7 +25,7 @@
\preamble
Copyright (C) 1995, 1999 American Mathematical Society.
-Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amsgen.dtx b/Master/texmf-dist/source/latex/amsmath/amsgen.dtx
index 6c4aefed671..a7b1ebc87f3 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsgen.dtx
+++ b/Master/texmf-dist/source/latex/amsmath/amsgen.dtx
@@ -2,7 +2,7 @@
% \iffalse meta-comment
%
% Copyright (C) 1995, 1999 American Mathematical Society.
-% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amsgen.ins b/Master/texmf-dist/source/latex/amsmath/amsgen.ins
index faef4aa275b..8b6f4185955 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsgen.ins
+++ b/Master/texmf-dist/source/latex/amsmath/amsgen.ins
@@ -25,7 +25,7 @@
\preamble
Copyright (C) 1995, 1999 American Mathematical Society.
-Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amsmath.dtx b/Master/texmf-dist/source/latex/amsmath/amsmath.dtx
index bf8aa418df8..ec44957a89e 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsmath.dtx
+++ b/Master/texmf-dist/source/latex/amsmath/amsmath.dtx
@@ -2,7 +2,7 @@
% \iffalse meta-comment
%
% Copyright (C) 1995, 2000, 2013 American Mathematical Society.
-% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
@@ -76,17 +76,16 @@ Bug reports can be opened (category \texttt{#1}) at\\%
[1994/12/01]% LaTeX date must be December 1994 or later
% \end{macrocode}
%
-% Providing a rollback to earlier version(s)
+% Providing a rollback to earlier version(s). Anything prior to
+% 2018 we attempt to fulfill by using the version from 2018.
% \begin{macrocode}
-\providecommand\DeclareRelease[3]{}
-\providecommand\DeclareCurrentRelease[2]{}
-%
+\DeclareRelease{}{1994-06-01}{amsmath-2018-12-01.sty}
\DeclareRelease{}{2018-12-01}{amsmath-2018-12-01.sty}
\DeclareCurrentRelease{}{2019-04-01}
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesPackage{amsmath}[2023/05/13 v2.17o AMS math features]
+\ProvidesPackage{amsmath}[2024/05/23 v2.17q AMS math features]
% \end{macrocode}
%
% \section{Catcode defenses}
@@ -1162,7 +1161,7 @@ Foreign command \@backslashchar#1;\MessageBreak
% \begin{macrocode}
\@xp\Umathch@\meaning@"0"\Umathch@
\ifgtest@ % if \Umathchar
- \else % else not \Umathcar
+ \else % else not \Umathchar
% \end{macrocode}
% \begin{macrocode}
\@xp\macro@\meaning@@\macro@
@@ -4153,6 +4152,12 @@ and fix things up.}
% cause \cs{row@} to be advanced twice instead of once.
% \begin{macrocode}
\global\advance\row@\@ne
+% \end{macrocode}
+% Also reset \cs{lineht@} to avoid that this is incorrectly picked
+% up by a following environment, such as \env{align}.
+% \changes{v2.17p}{2024/03/11}{Reset \cs{lineht@} (gh/1289)}
+% \begin{macrocode}
+ \global\lineht@\z@
\cr
}
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/amsmath/amsmath.ins b/Master/texmf-dist/source/latex/amsmath/amsmath.ins
index f92839f959c..528700f238e 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsmath.ins
+++ b/Master/texmf-dist/source/latex/amsmath/amsmath.ins
@@ -1,6 +1,6 @@
%%
%% Copyright (C) 2010 American Mathematical Society.
-%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+%% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3c
@@ -25,7 +25,7 @@
\preamble
Copyright (C) 1995, 1999, 2000, 2013 American Mathematical Society.
-Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amsopn.dtx b/Master/texmf-dist/source/latex/amsmath/amsopn.dtx
index b089749c170..11ad62ddc1f 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsopn.dtx
+++ b/Master/texmf-dist/source/latex/amsmath/amsopn.dtx
@@ -2,7 +2,7 @@
% \iffalse meta-comment
%
% Copyright (C) 1995, 1999 American Mathematical Society.
-% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amsopn.ins b/Master/texmf-dist/source/latex/amsmath/amsopn.ins
index 859e3d7e5ad..67b2b3c077e 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsopn.ins
+++ b/Master/texmf-dist/source/latex/amsmath/amsopn.ins
@@ -1,6 +1,6 @@
%%
%% Copyright (C) 2010 American Mathematical Society.
-%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+%% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3c
@@ -25,7 +25,7 @@
\preamble
Copyright (C) 1995, 1999 American Mathematical Society.
-Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amstext.dtx b/Master/texmf-dist/source/latex/amsmath/amstext.dtx
index a4bc541d349..68299946b07 100644
--- a/Master/texmf-dist/source/latex/amsmath/amstext.dtx
+++ b/Master/texmf-dist/source/latex/amsmath/amstext.dtx
@@ -2,7 +2,7 @@
% \iffalse meta-comment
%
% Copyright (C) 1995, 1999 American Mathematical Society.
-% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amstext.ins b/Master/texmf-dist/source/latex/amsmath/amstext.ins
index 11ed56cc3c9..8ecb9523c9e 100644
--- a/Master/texmf-dist/source/latex/amsmath/amstext.ins
+++ b/Master/texmf-dist/source/latex/amsmath/amstext.ins
@@ -1,6 +1,6 @@
%%
%% Copyright (C) 2010 American Mathematical Society.
-%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+%% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3c
@@ -25,7 +25,7 @@
\preamble
Copyright (C) 1995, 1999 American Mathematical Society.
-Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amsxtra.dtx b/Master/texmf-dist/source/latex/amsmath/amsxtra.dtx
index a1f2c6686c3..5ace38995da 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsxtra.dtx
+++ b/Master/texmf-dist/source/latex/amsmath/amsxtra.dtx
@@ -2,7 +2,7 @@
% \iffalse meta-comment
%
% Copyright (C) 1995, 1999 American Mathematical Society.
-% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/amsmath/amsxtra.ins b/Master/texmf-dist/source/latex/amsmath/amsxtra.ins
index 47072225138..2ba4f221386 100644
--- a/Master/texmf-dist/source/latex/amsmath/amsxtra.ins
+++ b/Master/texmf-dist/source/latex/amsmath/amsxtra.ins
@@ -1,6 +1,6 @@
%%
%% Copyright (C) 2010 American Mathematical Society.
-%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+%% Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3c
@@ -25,7 +25,7 @@
\preamble
Copyright (C) 1995, 1999 American Mathematical Society.
-Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society.
+Copyright (C) 2016-2024 LaTeX Project and American Mathematical Society.
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/Master/texmf-dist/source/latex/base/alltt.dtx b/Master/texmf-dist/source/latex/base/alltt.dtx
index c7e20ba52d1..4718c004b40 100644
--- a/Master/texmf-dist/source/latex/base/alltt.dtx
+++ b/Master/texmf-dist/source/latex/base/alltt.dtx
@@ -40,7 +40,7 @@
%<package>\ProvidesPackage{alltt}
%<driver>\ProvidesFile{alltt.drv}
%\ProvidesFile{alltt.dtx}
- [2021/01/29 v2.0g defines alltt environment]
+ [2024/02/08 v2.0g defines alltt environment]
%
%<*driver>
\documentclass{ltxdoc}
@@ -97,7 +97,7 @@
% \end{itemize}
%
% \textbf{NB} When you are using \textsf{OT1} encoded fonts you might
-% be surprsied when you switch to italics, becuase those fonts have
+% be surprised when you switch to italics, because those fonts have
% a different set of glyphs:
% \begin{alltt}
% The glyph at the position of the $ in a slanted font: \textsl{$}.
diff --git a/Master/texmf-dist/source/latex/base/classes.dtx b/Master/texmf-dist/source/latex/base/classes.dtx
index 688380e3e19..f7c53f0f719 100644
--- a/Master/texmf-dist/source/latex/base/classes.dtx
+++ b/Master/texmf-dist/source/latex/base/classes.dtx
@@ -53,7 +53,7 @@
%<*driver>
\ProvidesFile{classes.drv}
%</driver>
- [2023/05/17 v1.4n
+ [2024/02/08 v1.4n
%<article|report|book> Standard LaTeX document class]
%<10pt|11pt|12pt> Standard LaTeX file (size option)]
% \end{macrocode}
@@ -1882,7 +1882,7 @@
% \changes{v1.3a}{1995/05/17}{Use \cs{@makefnmark} in definition of
% \cs{@makefntext}}
% \changes{v1.3g}{1995/06/26}{Fix definition of \cs{@makefnmark} and
-% \cs{@makefntext} to a) work and b) without using math}
+% \cs{@makefntext} to (a) work and (b) without using math}
% \begin{macrocode}
\else
\newcommand\maketitle{\par
@@ -2002,7 +2002,7 @@
% `section'.
% \item[\meta{level}] A number, denoting the depth of the section
% -- e.g., chapter=1, section = 2, etc. A section number
-% will be printed if and only if \meta{level} $<=$ the value
+% will be printed if and only if \meta{level} $\leq$ the value
% of the \Lcount{secnumdepth} counter.
% \item[\meta{indent}] The indentation of the heading from the left
% margin
@@ -3068,7 +3068,7 @@
% list environment's parameters. The user types |\\| to end a line.
% This is implemented by |\let|'ing |\\| equal |\@centercr|.
%
-% \changes{v1.3j}{1995/08/16}{stop \cs{item} scanning for [ with
+% \changes{v1.3j}{1995/08/16}{stop \cs{item} scanning for [ with ^^A ]
% \cs{relax}}
% \begin{macrocode}
\newenvironment{verse}
@@ -3091,7 +3091,7 @@
% are set smaller than |\textwidth|. The first line of a paragraph
% inside this environment is indented.
%
-% \changes{v1.3j}{1995/08/16}{stop \cs{item} scanning for [ with
+% \changes{v1.3j}{1995/08/16}{stop \cs{item} scanning for [ with ^^A ]
% \cs{relax}}
% \begin{macrocode}
\newenvironment{quotation}
@@ -3110,7 +3110,7 @@
% The quote environment is like the quotation environment except
% that paragraphs are not indented.
%
-% \changes{v1.3j}{1995/08/16}{stop \cs{item} scanning for [ with
+% \changes{v1.3j}{1995/08/16}{stop \cs{item} scanning for [ with ^^A ]
% \cs{relax}}
% \begin{macrocode}
\newenvironment{quote}
diff --git a/Master/texmf-dist/source/latex/base/doc.dtx b/Master/texmf-dist/source/latex/base/doc.dtx
index 8b48f59d6a6..946f187389f 100644
--- a/Master/texmf-dist/source/latex/base/doc.dtx
+++ b/Master/texmf-dist/source/latex/base/doc.dtx
@@ -34,9 +34,9 @@
%\catcode`\<=14
%<+package|shortvrb>\NeedsTeXFormat{LaTeX2e}[1994/12/01]
%<+package>
-%<+package>\providecommand\DeclareRelease[3]{}
-%<+package>\providecommand\DeclareCurrentRelease[2]{}
-%<+package>
+% Any rollback request before 2016-02-15 we try to fullfil with the 2016 version:
+%<+package>\DeclareRelease{}{1994-06-01}
+%<+package> {doc-2016-02-15.sty}
%<+package>\DeclareRelease{v2.1g}{2016-02-15}
%<+package> {doc-2016-02-15.sty}
%<+package>\DeclareRelease{v2}{2021-06-01}
@@ -45,7 +45,7 @@
%<+package>
%<+package>\ProvidesPackage{doc}
%<+shortvrb>\ProvidesPackage{shortvrb}
-%<+package|shortvrb> [2022/11/13 v3.0m
+%<+package|shortvrb> [2024/04/26 v3.0p
%<+package|shortvrb> Standard LaTeX documentation package V3 (FMi)]
%\catcode`\<=12
%
@@ -57,7 +57,7 @@
%
%
%% Package `doc' to use with LaTeX 2e
-%% Copyright (C) 1989-2022 Frank Mittelbach, all rights reserved.
+%% Copyright (C) 1989-2023 Frank Mittelbach, all rights reserved.
%
%
% Version: Date: Changes:
@@ -143,8 +143,8 @@
% \MakeShortVerb{\|}
% \setcounter{StandardModuleDepth}{1}
%
-% {\catcode`\p=12 \catcode`\t=12 ^^A hack used later on to print
-% \gdef\dimenvalue#1pt{$#1$pt}} ^^A a register value with a - sign
+% {\catcode`\p=12 \catcode`\t=12 ^^A hack used later on to print a
+% \gdef\dimenvalue#1pt{$#1$pt}} ^^A register value with a - sign
%
% \newcommand{\DOC}{\texttt{doc}\xspace}
%
@@ -167,7 +167,7 @@
%\RenewDocElement[macrolike = true ,
% toplevel = false,
% idxtype = ,
-% idxgroup = LaTeX comands\actualchar\LaTeX{} commands ,
+% idxgroup = LaTeX commands\actualchar\LaTeX{} commands ,
% printtype =
% ]{Macro}{macro}
%
@@ -237,7 +237,7 @@
% \changes{v1.9t}{1995/05/11}{Use \cs{GetFileInfo}}
% \GetFileInfo{doc.sty}
%
-% \CheckSum{0} ^^A % keep the checksum in this file but not now :-)
+% \CheckSum{0}
%
% \title{The \DOC{} and \texttt{shortvrb} Packages\thanks
% {This file has version number \fileversion{} dated \filedate{}.}}
@@ -595,7 +595,16 @@
% class file (like \texttt{ltugboat.cls}) use the |\DocstyleParms|
% command described below. Starting with release 2.0a it can now
% be changed directly as long as the redefinition happens before
-% the |\begin{document}|.
+% the |\begin{document}| (if you change it later you might see strange
+% typesetting effects if you are unlucky).
+%
+% |\MacroFont| does not alter the font of
+% |\verb| or |\verb*| because it is often used to make the font size of
+% the code displays smaller, which would look odd if used within a
+% paragraph. If you decide to use a different font family and want to
+% use the same family with
+% |\verb| you need to alter the font setup for |\ttfamily| in addition
+% to |\MacroFont|.
%
% \DescribeEnv{environment}
% For documenting the definition of environments one can use the
@@ -695,6 +704,12 @@
% |\NewDocElement{Env}{environment}|
% though that's not quite what has been done, as we will see later.
%
+% \DescribeInterfaceMacro{\ProvideDocElement}
+% This declaration does nothing when the doc element is already
+% declared, otherwise it works like \cs{NewDocElement}. It can be
+% useful if you have many documentation files that you may want to
+% process individually as well as together.
+%
% \DescribeOption[noprint]{macrolike}
% \DescribeOption[noprint]{envlike}
% \DescribeOption[noprint]{toplevel}
@@ -1367,7 +1382,7 @@
%\RenewDocElement[macrolike = true ,
% toplevel = false,
% idxtype = ,
-% idxgroup = LaTeX comands\actualchar\LaTeX{} commands ,
+% idxgroup = LaTeX commands\actualchar\LaTeX{} commands ,
% printtype =
% ]{Macro}{macro}
%\end{verbatim}
@@ -1515,7 +1530,7 @@
%
% Thirty years is a long time in the life of computer programs, so
% there are a good number of interfaces within \DOC that are really
-% only of historical interest (or when processing equally old sources.
+% only of historical interest (or when processing equally old sources).
% We list them here, but in general we suggest that for new
% documentation they should not be used.
%
@@ -2108,9 +2123,12 @@
% that is, they must be given |\catcode| $12$.
% \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX verbatim,
% which handles more ligatures.}
+% \changes{v3.0o}{2023/12/30}{Use \cs{@noligs} from the \LaTeX\
+% kernel, so that the \texttt{upquote} package can
+% add its patch (gh/1230)}
% \begin{macrocode}
\obeylines
- \let\do\do@noligs \verbatim@nolig@list
+ \@noligs
\let\do\@makeother \dospecials
% \end{macrocode}
% \changes{v1.5t}{1989/11/07}{Common code added.}
@@ -2183,7 +2201,7 @@
% \changes{v1.7a}{1992/03/13}{Added \cs{reset@font} for NFSS.}
% \changes{v1.8c}{1993/10/25}{NFSS standard}
% \changes{v1.9t}{1995/05/26}{Removed \cs{math@fontsfalse} (different
-% math setup /pr1622}
+% math setup /pr1622)}
% \begin{macrocode}
\@ifundefined{MacroFont}{%
\if@compatibility
@@ -2220,7 +2238,7 @@
% \changes{v1.7m}{1992/10/11}{Use sltt as default.}
% \changes{v1.8c}{1993/10/25}{NFSS standard}
% \changes{v1.9t}{1995/05/26}{Removed \cs{math@fontsfalse} (different
-% math setup /pr1622}
+% math setup /pr1622)}
% Although most of the macro code is set in |\MacroFont| we want to be
% able to switch to indicate module code set in |\AltMacroFont|.
% |\macro@font| keeps track of which one we're using. We can't do the
@@ -2681,7 +2699,7 @@
% \end{macrocode}
%
% \changes{v2.1j}{2019/11/03}{Kernel now sets up \cs{verbvisiblespace} (gh/205)}
-% \changes{v2.1k}{2019/11/10}{Put the definition into the right command :-( (gh/205)}
+% \changes{v2.1k}{2019/11/10}{Put the definition into the right command (gh/205)}
% \begin{macrocode}
\@setupverbvisiblespace
\MacroFont \@vobeyspaces \@sxverbatim}
@@ -2895,32 +2913,32 @@
% following tasks:
% \begin{itemize}
% \parindent4em
-% \item[1)]
+% \item[(1)]
% |\catcode| all characters used in macro names to
-% 11 (i.e.\ `letter').
-% \item[2)]
+% 11 (i.e., `letter').
+% \item[(2)]
% |\catcode| the `|\|' character to 13
-% (i.e.\ `active').
-% \item[3a)]
+% (i.e., `active').
+% \item[(3a)]
% |\let| the `|\|' equal |\scan@macro|
-% (i.e.\ start the macro scanning mechanism) if there is
-% no special escape character (i.e.\ the
+% (i.e., start the macro scanning mechanism) if there is
+% no special escape character (i.e., the
% |\special@escape@char| is `|\|').
-% \item[3b)]
+% \item[(3b)]
% Otherwise |\let| it equal |\bslash|, i.e.\
% produce a printable |\|.
-% \item[4)]
+% \item[(4)]
% Make the \meta{special escape character} active.
-% \item[5)]
+% \item[(5)]
% |\let| the active version of the special escape
% character
-% (i.e.\ the expansion of |\active@escape@char|) equal
+% (i.e., the expansion of |\active@escape@char|) equal
% |\scan@macro|.
% \end{itemize}
% The reader might ask why we bother to |\catcode| the
% `|\|' first to 12 (at the end of |\macro@code|) then
% re-|\catcode| it to 13 in order to produce a $|\|_{12}$
-% in case 3b) above. This is done because we have to ensure that
+% in case (3b) above. This is done because we have to ensure that
% `|\|' has |\catcode| 13 within the \env{macrocode}
% environment. Otherwise the delimiter for the argument of
% |\xmacro@code| would not be found (parameter matching
@@ -2930,14 +2948,14 @@
% \begin{macrocode}
\begingroup \catcode`\|=\z@ \catcode`\\=\active
% \end{macrocode}
-% We carry out tasks 2) and 3b) first.
+% We carry out tasks (2) and (3b) first.
% \SpecialEscapechar\|
% \begin{macrocode}
|gdef|init@crossref{|catcode`|\|active |let\|bslash
% \end{macrocode}
% Because of the popularity of the `|@|' character as a
% `letter' in macros, we normally have to change its
-% |\catcode| here, and thus fulfill task 1). But the macro
+% |\catcode| here, and thus fulfill task (1). But the macro
% designer might use other characters as private letters as well,
% so we use a macro to do the |\catcode| switching.
% \SpecialEscapechar\|
@@ -2945,8 +2963,8 @@
|MakePrivateLetters
% \end{macrocode}
% Now we |\catcode| the special escape character to 13 and
-% |\let| it equal |\scan@macro|, i.e.\ fulfill tasks 4)
-% and 5). Note the use of |\expandafter| to insert the chosen
+% |\let| it equal |\scan@macro|, i.e., fulfill tasks (4)
+% and (5). Note the use of |\expandafter| to insert the chosen
% escape character saved in |\special@escape@char| and
% |\active@escape@char|.
% \SpecialEscapechar\|
@@ -2955,7 +2973,7 @@
|expandafter|let|active@escape@char|scan@macro}
|endgroup
% \end{macrocode}
-% If there is no special escape character, i.e.\ if
+% If there is no special escape character, i.e., if
% |\SpecialEscapechar| is |\\|, the second last line will
% overwrite the previous definition of $|\|_{13}$. In this
% way all tasks are fulfilled.
@@ -3109,9 +3127,9 @@
% done by the |\ifnot@excluded| macro which assumes that the
% macro name is saved in |\macro@namepart|. The character
% mustn't be stored with a special category code or exclusion from
-% the index won't work, so we we use \cs{string} to normalize it
-% the same way it is done in \cs{DoNotIndex}, i.e. everything ends up catcode 12
-% except for the space character.
+% the index won't work, so we use \cs{string} to normalize it
+% the same way it is done in \cs{DoNotIndex}, i.e. everything ends up
+% catcode 12 except for the space character.
% \changes{v2.0e}{1998/12/28}{Correctly use the case-changing trick.}
% \changes{v3.0l}{2022/11/03}{No longer using the case-changing trick.}
% \begin{macrocode}
@@ -3254,7 +3272,7 @@
% unnecessarily index within that part of the code. As the sequence
% is local it will revert this setting at the end of the
% environment so that the command is indexed elsewhere (unless it
-% is generally disabled from indexing.
+% is generally disabled from indexing).
%
% \DescribeMacro\g__doc_idxtype_prop
% Global property list that holds for all commands that are special
@@ -3282,7 +3300,7 @@
% \DescribeInterfaceMacro\RecordIndexType
% This command takes two arguments: a command (with escape char)
% and its type (i.e., first mandatory
-% argument of a |\NewDocElement| declaration. If |#1| should not be
+% argument of a |\NewDocElement| declaration). If |#1| should not be
% included from the index, then the data is used to record that
% this command is of this type. The information is then used to
% generate appropriate index entries. Obviously, index entries
@@ -3481,7 +3499,7 @@
% \begin{macro}{\__doc_idxtype_put:nn}
% This internal command takes two arguments: a command name as
% string (no backslash) and its type (i.e., first mandatory
-% argument of a |\NewDocElement| declaration. If |#1| is not in
+% argument of a |\NewDocElement| declaration). If |#1| is not in
% |\l__doc_donotindex_seq| it will add this data to the property
% list |\g__doc_idxtype_prop| using |#1| as key and |#2| as its
% value. If the key already exist its value will be overwritten. If
@@ -3884,7 +3902,8 @@
% \begin{imacro}{\RightBraceIndex}
% \changes{v1.5s}{1989/11/05}{Support for code line no. (Undoc)} These
% two macros fix the problems with \prg{makeindex}. Note the
-% `hack' with |\iffalse}\fi| to satisfy both \TeX{} and the
+% `hack' with \iffalse{-to get matching braces\fi |\iffalse}\fi|
+% to satisfy both \TeX{} and the
% \prg{makeindex} program. When this is written to the
% \texttt{.idx} file \TeX{} will see both braces (so we get a
% balanced text). \prg{makeindex} will also see balanced braces
@@ -5539,7 +5558,7 @@
% \begin{macrocode}
\long\def\@doc@env#1#2#3{
% \end{macrocode}
-% The |\endgroup| here closes the scanning of names (using special catcodes.
+% The |\endgroup| here closes the scanning of names (using special catcodes).
% \begin{macrocode}
\endgroup
\clist_map_inline:nn {#3} { \@doc@env@{#1}{#2}{##1} }
@@ -5565,8 +5584,8 @@
% they are technically part of the generated API, only not meant for public
% use.
%
-% \fmi{above docu is no longer right (but code needs further changes
-% anyway}
+% \fmi{above docu is no longer right (but code probably needs further changes
+% anyway)}
%
% |#1| is either \texttt{TT} (for true = macrolike) or \texttt{TF}.
% If true then we drop the first char from |\saved@macroname| and
@@ -5580,7 +5599,7 @@
% If the \DOC element described is macrolike but not a normal
% ``macro'' then its type should be recorded and this is the places
% where this happens. For macros (which should make up the bulk of
-% these items we don't do this and for anything else that looks
+% these items) we don't do this and for anything else that looks
% from an indexing perspective like a macro we don't do that either
% to keep the list of exceptions small. That would be the case if
% the indexing command |\Code|\meta{doc-element}|Index| is
@@ -5635,7 +5654,7 @@
\fi
% \end{macrocode}
% Suppress further |\index| entries when we are within a
-% \texttt{macrolike} environment. (There is no point doing that for
+% \texttt{macrolike} environment. There is no point doing that for
% non-\texttt{macrolike} environments are index entries are only
% generated for items starting with a backslash anyway.
% \fmi{fix}
@@ -5940,6 +5959,16 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\doc@ignoredinfo}
+%
+% \begin{macrocode}
+\def\doc@ignoredinfo#1#2{%
+ \PackageInfo{doc}{Doc element '#1/#2' declaration
+ ignored}%
+}
+% \end{macrocode}
+% \end{macro}
+%
%
% \begin{imacro}{\NewDocElement}
% \oarg{options}\marg{name}\marg{envname}
@@ -5963,6 +5992,30 @@
% \end{macrocode}
% \end{imacro}
%
+% \begin{imacro}{\ProvideDocElement}
+% \oarg{options}\marg{name}\marg{envname}
+% This does nothing unless the doc element could be declared with
+% \cs{NewDocElement}.
+% \begin{macrocode}
+\newcommand\ProvideDocElement[3][]{%
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \@ifundefined{Print#2Name}%
+ {\@ifundefined{PrintDescribe#2}%
+ {\@ifundefined{#3}%
+ {\@ifundefined{end#3}%
+ {\@NewDocElement{#1}}%
+ \doc@ignoredinfo
+ }\doc@ignoredinfo
+ }\doc@ignoredinfo
+ }\doc@ignoredinfo
+ {#2}{#3}%
+}
+% \end{macrocode}
+% \end{imacro}
+%
+%
% \begin{imacro}{\RenewDocElement}
% \oarg{options}\marg{name}\marg{envname}
%
@@ -6098,7 +6151,7 @@
% \end{macrocode}
-% \begin{macro}{SpecialMainIndex}
+% \begin{macro}{\SpecialMainIndex}
%
% In \DOC v2 we had \cs{SpecialMainIndex} and
% \cs{SpecialMainEnvIndex} but now with additional \DOC elements we
@@ -6110,7 +6163,7 @@
% \end{macrocode}
% \end{macro}
-% \begin{macro}{SpecialUsageIndex}
+% \begin{macro}{\SpecialUsageIndex}
% \DOC v2 also had \cs{SpecialUsageIndex} which is now called
% \cs{SpecialMacroIndex} generating the ``usage'' index entry for
% a macro. Again we provide that as an alias via |\def|.
@@ -6206,86 +6259,6 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% \section{Code no longer used}
-%
-% \begin{imacro}{\verb}
-% \changes{v1.7a}{1992/02/27}{Now warns about newlines (from
-% newdoc with `@noligs added).}
-% \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX \cs{verb}}
-% We re-define |\verb| to check for newlines in its argument since a
-% missing delimiter is difficult to detect in \DOC{} source.
-% The code is the same as in \texttt{latex.tex} of September 19, 1993.
-% Perhaps there should be a font-changing
-% hook rather than just using |\ttfamily|, but if so it probably should be
-% different from |\MacroFont| since that normally includes |\small|
-% and would look wrong inline.
-% \changes{v1.7a}{1992/02/28}{Added math mode check (from verbatim.sty)}
-% \begin{macrocode}
-%\def\verb{\relax\ifmmode\hbox\else\leavevmode\null\fi
-% \bgroup \let\do\do@noligs \verbatim@nolig@list
-% \ttfamily \verb@eol@error \let\do\@makeother \dospecials
-% \@ifstar{\@sverb}{\@vobeyspaces \frenchspacing \@sverb}}
-% \end{macrocode}
-% \end{imacro}
-%
-% \begin{macro}{\verb@balance@group}
-% \begin{macro}{\verb@egroup}
-% \begin{macro}{\verb@eol@error}
-% \changes{v1.8b}{1993/09/21}{Renamed \cs{verb@err} to
-% \cs{verb@eol@error}, as in new LaTeX verbatim.}
-% \begin{macrocode}
-%\let\verb@balance@group\@empty
-% \end{macrocode}
-%
-% \begin{macrocode}
-%\def\verb@egroup{\global\let\verb@balance@group\@empty\egroup}
-% \end{macrocode}
-%
-% \begin{macrocode}
-%\begingroup
-% \obeylines%
-% \gdef\verb@eol@error{\obeylines%
-% \def^^M{\verb@egroup\@latex@error{%
-% \noexpand\verb command ended by end of line}\@ehc}}%
-%\endgroup
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@sverb}
-% \changes{v1.7a}{1992/02/27}{Added for \cs{verb} change.}
-% \changes{v1.7a}{1992/02/28}{Now same as in verbatim.sty.}
-% \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX verbatim,
-% which has better error trapping.}
-% See \cite{art:verbatim} for commentary.
-% \changes{v2.1j}{2019/11/03}{Use the kernel definition, no change needed (gh/205)}
-% \begin{macrocode}
-%\def\@sverb#1{%
-% \catcode`#1\active \lccode`\~`#1%
-% \gdef\verb@balance@group{\verb@egroup
-% \@latex@error{Illegal use of \noexpand\verb command}\@ehc}%
-% \aftergroup\verb@balance@group
-% \lowercase{\let~\verb@egroup}}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\verbatim@nolig@list}
-% \begin{macro}{\do@noligs}
-% These macros replace the old |\@noligs| mechanism by an
-% extensible version to allow more ligatures to be added.
-% \begin{macrocode}
-%\def\verbatim@nolig@list{\do\`\do\<\do\>\do\,\do\'\do\-}
-%\def\do@noligs#1{%
-% \catcode`#1\active
-% \begingroup
-% \lccode`\~`#1\relax
-% \lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1}}}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-
^^A Needed for emacs
^^A
diff --git a/Master/texmf-dist/source/latex/base/docstrip.dtx b/Master/texmf-dist/source/latex/base/docstrip.dtx
index 9677fdad61f..d5366b3fddf 100644
--- a/Master/texmf-dist/source/latex/base/docstrip.dtx
+++ b/Master/texmf-dist/source/latex/base/docstrip.dtx
@@ -31,7 +31,7 @@
\def\filename{docstrip.dtx}
\def\fileversion{v2.6b}
\def\filedate{2022-09-03}
-\def\docdate {2023-10-10}
+\def\docdate {2024-02-08}
%%
%
%\iffalse
@@ -450,7 +450,7 @@
% \DescribeMacro{\endbatchfile}
% All batch files should end with this command. Any lines after this
% in the file are ignored. In old files that start
-% |\def\batchfile{|\ldots\ this command is optional, but is a good
+% |\def\batchfile{|\ldots\ \iffalse}\fi this command is optional, but is a good
% idea anyway. If this command is omitted from a batchfile then
% normally \TeX\ will go to its interactive |*| prompt, so you may
% stop \ds{} by typing |\endbatchfile| to this prompt.
@@ -757,7 +757,7 @@
% \meta{Primary}]*\\
% \meta{Primary} & $::=$ &
% \meta{Terminal} $|$ \texttt{!}\meta{Primary}
-% $|$ \texttt{(}\meta{Expression}\texttt{)}\\
+% $|$ \texttt(\meta{Expression}\texttt)\\
% \end{tabular}
%
% The \texttt{|} stands for disjunction, the \texttt{\&} stands for
@@ -1712,7 +1712,7 @@ Z
% \end{macrocode}
%
% \begin{macro}{\quote@name}
-% \changes{v2.5h}{2020/04/18}{Macro added gfh/221)}
+% \changes{v2.5h}{2020/04/18}{Macro added (gh/221)}
% A macro copied from \texttt{ltfiles.dtx} in order to be able to
% allow spaces in filenames.
% \begin{macrocode}
@@ -1994,7 +1994,7 @@ Z
% \meta{Primary} & $::=$ &
% \meta{Terminal} $|$ \texttt{!}\meta{Primary}
% $|$
-% \texttt{(}\meta{Expression}\texttt{)}\\
+% \texttt(\meta{Expression}\texttt)\\
% \end{tabular}
%
% The \texttt{|} stands for disjunction, the \texttt{\&} stands for
@@ -2023,7 +2023,7 @@ Z
% \begin{eqnarray*}
% \tau(\meta{Terminal})&=&"\t@<Terminal>,#1,<Terminal>,\qStop"\\
% \tau(!\meta{Primary})&=&"\if1"\,\tau(\meta{Primary})\,"0\else1\fi"\\
-% \tau(\mbox{\texttt{(}\meta{Expression}\texttt{)}})
+% \tau(\mbox{\texttt(\meta{Expression}\texttt)})
% &=&\tau(\meta{Expression})\\
% \tau(\mbox{\meta{Primary}\texttt{\&}\meta{Secondary}})
% &=&"\if0"\,\tau(\meta{Primary})\,"0\else"
@@ -4473,7 +4473,7 @@ for copying and modification in the file \inFileName.
% {Macro added (DPC)}
% Process the batch file, and then terminate cleanly.
% This may be set to |\relax| for `new style' batch files that
-% do not start with |\def\batchfile{|\ldots
+% do not start with |\def\batchfile{|\ldots \iffalse}\fi
% \begin{macrocode}
\def\process@first@batchfile{%
\processbatchFile
diff --git a/Master/texmf-dist/source/latex/base/fontdef.dtx b/Master/texmf-dist/source/latex/base/fontdef.dtx
index 82b09709af1..281add29efc 100644
--- a/Master/texmf-dist/source/latex/base/fontdef.dtx
+++ b/Master/texmf-dist/source/latex/base/fontdef.dtx
@@ -27,7 +27,8 @@
%
% \fi
% \iffalse
-%%% From File: fontdef.dtx
+%%% From File: fontdef.dtx
+%<*!latexrelease>
%<*dtx>
\ProvidesFile{fontdef.dtx}
%</dtx>
@@ -38,17 +39,24 @@
%<+cfgprel>\ProvidesFile{preload.cfg}
%<driver, >\ProvidesFile{fontdef.drv}
% \fi
-% \ProvidesFile{fontdef.dtx}
-%<-latexrelease> [2021/01/15 v3.0i LaTeX Kernel
-% \iftrue (\else
-%<text, >(Text
-%<math, >(Math
-%<+cfgtext>(Uncustomized text
-%<+cfgmath>(Uncustomized math
-%<+cfgprel>(Uncustomized preload
+% \ProvidesFile{fontdef.dtx}
+ [2024/02/09 v3.0i LaTeX Kernel
+% \iffalse
+%<text, > (Text font setup)
+%<math, > (Math font setup)
+%<+cfgtext> (Uncustomized text font setup)
+%<+cfgmath> (Uncustomized math font setup)
+%<+cfgprel> (Uncustomized preload font setup)
+%<*dtx>
% \fi
-%<-latexrelease> font setup)]
-%
+(font setup)
+%\iffalse
+%</dtx>
+%\fi
+]
+% \iffalse
+%</!latexrelease>
+%\fi
%
%\iffalse This is a META comment
%
diff --git a/Master/texmf-dist/source/latex/base/format.ins b/Master/texmf-dist/source/latex/base/format.ins
index 2e14ee0e62a..e20ff094380 100644
--- a/Master/texmf-dist/source/latex/base/format.ins
+++ b/Master/texmf-dist/source/latex/base/format.ins
@@ -170,6 +170,7 @@ the system are in the document `cfgguide.tex'.
\from{lthooks.dtx}{2ekernel} % L3 layer module
\from{ltcmdhooks.dtx}{2ekernel} % L3 layer module
\from{ltsockets.dtx}{2ekernel} % L3 layer module
+ \from{lttemplates.dtx}{2ekernel} % L3 layer module
\from{ltalloc.dtx}{2ekernel}
\from{ltcntrl.dtx}{2ekernel}
\from{lterror.dtx}{2ekernel}
@@ -206,11 +207,12 @@ the system are in the document `cfgguide.tex'.
\from{ltbibl.dtx}{2ekernel}
\from{ltmarks.dtx}{trace,2ekernel} % L3 layer module
\from{ltpage.dtx}{2ekernel}
- \from{ltclass.dtx}{2ekernel,tracerollback}
+ \from{ltclass.dtx}{2ekernel,tracerollback}
\from{ltkeys.dtx}{2ekernel} % L3 layer module
\from{ltfilehook.dtx}{2ekernel} % L3 layer module
\from{ltshipout.dtx}{2ekernel} % L3 layer module
\from{ltoutput.dtx}{2ekernel}
+ \from{lttagging.dtx}{2ekernel}
\from{ltfinal.dtx}{2ekernel}}
\file{tracefnt.sty}{%
\from{ltfsstrc.dtx}{package,trace}}
@@ -228,6 +230,8 @@ the system are in the document `cfgguide.tex'.
\from{lttextcomp.dtx}{TS1sty}}
\file{textcomp-2018-08-11.sty}{%
\from{lttextcomp.dtx}{TS1oldsty}}
+ \file{checkencodingsubset.tex}{%
+ \from{lttextcomp.dtx}{TS1check}}
}
\generateFile{oldlfont.sty}{t}{%
diff --git a/Master/texmf-dist/source/latex/base/ifthen.dtx b/Master/texmf-dist/source/latex/base/ifthen.dtx
index ef7d8ab3987..0bbe3612115 100644
--- a/Master/texmf-dist/source/latex/base/ifthen.dtx
+++ b/Master/texmf-dist/source/latex/base/ifthen.dtx
@@ -30,7 +30,7 @@
%%
%% File `ifthen.dtx'.
%% Copyright (C) 1991 by Leslie Lamport
-%% Copyright (C) 1994-2001 LaTeX project, David Carlisle
+%% Copyright (C) 1994-2024 LaTeX project, David Carlisle
%% all rights reserved.
%%
%
@@ -42,7 +42,7 @@
%<driver>\ProvidesFile{ifthen.drv}
% \fi
% \ProvidesFile{ifthen.dtx}
- [2022/04/13 v1.1d Standard LaTeX ifthen package (DPC)]
+ [2024/03/16 v1.1e Standard LaTeX ifthen package (DPC)]
%
% \iffalse
%<*driver>
@@ -273,15 +273,35 @@
\ifx##1\relax\z@\else\expandafter##2##1\fi}}}
% \end{macrocode}
% \begin{macrocode}
+\begingroup
+\lccode`\~`\> %
+\catcode`\+\active
+\lccode`\+`\< %
+\catcode`\!\active
+\lccode`\!`\= %
+\lowercase{\endgroup
+% \end{macrocode}
+% \begin{macrocode}
+\def\TE@repl@active{%
+ \TE@repl~>%
+ \TE@repl+<%
+ \TE@repl!=%
+}
+% \end{macrocode}
+% \begin{macrocode}
\long\def\ifthenelse#1{%
% \end{macrocode}
% \changes{v1.0h}{1994/05/14}{Use \cs{TE@repl}}
+% \changes{v1.1e}{2024/03/16}{replace active \cs{ifnum} syntax}
% \begin{macrocode}
\toks@{#1}%
\TE@repl\or\TE@or
\TE@repl\and\TE@and
\TE@repl\not\TE@neg
% \end{macrocode}
+% \begin{macrocode}
+ \TE@repl@active
+% \end{macrocode}
%
% \changes{v1.1c}{2001/05/25}{Added \cs{AND}, \cs{OR} and \cs{NOT} as
% boolean operators as alternative to the lower case versions
@@ -353,7 +373,10 @@
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
- \fi}
+ \fi}%
+% \end{macrocode}
+% \begin{macrocode}
+}
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/inputenc.dtx b/Master/texmf-dist/source/latex/base/inputenc.dtx
index 5858743afd8..7ab9713d8e9 100644
--- a/Master/texmf-dist/source/latex/base/inputenc.dtx
+++ b/Master/texmf-dist/source/latex/base/inputenc.dtx
@@ -142,7 +142,7 @@
% Originally this command was only to be used in vertical mode (with
% the idea that it should be only within a document when
% using text from several documents to build up a composite work such
-% as a volume of journal articles. However, usages in certain
+% as a volume of journal articles). However, usages in certain
% languages suggested that it might be preferable to allow changing
% the input encoding at any time, which is what is possible now
% (though that is quite computing resource intensive).
@@ -410,7 +410,7 @@
%<cp1252&!ansinew> \ProvidesFile{cp1252.def}
%<cp1250> \ProvidesFile{cp1250.def}
%<cp1257> \ProvidesFile{cp1257.def}
- [2021/02/14 v1.3d Input encoding file]
+ [2024/02/08 v1.3d Input encoding file]
%<cp850>%%
%<cp850>%% If you need a Euro symbol, try cp858 instead.
%<cp850>%%
@@ -2204,7 +2204,7 @@
% \section{The Next encoding}
%
% This input encoding is based on work by Stefan Ried
-% (\texttt{stef@\linebreak[0]theo-phys.uni-essen.de} and Holger Uhr
+% (\texttt{stef@\linebreak[0]theo-phys.uni-essen.de}) and Holger Uhr
% (\texttt{huhr@\linebreak[0]uni-paderborn.de}).
%
% Further extended by
diff --git a/Master/texmf-dist/source/latex/base/latexrelease.ins b/Master/texmf-dist/source/latex/base/latexrelease.ins
index 8ae19b318d3..89c3b0fc3a7 100644
--- a/Master/texmf-dist/source/latex/base/latexrelease.ins
+++ b/Master/texmf-dist/source/latex/base/latexrelease.ins
@@ -97,6 +97,7 @@ extension .ins) which are part of the distribution.
\from{lthooks.dtx} {latexrelease}% L3 layer module
\from{ltcmdhooks.dtx} {latexrelease}% L3 layer module
\from{ltsockets.dtx} {latexrelease}% L3 layer module
+ \from{lttemplates.dtx} {latexrelease}% L3 layer module
\from{ltalloc.dtx} {latexrelease}% empty
\from{ltcntrl.dtx} {latexrelease}% empty
\from{lterror.dtx} {latexrelease}% empty
diff --git a/Master/texmf-dist/source/latex/base/ltboxes.dtx b/Master/texmf-dist/source/latex/base/ltboxes.dtx
index 7c5a7c01397..7e6c787ab89 100644
--- a/Master/texmf-dist/source/latex/base/ltboxes.dtx
+++ b/Master/texmf-dist/source/latex/base/ltboxes.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltboxes.dtx}
- [2023/10/26 v1.4e LaTeX Kernel (Box Commands)]
+ [2024/04/22 v1.4f LaTeX Kernel (Box Commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltboxes.dtx}
@@ -87,7 +87,7 @@
% Note that in this picture mode version of |\makebox| a [b] aligns on
% the \emph{bottom} of the text as documented. If you want to align on
% the \emph{baseline} use
-% |\makebox( , )[b]{\raisebox{0pt}[\height][0pt]{xyz}}}|
+% |\makebox( , )[b]{\raisebox{0pt}[\height][0pt]{xyz}}|
% or |\makebox( , )[b]{\smash{xyz}}|
%
% \DescribeMacro\mbox
@@ -235,7 +235,8 @@
% \begin{macro}{\makebox}
% \changes{v0.1a}{1993/12/03}
% {modified}
-% |\makebox| User level command just looks for optional |[| or |(|.
+% |\makebox| User level command just looks for optional
+% |[| or |(|. \iffalse)]\fi
% \changes{v1.1h}{2015/01/08}{Make Robust (latexrelease)}
% \begin{macrocode}
%</2ekernel>
@@ -1010,7 +1011,7 @@
% set globally to false when they are definitely true.
%
% If anyone is unhappy with this argument then both flags should be
-% treated as in |\set@nobreak|; otherwise this command will be
+% treated as in |\@setnobreak|; otherwise this command will be
% redundant.
% \changes{v1.1a}{1996/10/24}{Added local settings of flags: dangerous!!}
% \begin{macrocode}
@@ -1486,9 +1487,40 @@
%
% The |\nobreak| was added (1995/10/31) to allow hyphenation of the
% final word of the paragraph.
+%
+% In 2024 we changed the macro to account for vertical mode. In
+% that case we use a strut produced with \cs{hrule} to avoid
+% starting a new paragraph (resulting in spurious extra line) and
+% also account for the \cs{prevdepth} of the previous line.
+% \changes{v1.4f}{2024/04/18}
+% {Use a \cs{hrule} strut not a \cs{vrule} if already in
+% vertical mode (bug seen first with footmisc/14)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2024/06/01}%
+%<latexrelease> {\@finalstrut}{final strut correction}%
\def\@finalstrut#1{%
- \unskip\ifhmode\nobreak\fi\vrule\@width\z@\@height\z@\@depth\dp#1}
+ \unskip
+ \ifhmode \nobreak \vrule
+ \else
+ \ifdim \prevdepth=-\@m\p@
+ \else
+ \vskip-\prevdepth
+ \fi
+ \hrule
+ \fi
+ \@width\z@\@height\z@\@depth\dp#1}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@finalstrut}{final strut correction}%
+%<latexrelease>\def\@finalstrut#1{%
+%<latexrelease> \unskip\ifhmode\nobreak\fi
+%<latexrelease> \vrule\@width\z@\@height\z@\@depth\dp#1}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/ltclass.dtx b/Master/texmf-dist/source/latex/base/ltclass.dtx
index 139eb7a1a72..35bbb8a55a4 100644
--- a/Master/texmf-dist/source/latex/base/ltclass.dtx
+++ b/Master/texmf-dist/source/latex/base/ltclass.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltclass.dtx}
- [2023/04/14 v1.5h LaTeX Kernel (Class & Package Interface)]
+ [2024/04/10 v1.5k LaTeX Kernel (Class & Package Interface)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltclass.dtx}
@@ -390,7 +390,7 @@
% package files.)
%
% |\DeclareOption*{\PassOptionsToPackage{\CurrentOption}|^^A
-% |{|\meta{pkg-name}|}|\\
+% |{|\meta{pkg-name}|}}|\\
% Handle the current option by passing it on to the package
% \meta{pkg-name}, which will presumably be loaded via
% |\RequirePackage| later in the file. This is useful for building
@@ -1075,19 +1075,20 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2021/11/15}%
-%<latexrelease> {\IfPackageLoadedtTF}{Test package loading}%
+%<latexrelease>\IncludeInRelease{2024/06/01}%
+%<latexrelease> {\IfPackageLoadedTF}{Test package loading}%
\let \IfPackageLoadedTF \@ifpackageloaded
\let \IfClassLoadedTF \@ifclassloaded
\let \IfPackageLoadedWithOptionsTF \@ifpackagewith
\let \IfClassLoadedWithOptionsTF \@ifclasswith
% \end{macrocode}
-% For rollback pretend it was available since the beginning of dawn.
+% For rollback/rollforward pretend everything was available since
+% the beginning of dawn.
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\IfPackageLoadedtTF}{Test package loading}%
+%<latexrelease> {\IfPackageLoadedTF}{Test package loading}%
%<latexrelease>
%<latexrelease>\let \IfPackageLoadedTF \@ifpackageloaded
%<latexrelease>\let \IfClassLoadedTF \@ifclassloaded
@@ -1102,6 +1103,99 @@
%
%
%
+% \begin{macro}{
+% \IfPackageLoadedT,\IfPackageLoadedF,
+% \IfPackageAtLeastT,\IfPackageAtLeastF,
+% \IfClassAtLeastT,\IfClassAtLeastF,
+% \IfFileAtLeastT,\IfFileAtLeastF,
+% \IfFormatAtLeastT,\IfFormatAtLeastF,
+% \IfPackageLoadedWithOptionsT,\IfPackageLoadedWithOptionsF,
+% \IfClassLoadedT,\IfClassLoadedF,
+% \IfClassLoadedWithOptionsF,\IfClassLoadedWithOptionTF
+% }
+% A few more conditionals for convenience
+% \changes{v1.5k}{2024/04/10}{Provide T and F conditionals not just TF
+% (gh/1262)}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2024/06/01}%
+%<latexrelease> {\IfPackageLoadedT}{More conditionals}%
+\def\IfPackageLoadedT #1#2{\IfPackageLoadedTF{#1}{#2}{}}
+\def\IfPackageLoadedF #1{\IfPackageLoadedTF{#1}{}}
+\def\IfClassLoadedT #1#2{\IfClassLoadedTF{#1}{#2}{}}
+\def\IfClassLoadedF #1{\IfClassLoadedTF{#1}{}}
+\def\IfPackageAtLeastT#1#2#3{\IfPackageAtLeastTF{#1}{#2}{#3}{}}
+\def\IfPackageAtLeastF #1#2{\IfPackageAtLeastTF{#1}{#2}{}}
+\def\IfClassAtLeastT #1#2#3{\IfClassAtLeastTF{#1}{#2}{#3}{}}
+\def\IfClassAtLeastF #1#2{\IfClassAtLeastTF{#1}{#2}{}}
+\def\IfFileAtLeastT #1#2#3{\IfFileAtLeastTF{#1}{#2}{#3}{}}
+\def\IfFileAtLeastF #1#2{\IfFileAtLeastTF{#1}{#2}{}}
+\def\IfFormatAtLeastT #1#2{\IfFormatAtLeastTF{#1}{#2}{}}
+\def\IfFormatAtLeastF #1{\IfFormatAtLeastTF{#1}{}}
+\def\IfPackageLoadedWithOptionsT #1#2#3{\IfPackageLoadedWithOptionsTF{#1}{#2}{#3}{}}
+\def\IfPackageLoadedWithOptionsF #1#2{\IfPackageLoadedWithOptionsTF{#1}{#2}{}}
+\def\IfClassLoadedWithOptionsT #1#2#3{\IfClassLoadedWithOptionsTF{#1}{#2}{#3}{}}
+\def\IfClassLoadedWithOptionsF #1#2{\IfClassLoadedWithOptionsTF{#1}{#2}{}}
+% \end{macrocode}
+%
+% \begin{macro}{\IfFileLoadedTF,\IfFileLoadedT,\IfFileLoadedF}
+% These three commands haven't been there at all in the past.
+% \changes{v1.5k}{2024/04/10}{Provide \cs{IfFileLoadedTF} and variants
+% (gh/1222)}
+% \begin{macrocode}
+\def\IfFileLoadedTF#1{%
+ \expandafter\ifx\csname ver@#1\endcsname\relax
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi}
+\def\IfFileLoadedT#1#2{\IfFileLoadedTF{#1}{#2}{}}
+\def\IfFileLoadedF #1{\IfFileLoadedTF{#1}{}}
+% \end{macrocode}
+% For rollback/rollforward pretend everything was available since
+% the beginning of dawn.
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\IfPackageLoadedT}{More conditionals}%
+%<latexrelease>
+%<latexrelease>\def\IfPackageLoadedT #1#2{\IfPackageLoadedTF{#1}{#2}{}}
+%<latexrelease>\def\IfPackageLoadedF #1{\IfPackageLoadedTF{#1}{}}
+%<latexrelease>\def\IfClassLoadedT #1#2{\IfClassLoadedTF{#1}{#2}{}}
+%<latexrelease>\def\IfClassLoadedF #1{\IfClassLoadedTF{#1}{}}
+%<latexrelease>\def\IfPackageAtLeastT#1#2#3{\IfPackageAtLeastTF{#1}{#2}{#3}{}}
+%<latexrelease>\def\IfPackageAtLeastF #1#2{\IfPackageAtLeastTF{#1}{#2}{}}
+%<latexrelease>\def\IfClassAtLeastT #1#2#3{\IfClassAtLeastTF{#1}{#2}{#3}{}}
+%<latexrelease>\def\IfClassAtLeastF #1#2{\IfClassAtLeastTF{#1}{#2}{}}
+%<latexrelease>\def\IfFileAtLeastT #1#2#3{\IfFileAtLeastTF{#1}{#2}{#3}{}}
+%<latexrelease>\def\IfFileAtLeastF #1#2{\IfFileAtLeastTF{#1}{#2}{}}
+%<latexrelease>\def\IfFormatAtLeastT #1#2{\IfFormatAtLeastTF{#1}{#2}{}}
+%<latexrelease>\def\IfFormatAtLeastF #1{\IfFormatAtLeastTF{#1}{}}
+%<latexrelease>\def\IfPackageLoadedWithOptionsT #1#2#3{\IfPackageLoadedWithOptionsTF{#1}{#2}{#3}{}}
+%<latexrelease>\def\IfPackageLoadedWithOptionsF #1#2{\IfPackageLoadedWithOptionsTF{#1}{#2}{}}
+%<latexrelease>\def\IfClassLoadedWithOptionsT #1#2#3{\IfClassLoadedWithOptionsTF{#1}{#2}{#3}{}}
+%<latexrelease>\def\IfClassLoadedWithOptionsF #1#2{\IfClassLoadedWithOptionsTF{#1}{#2}{}}
+%<latexrelease>
+%<latexrelease>\def\IfFileLoadedTF#1{%
+%<latexrelease> \expandafter\ifx\csname ver@#1\endcsname\relax
+%<latexrelease> \expandafter\@secondoftwo
+%<latexrelease> \else
+%<latexrelease> \expandafter\@firstoftwo
+%<latexrelease> \fi}
+%<latexrelease>\def\IfFileLoadedT#1#2{\IfFileLoadedTF{#1}{#2}{}}
+%<latexrelease>\def\IfFileLoadedF #1{\IfFileLoadedTF{#1}{}}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
% \begin{macro}{\ProvidesPackage}
% Checks that the current filename is correct, and defines
% |\ver@filename|.
@@ -1327,11 +1421,11 @@
% \changes{v1.4c}{2021/06/06}
% {apply \cs{expandafter} to raw options for gh/580}
% \begin{macrocode}
- \@ifundefined{@raw@opt@#3.#1}%
- {\expandafter\gdef\csname @raw@opt@#3.#1\expandafter\endcsname
- \expandafter{#2}}%
- {\expandafter\g@addto@macro\csname @raw@opt@#3.#1\expandafter\endcsname
- \expandafter{\expandafter,#2}}%
+ \@ifundefined{@raw@opt@#3.#1}%
+ {\expandafter\gdef\csname @raw@opt@#3.#1\expandafter\endcsname
+ \expandafter{#2}}%
+ {\expandafter\g@addto@macro\csname @raw@opt@#3.#1\expandafter\endcsname
+ \expandafter{\expandafter,#2}}%
}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
@@ -1950,12 +2044,34 @@
% \end{macro}
%
% \begin{macro}{\@fileswithoptions}
+% \changes{v1.5i}{2024/01/30}{Test group level}
% The common part of |\documentclass| and |\usepackage|.
% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2024/06/01}%
+%<latexrelease> {\@fileswithoptions}{Check Group}%
+%<*2ekernel|latexrelease>
\def\@fileswithoptions#1{%
+ \ifnum\currentgrouplevel>\z@
+ \@latex@error
+ {Loading a class or package in a group}%
+ {Classes and packages should only be loaded at the top level}%
+ \fi
\@ifnextchar[%]
{\@fileswith@ptions#1}%
{\@fileswith@ptions#1[]}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@fileswithoptions}{Check Group}%
+%<latexrelease>\def\@fileswithoptions#1{%
+%<latexrelease> \@ifnextchar[%]
+%<latexrelease> {\@fileswith@ptions#1}%
+%<latexrelease> {\@fileswith@ptions#1[]}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \begin{macrocode}
\@onlypreamble\@fileswithoptions
% \end{macrocode}
%
@@ -2221,9 +2337,17 @@
% \end{macrocode}
% \changes{v1.5d}{2022/10/10}{Use \cs{protected@edef}.}
% \begin{macrocode}
- \expandafter\protected@edef\csname opt@\@currname.\@currext\endcsname
+ \expandafter\protected@edef
+ \csname opt@\@currname.\@currext\endcsname
{\zap@space#2 \@empty}%
- \@namedef{@raw@opt@\@currname.\@currext}{#2}%
+% \end{macrocode}
+% \changes{v1.5j}{2024/03/22}
+% {Apply one-step expansion to raw option list,
+% to be consistent with change for gh/580 (gh/1298).}
+% \begin{macrocode}
+ \expandafter\def
+ \csname @raw@opt@\@currname.\@currext\expandafter\endcsname
+ \expandafter{#2}%
\@nameuse{opt@handler@\@currname.\@currext}%
}%
}%
@@ -2624,8 +2748,8 @@
%
% Allow code to be saved to be executed at specific later times.
%
-% Save things in macros, I considered using toks registers, (and
-% |\addto@hook| from the NFSS code, that would require stacking the
+% Here we save things in macros. I considered using toks registers (and
+% |\addto@hook| from the NFSS code), but that would require stacking the
% contents in the case of required packages, so just generate a new
% macro for each package.
% \begin{macro}{\@begindocumenthook}
@@ -2997,7 +3121,7 @@
\let\do\@makeother\dospecials%
% \end{macrocode}
% If there are active characters in the upper half (e.g., from
-% \texttt{inputenc} there would be confusion so we render everything
+% \texttt{inputenc}) there would be confusion so we render everything
% harmless.
% \changes{v1.2f}{2018/03/27}
% {Use full file name for old release}
@@ -3585,7 +3709,7 @@
% and therefore we can now test its value. If the value is zero we
% assume that the remaining argument string represents a version
% and change |\pkgcls@targetdate| and set |\pkgcls@targetlabel| to
-% the version name (after stripping off the trailing \texttt{=}.
+% the version name (after stripping off the trailing \texttt{=}).
% \begin{macrocode}
\ifnum \pkgcls@targetdate=\z@
\pkgcls@targetdate\@ne
@@ -3695,7 +3819,7 @@
% late, but if there wasn't one (i.e., if current release is the
% oldest that exists) we use it as the best choice. However in
% that case something is wrong (as there shouldn't be a rollback to
-% a date where a package used doesn't yet exists. So we make a
+% a date when a package used didn't yet exists). So we make a
% complained to the user.
% \begin{macrocode}
\ifx\pkgcls@candidate\@empty
diff --git a/Master/texmf-dist/source/latex/base/ltcmd.dtx b/Master/texmf-dist/source/latex/base/ltcmd.dtx
index 0a6cb1a53c5..69bd162e56b 100644
--- a/Master/texmf-dist/source/latex/base/ltcmd.dtx
+++ b/Master/texmf-dist/source/latex/base/ltcmd.dtx
@@ -34,8 +34,8 @@
%%% From File: ltcmd.dtx
%
% \begin{macrocode}
-\def\ltcmdversion{v1.2a}
-\def\ltcmddate{2023-08-19}
+\def\ltcmdversion{v1.2e}
+\def\ltcmddate{2024-04-17}
% \end{macrocode}
%
%<*driver>
@@ -415,8 +415,6 @@
\cs_new_protected:Npn \@@_declare_cmd_internal:Nnnn #1#2#3#4
{
\tl_set:Nx \l_@@_function_tl { \cs_to_str:N #1 }
- \tl_set:Nx \l_@@_fn_tl
- { \exp_not:c { \l_@@_function_tl \c_space_tl } }
\@@_normalize_arg_spec:n {#2}
\exp_args:No \@@_prepare_signature:n \l_@@_arg_spec_tl
\@@_declare_cmd_code:Nnn #1 {#2} {#3}
@@ -435,17 +433,93 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[EXP]{\@@_all_m_check:n, \@@_all_m_check_aux:n}
+% A quick loop to check for all |(+)m|-type arguments.
+% \begin{macrocode}
+\cs_new:Npn \@@_all_m_check:n #1
+ { \tl_map_function:nN {#1} \@@_all_m_check_aux:n }
+\cs_new:Npn \@@_all_m_check_aux:n #1
+ {
+ \str_if_eq:nnF {#1} { m }
+ {
+ \str_if_eq:nnF {#1} { + }
+ { X }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_declare_cmd_code:Nnn}
% \begin{macro}
-% {\@@_declare_cmd_code_aux:Nnn, \@@_declare_cmd_code_expandable:Nnn}
-% The appropriate auxiliary is called.
+% {
+% \@@_declare_cmd_optimized:Nnn,
+% \@@_declare_cmd_code_aux:Nnn,
+% \@@_declare_cmd_code_expandable:Nnn
+% }
+% \begin{macro}{\@@_start_optimized:}
+% \changes{v1.2b}{2023/12/01}
+% {Optimize cmd creation for all-\texttt{m} arguments}
+% At this stage we can check for a short-cut possibility: if the argument
+% specification is made up of just |(+)m| tokens, and if all arguments are
+% either short or long, then we can produce an optimized document command.
+% This only applies to document commands, not creation of environments (which
+% are more complex).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_cmd_code:Nnn #1#2
+ {
+ \bool_lazy_any:nTF
+ {
+ { \l_@@_environment_bool }
+ {
+ \bool_lazy_and_p:nn
+ { \l_@@_some_short_bool }
+ { \l_@@_some_long_bool }
+ }
+ { ! \tl_if_blank_p:e { \@@_all_m_check:n {#2} } }
+ }
+ {
+ \tl_set:Nx \l_@@_fn_tl
+ { \exp_not:c { \l_@@_function_tl \c_space_tl } }
+ \bool_if:NTF \l_@@_grab_expandably_bool
+ { \@@_declare_cmd_code_expandable:Nnn }
+ { \@@_declare_cmd_code_aux:Nnn }
+ }
+ { \@@_declare_cmd_optimized:Nnn }
+ #1 {#2}
+ }
+% \end{macrocode}
+% The optimized version of commands just has to worry about whether to make
+% them protected or long. The commands start with an expandable marker so
+% that other parts of the kernel know these are set up by \pkg{ltcmd}.
+% We need the two layers of redirection so that the \texttt{code} internal
+% function has the same form as it would for any other document command.
+% Optimization means that there is no \cs{group_align_safe_begin:} before
+% grabbing the arguments, so anything involving |&| tokens will not work.
+% However, this is really only intended for making optional argument
+% processing safe anyway, so in practice should not be an issue.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_declare_cmd_code:Nnn
+\cs_new_protected:Npn \@@_declare_cmd_optimized:Nnn #1#2#3
{
- \bool_if:NTF \l_@@_grab_expandably_bool
- { \@@_declare_cmd_code_expandable:Nnn }
- { \@@_declare_cmd_code_aux:Nnn }
- }
+ \bool_if:NTF \l_@@_expandable_bool
+ { \cs_set_nopar:Npe }
+ { \cs_set_protected_nopar:Npe }
+ #1
+ {
+ \exp_not:N \@@_start_optimized:
+ \exp_not:c { \l_@@_function_tl \c_space_tl code }
+ }
+ \exp_args:Ncc \cs_generate_from_arg_count:NNnn
+ { \l_@@_function_tl \c_space_tl code }
+ {
+ cs_set
+ \bool_if:NF \l_@@_expandable_bool { _protected }
+ \bool_if:NF \l_@@_some_long_bool { _nopar }
+ :Npn
+ }
+ \l_@@_current_arg_int
+ {#3}
+ }
+\cs_new:Npn \@@_start_optimized: { }
% \end{macrocode}
% Standard functions call \cs{@@_start:nNNnnn}, which receives the
% argument specification, an auxiliary used for
@@ -544,6 +618,7 @@
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\@@_declare_env:nnnn}
% \begin{macro}{\@@_declare_env_internal:nnnn}
@@ -1286,7 +1361,7 @@
% that is not possible without the risk of mistakenly grabbing the
% entire brace group (potentially leading to a~\texttt{!~Runaway argument}
% error) or trying to grab a |}|$_2$, leading to
-% an~\verb|! Argument of \dots has an extra }| error.
+% \iffalse{\fi an~\verb|! Argument of \dots has an extra }| error.
% \begin{macrocode}
\cs_new_protected:Npn \@@_allowed_token_check:N #1
{
@@ -1373,6 +1448,9 @@
% \end{macro}
%
% \begin{macro}{\@@_add_arg_spec:n, \@@_add_arg_spec_mandatory:n}
+% \changes{v1.2c}{2023/12/22}
+% {Clarify error message when \texttt{!} prefix is applied to
+% non-trailing opt-arg (gh/1198)}
% When adding an argument to the argument specification, set the
% \texttt{some_long} or \texttt{some_short} booleans as appropriate
% and clear the booleans keeping track of |+|, |!| and |=| markers.
@@ -1414,7 +1492,12 @@
\bool_if:NT \l_@@_some_obey_spaces_bool
{
\msg_error:nnxx { cmd } { invalid-bang }
- { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ { \@@_environment_or_command: }
+ {
+ \bool_if:NTF \l_@@_obey_spaces_bool
+ { \tl_to_str:n {'#1'} }
+ { an~optional~argument~before~mandatory~ \tl_to_str:n {'#1'} }
+ }
\@@_bad_def:wn
}
\tl_clear:N \l_@@_last_delimiters_tl
@@ -1626,8 +1709,10 @@
% argument, so we need to break out of one layer of braces in
% \cs{l_@@_process_one_tl}, add copies of the processor as necessary,
% and then return the removed brace. The function below does just
-% that: it defines \cs{l_@@_process_one_tl} starting with a |}|$_2$
-% and ending with a |{|$_1$, so that it adds as many processors as
+% that: it defines \cs{l_@@_process_one_tl} starting with a
+% \iffalse{\fi |}|$_2$
+% and ending with a |{|$_1$, \iffalse}\fi
+% so that it adds as many processors as
% needed when |x|-expanded.
% \begin{macrocode}
\cs_new_protected:Npn \@@_replicate_processor:nn #1 #2
@@ -2033,7 +2118,7 @@
% \begin{macro}{\@@_copy:NN}
% \begin{macro}{\@@_set_eq_if_exist:NN,\@@_set_eq_if_exist:cc}
% This macro just branches to the proper copying command by using
-% \cs{@@_cmd_type_cases:NnnnnF}. The copying command takes the names
+% \cs{@@_cmd_type_cases:NnnnnnF}. The copying command takes the names
% of the commands to be copied to and from, and the actual commands
% as its four arguments.
% \begin{macrocode}
@@ -2042,9 +2127,10 @@
\use:x
{
\int_set:Nn \tex_escapechar:D { 92 }
- \exp_not:N \@@_cmd_type_cases:NnnnnF \exp_not:N #2
+ \exp_not:N \@@_cmd_type_cases:NnnnnnF \exp_not:N #2
{ \@@_copy_command:nnNN }
{ \@@_copy_expandable:nnNN }
+ { \@@_copy_optimized:nnNN }
{ \@@_copy_environment:nnNN }
{ \@@_copy_environment_end:nnNN }
{ \@@_cant_copy:nwn { non-ltcmd } }
@@ -2186,6 +2272,24 @@
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
+% \begin{macro}{\@@_copy_optimized:nnNN}
+% Copy the code, simply define the wrapper.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_copy_optimized:nnNN #1#2#3#4
+ {
+ \cs_set_eq:cc { #1 ~ code } { #2 ~ code }
+ \token_if_protected_macro:NTF #4
+ { \cs_set_protected_nopar:Npe }
+ { \cs_set_nopar:Npe }
+ #3
+ {
+ \exp_not:N \@@_start_optimized:
+ \exp_not:c { #1 ~ code }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_copy:NN (part 2)}%
%<latexrelease> {Support~\NewCommandCopy~in~ltcmd}
@@ -2423,7 +2527,7 @@
%
% \begin{macro}{\@@_show:N}
% This macro just branches to the proper showing command by using
-% \cs{@@_cmd_type_cases:NnnnnF}. The showing command takes the command
+% \cs{@@_cmd_type_cases:NnnnnnF}. The showing command takes the command
% to be shown as argument.
% \begin{macrocode}
\cs_new_protected:Npn \@@_show:N #1
@@ -2431,9 +2535,10 @@
\use:x
{
\int_set:Nn \tex_escapechar:D { 92 }
- \exp_not:N \@@_cmd_type_cases:NnnnnF \exp_not:N #1
+ \exp_not:N \@@_cmd_type_cases:NnnnnnF \exp_not:N #1
{ \@@_show_command:N }
{ \@@_show_expandable:N }
+ { \@@_show_optimized:N }
{ \@@_show_environment:N }
{ \@@_show_environment_end:N }
{ \@@_cant_copy:nwn { non-ltcmd } }
@@ -2450,6 +2555,7 @@
% \@@_show_command:NnNNwN,
% \@@_show_expandable:N,
% \@@_show_expandable:NnNNNNnN,
+% \@@_show_optimized:N,
% \@@_show_command_aux:NnNNn,
% \@@_show_environment:N,
% \@@_show:x,
@@ -2530,6 +2636,48 @@
}
% \end{macrocode}
%
+% Optimized functions need things done a bit differently as we need to
+% reconstruct the argument spec.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_optimized:N #1
+ {
+ \exp_args:Nc \@@_show_optimized:NN
+ { \cs_to_str:N #1 \c_space_tl code }
+ #1
+ }
+\cs_new_protected:Npn \@@_show_optimized:NN #1#2
+ {
+ \cs_set:Npe \@@_show_optimized_aux:N ##1
+ {
+ \c_space_tl \c_space_tl \c_hash_str ##1 :
+ \bool_lazy_or:nnT
+ { \token_if_long_macro_p:N #1 }
+ { \token_if_protected_long_macro_p:N #1 }
+ { + } m
+ \iow_newline:
+ }
+ \tl_show:e
+ {
+ \token_to_str:N #2 =
+ \bool_lazy_or:nnF
+ { \token_if_protected_macro_p:N #1 }
+ { \token_if_protected_long_macro_p:N #1 }
+ { expandable ~ } document~command:
+ \iow_newline:
+ \int_step_function:nN
+ {
+ \int_div_truncate:nn
+ { \tl_count:e { \cs_parameter_spec:N #1 } }
+ { 2 }
+ }
+ \@@_show_optimized_aux:N
+ ->
+ \cs_replacement_spec:N #1
+ }
+ }
+\cs_generate_variant:Nn \tl_count:n { e }
+% \end{macrocode}
+%
% We can reuse most of the above to show an environment, except that
% we need to ensure that the proper \cs[no-index]{environment~\ldots}
% are passed to \cs{@@_show_command_aux:NnNNn}. Additionally, when
@@ -3533,18 +3681,38 @@
% \end{macro}
%
% \begin{macro}{\@@_grab_v_aux_put:N}
+% \changes{v1.2d}{2024/03/21}{Collect \cs{endlinechar} as \cs{obeyedline}}
% Storing one token in the collected argument. Most tokens are
% converted to category code $12$, with the exception of active
% characters, and spaces (not sure what should be done for those).
% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2024/06/01}{\@@_grab_v_aux_put:N}%
+%<latexrelease> {Endlines~as~\obeyedline}
\cs_new_protected:Npn \@@_grab_v_aux_put:N #1
{
\tl_put_right:Nx \l_@@_v_arg_tl
{
\token_if_active:NTF #1
- { \exp_not:N #1 } { \token_to_str:N #1 }
+ { \exp_not:N #1 }
+ {
+ \int_compare:nNnTF {`#1} = \tex_endlinechar:D
+ { \exp_not:N \obeyedline }
+ { \token_to_str:N #1 }
+ }
}
}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_grab_v_aux_put:N}%
+%<latexrelease> {Endlines~as~\obeyedline}
+%<latexrelease>\cs_new_protected:Npn \@@_grab_v_aux_put:N #1
+%<latexrelease> {
+%<latexrelease> \tl_put_right:Nx \l_@@_v_arg_tl
+%<latexrelease> {
+%<latexrelease> \token_if_active:NTF #1
+%<latexrelease> { \exp_not:N #1 } { \token_to_str:N #1 }
+%<latexrelease> }
+%<latexrelease> }
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
%
@@ -4376,13 +4544,16 @@
% \end{macro}
%
% \begin{macro}{\__kernel_cmd_if_xparse:NTF}
-% \begin{macro}{\@@_cmd_type_cases:Nnnnn}
+% \begin{macro}{\@@_cmd_type_cases:NnnnnnF}
% \changes{v1.0d}{2021/04/19}{Renamed \cs{__cmd_cmd_if_xparse:NTF} to
% \cs{__kernel_cmd_if_xparse:NTF} for cross-module usage}
% \changes{v1.0d}{2021/07/30}{Added \cs{@@_cmd_type_cases:NnnnnF} for
% \cs{NewCommandCopy} and \cs{ShowCommand} support}
% \changes{v1.0l}{2022/03/18}{Fix \cs{@@_cmd_type_cases:NnnnnF}
-%" prematurely expanding macros (gh/795)}
+% prematurely expanding macros (gh/795)}
+% \changes{v1.2b}{2023/12/01}{Extend for optimized commands}
+% \changes{v1.2e}{2024/04/17}{Use \cs{__kernel_cs_parameter_spec:N} instead
+% of \cs{cs_argument_spec:N}/\cs{cs_parameter_spec:N}}
% \begin{macro}{\@@_cmd_if_xparse_aux:N}
%
% To determine whether the command is an \pkg{xparse} command check
@@ -4390,36 +4561,38 @@
% that its |replacement_spec| starts with either
% \cs{@@_start:nNNnnn} (non-expandable command) or
% \cs{@@_start_expandable:nNNNNn} (expandable command) or
+% \cs{@@_start_optimized:} (optimized command) or
% \cs{@@_start_env:nnnnn} (environment) or
% \cs[no-index]{environment~\#1~end~aux} (environment end).
%
% This conditional is needed in several kernel modules and is
% therefore has a kernel-internal name.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_cmd_type_cases:NnnnnF #1 #2 #3 #4 #5 #6
+\cs_new_protected:Npn \@@_cmd_type_cases:NnnnnnF #1 #2 #3 #4 #5 #6 #7
{
\exp_args:Ne \str_case_e:nnF
{
- \exp_args:Nf \tl_if_empty:nT { \cs_argument_spec:N #1 }
+ \exp_args:Nf \tl_if_empty:nT { \__kernel_cs_parameter_spec:N #1 }
{ \exp_not:N \exp_not:n { \exp_not:e { \tl_head:N #1 } } }
}
{
{ \exp_not:N \@@_start:nNNnnn } {#2}
{ \exp_not:N \@@_start_expandable:nNNNNn } {#3}
- { \exp_not:N \@@_start_env:nnnnn } {#4}
+ { \exp_not:N \@@_start_optimized: } {#4}
+ { \exp_not:N \@@_start_env:nnnnn } {#5}
{
\exp_after:wN \exp_not:N
\cs:w environment~
\exp_last_unbraced:Ne \use_none:nnn
{ \cs_to_str:N #1 } ~end~aux \cs_end:
- } {#5}
+ } {#6}
}
- {#6}
+ {#7}
}
\cs_new_protected:Npn \__kernel_cmd_if_xparse:NTF #1
{
- \@@_cmd_type_cases:NnnnnF #1
- { } { } { } { } { \use_iii:nnn }
+ \@@_cmd_type_cases:NnnnnnF #1
+ { } { } { } { } { } { \use_iii:nnn }
\use_i:nn
}
% \end{macrocode}
@@ -4511,10 +4684,8 @@
\bool_if:NTF \l_@@_environment_bool
{ environment ~ ' \l_@@_environment_str ' }
{
- command ~ '
- \exp_args:Nf \tl_trim_spaces:n
- { \exp_after:wN \token_to_str:N \l_@@_fn_tl }
- '
+ command ~
+ ' \c_backslash_str \tl_to_str:N \l_@@_function_tl '
}
}
% \end{macrocode}
@@ -4522,6 +4693,8 @@
%
% Some messages intended as errors when defining commands/environments.
% \changes{v1.0f}{2021/06/04}{Normalize various error messages}
+% \changes{v1.2c}{2023/12/22}
+% {Generalize message \texttt{invalid-bang} (gh/1198)}
% \begin{macrocode}
\msg_new:nnnn { cmd } { arg-after-body }
{ Argument~type~'b'~must~be~last~in~#1. }
@@ -4612,7 +4785,7 @@
{ Invalid~argument~prefix~'!'~in~#1. }
{
The~prefix~'!'~is~only~allowed~for~trailing~optional~arguments.~
- You~tried~to~apply~it~to~'#2'.
+ You~tried~to~apply~it~to~#2.
\c_@@_ignore_def_tl
}
\msg_new:nnnn { cmd } { not-definable }
diff --git a/Master/texmf-dist/source/latex/base/ltcmdhooks.dtx b/Master/texmf-dist/source/latex/base/ltcmdhooks.dtx
index 73bd7f63518..f8a8699d7ed 100644
--- a/Master/texmf-dist/source/latex/base/ltcmdhooks.dtx
+++ b/Master/texmf-dist/source/latex/base/ltcmdhooks.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: ltcmdhooks.dtx
+%% From File: ltcmdhooks.dtx
%% Copyright (C) 2020-2024
%% Frank Mittelbach, Phelype Oleinik, The LaTeX Project
%
@@ -12,16 +12,20 @@
% https://www.latex-project.org/lppl.txt
%
%
-%%% From File: ltcmdhooks.dtx
-%
-\def\ltcmdhooksversion{v1.0i}
-\def\ltcmdhooksdate{2023/06/16}
-%
+% \fi
%
+% \iffalse
+%%% From File: lthooks.dtx
%
%<*driver>
+% \fi
+\ProvidesFile{ltcmdhooks.dtx}
+ [2024/04/17 v1.0j LaTeX Kernel (Command hooks)]
+% \iffalse
+%
\documentclass{l3doc}
-%\usepackage{ltcmdhooks}
+\GetFileInfo{ltcmdhooks.dtx}
+% \usepackage{ltcmdhooks}
\EnableCrossrefs
\CodelineIndex
\begin{document}
@@ -38,7 +42,7 @@
% \providecommand\phoinline[1]{\begin{quote}\itshape\footnotesize PhO: #1\end{quote}}
%
% \title{The \texttt{ltcmdhooks} module\thanks{This file has version
-% \ltcmdhooksversion\ dated \ltcmdhooksdate, \copyright\ \LaTeX\
+% \fileversion\ dated \filedate, \copyright\ \LaTeX\
% Project.}}
% \author{Frank Mittelbach \and Phelype Oleinik}
%
@@ -125,8 +129,8 @@
% \item
%
% that code can be prepended or appended (i.e., added to the
-% hooks) even if the command itself is not defined, because the
-% defining package has not yet been loaded;
+% hooks) even if the command itself is not (yet) defined, because the
+% defining package has not been loaded at this point;
%
% \item
%
@@ -214,6 +218,14 @@
% optional and mandatory arguments. By adding code to the
% \hook{cmd/section/after} hook, you get in the way of that scanning.
%
+% In such a case, where it is known that a specific generic command
+% hook does not work if code is added to it, the package author can
+% add a \cs{DisableGenericHook}\footnote{Please use
+% \cs{DisableGenericHook} if at all, only on hooks that you
+% \enquote{own}, i.e., for commands your package or class defines and
+% not second guess whether or not hooks of other packages should get
+% disabled!} declaration to prevent this from happening in user
+% documents and thereby avoiding obscure errors.
%
%
% \section{Package Author Interface}
@@ -394,6 +406,8 @@
% \end{macrocode}
%
% \changes{v1.0b}{2021/05/24}{Use \cs{msg_...} instead of \cs{__kernel_msg...}}
+% \changes{v1.0j}{2024/04/17}{Use \cs{__kernel_cs_parameter_spec:N} instead
+% of \cs{cs_argument_spec:N}/\cs{cs_parameter_spec:N}}
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
@@ -643,7 +657,7 @@
}
}
% \end{macrocode}
-% and a conditional \cs{@@_if_public_command:N} to check if a command
+% and a conditional \cs{@@_if_public_command:NTF} to check if a command
% has |__| in its name (no other checking is performed). Primitives
% with |:D| in their name could be included here, but they are already
% discarded in the \cs{token_if_macro:NTF} test above.
@@ -838,14 +852,14 @@
\@@_patch_debug:x { ++~command~can~be~patched~without~rescanning }
% \end{macrocode}
% We'll start by counting the number of arguments in the command by
-% counting the number of characters in the \cs{cs_argument_spec:N} of
+% counting the number of characters in the \cs{cs_parameter_spec:N} of
% the macro, divided by two, and subtracting one if the command has an
% optional argument (that is, an extra |[]| in its
% \meta{parameter text}).
% \begin{macrocode}
\int_set:Nn \l_@@_patch_num_args_int
{
- \exp_args:Nf \str_count:n { \cs_argument_spec:N #2 } / 2
+ \exp_args:Nf \str_count:n { \__kernel_cs_parameter_spec:N #2 } / 2
\bool_if:NT #1 { -1 }
}
% \end{macrocode}
@@ -998,7 +1012,7 @@
%<latexrelease> \@@_patch_debug:x { ++~command~can~be~patched~without~rescanning }
%<latexrelease> \int_set:Nn \l_@@_patch_num_args_int
%<latexrelease> {
-%<latexrelease> \exp_args:Nf \str_count:n { \cs_argument_spec:N #2 } / 2
+%<latexrelease> \exp_args:Nf \str_count:n { \__kernel_cs_parameter_spec:N #2 } / 2
%<latexrelease> \bool_if:NT #1 { -1 }
%<latexrelease> }
%<latexrelease> \int_compare:nNnTF { \l_@@_patch_num_args_int } > { \c_zero_int }
@@ -1248,12 +1262,12 @@
% top-level macro with no arguments, so testing this first would
% short-circuit \tn{robust@command@act} and the top-level macros would
% be incorrectly patched. In that case, we just check if the
-% \cs{cs_argument_spec:N} is empty, and call
+% \cs{cs_parameter_spec:N} is empty, and call
% \cs{@@_patch_expand_redefine:NNnn}.
% \begin{macrocode}
\cs_new_protected:Npn \@@_retokenize_patch:Nnn #1 #2 #3
{
- \str_if_eq:eeTF { \cs_argument_spec:N #1 } { }
+ \str_if_eq:eeTF { \__kernel_cs_parameter_spec:N #1 } { }
{ \@@_patch_expand_redefine:NNnn \c_false_bool #1 {#2} {#3} }
{
\@@_patch_debug:x { ..~command~can~only~be~patched~by~rescanning }
diff --git a/Master/texmf-dist/source/latex/base/ltcounts.dtx b/Master/texmf-dist/source/latex/base/ltcounts.dtx
index c58ad2dcb61..006486d23b2 100644
--- a/Master/texmf-dist/source/latex/base/ltcounts.dtx
+++ b/Master/texmf-dist/source/latex/base/ltcounts.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltcounts.dtx}
- [2021/07/08 v1.1m LaTeX Kernel (Counters)]
+ [2021/11/08 v1.1n LaTeX Kernel (Counters)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltcounts.dtx}
@@ -305,6 +305,7 @@
% \begin{macro}{\@definecounter}
% \changes{v1.1b}{1995/05/20}{Streamlined code}
% \changes{v1.1c}{1995/05/20}{And do it right}
+% \changes{v1.1n}{2023/11/07}{Do not change \cs{the...} if already defined (gh/823)}
%
% \begin{macrocode}
\def\@definecounter#1{\expandafter\newcount\csname c@#1\endcsname
@@ -312,9 +313,21 @@
\global\expandafter\let\csname cl@#1\endcsname\@empty
\@addtoreset{#1}{@ckpt}%
\global\expandafter\let\csname p@#1\endcsname\@empty
+% \end{macrocode}
+% If \cs{the\#1} is undefined or \cs{relax} we define it with the
+% standard definition for counters, otherwise we warn. This will
+% catch, for example, that somebody defines a counter named
+% ``index'' conflicting with the \env{theindex} environment.
+% \begin{macrocode}
\expandafter
- \gdef\csname the#1\expandafter\endcsname\expandafter
- {\expandafter\@arabic\csname c@#1\endcsname}}
+ \ifx\csname the#1\endcsname\relax
+ \expandafter
+ \gdef\csname the#1\expandafter\endcsname\expandafter
+ {\expandafter\@arabic\csname c@#1\endcsname}%
+ \else
+ \@latex@warning{Command `\string\the#1' already
+ defined -- not changed}%
+ \fi}
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/ltdefns.dtx b/Master/texmf-dist/source/latex/base/ltdefns.dtx
index 24c13696985..d9ec12e75a6 100644
--- a/Master/texmf-dist/source/latex/base/ltdefns.dtx
+++ b/Master/texmf-dist/source/latex/base/ltdefns.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltdefns.dtx}
- [2022/11/24 v1.5s LaTeX Kernel (definition commands)]
+ [2024/04/17 v1.5t LaTeX Kernel (definition commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltdefns.dtx}
@@ -91,6 +91,9 @@
% \changes{v1.4b}{2015/02/21}
% {Removed autoload support}
% \changes{v1.5l}{2020/08/21}{Integration of new hook management interface}
+% \changes{v1.5t}{2024/04/17}
+% {Rename \cs{@expl@cs@argument@spec@@N} to
+% \cs{@expl@cs@parameter@spec@@N} (gh/1014)}
%
% \section{Definitions}
%
@@ -215,12 +218,12 @@
% This section defines the following commands:
%
% \DescribeMacro
-% {\@namedef}\marg{NAME}\\ Expands to |\def\|\marg{NAME},
+% {\@namedef}\marg{NAME}\\ Expands to |\def\|\meta{NAME},
% except name can contain any characters.
%
% \DescribeMacro
% {\@nameuse}\marg{NAME}\\
-% Expands to |\|\marg{NAME}.
+% Expands to |\|\meta{NAME}.
%
% \DescribeMacro
% {\@ifnextchar} X\marg{YES}\marg{NO}\\
@@ -530,9 +533,11 @@
% This macro encapsulates the most common call to |\@ifnextchar|, saving
% several tokens each time it is used in the definition of a command
% with an optional argument.
-% |#1| The code to execute in the case that there is a |[| need not be
+% |#1| The code to execute in the case that there is a |[| \iffalse]\fi
+% need not be
% a single token but can be any sequence of commands that `expects' to
-% be followed by |[|. If this command were only used in |\newcommand|
+% be followed by |[|. \iffalse]\fi
+% If this command were only used in |\newcommand|
% definitions then |#1| would be a single token and the braces could
% be omitted from |{#1}| in the definition below, saving a bit of
% memory.
@@ -595,7 +600,7 @@
% required argument spec by using a delimited argument (delimited
% by the digit). This is faster and uses less tokens. The coding
% is slightly odd to preserve the old interface (using |#2| =
-% |\tw@| as the flag to surround the first argument with |[]|. But
+% |\tw@| as the flag to surround the first argument with |[]|). But
% the new method did not allow for the number of arguments |#3| not
% being given as an explicit digit; hence (further expansion of
% this argument and use of) |\number| was added later in 1999.
@@ -706,13 +711,14 @@
% \begin{macro}{\newenvironment}
% Define a new user environment.
% |#1| is the environment name. |#2#| Grabs all the tokens up to
-% the first |{|. These will be any optional arguments. They are not
+% the first |{|. \iffalse}\fi
+% These will be any optional arguments. They are not
% parsed at this point, but are just passed to |\@newenv| which
% will eventually call |\newcommand|. Any optional arguments will
% then be parsed by |\newcommand| as it defines the command that
% executes the `begin code' of the environment.
%
-% This |#2#| trick removed with version 1.2i as it fails if a |{|
+% This |#2#| trick removed with version 1.2i as it fails if a |{| \iffalse}\fi
% occurs in the optional argument. Now use |\@ifnextchar| directly.
% \begin{macrocode}
\def\newenvironment{\@star@or@long\new@environment}
@@ -888,7 +894,8 @@
% \begin{macro}{\@check@c}
% \changes{v1.2i}{1995/04/25}{Make \cs{long} for latex/1346}
% |\CheckCommand| itself just grabs all the arguments we need,
-% without actually looking for |[| optional argument forms. Now
+% without actually looking for |[| \iffalse]\fi
+% optional argument forms. Now
% define |\reserved@a|. If |\\reserved@a| is then defined, compare it
% with the ``|\#1|' otherwise compare |\reserved@a| with |#1|.
% \begin{macrocode}
@@ -2016,7 +2023,7 @@
\long\def\@show@newcommand@aux#1#2#3{%
\typeout{> \string#1=\@expl@cs@prefix@spec@@N#1macro:}%
#3{default \string##1=\expandafter\detokenize\@gobblethree#2.^^J%
- \@expl@cs@argument@spec@@N#1->\@expl@cs@replacement@spec@@N#1}}
+ \@expl@cs@parameter@spec@@N#1->\@expl@cs@replacement@spec@@N#1}}
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -2117,7 +2124,7 @@
\@show@environment@end#1}
\long\def\@show@environment@begin#1{%
\typeout{> \string\begin{\@expl@cs@to@str@@N#1}=environment:}%
- \typeout{\@expl@cs@argument@spec@@N#1->%
+ \typeout{\@expl@cs@parameter@spec@@N#1->%
\@expl@cs@replacement@spec@@N#1.^^J}}
% \end{macrocode}
% \end{macro}
@@ -2139,7 +2146,7 @@
\long\def\@show@environment@end@aux#1#2{%
\@show@tokens{\string\end{\@expl@cs@to@str@@N#2}%
\ifx\relax#1=undefined%
- \else:^^J\@expl@cs@argument@spec@@N#1->%
+ \else:^^J\@expl@cs@parameter@spec@@N#1->%
\@expl@cs@replacement@spec@@N#1%
\fi}}
% \end{macrocode}
@@ -2158,7 +2165,7 @@
% \begin{macrocode}
\def\@show@nonstop#1{%
\typeout{> \string#1=\@expl@cs@prefix@spec@@N#1macro:^^J%
- \@expl@cs@argument@spec@@N#1->\@expl@cs@replacement@spec@@N#1.}}
+ \@expl@cs@parameter@spec@@N#1->\@expl@cs@replacement@spec@@N#1.}}
\def\@show@typeout#1{\typeout{> #1.^^J}}
% \end{macrocode}
% \end{macro}
@@ -2296,7 +2303,7 @@
% \changes{v1.3g}{2004/01/23}{Added macro (pr/3501)}
% This macro is the kernel version of |\@ifnextchar| which is used
% in a couple of places to prevent the AMS variant from being used
-% since in some places this produced chaos (for example
+% since in some places this produced chaos. For example,
% if an \texttt{fd} file
% is loaded in a random place then the optional argument to
% |\ProvidesFile| could get printed there instead of being written
diff --git a/Master/texmf-dist/source/latex/base/ltdirchk.dtx b/Master/texmf-dist/source/latex/base/ltdirchk.dtx
index ef959c56939..917431552b7 100644
--- a/Master/texmf-dist/source/latex/base/ltdirchk.dtx
+++ b/Master/texmf-dist/source/latex/base/ltdirchk.dtx
@@ -36,8 +36,10 @@
%</unstripped>
%<*driver>
% \fi
+% \fi
\ProvidesFile{ltdirchk.dtx}
- [2021/12/11 v1.3a LaTeX Kernel (System Dependent Parts)]
+ [2024/02/11 v1.3a LaTeX Kernel (System Dependent Parts)]
+% \iffalse
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltdirchk.dtx}
@@ -261,6 +263,10 @@
% In current formats enable primitives with unprefixed names.
% the \textsf{latexrelease} guards allow the primitives to be
% defined with a |\luatex| prefix if older formats are specified.
+%
+% The unprefixed forms are \emph{not} undefined for improved
+% compatibility with external packages when rolling back
+% the format.
% \begin{macrocode}
%</initex>
%</dircheck>
@@ -278,25 +284,6 @@
%<latexrelease> "luatex",
%<latexrelease> tex.extraprimitives("core","omega", "aleph", "luatex")
%<latexrelease> )
-%<latexrelease> local i
-%<latexrelease> local t = { }
-%<latexrelease> for _,i in pairs(tex.extraprimitives("luatex")) do
-%<latexrelease> if not string.match(i,"^U") then
-%<latexrelease> if not string.match(i, "^luatex") then
-%<latexrelease> table.insert(t,i)
-%<latexrelease> end
-%<latexrelease> else
-%<latexrelease> if string.match(i,"^Uchar$") then
-%<latexrelease> table.insert(t,i)
-%<latexrelease> end
-%<latexrelease> end
-%<latexrelease> end
-%<latexrelease> for _,i in pairs(t) do
-%<latexrelease> tex.print(
-%<latexrelease> "\noexpand\\let\noexpand\\" .. i
-%<latexrelease> .. "\noexpand\\undefined"
-%<latexrelease> )
-%<latexrelease> end
%<latexrelease>}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\fi
@@ -1000,8 +987,8 @@
% \begin{macro}{\@TeXversion}
% \TeX\ versions older than 3.141 require |\@TeXversion| to be
% set. This can be determined automatically due to a trick suggested
-% by Bernd Raichle. (Actually this will not always get the correct
-% version number, eg \TeX3.14 would be detected as \TeX3, but \LaTeX\
+% by Bernd Raichle. Actually this will not always get the correct
+% version number, e.g., \TeX3.14 would be detected as \TeX3, but \LaTeX\
% only needs to take account of \TeX's older than 3, or between 3 and
% 3.14.
% \changes{v1.0h}{1994/10/11}
diff --git a/Master/texmf-dist/source/latex/base/ltexpl.dtx b/Master/texmf-dist/source/latex/base/ltexpl.dtx
index 4aaf799e325..410235a056c 100644
--- a/Master/texmf-dist/source/latex/base/ltexpl.dtx
+++ b/Master/texmf-dist/source/latex/base/ltexpl.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltexpl.dtx}
- [2023/10/13 v1.3g LaTeX Kernel (expl3-dependent code)]
+ [2024/04/17 v1.3h LaTeX Kernel (expl3-dependent code)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltexpl.dtx}
@@ -356,9 +356,19 @@
% \changes{v1.2e}{2020/08/19}
% {Add \cs{@expl@cs@\meta{thing}@spec@@N}
% for \cs{ShowCommand} (gh/373)}
+% \changes{v1.3h}{2024/04/17}
+% {Rename \cs{@expl@cs@argument@spec@@N} to
+% \cs{@expl@cs@parameter@spec@@N} (gh/1014)}
+% \changes{v1.3h}{2024/04/17}
+% {Update name of \pkg{expl3} function}
+% \changes{v1.3h}{2024/04/17}
+% {Add a kernel-level copy of \cs{cs_parameter_spec:N}}
% \begin{macrocode}
\cs_gset_eq:NN \@expl@cs@prefix@spec@@N \cs_prefix_spec:N
-\cs_gset_eq:NN \@expl@cs@argument@spec@@N \cs_argument_spec:N
+\cs_if_exist:NTF \cs_parameter_spec:N
+ { \cs_gset_eq:NN \@expl@cs@parameter@spec@@N \cs_parameter_spec:N }
+ { \cs_gset_eq:NN \@expl@cs@parameter@spec@@N \cs_argument_spec:N }
+\cs_gset_eq:NN \__kernel_cs_parameter_spec:N \@expl@cs@parameter@spec@@N
\cs_gset_eq:NN \@expl@cs@replacement@spec@@N \cs_replacement_spec:N
% \end{macrocode}
%
@@ -387,7 +397,7 @@
%<latexrelease>\let \@expl@cs@to@str@@N \@undefined
%<latexrelease>\let \@expl@str@if@eq@@nnTF \@undefined
%<latexrelease>\let \@expl@cs@prefix@spec@@N \@undefined
-%<latexrelease>\let \@expl@cs@argument@spec@@N \@undefined
+%<latexrelease>\let \@expl@cs@parameter@spec@@N \@undefined
%<latexrelease>\let \@expl@cs@replacement@spec@@N \@undefined
%<latexrelease>\let \@expl@str@map@function@@NN \@undefined
%<latexrelease>\EndIncludeInRelease
diff --git a/Master/texmf-dist/source/latex/base/ltfilehook.dtx b/Master/texmf-dist/source/latex/base/ltfilehook.dtx
index 4f88b928712..02e95d0f8fa 100644
--- a/Master/texmf-dist/source/latex/base/ltfilehook.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfilehook.dtx
@@ -30,16 +30,22 @@
%
%%% From File: ltfilehook.dtx
%
-% \begin{macrocode}
-\providecommand\ltfilehookversion{v1.0o}
-\providecommand\ltfilehookdate{2023/07/10}
-% \end{macrocode}
-%
+% \fi
+%\iffalse
+%<*driver,structuredlog>
+%\fi
+\def\ltfilehookdate{2024/03/13}
+\def\ltfilehookversion{v1.0o}
+%\iffalse
+%</driver,structuredlog>
%<*driver>
-
+%\fi
+\expanded{\noexpand\ProvidesFile{ltfilehook.dtx}
+[\ltfilehookdate\space \ltfilehookversion\space LaTeX Kernel (hooks)]}
+% \iffalse
+%
\documentclass{l3doc}
-
\providecommand\InternalDetectionOff{}
\providecommand\InternalDetectionOn{}
@@ -375,7 +381,7 @@
%
%
%
-% \subsection{Internal interfaces for \LaTeX{}}
+% \subsection{Kernel, class, and package interfaces for \LaTeX{}}
%
% \begin{function}{\declare@file@substitution,\undeclare@file@substitution}
% \begin{syntax}
@@ -393,6 +399,8 @@
% example, or to provide a version that makes use of new kernel
% functionality while the original package remains available for
% use with older releases.
+% As such it is mainly meant for use in the \LaTeX{} kernel but
+% other use cases are conceivable.
%
% The \cs{undeclare@file@substitution} declaration undoes a
% substitution made earlier.
@@ -407,10 +415,10 @@
%
% \begin{function}{\disable@package@load,\reenable@package@load}
% \begin{syntax}
-% \cs{disable@package@load} \Arg{package} \Arg{alternate-code}
+% \cs{disable@package@load} \Arg{package} \Arg{alternate-code}
% \cs{reenable@package@load} \Arg{package}
% \end{syntax}
-% If \meta{package} is requested do not load it but instead run
+% If \meta{package} is requested, do not load it but instead run
% \meta{alternate-code} which could issue a warning, error or any
% other code.
%
@@ -421,7 +429,9 @@
% are not available.
%
% The function is only implemented for packages not for arbitrary
-% files.
+% files and again it should only be applied if there are good
+% reasons for doing this.\footnote{Just to be sure: \enquote{I don't
+% like this package by somebody else} is not a good one :-)}
% \end{function}
%
%
@@ -1328,7 +1338,7 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{flag @@_file_replaced}
+% \begin{macro}{@@_file_replaced}
% \begin{macro}{\@@_if_file_replaced:TF}
% \begin{macro}{\@@_clear_replacement_flag:}
% Since the file replacement is done expandably in a \cs{csname}, use
diff --git a/Master/texmf-dist/source/latex/base/ltfiles.dtx b/Master/texmf-dist/source/latex/base/ltfiles.dtx
index 92a957f6c51..2e2a8884a01 100644
--- a/Master/texmf-dist/source/latex/base/ltfiles.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfiles.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfiles.dtx}
- [2023/06/17 v1.2u LaTeX Kernel (File Handling)]
+ [2024/02/08 v1.2v LaTeX Kernel (File Handling)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfiles.dtx}
@@ -1087,7 +1087,7 @@
% \texttt{-1} we ensure that we don't get a backslash in front. As a
% result we end up with all characters as catcode 12 (plus
% spaces). We then sometimes add quotes around the construct
-% (removing any existing inner quotes. Sometimes we only remove the
+% (removing any existing inner quotes). Sometimes we only remove the
% quotes if they have been supplied by the user. There is clearly
% some room for improvement.
%
@@ -1682,6 +1682,22 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\if@listfiles@hashes}
+% \changes{v1.2v}{2023/11/15}{Extend file list information}
+% \begin{macro}{\if@listfiles@sizes}
+% \changes{v1.2v}{2023/11/15}{Extend file list information}
+% \begin{macrocode}
+\ExplSyntaxOn
+\keys_define:nn { __kernel / listfiles }
+ {
+ hashes .legacy_if_set:n = @listfiles@hashes ,
+ sizes .legacy_if_set:n = @listfiles@sizes
+ }
+\ExplSyntaxOff
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}{\listfiles}
% A preamble command to cause |\end{document}| to list files input
% from the main file.
@@ -1693,8 +1709,10 @@
% {Stop \cs{listfiles} being run twice}
% \changes{v1.0i}{1994/10/18}
% {code moved here from ltclass}
+% \changes{v1.2v}{2023/11/15}{Extend file list information}
% \begin{macrocode}
-\def\listfiles{%
+\NewDocumentCommand\listfiles{O{}}{%
+ \SetKeys[__kernel/listfiles]{#1}%
\let\listfiles\relax
\def\@listfiles##1##2##3##4##5##6##7##8##9\@@{%
\def\reserved@d{\\}%
@@ -1730,9 +1748,40 @@
\filename@area\filename@base\\\\\\\\\\\\\\\\\\\@@
\typeout{%
\filename@area\reserved@a
- \ifx\reserved@b\relax\else\@spaces\reserved@b\fi}}%
+ \ifx\reserved@b\relax\else\@spaces\reserved@b\fi
+% \end{macrocode}
+% Now we add the additional information if requested.
+% \begin{macrocode}
+ \ifnum0%
+ \if@listfiles@hashes1\fi
+ \if@listfiles@sizes1\fi
+ >0 %
+ ^^J\@spaces
+ (%
+ \if@listfiles@sizes
+ size \@dofilelist@size\@currname
+ \if@listfiles@hashes
+ , %
+ \fi
+ \fi
+ \if@listfiles@hashes
+ hash \@dofilelist@hash\@currname
+ \fi
+ )%
+ \fi
+ }}%
\typeout{ ***********^^J}}}
% \end{macrocode}
+% \begin{macro}{\@dofilelist@hash}
+% \begin{macro}{\@dofilelist@size}
+% \begin{macrocode}
+\ExplSyntaxOn
+\cs_new_eq:NN \@dofilelist@hash \file_mdfive_hash:n
+\cs_new_eq:NN \@dofilelist@size \file_size:n
+\ExplSyntaxOff
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
%
% \changes{LaTeX2e}{1994/03/13}
% {Reset \cs{@addtofilelist} at begin document}
diff --git a/Master/texmf-dist/source/latex/base/ltfinal.dtx b/Master/texmf-dist/source/latex/base/ltfinal.dtx
index f495cd41928..648e3e1b8bd 100644
--- a/Master/texmf-dist/source/latex/base/ltfinal.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfinal.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfinal.dtx}
- [2023/05/30 v2.3c LaTeX Kernel (Final Settings)]
+ [2024/02/08 v2.3c LaTeX Kernel (Final Settings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfinal.dtx}
@@ -273,7 +273,7 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{trace\string_stack\string_levels}
+% \begin{macro}{trace_stack_levels}
% Now define the Lua function to emulate \cs{tracingstacklevels} and
% install it in the |input_level_string| callback.
% \begin{macrocode}
@@ -1384,7 +1384,7 @@
% \end{macro}
%
% \begin{macro}{\@filelist}
-% \changes{v1.0w}{1995/10/19}{Move after \cs{reserved@a} setting:-)}
+% \changes{v1.0w}{1995/10/19}{Move after \cs{reserved@a} setting}
% \begin{macro}{\@addtofilelist}
% Reset |\@filelist| so files input while making the format are not
% listed. The list built up so far may take up a lot of memory and so
diff --git a/Master/texmf-dist/source/latex/base/ltfloat.dtx b/Master/texmf-dist/source/latex/base/ltfloat.dtx
index a07e5e81dae..ef057def0b8 100644
--- a/Master/texmf-dist/source/latex/base/ltfloat.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfloat.dtx
@@ -31,7 +31,7 @@
%
%<*driver>
% \fi
-\ProvidesFile{ltfloat.dtx}[2021/10/14 v1.2g LaTeX Kernel (Floats)]
+\ProvidesFile{ltfloat.dtx}[2024/04/22 v1.2g LaTeX Kernel (Floats)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfloat.dtx}
@@ -559,7 +559,7 @@
% set globally to false when they are definitely true.
%
% If anyone is unhappy with this argument then both flags should be
-% treated as in |\set@nobreak|; otherwise this command will be
+% treated as in |\@setnobreak|; otherwise this command will be
% redundant.
% \changes{v1.1p}{1996/10/24}
% {Added local settings of flags: dangerous!!}
@@ -1061,7 +1061,7 @@
% set globally to false when they are definitely true.
%
% If anyone is unhappy with this argument then both flags should be
-% treated as in |\set@nobreak|; otherwise this command will be
+% treated as in |\@setnobreak|; otherwise this command will be
% redundant.
% \changes{v1.1p}{1996/10/24}
% {Added local settings of flags: dangerous!!}
diff --git a/Master/texmf-dist/source/latex/base/ltfntcmd.dtx b/Master/texmf-dist/source/latex/base/ltfntcmd.dtx
index 360a4de8a49..097b8f692e4 100644
--- a/Master/texmf-dist/source/latex/base/ltfntcmd.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfntcmd.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfntcmd.dtx}
- [2021/09/12 v3.5a LaTeX Kernel (Font commands)]
+ [2023/12/26 v3.5a LaTeX Kernel (Font commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfntcmd.dtx}
@@ -393,9 +393,9 @@
% \end{macro}
-% \begin{macro}{textulc}
-% \begin{macro}{textsw}
-% \begin{macro}{textssc}
+% \begin{macro}{\textulc}
+% \begin{macro}{\textsw}
+% \begin{macro}{\textssc}
%
% \changes{v3.4c}{2019/12/17}{Macro added}
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltfssaxes.dtx b/Master/texmf-dist/source/latex/base/ltfssaxes.dtx
index 6fefa5cee9a..8b5014a4cc1 100644
--- a/Master/texmf-dist/source/latex/base/ltfssaxes.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssaxes.dtx
@@ -28,14 +28,14 @@
% \fi
% \iffalse
%%% From File: ltfssaxes.dtx
-%% Copyright (C) 1999-2020 Frank Mittelbach
+%% Copyright (C) 2019-2020 Frank Mittelbach
%
%<*driver>
% \fi
%
%
\ProvidesFile{ltfssaxes.dtx}
- [2023/10/30 v1.0i LaTeX Kernel (NFSS Axes handing)]
+ [2024/02/08 v1.0i LaTeX Kernel (NFSS Axes handing)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -1087,7 +1087,7 @@
%
% Shapes are also split in two axes (though it could be more if
% that is desirable), essentially building in an ``sc''
-% axis).
+% axis.
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
@@ -1118,7 +1118,7 @@
% resets everything and \texttt{up} changes italic or slanted to
% upright and \texttt{ulc} undoes small caps.
%
-% So we now offer \cs{normalshape} (using \cs{shapedefault} which
+% So we now offer \cs{normalshape} (using \cs{shapedefault}) which
% is normally the same as calling both \cs{ulcshape} and
% \cs{upshape}, only more efficient.
%
@@ -1494,7 +1494,7 @@
% provide. So its redefinitions for the various shape commands,
% such as \cs{itshape} should no longer happen. We therefore force
% the standard definitions at \cs{AtBeginDocument} (later when this
-% is defined. Once
+% is defined). Once
% \texttt{fontaxes} is no longer doing such redefinitions that could
% be taken out again.
%
diff --git a/Master/texmf-dist/source/latex/base/ltfssbas.dtx b/Master/texmf-dist/source/latex/base/ltfssbas.dtx
index eaea328dac3..df02a5749a7 100644
--- a/Master/texmf-dist/source/latex/base/ltfssbas.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssbas.dtx
@@ -35,7 +35,7 @@
%
%
\ProvidesFile{ltfssbas.dtx}
- [2023/10/21 v3.2l LaTeX Kernel (NFSS Basic Macros)]
+ [2024/02/08 v3.2l LaTeX Kernel (NFSS Basic Macros)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -962,7 +962,7 @@
% case, however, we also need the value of |\baselineskip|. As the
% first argument to |\set@fontsize| we pass the current value of
% |\baselinestretch|. This will either match the internal value (in
-% which case nothing changes, or it will be an updated value due to
+% which case nothing changes) or it will be an updated value due to
% a user change of that macro using |\renewcommand|. If we would
% pass the internal |\f@linespread| such a change would be
% effectively overwritten by a size change.
diff --git a/Master/texmf-dist/source/latex/base/ltfssini.dtx b/Master/texmf-dist/source/latex/base/ltfssini.dtx
index 273ed4babd3..255abe03f3a 100644
--- a/Master/texmf-dist/source/latex/base/ltfssini.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssini.dtx
@@ -36,7 +36,7 @@
%
%
\ProvidesFile{ltfssini.dtx}
- [2021/09/10 v3.2i LaTeX Kernel (NFSS Initialisation)]
+ [2024/02/08 v3.2i LaTeX Kernel (NFSS Initialisation)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -864,7 +864,7 @@
%
% If \cs{bfdefault} and \cs{bfdefault@previous} are different then
% the default got changed directly through the legacy interface
-% (i.e., via \cs{def} or \cs{renewcommand}. In that case we reset
+% (i.e., via \cs{def} or \cs{renewcommand}). In that case we reset
% all meta family defaults so that the document behaves like it was
% the case before the new mechanism was introduced.
% \changes{v3.1k}{2020/03/19}{Support legacy use of \cs{bfdefault}
@@ -885,7 +885,7 @@
\let\bfdefault@previous\bfdefault
% \end{macrocode}
% And we reset the meta family defaults (\cs{bfdef@ult} is an
-% expanded version of \cs{bfdefault}.
+% expanded version of \cs{bfdefault}).
% \begin{macrocode}
\let\bfseries@rm\bfdef@ult
\let\bfseries@sf\bfdef@ult
@@ -1661,8 +1661,8 @@
% \begin{macrocode}
\def\emfontdeclare@clist{#2,#1}%
% \end{macrocode}
-% Then we execute current declaration. Appending |\selectfont| means one
-% can write just |\fontshape{it}}| and that works then too.
+% Then we execute the current declaration. Appending |\selectfont| means one
+% can write just |\fontshape{it}| and that works then too.
% \begin{macrocode}
% \typeout{Use: \detokenize{#1}}%
#1\selectfont
diff --git a/Master/texmf-dist/source/latex/base/ltfsstrc.dtx b/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
index f5dc2ad5898..4f0e43021aa 100644
--- a/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
@@ -37,7 +37,7 @@
%<package> [2020/12/22 v3.0n Standard LaTeX package (font tracing)]
% \fi
% \ProvidesFile{ltfsstrc.dtx}
-% [2021/04/26 v3.0o LaTeX Kernel (NFSS tracing)]
+% [2024/02/08 v3.0o LaTeX Kernel (NFSS tracing)]
%
% \iffalse
%<+checkmem>\CHECKMEM
@@ -125,7 +125,7 @@
%
% \item[debugshow] In addition to \texttt{infoshow} show also
% changing of math fonts as far as possible (this option can produce a
-% large amount of output.
+% large amount of output).
%
% \item[loading] Show the name of external fonts when they are
% loaded. This option shows only ``newly'' loaded fonts not those
@@ -489,8 +489,8 @@
\let\f@shape@saved\f@shape
\let\f@series@saved\f@series
% \end{macrocode}
-% The we run the delayed adjustments (which is using the
-% \cs{..@without@substitution} commands
+% Then we run the delayed adjustments (which use the
+% \cs{..@without@substitution} commands):
% \begin{macrocode}
\delayed@f@adjustment
% \end{macrocode}
@@ -863,14 +863,15 @@
%
% \TeX{} uses the math fonts that are current when the end of a
% formula is reached. If we don't want to keep font setups local to
-% every formula (which would result in an enormous overhead, we have
+% every formula (which would result in an enormous overhead), we have
% to be careful not to end up with the wrong setup in case formulas
% are nested, e.g., we need to be able to handle
% \begin{verbatim}
% $ a=b+c \mbox{ \small for all $b$ and $c\in Z$}$
%\end{verbatim}
% Here the inner formulae |b| and |c\in Z| are typeset in |\small| but
-% we have to return to |\normalsize| before we reach the closing |$|
+% we have to return to |\normalsize| before we reach the
+% closing |$| \iffalse$\fi
% of the outer formula.
%
% This is handled in the following way:
@@ -1042,8 +1043,8 @@
% If so we first call the `=' macro (i.e.\ argument three) to set
% up special things for the selected math group. Then we call
% |\mathgroup| to select the group given by argument two and
-% finally we place |#1| (i.e.\ the argument of the \meta{math
-% alphabet identifier} at the end. This part of the code is
+% finally we place |#1| (i.e., the argument of the \meta{math
+% alphabet identifier}) at the end. This part of the code is
% surrounded by two commands which behave like |\begingroup|
% and |\endgroup| if we want \meta{math alphabet identifier}s
% but will expand into |\@empty| if we want simply switches to
@@ -1081,7 +1082,7 @@
% \begin{macro}{\math@egroup}
% \changes{v1.0q}{1990/07/07}{Tracing code added.} If the
% \texttt{margid} option is in force (which can be tested by
-% looking at the definition of |\math@bgroup| we change the
+% looking at the definition of |\math@bgroup|) we change the
% |\math@egroup| command a bit to display the current \meta{math
% group number} after it closes the scope of \meta{math alphabet}
% with |\endgroup|.
@@ -1385,7 +1386,7 @@
% It looks for font ranges with font size functions. It's operation
% is rather simple: it discards everything up to the next size
% specification and passes this on to |\is@range| for inspection.
-% The specification (parameter |#2| is inserted again, in case
+% The specification (parameter |#2|) is inserted again, in case
% it is needed later.
% \begin{macrocode}
\def\extract@rangefontinfo#1<#2>{%
@@ -1402,7 +1403,7 @@
%
% From the way |\is@range| is called inside |\extract@rangefontinfo|
% we see that |#2| is the character |>| if the size specification
-% found is a simple one (as it does not contain a |-| character.
+% found is a simple one (that does not contain a |-| character).
% This is checked easily enough and |\extract@rangefontinfo|
% called again. Note that the extra tokens inserted after the
% |\@nil| in the call to |\is@range| appear at the beginning of
diff --git a/Master/texmf-dist/source/latex/base/lthooks.dtx b/Master/texmf-dist/source/latex/base/lthooks.dtx
index 446cdaae060..d282ff841c7 100644
--- a/Master/texmf-dist/source/latex/base/lthooks.dtx
+++ b/Master/texmf-dist/source/latex/base/lthooks.dtx
@@ -27,17 +27,16 @@
% \fi
%
% \iffalse
-%
%%% From File: lthooks.dtx
%
-% \begin{macrocode}
-\def\lthooksversion{v1.1f}
-\def\lthooksdate{2023/10/02}
-% \end{macrocode}
-%
%<*driver>
+% \fi
+\ProvidesFile{lthooks.dtx}
+ [2024/04/22 v1.1h LaTeX Kernel (hooks)]
+% \iffalse
+%
\documentclass{l3doc}
-
+\GetFileInfo{lthooks.dtx}
\providecommand\InternalDetectionOff{}
\providecommand\InternalDetectionOn{}
@@ -62,7 +61,7 @@
%
%
% \title{\LaTeX{}'s hook management\thanks{This module has version
-% \lthooksversion\ dated \lthooksdate, \copyright\ \LaTeX\
+% \fileversion\ dated \filedate, \copyright\ \LaTeX\
% Project.}}
%
% \author{Frank Mittelbach\thanks{Code improvements for speed and other goodies by Phelype Oleinik}}
@@ -160,7 +159,7 @@
% \end{function}
%
%
-% \begin{function}{\NewHookWithArguments}
+% \begin{function}[added=2023-06-01]{\NewHookWithArguments}
% \begin{syntax}
% \cs{NewHookWithArguments} \Arg{hook} \Arg{number}
% \end{syntax}
@@ -172,7 +171,7 @@
% the current package name. See section~\ref{sec:default-label}.
% \end{function}
%
-% \begin{function}{\NewReversedHookWithArguments}
+% \begin{function}[added=2023-06-01]{\NewReversedHookWithArguments}
% \begin{syntax}
% \cs{NewReversedHookWithArguments} \Arg{hook} \Arg{number}
% \end{syntax}
@@ -184,7 +183,7 @@
% the current package name. See section~\ref{sec:default-label}.
% \end{function}
%
-% \begin{function}{\NewMirroredHookPairWithArguments}
+% \begin{function}[added=2023-06-01]{\NewMirroredHookPairWithArguments}
% \begin{syntax}
% \cs{NewMirroredHookPairWithArguments} \Arg{hook-1} \Arg{hook-2} \Arg{number}
% \end{syntax}
@@ -234,9 +233,9 @@
% (e.g., one used in code with \cs{UseHook} or
% \cs{UseOneTimeHook}) without it being explicitly declared with
% \cs{NewHook}).
-% This command undoes the effect of \cs{DisableGenericHook}.
% If the hook is already activated, this command does nothing.
%
+% Note that this command does not undo the effect of \cs{DisableGenericHook}.
% See section~\ref{sec:generic-hooks} for a discussion of when this
% declaration is appropriate.
% \end{function}
@@ -264,7 +263,7 @@
% A leading |.| is treated literally.
% \end{function}
%
-% \begin{function}{\UseHookWithArguments}
+% \begin{function}[added=2023-06-01]{\UseHookWithArguments}
% \begin{syntax}
% \cs{UseHookWithArguments} \Arg{hook} \Arg{number} \Arg{arg_1} \ldots \Arg{arg_n}
% \end{syntax}
@@ -314,7 +313,7 @@
%
% \end{function}
%
-% \begin{function}{\UseOneTimeHookWithArguments}
+% \begin{function}[added=2023-06-01]{\UseOneTimeHookWithArguments}
% \begin{syntax}
% \cs{UseOneTimeHookWithArguments} \Arg{hook} \Arg{number} \Arg{arg_1} \ldots \Arg{arg_n}
% \end{syntax}
@@ -340,7 +339,7 @@
%
% \begin{function}{\AddToHook}
% \begin{syntax}
-% \cs{AddToHook} \Arg{hook}\oarg{label}\Arg{code}
+% \cs{AddToHook} \Arg{hook} \oarg{label} \Arg{code}
% \end{syntax}
% Adds \meta{code} to the \meta{hook} labeled by \meta{label}.
% When the optional argument \meta{label} is not provided, the
@@ -368,9 +367,9 @@
% See section~\ref{sec:default-label}.
% \end{function}
%
-% \begin{function}{\AddToHookWithArguments}
+% \begin{function}[added=2023-06-01]{\AddToHookWithArguments}
% \begin{syntax}
-% \cs{AddToHookWithArguments} \Arg{hook}\oarg{label}\Arg{code}
+% \cs{AddToHookWithArguments} \Arg{hook} \oarg{label} \Arg{code}
% \end{syntax}
% Works exactly like \cs{AddToHook}, except that the \meta{code} can
% access the arguments passed to the hook using \verb|#1|, \verb|#2|,
@@ -398,7 +397,7 @@
%
% \begin{function}{\RemoveFromHook}
% \begin{syntax}
-% \cs{RemoveFromHook} \Arg{hook}\oarg{label}
+% \cs{RemoveFromHook} \Arg{hook} \oarg{label}
% \end{syntax}
% Removes any code labeled by \meta{label} from the \meta{hook}.
% When the optional argument \meta{label} is not provided, the
@@ -459,7 +458,7 @@
%
% \begin{function}{\AddToHookNext}
% \begin{syntax}
-% \cs{AddToHookNext} \Arg{hook}\Arg{code}
+% \cs{AddToHookNext} \Arg{hook} \Arg{code}
% \end{syntax}
% Adds \meta{code} to the next invocation of the \meta{hook}.
% The code is executed after the normal hook code has finished and
@@ -505,9 +504,9 @@
% \end{function}\footnotetext{There is
% no mechanism to reorder such code chunks (or delete them).}
%
-% \begin{function}{\AddToHookNextWithArguments}
+% \begin{function}[added=2023-06-01]{\AddToHookNextWithArguments}
% \begin{syntax}
-% \cs{AddToHookNextWithArguments} \Arg{hook}\Arg{code}
+% \cs{AddToHookNextWithArguments} \Arg{hook} \Arg{code}
% \end{syntax}
% Works exactly like \cs{AddToHookNext}, but the \meta{code} can
% contain references to the arguments of the \meta{hook} as described
@@ -522,7 +521,7 @@
%
% \begin{function}{\ClearHookNext}
% \begin{syntax}
-% \cs{ClearHookNext}\Arg{hook}
+% \cs{ClearHookNext} \Arg{hook}
% \end{syntax}
% Normally \cs{AddToHookNext} is only used when you know precisely
% where it will apply and why you want some extra code at that
@@ -746,7 +745,7 @@
%
% \begin{function}{\DeclareHookRule}
% \begin{syntax}
-% \cs{DeclareHookRule} \Arg{hook}\Arg{label1}\Arg{relation}\Arg{label2}
+% \cs{DeclareHookRule} \Arg{hook} \Arg{label1} \Arg{relation} \Arg{label2}
% \end{syntax}
% Defines a relation between \meta{label1} and \meta{label2} for a
% given \meta{hook}. If \meta{hook} is \texttt{??} this defines a default
@@ -807,7 +806,7 @@
%
% \begin{function}{\ClearHookRule}
% \begin{syntax}
-% \cs{ClearHookRule}\Arg{hook}\Arg{label1}\Arg{label2}
+% \cs{ClearHookRule} \Arg{hook} \Arg{label1} \Arg{label2}
% \end{syntax}
% Syntactic sugar for saying that \meta{label1} and \meta{label2}
% are unrelated for the given \meta{hook}.
@@ -817,7 +816,7 @@
%
% \begin{function}{\DeclareDefaultHookRule}
% \begin{syntax}
-% \cs{DeclareDefaultHookRule}\Arg{label1}\Arg{relation}\Arg{label2}
+% \cs{DeclareDefaultHookRule} \Arg{label1} \Arg{relation} \Arg{label2}
% \end{syntax}
% This sets up a relation between \meta{label1} and \meta{label2}
% for all hooks unless overwritten by a specific rule for a hook.
@@ -1004,7 +1003,7 @@
%
% \begin{function}{\DebugHooksOn,\DebugHooksOff}
% \begin{syntax}
-% \cs{DebugHooksOn}
+% \cs{DebugHooksOn} \ldots\ \cs{DebugHooksOff}
% \end{syntax}
% Turn the debugging of hook code on or off. This displays most changes
% made to the hook data structures. The output is rather coarse and
@@ -1044,7 +1043,7 @@
% the current package name. See section~\ref{sec:default-label}.
% \end{function}
%
-% \begin{function}{
+% \begin{function}[added=2023-06-01]{
% \hook_new_with_args:nn,
% \hook_new_reversed_with_args:nn,
% \hook_new_pair_with_args:nnn
@@ -1100,9 +1099,14 @@
%
%
%
-% \begin{function}{\hook_use:n,\hook_use:nnw}
+% \begin{function}{\hook_use:n}
+% \begin{syntax}
+% ~~\cs{hook_use:n} \Arg{hook}
+% \end{syntax}
+% \end{function}
+% \vskip-1.2\baselineskip
+% \begin{function}[added=2023-06-01]{\hook_use:nnw}
% \begin{syntax}
-% \cs{hook_use:n} \Arg{hook}
% \cs{hook_use:nnw} \Arg{hook} \Arg{number} \Arg{arg_1} \ldots \Arg{arg_n}
% \end{syntax}
% Executes the \Arg{hook} code followed (if set up) by the code for next
@@ -1118,9 +1122,14 @@
% A leading |.| is treated literally.
% \end{function}
%
-% \begin{function}{\hook_use_once:n,\hook_use_once:nnw}
+% \begin{function}{\hook_use_once:n}
% \begin{syntax}
% \cs{hook_use_once:n} \Arg{hook}
+% \end{syntax}
+% \end{function}
+% \vskip-1.2\baselineskip
+% \begin{function}[added=2023-06-01]{\hook_use_once:nnw}
+% \begin{syntax}
% \cs{hook_use_once:nnw} \Arg{hook} \Arg{number} \Arg{arg_1} \ldots \Arg{arg_n}
% \end{syntax}
% Changes the \Arg{hook} status so that from now on any addition to
@@ -1139,10 +1148,16 @@
%
% \begin{function}{
% \hook_gput_code:nnn,
+% }
+% \begin{syntax}
+% ~~~~~~~~~\cs{hook_gput_code:nnn} \Arg{hook} \Arg{label} \Arg{code}
+% \end{syntax}
+% \end{function}
+% \vskip -1.2\baselineskip
+% \begin{function}[added=2023-06-01]{
% \hook_gput_code_with_args:nnn
% }
% \begin{syntax}
-% \cs{hook_gput_code:nnn} \Arg{hook} \Arg{label} \Arg{code}
% \cs{hook_gput_code_with_args:nnn} \Arg{hook} \Arg{label} \Arg{code}
% \end{syntax}
% Adds a chunk of \meta{code} to the \meta{hook} labeled
@@ -1168,10 +1183,17 @@
%
% \begin{function}{
% \hook_gput_next_code:nn,
+% }
+% \begin{syntax}
+% ~~~~~~~~~~~~~\cs{hook_gput_next_code:nn} \Arg{hook} \Arg{code}
+% \end{syntax}
+% \end{function}
+% \vskip-1.2\baselineskip
+% \begin{function}[added=2023-06-01]{
% \hook_gput_next_code_with_args:nn,
% }
% \begin{syntax}
-% \cs{hook_gput_next_code:nn} \Arg{hook} \Arg{code}
+% \cs{hook_gput_next_code_with_args:nn} \Arg{hook} \Arg{code}
% \end{syntax}
% Adds a chunk of \meta{code} for use only in the next invocation of the
% \meta{hook}. Once used it is gone.
@@ -1183,6 +1205,7 @@
% In that case, if an actual parameter token should be added to the
% code, it should be doubled.
%
+% \end{function}
% This is simpler than \cs{hook_gput_code:nnn}, the code is simply
% appended to the hook in the order of declaration at the very end,
% i.e., after all standard code for the hook got executed.
@@ -1191,7 +1214,6 @@
%
% The \meta{hook} can be specified using the dot-syntax to denote
% the current package name. See section~\ref{sec:default-label}.
-% \end{function}
%
%
% \begin{function}{\hook_gclear_next_code:n}
@@ -1527,7 +1549,7 @@
% \hook{cmd},
% \hook{env},
% \hook{file},
-% \hook{include}
+% \hook{include},
% \hook{package}, and
% \hook{class},
% and all these are available out of the box: you only have to
@@ -1862,15 +1884,17 @@
% \item[\hook{env/\meta{env}/begin}]
%
% This hook is executed as part of \cs{begin} directly in front
-% of the code specific to the environment start (e.g., the
-% second argument of \cs{newenvironment}). Its scope is the
-% environment body.
+% of the code specific to the environment start (e.g.,
+% the third argument of \cs{NewDocumentEnvironment} and
+% the second argument of \cs{newenvironment}).
+% Its scope is the environment body.
%
% \item[\hook{env/\meta{env}/end}]
%
% This hook is executed as part of \cs{end} directly in front of the
-% code specific to the end of the environment (e.g., the third
-% argument of \cs{newenvironment}).
+% code specific to the end of the environment (e.g.,
+% the forth argument of \cs{NewDocumentEnvironment} and
+% the third argument of \cs{newenvironment}).
%
% \item[\hook{env/\meta{env}/after}]
%
@@ -2701,7 +2725,7 @@
% \hook_new:n,
% \hook_new_with_args:nn
% }
-% \begin{macro}{@@_new:nn}
+% \begin{macro}{\@@_new:nn}
% The \cs{hook_new:n} declaration declares a new hook and expects
% the hook \meta{name} as its argument, e.g.,
% \hook{begindocument}.
@@ -3509,7 +3533,8 @@
\msg_error:nnnnn { hooks } { set-top-level }
{ for } { SetDefaultHookLabel } {#1}
}
- { \exp_args:Nx \@@_set_default_label:n { \@@_make_name:n {#1} } }
+ { \exp_args:Nx
+ \@@_set_default_label:n { \@@_make_name:n {#1} } }
}
\cs_new_protected:Npn \@@_set_default_label:n #1
{
@@ -3722,7 +3747,8 @@
%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_gput_code:nnn}
%<latexrelease> {Providing~hooks}
%<latexrelease>\cs_gset_protected:Npn \hook_gput_code:nnn #1 #2
-%<latexrelease> { \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} }
+%<latexrelease> { \@@_normalize_hook_args:Nnn
+%<latexrelease> \@@_gput_code:nnn {#1} {#2} }
%<latexrelease>\cs_gset_protected:Npn \@@_gput_code:nnn #1 #2 #3
%<latexrelease> {
%<latexrelease> \@@_if_execute_immediately:nTF {#1}
@@ -3736,7 +3762,8 @@
%<latexrelease> {
%<latexrelease> \@@_if_disabled:nTF {#1}
%<latexrelease> { \msg_error:nnn { hooks } { hook-disabled } {#1} }
-%<latexrelease> { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} }
+%<latexrelease> { \@@_try_declaring_generic_hook:nnn
+%<latexrelease> {#1} {#2} {#3} }
%<latexrelease> }
%<latexrelease> }
%<latexrelease> }
@@ -3748,7 +3775,8 @@
%<latexrelease> \on@line\space <-~ \tl_to_str:n{#3}} }
%<latexrelease> \str_if_eq:nnTF {#2} { top-level }
%<latexrelease> {
-%<latexrelease> \str_if_eq:eeTF { top-level } { \@@_currname_or_default: }
+%<latexrelease> \str_if_eq:eeTF { top-level }
+%<latexrelease> { \@@_currname_or_default: }
%<latexrelease> {
%<latexrelease> \@@_init_structure:n {#1}
%<latexrelease> \@@_tl_gput_right:cn { @@_toplevel~#1 } {#3}
@@ -3756,7 +3784,8 @@
%<latexrelease> { \msg_error:nnn { hooks } { misused-top-level } {#1} }
%<latexrelease> }
%<latexrelease> {
-%<latexrelease> \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
+%<latexrelease> \prop_get:cnNTF
+%<latexrelease> { g_@@_#1_code_prop } {#2} \l_@@_return_tl
%<latexrelease> {
%<latexrelease> \prop_gput:cno { g_@@_#1_code_prop } {#2}
%<latexrelease> { \l_@@_return_tl #3 }
@@ -3840,7 +3869,8 @@
% \changes{v1.1d}{2023/05/21}
% {Changes to allow support arguments in cmd hooks (cmd-args).}
% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_try_declaring_generic_hook:nnn}
+%<latexrelease>\IncludeInRelease{2023/06/01}
+%<latexrelease> {\@@_try_declaring_generic_hook:nnn}
%<latexrelease> {Hooks~with~args}
\cs_new_protected:Npn \@@_try_declaring_generic_hook:nnn #1
{
@@ -3857,31 +3887,38 @@
{#1}
}
%<latexrelease>\EndIncludeInRelease
-%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_declaring_generic_hook:nnn}
+%<latexrelease>\IncludeInRelease{2021/11/15}
+%<latexrelease> {\@@_try_declaring_generic_hook:nnn}
%<latexrelease> {Standardise~generic~hook~names}
%<latexrelease>\cs_gset_protected:Npn \@@_try_declaring_generic_hook:nnn #1
%<latexrelease> {
-%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
+%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop:
+%<latexrelease> {#1}
%<latexrelease> \hook_gput_code:nnn
%<latexrelease> \@@_gput_undeclared_hook:nnn
%<latexrelease> {#1}
%<latexrelease> }
-%<latexrelease>\cs_gset_protected:Npn \@@_try_declaring_generic_next_hook:nn #1
+%<latexrelease>\cs_gset_protected:Npn
+%<latexrelease> \@@_try_declaring_generic_next_hook:nn #1
%<latexrelease> {
-%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
+%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop:
+%<latexrelease> {#1}
%<latexrelease> \hook_gput_next_code:nn
%<latexrelease> \@@_gput_next_do:nn
%<latexrelease> {#1}
%<latexrelease> }
%<latexrelease>\EndIncludeInRelease
-%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_try_declaring_generic_hook:nnn}
+%<latexrelease>\IncludeInRelease{2020/10/01}
+%<latexrelease> {\@@_try_declaring_generic_hook:nnn}
%<latexrelease> {Standardise~generic~hook~names}
-%<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_hook:nnn #1
+%<latexrelease>\cs_new_protected:Npn
+%<latexrelease> \@@_try_declaring_generic_hook:nnn #1
%<latexrelease> {
%<latexrelease> \@@_try_declaring_generic_hook:nNNnn {#1}
%<latexrelease> \hook_gput_code:nnn \@@_gput_undeclared_hook:nnn
%<latexrelease> }
-%<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_next_hook:nn #1
+%<latexrelease>\cs_new_protected:Npn
+%<latexrelease> \@@_try_declaring_generic_next_hook:nn #1
%<latexrelease> {
%<latexrelease> \@@_try_declaring_generic_hook:nNNnn {#1}
%<latexrelease> \hook_gput_next_code:nn \@@_gput_next_do:nn
@@ -3904,12 +3941,15 @@
%
% \changes{v1.0s}{2021/09/28}
% {Correct usage of older \cs{@@_if_file_hook:wTF} (gh/675)}
+% \changes{v1.1h}{2024/01/24}
+% {Correct usage of older \cs{@@_if_file_hook:wTF} (gh/1243)}
% \begin{macrocode}
%<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_hook:nNNnn #1
%<latexrelease> {
-%<latexrelease> \@@_if_file_hook:wTF #1 / \s_@@_mark
+%<latexrelease> \@@_if_file_hook:wTF #1 / / \s_@@_mark
%<latexrelease> {
-%<latexrelease> \exp_args:Ne \@@_try_declaring_generic_hook_split:nNNnn
+%<latexrelease> \exp_args:Ne
+%<latexrelease> \@@_try_declaring_generic_hook_split:nNNnn
%<latexrelease> { \exp_args:Ne \@@_file_hook_normalize:n {#1} }
%<latexrelease> }
%<latexrelease> { \@@_try_declaring_generic_hook_split:nNNnn {#1} }
@@ -3917,9 +3957,11 @@
% \end{macrocode}
%
% \begin{macrocode}
-%<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_hook_split:nNNnn #1 #2 #3
+%<latexrelease>\cs_new_protected:Npn
+%<latexrelease> \@@_try_declaring_generic_hook_split:nNNnn #1 #2 #3
%<latexrelease> {
-%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
+%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop:
+%<latexrelease> {#1}
%<latexrelease> { #2 }
%<latexrelease> { #3 } {#1}
%<latexrelease> }
@@ -3931,9 +3973,11 @@
% \changes{v1.1a}{2023/04/06}
% {Changes to add hook arguments (hook-args).}
% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_try_declaring_generic_hook:wn}
+%<latexrelease>\IncludeInRelease{2023/06/01}
+%<latexrelease> {\@@_try_declaring_generic_hook:wn}
%<latexrelease> {Hooks~with~args}
-\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
+\prg_new_protected_conditional:Npnn
+ \@@_try_declaring_generic_hook:wn
#1 / #2 / #3 / #4 \scan_stop: #5 { TF }
{
\@@_if_generic:nTF {#5}
@@ -4052,9 +4096,11 @@
% \end{macro}
%
% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_declaring_generic_hook:wn}
+%<latexrelease>\IncludeInRelease{2021/11/15}
+%<latexrelease> {\@@_try_declaring_generic_hook:wn}
%<latexrelease> {Standardise~generic~hook~names}
-%<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
+%<latexrelease>\prg_new_protected_conditional:Npnn
+%<latexrelease> \@@_try_declaring_generic_hook:wn
%<latexrelease> #1 / #2 / #3 / #4 \scan_stop: #5 { TF }
%<latexrelease> {
%<latexrelease> \@@_if_generic:nTF {#5}
@@ -4083,9 +4129,11 @@
% \end{macrocode}
%
% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2021/06/01}{\@@_try_declaring_generic_hook:wn}
+%<latexrelease>\IncludeInRelease{2021/06/01}
+%<latexrelease> {\@@_try_declaring_generic_hook:wn}
%<latexrelease> {Support~cmd~hooks}
-%<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
+%<latexrelease>\prg_new_protected_conditional:Npnn
+%<latexrelease> \@@_try_declaring_generic_hook:wn
%<latexrelease> #1 / #2 / #3 / #4 \scan_stop: #5 { TF }
%<latexrelease> {
%<latexrelease> \tl_if_empty:nTF {#2}
@@ -4099,10 +4147,12 @@
%<latexrelease> { \@@_try_put_cmd_hook:n {#5} }
%<latexrelease> \@@_make_usable:n {#5}
%<latexrelease> }
-%<latexrelease> \prop_if_in:NnTF \c_@@_generics_reversed_ii_prop {#2}
+%<latexrelease> \prop_if_in:NnTF
+%<latexrelease> \c_@@_generics_reversed_ii_prop {#2}
%<latexrelease> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
%<latexrelease> {
-%<latexrelease> \prop_if_in:NnT \c_@@_generics_reversed_iii_prop {#3}
+%<latexrelease> \prop_if_in:NnT
+%<latexrelease> \c_@@_generics_reversed_iii_prop {#3}
%<latexrelease> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
%<latexrelease> }
%<latexrelease> \prg_return_true:
@@ -4114,9 +4164,11 @@
% \end{macrocode}
%
% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_try_declaring_generic_hook:wn}
+%<latexrelease>\IncludeInRelease{2020/10/01}
+%<latexrelease> {\@@_try_declaring_generic_hook:wn}
%<latexrelease> {Support~cmd~hooks}
-%<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
+%<latexrelease>\prg_new_protected_conditional:Npnn
+%<latexrelease> \@@_try_declaring_generic_hook:wn
%<latexrelease> #1 / #2 / #3 / #4 \scan_stop: #5 { TF }
%<latexrelease> {
%<latexrelease> \tl_if_empty:nTF {#2}
@@ -4125,10 +4177,12 @@
%<latexrelease> \prop_if_in:NnTF \c_@@_generics_prop {#1}
%<latexrelease> {
%<latexrelease> \@@_if_declared:nF {#5} { \hook_new:n {#5} }
-%<latexrelease> \prop_if_in:NnTF \c_@@_generics_reversed_ii_prop {#2}
+%<latexrelease> \prop_if_in:NnTF
+%<latexrelease> \c_@@_generics_reversed_ii_prop {#2}
%<latexrelease> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
%<latexrelease> {
-%<latexrelease> \prop_if_in:NnT \c_@@_generics_reversed_iii_prop {#3}
+%<latexrelease> \prop_if_in:NnT
+%<latexrelease> \c_@@_generics_reversed_iii_prop {#3}
%<latexrelease> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
%<latexrelease> }
%<latexrelease> \prg_return_true:
@@ -4204,11 +4258,11 @@
% \changes{v1.0h}{2021/01/07}{Assume hook name has at least three
% nonempty parts (gh/464)}
% \begin{macrocode}
-%<latexrelease>\cs_new:Npn \@@_strip_double_slash:w #1/#2/#3 // #4 \s_@@_mark
+%<latexrelease>\cs_new:Npn \@@_strip_double_slash:w #1/#2/#3//#4\s_@@_mark
%<latexrelease> {
%<latexrelease> \tl_if_empty:nTF {#4}
%<latexrelease> { #1/#2/#3 }
-%<latexrelease> { \@@_strip_double_slash:w #1/#2/#3 / #4 \s_@@_mark }
+%<latexrelease> { \@@_strip_double_slash:w #1/#2/#3 /#4\s_@@_mark }
%<latexrelease> }
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
@@ -4287,9 +4341,12 @@
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_generics_reversed_ii_prop}
%<latexrelease> {Standardise~generic~hook~names}
-%<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_reversed_ii_prop {after=,end=}
-%<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_reversed_iii_prop {after=}
-%<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_file_prop {before=,after=}
+%<latexrelease>\prop_const_from_keyval:Nn
+%<latexrelease> \c_@@_generics_reversed_ii_prop {after=,end=}
+%<latexrelease>\prop_const_from_keyval:Nn
+%<latexrelease> \c_@@_generics_reversed_iii_prop {after=}
+%<latexrelease>\prop_const_from_keyval:Nn
+%<latexrelease> \c_@@_generics_file_prop {before=,after=}
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
@@ -4369,7 +4426,8 @@
\str_if_eq:nnTF {#2} { top-level }
{ \@@_toplevel_gset:nn {#1} { } }
{
- \prop_gpop:cnNF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
+ \prop_gpop:cnNF { g_@@_#1_code_prop }
+ {#2} \l_@@_return_tl
{ \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} }
}
}
@@ -4387,7 +4445,8 @@
\@@_if_deprecated_generic:nTF {#1}
{
\@@_deprecated_generic_warn:n {#1}
- \@@_do_deprecated_generic:Nn \@@_gremove_code:nn {#1} {#2}
+ \@@_do_deprecated_generic:Nn
+ \@@_gremove_code:nn {#1} {#2}
}
{ \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} }
}
@@ -4412,8 +4471,10 @@
%<latexrelease> \str_if_eq:nnTF {#2} { top-level }
%<latexrelease> { \@@_tl_gclear:c { @@_toplevel~#1 } }
%<latexrelease> {
-%<latexrelease> \prop_gpop:cnNF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
-%<latexrelease> { \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} }
+%<latexrelease> \prop_gpop:cnNF { g_@@_#1_code_prop }
+%<latexrelease> {#2} \l_@@_return_tl
+%<latexrelease> { \msg_warning:nnnn { hooks } { cannot-remove }
+%<latexrelease> {#1} {#2} }
%<latexrelease> }
%<latexrelease> }
%<latexrelease> \@@_if_usable:nT {#1}
@@ -4423,9 +4484,11 @@
%<latexrelease> \@@_if_deprecated_generic:nTF {#1}
%<latexrelease> {
%<latexrelease> \@@_deprecated_generic_warn:n {#1}
-%<latexrelease> \@@_do_deprecated_generic:Nn \@@_gremove_code:nn {#1} {#2}
+%<latexrelease> \@@_do_deprecated_generic:Nn
+%<latexrelease> \@@_gremove_code:nn {#1} {#2}
%<latexrelease> }
-%<latexrelease> { \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} }
+%<latexrelease> { \msg_warning:nnnn { hooks } { cannot-remove }
+%<latexrelease> {#1} {#2} }
%<latexrelease> }
%<latexrelease> }
%<latexrelease>\EndIncludeInRelease
@@ -4467,7 +4530,8 @@
{#1} {#2}
}
\cs_new_protected:Npn \@@_cs_gput_right_fast:nnn #1 #2 #3
- { \cs_gset:cpx { @@#1~#2 } { \exp_not:v { @@#1~#2 } \exp_not:n {#3} } }
+ { \cs_gset:cpx { @@#1~#2 }
+ { \exp_not:v { @@#1~#2 } \exp_not:n {#3} } }
\cs_new_protected:Npn \@@_cs_gput_right_slow:nnn #1 #2 #3
{
% \end{macrocode}
@@ -4693,7 +4757,8 @@
% \begin{macrocode}
\exp_last_unbraced:NNf
\cs_set:Npn \@@_tmp:w { \@@_parameter:n {#1} } { }
- \tl_set:Ne \l_@@_tmpa_tl { \@@_braced_cs_parameter:n { @@_tmp:w } }
+ \tl_set:Ne \l_@@_tmpa_tl
+ { \@@_braced_cs_parameter:n { @@_tmp:w } }
% \end{macrocode}
% Now this function does the fun part. It is meant to be used with
% \cs{prop_map_function:NN}, taking a label name in \verb|##1| and the
@@ -5069,8 +5134,8 @@
%<latexrelease> \@@_if_deprecated_generic:nT {#1}
%<latexrelease> {
%<latexrelease> \@@_deprecated_generic_warn:n {#1}
-%<latexrelease> \@@_do_deprecated_generic:Nn \@@_gset_rule:nnnn {#1}
-%<latexrelease> {#2} {#3} {#4}
+%<latexrelease> \@@_do_deprecated_generic:Nn \@@_gset_rule:nnnn
+%<latexrelease> {#1} {#2} {#3} {#4}
%<latexrelease> \exp_after:wN \use_none:nnnnnnnnn \use_none:n
%<latexrelease> }
%<latexrelease> \@@_init_structure:n {#1}
@@ -5110,7 +5175,8 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_rule_before_gset:nnn #1#2#3
{
- \@@_tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
+ \@@_tl_gset:cx
+ { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
{ \@@_label_ordered:nnTF {#2} {#3} { < } { > } }
}
\cs_new_eq:cN { @@_rule_<_gset:nnn } \@@_rule_before_gset:nnn
@@ -5119,7 +5185,8 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_rule_after_gset:nnn #1#2#3
{
- \@@_tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#3} {#2} _tl }
+ \@@_tl_gset:cx
+ { g_@@_#1_rule_ \@@_label_pair:nn {#3} {#2} _tl }
{ \@@_label_ordered:nnTF {#3} {#2} { < } { > } }
}
\cs_new_eq:cN { @@_rule_>_gset:nnn } \@@_rule_after_gset:nnn
@@ -5132,7 +5199,8 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_rule_voids_gset:nnn #1#2#3
{
- \@@_tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
+ \@@_tl_gset:cx
+ { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
{ \@@_label_ordered:nnTF {#2} {#3} { -> } { <- } }
}
% \end{macrocode}
@@ -5146,11 +5214,15 @@
% together in hook |#1|.
% \begin{macrocode}
\cs_new_protected:cpn { @@_rule_incompatible-error_gset:nnn } #1#2#3
- { \@@_tl_gset:cn { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
- { xE } }
+ { \@@_tl_gset:cn
+ { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
+ { xE }
+ }
\cs_new_protected:cpn { @@_rule_incompatible-warning_gset:nnn } #1#2#3
- { \@@_tl_gset:cn { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
- { xW } }
+ { \@@_tl_gset:cn
+ { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
+ { xW }
+ }
% \end{macrocode}
% \end{macro}
%
@@ -5268,7 +5340,7 @@
}
% \end{macrocode}
% After all hooks are initialized we change the ``use'' to just
-% call the hook code and not initialize it (as it was done in the
+% call the hook code and not initialize it (as this was already done in the
% preamble.
% \begin{macrocode}
\@@_post_initialization_defs:
@@ -5281,7 +5353,8 @@
%<latexrelease> {Hooks~with~args}
%<latexrelease>\cs_gset_protected:Npn \@@_initialize_all:
%<latexrelease> {
-%<latexrelease> \cs_gset_eq:NN \@@_update_hook_code:n \@@_initialize_hook_code:n
+%<latexrelease> \cs_gset_eq:NN \@@_update_hook_code:n
+%<latexrelease> \@@_initialize_hook_code:n
%<latexrelease> \@@_debug:n { \prop_gclear:N \g_@@_used_prop }
%<latexrelease> \seq_map_inline:Nn \g_@@_all_seq
%<latexrelease> { \@@_update_hook_code:n {##1} }
@@ -5291,7 +5364,8 @@
%<latexrelease> \prop_map_inline:Nn \g_@@_used_prop
%<latexrelease> {
%<latexrelease> \iow_term:x
-%<latexrelease> { ^^J ~ ##1 ~ -> ~ \cs_replacement_spec:c { @@~##1 } ~ }
+%<latexrelease> { ^^J ~ ##1 ~ -> ~
+%<latexrelease> \cs_replacement_spec:c { @@~##1 } ~ }
%<latexrelease> }
%<latexrelease> }
%<latexrelease> \cs_gset_eq:NN \hook_use:n \@@_use_initialized:n
@@ -5350,8 +5424,10 @@
% after the \verb|_next| and \verb|_toplevel| macros, so that the
% arguments passed to the hook are forwarded to them.
% \begin{macrocode}
- \exp_not:c { @@_toplevel~#1 } \@@_braced_parameter:n {#1}
- \exp_not:c { @@_next~#1 } \@@_braced_parameter:n {#1}
+ \exp_not:c { @@_toplevel~#1 }
+ \@@_braced_parameter:n {#1}
+ \exp_not:c { @@_next~#1 }
+ \@@_braced_parameter:n {#1}
}
}
{
@@ -5400,7 +5476,8 @@
%<latexrelease>\cs_gset_protected:Npn \@@_initialize_hook_code:n #1
%<latexrelease> {
%<latexrelease> \@@_debug:n
-%<latexrelease> { \iow_term:x { ^^J Update~code~for~hook~'#1' \on@line :^^J } }
+%<latexrelease> { \iow_term:x { ^^J Update~code~for~hook~'#1'
+%<latexrelease> \on@line :^^J } }
%<latexrelease> \@@_include_legacy_code_chunk:n {#1}
%<latexrelease> \@@_if_usable:nT {#1}
%<latexrelease> {
@@ -5414,15 +5491,21 @@
%<latexrelease> }
%<latexrelease> {
%<latexrelease> \@@_if_reversed:nTF {#1}
-%<latexrelease> { \cs_set_eq:NN \@@_tl_gput:Nn \@@_tl_gput_left:Nn
-%<latexrelease> \cs_set_eq:NN \@@_clist_gput:NV \clist_gput_left:NV }
-%<latexrelease> { \cs_set_eq:NN \@@_tl_gput:Nn \@@_tl_gput_right:Nn
-%<latexrelease> \cs_set_eq:NN \@@_clist_gput:NV \clist_gput_right:NV }
-%<latexrelease> \prop_set_eq:Nc \l_@@_work_prop { g_@@_#1_code_prop }
+%<latexrelease> { \cs_set_eq:NN \@@_tl_gput:Nn
+%<latexrelease> \@@_tl_gput_left:Nn
+%<latexrelease> \cs_set_eq:NN \@@_clist_gput:NV
+%<latexrelease> \clist_gput_left:NV }
+%<latexrelease> { \cs_set_eq:NN \@@_tl_gput:Nn
+%<latexrelease> \@@_tl_gput_right:Nn
+%<latexrelease> \cs_set_eq:NN \@@_clist_gput:NV
+%<latexrelease> \clist_gput_right:NV }
+%<latexrelease> \prop_set_eq:Nc \l_@@_work_prop
+%<latexrelease> { g_@@_#1_code_prop }
%<latexrelease> \@@_initialize_single:ccn
%<latexrelease> { @@~#1 } { g_@@_#1_labels_clist } {#1}
%<latexrelease> \@@_debug:n
-%<latexrelease> { \exp_args:NNx \prop_gput:Nnn \g_@@_used_prop {#1} { } }
+%<latexrelease> { \exp_args:NNx \prop_gput:Nnn \g_@@_used_prop
+%<latexrelease> {#1} { } }
%<latexrelease> }
%<latexrelease> }
%<latexrelease> }
@@ -5621,7 +5704,8 @@
\int_compare:nNnT
{ \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0
{
- \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } } {##1}
+ \tl_set:cn
+ { \@@_tl_csname:n { \l_@@_rear_tl } } {##1}
\tl_set:Nn \l_@@_rear_tl {##1}
}
}
@@ -5703,42 +5787,50 @@
%<latexrelease> {#3}
%<latexrelease> }
%<latexrelease> }
-%<latexrelease> \@@_debug:n { \@@_debug_label_data:N \l_@@_work_prop }
+%<latexrelease> \@@_debug:n
+%<latexrelease> { \@@_debug_label_data:N \l_@@_work_prop }
%<latexrelease> \tl_set:Nn \l_@@_rear_tl { 0 }
%<latexrelease> \tl_set:cn { \@@_tl_csname:n { 0 } } { 0 }
%<latexrelease> \seq_map_inline:Nn \l_@@_labels_seq
%<latexrelease> {
-%<latexrelease> \int_compare:nNnT { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0
-%<latexrelease> {
-%<latexrelease> \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } }{##1}
-%<latexrelease> \tl_set:Nn \l_@@_rear_tl {##1}
-%<latexrelease> }
+%<latexrelease> \int_compare:nNnT
+%<latexrelease> { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0
+%<latexrelease> {
+%<latexrelease> \tl_set:cn { \@@_tl_csname:n
+%<latexrelease> { \l_@@_rear_tl } } {##1}
+%<latexrelease> \tl_set:Nn \l_@@_rear_tl {##1}
+%<latexrelease> }
%<latexrelease> }
%<latexrelease> \tl_set_eq:Nc \l_@@_front_tl { \@@_tl_csname:n { 0 } }
%<latexrelease> \@@_tl_gclear:N #1
%<latexrelease> \clist_gclear:N #2
-%<latexrelease> \bool_while_do:nn { ! \str_if_eq_p:Vn \l_@@_front_tl { 0 } }
+%<latexrelease> \bool_while_do:nn
+%<latexrelease> { ! \str_if_eq_p:Vn \l_@@_front_tl { 0 } }
%<latexrelease> {
%<latexrelease> \int_decr:N \l_@@_labels_int
-%<latexrelease> \prop_get:NVN \l_@@_work_prop \l_@@_front_tl \l_@@_return_tl
+%<latexrelease> \prop_get:NVN \l_@@_work_prop
+%<latexrelease> \l_@@_front_tl \l_@@_return_tl
%<latexrelease> \exp_args:NNV \@@_tl_gput:Nn #1 \l_@@_return_tl
%<latexrelease> \@@_clist_gput:NV #2 \l_@@_front_tl
-%<latexrelease> \@@_debug:n{ \iow_term:x{Handled~ code~ for~ \l_@@_front_tl} }
-%<latexrelease> \seq_map_inline:cn { \@@_seq_csname:n { \l_@@_front_tl } }
+%<latexrelease> \@@_debug:n{ \iow_term:x
+%<latexrelease> {Handled~ code~ for~ \l_@@_front_tl} }
+%<latexrelease> \seq_map_inline:cn
+%<latexrelease> { \@@_seq_csname:n { \l_@@_front_tl } }
%<latexrelease> {
%<latexrelease> \tl_set:cx { \@@_tl_csname:n {##1} }
-%<latexrelease> { \int_eval:n
-%<latexrelease> { \cs:w \@@_tl_csname:n {##1} \cs_end: - 1 }
-%<latexrelease> }
+%<latexrelease> { \int_eval:n
+%<latexrelease> { \cs:w \@@_tl_csname:n {##1} \cs_end: - 1 }
+%<latexrelease> }
%<latexrelease> \int_compare:nNnT
-%<latexrelease> { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0
-%<latexrelease> {
-%<latexrelease> \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } } {##1}
-%<latexrelease> \tl_set:Nn \l_@@_rear_tl {##1}
-%<latexrelease> }
+%<latexrelease> { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0
+%<latexrelease> {
+%<latexrelease> \tl_set:cn { \@@_tl_csname:n
+%<latexrelease> { \l_@@_rear_tl } } {##1}
+%<latexrelease> \tl_set:Nn \l_@@_rear_tl {##1}
+%<latexrelease> }
%<latexrelease> }
%<latexrelease> \tl_set_eq:Nc \l_@@_front_tl
-%<latexrelease> { \@@_tl_csname:n { \l_@@_front_tl } }
+%<latexrelease> { \@@_tl_csname:n { \l_@@_front_tl } }
%<latexrelease> }
%<latexrelease> \int_compare:nNnF \l_@@_labels_int = 0
%<latexrelease> {
@@ -5747,7 +5839,8 @@
%<latexrelease> \@@_debug_label_data:N \l_@@_work_prop
%<latexrelease> \iow_term:x{====================}
%<latexrelease> }
-%<latexrelease> \exp_args:NNo \@@_tl_gput:Nn #1 { \cs:w @@_toplevel~#3 \cs_end: }
+%<latexrelease> \exp_args:NNo \@@_tl_gput:Nn #1
+%<latexrelease> { \cs:w @@_toplevel~#3 \cs_end: }
%<latexrelease> \@@_tl_gput_right:No #1 { \cs:w @@_next~#3 \cs_end: }
%<latexrelease> }
%<latexrelease>\cs_generate_variant:Nn \@@_tl_gput_right:Nn { No }
@@ -6008,6 +6101,8 @@
%
% \changes{v1.1a}{2023/04/06}
% {Changes to add hook arguments (hook-args).}
+% \changes{v1.1g}{2024/01/03}
+% {Fix expansion of \cs{@@_print_args:nn} argument (gh/1221).}
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_log:nN}
%<latexrelease> {Hooks~with~args}
@@ -6027,7 +6122,7 @@
hook~'#1'
\@@_if_disabled:nF {#1}
{
- \exp_args:Nf \@@_print_args:nn {#1}
+ \exp_args:Nne \@@_print_args:nn {#1}
{
\int_eval:n
{ \str_count:e { \@@_parameter:n {#1} } / 3 }
@@ -6164,7 +6259,8 @@
%<latexrelease> }
%<latexrelease> \@@_preamble_hook:n {#1}
%<latexrelease> \@@_log_cmd:x
-%<latexrelease> { ^^J ->~The~ \@@_if_generic:nT {#1} { generic~ } hook~'#1': }
+%<latexrelease> { ^^J ->~The~ \@@_if_generic:nT
+%<latexrelease> {#1} { generic~ } hook~'#1': }
%<latexrelease> \@@_if_usable:nF {#1}
%<latexrelease> { \@@_log_line:x { The~hook~is~not~declared. } }
%<latexrelease> \@@_if_disabled:nT {#1}
@@ -6177,26 +6273,30 @@
%<latexrelease> { \@@_log_line_indent:x { --- } }
%<latexrelease> {
%<latexrelease> \prop_map_inline:cn { g_@@_#1_code_prop }
-%<latexrelease> { \@@_log_line_indent:x { ##1~->~\tl_to_str:n {##2} } }
+%<latexrelease> { \@@_log_line_indent:x
+%<latexrelease> { ##1~->~\tl_to_str:n {##2} } }
%<latexrelease> }
%<latexrelease> \@@_log_line:x
%<latexrelease> {
%<latexrelease> Document-level~(top-level)~code
%<latexrelease> \@@_if_usable:nT {#1}
-%<latexrelease> { ~(executed~\@@_if_reversed:nTF {#1} {first} {last} ) } :
+%<latexrelease> { ~(executed~
+%<latexrelease> \@@_if_reversed:nTF {#1} {first} {last} ) } :
%<latexrelease> }
%<latexrelease> \@@_log_line_indent:x
%<latexrelease> {
%<latexrelease> \tl_if_empty:cTF { @@_toplevel~#1 }
%<latexrelease> { --- }
-%<latexrelease> { -> ~ \exp_args:Nv \tl_to_str:n { @@_toplevel~#1 } }
+%<latexrelease> { -> ~ \exp_args:Nv \tl_to_str:n
+%<latexrelease> { @@_toplevel~#1 } }
%<latexrelease> }
%<latexrelease> \@@_log_line:x { Extra~code~for~next~invocation: }
%<latexrelease> \@@_log_line_indent:x
%<latexrelease> {
%<latexrelease> \tl_if_empty:cTF { @@_next~#1 }
%<latexrelease> { --- }
-%<latexrelease> { ->~ \exp_args:Nv \@@_log_next_code:n { @@_next~#1 } }
+%<latexrelease> { ->~ \exp_args:Nv \@@_log_next_code:n
+%<latexrelease> { @@_next~#1 } }
%<latexrelease> }
%<latexrelease> \@@_log_line:x { Rules: }
%<latexrelease> \bool_set_true:N \l_@@_tmpa_bool
@@ -6220,7 +6320,8 @@
%<latexrelease> {
%<latexrelease> Execution~order
%<latexrelease> \bool_if:NTF \l_@@_tmpa_bool
-%<latexrelease> { \@@_if_reversed:nT {#1} { ~(after~reversal) } }
+%<latexrelease> { \@@_if_reversed:nT
+%<latexrelease> {#1}{ ~(after~reversal) } }
%<latexrelease> { ~(after~
%<latexrelease> \@@_if_reversed:nT {#1} { reversal~and~ }
%<latexrelease> applying~rules)
@@ -6231,16 +6332,19 @@
%<latexrelease> \@spaces
%<latexrelease> \clist_if_empty:cTF { g_@@_#1_labels_clist }
%<latexrelease> { --- }
-%<latexrelease> { \clist_use:cn { g_@@_#1_labels_clist } { ,~ } }
+%<latexrelease> { \clist_use:cn
+%<latexrelease> { g_@@_#1_labels_clist } { ,~ } }
%<latexrelease> }
%<latexrelease> }
%<latexrelease> {
%<latexrelease> \@@_log_line:x { Execution~order: }
%<latexrelease> #2
%<latexrelease> {
-%<latexrelease> \@spaces Not~set~because~the~hook~ \@@_if_usable:nTF {#1}
+%<latexrelease> \@spaces Not~set~because~the~hook~
+%<latexrelease> \@@_if_usable:nTF {#1}
%<latexrelease> { code~pool~is~empty }
-%<latexrelease> { is~\@@_if_disabled:nTF {#1} {disabled} {undeclared} }
+%<latexrelease> { is~\@@_if_disabled:nTF
+%<latexrelease> {#1} {disabled} {undeclared} }
%<latexrelease> }
%<latexrelease> }
%<latexrelease> }
@@ -6388,7 +6492,8 @@
%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_gput_next_code:nn}
%<latexrelease> {Hooks~with~args}
%<latexrelease>\cs_gset_protected:Npn \hook_gput_next_code:nn #1
-%<latexrelease> { \@@_normalize_hook_args:Nn \@@_gput_next_code:nn {#1} }
+%<latexrelease> { \@@_normalize_hook_args:Nn
+%<latexrelease> \@@_gput_next_code:nn {#1} }
%<latexrelease>\cs_gset_protected:Npn \hook_gput_next_code_with_args:nn #1 #2 { }
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
@@ -6580,7 +6685,8 @@
%<latexrelease> \fi:
%<latexrelease> \cs:w @@~#1 \@@_use_end:
%<latexrelease> }
-%<latexrelease>\cs_new:Npn \@@_use_undefined:w #1 #2 @@~#3 \@@_use_end:
+%<latexrelease>\cs_new:Npn \@@_use_undefined:w
+%<latexrelease> #1 #2 @@~#3 \@@_use_end:
%<latexrelease> {
%<latexrelease> #1 % fi
%<latexrelease> \@@_use:wn #3 / \s_@@_mark {#3}
@@ -6680,15 +6786,18 @@
%
% \changes{v1.0s}{2021/09/28}
% {Correct usage of older \cs{@@_if_file_hook:wTF} (gh/675)}
+% \changes{v1.1h}{2024/01/24}
+% {Correct usage of older \cs{@@_if_file_hook:wTF} (gh/1243)}
% \begin{macrocode}
%<latexrelease>\cs_new_protected:Npn \@@_try_file_hook:n #1
%<latexrelease> {
-%<latexrelease> \@@_if_file_hook:wTF #1 / \s_@@_mark
+%<latexrelease> \@@_if_file_hook:wTF #1 / / \s_@@_mark
%<latexrelease> {
%<latexrelease> \exp_args:Ne \@@_if_usable_use:n
%<latexrelease> { \exp_args:Ne \@@_file_hook_normalize:n {#1} }
%<latexrelease> }
-%<latexrelease> { \@@_if_usable_use:n {#1} } % file/ generic hook (e.g. file/before)
+%<latexrelease> { \@@_if_usable_use:n {#1} }
+%<latexrelease> % file/ generic hook (e.g. file/before)
%<latexrelease> }
% \end{macrocode}
%
@@ -6726,12 +6835,14 @@
\cs_new_protected:Npn \hook_use_once:n #1
{
\@@_if_execute_immediately:nF {#1}
- { \@@_normalize_hook_args:Nn \@@_use_once:nn { \use:n {#1} } { 0 } }
+ { \@@_normalize_hook_args:Nn \@@_use_once:nn
+ { \use:n {#1} } { 0 } }
}
\cs_new_protected:Npn \hook_use_once:nnw #1 #2
{
\@@_if_execute_immediately:nF {#1}
- { \@@_normalize_hook_args:Nn \@@_use_once:nn { \use:n {#1} } {#2} }
+ { \@@_normalize_hook_args:Nn \@@_use_once:nn
+ { \use:n {#1} } {#2} }
}
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
@@ -6743,7 +6854,8 @@
%<latexrelease>\cs_gset_protected:Npn \hook_use_once:n #1
%<latexrelease> {
%<latexrelease> \@@_if_execute_immediately:nF {#1}
-%<latexrelease> { \@@_normalize_hook_args:Nn \@@_use_once:n { \use:n {#1} } }
+%<latexrelease> { \@@_normalize_hook_args:Nn \@@_use_once:n
+%<latexrelease> { \use:n {#1} } }
%<latexrelease> }
%<latexrelease>\cs_gset:Npn \hook_use_once:nnw #1 #2
%<latexrelease> { \use:c { use_none: \prg_replicate:nn {#2} { n } } }
@@ -6768,7 +6880,8 @@
% along with the next execution code.
% \begin{macrocode}
\@@_replacing_args_false:
- \@@_cs_gput_right:nnn { _next } {#1} { \@@_use_once_clear:n {#1} }
+ \@@_cs_gput_right:nnn { _next } {#1}
+ { \@@_use_once_clear:n {#1} }
\@@_replacing_args_reset:
\@@_if_usable:nTF {#1}
{ \@@_use_initialized:n {#1} }
@@ -7215,7 +7328,8 @@
{ Cannot~add~code~to~disabled~hook~'#1'. }
{
The~hook~'#1'~you~tried~to~add~code~to~was~previously~disabled~
- with~\iow_char:N\\hook_disable_generic:n~or~\iow_char:N\\DisableGenericHook,~so~
+ with~\iow_char:N\\hook_disable_generic:n~or~
+ \iow_char:N\\DisableGenericHook,~so~
it~cannot~have~code~added~to~it.
}
% \end{macrocode}
@@ -7383,7 +7497,7 @@
%<latexrelease> {Hooks~with~args}
%<latexrelease>\cs_new_protected:Npn \NewHookWithArguments #1 #2 { }
%<latexrelease>\cs_new_protected:Npn \NewReversedHookWithArguments #1 #2 { }
-%<latexrelease>\cs_new_protected:Npn \NewMirroredHookPairWithArguments #1 #2 #3 { }
+%<latexrelease>\cs_new_protected:Npn \NewMirroredHookPairWithArguments #1 #2 #3{}
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
@@ -7835,7 +7949,8 @@
%<latexrelease> \exp_args:No \exp_not:o
%<latexrelease> {
%<latexrelease> \cs:w @@#1~#2 \exp_last_unbraced:Ne \cs_end:
-%<latexrelease> { \@@_braced_cs_parameter:n { @@#1~#2 } }
+%<latexrelease> { \@@_braced_cs_parameter:n
+%<latexrelease> { @@#1~#2 } }
%<latexrelease> }
%<latexrelease> }
%<latexrelease> }
diff --git a/Master/texmf-dist/source/latex/base/ltkeys.dtx b/Master/texmf-dist/source/latex/base/ltkeys.dtx
index da8340ea9d0..34a0ab4b477 100644
--- a/Master/texmf-dist/source/latex/base/ltkeys.dtx
+++ b/Master/texmf-dist/source/latex/base/ltkeys.dtx
@@ -100,7 +100,7 @@
% \texttt{second-name} can be given anywhere, and will save its value in
% \cs{@mypkg@other@name}.
%
-% Keys created \emph{before} the use of \cs{ProcessKeyOptions}act as
+% Keys created \emph{before} the use of \cs{ProcessKeyOptions} act as
% package options.
% \end{function}
%
diff --git a/Master/texmf-dist/source/latex/base/ltluatex.dtx b/Master/texmf-dist/source/latex/base/ltluatex.dtx
index c310ac8ecff..a15019dcd55 100644
--- a/Master/texmf-dist/source/latex/base/ltluatex.dtx
+++ b/Master/texmf-dist/source/latex/base/ltluatex.dtx
@@ -23,16 +23,22 @@
%<tex> \ProvidesFile\undefined\begingroup\def\ProvidesFile
%<tex> #1#2[#3]{\endgroup\immediate\write-1{File: #1 #3}}
%<tex>\fi
-%<plain>\ProvidesFile{ltluatex.tex}%
-%<*driver>
+%<*dtx>
\ProvidesFile{ltluatex.dtx}
-%</driver>
-%<*tex>
-[2023/08/03 v1.2c
-%</tex>
-%<plain> LuaTeX support for plain TeX (core)
-%<*tex>
+%</dtx>
+%<plain>\ProvidesFile{ltluatex.tex}
+%<*plain>
+% \fi
+% \ProvidesFile{ltluatex.dtx}
+[2024/02/11 v1.2c
+% LaTeX Kernel (LuaTeX support)^^A
+%\iffalse
+%<plain> LuaTeX support for plain TeX (core)%
+%\fi
]
+% \iffalse
+%</plain>
+%<*tex>
\edef\etatcatcode{\the\catcode`\@}
\catcode`\@=11
%</tex>
@@ -541,9 +547,9 @@
\csname globbox\endcsname
% \end{macrocode}
%
-% Define|\e@alloc| as in latex (the existing macros in |etex.src|
+% Define|\e@alloc| as in \LaTeX{} (the existing macros in |etex.src| are
% hard to extend to further register types as they assume specific
-% 26x and 27x count range. For compatibility the existing register
+% 26x and 27x count range). For compatibility the existing register
% allocation is not changed.
%
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltmarks.dtx b/Master/texmf-dist/source/latex/base/ltmarks.dtx
index f8268564841..a9f3bb0184f 100644
--- a/Master/texmf-dist/source/latex/base/ltmarks.dtx
+++ b/Master/texmf-dist/source/latex/base/ltmarks.dtx
@@ -14,21 +14,14 @@
%
%%% From File: ltmarks.dtx
%
-% \begin{macrocode}
-\def\ltmarksversion{v1.0d}
-\def\ltmarksdate{2022/06/01}
-% \end{macrocode}
%<*driver>
+% \fi
+\ProvidesFile{ltmarks.dtx}
+ [2024/05/31 v1.0g LaTeX Kernel (Marks)]
+% \iffalse
+%
\documentclass{l3doc}
-
-%\usepackage{ltmarks}
-
-% Fixing footnotes in functions and variables: this should be in l3doc!
-
-\newcommand\fixfootnote[2]{\footnotemark
- \AddToHookNext{env/#1/after}{\footnotetext{#2}}}
-\AddToHook{env/function/begin}{\def\footnote{\fixfootnote{function}}}
-\AddToHook{env/variable/begin}{\def\footnote{\fixfootnote{variable}}}
+\GetFileInfo{ltmarks.dtx}
\EnableCrossrefs
\CodelineIndex
@@ -45,7 +38,7 @@
%
%
% \title{The \texttt{ltmarks.dtx} code\thanks{This file has version
-% \ltmarksversion\ dated \ltmarksdate, \copyright\ \LaTeX\
+% \fileversion\ dated \filedate, \copyright\ \LaTeX\
% Project.}}
% \author{^^A
% Frank Mittelbach, \LaTeX{} Project\thanks
@@ -156,7 +149,7 @@
% \begin{function}{\InsertMark,\mark_insert:nn}
% \begin{syntax}
% \cs{InsertMark} \Arg{class} \Arg{text}
-% \cs{mark_insert:nn} \Arg{class} \Arg{text}
+% \cs{mark_insert:nn} \Arg{class} \Arg{text}
% \end{syntax}
% Adds a mark to the current galley for the \meta{class}, containing the
% \meta{text}.
@@ -291,6 +284,11 @@
% The \meta{pos\textsubscript{\itshape i}} argument can be either
% \texttt{top}, \texttt{first}, or \texttt{last}.
%
+% Important to note is that the comparison is not with respect to
+% the textual content of the marks but whether or not they
+% originated from the same \cs{InsertMark} command (or the L3 layer
+% version \cs{mark_insert:nn}).
+%
% If you wish to compare marks across different regions or across
% different classes, you have to do it using the generic test only
% available in the L3 programming layer or do it manually, i.e.,
@@ -299,6 +297,8 @@
% \emph{true}; if a declared and an undeclared mark class is used
% it is always \emph{false}.}
%
+% \subsection{Use cases for conditionals}
+%
% However, the basic version is enough for the following typical use cases:
% \begin{description}
% \item[Test for at most one mark of class \texttt{myclass} on current
@@ -353,7 +353,7 @@
% \begin{function}{\DebugMarksOn,\DebugMarksOff,
% \mark_debug_on:,\mark_debug_off:}
% \begin{syntax}
-% \cs{DebugMarksOn} ... \cs{DebugMarksOff}
+% \cs{DebugMarksOn} \ldots\ \cs{DebugMarksOff}
% \end{syntax}
%
% Commands to turn the debugging of mark code on or off. The
@@ -397,8 +397,8 @@
%
% \begin{function}{\markboth, \markright}
% \begin{syntax}
-% \cs{markboth} \Arg{left} \Arg{right}
-% \cs{markright} \Arg{right}
+% \cs{markboth} \Arg{left} \Arg{right}
+% \cs{markright} \Arg{right}
% \end{syntax}
% \LaTeXe{} uses two marks which aren't fully independent. A
% \enquote{left} mark generated by the first argument of \cs{markboth}
@@ -610,9 +610,9 @@
% marks. It too is called as part of \cs{@opcol}.
% \end{function}
%
-% \begin{function}{\@@_update_structure:nn}
+% \begin{function}{\@@_update_structure_from_material:nn}
% \begin{syntax}
-% \cs{@@_update_structure:nn} \Arg{region} \Arg{material with marks}
+% \cs{@@_update_structure_from_material:nn} \Arg{region} \Arg{material with marks}
% \end{syntax}
% Helper function that inspects the marks
% inside the second argument and assigns new mark values based on
@@ -627,8 +627,8 @@
% \texttt{page} and \texttt{column} because only they have
% \texttt{previous-...} counterparts.
%
-% Another important part to keep in mind is that marks are only
-% recognized if they appear on top-level, e.g., if we want to
+% Another important aspect to keep in mind is that marks are recognized
+% only if they appear on the top level, e.g., if we want to
% process material stored in boxes we need to put it unboxed (using
% \cs{unvcopy} etc.)\ into the second argument.
% \end{function}
@@ -642,7 +642,7 @@
% Helper function that copies all mark values in the \meta{source}
% region to \meta{alias}, i.e., make the structures identical. Used
% to update the \texttt{previous-...} structures inside
-% \cs{@@_update_structure:nn} and \texttt{first-column} and
+% \cs{@@_update_structure_from_material:nn} and \texttt{first-column} and
% \texttt{last-column} structures inside
% \cs{@@_update_singlecol_structures:} or
% \cs{@@_update_dblcol_structures:}.
@@ -650,7 +650,6 @@
%
%
%
-%
% \begin{function}{\@@_update_structure_to_err:n}
% \begin{syntax}
% \cs{@@_update_structure_to_err:n} \Arg{region}
@@ -662,6 +661,37 @@
% \end{function}
%
%
+% \begin{function}{\@@_get_marks_for_reinsertion:nNN}
+% \begin{syntax}
+% \cs{@@_get_marks_for_reinsertion:nNN} \Arg{source}
+% \qquad \meta{token-list-var for collecting first marks}
+% \qquad \meta{token-list-var for collecting last marks}
+% \end{syntax}
+% Helper function for extracting marks that would otherwise get
+% lost, for example when they are hidden inside a box. This helper
+% does not update mark structures and can therefore be used outside
+% the output routine as well.
+%
+% It collect all the top-level marks from inside the \meta{source}
+% and adds suitable \cs{mark_insert:nn} in the two token
+% lists. These token lists can then be executed at the right place
+% to reinsert the marks, e.g., directly after the box. This is, for
+% example, used by \pkg{multicol} when a short balanced
+% \env{multicols} is returned to the galley for typesetting.
+%
+% If the \meta{source} consists of a single vertical box (plus
+% possibly followed by some glue but nothing else) then the box is
+% unpacked and the top-level marks are collected from its
+% content. However, if it is not a vertical box or there are are
+% other data then nothing is unpacked and you have to do the
+% unpacking yourself to get at the marks inside.
+%
+% It is quite likely that one only needs a single token list for
+% returning the \cs{mark_insert:nn} statements. If that is the case
+% this command may change to take only two arguments.
+% \end{function}
+%
+%
%
% ^^A \end{documentation}
%
@@ -703,12 +733,13 @@
%
%
% \begin{macro}{\mark_new_class:n,\@@_new_class:nn}
+%
% A mark class is created by initializing a number of data
-% structures. First, we get a register number to refer to the mark class.
-% The new mark class is then added to the \cs{g_@@_classes_seq}
-% sequence to be able to easily loop over all classes. Finally a
-% number of top-level global token lists are declared that hold
-% various versions of the mark for access.
+% structures. First, we get a register number to refer to the mark
+% class. The new mark class is then added to the
+% \cs{g_@@_classes_seq} sequence to be able to easily loop over all
+% classes. Finally a number of top-level global token lists are
+% declared that hold various versions of the mark for access.
% \begin{macrocode}
\cs_new_protected:Npn \mark_new_class:n #1
{
@@ -774,6 +805,32 @@
\tl_new:c { g_@@_last-column_top_ #1 _tl }
\tl_new:c { g_@@_last-column_first_ #1 _tl }
\tl_new:c { g_@@_last-column_last_ #1 _tl }
+% \end{macrocode}
+% All marks will have an identication at the beginning of the form
+% \cs{@@_id:n}\texttt\{\meta{number}\texttt\} and therefore the
+% initial empty values should have that too, so that data extraction
+% is going to be uniform.
+% \changes{v1.0g}{2024/05/31}{Initialize all marks with an id, use 0
+% when a new class is made (gh/1359)}
+% \begin{macrocode}
+ \tl_set:cn { g_@@_page_top_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_page_first_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_page_last_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_previous-page_top_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_previous-page_first_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_previous-page_last_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_column_top_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_column_first_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_column_last_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_previous-column_top_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_previous-column_first_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_previous-column_last_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_first-column_top_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_first-column_first_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_first-column_last_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_last-column_top_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_last-column_first_ #1 _tl }{ \@@_id:n{0} }
+ \tl_set:cn { g_@@_last-column_last_ #1 _tl }{ \@@_id:n{0} }
}
% \end{macrocode}
% \end{macro}
@@ -784,57 +841,74 @@
% \subsection{Updating mark structures}
%
%
-% \begin{macro}{\l_@@_box,\g_@@_tmp_tl,\g_@@_new_top_tl}
-% For some operations we need a temporary private box and two
+% \begin{macro}{\l_@@_box,\l_@@_ii_box,\g_@@_tmp_tl,\g_@@_new_top_tl}
+% For some operations we need two temporary private boxes and two
% private global token lists.
% \begin{macrocode}
\box_new:N \l_@@_box
+\box_new:N \l_@@_ii_box
\tl_new:N \g_@@_tmp_tl
\tl_new:N \g_@@_new_top_tl
% \end{macrocode}
% \end{macro}
%
%
-% \begin{macro}{\@@_update_structure:nn}
-%
-% This function updates the mark structures. The first argument is
-% the region to update and second argument receives the material
-% that holds the marks. Out of this material we extract the first
-% and last marks for all classes (if there are any) to do the
-% assignments.
%
+% \begin{macro}{\@@_extract_and_handle_marks:nn}
+% \changes{v1.0e}{2024/01/29}{Macro added}
+%
+% This is the main macro to extract and handle marks inside some
+% vertical material. It is used by
+% \cs{@@_update_structure_from_material:nn} (for updating the mark
+% structure for a region based on the marks found) and by
+% \cs{@@_get_marks_for_reinsertion:nNN} (for extracting marks from
+% some material and prepare for reinserting them later (e.g., out
+% of a box that is placed as a box into the main galley).
% \begin{macrocode}
-\cs_new_protected:Npn \@@_update_structure:nn #1#2
- {
+\cs_new_protected:Npn \@@_extract_and_handle_marks:nn #1#2 {
% \end{macrocode}
-% First thing we do is copying the current structure to
-% \texttt{previous-...}; this leaves the current structure
-% untouched so we can update it class by class (which is necessary).
+% This macro expects code to handle extracted marks in its first argument and
+% vertical material (not boxed or just consisting of a single
+% vertical box) as its second. It
+% extracts top-level mark information from \verb/#2/, stores them
+% as split marks and then calls
+% \verb/#1/ to make use of this information.
+%
+% If it finds a forced break in the material it removes it and then
+% restarts the attempt without it.
+%
+% We start with a group to keep most changes local.
% \begin{macrocode}
- \@@_update_structure_alias:nn { previous-#1 } {#1}
+ \group_begin:
% \end{macrocode}
+%
% Getting the first and last marks out of the material in \verb=#2=
-% is done by putting the material in a box and then doing a
-% split operation to the maximum size possible (which hopefully
-% means all of the content).\footnote{We could verify this, maybe we
-% should.} Because this is an action only for the sake of getting
-% at the mark values we don't want any underfull
-% box warnings so we turn those (locally) off.
+% is done by putting the material in a box and then doing a split
+% operation to the maximum size possible (which hopefully gets us
+% all of the content).\footnote{With normal column material cut
+% from the main galley we should always get all material in one go,
+% but in certain situations, for example, in a \pkg{multicols}
+% environment that contains some \cs{columnbreak}s a single split
+% operation will not be enough. Thus, this is something we need to
+% handle.} Because this action is used only to get the mark
+% values, we don't want any underfull box warnings so we (locally)
+% turn those off.
+%
% \begin{macrocode}
- \group_begin:
\dim_set_eq:NN \tex_splitmaxdepth:D \c_max_dim
\int_set_eq:NN \tex_vbadness:D \c_max_int
\dim_set_eq:NN \tex_vfuzz:D \c_max_dim
% \end{macrocode}
-% There is a further complication: if the region contains infinite
+%
+% There is a further complication: if the material contains infinite
% shrinking glue then a \tn{vsplit} operation will balk with a
-% low-level error. Now pages or columns, which are our main concern here, can't
-% have such infinite shrinkage if they are cut straight from the
-% galley, however the use of \tn{enlargethispage} actually does add
-% some at the very bottom (and also wraps the whole page into a box
-% by itself, so if we leave it this way then a) we get this error
-% and b) we don't see any marks because they are hidden one level
-% down).
+% low-level error. Now pages or columns, which are our main concern
+% here, can't have such infinite shrinkage if they are cut straight
+% from the galley, however the use of \tn{enlargethispage} actually
+% does add some at the very bottom (and also wraps the whole page
+% into a box by itself, so if we leave it this way then a) we get
+% this error and b) we don't see any marks because they are hidden
+% one level down).
%
% Another possible issue are packages or user code that place stray
% \tn{vbox}es directly into the main galley (an example is
@@ -842,93 +916,236 @@
% boxes end up as the last item on the page we should not unpack
% them.
%
-% We therefore do an \tn{unskip} to get rid of that glue if present and
-% also check if we have then a \tn{vbox} as the last item and if so
-% unpack that too, but only under certain conditions, see
-% below. All this is temporary, just for getting the
-% marks out, so it doesn't affect the final page production.
-%
-% In fact, we go one step further and set the box to a large
-% negative height possible and afterwards take a look at the
-% reported badness: if it is zero we know that there has still been
-% infinite shrinkage in the box so that we can't do a
-% \tn{vsplit}. If that is the case we generate an error message and
-% bypass extracting the marks. We use only half of \cs{c_max_dim}
-% because otherwise \TeX{} will report an overfull vbox despite our
-% setting of \cs{tex_vfuzz:D}. This test will not find existing
-% infinite shrinkage in all cases, e.g., if there are several glues
-% that cancel each other, but it is the best we can do.
-% \begin{macrocode}
- \vbox_set_to_ht:Nnn \l_@@_box { -.5\c_max_dim }
- {
- #2
- \tex_unskip:D
- \box_set_to_last:N \l_@@_box
+% All these issues need to be handled, which is done in
+% \cs{@@_prepare_and_extract:nn}.
+%
+% \begin{macrocode}
+ \@@_prepare_and_extract:nn {#1} {#2}
+% \end{macrocode}
+% Once all mark classes have been processed, the data structures are
+% updated and we can close the group, which undoes our local
+% changes and retains only the global ones.
+% \begin{macrocode}
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_prepare_and_extract:nn}
+%
+% This macro does the dirty work. It is not directly integrated in
+% \cs{@@_extract_and_handle_marks:nn} because we may have to call
+% it recursively if we find forced breaks.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_prepare_and_extract:nn #1#2 {
+% \end{macrocode}
+%
+% To handle the \cs{enlargethispage} case we do an \tn{unskip} to
+% get rid of any glue that is present at the very end of the material
+% and also check if we have then a \tn{vbox} as the last item and
+% if so unpack that too, but only under certain conditions, see
+% below. All this is temporary done in a group, just for getting
+% the marks out, so it doesn't affect the final page production.
+%
+% \begin{macrocode}
+ \vbox_set:Nn \l_@@_box
+ {
+ #2
+ \tex_unskip:D
+ \box_set_to_last:N \l_@@_box
% \end{macrocode}
% After having removed the last box from the current list (if there
-% was one)
-% we check if the list is now empty. If not, the the last box is
-% definitely not the one from \tn{enlargethispage} and so we can
-% and should leave it alone. Otherwise we check if this last box is
-% a \tn{vbox}.
+% was one) we check whether the vertical list is now empty. If not,
+% then the last box is definitely not the one from
+% \tn{enlargethispage} and so we can, and should, leave it
+% alone. Otherwise we check if this last box is a \tn{vbox}.
% \changes{v1.0d}{2022/06/01}{Extend the logic for detecting the marks
% in the box (gh/836)}
% \begin{macrocode}
- \int_compare:nNnT \tex_lastnodetype:D < 0
- {
- \box_if_vertical:NT \l_@@_box
- {
-% \end{macrocode}
-% If it is we do a further test and reset the \cs{l_@@_box}
-% to check if it contains infinitely shrinkable glue.
-% \begin{macrocode}
- \vbox_set_to_ht:Nnn \l_@@_box { -.5\c_max_dim }
- {
- \vbox_unpack:N \l_@@_box
- \tex_kern:D \c_zero_dim % ensure that box
- % is not empty
- }
+ \int_compare:nNnT \tex_lastnodetype:D < 0
+ {
+ \box_if_vertical:NT \l_@@_box
% \end{macrocode}
-% If not, then we unpack it, if yes we still ignore it for the process of
-% mark extraction. We do not generate an error though, because in all
-% likelihood this is an ordinary box like a marginal that does
-% contain something like \tn{vss}.
+% If it is, we unpack the box.
% \begin{macrocode}
- \int_compare:nNnT \tex_badness:D > 0
- { \vbox_unpack:N \l_@@_box }
- }
- }
+ { \vbox_unpack:N \l_@@_box }
+ }
% \end{macrocode}
% If it wasn't a vbox, it was either an hbox or there was no box.
% Given that we are only interested in the marks we don't need put
-% it back in that case. However, we have to make sure that the
-% outer box under construction
-% is not totally empty (which it might have been from the start, or
-% now), because \TeX{} does not report a badness for empty boxes
-% and that means our test would incorrectly conclude that we have
-% infinite shrinking glue. A simple \tn{kern} is enough to avoid
-% this (the same was already done above).
-% \begin{macrocode}
- \tex_kern:D \c_zero_dim
- }
- \int_compare:nNnTF \tex_badness:D > 0
+% it back in that case.
+% \begin{macrocode}
+ }
% \end{macrocode}
-% If the box had no infinite shrinkage (or rather if our test
-% didn't show any) we vsplit it. Note that it
-% doesn't matter that we set it to this strange size first. If there
-% was infinite shrinkage after all, we end up with a low-level
-% \TeX{} error, but if there is, it is a coding error and needs
-% correcting.
+% We are now ready to \cs{vsplit} the box to get at the marks. If
+% the box contains some infinite negative glue the \TeX{} will
+% produce an error complaining about it but it will correctly find
+% the the split marks. Given that we can't prevent that error, we
+% hide it from the user and ensure that \TeX{} doesn't stop. The
+% error message still shows in the log, but even that is mitigated
+% as best as possible---see the definition of
+% \cs{@@_vbox_set_split_to_maxdimen:NN} for the tricks employed.
% \begin{macrocode}
- {
- \vbox_set_split_to_ht:NNn \l_@@_box \l_@@_box \c_max_dim
+ \@@_vbox_set_split_to_maxdimen:NN \l_@@_ii_box \l_@@_box
+% \end{macrocode}
+% After splitting we check if there is anything left in
+% \cs{l_@@_box}. If not then the above split has set some split marks
+% that we can then use to finish the extraction:
+% \begin{macrocode}
+ \box_if_empty:NTF \l_@@_box
+ { #1 }
+% \end{macrocode}
+% If we have a remainder after the split then this means that there
+% was some forced break in the material. We get rid of that by
+% combining the content of the two boxes and restart.
+% \begin{macrocode}
+ {
+%<*trace>
+ \@@_debug:n { \iow_term:x
+ { Marks:~ mark~ extraction~needs~ recursion~
+ \msg_line_context: } }
+%</trace>
+ \@@_prepare_and_extract:nn {#1}
+ { \vbox_unpack:N \l_@@_ii_box
+ \vbox_unpack:N \l_@@_box }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_vbox_set_split_to_maxdimen:NN}
+%
+% Split a box to get at its marks without pausing even if \TeX{} is
+% producing an error message because of infinite negative glue in
+% the box. If there is such an error we ensure that it only shows
+% up in the log but not on the terminal.
+%
+% The nice low-level hack by DPC records in the \texttt{.log} that a glue
+% shrinkage error is harmless.
+%
+% We disguise \cs{c_max_dim} in an odd looking csname, which then
+% shows up as part of the display of an error message if that error
+% happens. This csname forms part of the error diplay so what
+% you get is something like
+%\begin{verbatim}
+% ! Infinite glue shrinkage found in box being split.
+% <argument> Infinite shrink error above ignored !
+% l. ... }
+%\end{verbatim}
+% which hopefully makes it clear that the error is harmless and
+% and should be ignored by the reader of the \texttt{.log}.
+% \begin{macrocode}
+\cs_set_eq:cN {Infinite~shrink~error~above~ignored~!}\c_max_dim
+% \end{macrocode}
+%
+% The whole definition of \cs{@@_vbox_set_split_to_maxdimen:NN}
+% below is fully expanded, so we have to use a lot of
+% \cs{exp_not:N} commands to prevent expansion where necessary.
+% \begin{macrocode}
+\cs_new_protected:Npx \@@_vbox_set_split_to_maxdimen:NN #1#2 {
+% \end{macrocode}
+% We start by saving the current interaction and escape char settings.
+% \begin{macrocode}
+ \tl_set:Ne \exp_not:N \l_@@_saved_parameters_tl
+ {
+ \tex_interactionmode:D
+ \exp_not:N \int_use:N \tex_interactionmode:D \scan_stop:
+ \tex_escapechar:D
+ \exp_not:N \int_use:N \tex_escapechar:D \scan_stop:
+ }
+% \end{macrocode}
+% Then we change them so that no escape char is printed in the
+% error message (accounts for the missing backslash in front of
+% \verb/Infinite shrink .../) and we set the interaction to
+% \cs{nonstopmode} so that the the error (if any) just goes into
+% the \texttt{.log} file and \TeX{} doesn't stop at that point.
+% \begin{macrocode}
+ \tex_escapechar:D -1 \scan_stop:
+ \tex_interactionmode:D 0 \scan_stop:
+% \end{macrocode}
+% Then we do the splitting of the box to \cs{c_max_dim} to get at
+% the marks. This may generate the error we are worried about,
+% i.e., if the box contains infinite negative glue. However, \TeX{}
+% makes this glue finite and continues, which means we get our split
+% marks which is really all we care about.
+% \begin{macrocode}
+ \tex_setbox:D #1 \tex_vsplit:D #2 to
+% \end{macrocode}
+% The \cs{use:n} may seem pointless, and it is to some extent, but
+% we need it to get our disguised \cs{c_max_dim} displayed
+% properly as part of the error message if there is one. Without
+% it, the display would show only part of what we want it to show
+% (try it).
+% \begin{macrocode}
+ \exp_not:N \use:n {
+ \use:c{Infinite~shrink~error~above~ignored~!}
+ }
+% \end{macrocode}
+% Finally, we change the escape char and the interaction mode back
+% to what it was before:
+% \begin{macrocode}
+ \exp_not:N \l_@@_saved_parameters_tl
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\l_@@_saved_parameters_tl}
+% The temporary variable used for resetting escape char and
+% interaction mode.
+% \begin{macrocode}
+\tl_new:N \l_@@_saved_parameters_tl
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_update_structure_from_material:nn}
+%
+% \changes{v1.0e}{2024/01/29}{Macro renamed}
+%
+% This function updates the mark structures of a region. The first
+% argument is the region to update and second argument receives the
+% material that holds the marks. Out of this material we extract
+% the first and last marks for all classes (if there are any) to do
+% the assignments.
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_update_structure_from_material:nn #1#2 {
+ \@@_extract_and_handle_marks:nn
+% \end{macrocode}
+%
+% Once the marks can be extracted we update the structure from the
+% split marks (code in \cs{@@_update_structure_from_splitmarks:n}).
+% \begin{macrocode}
+ { \@@_update_structure_from_splitmarks:n {#1} }
+ { #2 }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_update_structure_from_splitmarks:n}
+% This macro is called after we have done a \cs{tex_vsplit:D}
+% operation and the mark data is in the split marks.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_update_structure_from_splitmarks:n #1 {
+% \end{macrocode}
+%
+% The first thing we do is to copy the current region structure to
+% \texttt{previous-...}; this leaves the current structure
+% untouched so we can update it class by class (which is necessary).
+% \begin{macrocode}
+ \@@_update_structure_alias:nn { previous-#1 } {#1}
% \end{macrocode}
% After this action we can get first and last marks of the various
% classes through \cs{tex_splitfirstmarks:D} and
% \cs{tex_splitbotmarks:D}. So now we loop over all classes stored in
% \cs{g_@@_classes_seq}.
% \begin{macrocode}
- \seq_map_inline:Nn \g_@@_classes_seq
+ \seq_map_inline:Nn \g_@@_classes_seq
{
% \end{macrocode}
% First action: get the last mark from the previous region, i.e.,
@@ -950,14 +1167,14 @@
\tl_gset:No \g_@@_tmp_tl
{ \tex_splitbotmarks:D \use:c { c_@@_class_##1_mark } }
% \end{macrocode}
-% If this mark doesn't exist then obviously first mark does
-% neither, so both become the last mark from the previous region. We
+% If this mark doesn't exist then obviously neither does the first mark,
+% so both become the last mark from the previous region. We
% have to be a little careful here: something like
% \verb=\mark_insert:nn{foo}{}= adds an \enquote{empty} mark that should
% not be confused with no mark at all. But no mark in our material
% will result in \cs{g_@@_tmp_tl} being fully empty. This is why we
% have to make sure that \enquote{empty} from \cs{mark_insert:nn} only
-% appears to be empty but fails the next test (see below how this
+% appears to be empty when typeset but fails the next test (see below how this
% is done).
% \begin{macrocode}
\tl_if_empty:NTF \g_@@_tmp_tl
@@ -987,29 +1204,144 @@
}
}
}
- }
+}
% \end{macrocode}
-% If the badness was zero (we actually tested for${}>0$ but it
-% can't get negative) then we had infinite shrinkage, so we report
-% that and set all marks to the value the last mark had before.
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_get_marks_for_reinsertion:nNN}
+%
+% This function extracts the marks from the material in the first
+% argument but it does not update any the mark structures. Instead,
+% it collects the marks in the token lists given as the second and
+% third argument, in such a way that they can be reinserted by just
+% executing the token lists.\footnote{It is probably enough to
+% collect everything in a single token list as long as we put the
+% first marks first and the last marks last). But for extra
+% flexibility, I currently use 2 token lists. This might change when it is
+% really clear that this is never needed.}
+%
% \begin{macrocode}
- {
- \msg_error:nnn { mark } { infinite-shrinkage } {#1}
- \seq_map_inline:Nn \g_@@_classes_seq
+\cs_new_protected:Npn \@@_get_marks_for_reinsertion:nNN #1#2#3 {
+% \end{macrocode}
+% First we clear the temporary token lists as we haven't seen any marks yet.
+% \begin{macrocode}
+ \tl_clear:N \g_@@_first_marks_tl
+ \tl_clear:N \g_@@_last_marks_tl
+% \end{macrocode}
+% Then we extract all top-level marks, thereby filling the token lists
+% with suitable \cs{mark_insert:nn} calls.
+% \begin{macrocode}
+ \@@_extract_and_handle_marks:nn
+% \end{macrocode}
+% The first argument holds the code for fill the token lists and
+% the second is the material we extract from.
+% \begin{macrocode}
+ \@@_get_from_splitmarks:
+ { #1 }
+% \end{macrocode}
+%
+% Finally, we copy the updated (or not updated) temporary token
+% lists to the two that have been supplied when the function was
+% called. By convention \enquote{get} operations return their
+% values in local variables and \cs{@@_extract_and_handle_marks:nn}
+% runs in a group, which is why we have to use global temporary
+% variables for collecting.
+% \begin{macrocode}
+ \tl_set_eq:NN #2 \g_@@_first_marks_tl
+ \tl_set_eq:NN #3 \g_@@_last_marks_tl
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_get_from_splitmarks:}
+% This function is called after we have done a \cs{vsplit} to
+% update the split marks. It loops through all mark classes to find
+% out if there are marks for this class and if so updates the
+% global tls used for collecting.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_get_from_splitmarks: {
+ \seq_map_inline:Nn \g_@@_classes_seq
{
- \tl_gset_eq:cc { g_@@_#1_top_ ##1_tl }
- { g_@@_#1_last_ ##1_tl }
- \tl_gset_eq:cc { g_@@_#1_first_##1_tl }
- { g_@@_#1_last_ ##1_tl }
+% \end{macrocode}
+% First we to get the last mark for the current class from the
+% material supplied.
+% \begin{macrocode}
+ \tl_gset:No \g_@@_tmp_tl
+ { \tex_splitbotmarks:D \use:c { c_@@_class_##1_mark } }
+% \end{macrocode}
+%
+% If this mark doesn't exist then obviously first mark doesn't
+% either, so we do nothing (other than issuing some debugging
+% info).
+
+% We have to be a little careful here: something like
+% \verb=\mark_insert:nn{foo}{}= adds an \enquote{empty} mark that
+% we should not confuse with the case where there is no mark at
+% all.
+%
+% When there is no mark at all we get a truly empty
+% \cs{g_@@_tmp_tl} as a result. This is why we have to make sure
+% that an \enquote{empty} mark generated with \cs{mark_insert:nn}
+% only appears to be empty when it is typeset, but fails the next
+% test (see below how this is done).
+% \begin{macrocode}
+ \tl_if_empty:NTF \g_@@_tmp_tl
+ {
+%<*trace>
+ \@@_debug:n { \iow_term:x { Marks:~no~ marks~
+ for~ class~ '##1'~\msg_line_context: } }
+%</trace>
+ }
+% \end{macrocode}
+%
+% If it wasn't empty, i.e., if it had a real value then we use this
+% value for our new last mark instead. This means we put an
+% appropriate \cs{mark_insert:nn} statement into
+% \cs{g_@@_last_marks_tl}.
+% \begin{macrocode}
+ {
+%<*trace>
+ \@@_debug:n { \iow_term:x { Marks:~ extract~ last~
+ mark~ for~ class~ '##1'~ =~ \g_@@_tmp_tl } }
+%</trace>
+ \tl_gput_right:Ne \g_@@_last_marks_tl
+ { \mark_insert:nn {##1} { \g_@@_tmp_tl } }
+% \end{macrocode}
+% Because we had a last mark we also have a first mark (which might
+% be the same, but might not be), so we pick that up and add it to
+% the \cs{g_@@_first_marks_tl} token list. This explains why we
+% first checked for the last mark because that makes the processing
+% faster in case there is none.
+% \begin{macrocode}
+%<*trace>
+ \@@_debug:n { \iow_term:x { Marks:~ extract~ first~
+ mark~ for~ class~ '##1'~ =~
+ \tex_splitfirstmarks:D
+ \use:c { c_@@_class_##1_mark }
+ } }
+%</trace>
+ \tl_gput_right:Ne \g_@@_first_marks_tl
+ { \mark_insert:nn {##1}
+ {
+ \tex_splitfirstmarks:D
+ \use:c { c_@@_class_##1_mark }
+ }
+ }
+ }
}
- }
+}
% \end{macrocode}
-% Once all mark classes have been processed the data structures are
-% updated and we can close the group which undoes our local
-% changes and retains only the global ones.
+% \end{macro}
+%
+%
+% \begin{macro}{\g_@@_first_marks_tl,\g_@@_last_marks_tl}
+% These are two global temporary variables used in the code above.
% \begin{macrocode}
- \group_end:
- }
+\tl_new:N \g_@@_first_marks_tl
+\tl_new:N \g_@@_last_marks_tl
% \end{macrocode}
% \end{macro}
%
@@ -1098,7 +1430,18 @@
% \begin{macrocode}
\@kernel@before@insertmark
\hook_use:n { insertmark }
- \unrestored@protected@xdef \g_@@_tmp_tl {#2}
+ \unrestored@protected@xdef \g_@@_tmp_tl
+ {
+% \end{macrocode}
+% To ensure that marks are unique we insert a hidden sequence
+% marker at the beginning of the content of the mark containing the
+% sequence number of the mark.
+% \changes{v1.0f}{2024/05/30}{Use sequence marker to make all marks
+% unique on nearby regions (gh/1359)}
+% \begin{macrocode}
+ \@@_id:n{ \int_use:N\g_@@_int }
+ #2
+ }
%<*trace>
\@@_debug:n{ \iow_term:x { Marks:~ set~#1~<-~
'\tl_to_str:V \g_@@_tmp_tl' ~ \msg_line_context: } }
@@ -1111,9 +1454,11 @@
% becomes empty, but not immediately; otherwise we just put
% \cs{g_@@_tmp_tl} in.
% \begin{macrocode}
- \tl_if_empty:NTF \g_@@_tmp_tl
- { \exp_not:n { \prg_do_nothing: } }
- { \exp_not:o { \g_@@_tmp_tl } }
+% this is no longer needed with 1.0f
+% \tl_if_empty:NTF \g_@@_tmp_tl
+% { \exp_not:n { \prg_do_nothing: } }
+% { \exp_not:o { \g_@@_tmp_tl } }
+ \exp_not:o { \g_@@_tmp_tl }
}
\group_end:
% \end{macrocode}
@@ -1135,15 +1480,43 @@
% \end{macro}
%
%
+% \begin{macro}{\@@_id:n}
+% A hidden marker is placed into every mark added by
+% \cs{mark_insert:nn}. It will will not show up in the output but
+% its argument (a counter value that is incremented) makes all
+% marks unique so the test for \enquote{equal} is not fooled by two
+% different marks having the same mark text.
+% \changes{v1.0f}{2024/05/30}{Use sequence marker to make all marks
+% unique on nearby regions (gh/1359)}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_id:n #1 { }
+% \end{macrocode}
+% \end{macro}
+%
+%
% \begin{macro}[int]{\@kernel@before@insertmark}
% \begin{macro}{insertmark}
% By default \cs{label}, \cs{index}, and \cs{glossary} do nothing
% when the mark is inserted.
% \begin{macrocode}
+\int_new:N \g_@@_int
\cs_new:Npn \@kernel@before@insertmark {
\cs_set_eq:NN \label \scan_stop:
\cs_set_eq:NN \index \scan_stop:
\cs_set_eq:NN \glossary \scan_stop:
+% \end{macrocode}
+% We count each mark and use that to place a hidden marker in front
+% of the mark text. To ensure that there is no overflow (very
+% unlikely but you never know) we restart every 100000 marks. Thus,
+% if somebody puts more than that number of marks on a single page
+% you could construct a scenario in which that approach fails.
+% \changes{v1.0f}{2024/05/30}{Use sequence marker to make all marks
+% unique on nearby regions (gh/1359)}
+% \begin{macrocode}
+ \int_compare:nNnTF \g_@@_int < {99999}
+ { \int_gincr:N \g_@@_int }
+ { \int_gzero:N \g_@@_int }
+
}
% \end{macrocode}
% The public hook to augment the setup.
@@ -1158,15 +1531,25 @@
% To retrieve the first, last or top region mark, we grab the
% appropriate value stored in the corresponding token list variable
% and pass its contents back. These functions should be used only
-% in output routines after \cs{@@_update_structure:nn} has acted,
+% in output routines and only after \cs{@@_update_structure_from_material:nn} has acted,
% otherwise their value will be wrong.
%
% If used with an unknown class or region they generate an error
% (fairly low-level because we are in an expandable context).
+%
+% Each mark starts with an id and while the id does not print it is
+% nevertheless better to remove it when returning the mark, so that
+% downstream manipulation of the data doesn't have to deal with it.
+% \changes{v1.0g}{2024/05/31}{Remove the id when returning the mark value (gh/1359)}
% \begin{macrocode}
-\cs_new:Npn \mark_use_first:nn #1#2 { \exp_not:v { g_@@_#1_first_#2_tl } }
-\cs_new:Npn \mark_use_last:nn #1#2 { \exp_not:v { g_@@_#1_last_#2_tl } }
-\cs_new:Npn \mark_use_top:nn #1#2 { \exp_not:v { g_@@_#1_top_#2_tl } }
+\cs_new:Npn \mark_use_first:nn #1#2 { \@@_use:v { g_@@_#1_first_#2_tl } }
+\cs_new:Npn \mark_use_last:nn #1#2 { \@@_use:v { g_@@_#1_last_#2_tl } }
+\cs_new:Npn \mark_use_top:nn #1#2 { \@@_use:v { g_@@_#1_top_#2_tl } }
+% \end{macrocode}
+% This is what the \cs{use_none:nn} accomplishes.
+% \begin{macrocode}
+\cs_new:Npn \@@_use:n #1 { \exp_not:o { \use_none:nn #1 } }
+\cs_generate_variant:Nn \@@_use:n { v }
% \end{macrocode}
% \end{macro}
%
@@ -1207,7 +1590,7 @@
%
% \subsection{Messages}
%
-% Mark errors are LaTeX kernel errors:
+% Mark errors are \LaTeX{} kernel errors:
% \changes{v1.0d}{2022/06/01}{Marks are kernel errors}
% \begin{macrocode}
\prop_gput:Nnn \g_msg_module_type_prop { mark } { LaTeX }
@@ -1247,17 +1630,7 @@
}
% \end{macrocode}
%
-% \begin{macrocode}
-\msg_new:nnnn { mark } { infinite-shrinkage }
- { Infinite~shrinkage~found~in~'#1'. }
- {
- \c__msg_coding_error_text_tl
- The~mark~region~'#1'~contains~some~infinite~negative~glue~
- allowing~it~to~shrink~to~an~arbitrary~size.~
- This~makes~it~impossible~to~split~the~region~apart~to~
- get~at~its~marks.~They~are~lost.
- }
-% \end{macrocode}
+%
%
%
%
@@ -1358,7 +1731,7 @@
%
%
% \begin{macro}{\@@_status:n}
-% Show all mark class values across all regions.
+% Show a snapshot of all mark class values across all regions.
% \begin{macrocode}
\cs_new_protected:Npn \@@_status:n #1
{
@@ -1370,6 +1743,22 @@
% \end{macro}
%
%
+% \begin{macro}{\ShowMarksAt}
+% \changes{v1.0e}{2024/01/29}{Macro added}
+% Debugging helper that displays a snapshot of all known mark
+% structures. The argument is a text string that is
+% displayed to help identifying when the snapshot was made.
+%
+% This may not stay like this (or at all), which is why it isn't
+% yet documented as an official command.
+% \begin{macrocode}
+\cs_new_protected:Npn \ShowMarksAt #1 {
+%<*trace>
+ \@@_debug:n { \@@_status:n {#1} }
+%</trace>
+}
+% \end{macrocode}
+% \end{macro}
%
%
% \subsection{Designer-level interfaces}
@@ -1425,9 +1814,9 @@
%
%
%
-% \section{\LaTeXe{} integration}
+% \section{\LaTeXe{} integration}
%
-% \subsection{Core \LaTeXe{} integration}
+% \subsection{Core \LaTeXe{} integration}
%
% \begin{macro}{\@@_update_singlecol_structures:}
% This command updates the mark structures if we are producing a
@@ -1445,11 +1834,11 @@
% \begin{macrocode}
\box_if_vertical:NTF \@outputbox
{
- \@@_update_structure:nn {page}
+ \@@_update_structure_from_material:nn {page}
{ \vbox_unpack:N \@outputbox }
}
{
- \@@_update_structure:nn {page}
+ \@@_update_structure_from_material:nn {page}
{ \hbox_unpack:N \@outputbox }
}
% \end{macrocode}
@@ -1489,11 +1878,11 @@
% \begin{macrocode}
\box_if_vertical:NTF \@outputbox
{
- \@@_update_structure:nn {column}
+ \@@_update_structure_from_material:nn {column}
{ \vbox_unpack:N \@outputbox }
}
{
- \@@_update_structure:nn {column}
+ \@@_update_structure_from_material:nn {column}
{ \hbox_unpack:N \@outputbox }
}
% \end{macrocode}
@@ -1538,6 +1927,12 @@
% \begin{macrocode}
\seq_map_inline:Nn \g_@@_classes_seq
{
+% \end{macrocode}
+% The \texttt{previous-page} updates need to come before the
+% updates for \texttt{page} region because otherwise the values
+% to copy are already overwritten.
+% necessary values.
+% \begin{macrocode}
\tl_gset_eq:cc { g_@@_previous-page_top_ ##1 _tl }
{ g_@@_page_top_ ##1 _tl }
\tl_gset_eq:cc { g_@@_previous-page_first_ ##1 _tl }
@@ -1545,16 +1940,48 @@
\tl_gset_eq:cc { g_@@_previous-page_last_ ##1 _tl }
{ g_@@_page_last_ ##1 _tl }
% \end{macrocode}
-% The \texttt{page} updates need to come after the corresponding
-% updates for \texttt{previous-page} otherwise we loose the
-% necessary value.
+% To update the \texttt{top} we only have to copy what is in
+% \texttt{first-column}:
% \begin{macrocode}
\tl_gset_eq:cc { g_@@_page_top_ ##1 _tl }
{ g_@@_first-column_top_ ##1 _tl }
- \tl_gset_eq:cc { g_@@_ page_first_ ##1 _tl }
- { g_@@_first-column_first_ ##1 _tl }
- \tl_gset_eq:cc { g_@@_page_last_ ##1 _tl }
- { g_@@_last-column_last_ ##1 _tl }
+
+% \end{macrocode}
+% Updating the \texttt{first} mark for the \texttt{page} region is
+% more complicated. We first have to find out of there is any mark
+% in the first column (this can be done by comparing the \texttt{top} and
+% the \texttt{first} mark of of that region).
+% \changes{v1.0f}{2024/05/30}{Correct logic for first mark in page
+% region if first column contains no marks (gh/1359)}
+% \begin{macrocode}
+ \tl_if_eq:ccTF { g__@@_first-column_top_ ##1 _tl }
+ { g__@@_first-column_first_ ##1 _tl }
+ {
+% \end{macrocode}
+% If there is no mark in the first column we copy the first mark of
+% the last column. If that doesn't contain a mark we still get the
+% right result because the first mark is then equal to the top mark.
+% \begin{macrocode}
+ \tl_gset_eq:cc { g_@@_page_first_ ##1 _tl }
+ { g_@@_last-column_first_ ##1 _tl }
+ }
+ {
+% \end{macrocode}
+% On the other hand, if there is a mark in the first column we copy
+% over the \texttt{first} mark from that column.
+% \begin{macrocode}
+ \tl_gset_eq:cc { g_@@_page_first_ ##1 _tl }
+ { g_@@_first-column_first_ ##1 _tl }
+ }
+% \end{macrocode}
+% The logic for the \texttt{last} page mark is again simple, we can
+% just copy the value in the \texttt{last} mark of the last column.
+% If that column doesn't contain any marks, then the value in
+% \texttt{last} will be automatically the same as the \texttt{last}
+% from the first column.
+% \begin{macrocode}
+ \tl_gset_eq:cc { g_@@_page_last_ ##1 _tl }
+ { g_@@_last-column_last_ ##1 _tl }
}
}
%<*trace>
@@ -1583,17 +2010,26 @@
%<@@=>
% \end{macrocode}
%
-% \begin{macro}[int]{\@expl@@@mark@update@singlecol@structures@@,
-% \@expl@@@mark@update@dblcol@structures@@}
+% \begin{macro}[int]{\@expl@@@mark@update@singlecol@structures@@}
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@mark@update@singlecol@structures@@
\__mark_update_singlecol_structures:
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}[int]{\@expl@@@mark@update@dblcol@structures@@}
+% \begin{macrocode}
\cs_new_eq:NN \@expl@@@mark@update@dblcol@structures@@
\__mark_update_dblcol_structures:
% \end{macrocode}
% \end{macro}
%
-% \subsection{Other \LaTeXe{} output routines}
+%
+%
+%
+% \subsection{Other \LaTeXe{} output routines}
%
% This section will cover \pkg{multicol} and other packages altering
% or providing their own output routine. Not done yet.
@@ -1601,6 +2037,9 @@
%
%
%
+% \subsection{Rollback information}
+%
+%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}{ltmarks}%
%<latexrelease> {Undo~Marks~handling}
@@ -1609,7 +2048,7 @@
% We keep the interface commands around even if we roll back in
% case they are used in packages that don't roll back. Not likely
% to do a lot of good, but then there is not much we can do, but
-% this at least then doesn't give errors.
+% this at least they won't give unknown csname errors.
% \begin{macrocode}
%<latexrelease>\DeclareRobustCommand \NewMarkClass[1]{}
%<latexrelease>\DeclareRobustCommand \InsertMark[2]{}
diff --git a/Master/texmf-dist/source/latex/base/ltmeta.dtx b/Master/texmf-dist/source/latex/base/ltmeta.dtx
index 30da4016fb4..cc3e62811df 100644
--- a/Master/texmf-dist/source/latex/base/ltmeta.dtx
+++ b/Master/texmf-dist/source/latex/base/ltmeta.dtx
@@ -13,20 +13,14 @@
%
%
%%% From File: ltmeta.dtx
-%
-% \begin{macrocode}
-\def\ltmetaversion{v1.0b}
-\def\ltmetadate{2022/05/18}
-% \end{macrocode}
%<*driver>
+% \fi
+\ProvidesFile{ltmeta.dtx}
+ [2024/05/16 v1.0b LaTeX Kernel (Document Metadata)]
+% \iffalse
+%
\documentclass{l3doc}
-
-% Fixing footnotes in functions and variables: this should be in l3doc!
-
-\newcommand\fixfootnote[2]{\footnotemark
- \AddToHookNext{env/#1/after}{\footnotetext{#2}}}
-\AddToHook{env/function/begin}{\def\footnote{\fixfootnote{function}}}
-\AddToHook{env/variable/begin}{\def\footnote{\fixfootnote{variable}}}
+\GetFileInfo{ltmeta.dtx}
\EnableCrossrefs
\CodelineIndex
@@ -43,7 +37,7 @@
%
%
% \title{The \texttt{ltmeta.dtx} code\thanks{This file has version
-% \ltmetaversion\ dated \ltmetadate, \copyright\ \LaTeX\
+% \fileversion\ dated \filedate, \copyright\ \LaTeX\
% Project.}}
% \author{Frank Mittelbach}
%
diff --git a/Master/texmf-dist/source/latex/base/ltmiscen.dtx b/Master/texmf-dist/source/latex/base/ltmiscen.dtx
index 9706f272035..accdac24b2f 100644
--- a/Master/texmf-dist/source/latex/base/ltmiscen.dtx
+++ b/Master/texmf-dist/source/latex/base/ltmiscen.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltmiscen.dtx}
- [2023/09/13 v1.2c LaTeX Kernel (Misc. Environments)]
+ [2024/02/08 v1.2c LaTeX Kernel (Misc. Environments)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltmiscen.dtx}
@@ -509,8 +509,8 @@
% endings are converted to spaces by \TeX{} during that process.
%
% However, especially the \texttt{.toc} file might be read in L-R mode
-% (in cases the \cs{tableofcontents} attempts to put, say a list of
-% sub-sections as a paragraph. In that case the newlines after a line
+% (in cases the \cs{tableofcontents} attempts to put, say, a list of
+% sub-sections as a paragraph). In that case the newlines after a line
% like
% \begin{verbatim}
% \contentsline {subsubsection}{\numberline {1.1.1}A C-head}{2}
@@ -520,9 +520,9 @@
%
% That could be fixed by reading in the file using
% \cs{endlinechar}\texttt{=-1} but that has the danger that it drops
-% some valid endlines that should be converted to spaces (for example
+% some valid endlines that should be converted to spaces (for example,
% when the user edited the TOC and then used \cs{nofiles} to preserve
-% it.
+% it).
%
% So the approach taken instead is this:
% \begin{itemize}
@@ -1604,7 +1604,7 @@
% ``\verb=!~!foo='' in the output.
% To avoid this scenario we check if \verb=#1= has the character
% code of a space, if so we recurse otherwise we call \cs{@@sverb}
-% (which is the original definition of \cs{@sverb}.
+% (which is the original definition of \cs{@sverb}).
% \changes{v1.1u}{2020/04/22}{Drop spaces before \cs{verb} delimiter (gh/327)}
% \begin{macrocode}
\def\@sverb#1{\if\noexpand#1 \expandafter\@sverb\else\@@sverb{#1}\fi}
diff --git a/Master/texmf-dist/source/latex/base/ltoutenc.dtx b/Master/texmf-dist/source/latex/base/ltoutenc.dtx
index e7d48e4ba20..c18ff014464 100644
--- a/Master/texmf-dist/source/latex/base/ltoutenc.dtx
+++ b/Master/texmf-dist/source/latex/base/ltoutenc.dtx
@@ -44,7 +44,7 @@
%<*driver>
% \fi
\ProvidesFile{ltoutenc.dtx}
- [2022/05/27 v2.0z LaTeX Kernel (font encodings)]
+ [2024/02/08 v2.1a LaTeX Kernel (font encodings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltoutenc.dtx}
@@ -383,10 +383,10 @@
% other encodings, so there are some optimizations provided:
% \begin{quote}
% |\DeclareTextSymbolDefault{|^^A
-% \meta{command}|}|^^A
+% \meta{command}|}{|^^A
% \meta{encoding}|}|\\
% |\DeclareTextAccentDefault{|^^A
-% \meta{command}|}|^^A
+% \meta{command}|}{|^^A
% \meta{encoding}|}|
% \end{quote}
% are short for:
@@ -840,7 +840,7 @@
% interfere between accent and base character. Therefore we need to
% avoid that (they are some hidden inside \cs{maybe@load@fontshape}).
% As we don't have to load the fontshape in this case
-% (as that happened in the box above if necessary, we simply
+% (as that already happened in the box above, if necessary), we simply
% disable that part of the code temporarily.
% We also ignore \cs{ignorespaces} which has the same issue and may
% show up as part of \cs{normalfont} if that is used.
@@ -3659,10 +3659,10 @@
\let\encodingdefault\CurrentOption
% \end{macrocode}
% From 2020/02/02 release onward we only load the encoding files if
-% they haven't be loaded already. To check this we look if
-% \verb=\T@=\textit{encoding} is already defined. If not we load
+% they haven't be loaded already. To check this we look at whether
+% \verb=\T@=\textit{encoding} is already defined. If not, we load it later
% (indicated by setting the switch
-% \texttt{@tempswa} to true and we always load if we run in an older
+% \texttt{@tempswa} to true) and we always load if we are using an older
% format (or rather in a rollback situation).
% \changes{v2.0m}{2020/01/25}{Load each encoding file only once (gh/255)}
% \begin{macrocode}
@@ -3677,6 +3677,7 @@
\if@tempswa
% \end{macrocode}
%
+% \changes{v2.1a}{2023/11/07}{Add more explanation to error message (gh/1102)}
% \begin{macrocode}
\edef\reserved@f{%
\lowercase{\def\noexpand\reserved@f{\CurrentOption enc.def}}}%
@@ -3685,7 +3686,11 @@
{}{\PackageError{fontenc}%
{Encoding file `\reserved@f' not found.%
\MessageBreak
- You might have misspelt the name of the encoding}%
+ You might have misspelled the name of the encoding
+ \MessageBreak
+ or a required support package (e.g., cyrillic) is
+ \MessageBreak
+ missing in your installation}%
{Necessary code for this encoding was not
loaded.\MessageBreak
Thus calling the encoding later on will
@@ -3723,8 +3728,8 @@
% \end{macrocode}
%
% We select the new font encoding default (i.e., the last encoding
-% specified in the option list. But this encoding may not work with
-% the current |\f@shape|, e.g., \texttt{LY1} is not defined for
+% specified in the option list). But this encoding may not work with
+% the current |\f@shape|: e.g., \texttt{LY1} is not defined for
% \texttt{cmr} and therefore packages switching to \texttt{LY1}
% usually also change \cs{rmdefault}. But that only applies at
% |\begin{document}| so we get a spurious warning if we use what
diff --git a/Master/texmf-dist/source/latex/base/ltoutput.dtx b/Master/texmf-dist/source/latex/base/ltoutput.dtx
index b067ef5ecbd..f0c1bf830b3 100644
--- a/Master/texmf-dist/source/latex/base/ltoutput.dtx
+++ b/Master/texmf-dist/source/latex/base/ltoutput.dtx
@@ -37,7 +37,7 @@
%<*driver>
% \fi
\ProvidesFile{ltoutput.dtx}
- [2023/05/26 v1.4j LaTeX Kernel (Output Routine)]
+ [2024/03/16 v1.4j LaTeX Kernel (Output Routine)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltoutput.dtx}
@@ -847,7 +847,7 @@
% \begin{macro}{\if@firstcolumn}
% \begin{macro}{\if@twocolumn}
% \begin{macro}{\if@twoside}
-% \begin{macro}{\if@reversemarginpar}
+% \begin{macro}{\if@reversemargin}
% \begin{macro}{\if@mparswitch}
% \begin{macro}{\col@number}
% \changes{v1.0n}{1994/04/30}{Added \cs{col@number}}
diff --git a/Master/texmf-dist/source/latex/base/ltpara.dtx b/Master/texmf-dist/source/latex/base/ltpara.dtx
index f76352fb917..f102d68e0d6 100644
--- a/Master/texmf-dist/source/latex/base/ltpara.dtx
+++ b/Master/texmf-dist/source/latex/base/ltpara.dtx
@@ -14,21 +14,14 @@
%
%%% From File: ltpara.dtx
%
-% \begin{macrocode}
-\def\ltparaversion{v1.0l}
-\def\ltparadate{2023/01/30}
-% \end{macrocode}
%<*driver>
+% \fi
+\ProvidesFile{ltpara.dtx}
+ [2024/05/16 v1.0m LaTeX Kernel (paragraph hooks)]
+% \iffalse
+%
\documentclass{l3doc}
-
-%\usepackage{ltpara}
-
-% Fixing footnotes in functions and variables: this should be in l3doc!
-
-\newcommand\fixfootnote[2]{\footnotemark
- \AddToHookNext{env/#1/after}{\footnotetext{#2}}}
-\AddToHook{env/function/begin}{\def\footnote{\fixfootnote{function}}}
-\AddToHook{env/variable/begin}{\def\footnote{\fixfootnote{variable}}}
+\GetFileInfo{ltpara.dtx}
\EnableCrossrefs
\CodelineIndex
@@ -45,7 +38,7 @@
%
%
% \title{The \texttt{ltpara.dtx} code\thanks{This file has version
-% \ltparaversion\ dated \ltparadate, \copyright\ \LaTeX\
+% \fileversion\ dated \filedate, \copyright\ \LaTeX\
% Project.}}
% \author{Frank Mittelbach}
%
@@ -811,9 +804,11 @@
\hook_use:n {para/begin}
% \end{macrocode}
% If we aren't in horizontal mode any longer the hooks above misbehaved.
+% \changes{v1.0m}{2023/11/16}{Correct error message: hook
+% left horizontal not vertical mode (gh/1182)}
% \begin{macrocode}
\if_mode_horizontal: \else:
- \msg_error:nnnn { hooks }{ para-mode }{begin}{vertical} \fi:
+ \msg_error:nnnn { hooks }{ para-mode }{begin}{horizontal} \fi:
% \end{macrocode}
% Finally we reinsert the indentation box (unless suppressed) and
% then call \cs{everypar} the way legacy \LaTeX\ code expects it.
@@ -845,7 +840,7 @@
%<latexrelease> \@kernel@before@para@begin
%<latexrelease> \hook_use:n {para/begin}
%<latexrelease> \if_mode_horizontal: \else:
-%<latexrelease> \msg_error:nnnn { hooks }{ para-mode }{begin}{vertical} \fi:
+%<latexrelease> \msg_error:nnnn { hooks }{ para-mode }{begin}{horizontal} \fi:
%<latexrelease> \@@_handle_indent:
%<latexrelease>}
% \end{macrocode}
@@ -1261,7 +1256,7 @@
% redo the \cs{everypar} setting from the kernel, otherwise that
% gets lost (as it happens before that file is loaded).
% \begin{macrocode}
-\everypar{\@nodocument} %% To get an error if text appears before the
+\everypar{\@nodocument} %% To get an error if text appears before the \document
% \end{macrocode}
%
%
diff --git a/Master/texmf-dist/source/latex/base/ltplain.dtx b/Master/texmf-dist/source/latex/base/ltplain.dtx
index 37733735623..a628b954d97 100644
--- a/Master/texmf-dist/source/latex/base/ltplain.dtx
+++ b/Master/texmf-dist/source/latex/base/ltplain.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltplain.dtx}
- [2023/10/21 v2.3i LaTeX Kernel (Plain TeX)]
+ [2024/02/08 v2.3j LaTeX Kernel (Plain TeX)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltplain.dtx}
@@ -1241,11 +1241,11 @@
%<latexrelease>\IncludeInRelease{2022/06/01}{\obeylines}%
%<latexrelease> {Add a redirection to obeylines and obeyspaces}%
% \end{macrocode}
-% If the active |^^M| escapes, e.g. into a \cs{write} (which is
-% effectively in a different context) we don't want the definition
+% If the active |^^M| escapes, e.g., into a \cs{write} (which is
+% effectively in a different context) then we don't want the definition
% from \cs{obeylines} but rather a simple \cs{par} (in fact even
% the primitive one, not the \LaTeX{} version \cs{para\_end:} which
-% is only defined later.
+% is only defined later).
%
% \begin{macrocode}
\begingroup
@@ -1263,7 +1263,7 @@
% line ending characters and in that mode \TeX{} discards
% everything from that point onwards to the real end of the line so
% it works like a comment --- pretty strange really (and I think
-% due to the fact the the original pascal compiler could have some
+% due to the fact that the original pascal compiler could have some
% garbage showing up after the normal line ending character. Thus
% we really have to make sure that any closing braces is not one
% the same line as an |^^M|, because otherwise it would get dropped
@@ -1293,7 +1293,7 @@
% one that is current when \cs{obeylines} act.
%
% There is a small subtlety here: in an \cs{edef} the active |^^M| stayed
-% put (because it was equal to to the primitive \cs{par}), now
+% put (because it was equal to the primitive \cs{par}), now
% \cs{obeyedline} expands and you get what it contains, i.e., in that
% case \cs{par}, into the \cs{edef} or \cs{mark} unless we use
% \cs{protected} on it.
@@ -1813,7 +1813,13 @@
\tracinggroups\z@
\tracingparagraphs\z@
\tracingmacros\z@
- \tracinglostchars\@ne
+% \end{macrocode}
+% None really means go back to the \LaTeX{} ``default'' and for
+% \cs{tracinglostchars} this should therefore be 2 these days.
+% \changes{v2.3j}{2023/11/07}{Set \cs{tracinglostchars} to 2 in
+% \cs{tracingnone} (gh/549)}
+% \begin{macrocode}
+ \tracinglostchars\tw@
\tracingpages\z@
\tracingstats\z@
}%
diff --git a/Master/texmf-dist/source/latex/base/ltproperties.dtx b/Master/texmf-dist/source/latex/base/ltproperties.dtx
index 40c50cd20a2..0fd8f22e0ef 100644
--- a/Master/texmf-dist/source/latex/base/ltproperties.dtx
+++ b/Master/texmf-dist/source/latex/base/ltproperties.dtx
@@ -1,8 +1,8 @@
% \iffalse meta-comment
%
-%% File: ltproperties.dtx
+% File: ltproperties.dtx
%
-% Copyright (C) 2021-2023 The LaTeX Project
+% Copyright (C) 2023-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -21,13 +21,21 @@
% https://github.com/latex3/latex2e
%
% for those people who are interested.
-% \begin{macrocode}
-\def\ltpropertiesversion{1.0c}
-\def\ltpropertiesdate{2023-10-15}
-% \end{macrocode}
-
-%<*driver>
+%
+% \fi
+%
+% \iffalse
+%%% From File: ltproperties.dtx
+%
+%<*driver>
+% \fi
+\ProvidesFile{ltproperties.dtx}
+ [2024/04/17 v1.0e LaTeX Kernel (Properties)]
+% \iffalse
+%
\documentclass[full]{l3doc}
+\GetFileInfo{ltproperties.dtx}
+
\EnableCrossrefs
\CodelineIndex
\begin{document}
@@ -39,7 +47,7 @@
% \title{^^A
% Recording and cross-referencing document properties^^A
% \thanks{This module has version
-% \ltpropertiesversion\ dated \ltpropertiesdate, \copyright\ The \LaTeX\
+% \fileversion\ dated \filedate, \copyright\ The \LaTeX\
% Project.}
% }
%
@@ -157,8 +165,8 @@
%
% \begin{function}{\property_new:nnnn,\property_gset:nnnn}
% \begin{syntax}
-% \cs{property_new:nnnn} \Arg{property} \Arg{setpoint} \Arg{default} \Arg{code}
-% \cs{property_gset:nnnn} \Arg{property}\Arg{setpoint} \Arg{default} \Arg{code}
+% \cs{property_new:nnnn} \Arg{property} \Arg{setpoint} \Arg{default} \Arg{code}
+% \cs{property_gset:nnnn} \Arg{property} \Arg{setpoint} \Arg{default} \Arg{code}
% \end{syntax}
% \LaTeXe-interface: see \cs{NewProperty}, \cs{SetProperty}.\\
% Sets the \meta{property} to have the \meta{default} specified, and at the
@@ -180,7 +188,7 @@
% \property_record:nn, \property_record:nV, \property_record:ee
% }
% \begin{syntax}
-% \cs{property_record:nN} \Arg{label} \Arg{clist var}
+% \cs{property_record:nN} \Arg{label} \meta{clist var}
% \cs{property_record:nn} \Arg{label} \Arg{clist}
% \end{syntax}
% \LaTeXe{}-interface: see \cs{RecordProperties}.\\
@@ -266,7 +274,7 @@
% \cs{property_if_exist_p:n} \Arg{property}
% \cs{property_if_exist:nTF} \Arg{property} \Arg{true code} \Arg{false code}
% \end{syntax}
-% \LaTeXe{}-interface: \cs{IfPropertyExistTF}.\\
+% \LaTeXe{}-interface: \cs{IfPropertyExistsTF}.\\
% Tests if the \meta{property} has been declared.
% \end{function}
%
@@ -275,7 +283,7 @@
% \cs{property_if_recorded_p:n} \Arg{label}
% \cs{property_if_recorded:nTF} \Arg{label} \Arg{true code} \Arg{false code}
% \end{syntax}
-% \LaTeXe{}-interface: \cs{IfLabelExistTF}\\
+% \LaTeXe{}-interface: \cs{IfLabelExistsTF}\\
% Tests if the \meta{label} is known. This is also true if the label has been
% set with the standard \cs{label} command.
% \end{function}
@@ -307,8 +315,8 @@
%
% \begin{function}{\NewProperty,\SetProperty}
% \begin{syntax}
-% \cs{NewProperty} \Arg{property} \Arg{setpoint} \Arg{default} \Arg{code}
-% \cs{SetProperty} \Arg{property} \Arg{setpoint} \Arg{default} \Arg{code}
+% \cs{NewProperty} \Arg{property} \Arg{setpoint} \Arg{default} \Arg{code}
+% \cs{SetProperty} \Arg{property} \Arg{setpoint} \Arg{default} \Arg{code}
% \end{syntax}
% Sets the \meta{property} to have the \meta{default} specified, and at the
% \meta{setpoint} (either |now| or |shipout|) to write the result of the
@@ -329,7 +337,7 @@
% of properties. Also similar to the standard \cs{label} command, the command is surrounded
% by an \cs{@bsphack}/\cs{@esphack} pair to preserve spacing.
% \end{function}
-
+%
% \begin{function}[EXP]{\RefProperty}
% \begin{syntax}
% \cs{RefProperty} \oarg{local default} \Arg{label} \Arg{property}
@@ -340,16 +348,16 @@
% If \Arg{property} has not been declared an error is issued.
% \end{function}
%
-% \begin{function}{\IfPropertyExistTF}
+% \begin{function}{\IfPropertyExistsTF,\IfPropertyExistsT,\IfPropertyExistsF}
% \begin{syntax}
-% \cs{IfPropertyExistTF} \Arg{property} \Arg{true code} \Arg{false code}
+% \cs{IfPropertyExistsTF} \Arg{property} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the \meta{property} has been declared.
% \end{function}
%
-% \begin{function}{\IfLabelExistTF}
+% \begin{function}{\IfLabelExistsTF,\IfLabelExistsT,\IfLabelExistsF}
% \begin{syntax}
-% \cs{IfLabelExistTF} \Arg{label} \Arg{true code} \Arg{false code}
+% \cs{IfLabelExistsTF} \Arg{label} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the \meta{label} has been recorded. This is also true if a label
% has been set with the standard \cs{label} command.
@@ -361,7 +369,7 @@
% \end{syntax}
% Tests if the label and a value of the \meta{property} for the \meta{label} are both known.
% \end{function}
-
+%
% \begin{function}{\RefUndefinedWarn}
% \begin{syntax}
% \cs{RefUndefinedWarn} \Arg{label} \Arg{property}
@@ -551,6 +559,7 @@
% later too. That is all pretty easy using \pkg{expl3}: we accept a stray
% comma at the end of the list as that is easier to deal with than trying
% to tidy up, and there is no real downside.
+% \changes{v1.0d}{2024-01-17}{Use \cs{protected@write}}%
% \begin{macrocode}
\cs_new_protected:Npn \property_record:nN #1#2
{ \property_record:nV {#1} #2 }
@@ -561,7 +570,7 @@
{
\legacy_if:nT { @filesw }
{
- \iow_shipout_x:Nx \@auxout
+ \protected@write \@auxout {}
{
\token_to_str:N \new@label@record
{#1}
@@ -737,9 +746,13 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{IfPropertyExistTF}
+% \begin{macro}{\IfPropertyExistsTF,\IfPropertyExistsT,\IfPropertyExistsF}
+% \changes{v1.0e}{2024-04-17}{Renamed \cs{IfPropertyExistTF} to
+% \cs{IfPropertyExistsTF} (gh/1262)}
% \begin{macrocode}
-\cs_new_eq:NN \IfPropertyExistTF \property_if_exist:eTF
+\cs_new_eq:NN \IfPropertyExistsTF \property_if_exist:eTF
+\cs_new:Npn \IfPropertyExistsT #1#2 {\property_if_exist:eTF {#1}{#2}{} }
+\cs_new:Npn \IfPropertyExistsF #1 {\property_if_exist:eTF {#1}{} }
% \end{macrocode}
% \end{macro}
%
@@ -762,9 +775,13 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\IfLabelExistTF}
+% \begin{macro}{\IfLabelExistsTF,\IfLabelExistsT,\IfLabelExistsF}
+% \changes{v1.0e}{2024-04-17}{Renamed \cs{IfLabelExistTF} to
+% \cs{IfLabelExistsTF} (gh/1262)}
% \begin{macrocode}
-\cs_new_eq:NN \IfLabelExistTF \property_if_recorded:eTF
+\cs_new_eq:NN \IfLabelExistsTF \property_if_recorded:eTF
+\cs_new:Npn \IfLabelExistsT #1#2 {\property_if_exist:eTF {#1}{#2}{} }
+\cs_new:Npn \IfLabelExistsF #1 {\property_if_exist:eTF {#1}{} }
% \end{macrocode}
% \end{macro}
%
@@ -938,8 +955,8 @@
%<latexrelease>\let \RefProperty \@undefined
%<latexrelease>\let \RefUndefinedWarn \@undefined
%<latexrelease>
-%<latexrelease>\let \IfPropertyExistTF \@undefined
-%<latexrelease>\let \IfLabelExistTF \@undefined
+%<latexrelease>\let \IfPropertyExistsTF \@undefined
+%<latexrelease>\let \IfLabelExistsTF \@undefined
%<latexrelease>\let \IfPropertyRecordedTF \@undefined
%<latexrelease>
%<latexrelease>\let\new@label@record \@undefined
diff --git a/Master/texmf-dist/source/latex/base/ltsect.dtx b/Master/texmf-dist/source/latex/base/ltsect.dtx
index 4560704463a..21aeda32e02 100644
--- a/Master/texmf-dist/source/latex/base/ltsect.dtx
+++ b/Master/texmf-dist/source/latex/base/ltsect.dtx
@@ -31,7 +31,7 @@
%%% From File: ltsect.dtx
%<*driver>
% \fi
-\ProvidesFile{ltsect.dtx}[2021/07/28 v1.1f LaTeX Kernel (Sectioning)]
+\ProvidesFile{ltsect.dtx}[2024/03/25 v1.1f LaTeX Kernel (Sectioning)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltsect.dtx}
@@ -835,13 +835,13 @@
% \begin{macro}{\contentsline}
% The |\contentsline{|\meta{type}|}{|\meta{entry}|}{|\meta{page}|}{}|
% macro produces a \meta{type} entry in a table of contents, etc.
-% It will appear in the |.toc| or other file. For example,
-% The entry for subsection 1.4.3 in the table of contents for
-% example, might be produced by:
+% It will appear in the |.toc| or other file.
+% For example, the entry for subsection 1.4.3 in the table of contents,
+% might be produced by:
%
% \begin{verbatim}
% \contentsline{subsection}
-% {\makebox{30pt}[r]{1.4.3} Gnats and Gnus}{22}
+% {\numberline{1.4.3}Gnats and Gnus}{22}{}
% \end{verbatim}
%
% The |\protect| command causes command sequences to be written
diff --git a/Master/texmf-dist/source/latex/base/ltshipout.dtx b/Master/texmf-dist/source/latex/base/ltshipout.dtx
index aaeba15ea70..0c9113ce938 100644
--- a/Master/texmf-dist/source/latex/base/ltshipout.dtx
+++ b/Master/texmf-dist/source/latex/base/ltshipout.dtx
@@ -31,30 +31,14 @@
%
%%% From File: ltshipout.dtx
%
-% \begin{macrocode}
-\providecommand\ltshipoutversion{v1.0n}
-\providecommand\ltshipoutdate{2022/11/08}
-% \end{macrocode}
-%
%<*driver>
-
+% \fi
+\ProvidesFile{ltshipout.dtx}
+ [2024/02/11 v1.0n LaTeX Kernel (Shipout)]
+% \iffalse
+%
\documentclass{l3doc}
-
-% bug fix fo l3doc.cls
-\ExplSyntaxOn
-\cs_set_protected:Npn \__codedoc_macro_typeset_one:nN #1#2
- {
- \vbox_set:Nn \l__codedoc_macro_box
- {
- \vbox_unpack_drop:N \l__codedoc_macro_box
- \hbox { \llap { \__codedoc_print_macroname:nN {#1} #2
- \MacroFont % <----- without it the \ is in lmr10 if a link is made
- \
- } }
- }
- \int_incr:N \l__codedoc_macro_int
- }
-\ExplSyntaxOff
+\GetFileInfo{ltshipout.dtx}
\providecommand\InternalDetectionOff{}
\providecommand\InternalDetectionOn{}
@@ -76,7 +60,7 @@
%
%
% \title{The \texttt{ltshipout} documentation\thanks{This file has version
-% \ltshipoutversion\ dated \ltshipoutdate, \copyright\ \LaTeX\
+% \fileversion\ dated \filedate, \copyright\ \LaTeX\
% Project.}}
%
% \author{Frank Mittelbach, \LaTeX{} Project Team}
@@ -859,7 +843,7 @@
%
% \changes{v1.0d}{2020/11/23}{Check for both kernel and user hook (gh/431)}
% \changes{v1.0f}{2021/01/08}{Added another kernel hook for more
-% flexibility (cf \texttt{https://github.com/pgf-tikz/pgf/issues/960}}
+% flexibility (cf.\ \texttt{https://github.com/pgf-tikz/pgf/issues/960}}
% \begin{macrocode}
\bool_lazy_and:nnF
{ \hook_if_empty_p:n {shipout/background} }
diff --git a/Master/texmf-dist/source/latex/base/ltsockets.dtx b/Master/texmf-dist/source/latex/base/ltsockets.dtx
index 909792a4f54..243963f7bcc 100644
--- a/Master/texmf-dist/source/latex/base/ltsockets.dtx
+++ b/Master/texmf-dist/source/latex/base/ltsockets.dtx
@@ -30,14 +30,14 @@
%
%%% From File: ltsockets.dtx
%
-% \begin{macrocode}
-\def\ltsocketsversion{0.9a}
-\def\ltsocketsdate{2023-08-21}
-% \end{macrocode}
+%<*driver>
+% \fi
+\ProvidesFile{ltsockets.dtx}
+ [2024/02/11 v0.9a LaTeX Kernel (Sockets)]
+% \iffalse
%
-%<*driver>
\documentclass{l3doc}
-
+\GetFileInfo{ltsockets.dtx}
\providecommand\InternalDetectionOff{}
\providecommand\InternalDetectionOn{}
@@ -55,7 +55,7 @@
%
%
% \title{\LaTeX{}'s socket management\thanks{This module has version
-% \ltsocketsversion\ dated \ltsocketsdate, \copyright\ \LaTeX\
+% \fileversion\ dated \filedate, \copyright\ \LaTeX\
% Project.}}
%
% \author{Frank Mittelbach}
@@ -530,8 +530,8 @@
%
% \begin{function}{\NewSocket,\socket_new:nn}
% \begin{syntax}
-% \cs{NewSocket} \Arg{socket-name}\Arg{number-of-inputs}
-% \cs{socket_new:nn}\Arg{socket-name}\Arg{number-of-inputs}
+% \cs{NewSocket} \Arg{socket-name} \Arg{number-of-inputs}
+% \cs{socket_new:nn} \Arg{socket-name} \Arg{number-of-inputs}
% \end{syntax}
% Declares a new socket with name \meta{socket-name} having
% \meta{number-of-inputs} inputs. There is automatically a
@@ -563,9 +563,9 @@
%
% \begin{function}{\NewSocketPlug,\socket_new_plug:nnn,\socket_set_plug:nnn}
% \begin{syntax}
-% \cs{NewSocketPlug} \Arg{socket-name}\Arg{socket-plug-name}\Arg{code}
-% \cs{socket_new_plug:nnn}\Arg{socket-name}\Arg{socket-plug-name}\Arg{code}
-% \cs{socket_set_plug:nnn}\Arg{socket-name}\Arg{socket-plug-name}\Arg{code}
+% \cs{NewSocketPlug} \Arg{socket-name} \Arg{socket-plug-name} \Arg{code}
+% \cs{socket_new_plug:nnn} \Arg{socket-name} \Arg{socket-plug-name} \Arg{code}
+% \cs{socket_set_plug:nnn} \Arg{socket-name} \Arg{socket-plug-name} \Arg{code}
% \end{syntax}
% Declares a new plug for socket \meta{socket-name} that runs
% \meta{code} when executing. It complains if the plug was already
@@ -582,8 +582,8 @@
%
% \begin{function}{\AssignSocketPlug,\socket_assign_plug:nn}
% \begin{syntax}
-% \cs{AssignSocketPlug} \Arg{socket-name}\Arg{socket-plug-name}
-% \cs{socket_assign_plug:nn}\Arg{socket-name}\Arg{socket-plug-name}
+% \cs{AssignSocketPlug} \Arg{socket-name} \Arg{socket-plug-name}
+% \cs{socket_assign_plug:nn} \Arg{socket-name} \Arg{socket-plug-name}
% \end{syntax}
% Assigns the plug \meta{socket-plug-name} to the socket
% \meta{socket-name}. It errors if either socket or plug is not
@@ -595,8 +595,8 @@
%
% \begin{function}{\UseSocket,\socket_use:nw,\socket_use:n,\socket_use:nn,\socket_use:nnn,\socket_use:nnnn}
% \begin{syntax}
-% \cs{UseSocket} \Arg{socket-name}
-% \cs{socket_use:nnn}\Arg{socket-name} \Arg{socket-arg\textsubscript{1}} \Arg{socket-arg\textsubscript{2}}
+% \cs{UseSocket} \Arg{socket-name}
+% \cs{socket_use:nnn} \Arg{socket-name} \Arg{socket-arg\textsubscript{1}} \Arg{socket-arg\textsubscript{2}}
% \end{syntax}
% Executes the socket \meta{socket-name} by retrieving the
% \meta{code} of the current plug assigned to the socket. This is
@@ -619,8 +619,8 @@
%
% \begin{function}{\ShowSocket,\LogSocket,\socket_show:n,\socket_log:n}
% \begin{syntax}
-% \cs{ShowSocket} \Arg{socket-name}
-% \cs{socket_show:n}\Arg{socket-name}
+% \cs{ShowSocket} \Arg{socket-name}
+% \cs{socket_show:n} \Arg{socket-name}
% \end{syntax}
% Displays information about the socket \meta{socket-name} and its
% state then stops and waits for further instructions --- at the
diff --git a/Master/texmf-dist/source/latex/base/ltspace.dtx b/Master/texmf-dist/source/latex/base/ltspace.dtx
index 73941d48156..206e4f38858 100644
--- a/Master/texmf-dist/source/latex/base/ltspace.dtx
+++ b/Master/texmf-dist/source/latex/base/ltspace.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltspace.dtx}
- [2023/10/26 v1.3r LaTeX Kernel (spacing)]
+ [2024/02/08 v1.3r LaTeX Kernel (spacing)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltspace.dtx}
@@ -568,7 +568,7 @@
% \changes{LaTeX2e}{1993/12/08}
% {Command reimplemented; late birthday present for Chris}
% \changes{LaTeX2e}{1993/12/08}{Command reimplemented}
-% \changes{LaTeX2e}{1993/12/16}{Corrected optimisation :-)}
+% \changes{LaTeX2e}{1993/12/16}{Corrected optimisation}
% |\@bsphack| and |\@esphack|
% used by macros such as |\index| and
% |\begin{@float}| \ldots |\end{@float}|
@@ -1156,8 +1156,8 @@
% \subsection{Horizontal space (and breaks)}
%
% \begin{macro}{\nobreakdashes}
-% \changes{v1.3}{2004/02/04}{(Macro added}
-% \changes{v1.3a}{2004/02/15}{(Added spacefactor setting}
+% \changes{v1.3}{2004/02/04}{Macro added}
+% \changes{v1.3a}{2004/02/15}{Added spacefactor setting}
% This idea is borrowed from the \textsf{amsmath} package but
% here we define a robust command.
%
@@ -1194,7 +1194,7 @@
% \end{macro}
%
% \begin{macro}{\nobreakspace}
-% \changes{v1.2k}{1995/12/04}{(Macro added}
+% \changes{v1.2k}{1995/12/04}{Macro added}
% \changes{v1.3r}{2023/10/26}{Protected definition for tilde}
% \begin{macro}{\@xobeysp}
% \changes{v1.2t}{1996/09/28}{Moved from ltmiscen.dtx and redefined to
@@ -1209,7 +1209,7 @@
%
% The braces in the definition of |~| are needed to ensure that a
% following space is preserved when reading to/from internal files.
-% \changes{v1.2l}{1995/12/04}{(braces added to definition of tilde}
+% \changes{v1.2l}{1995/12/04}{braces added to definition of tilde}
%
% We need to keep \cs{@xobeysp} as it is widely used; so here it is
% let to the non-robust command \cs{nobreakspace }.
diff --git a/Master/texmf-dist/source/latex/base/lttagging.dtx b/Master/texmf-dist/source/latex/base/lttagging.dtx
new file mode 100644
index 00000000000..585479df214
--- /dev/null
+++ b/Master/texmf-dist/source/latex/base/lttagging.dtx
@@ -0,0 +1,775 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2023-2024
+% The LaTeX Project and any individual authors listed elsewhere
+% in this file.
+%
+% This file is part of the LaTeX base system.
+% -------------------------------------------
+%
+% It may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% https://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008 or later.
+%
+% This file has the LPPL maintenance status "maintained".
+%
+% The list of all files belonging to the LaTeX base distribution is
+% given in the file `manifest.txt'. See also `legal.txt' for additional
+% information.
+%
+% The list of derived (unpacked) files belonging to the distribution
+% and covered by LPPL is defined by the unpacking scripts (with
+% extension .ins) which are part of the distribution.
+%
+% \fi
+%
+% \iffalse
+%%% From File: lttagging.dtx
+%
+%<*driver>
+% \fi
+\ProvidesFile{lttagging.dtx}
+ [2023/12/19 v1.0a LaTeX Kernel (tagging support)]
+% \iffalse
+\documentclass{l3doc}
+\GetFileInfo{lttagging.dtx}
+\title{\filename}
+\date{\filedate}
+\author{\LaTeX{} project}
+
+\begin{document}
+% \MaintainedByLaTeXTeam{latex} % should be added again the moment
+ % it is supported by l3doc
+ \maketitle
+ \DocInput{\filename}
+\end{document}
+%</driver>
+% \fi
+%
+% \providecommand\env[1]{\texttt{#1}}
+%
+% \providecommand\hook[1]{\texttt{#1\DescribeHook[noprint]{#1}}}
+% \providecommand\socket[1]{\texttt{#1\DescribeSocket[noprint]{#1}}}
+% \providecommand\plug[1]{\texttt{#1\DescribePlug[noprint]{#1}}}
+%
+% \let\ProvideDocElement\NewDocElement
+%
+% \ProvideDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+% \ProvideDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl}
+% \ProvideDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
+%
+%
+% \section{}
+%
+%
+%
+% \MaybeStop{}
+%
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+% \end{macrocode}
+%
+%
+% \section{General support for tagged output}
+%
+% \DescribeMacro\SuspendTagging
+% \DescribeMacro\ResumeTagging
+%
+% The are places in code where it is import top stop any tagging
+% activities, e.g., when we are doing trial typesetting that it is
+% done several times. In such a case one must tag only the final
+% version that is actually used, otherwise tagging structures are
+% allowed which then do not end up in the PDF and confuse the
+% mechanism. For this we have two commands that can be used in
+% packages: \cs{SuspendTagging} and \cs{ResumeTagging}. They are
+% available as part of the \LaTeX{} kernel, so that they can be
+% safely used in packages whether or not tagging is requested .They
+% both take string argument that is used for debugging to easily
+% identify why tagging was suspended or restarted, for example, in
+% \pkg{tabularx} you find \verb=\SuspendTagging{tabularx}=. By default
+% they two commands do nothing.
+%
+% TODO: the corresponding L3 layer commands should also have a dummy
+% definition in the kernel!
+%
+% \DescribeMacro\UseTaggingSocket
+% \DescribeMacro\tag_socket_use:n
+% \DescribeMacro\tag_socket_use:nn
+% To support tagging in packages we use sockets with names starting
+% with \texttt{tagsupport/}. Usually, these sockets have exactly two
+% plugs defined:
+% \plug{noop} (when no tagging is requested or tagging is not wanted
+% for some reason) and a second plug that enables the tagging. There
+% may be more, e.g., tagging with special debugging, etc., but right
+% now it is usually just on or off.
+%
+% Given that we sometimes have to suspend tagging, it would be fairly
+% inefficient to put different plugs into these sockets whenever that
+% happens. We therefore offer \cs{UseTaggingSocket} which is like
+% \cs{UseSocket} except that the socket name is specified without
+% \texttt{tagsupport/}, i.e.,
+% \begin{quote}
+% \verb=\UseTaggingSocket{foo}= $\to$
+% \verb=\UseSocket{tagsupport/foo}=
+% \end{quote}
+% Beside being slightly shorter, the big advantage is that this way
+% we can change \cs{UseTaggingSocket} to do nothing when tagging is
+% suspended with \cs{SuspendTagging} instead of changing the plugs of
+% the tagging support sockets back and forth.
+%
+% It is possible to use the tagging support sockets with
+% \cs{UseSocket} directly, but in this case the socket remains active
+% if \cs{SuspendTagging} is in force. There my be reasons for doing
+% that but in general we expect to always use \cs{UseTaggingSocket}.
+%
+% The L3 programming layer versions \cs{tag_socket_use:n} and
+% \cs{tag_socket_use:nn} are slightly more efficient than
+% \cs{UseTaggingSocket} because they do not have to determine how
+% many arguments the socket takes when disabling it, so in code that
+% is using the L3 programming layer we recommend to use them instead
+% of the CamelCase command.
+%
+%
+%
+% \begin{macro}{\SuspendTagging,\ResumeTagging}
+%
+% In the kernel, these two commands get dummy definitions so that
+% they can be used without harm in packages. The real definition is
+% used when tagging gets enabled.
+% \begin{macrocode}
+\cs_new_eq:NN \SuspendTagging \use_none:n
+\cs_new_eq:NN \ResumeTagging \use_none:n
+% \end{macrocode}
+%
+% A simplified version of this defnition should move to
+% \pkg{tagpdf} and dropped here, eventually.
+% \begin{macrocode}
+\AddToHook{begindocument/before}{
+ \cs_if_exist:NT \tag_stop:n
+ {
+ \cs_set:Npn \SuspendTagging #1 {
+% \end{macrocode}%
+% This stops tagging and also disables all tagging sockets so we are done.
+% \begin{macrocode}
+ \tag_stop:n {#1}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \cs_set:Npn \ResumeTagging #1 { \tag_start:n {#1} }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tag_socket_use:n,
+% \tag_socket_use:nn,
+% \UseTaggingSocket,
+% }
+% Again this is not the final definition for the kernel; it is just
+% a version to get going while some parts of the kernel support are
+% still missing.
+% \begin{macrocode}
+\AddToHook{begindocument}[kernel]{
+ \cs_if_exist:NF \tag_if_active:T
+ {
+ \prg_new_conditional:Npnn \tag_if_active: { p , T , TF, F }
+ { \prg_return_false: }
+ }
+}
+% \end{macrocode}
+%
+% Dummy definitions in the kernel.
+% These definitions will get updated in \pkg{tagpdf}.
+% \begin{macrocode}
+\cs_new_protected:Npn \tag_socket_use:n #1 { }
+\cs_new_protected:Npn \tag_socket_use:nn #1#2 { }
+% \end{macrocode}
+% The default in the kernel is just to get rid of the argument:
+% \begin{macrocode}
+\cs_new_protected:Npn \UseTaggingSocket #1 {
+ \int_case:nnF
+ { \int_use:c { c__socket_tagsupport/#1_args_int } }
+ {
+ 0 \prg_do_nothing:
+ 1 \use_none:n
+ 2 \use_none:nn
+% \end{macrocode}
+% We do not expect tagging sockets with more than one or two
+% arguments, so for now we only provide those.
+% \begin{macrocode}
+ }
+ \ERRORusetaggingsocket % that should get a proper error message
+}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \end{macro}
+%
+%
+%
+%
+%
+%
+% \subsection{Tagging support for table/tabular packages}
+%
+% The code uses a number of sockets to inject the tagging
+% commands. These can be easily set to a noop-plug in case the
+% automated tagging is not wanted.
+%
+% \begin{socketdecl}{tagsupport/tbl/cell/begin,
+% tagsupport/tbl/cell/end,
+% tagsupport/tbl/pcell/end,
+% tagsupport/tbl/pcell/end,
+% tagsupport/tbl/row/begin,
+% tagsupport/tbl/row/end,
+% }
+% At first sockets for the begin and end of cells and table rows:
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/cell/begin}{0}
+\NewSocket{tagsupport/tbl/cell/end}{0}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/row/begin}{0}
+\NewSocket{tagsupport/tbl/row/end}{0}
+% \end{macrocode}
+% Multi-line cells have their own sockets (as they start out in
+% vertical mode and need different treatment).
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/pcell/begin}{0}
+\NewSocket{tagsupport/tbl/pcell/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{socketdecl}{tagsupport/tbl/init}
+% This socket should be at the begin of the table, inside a group.
+% It is used for settings such as disabling para-tagging inside the
+% table. This socket
+% can perhaps be merged later into the begin-sockets.
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/init}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+%
+% \begin{socketdecl}{tagsupport/tbl/finalize}
+% To fine tune the structure (change cells to header cells, remove
+% unwanted structures, move a foot to the end, etc.). We also need a
+% socket that is executed at the end of the table but \emph{before}
+% all the variables are restored to the outer or default values.
+% The code in the socket can make assignments, but probably
+% shouldn't do typesetting and not write whatsits.
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/finalize}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+
+
+% \begin{socketdecl}{tagsupport/tbl/colspan}
+% This socket is used to manage spanning cells, e.g., a
+% \cs{multicolumn}. It expects one argument (the number of cells
+% spanned) and if tagging is enabled set appropriate tag attributes
+% in the background. We probably need a similar socket for row
+% spans eventually.
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/colspan}{1}
+% \end{macrocode}
+% \end{socketdecl}
+%
+
+
+% \begin{socketdecl}{tagsupport/tbl/hmode/begin,
+% tagsupport/tbl/hmode/end,
+% tagsupport/tbl/vmode/begin,
+% tagsupport/tbl/vmode/end
+% }
+%
+% These sockets are used in the begin and end code of environments,
+% to allow a fast enabling and disabling of the tagging. We
+% distinguish between tables that can be used inside paragraphs and
+% standalone tables such as \env{longtable} that are always in
+% vertical mode.
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/hmode/begin}{0}
+\NewSocket{tagsupport/tbl/hmode/end}{0}
+\NewSocket{tagsupport/tbl/vmode/begin}{0}
+\NewSocket{tagsupport/tbl/vmode/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+%
+%
+% \begin{socketdecl}{tagsupport/tbl/longtable/init,
+% tagsupport/tbl/longtable/finalize}
+% \env{longtable} needs its own sockets to fine tune the structure.
+% Simply switching the plug in the previous socket interferes with
+% enabling/disabling the tagging.
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/longtable/init}{0}
+\NewSocket{tagsupport/tbl/longtable/finalize}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{socketdecl}{tagsupport/tbl/longtable/head,
+% tagsupport/tbl/longtable/foot}
+% Header and footer boxes need special handling because they are repeatedly
+% used.
+% \begin{macrocode}
+\NewSocket{tagsupport/tbl/longtable/head}{0}
+\NewSocket{tagsupport/tbl/longtable/foot}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+%
+%
+%
+%
+% \section{For lttab.dtx parked here for now}
+%
+%
+% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
+% \end{macrocode}
+%
+%
+% \subsection{Variables for row, column and span counting}
+%
+% This part needs a decision on names for various integer registers
+% as well as a decision if those should be also made available for
+% \LaTeXe{}-style packages in form of 2e names and or as
+% non-internals for the L3 programming layer.
+%
+% At the moment they are all internal but this probably has to change.
+%
+% \begin{macro}{
+% \g_@@_col_int,
+% \g_@@_row_int,
+% \g_@@_span_tl,
+% \g_@@_table_cols_tl}
+%
+% \cs{g_@@_row_int} holds the current row number in the table. The
+% value \texttt{0} means we haven't yet processed the table
+% preamble (or in case of longtable are just in front of the next
+% chunk to be processed). It is incremented by every \cs{cr}
+% including the one ending the table preamble.
+%
+% TODO: due to the gymnastics needed inside the longtable code the
+% row counter is directly exposed there rather than hidden by
+% interfaces. This needs changing when it is decided how to manage
+% these counters.
+%
+% \cs{g_@@_col_int} holds the current column number. The value
+% \texttt{0} means we have not yet started the table or just finished a table row
+% (with \verb=\\= typically); any other positive value means we
+% are currently typesetting a cell in that column in some row
+% (denoted by the \cs{g_@@_row_int}).
+%
+% In a \cs{multicolumn} it holds the column number of the first
+% spanned column and \cs{g_@@_span_tl} the info how many cells are
+% spanned.
+%
+% \cs{g_@@_span_tl} is normally \texttt{1} except in a
+% \cs{multicolumn} cell.
+% \begin{macrocode}
+\int_new:N \g_@@_col_int
+\int_new:N \g_@@_row_int
+\tl_new:N \g_@@_span_tl
+\tl_new:N \g_@@_table_cols_tl
+
+\tl_gset:Nn \g_@@_span_tl {1}
+\tl_gset:Nn \g_@@_table_cols_tl {0} % indicates outer level
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\l_@@_saved_col_tl,\l_@@_saved_row_tl,
+% \l_@@_saved_span_tl,\l_@@_saved_table_cols_tl}
+%
+% Saving the outer values if we are nesting tables is necessary (as
+% the above variables are globally altered). For this we always use
+% token lists because they don't change and we do not need to blow
+% additional integer registers.
+% \begin{macrocode}
+\tl_new:N \l_@@_saved_col_tl
+\tl_new:N \l_@@_saved_row_tl
+\tl_new:N \l_@@_saved_span_tl
+\tl_new:N \l_@@_saved_table_cols_tl
+
+\tl_set:Nn \l_@@_saved_col_tl{0}
+\tl_set:Nn \l_@@_saved_row_tl{0}
+\tl_set:Nn \l_@@_saved_span_tl{1}
+\tl_set:Nn \l_@@_saved_table_cols_tl{0} % indicates outer level
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_missingcells_int}
+% This will contain the number of missing cells in a row:
+% \begin{macrocode}
+\int_new:N \g_@@_missing_cells_int
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+% \subsection{Tracing/debugging}
+%
+% \begin{macro}{\DebugTablesOn,\DebugTablesOff}
+%
+% \begin{macrocode}
+\def\DebugTablesOn{
+ \cs_set_eq:NN \@@_trace:n \typeout
+}
+\def\DebugTablesOff{
+ \cs_set_eq:NN \@@_trace:n \use_none:n
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@@_trace:n \use_none:n
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{Interface commands}
+%
+% All interface commands for the cell number determination have to be
+% public on some level because they are needed in other packages as
+% well, e.g., longtable. We may or may not also want to provide 2e
+% style names for them.
+%
+% \begin{macro}{\tbl_update_cell_data:}
+% Updating cell data in columns after the first means we have to
+% increment the \cs{g_@@_col_int} by the span count of the previous
+% cell (in case it was a \cs{multicolumn}) and then reset the
+% \cs{g_@@_span_tl} to one (as the default).
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_update_cell_data: {
+ \int_gadd:Nn \g_@@_col_int { \g_@@_span_tl }
+ \tl_gset:Nn \g_@@_span_tl {1}
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\tbl_count_table_cols:}
+% Current implementation of \cs{@mkpream} uses the scratch counter
+% \cs{count@} to keep track of the number of toks registers it needs
+% (2 per column), but this can't be used as it counts also
+% insertions made with \verb+!{}+ and \verb+@{}+.
+% So similar as does longtable for \cs{LT@cols} we count the
+% numbers of ampersands instead.
+% \begin{macrocode}
+\cs_new:Npn \tbl_count_table_cols: {
+ \seq_set_split:NnV\l_@@_tmpa_seq {&}\@preamble
+ \tl_gset:Ne \g_@@_table_cols_tl { \seq_count:N \l_@@_tmpa_seq }
+ \@@_trace:n { ==>~ Table~ has~ \g_@@_table_cols_tl \space columns }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\l_@@_tmpa_seq}
+%
+% \begin{macrocode}
+\seq_new:N \l_@@_tmpa_seq
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\tbl_count_missing_cells:n}
+%
+% We might have the situation that some table package has not
+% implemented the \cs{tbl_count_table_cols:} in which case
+% \cs{g_@@_table_cols_tl} would always be zero and we would get an
+% error below when we try to determine the missing cells, so bypass
+% that calculation if we aren't doing tagging (there the packages
+% should have the proper code added). Recall that this is code,
+% that is called by \verb=\\= and an old table packagee might rely
+% on whatever the \LaTeX{} kernel offers here.
+% \begin{macrocode}
+\cs_new:Npn \tbl_count_missing_cells:n #1 {
+ \tag_if_active:T {
+ \int_compare:nNnT \g_@@_col_int > 0
+ {
+ \int_gset:Nn \g_@@_missing_cells_int
+ {
+ \g_@@_table_cols_tl
+ - \g_@@_col_int
+ - \g_@@_span_tl
+ + 1
+ }
+ \int_compare:nNnT \g_@@_missing_cells_int < 0 \ERRORmissingcells % should not happen
+ \@@_trace:n{==>~
+ (#1)~
+ This~ row~ needs~
+ \int_use:N \g_@@_missing_cells_int \space
+ additional~ cell(s)
+ }
+ }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\tbl_save_outer_table_cols:}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_save_outer_table_cols: {
+ \tl_set_eq:NN \l_@@_saved_table_cols_tl \g_@@_table_cols_tl
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\tbl_init_cell_data_for_table:}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_init_cell_data_for_table: {
+ \tl_set:No \l_@@_saved_col_tl {\int_use:N \g_@@_col_int }
+ \tl_set:No \l_@@_saved_row_tl {\int_use:N \g_@@_row_int }
+ \tl_set_eq:NN \l_@@_saved_span_tl \g_@@_span_tl
+%
+ \@@_trace:n { ==>~ saved~cell~data:~
+ \l_@@_saved_row_tl,
+ \l_@@_saved_col_tl,
+ \l_@@_saved_span_tl \space
+ (
+ \int_compare:nNnTF \l_@@_saved_table_cols_tl = 0
+ { outer~ level }
+ { max:~ \l_@@_saved_table_cols_tl }
+ )
+ }
+% \end{macrocode}
+% These are the initial values when starting a table:
+% \begin{macrocode}
+ \int_gzero:N \g_@@_row_int
+ \int_gzero:N \g_@@_col_int
+ \tl_gset:Nn \g_@@_span_tl {1}
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\tbl_update_cell_data_for_next_row:}
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_update_cell_data_for_next_row: {
+ \int_gincr:N \g_@@_row_int % this row about to start
+ \int_gzero:N \g_@@_col_int % we are before first col
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\tbl_init_cell_data_for_row:}
+% If we start processing a cell in the first column we set
+% \cs{g_@@_col_int} to \texttt{1} as we are no longer "at" but "in"
+% the first column. We also set \cs{g_@@_span_tl} to its default
+% value (not spanning cells).
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_init_cell_data_for_row: {
+ \int_gset:Nn \g_@@_col_int {1}
+ \tl_gset:Nn \g_@@_span_tl {1}
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\tbl_if_row_was_started:T,
+% \tbl_if_row_was_started:TF}
+% We use \cs{g_@@_col_int} equal zero to indicate that we are just
+% after a TR (i.e.n between rows or at the very beginning of the
+% table). Using the row
+% count is not so good as longtable may split the table in chunks.
+%
+% These conditionals have to be expandable (i.e., unprotected) as
+% they are sometimes executed when \TeX{} is scanning inside a table.
+% \begin{macrocode}
+\cs_new:Npn \tbl_if_row_was_started:T {
+ \int_compare:nNnT \g_@@_col_int > 0
+}
+\cs_new:Npn \tbl_if_row_was_started:TF {
+ \int_compare:nNnTF \g_@@_col_int > 0
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\tbl_gzero_row_count:,\tbl_gincr_row_count:,\tbl_gdecr_row_count:}
+% This here is basically a temporary interface. What it will be in
+% the end depends on what we decide concerning exposing row and
+% column counters, if they stay internal we need something like
+% this here (perhaps using \texttt{gincr} etc, or perhaps some
+% other names in the first place).
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_gzero_row_count: {
+ \int_gzero:N \g_@@_row_int
+}
+\cs_new_protected:Npn \tbl_gincr_row_count: {
+ \int_gincr:N \g_@@_row_int
+}
+\cs_new_protected:Npn \tbl_gdecr_row_count: {
+ \int_gdecr:N \g_@@_row_int
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\tbl_inbetween_rows:}
+% Again name is not really brilliant so far.
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_inbetween_rows: {
+ \int_gzero:N \g_@@_col_int
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+%
+% \begin{macro}{\tbl_restore_outer_cell_data:}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_restore_outer_cell_data: {
+ \int_gset:Nn \g_@@_col_int { \l_@@_saved_col_tl }
+ \int_gset:Nn \g_@@_row_int { \l_@@_saved_row_tl }
+ \tl_gset_eq:NN \g_@@_span_tl \l_@@_saved_span_tl
+ \tl_gset_eq:NN \g_@@_table_cols_tl \l_@@_saved_table_cols_tl
+ \@@_trace:n { ==>~ restored~cell~data:~
+ \int_use:N \g_@@_row_int,
+ \int_use:N \g_@@_col_int,
+ \l_@@_saved_span_tl \space
+ (
+ \int_compare:nNnTF \g_@@_table_cols_tl = 0
+ { outer~ level }
+ { max:~ \g_@@_table_cols_tl }
+ )
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\tbl_update_multicolumn_cell_data:n}
+% This macro updates \cs{g_@@_col_int} and \cs{g_@@_span_tl} inside
+% a \cs{multicolumn} and possibly calls the tagging socket
+% \texttt{tbl/row/begin}.
+% \begin{macrocode}
+\cs_new_protected:Npn \tbl_update_multicolumn_cell_data:n #1 {
+% \end{macrocode}
+% We execute socket for tagging only if this \cs{multicolumn}
+% replaces the preamble of the first column. In that case we also have
+% to set \cs{g_@@_col_int} to 1 because this is no longer done in the
+% preamble for the cell either.
+% \begin{macrocode}
+ \int_compare:nNnTF \g_@@_col_int = 0
+ {
+ \UseTaggingSocket{tbl/row/begin}
+ \int_gset:Nn \g_@@_col_int {1}
+ }
+% \end{macrocode}
+% If we are in a later column we use \cs{g_@@_span_tl} from the
+% previous column to update.
+% \begin{macrocode}
+ {
+ \int_gadd:Nn \g_@@_col_int { \g_@@_span_tl }
+ }
+% \end{macrocode}
+% Then we set the span value so that it can be use in the next column.
+% \begin{macrocode}
+ \tl_gset:Nn \g_@@_span_tl {#1}
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\tbl_crcr:n}
+% This macro is used instead of the usual \cs{crcr} at the end of a
+% table. It is deliberately defined without protection because it
+% may get expanded by the scanning mechanism of low-level \TeX{}
+% after a final \cs{cr} (aka \verb=\\=) in the table. In that case
+% it shouldn't stop the expansion and the conditional inside will
+% be false, thus it just vanishes without doing anything. If there
+% are missing cells (in which case we also haven't see \cs{cr} yet)
+% the macro \cs{tbl_count_missing_cells:n} is executed and
+% then the row is finished with a final \cs{cr}.
+% \begin{macrocode}
+\cs_new:Npn \tbl_crcr:n #1 {
+ \int_compare:nNnT \g_@@_col_int > 0
+ {
+ \tbl_count_missing_cells:n {#1}
+ \cr
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+%<@@=>
+% \end{macrocode}
+%
+% This is needed for \pkg{longtable} because \cs{refstepcounter} is
+% setting up a target when \pkg{hyperref} is loaded and we don't
+% want that in \pkg{longtable}.
+%
+% TODO: move to right .dtx file
+% \begin{macrocode}
+\let\@kernel@refstepcounter\refstepcounter
+% \end{macrocode}
+% Prevent longtable patching by hyperref until hyperref does so automatically:
+% \begin{macrocode}
+\def\hyper@nopatch@longtable{}
+% \end{macrocode}
+%
+%
+% Should there be a module?
+%
+% \begin{macrocode}
+%<latexrelease>\NewModuleRelease{2024/06/01}{lttagging}
+%<latexrelease> {Tagging support}
+% \end{macrocode}
+%
+%
+%
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}{lttagging}%
+%<latexrelease> {Undo tagging support}
+%<latexrelease>
+%<latexrelease>
+%<latexrelease>
+%<latexrelease>\EndModuleRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \Finale
+%
diff --git a/Master/texmf-dist/source/latex/base/lttemplates.dtx b/Master/texmf-dist/source/latex/base/lttemplates.dtx
new file mode 100644
index 00000000000..7192359e726
--- /dev/null
+++ b/Master/texmf-dist/source/latex/base/lttemplates.dtx
@@ -0,0 +1,2634 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 1999 Frank Mittelbach, Chris Rowley, David Carlisle
+% Copyright (C) 2004-2010 Frank Mittelbach, The LaTeX Project
+% Copyright (C) 2011-2024
+% The LaTeX Project and any individual authors listed elsewhere
+% in this file.
+%
+% This file is part of the LaTeX base system.
+% -------------------------------------------
+%
+% It may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% https://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008 or later.
+%
+% This file has the LPPL maintenance status "maintained".
+%
+% The list of all files belonging to the LaTeX base distribution is
+% given in the file `manifest.txt'. See also `legal.txt' for additional
+% information.
+%
+% The list of derived (unpacked) files belonging to the distribution
+% and covered by LPPL is defined by the unpacking scripts (with
+% extension .ins) which are part of the distribution.
+%
+% \fi
+%
+% \iffalse
+%
+%%% From File: lttemplates.dtx
+%
+%<*driver>
+% \fi
+\ProvidesFile{lttemplates.dtx}
+ [2024-04-17 v1.0c LaTeX Kernel (Prototype document functions)]
+% \iffalse
+\documentclass{l3doc}
+\GetFileInfo{lttemplates.dtx}
+\begin{document}
+ \DocInput{lttemplates.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \texttt{lttemplates.dtx} code\thanks{This file has version
+% \fileversion\ dated \filedate, \copyright\ \LaTeX\
+% Project.}}
+% \author{^^A
+% Frank Mittelbach, Chris Rowley, David Carlisle, \LaTeX{} Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \maketitle
+%
+% \section{Introduction}
+%
+% There are three broad \enquote{layers} between putting down ideas into
+% a source file and ending up with a typeset document. These layers of
+% document writing are
+% \begin{enumerate}
+% \item authoring of the text with mark-up;
+% \item document layout design;
+% \item implementation (with \TeX{} programming) of the design.
+% \end{enumerate}
+% We write the text as an author, and we see the visual output of the design
+% after the document is generated; the \TeX{} implementation in the middle is
+% the glue between the two.
+%
+% \LaTeX{}'s greatest success has been to standardise a system of mark-up that
+% balances the trade-off between ease of reading and ease of writing to suit
+% almost all forms of technical writing. It's
+% other original strength was a good background in typographical design; while
+% the standard \LaTeXe{} classes look somewhat dated now in terms of their
+% visual design, their typography is generally sound (barring the occasional
+% minor faults).
+%
+% However, \LaTeXe{} has always lacked a standard approach to customising
+% the visual design of a document. Changing the looks of the standard classes
+% involved either:
+% \begin{itemize}
+% \item Creating a new version of the implementation code of the class and
+% editing it.
+% \item Loading one of the many packages to customise certain elements of
+% the standard classes.
+% \item Loading a completely different document class, such as
+% \textsf{KOMA-Script} or \textsf{memoir}, that allows easy customisation.
+% \end{itemize}
+% All three of these approaches have their drawbacks and learning curves.
+%
+% The idea behind \pkg{lttemplates} is to cleanly separate the three layers
+% introduced at the beginning of this section, so that document authors who
+% are not programmers can easily change the design of their documents.
+% \pkg{lttemplates} also makes it easier for \LaTeX{} programmers to provide
+% their own customisations on top of a pre-existing class.
+%
+% \section{What is a document?}
+%
+% Besides the textual content of the words themselves, the source file
+% of a document contains mark-up elements that add structure to the
+% document. These elements include sectional divisions, figure/table
+% captions, lists of various sorts, theorems/proofs, and so on.
+% The list will be different for every document that can be written.
+%
+% Each element can be represented logically without worrying about the
+% formatting, with mark-up such as \cs{section}, \cs{caption},
+% |\begin{enumerate}| and so on. The output of each one of these
+% document elements will be a typeset representation of the information
+% marked up, and the visual arrangement and design of these elements
+% can vary widely in producing a variety of desired outcomes.
+%
+% For each type of document element, there may be design variations that
+% contain the same sort of information but present it in slightly
+% different ways. For example, the difference between a numbered and an
+% unnumbered section, \cs{section} and |\section*|, or the difference
+% between an itemised list or an enumerated list.
+%
+% There are three distinct layers in the definition of
+% \enquote{a document} at this level
+% \begin{enumerate}
+% \item semantic elements such as the ideas of sections and lists;
+% \item a set of design solutions for representing these elements
+% visually;
+% \item specific variations for these designs that represent the
+% elements in the document.
+% \end{enumerate}
+% In the parlance of the template system, these are called types,
+% templates, and instances, and they are discussed below in sections
+% \ref{sec:types}, \ref{sec:templates}, and~\ref{sec:instances},
+% respectively.
+%
+% \section {Types, templates, and instances}
+%
+% By formally declaring documents to be composed of mark-up elements
+% grouped into types, which are interpreted and typeset with a set of
+% templates, each of which has one or more instances with which to
+% compose each and every semantic unit of the text, we can cleanly
+% separate the components of document construction.
+%
+% All of the structures provided by the template system are global,
+% and do not respect \TeX{} grouping.
+%
+% \section{Template types}
+% \label{sec:types}
+%
+% An \emph{template type} (sometimes just \enquote{type}) is an
+% abstract idea of a document element that takes a fixed number of
+% arguments corresponding to the information from the document author
+% that it is representing. A sectioning type, for example, might take
+% three inputs: \enquote{title}, \enquote{short title}, and
+% \enquote{label}.
+%
+% Any given document class will define which types are to be
+% used in the document, and any template of a given type can be
+% used to generate an instance for the type. (Of course, different
+% templates will produce different typeset representations, but the
+% underlying content will be the same.)
+%
+% \begin{function}{\NewTemplateType}
+% \begin{syntax}
+% \cs{NewTemplateType} \Arg{template type} \Arg{no. of args}
+% \end{syntax}
+% This function defines an \meta{template type} taking
+% \meta{number of arguments}, where the \meta{type} is an
+% abstraction as discussed above. For example,
+% \begin{verbatim}
+% \NewTemplateType{sectioning}{3}
+% \end{verbatim}
+% creates a type \enquote{sectioning}, where each use of that
+% type will need three arguments.
+% \end{function}
+%
+% \section{Templates}
+% \label{sec:templates}
+%
+% A \emph{template} is a generalised design solution for representing
+% the information of a specified type. Templates that do the same
+% thing, but in different ways, are grouped together by their type
+% and given separate names. There are two important parts to a template:
+% \begin{itemize}
+% \item the parameters it takes to vary the design it is producing;
+% \item the implementation of the design.
+% \end{itemize}
+% As a document author or designer does not care about the
+% implementation but rather only the interface to the template, these two
+% aspects of the template definition are split into two independent
+% declarations, \cs{DeclareTemplateInterface} and
+% \cs{DeclareTemplateCode}.
+%
+% \begin{function}{\DeclareTemplateInterface}
+% \begin{syntax}
+% \cs{DeclareTemplateInterface}
+% ~~\Arg{type} \Arg{template} \Arg{no.~of args}
+% ~~\Arg{key list}
+% \end{syntax}
+% A \meta{template} interface is declared for a particular
+% \meta{type}, where the \meta{number of arguments} must
+% agree with the type declaration. The interface itself is
+% defined by the \meta{key list}, which is itself a key--value list
+% taking a specialized format:
+% \begin{quotation}
+% \obeylines
+% \noindent
+% \meta{key1}~":"~\meta{key type1}~","
+% \meta{key2}~":"~\meta{key type2}~","
+% \meta{key3}~":"~\meta{key type3}~"="~\meta{default3}~","
+% \meta{key4}~":"~\meta{key type4}~"="~\meta{default4}~","
+% \ldots
+% \end{quotation}
+% Each \meta{key} name should consist of \textsc{ascii} characters,
+% with the exception of |,|, |=| and \verb*| |. The recommended form
+% for key names is to use lower case letters, with dashes to separate
+% out different parts. Spaces are ignored in key names, so they can be
+% included or missed out at will. Each \meta{key} must have a
+% \meta{key type}, which defined the type of input that the \meta{key}
+% requires. A full list of key types is given in
+% Table~\ref{tab:key-types}. Each key may have a \meta{default}
+% value, which will be used in by the template if the \meta{key} is
+% not set explicitly. The \meta{default} should be of the correct
+% form to be accepted by the \meta{key type} of the \meta{key}: this
+% is not checked by the code. Expressions for numerical values are
+% evaluated when the template is used, thus for example values given
+% in terms of |em| or |ex| will be set respecting the prevailing font.
+% \end{function}
+%
+% \begin{table}
+% \centering
+% \begin{tabular}{>{\ttfamily}ll}
+% \toprule
+% \multicolumn{1}{l}{Key-type} & Description of input \\
+% \midrule
+% boolean & \texttt{true} or \texttt{false} \\
+% choice\Arg{choices}
+% & A list of pre-defined \meta{choices} \\
+% commalist & A comma-separated list \\
+% function\Arg{$N$}
+% & A function definition with $N$ arguments
+% ($N$ from $0$ to $9$) \\
+% instance\Arg{name}
+% & An instance of type \meta{name} \\
+% integer & An integer or integer expression \\
+% length & A fixed length \\
+% muskip & A math length with shrink and stretch components \\
+% real & A real (floating point) value \\
+% skip & A length with shrink and stretch components \\
+% tokenlist & A token list: any text or commands \\
+% \bottomrule
+% \end{tabular}
+% \caption{Key-types for defining template interfaces with
+% \cs{DeclareTemplateInterface}.}
+% \label{tab:key-types}
+% \end{table}
+%
+% \begin{function}{\KeyValue}
+% \begin{syntax}
+% \cs{KeyValue} \Arg{key name}
+% \end{syntax}
+% There are occasions where the default (or value) for one key
+% should be taken from another. The \cs{KeyValue} function can be
+% used to transfer this information without needing to know the
+% internal implementation of the key:
+% \begin{verbatim}
+% \DeclareTemplateInterface { type } { template } { no. of args }
+% {
+% key-name-1 : key-type = value ,
+% key-name-2 : key-type = \KeyValue { key-name-1 },
+% ...
+% }
+% \end{verbatim}
+% \end{function}
+%
+% \begin{function}{\DeclareTemplateCode}
+% \begin{syntax}
+% \cs{DeclareTemplateCode}
+% ~~\Arg{type} \Arg{template} \Arg{no.~of args}
+% ~~\Arg{key bindings} \Arg{code}
+% \end{syntax}
+% The relationship between a templates keys and the internal
+% implementation is created using the \cs{DeclareTemplateCode}
+% function. As with \cs{DeclareTemplateInterface}, the
+% \meta{template} name is given along with the \meta{type}
+% and \meta{number of arguments} required. The \meta{key bindings}
+% argument is a key--value list which specifies the relationship
+% between each \meta{key} of the template interface with an
+% underlying\meta{variable}.
+%
+% \begin{quotation}
+% \obeylines
+% \noindent
+% \meta{key1}~"="~\meta{variable1},
+% \meta{key2}~"="~\meta{variable2},
+% \meta{key3}~"="~global~\meta{variable3},
+% \meta{key4}~"="~global~\meta{variable4},
+% \ldots
+% \end{quotation}
+% With the exception of the choice, code and function key types,
+% the \meta{variable} here should be the name of an existing
+% \LaTeX3 register. As illustrated, the key word \enquote{global}
+% may be included in the listing to indicate that the \meta{variable}
+% should be assigned globally. A full list of variable bindings is
+% given in Table~\ref{tab:key-vars}.
+%
+% The \meta{code} argument of \cs{DeclareTemplateCode} is used
+% as the replacement text for the template when it is used, either
+% directly or as an instance. This may therefore accept arguments
+% |#1|, |#2|, \emph{etc}.~as detailed by the \meta{number of arguments}
+% taken by the type.
+% \end{function}
+%
+% \begin{table}
+% \centering
+% \begin{tabular}{>{\ttfamily}ll}
+% \toprule
+% \multicolumn{1}{l}{Key-type} & Description of binding \\
+% \midrule
+% \ & Boolean variable, \emph{e.g}.~\cs{l_tmpa_bool} \\
+% choice
+% & List of choice implementations
+% (see Section~\ref{sec:choices-key}) \\
+% commalist & Comma list, \emph{e.g}.~\cs{l_tmpa_clist} \\
+% function
+% & Function taking $N$ arguments, \emph{e.g}.~\cs{use_i:nn} \\
+% instance \\
+% integer & Integer variable, \emph{e.g}.~\cs{l_tmpa_int} \\
+% length & Dimension variable, \emph{e.g}.~\cs{l_tmpa_dim} \\
+% muskip & Muskip variable, \emph{e.g}.~\cs{l_tmpa_muskip} \\
+% real & Floating-point variable, \emph{e.g}.~\cs{l_tmpa_fp} \\
+% skip & Skip variable, \emph{e.g}.~\cs{l_tmpa_skip} \\
+% tokenlist & Token list variable, \emph{e.g}.~\cs{l_tmpa_tl} \\
+% \bottomrule
+% \end{tabular}
+% \caption{Bindings required for different key types when defining
+% template implementations with \cs{DeclareTemplateCode}. Apart
+% from \texttt{code}, \texttt{choice} and \texttt{function}
+% all of these accept the key word \texttt{global} to carry
+% out a global assignment.}
+% \label{tab:key-vars}
+% \end{table}
+%
+% \begin{function}{\AssignTemplateKeys}
+% \begin{syntax}
+% \cs{AssignTemplateKeys}
+% \end{syntax}
+% In the final argument of \cs{DeclareTemplateCode} the assignment of
+% keys defined by the template may be delayed by including the command
+% \cs{AssignTemplateKeys}. If this is \emph{not} present, keys are assigned
+% immediately before the template code. If \cs{AssignTemplateKeys} is
+% present, assignment is delayed until this point. Note that the
+% command must be \emph{directly} present in the code, not placed
+% within a nested command/macro.
+% \end{function}
+%
+% \begin{function}{\DeclareTemplateCopy}
+% \begin{syntax}
+% \cs{DeclareTemplateCopy}
+% ~~\Arg{type} \Arg{template2} \Arg{template1}
+% \end{syntax}
+% Copies \meta{template1} of \meta{type} to a new name \meta{template2}:
+% the copy can then be edited independent of teh original.
+% \end{function}
+%
+% \section{Multiple choices}
+% \label{sec:choices-key}
+%
+% The \texttt{choice} key type implements multiple choice input. At the
+% interface level, only the list of valid choices is needed:
+% \begin{verbatim}
+% \DeclareTemplateInterface { foo } { bar } { 0 }
+% { key-name : choice { A, B, C } }
+% \end{verbatim}
+% where the choices are given as a comma-list (which must therefore
+% be wrapped in braces). A default value can also be given:
+% \begin{verbatim}
+% \DeclareTemplateInterface { foo } { bar } { 0 }
+% { key-name : choice { A, B, C } = A }
+% \end{verbatim}
+%
+% At the implementation level, each choice is associated with code,
+% using a nested key--value list.
+% \begin{verbatim}
+% \DeclareTemplateCode { foo } { bar } { 0 }
+% {
+% key-name =
+% {
+% A = Code-A ,
+% B = Code-B ,
+% C = Code-C
+% }
+% }
+% { ... }
+% \end{verbatim}
+% The two choice lists should match, but in the implementation a
+% special \texttt{unknown} choice is also available. This can be used
+% to ignore values and implement an \enquote{else} branch:
+% \begin{verbatim}
+% \DeclareTemplateCode { foo } { bar } { 0 }
+% {
+% key-name =
+% {
+% A = Code-A ,
+% B = Code-B ,
+% C = Code-C ,
+% unknown = Else-code
+% }
+% }
+% { ... }
+% \end{verbatim}
+% The \texttt{unknown} entry must be the last one given, and should
+% \emph{not} be listed in the interface part of the template.
+%
+% For keys which accept the values \texttt{true} and \texttt{false}
+% both the boolean and choice key types can be used. As template
+% interfaces are intended to prompt clarity at the design level, the
+% boolean key type should be favoured, with the choice type reserved
+% for keys which take arbitrary values.
+%
+% \section{Instances}
+% \label{sec:instances}
+%
+% After a template is defined it still needs to be put to use. The
+% parameters that it expects need to be defined before it can be used in
+% a document. Every time a template has parameters given to it, an
+% \emph{instance} is created, and this is the code that ends up in the
+% document to perform the typesetting of whatever pieces of information
+% are input into it.
+%
+% For example, a template might say \enquote{here is a section with or
+% without a number that might be centred or left aligned and print its
+% contents in a certain font of a certain size, with a bit of a gap
+% before and after it} whereas an instance declares \enquote{this is a
+% section with a number, which is centred and set in $12\,\text{pt}$
+% italic with a $10\,\text{pt}$ skip before and a
+% $12\,\text{pt}$ skip after it}. Therefore, an instance is just a
+% frozen version of a template with specific settings as chosen by the
+% designer.
+%
+% \begin{function}{\DeclareInstance}
+% \begin{syntax}
+% \cs{DeclareInstance}
+% ~~\Arg{type} \Arg{instance} \Arg{template} \Arg{parameters}
+% \end{syntax}
+% This function uses a \meta{template} for an \meta{type}
+% to create an \meta{instance}. The \meta{instance} will be set
+% up using the \meta{parameters}, which will set some of the
+% \meta{keys} in the \meta{template}.
+%
+% As a practical example, consider a type for document sections
+% (which might include chapters, parts, sections, \emph{etc}.), which
+% is called \texttt{sectioning}. One possible template for this
+% type might be called \texttt{basic}, and one instance of this
+% template would be a numbered section. The instance declaration might
+% read:
+% \begin{verbatim}
+% \DeclareInstance { sectioning } { section-num } { basic }
+% {
+% numbered = true ,
+% justification = center ,
+% font =\normalsize\itshape ,
+% before-skip = 10pt ,
+% after-skip = 12pt ,
+% }
+% \end{verbatim}
+% Of course, the key names here are entirely imaginary, but illustrate
+% the general idea of fixing some settings.
+% \end{function}
+%
+% \begin{function}{\IfInstanceExistsT, \IfInstanceExisstF, \IfInstanceExistsTF}
+% \begin{syntax}
+% \cs{IfInstanceExistsTF} \Arg{type} \Arg{instance} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the named \meta{instance} of a \meta{type} exists, and
+% then inserts the appropriate code into the input stream.
+% \end{function}
+%
+% \begin{function}{\DeclareInstanceCopy}
+% \begin{syntax}
+% \cs{DeclareInstanceCopy}
+% ~~\Arg{type} \Arg{instance2} \Arg{instance1}
+% \end{syntax}
+% Copies the \meta{values} for \meta{instance1} for an
+% \meta{type} to \meta{instance2}.
+% \end{function}
+%
+% \section{Document interface}
+%
+% After the instances have been chosen, document commands must be
+% declared to use those instances in the document. \cs{UseInstance}
+% calls instances directly, and this command should be used internally
+% in document-level mark-up.
+%
+% \begin{function}{\UseInstance}
+% \begin{syntax}
+% \cs{UseInstance}
+% ~~\Arg{type} \Arg{instance} \meta{arguments}
+% \end{syntax}
+% Uses an \meta{instance} of the \meta{type}, which will require
+% \meta{arguments} as determined by the number specified for the
+% \meta{type}. The \meta{instance} must have been declared
+% before it can be used, otherwise an error is raised.
+% \end{function}
+%
+% \begin{function}{\UseTemplate}
+% \begin{syntax}
+% \cs{UseTemplate} \Arg{type} \Arg{template}
+% ~~\Arg{settings} \meta{arguments}
+% \end{syntax}
+% Uses the \meta{template} of the specified \meta{type},
+% applying the \meta{settings} and absorbing \meta{arguments} as
+% detailed by the \meta{type} declaration. This in effect
+% is the same as creating an instance using \cs{DeclareInstance}
+% and immediately using it with \cs{UseInstance}, but without the
+% instance having any further existence. It is therefore useful where
+% a template needs to be used once.
+%
+% This function can also be used as the argument to \texttt{instance}
+% key types:
+% \begin{verbatim}
+% \DeclareInstance { type } { template } { instance }
+% {
+% instance-key =
+% \UseTemplate { type2 } { template2 } { <settings> }
+% }
+% \end{verbatim}
+% \end{function}
+%
+% \section{Changing existing definitions}
+%
+% Template parameters may be assigned specific defaults for instances
+% to use if the instance declaration doesn't explicit set those
+% parameters. In some cases, the document designer will wish to edit
+% these defaults to allow them to \enquote{cascade} to the instances.
+% The alternative would be to set each parameter identically for each
+% instance declaration, a tedious and error-prone process.
+%
+% \begin{function}{\EditTemplateDefaults}
+% \begin{syntax}
+% \cs{EditTemplateDefaults}
+% ~~\Arg{type} \Arg{template} \Arg{new defaults}
+% \end{syntax}
+% Edits the \meta{defaults} for a \meta{template} for an
+% \meta{type}. The \meta{new defaults}, given as a key--value
+% list, replace the existing defaults for the \meta{template}. This
+% means that the change will apply to instances declared after the
+% editing, but that instances which have already been created are
+% unaffected.
+% \end{function}
+%
+% \begin{function}{\EditInstance}
+% \begin{syntax}
+% \cs{EditInstance}
+% ~~\Arg{type} \Arg{instance} \Arg{new values}
+% \end{syntax}
+% Edits the \meta{values} for an \meta{instance} for an
+% \meta{type}. The \meta{new values}, given as a key--value
+% list, replace the existing values for the \meta{instance}. This
+% function is complementary to \cs{EditTemplateDefaults}:
+% \cs{EditInstance} changes a single instance while leaving the
+% template untouched.
+% \end{function}
+%
+% \section{\emph{Ad hoc} adjustment of templates}
+%
+% \begin{function}{\SetTemplateKeys}
+% \begin{syntax}
+% \cs{SetTemplateKeys} \Arg{type} \Arg{template} \Arg{keyvals}
+% \end{syntax}
+% At point of use it may be useful to apply changed to individual instances.
+% This is supported as each template key is made available for adjustment
+% using \cs{SetTemplateKeys}.
+% \end{function}
+%
+% For example, after
+% \begin{verbatim}
+% \NewTypeType{MyObj}{0}
+% \DeclareTemplateInterface{MyObj}{TemplateA}{0}
+% {
+% akey: tokenlist ,
+% bkey: function{2}
+% }
+% \DeclareTemplateCode{MyObj}{TemplateA}{0}
+% {
+% akey = SomeTokens ,
+% bkey = \func:nn ,
+% }
+% \end{verbatim}
+% the template keys could be adjusted in an \emph{ad hoc} fashion using
+% \begin{verbatim}
+% \SetTemplateKeys{MyObj}{TemplateA}
+% {
+% akey = OtherTokens ,
+% bkey = \AltFunc:nn
+% }
+% \end{verbatim}
+%
+% \section{Getting information about templates and instances}
+%
+% \begin{function}{\ShowInstanceValues}
+% \begin{syntax}
+% \cs{ShowInstanceValues} \Arg{type} \Arg{instance}
+% \end{syntax}
+% Shows the \meta{values} for an \meta{instance} of the given
+% \meta{type} at the terminal.
+% \end{function}
+%
+% \begin{function}{\ShowTemplateCode}
+% \begin{syntax}
+% \cs{ShowTemplateCode} \Arg{type} \Arg{template}
+% \end{syntax}
+% Shows the \meta{code} of a \meta{template} for an \meta{type}
+% in the terminal.
+% \end{function}
+%
+% \begin{function}{\ShowTemplateDefaults}
+% \begin{syntax}
+% \cs{ShowTemplateDefaults} \Arg{type} \Arg{template}
+% \end{syntax}
+% Shows the \meta{default} values of a \meta{template} for an
+% \meta{type} in the terminal.
+% \end{function}
+%
+% \begin{function}{\ShowTemplateInterface}
+% \begin{syntax}
+% \cs{ShowTemplateInterface} \Arg{type} \Arg{template}
+% \end{syntax}
+% Shows the \meta{keys} and associated \meta{key types} of a
+% \meta{template} for an \meta{type} in the terminal.
+% \end{function}
+%
+% \begin{function}{\ShowTemplateVariables}
+% \begin{syntax}
+% \cs{ShowTemplateVariables} \Arg{type} \Arg{template}
+% \end{syntax}
+% Shows the \meta{variables} and associated \meta{keys} of a
+% \meta{template} for an \meta{type} in the terminal. Note that
+% \texttt{code} and \texttt{choice} keys do not map directly to variables
+% but to arbitrary code. For \texttt{choice} keys, each valid choice
+% is shown as a separate entry in the list, with the key name and choice
+% separated by a space, for example
+% \begin{verbatim}
+% Template 'example' of type 'example' has variable mapping:
+% > demo unknown => \def \demo {?}
+% > demo c => \def \demo {c}
+% > demo b => \def \demo {b}
+% > demo a => \def \demo {a}.
+% \end{verbatim}
+% would be shown for a choice key \texttt{demo} with valid choices
+% \texttt{a}, \texttt{b} and \texttt{c}, plus code for an \texttt{unknown}
+% branch.
+% \end{function}
+%
+% \MaybeStop{\setlength\IndexMin{200pt}\PrintIndex}
+%
+% \section{The implementation}
+%
+% \begin{macrocode}
+%<@@=template>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*2ekernel>
+\message{templates,}
+%</2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\NewModuleRelease{2024/06/01}{lttemplates}
+%<latexrelease> {Prototype~document~commands}%
+% \end{macrocode}
+%
+% \subsection{Variables and constants}
+%
+% \begin{variable}
+% {
+% \c_@@_code_root_tl ,
+% \c_@@_defaults_root_tl ,
+% \c_@@_instances_root_tl ,
+% \c_@@_keytypes_root_tl ,
+% \c_@@_key_order_root_tl ,
+% \c_@@_restrict_root_tl ,
+% \c_@@_values_root_tl ,
+% \c_@@_vars_root_tl
+% }
+% So that literal values are kept to a minimum.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_code_root_tl { template~code~>~ }
+\tl_const:Nn \c_@@_defaults_root_tl { template~defaults~>~ }
+\tl_const:Nn \c_@@_instances_root_tl { template~instance~>~ }
+\tl_const:Nn \c_@@_keytypes_root_tl { template~key~types~>~ }
+\tl_const:Nn \c_@@_key_order_root_tl { template~key~order~>~ }
+\tl_const:Nn \c_@@_values_root_tl { template~values~>~ }
+\tl_const:Nn \c_@@_vars_root_tl { template~vars~>~ }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_@@_keytypes_arg_seq}
+% A list of keytypes which also need additional data (an argument),
+% used to parse the keytype correctly.
+% \begin{macrocode}
+\seq_const_from_clist:Nn \c_@@_keytypes_arg_seq
+ { choice , function , instance }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_type_prop}
+% For storing types and the associated number of arguments.
+% \begin{macrocode}
+\prop_new:N \g_@@_type_prop
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_assignments_tl}
+% When creating an instance, the assigned values are collected here.
+% \begin{macrocode}
+\tl_new:N \l_@@_assignments_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\l_@@_default_tl}
+% The default value for a key is recovered here from the property list
+% in which it is stored.
+% \begin{macrocode}
+\tl_new:N \l_@@_default_tl
+% \end{macrocode}
+%\ end{macro}
+%
+% \begin{variable}{\l_@@_error_bool}
+% A flag for errors to be carried forward.
+% \begin{macrocode}
+\bool_new:N \l_@@_error_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_global_bool}
+% Used to indicate that assignments should be global.
+% \begin{macrocode}
+\bool_new:N \l_@@_global_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {
+% \l_@@_key_name_tl ,
+% \l_@@_keytype_tl ,
+% \l_@@_keytype_arg_tl ,
+% \l_@@_value_tl ,
+% \l_@@_var_tl
+% }
+% When defining each key in a template, the name and type of the key
+% need to be separated and stored. Any argument needed by the
+% keytype is also stored separately.
+% \begin{macrocode}
+\tl_new:N \l_@@_key_name_tl
+\tl_new:N \l_@@_keytype_tl
+\tl_new:N \l_@@_keytype_arg_tl
+\tl_new:N \l_@@_value_tl
+\tl_new:N \l_@@_var_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {
+% \l_@@_keytypes_prop ,
+% \l_@@_key_order_seq ,
+% \l_@@_values_prop ,
+% \l_@@_vars_prop
+% }
+% To avoid needing too many difficult-to-follow csname assignments,
+% various scratch token registers are used to build up data, which is
+% then transferred
+% \begin{macrocode}
+\prop_new:N \l_@@_keytypes_prop
+\seq_new:N \l_@@_key_order_seq
+\prop_new:N \l_@@_values_prop
+\prop_new:N \l_@@_vars_prop
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {
+% \l_@@_tmp_clist ,
+% \l_@@_tmp_dim ,
+% \l_@@_tmp_int ,
+% \l_@@_tmp_muskip ,
+% \l_@@_tmp_skip ,
+% \l_@@_tmp_tl
+% }
+% Scratch space.
+% \begin{macrocode}
+\clist_new:N \l_@@_tmp_clist
+\dim_new:N \l_@@_tmp_dim
+\int_new:N \l_@@_tmp_int
+\muskip_new:N \l_@@_tmp_muskip
+\skip_new:N \l_@@_tmp_skip
+\tl_new:N \l_@@_tmp_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\s_@@_mark, \s_@@_stop}
+% Internal scan marks.
+% \begin{macrocode}
+\scan_new:N \s_@@_mark
+\scan_new:N \s_@@_stop
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\q_@@_nil}
+% Internal quarks.
+% \begin{macrocode}
+\quark_new:N \q_@@_nil
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[pTF]{\@@_quark_if_nil:n}
+% Branching quark conditional.
+% \begin{macrocode}
+\__kernel_quark_new_conditional:Nn \@@_quark_if_nil:N { F }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Testing existence and validity}
+%
+% There are a number of checks needed for either the existence of
+% a type, template or instance. There are also some for the
+% validity of a particular call. All of these are collected up here.
+%
+% \begin{macro}{\@@_execute_if_arg_agree:nnT}
+% A test agreement between the number of arguments for the template
+% type and that specified when creating a template. This is not done as a
+% separate conditional for efficiency and better error message
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_execute_if_arg_agree:nnT #1#2#3
+ {
+ \prop_get:NnN \g_@@_type_prop {#1} \l_@@_tmp_tl
+ \int_compare:nNnTF {#2} = \l_@@_tmp_tl
+ {#3}
+ {
+ \msg_error:nneee { template } { argument-number-mismatch }
+ {#1} { \l_@@_tmp_tl } {#2}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_execute_if_code_exist:nnT}
+% A template is only fully declared if the code has been set up,
+% which can be checked by looking for the template function itself.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_execute_if_code_exist:nnT #1#2#3
+ {
+ \cs_if_exist:cTF { \c_@@_code_root_tl #1 / #2 }
+ {#3}
+ { \msg_error:nnnn { template } { no-template-code } {#1} {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {\@@_execute_if_keytype_exist:nT, \@@_execute_if_keytype_exist:VT}
+% The test for valid keytypes looks for a function to set up the key,
+% which is part of the \enquote{code} side of the template definition.
+% This avoids having different lists for the two parts of the process.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_execute_if_keytype_exist:nT #1#2
+ {
+ \cs_if_exist:cTF { @@_store_value_ #1 :n }
+ {#2}
+ { \msg_error:nnn { template } { unknown-keytype } {#1} }
+ }
+\cs_generate_variant:Nn \@@_execute_if_keytype_exist:nT { V }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_execute_if_type_exist:nT}
+% To check that a particular type is valid.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_execute_if_type_exist:nT #1#2
+ {
+ \prop_if_in:NnTF \g_@@_type_prop {#1}
+ {#2}
+ { \msg_error:nnn { template } { unknown-type } {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_execute_if_keys_exist:nnT}
+% To check that the keys for a template have been set up before trying
+% to create any code, a simple check for the correctly-named keytype
+% property list.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_if_keys_exist:nnT #1#2#3
+ {
+ \cs_if_exist:cTF { \c_@@_keytypes_root_tl #1 / #2 }
+ {#3}
+ { \msg_error:nnnn { template } { unknown-template } {#1} {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF]{\@@_if_key_value:n, \@@_if_key_value:V}
+% Tests for the first token in a string being \cs{KeyValue}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_key_value:n #1 { T , F , TF }
+ {
+ \str_if_eq:noTF { \KeyValue } { \tl_head:w #1 \q_nil \q_stop }
+ \prg_return_true:
+ \prg_return_false:
+ }
+\prg_generate_conditional_variant:Nnn \@@_if_key_value:n { V } { T , F , TF }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF]{\@@_if_instance_exist:nn}
+% Testing for an instance
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_instance_exist:nn #1#2 { T, F, TF }
+ {
+ \cs_if_exist:cTF { \c_@@_instances_root_tl #1 / #2 }
+ \prg_return_true:
+ \prg_return_false:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_if_use_template:nTF}
+% Tests for the first token in a string being \cs{UseTemplate}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_use_template:n #1 { TF }
+ {
+ \str_if_eq:noTF { \UseTemplate } { \tl_head:w #1 \q_nil \q_stop }
+ \prg_return_true:
+ \prg_return_false:
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Saving and recovering property lists}
+%
+% The various property lists for templates have to be shuffled in
+% and out of storage.
+%
+% \begin{macro}
+% {
+% \@@_store_defaults:nn ,
+% \@@_store_keytypes:nn ,
+% \@@_store_values:nn ,
+% \@@_store_vars:nn
+% }
+% The defaults and keytypes are transferred from the scratch property
+% lists to the \enquote{proper} lists for the template being created.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_store_defaults:nn #1#2
+ {
+ \debug_suspend:
+ \prop_gclear_new:c { \c_@@_defaults_root_tl #1 / #2 }
+ \prop_gset_eq:cN { \c_@@_defaults_root_tl #1 / #2 }
+ \l_@@_values_prop
+ \debug_resume:
+ }
+\cs_new_protected:Npn \@@_store_keytypes:nn #1#2
+ {
+ \debug_suspend:
+ \prop_if_exist:cTF { \c_@@_keytypes_root_tl #1 / #2 }
+ {
+ \msg_info:nnnn { template } { declare-template-interface } {#1} {#2}
+ \prop_gclear:c { \c_@@_keytypes_root_tl #1 / #2 }
+ }
+ { \prop_new:c { \c_@@_keytypes_root_tl #1 / #2 } }
+ \prop_gset_eq:cN { \c_@@_keytypes_root_tl #1 / #2 }
+ \l_@@_keytypes_prop
+ \seq_gclear_new:c { \c_@@_key_order_root_tl #1 / #2 }
+ \seq_gset_eq:cN { \c_@@_key_order_root_tl #1 / #2 }
+ \l_@@_key_order_seq
+ \debug_resume:
+ }
+\cs_new_protected:Npn \@@_store_values:nn #1#2
+ {
+ \debug_suspend:
+ \prop_clear_new:c { \c_@@_values_root_tl #1 / #2 }
+ \prop_set_eq:cN { \c_@@_values_root_tl #1 / #2 }
+ \l_@@_values_prop
+ \debug_resume:
+ }
+\cs_new_protected:Npn \@@_store_vars:nn #1#2
+ {
+ \debug_suspend:
+ \prop_gclear_new:c { \c_@@_vars_root_tl #1 / #2 }
+ \prop_gset_eq:cN { \c_@@_vars_root_tl #1 / #2 }
+ \l_@@_vars_prop
+ \debug_resume:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_recover_defaults:nn ,
+% \@@_recover_keytypes:nn ,
+% \@@_recover_values:nn ,
+% \@@_recover_vars:nn
+% }
+% Recovering the stored data for a template is rather less complex
+% than storing it. All that happens is the data is transferred from
+% the permanent to the scratch storage. However, we need to check the
+% scratch storage does exist.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_recover_defaults:nn #1#2
+ {
+ \prop_if_exist:cTF
+ { \c_@@_defaults_root_tl #1 / #2 }
+ {
+ \prop_set_eq:Nc \l_@@_values_prop
+ { \c_@@_defaults_root_tl #1 / #2 }
+ }
+ { \prop_clear:N \l_@@_values_prop }
+ }
+\cs_new_protected:Npn \@@_recover_keytypes:nn #1#2
+ {
+ \prop_if_exist:cTF
+ { \c_@@_keytypes_root_tl #1 / #2 }
+ {
+ \prop_set_eq:Nc \l_@@_keytypes_prop
+ { \c_@@_keytypes_root_tl #1 / #2 }
+ }
+ { \prop_clear:N \l_@@_keytypes_prop }
+ \seq_if_exist:cTF { \c_@@_key_order_root_tl #1 / #2 }
+ {
+ \seq_set_eq:Nc \l_@@_key_order_seq
+ { \c_@@_key_order_root_tl #1 / #2 }
+ }
+ { \seq_clear:N \l_@@_key_order_seq }
+ }
+\cs_new_protected:Npn \@@_recover_values:nn #1#2
+ {
+ \prop_if_exist:cTF
+ { \c_@@_values_root_tl #1 / #2 }
+ {
+ \prop_set_eq:Nc \l_@@_values_prop
+ { \c_@@_values_root_tl #1 / #2 }
+ }
+ { \prop_clear:N \l_@@_values_prop }
+ }
+\cs_new_protected:Npn \@@_recover_vars:nn #1#2
+ {
+ \prop_if_exist:cTF
+ { \c_@@_vars_root_tl #1 / #2 }
+ {
+ \prop_set_eq:Nc \l_@@_vars_prop
+ { \c_@@_vars_root_tl #1 / #2 }
+ }
+ { \prop_clear:N \l_@@_vars_prop }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Creating new template types}
+%
+% \begin{macro}{\@@_define_type:nn, \@@_declare_type:nn}
+% Although the type is the \enquote{top level} of the template
+% system, it is actually very easy to implement. All that happens is that
+% the number of arguments required is recorded, indexed by the name of the
+% type.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_define_type:nn #1#2
+ {
+ \prop_if_in:NnTF \g_@@_type_prop {#1}
+ { \msg_error:nnn { template } { type-already-defined } {#1} }
+ { \@@_declare_type:nn {#1} {#2} }
+ }
+\cs_new_protected:Npn \@@_declare_type:nn #1#2
+ {
+ \int_set:Nn \l_@@_tmp_int {#2}
+ \int_compare:nTF { 0 <= \l_@@_tmp_int <= 9 }
+ {
+ \msg_info:nnnV { template } { declare-type }
+ {#1} \l_@@_tmp_int
+ \prop_gput:NnV \g_@@_type_prop {#1}
+ \l_@@_tmp_int
+ }
+ {
+ \msg_error:nnnV { template } { bad-number-of-arguments }
+ {#1} \l_@@_tmp_int
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Design part of template declaration}
+%
+% The \enquote{design} part of a template declaration defines the general
+% behaviour of each key, and possibly a default value. However, it does
+% not include the implementation. This means that what happens here is
+% the two properties are saved to appropriate lists, which can then
+% be used later to recover the information when implementing the keys.
+%
+% \begin{macro}{\@@_declare_template_keys:nnnn}
+% The main function for the \enquote{design} part of creating a template
+% starts by checking that the type exists and that the number of
+% arguments required agree. If that is all fine, then the two storage
+% areas for defaults and keytypes are initialised. The mechanism is then
+% set up for the \pkg{l3keys} module to actually parse the keys.
+% Finally, the code hands of to the storage routine to save the parsed
+% information properly.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_template_keys:nnnn #1#2#3#4
+ {
+ \@@_execute_if_type_exist:nT {#1}
+ {
+ \@@_execute_if_arg_agree:nnT {#1} {#3}
+ {
+ \prop_clear:N \l_@@_values_prop
+ \prop_clear:N \l_@@_keytypes_prop
+ \seq_clear:N \l_@@_key_order_seq
+ \keyval_parse:NNn
+ \@@_parse_keys_elt:n \@@_parse_keys_elt:nn {#4}
+ \@@_store_defaults:nn {#1} {#2}
+ \@@_store_keytypes:nn {#1} {#2}
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_keys_elt:n}
+% \begin{macro}{\@@_parse_keys_elt_aux:n}
+% \begin{macro}{\@@_parse_keys_elt_aux:}
+% Processing the key part of the key--value pair is always carried out
+% using this function, even if a value was found. First, the key name
+% is separated from the keytype, and if necessary the keytype is
+% separated into two parts. This information is then used to check that
+% the keytype is valid, before storing the keytype (plus argument if
+% necessary) as a property of the key name. The key name is also stored
+% (in braces) in the token list to record the order the keys are defined
+% in.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_keys_elt:n #1
+ {
+ \@@_split_keytype:n {#1}
+ \bool_if:NF \l_@@_error_bool
+ {
+ \@@_execute_if_keytype_exist:VT \l_@@_keytype_tl
+ {
+ \seq_map_function:NN \c_@@_keytypes_arg_seq
+ \@@_parse_keys_elt_aux:n
+ \bool_if:NF \l_@@_error_bool
+ {
+ \seq_if_in:NoTF \l_@@_key_order_seq
+ \l_@@_key_name_tl
+ {
+ \msg_error:nnV { template } { duplicate-key-interface }
+ \l_@@_key_name_tl
+ }
+ { \@@_parse_keys_elt_aux: }
+ }
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_parse_keys_elt_aux:n #1
+ {
+ \str_if_eq:VnT \l_@@_keytype_tl {#1}
+ {
+ \tl_if_empty:NT \l_@@_keytype_arg_tl
+ {
+ \msg_error:nnn { template } { keytype-requires-argument } {#1}
+ \bool_set_true:N \l_@@_error_bool
+ \seq_map_break:
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_parse_keys_elt_aux:
+ {
+ \tl_set:Ne \l_@@_tmp_tl
+ {
+ \l_@@_keytype_tl
+ \tl_if_empty:NF \l_@@_keytype_arg_tl
+ { { \l_@@_keytype_arg_tl } }
+ }
+ \prop_put:NVV \l_@@_keytypes_prop \l_@@_key_name_tl
+ \l_@@_tmp_tl
+ \seq_put_right:NV \l_@@_key_order_seq \l_@@_key_name_tl
+ \str_if_eq:VnT \l_@@_keytype_tl { choice }
+ {
+ \clist_if_in:NnT \l_@@_keytype_arg_tl { unknown }
+ { \msg_error:nn { template } { choice-unknown-reserved } }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_keys_elt:nn}
+% For keys which have a default, the keytype and key name are first
+% separated out by the \cs{@@_parse_keys_elt:n}
+% routine, before storing the default value in the scratch property list.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_keys_elt:nn #1#2
+ {
+ \@@_parse_keys_elt:n {#1}
+ \use:c { @@_store_value_ \l_@@_keytype_tl :n } {#2}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_split_keytype:n}
+% \begin{macro}{\@@_split_keytype_aux:w}
+% The keytype and key name should be separated by |:|. As the
+% definition might be given inside or outside of a code block,
+% the category code of colons is standardised. After
+% that, the standard delimited argument method is used to separate the
+% two parts.
+% \begin{macrocode}
+\cs_new_protected:Npe \@@_split_keytype:n #1
+ {
+ \exp_not:N \bool_set_false:N \exp_not:N \l_@@_error_bool
+ \tl_set:Nn \exp_not:N \l_@@_tmp_tl {#1}
+ \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl { : } { \token_to_str:N : }
+ \tl_if_in:VnTF \exp_not:N \l_@@_tmp_tl { \token_to_str:N : }
+ {
+ \exp_not:n
+ {
+ \tl_clear:N \l_@@_key_name_tl
+ \exp_after:wN \@@_split_keytype_aux:w
+ \l_@@_tmp_tl \s_@@_stop
+ }
+ }
+ {
+ \exp_not:N \bool_set_true:N \exp_not:N \l_@@_error_bool
+ \msg_error:nnn { template } { missing-keytype } {#1}
+ }
+ }
+\use:e
+ {
+ \cs_new_protected:Npn \exp_not:N \@@_split_keytype_aux:w
+ #1 \token_to_str:N : #2 \s_@@_stop
+ {
+ \tl_put_right:Ne \exp_not:N \l_@@_key_name_tl
+ {
+ \exp_not:N \tl_trim_spaces:e
+ { \exp_not:N \tl_to_str:n {#1} }
+ }
+ \tl_if_in:nnTF {#2} { \token_to_str:N : }
+ {
+ \tl_put_right:Nn \exp_not:N \l_@@_key_name_tl
+ { \token_to_str:N : }
+ \exp_not:N \@@_split_keytype_aux:w #2 \s_@@_stop
+ }
+ {
+ \exp_not:N \tl_if_empty:NTF \exp_not:N \l_@@_key_name_tl
+ {
+ \msg_error:nnn { template } { empty-key-name }
+ { \token_to_str:N : #2 }
+ }
+ { \exp_not:N \@@_split_keytype_arg:n {#2} }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_split_keytype_arg:n, \@@_split_keytype_arg:V}
+% \begin{macro}{\@@_split_keytype_arg_aux:n}
+% \begin{macro}{\@@_split_keytype_arg_aux:w}
+% The second stage of sorting out the keytype is to check for an
+% argument. As there is no convenient delimiting token to look for,
+% a check is made instead for each possible text value for the keytype.
+% To keep things faster, this only involves the keytypes that need an
+% argument. If a match is made, then a check is also needed to see that
+% it is at the start of the keytype information. All being well, the
+% split can then be applied. Any non-matching keytypes are assumed to
+% be \enquote{correct} as given, and are left alone (this is checked by
+% other code).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_split_keytype_arg:n #1
+ {
+ \tl_set:Ne \l_@@_keytype_tl { \tl_trim_spaces:n {#1} }
+ \tl_clear:N \l_@@_keytype_arg_tl
+ \cs_set_protected:Npn \@@_split_keytype_arg_aux:n ##1
+ {
+ \tl_if_in:nnT {#1} {##1}
+ {
+ \cs_set:Npn \@@_split_keytype_arg_aux:w
+ ####1 ##1 ####2 \s_@@_stop
+ {
+ \tl_if_blank:nT {####1}
+ {
+ \tl_set:Ne \l_@@_keytype_tl
+ { \tl_trim_spaces:n {##1} }
+ \tl_if_blank:nF {####2}
+ {
+ \tl_set:Ne \l_@@_keytype_arg_tl
+ { \use:n ####2 }
+ }
+ \seq_map_break:
+ }
+ }
+ \@@_split_keytype_arg_aux:w #1 \s_@@_stop
+ }
+ }
+ \seq_map_function:NN \c_@@_keytypes_arg_seq
+ \@@_split_keytype_arg_aux:n
+ }
+\cs_generate_variant:Nn \@@_split_keytype_arg:n { V }
+\cs_new:Npn \@@_split_keytype_arg_aux:n #1 { }
+\cs_new:Npn \@@_split_keytype_arg_aux:w #1 \s_@@_stop { }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{Storing values}
+%
+% As \pkg{lttemplates} pre-processes key values for efficiency reasons,
+% there is a need to convert the values given as defaults into
+% \enquote{ready to use} data. The same general idea is true when an instance
+% is declared. However, assignments are not made until an instance is
+% used, and so there has to be some intermediate storage. Furthermore,
+% the ability to delay evaluation of results is needed. To achieve these
+% aims, a series of \enquote{process and store} functions are defined here.
+%
+% All of the information about the key (the key name and the keytype)
+% is already stored as variables. The same property list is always used
+% to store the data, meaning that the only argument required is the
+% value to be processed and potentially stored.
+%
+% \begin{macro}{\@@_store_value_boolean:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_store_value_boolean:n #1
+ { \prop_put:Non \l_@@_values_prop \l_@@_key_name_tl {#1} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_store_value:n, \@@_store_value_choice:n,
+% \@@_store_value_function:n, \@@_store_value_instance:n}
+% With no need to worry about delayed evaluation, these keytypes all
+% just store the input directly.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_store_value:n #1
+ { \prop_put:Non \l_@@_values_prop \l_@@_key_name_tl {#1} }
+\cs_new_eq:NN \@@_store_value_choice:n \@@_store_value:n
+\cs_new_eq:NN \@@_store_value_function:n \@@_store_value:n
+\cs_new_eq:NN \@@_store_value_instance:n \@@_store_value:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_store_value_aux:Nn, \@@_store_value_integer:n,
+% \@@_store_value_length:n, \@@_store_value_muskip:n,
+% \@@_store_value_real:n, \@@_store_value_skip:n,
+% \@@_store_value_tokenlist:n, \@@_store_value_commalist:n}
+% Storing values in \cs{l_@@_values_prop} is in most cases the same.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_store_value_aux:Nn #1#2
+ { \prop_put:Non \l_@@_values_prop \l_@@_key_name_tl {#2} }
+\cs_new_protected:Npn \@@_store_value_integer:n
+ { \@@_store_value_aux:Nn \int_eval:n }
+\cs_new_protected:Npn \@@_store_value_length:n
+ { \@@_store_value_aux:Nn \dim_eval:n }
+\cs_new_protected:Npn \@@_store_value_muskip:n
+ { \@@_store_value_aux:Nn \muskip_eval:n }
+\cs_new_protected:Npn \@@_store_value_real:n
+ { \@@_store_value_aux:Nn \fp_eval:n }
+\cs_new_protected:Npn \@@_store_value_skip:n
+ { \@@_store_value_aux:Nn \skip_eval:n }
+\cs_new_protected:Npn \@@_store_value_tokenlist:n
+ { \@@_store_value_aux:Nn \use:n }
+\cs_new_eq:NN \@@_store_value_commalist:n \@@_store_value_tokenlist:n
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Implementation part of template declaration}
+%
+% \begin{macro}{\@@_declare_template_code:nnnnn}
+% \begin{macro}{\@@_declare_template_code:nnnn}
+% The main function for implementing a template starts with a couple of
+% simple checks to make sure that there are no obvious mistakes: the
+% number of arguments must agree and the template keys must have been
+% declared.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_template_code:nnnnn #1#2#3#4#5
+ {
+ \@@_execute_if_type_exist:nT {#1}
+ {
+ \@@_execute_if_arg_agree:nnT {#1} {#3}
+ {
+ \@@_if_keys_exist:nnT {#1} {#2}
+ {
+ \@@_store_key_implementation:nnn {#1} {#2} {#4}
+ \regex_match:nnTF { \c { AssignTemplateKeys } } {#5}
+ { \@@_declare_template_code:nnnn {#1} {#2} {#3} {#5} }
+ {
+ \@@_declare_template_code:nnnn
+ {#1} {#2} {#3} { \AssignTemplateKeys #5 }
+ }
+ }
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_declare_template_code:nnnn #1#2#3#4
+ {
+ \cs_if_exist:cT { \c_@@_code_root_tl #1 / #2 }
+ { \msg_info:nnnn { template } { declare-template-code } {#1} {#2} }
+ \cs_generate_from_arg_count:cNnn
+ { \c_@@_code_root_tl #1 / #2 }
+ \cs_gset_protected:Npn {#3} {#4}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_store_key_implementation:nnn}
+% Actually storing the implementation part of a template is quite easy
+% as it only requires the list of keys given to be turned into a
+% property list. There is also some error-checking to do, hence the need
+% to have the list of defined keytypes available. In certain cases
+% (when choices are involved) parsing the key results in changes to the
+% default values. That is why they are loaded and then saved again.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_store_key_implementation:nnn #1#2#3
+ {
+ \@@_recover_defaults:nn {#1} {#2}
+ \@@_recover_keytypes:nn {#1} {#2}
+ \prop_clear:N \l_@@_vars_prop
+ \keyval_parse:nnn
+ { \@@_parse_vars_elt:n } { \@@_parse_vars_elt:nnn { #1 / #2 } } {#3}
+ \@@_store_vars:nn {#1} {#2}
+ \prop_map_inline:Nn \l_@@_keytypes_prop
+ { \msg_error:nnnnn { template } { key-not-implemented } {##1} {#2} {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_vars_elt:n}
+% At the implementation stage, every key must have a value given. So
+% this is an error function.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_vars_elt:n #1
+ { \msg_error:nnn { template } { key-no-variable } {#1} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_vars_elt:nnn}
+% \begin{macro}{\@@_parse_vars_elt_aux:nn}
+% \begin{macro}{\@@_parse_vars_elt_aux:nw}
+% \begin{macro}{\@@_parse_vars_elt_aux:nnn, \@@_parse_vars_elt_aux:nne}
+% \begin{macro}{\@@_parse_vars_elt_key:nn}
+% The actual storage part here is very simple: the storage bin name
+% is placed into the property list. At the same time, a comparison is
+% made with the keytypes defined earlier: if there is a mismatch then
+% an error is raised.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_vars_elt:nnn #1#2#3
+ {
+ \tl_set:Ne \l_@@_key_name_tl
+ { \tl_trim_spaces:e { \tl_to_str:n {#2} } }
+ \prop_get:NVNTF \l_@@_keytypes_prop
+ \l_@@_key_name_tl
+ \l_@@_keytype_tl
+ {
+ \@@_split_keytype_arg:V \l_@@_keytype_tl
+ \@@_parse_vars_elt_aux:nn {#1} {#3}
+ \prop_remove:NV \l_@@_keytypes_prop \l_@@_key_name_tl
+ }
+ { \msg_error:nnn { template } { unknown-key } {#2} }
+ }
+% \end{macrocode}
+% Split off any leading \texttt{global} and they look for the way to
+% implement.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_vars_elt_aux:nn #1#2
+ {
+ \@@_parse_vars_elt_aux:nw {#1} #2 global global \s_@@_stop
+ }
+\cs_new_protected:Npn \@@_parse_vars_elt_aux:nw
+ #1#2 global #3 global #4 \s_@@_stop
+ {
+ \tl_if_blank:nTF {#4}
+ { \@@_parse_vars_elt_aux:nnn {#1} { } {#2} }
+ {
+ \tl_if_blank:nTF {#2}
+ {
+ \@@_parse_vars_elt_aux:nne
+ {#1} { global } { \tl_trim_spaces:n {#3} }
+ }
+ { \msg_error:nnn { template } { bad-variable } { #2 global #3 } }
+ }
+ }
+\cs_new_protected:Npn \@@_parse_vars_elt_aux:nnn #1#2#3
+ {
+ \str_case:VnF \l_@@_keytype_tl
+ {
+ { choice } { \@@_implement_choices:nn {#1} {#3} }
+ { function }
+ {
+ \cs_if_exist:NF #3
+ { \cs_new:Npn #3 { } }
+ \@@_parse_vars_elt_key:nn {#1}
+ {
+ .code:n =
+ {
+ \cs_generate_from_arg_count:NNnn
+ \exp_not:N #3
+ \exp_not:c
+ { cs_ \str_if_eq:nnT {#1} { global } { g } set:Npn }
+ { \exp_not:V \l_@@_keytype_arg_tl }
+ {##1}
+ }
+ }
+ \prop_put:NVn \l_@@_vars_prop
+ \l_@@_key_name_tl {#2#3}
+ }
+ { instance }
+ {
+ \@@_parse_vars_elt_key:nn {#1}
+ {
+ .code:n =
+ {
+ \exp_not:c
+ { cs_ \str_if_eq:nnT {#1} { global } { g } set:Npn }
+ \exp_not:N #3 { \UseInstance {##1} }
+ }
+ }
+ \prop_put:NVn \l_@@_vars_prop
+ \l_@@_key_name_tl {#2#3}
+ }
+ }
+ {
+ \tl_if_single:nTF {#3}
+ {
+ \cs_if_exist:NF #3
+ { \use:c { \@@_map_var_type: _new:N } #3 }
+ \@@_parse_vars_elt_key:nn {#1}
+ {
+ . \@@_map_var_type:
+ _ \str_if_eq:nnT {#1} { global } { g } set:N
+ = \exp_not:N #3
+ }
+ \prop_put:NVn \l_@@_vars_prop
+ \l_@@_key_name_tl {#2#3}
+ }
+ { \msg_error:nnn { template } { bad-variable } {#2#3} }
+ }
+ }
+\cs_generate_variant:Nn \@@_parse_vars_elt_aux:nnn { nne }
+\cs_new_protected:Npn \@@_parse_vars_elt_key:nn #1#2
+ {
+ \keys_define:ne { template / #1 }
+ { \l_@@_key_name_tl #2 }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_map_var_type:}
+% Turn a \enquote{friendly} variable type into an \texttt{expl3} one.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_var_type:
+ {
+ \str_case:Vn \l_@@_keytype_tl
+ {
+ { boolean } { bool }
+ { commalist } { clist }
+ { integer } { int }
+ { length } { dim }
+ { muskip } { muskip }
+ { real } { fp }
+ { skip } { skip }
+ { tokenlist } { tl }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_implement_choices:nn}
+% \begin{macro}{\@@_implement_choices_default:}
+% Implementing choices requires a second key--value loop. So after a
+% little set-up, the standard parser is called.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_implement_choices:nn #1#2
+ {
+ \clist_set:NV \l_@@_tmp_clist \l_@@_keytype_arg_tl
+ \prop_put:NVn \l_@@_vars_prop \l_@@_key_name_tl { }
+ \keys_define:ne { template / #1 } { \l_@@_key_name_tl .choice: }
+ \keyval_parse:nnn
+ { \@@_implement_choice_elt:n }
+ { \@@_implement_choice_elt:nnn {#1} }
+ {#2}
+ \prop_get:NVNT \l_@@_values_prop \l_@@_key_name_tl
+ \l_@@_tmp_tl
+ { \@@_implement_choices_default: }
+ \clist_if_empty:NF \l_@@_tmp_clist
+ {
+ \clist_map_inline:Nn \l_@@_tmp_clist
+ { \msg_error:nnn { template } { choice-not-implemented } {##1} }
+ }
+ }
+% \end{macrocode}
+% A sanity check for the default value, so that an error is raised
+% now and not when converting to assignments.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_implement_choices_default:
+ {
+ \tl_set:Ne \l_@@_tmp_tl
+ { \l_@@_key_name_tl \c_space_tl \l_@@_tmp_tl }
+ \prop_if_in:NVF \l_@@_vars_prop \l_@@_tmp_tl
+ {
+ \tl_set:Ne \l_@@_tmp_tl
+ { \l_@@_key_name_tl \c_space_tl \l_@@_tmp_tl }
+ \prop_if_in:NVF \l_@@_vars_prop \l_@@_tmp_tl
+ {
+ \prop_get:NVN \l_@@_keytypes_prop \l_@@_key_name_tl
+ \l_@@_tmp_tl
+ \@@_split_keytype_arg:V \l_@@_tmp_tl
+ \prop_get:NVN \l_@@_values_prop \l_@@_key_name_tl
+ \l_@@_tmp_tl
+ \msg_error:nnVV { template } { unknown-default-choice }
+ \l_@@_key_name_tl
+ \l_@@_key_name_tl
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_implement_choice_elt:nnn, \@@_implement_choice_elt_aux:nnn}
+% \begin{macro}{\@@_implement_choice_elt_aux:n}
+% \begin{macro}{\@@_implement_choice_elt:n}
+% The actual storage of the implementation of a choice is mainly about
+% error checking. The code here ensures that all choices have to have
+% been declared, apart from the special \texttt{unknown} choice, which
+% must come last. The code for each choice is stored along with the
+% key name in the variables property list.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_implement_choice_elt:nnn #1#2#3
+ {
+ \clist_if_empty:NTF \l_@@_tmp_clist
+ {
+ \str_if_eq:nnTF {#2} { unknown }
+ { \@@_implement_choice_elt_aux:nnn {#1} {#2} {#3} }
+ { \@@_implement_choice_elt_aux:n {#2} }
+ }
+ {
+ \clist_if_in:NnTF \l_@@_tmp_clist {#2}
+ {
+ \clist_remove_all:Nn \l_@@_tmp_clist {#2}
+ \@@_implement_choice_elt_aux:nnn {#1} {#2} {#3}
+ }
+ { \@@_implement_choice_elt_aux:n {#2} }
+ }
+ }
+\cs_new_protected:Npn \@@_implement_choice_elt_aux:n #1
+ {
+ \prop_get:NVN \l_@@_keytypes_prop \l_@@_key_name_tl
+ \l_@@_tmp_tl
+ \@@_split_keytype_arg:V \l_@@_tmp_tl
+ \msg_error:nnVn { template } { unknown-choice } \l_@@_key_name_tl {#1}
+ }
+\cs_new_protected:Npn \@@_implement_choice_elt_aux:nnn #1#2#3
+ {
+ \keys_define:ne { template / #1 }
+ { \l_@@_key_name_tl / #2 .code:n = { \exp_not:n {#3} } }
+ \tl_set:Ne \l_@@_tmp_tl
+ { \l_@@_key_name_tl \c_space_tl #2 }
+ \prop_put:NVn \l_@@_vars_prop \l_@@_tmp_tl {#3}
+ }
+\cs_new_protected:Npn \@@_implement_choice_elt:n #1
+ {
+ \msg_error:nnVn { template } { choice-requires-code }
+ \l_@@_key_name_tl {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Editing template defaults}
+%
+% \begin{macro}{\@@_edit_defaults:nnn}
+% Editing the template defaults means getting the values back out
+% of the store, then parsing the list of new values before putting
+% the updated list back into storage.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_edit_defaults:nnn #1#2#3
+ {
+ \@@_if_keys_exist:nnT {#1} {#2}
+ {
+ \@@_recover_defaults:nn {#1} {#2}
+ \@@_parse_values:nnn {#1} {#2} {#3}
+ \@@_store_defaults:nn {#1} {#2}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_values:nnn}
+% The routine to parse values is the same for both editing a
+% template and setting up an instance. So the code here does only the
+% minimum necessary for reading the values.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_values:nnn #1#2#3
+ {
+ \@@_recover_keytypes:nn {#1} {#2}
+ \keyval_parse:NNn
+ \@@_parse_values_elt:n \@@_parse_values_elt:nn {#3}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_values_elt:n}
+% Every key needs a value, so this is just an error routine.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_values_elt:n #1
+ {
+ \bool_set_true:N \l_@@_error_bool
+ \msg_error:nnn { template } { key-no-value } {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_values_elt:nn}
+% \begin{macro}{\@@_parse_values_elt_aux:n}
+% To store the value, find the keytype then call the saving function.
+% These need the current key name saved as \cs{l_@@_key_name_tl}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_values_elt:nn #1#2
+ {
+ \tl_set:Ne \l_@@_key_name_tl
+ { \tl_trim_spaces:e { \tl_to_str:n {#1} } }
+ \prop_get:NVNTF \l_@@_keytypes_prop \l_@@_key_name_tl
+ \l_@@_tmp_tl
+ { \@@_parse_values_elt_aux:n {#2} }
+ { \msg_error:nnV { template } { unknown-key } \l_@@_key_name_tl }
+ }
+\cs_new_protected:Npn \@@_parse_values_elt_aux:n #1
+ {
+ \@@_split_keytype_arg:V \l_@@_tmp_tl
+ \use:c { @@_store_value_ \l_@@_keytype_tl :n } {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_template_set_eq:nnn}
+% To copy a template, each of the lists plus the code has to be copied
+% across. To keep this independent of the list storage system, it is
+% all done with two-part shuffles.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_template_set_eq:nnn #1#2#3
+ {
+ \@@_recover_defaults:nn {#1} {#3}
+ \@@_store_defaults:nn {#1} {#2}
+ \@@_recover_keytypes:nn {#1} {#3}
+ \@@_store_keytypes:nn {#1} {#2}
+ \@@_recover_vars:nn {#1} {#3}
+ \@@_store_vars:nn {#1} {#2}
+ \cs_if_exist:cT { \c_@@_code_root_tl #1 / #2 }
+ { \msg_info:nnnn { template } { declare-template-code } {#1} {#2} }
+ \cs_gset_eq:cc { \c_@@_code_root_tl #1 / #2 }
+ { \c_@@_code_root_tl #1 / #3 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Creating instances of templates}
+%
+% \begin{macro}
+% {
+% \@@_declare_instance:nnnn,
+% \@@_declare_instance_aux:nnnn
+% }
+% Making an instance has two distinct parts. First, the keys given are
+% parsed to transfer the values into the structured data format used
+% internally. This allows the default and given values to be combined
+% with no repetition. In the second step, the structured data is
+% converted to pre-defined variable assignments, and these are stored
+% in the function for the instance.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_instance:nnnn #1#2#3#4
+ {
+ \@@_execute_if_code_exist:nnT {#1} {#2}
+ {
+ \@@_recover_defaults:nn {#1} {#2}
+ \@@_recover_vars:nn {#1} {#2}
+ \@@_declare_instance_aux:nnnn {#1} {#2} {#3} {#4}
+ }
+ }
+\cs_new_protected:Npn \@@_declare_instance_aux:nnnn #1#2#3#4
+ {
+ \bool_set_false:N \l_@@_error_bool
+ \@@_parse_values:nnn {#1} {#2} {#4}
+ \bool_if:NF \l_@@_error_bool
+ {
+ \prop_put:Nnn \l_@@_values_prop { from~template } {#2}
+ \@@_store_values:nn {#1} {#3}
+ \@@_convert_to_assignments:
+ \cs_if_exist:cT { \c_@@_instances_root_tl #1 / #3 }
+ { \msg_info:nnnn { template } { declare-instance } {#3} {#1} }
+ \cs_set_protected:cpe { \c_@@_instances_root_tl #1 / #3 }
+ {
+ \exp_not:N \@@_assignments_push:n
+ { \exp_not:V \l_@@_assignments_tl }
+ \exp_not:c { \c_@@_code_root_tl #1 / #2 }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_instance_set_eq:nnn}
+% Copy--paste an instance.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_instance_set_eq:nnn #1#2#3
+ {
+ \@@_if_instance_exist:nnTF {#1} {#3}
+ {
+ \@@_recover_values:nn {#1} {#3}
+ \@@_store_values:nn {#1} {#2}
+ \cs_if_exist:cT { \c_@@_instances_root_tl #1 / #2 }
+ { \msg_info:nnnn { template } { declare-instance } {#2} {#1} }
+ \cs_set_eq:cc { \c_@@_instances_root_tl #1 / #2 }
+ { \c_@@_instances_root_tl #1 / #3 }
+ }
+ { \msg_error:nnnn { template } { unknown-instance } {#1} {#3} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_edit_instance:nnn}
+% \begin{macro}
+% {\@@_edit_instance_aux:nnnnn, \@@_edit_instance_aux:nVnnn}
+% Editing an instance is almost identical to declaring one. The only
+% variation is the source of the values to use. When editing, they are
+% recovered from the previous instance run.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_edit_instance:nnn #1#2#3
+ {
+ \@@_if_instance_exist:nnTF {#1} {#2}
+ {
+ \@@_recover_values:nn {#1} {#2}
+ \prop_get:NnN \l_@@_values_prop { from~template }
+ \l_@@_tmp_tl
+ \@@_edit_instance_aux:nVnn
+ {#1} \l_@@_tmp_tl {#2} {#3}
+ }
+ { \msg_error:nnnn { template } { unknown-instance } {#1} {#2} }
+ }
+\cs_new_protected:Npn \@@_edit_instance_aux:nnnn #1#2#3#4
+ {
+ \@@_recover_vars:nn {#1} {#2}
+ \@@_declare_instance_aux:nnnn {#1} {#2} {#3} {#4}
+ }
+\cs_generate_variant:Nn \@@_edit_instance_aux:nnnn { nV }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_convert_to_assignments:}
+% \begin{macro}{\@@_convert_to_assignments_aux:n}
+% \begin{macro}
+% {\@@_convert_to_assignments_aux:nn, \@@_convert_to_assignments_aux:nV}
+% The idea on converting to a set of assignments is to loop over each
+% key, so that the loop order follows the declaration order of the keys.
+% This is done using a sequence as property lists are not
+% \enquote{ordered}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_convert_to_assignments:
+ {
+ \tl_clear:N \l_@@_assignments_tl
+ \seq_map_function:NN \l_@@_key_order_seq
+ \@@_convert_to_assignments_aux:n
+ }
+\cs_new_protected:Npn \@@_convert_to_assignments_aux:n #1
+ {
+ \prop_get:NnN \l_@@_keytypes_prop {#1} \l_@@_tmp_tl
+ \@@_convert_to_assignments_aux:nV {#1} \l_@@_tmp_tl
+ }
+% \end{macrocode}
+% The second auxiliary function actually does the work. The
+% arguments here are the key name (|#1|) and the keytype (|#2|).
+% From those, the value to assign and the name of the appropriate
+% variable are recovered. A bit of work is then needed to sort out
+% keytypes with arguments (for example instances), and to look for
+% global assignments. Once that is done, a hand-off can be made to the
+% handler for the relevant keytype.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_convert_to_assignments_aux:nn #1#2
+ {
+ \prop_get:NnNT \l_@@_values_prop {#1} \l_@@_value_tl
+ {
+ \prop_get:NnNTF \l_@@_vars_prop {#1} \l_@@_var_tl
+ {
+ \@@_split_keytype_arg:n {#2}
+ \str_if_eq:VnF \l_@@_keytype_tl { choice }
+ {
+ \str_if_eq:VnF \l_@@_keytype_tl { code }
+ { \@@_find_global: }
+ }
+ \tl_set:Nn \l_@@_key_name_tl {#1}
+ \cs_if_exist_use:cF { @@_assign_ \l_@@_keytype_tl : }
+ { \@@_assign_variable: }
+ }
+ { \msg_error:nnn { template } { unknown-attribute } {#1} }
+ }
+ }
+\cs_generate_variant:Nn \@@_convert_to_assignments_aux:nn { nV }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_find_global:}
+% \begin{macro}{\@@_find_global_aux:w}
+% Global assignments should have the phrase |global| at the front.
+% This is pretty easy to find: no other error checking, though.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_find_global:
+ {
+ \bool_set_false:N \l_@@_global_bool
+ \tl_if_in:onT \l_@@_var_tl { global }
+ {
+ \exp_after:wN \@@_find_global_aux:w \l_@@_var_tl \s_@@_stop
+ }
+ }
+\cs_new_protected:Npn \@@_find_global_aux:w #1 global #2 \s_@@_stop
+ {
+ \tl_set:Nn \l_@@_var_tl {#2}
+ \bool_set_true:N \l_@@_global_bool
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Using templates directly}
+%
+% \begin{macro}{\@@_use_template:nnn}
+% Directly use a template with a particular parameter setting.
+% This is also picked up if used in a nested fashion inside a parameter
+% list. The idea is essentially the same as creating an instance,
+% just with no saving of the result.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_use_template:nnn #1#2#3
+ {
+ \@@_execute_if_code_exist:nnT {#1} {#2}
+ {
+ \@@_recover_defaults:nn {#1} {#2}
+ \@@_recover_vars:nn {#1} {#2}
+ \@@_parse_values:nnn {#1} {#2} {#3}
+ \@@_convert_to_assignments:
+ \use:c { \c_@@_code_root_tl #1 / #2 }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Assigning values to variables}
+%
+% \begin{macro}{\@@_assign_boolean:}
+% \begin{macro}{\@@_assign_boolean_aux:n}
+% Setting a Boolean value is slightly different to everything else
+% as the value can be used to work out which \texttt{set} function to
+% call. As long as there is no need to recover things from another
+% variable, everything is pretty easy. If there is, then we need to allow
+% for the fact that the recovered value here will \emph{not} be expandable,
+% so needs to be converted to something that is.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_assign_boolean:
+ {
+ \bool_if:NTF \l_@@_global_bool
+ { \@@_assign_boolean_aux:n { bool_gset } }
+ { \@@_assign_boolean_aux:n { bool_set } }
+ }
+\cs_new_protected:Npn \@@_assign_boolean_aux:n #1
+ {
+ \@@_if_key_value:VTF \l_@@_value_tl
+ {
+ \@@_key_to_value:
+ \tl_put_right:Ne \l_@@_assignments_tl
+ {
+ \exp_not:c { #1 _eq:NN }
+ \exp_not:V \l_@@_var_tl
+ \exp_not:V \l_@@_value_tl
+ }
+ }
+ {
+ \tl_put_right:Ne \l_@@_assignments_tl
+ {
+ \exp_not:c { #1 _ \l_@@_value_tl :N }
+ \exp_not:V \l_@@_var_tl
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_assign_choice:}
+% \begin{macro}
+% {\@@_assign_choice_aux:nF, \@@_assign_choice_aux:eF}
+% The idea here is to find either the choice as-given or else the
+% special |unknown| choice, and to copy the appropriate code across.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_assign_choice:
+ {
+ \@@_assign_choice_aux:eF
+ { \l_@@_key_name_tl \c_space_tl \l_@@_value_tl }
+ {
+ \@@_assign_choice_aux:eF
+ { \l_@@_key_name_tl \c_space_tl unknown }
+ {
+ \prop_get:NVN \l_@@_keytypes_prop \l_@@_key_name_tl
+ \l_@@_tmp_tl
+ \@@_split_keytype_arg:V \l_@@_tmp_tl
+ \msg_error:nnVV { template } { unknown-choice }
+ \l_@@_key_name_tl
+ \l_@@_value_tl
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_assign_choice_aux:nF #1
+ {
+ \prop_get:NnNTF \l_@@_vars_prop {#1} \l_@@_tmp_tl
+ { \tl_put_right:NV \l_@@_assignments_tl \l_@@_tmp_tl }
+ }
+\cs_generate_variant:Nn \@@_assign_choice_aux:nF { e }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_assign_function:}
+% \begin{macro}{\@@_assign_function_aux:N}
+% This looks a bit messy but is only actually one function.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_assign_function:
+ {
+ \bool_if:NTF \l_@@_global_bool
+ { \@@_assign_function_aux:N \cs_gset:Npn }
+ { \@@_assign_function_aux:N \cs_set:Npn }
+ }
+\cs_new_protected:Npn \@@_assign_function_aux:N #1
+ {
+ \tl_put_right:Ne \l_@@_assignments_tl
+ {
+ \cs_generate_from_arg_count:NNnn
+ \exp_not:V \l_@@_var_tl
+ \exp_not:N #1
+ { \exp_not:V \l_@@_keytype_arg_tl }
+ { \exp_not:V \l_@@_value_tl }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_assign_instance:}
+% \begin{macro}{\@@_assign_instance_aux:N}
+% Using an instance means adding the appropriate function creation to
+% the tl. No checks are made at this stage, so if the instance is
+% not valid then errors will arise later.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_assign_instance:
+ {
+ \bool_if:NTF \l_@@_global_bool
+ { \@@_assign_instance_aux:N \cs_gset_protected:Npn }
+ { \@@_assign_instance_aux:N \cs_set_protected:Npn }
+ }
+\cs_new_protected:Npn \@@_assign_instance_aux:N #1
+ {
+ \tl_put_right:Ne \l_@@_assignments_tl
+ {
+ \exp_not:N #1 \exp_not:V \l_@@_var_tl
+ {
+ \@@_use_instance:nn
+ { \exp_not:V \l_@@_keytype_arg_tl }
+ { \exp_not:V \l_@@_value_tl }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_assign_variable:}
+% \begin{macro}{\@@_assign_variable:N, \@@_assign_variable:c}
+% A general-purpose function for all of the other assignments.
+% As long as the value is not coming from another variable, the stored
+% value is simply transferred for output.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_assign_variable:
+ {
+ \@@_assign_variable:c
+ {
+ \@@_map_var_type: _
+ \bool_if:NT \l_@@_global_bool { g } set:Nn
+ }
+ }
+\cs_new_protected:Npn \@@_assign_variable:N #1
+ {
+ \@@_if_key_value:VT \l_@@_value_tl
+ { \@@_key_to_value: }
+ \tl_put_right:Ne \l_@@_assignments_tl
+ {
+ #1 \exp_not:V \l_@@_var_tl
+ { \exp_not:V \l_@@_value_tl }
+ }
+ }
+\cs_generate_variant:Nn \@@_assign_variable:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_key_to_value:}
+% \begin{macro}{\@@_key_to_value_auxi:w}
+% \begin{macro}{\@@_key_to_value_auxii:w}
+% The idea here is to recover the attribute value of another key. To
+% do that, the marker is removed and a look up takes place. If this
+% is successful, then the name of the variable of the attribute is
+% returned. This assumes that the value will be used in context where
+% it will be converted to a value, for example when setting a number.
+% There is also a need to check in case the copied value happens to be
+% \texttt{global}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_key_to_value:
+ { \exp_after:wN \@@_key_to_value_auxi:w \l_@@_value_tl }
+\cs_new_protected:Npn \@@_key_to_value_auxi:w \KeyValue #1
+ {
+ \tl_set:Ne \l_@@_tmp_tl { \tl_trim_spaces:e { \tl_to_str:n {#1} } }
+ \prop_get:NVNTF \l_@@_vars_prop \l_@@_tmp_tl
+ \l_@@_value_tl
+ {
+ \exp_after:wN \@@_key_to_value_auxii:w \l_@@_value_tl
+ \s_@@_mark global \q_@@_nil \s_@@_stop
+ }
+ { \msg_error:nnV { template } { unknown-attribute } \l_@@_tmp_tl }
+ }
+\cs_new_protected:Npn \@@_key_to_value_auxii:w #1 global #2#3 \s_@@_stop
+ {
+ \@@_quark_if_nil:NF #2
+ { \tl_set:Nn \l_@@_value_tl {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Using instances}
+%
+% \begin{macro}{\@@_use_instance:nn}
+% \begin{macro}{\@@_use_instance_aux:nNnnn}
+% \begin{macro}{\@@_use_instance_aux:nn}
+% Using an instance is just a question of finding the appropriate function.
+% If nothing is found, an error is raised. One complication is that
+% if the first token of argument |#2| is \cs{UseTemplate} then that
+% is also valid. There is an error-test to make sure that the
+% types agree, and if so the template is used directly.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_use_instance:nn #1#2
+ {
+ \@@_if_use_template:nTF {#2}
+ { \@@_use_instance_aux:nNnnn {#1} #2 }
+ { \@@_use_instance_aux:nn {#1} {#2} }
+ }
+\cs_new_protected:Npn \@@_use_instance_aux:nNnnn #1#2#3#4#5
+ {
+ \str_if_eq:nnTF {#1} {#3}
+ { \@@_use_template:nnn {#3} {#4} {#5} }
+ { \msg_error:nnnn { template } { type-mismatch } {#1} {#3} }
+}
+\cs_new_protected:Npn \@@_use_instance_aux:nn #1#2
+ {
+ \@@_if_instance_exist:nnTF {#1} {#2}
+ { \use:c { \c_@@_instances_root_tl #1 / #2 } }
+ { \msg_error:nnnn { template } { unknown-instance } {#1} {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%\subsection{Assignment manipulation}
+%
+% A few functions to transfer assignments about, as this is needed by
+% \cs{AssignTemplateKeys}.
+%
+% \begin{macro}{\@@_assignments_pop:}
+% To actually use the assignments.
+% \begin{macrocode}
+\cs_new:Npn \@@_assignments_pop: { \l_@@_assignments_tl }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_assignments_push:n}
+% Here, the assignments are stored for later use.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_assignments_push:n #1
+ { \tl_set:Nn \l_@@_assignments_tl {#1} }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Showing templates and instances}
+%
+% \begin{macro}{\@@_show_code:nn}
+% Showing the code for a template is just a translation of
+% \cs{cs_show:c}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_code:nn #1#2
+ { \cs_show:c { \c_@@_code_root_tl #1 / #2 } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_show_defaults:nn,
+% \@@_show_keytypes:nn,
+% \@@_show_vars:nn
+% }
+% \begin{macro}{\@@_show:Nnnn}
+% A modified version of the property-list printing code, such that
+% the output refers to templates and instances rather than to the
+% underlying structures.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_defaults:nn #1#2
+ {
+ \@@_if_keys_exist:nnT {#1} {#2}
+ {
+ \@@_recover_defaults:nn {#1} {#2}
+ \@@_show:Nnnn \l_@@_values_prop
+ {#1} {#2} { default~values }
+ }
+ }
+\cs_new_protected:Npn \@@_show_keytypes:nn #1#2
+ {
+ \@@_if_keys_exist:nnT {#1} {#2}
+ {
+ \@@_recover_keytypes:nn {#1} {#2}
+ \@@_show:Nnnn \l_@@_keytypes_prop
+ {#1} {#2} { interface }
+ }
+ }
+\cs_new_protected:Npn \@@_show_vars:nn #1#2
+ {
+ \@@_execute_if_code_exist:nnT {#1} {#2}
+ {
+ \@@_recover_vars:nn {#1} {#2}
+ \@@_show:Nnnn \l_@@_vars_prop
+ {#1} {#2} { variable~mapping }
+ }
+ }
+\cs_new_protected:Npn \@@_show:Nnnn #1#2#3#4
+ {
+ \msg_show:nneeee { template } { show-attribute }
+ { \tl_to_str:n {#2} }
+ { \tl_to_str:n {#3} }
+ { \tl_to_str:n {#4} }
+ { \prop_map_function:NN #1 \msg_show_item_unbraced:nn }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_show_values:nn}
+% Instance values are a little more complex, as is the template to consider.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_values:nn #1#2
+ {
+ \@@_if_instance_exist:nnT {#1} {#2}
+ {
+ \@@_recover_values:nn {#1} {#2}
+ \msg_show:nneee { template } { show-values }
+ { \tl_to_str:n {#1} }
+ { \tl_to_str:n {#2} }
+ {
+ \prop_map_function:NN \l_@@_values_prop
+ \msg_show_item_unbraced:nn
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+% The text for error messages: short and long text for all of them.
+% \begin{macrocode}
+\msg_new:nnnn { template } { argument-number-mismatch }
+ { Template~type~'#1'~takes~#2~argument(s). }
+ {
+ Templates~of~type~'#1'~require~#2~argument(s).\\
+ You~have~tried~to~make~a~template~for~'#1'~
+ with~#3~argument(s),~which~is~not~possible:~
+ the~number~of~arguments~must~agree.
+ }
+\msg_new:nnnn { template } { bad-number-of-arguments }
+ { Bad~number~of~arguments~for~template~type~'#1'. }
+ {
+ A~template~may~accept~between~0~and~9~arguments.\\
+ You~asked~to~use~#2~arguments:~this~is~not~supported.
+ }
+\msg_new:nnnn { template } { bad-variable }
+ { Incorrect~variable~description~'#1'. }
+ {
+ The~argument~'#1'~is~not~of~the~form \\
+ ~~'<variable>'\\
+ ~or~\\
+ ~~'global~<variable>'.\\
+ It~must~be~given~in~one~of~these~formats~to~be~used~in~a~template.
+ }
+\msg_new:nnnn { template } { choice-not-implemented }
+ { The~choice~'#1'~has~no~implementation. }
+ {
+ Each~choice~listed~in~the~interface~for~a~template~must~
+ have~an~implementation.
+ }
+\msg_new:nnnn { template } { choice-no-code }
+ { The~choice~'#1'~requires~implementation~details. }
+ {
+ When~creating~template~code~using~\DeclareTemplateCode,~
+ each~choice~name~must~have~an~associated~implementation.\\
+ This~should~be~given~after~a~'='~sign:~LaTeX~did~not~find~one.
+ }
+\msg_new:nnnn { template } { choice-requires-code }
+ { The~choice~'#2'~for~key~'#1'~requires~an~implementation. }
+ {
+ You~should~have~put:\\
+ \ \ #1~:~choice~{~#2 = <code> ~} \\
+ but~LaTeX~did~not~find~any~<code>.
+ }
+\msg_new:nnnn { template } { duplicate-key-interface }
+ { Key~'#1'~appears~twice~in~interface~definition~\msg_line_context:. }
+ {
+ Each~key~can~only~have~one~interface~declared~in~a~template.\\
+ LaTeX~found~two~interfaces~for~'#1'.
+ }
+\msg_new:nnnn { template } { keytype-requires-argument }
+ { The~key~type~'#1'~requires~an~argument~\msg_line_context:. }
+ {
+ You~should~have~put:\\
+ \ \ <key-name>~:~#1~{~<argument>~} \\
+ but~LaTeX~did~not~find~an~<argument>.
+ }
+\msg_new:nnnn { template } { invalid-keytype }
+ { The~key~'#1'~is~missing~a~key-type~\msg_line_context:. }
+ {
+ Each~key~in~a~template~requires~a~key-type,~given~in~the~form:\\
+ \ \ <key>~:~<key-type>\\
+ LaTeX~could~not~find~a~<key-type>~in~your~input.
+ }
+\msg_new:nnnn { template } { key-no-value }
+ { The~key~'#1'~has~no~value~\msg_line_context:. }
+ {
+ When~creating~an~instance~of~a~template~
+ every~key~listed~must~include~a~value:\\
+ \ \ <key>~=~<value>
+ }
+\msg_new:nnnn { template } { key-no-variable }
+ { The~key~'#1'~requires~implementation~details~\msg_line_context:. }
+ {
+ When~creating~template~code~using~\DeclareTemplateCode,~
+ each~key~name~must~have~an~associated~implementation.\\
+ This~should~be~given~after~a~'='~sign:~LaTeX~did~not~find~one.
+ }
+\msg_new:nnnn { template } { key-not-implemented }
+ { Key~'#1'~has~no~implementation~\msg_line_context:. }
+ {
+ The~definition~of~key~implementations~for~template~'#2'~
+ of~template~type~'#3'~does~not~include~any~details~for~key~'#1'.\\
+ The~key~was~declared~in~the~interface~definition,~
+ and~so~an~implementation~is~required.
+ }
+\msg_new:nnnn { template } { missing-keytype }
+ { The~key~'#1'~is~missing~a~key-type~\msg_line_context:. }
+ {
+ Key~interface~definitions~should~be~of~the~form\\
+ \ \ #1~:~<key-type>\\
+ but~LaTeX~could~not~find~a~<key-type>.
+ }
+\msg_new:nnnn { template } { no-template-code }
+ {
+ The~template~'#2'~of~type~'#1'~is~unknown~
+ or~has~no~implementation.
+ }
+ {
+ There~is~no~code~available~for~the~template~name~given.\\
+ This~should~be~given~using~\DeclareTemplateCode.
+ }
+\msg_new:nnnn { template } { type-already-defined }
+ { Template~type~'#1'~already~defined. }
+ {
+ You~have~used~\NewTemplateType~
+ with~a~template~type~that~has~already~been~defined.
+ }
+\msg_new:nnnn { template } { type-mismatch }
+ { Template~types~'#1'~and~'#2'~do~not~agree. }
+ {
+ You~are~trying~to~use~a~template~directly~with~\UseInstance
+ (or~a~similar~function),~but~the~template~types~do~not~match.
+ }
+\msg_new:nnnn { template } { unknown-attribute }
+ { The~template~attribute~'#1'~is~unknown. }
+ {
+ There~is~a~definition~in~the~current~template~reading\\
+ \ \ \token_to_str:N \KeyValue {~#1~} \\
+ but~there~is~no~key~called~'#1'.
+ }
+\msg_new:nnnn { template } { unknown-choice }
+ { The~choice~'#2'~was~not~declared~for~key~'#1'. }
+ {
+ The~key~'#1'~takes~a~fixed~list~of~choices~
+ and~this~list~does~not~include~'#2'.
+ }
+\msg_new:nnnn { template } { unknown-default-choice }
+ { The~default~choice~'#2'~was~not~declared~for~key~'#1'. }
+ {
+ The~key~'#1'~takes~a~fixed~list~of~choices~
+ and~this~list~does~not~include~'#2'.
+ }
+\msg_new:nnnn { template } { unknown-instance }
+ { The~instance~'#2'~of~type~'#1'~is~unknown. }
+ {
+ You~have~asked~to~use~an~instance~'#2',~
+ but~this~has~not~been~created.
+ }
+\msg_new:nnnn { template } { unknown-key }
+ { Unknown~template~key~'#1'. }
+ {
+ The~key~'#1'~was~not~declared~in~the~interface~
+ for~the~current~template.
+ }
+\msg_new:nnnn { template } { unknown-keytype }
+ { The~key-type~'#1'~is~unknown. }
+ {
+ Valid~key-types~are:\\
+ -~boolean;\\
+ -~choice;\\
+ -~commalist;\\
+ -~function;\\
+ -~instance;\\
+ -~integer;\\
+ -~length;\\
+ -~muskip;\\
+ -~real;\\
+ -~skip;\\
+ -~tokenlist.
+ }
+\msg_new:nnnn { template } { unknown-type }
+ { The~template~type~'#1'~is~unknown. }
+ {
+ A~template~type~needs~to~be~defined~with~\NewTemplateType
+ prior~to~using~it.
+ }
+\msg_new:nnnn { template } { unknown-template }
+ { The~template~'#2'~of~type~'#1'~is~unknown. }
+ {
+ No~interface~has~been~declared~for~a~template~
+ '#2'~of~template~type~'#1'.
+ }
+% \end{macrocode}
+%
+% Information messages only have text: more text should not be needed.
+% \begin{macrocode}
+\msg_new:nnn { template } { declare-instance }
+ { Declaring~instance~~'#1'~of~type~#2~\msg_line_context:. }
+\msg_new:nnn { template } { declare-template-code }
+ { Declaring~code~for~template~'#2'~of~template~type~'#1'~\msg_line_context:. }
+\msg_new:nnn { template } { declare-template-interface }
+ {
+ Declaring~interface~for~template~'#2'~of~template~type~'#1'~
+ \msg_line_context:.
+ }
+\msg_new:nnn { template } { declare-type }
+ { Declaring~template~type~'#1'~taking~#2~argument(s)~\msg_line_context:. }
+\msg_new:nnn { template } { show-attribute }
+ {
+ The~template~'#2'~of~type~'#1'~has~
+ \tl_if_empty:nTF {#4} { no~#3. } { #3 : #4 }
+ }
+\msg_new:nnn { template } { show-values }
+ {
+ The~instance~'#2'~of~type~'#1'~has~
+ \tl_if_empty:nTF {#3} { no~values. } { values: #3 }
+ }
+% \end{macrocode}
+%
+% Also add \pkg{template} to the \pkg{LaTeX} messages.
+% \begin{macrocode}
+\prop_gput:Nnn \g_msg_module_type_prop { template } { LaTeX }
+% \end{macrocode}
+%
+% \subsection{User functions}
+%
+% \begin{macro}{\NewTemplateType}
+% \begin{macro}{\DeclareTemplateInterface}
+% \begin{macro}{\DeclareTemplateCode}
+% \begin{macro}{\DeclareTemplateCopy}
+% \begin{macro}{\EditTemplateDefaults}
+% \begin{macro}{\UseTemplate}
+% \begin{macro}{\DeclareInstance}
+% \begin{macro}{\DeclareInstanceCopy}
+% \begin{macro}{\EditInstance}
+% \begin{macro}{\UseInstance}
+% All simple translations.
+% \begin{macrocode}
+\cs_new_protected:Npn \NewTemplateType #1#2
+ { \@@_define_type:nn {#1} {#2} }
+\cs_new_protected:Npn \DeclareTemplateInterface #1#2#3#4
+ { \@@_declare_template_keys:nnnn {#1} {#2} {#3} {#4} }
+\cs_new_protected:Npn \DeclareTemplateCode #1#2#3#4#5
+ { \@@_declare_template_code:nnnnn {#1} {#2} {#3} {#4} {#5} }
+\cs_new_protected:Npn \DeclareTemplateCopy #1#2#3
+ { \@@_template_set_eq:nnn {#1} {#2} {#3} }
+\cs_new_protected:Npn \EditTemplateDefaults #1#2#3
+ { \@@_edit_defaults:nnn {#1} {#2} {#3} }
+\cs_new_protected:Npn \UseTemplate #1#2#3
+ { \@@_use_template:nnn {#1} {#2} {#3} }
+\cs_new_protected:Npn \DeclareInstance #1#2#3#4
+ { \@@_declare_instance:nnnn {#1} {#3} {#2} {#4} }
+\cs_new_protected:Npn \DeclareInstanceCopy #1#2#3
+ { \@@_instance_set_eq:nnn {#1} {#2} {#3} }
+\cs_new_protected:Npn \EditInstance #1#2#3
+ { \@@_edit_instance:nnn {#1} {#2} {#3} }
+\cs_new_protected:Npn \UseInstance #1#2
+ { \@@_use_instance:nn {#1} {#2} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ShowTemplateCode}
+% \begin{macro}{\ShowTemplateDefaults}
+% \begin{macro}{\ShowTemplateInterface}
+% \begin{macro}{\ShowTemplateVariables}
+% \begin{macro}{\ShowInstanceValues}
+% The show functions are again just translation.
+% \begin{macrocode}
+\cs_new_protected:Npn \ShowTemplateCode #1#2
+ { \@@_show_code:nn {#1} {#2} }
+\cs_new_protected:Npn \ShowTemplateDefaults #1#2
+ { \@@_show_defaults:nn {#1} {#2} }
+\cs_new_protected:Npn \ShowTemplateInterface #1#2
+ { \@@_show_keytypes:nn {#1} {#2} }
+\cs_new_protected:Npn \ShowTemplateVariables #1#2
+ { \@@_show_vars:nn {#1} {#2} }
+\cs_new_protected:Npn \ShowInstanceValues #1#2
+ { \@@_show_values:nn {#1} {#2} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\IfInstanceExistsT, \IfInstanceExistsF, \IfInstanceExistsTF}
+% \changes{2024-02-15}{v1.0b}{New macros}
+% \changes{2024-04-17}{v1.0c}{Use plural names}
+% More direct translation.
+% \begin{macrocode}
+\cs_new:Npn \IfInstanceExistsTF #1#2
+ { \@@_if_instance_exist:nnTF {#1} {#2} }
+\cs_new:Npn \IfInstanceExistsT #1#2
+ { \@@_if_instance_exist:nnT {#1} {#2} }
+\cs_new:Npn \IfInstanceExistsF #1#2
+ { \@@_if_instance_exist:nnF {#1} {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KeyValue}
+% Simply dump the argument when executed: this should not happen.
+% \begin{macrocode}
+\cs_new_protected:Npn \KeyValue #1 {#1}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\AssignTemplateKeys}
+% A short call to use a token register by proxy.
+% \begin{macrocode}
+\cs_new_protected:Npn \AssignTemplateKeys { \@@_assignments_pop: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\SetTemplateKeys}
+% A friendly wrapper
+% \begin{macrocode}
+\cs_new_protected:Npn \SetTemplateKeys #1#2#3
+ { \keys_set_known:nnN { template / #1 / #2 } {#3} \l_@@_tmp_clist }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}{lttemplates}%
+%<latexrelease> {Prototype~document~commands}%
+%<latexrelease>
+%<latexrelease>\EndModuleRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% We need to stop DocStrip treating |@@| in a special way at this point.
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \Finale \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/base/lttextcomp.dtx b/Master/texmf-dist/source/latex/base/lttextcomp.dtx
index 5de3797f79b..7f247747d6a 100644
--- a/Master/texmf-dist/source/latex/base/lttextcomp.dtx
+++ b/Master/texmf-dist/source/latex/base/lttextcomp.dtx
@@ -37,7 +37,7 @@
%
%
\ProvidesFile{lttextcomp.dtx}
- [2022/08/07 v1.0g LaTeX Kernel (text companion symbols)]
+ [2024/04/24 v1.1c LaTeX Kernel (text companion symbols)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -163,11 +163,12 @@
%
% \begin{macro}{\DeclareEncodingSubset}
%
-% The declaration takes 3 mandatory arguments: an \emph{encoding}
+% The declaration takes 3 mandatory arguments: an \emph{encoding}
% for which a subsetting is wanted (currently always \texttt{TS1},
% and most likely forever), the \emph{font family} for which we
-% declare the subset and finally the \emph{subset} number (between \texttt{0} (all
-% of the encoding is supported) and \texttt{9} many glyphs are missing.
+% declare the subset and finally the \emph{subset} number, with a value between
+% \texttt{0} (all of the encoding is supported) and \texttt{9} (many
+% glyphs are missing).
%
% For \texttt{TS1} the numbers have been chosen in a way that most
% fonts can be fairly correctly categorized, but the default
@@ -439,7 +440,7 @@
% \end{macrocode}
%
% And here are the other \texttt{TS1} glyphs that are implemented
-% by every font (or nearly every---a few are commented out and
+% by every font (or nearly every)---a few are commented out and
% moved to sub-encoding 9,
% because they aren't around in some fonts.
% \begin{macrocode}
@@ -950,6 +951,8 @@
% This first block contains the fonts that have been already
% supported by the \texttt{textcomp} package way back, i.e., the
% font families that have \TeX{} support since the mid-nineties.
+% \changes{v1.1a}{2024/01/27}{Adjusted/corrected TS1 sub-encoding
+% declarations for various families (gh/1257)}
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{ccr} {0}
\DeclareEncodingSubset{TS1}{cmbr} {0}
@@ -981,16 +984,28 @@
\DeclareEncodingSubset{TS1}{lmss} {1}
\DeclareEncodingSubset{TS1}{lmssq} {1}
\DeclareEncodingSubset{TS1}{lmvtt} {1}
-\DeclareEncodingSubset{TS1}{lmtt} {1} % missing TM, SM and
- % pertenthousand for some reason
+% \end{macrocode}
+% The lmtt family is missing TM, SM, and perthousand for some
+% reason, so the first safe sub-encoding would be 2, but that is
+% then missing out a huge number of glyphs that are available, so
+% we claim it is sub-encoding 1 even if this can lead to missing glyphs.
+% \begin{macrocode}
+\DeclareEncodingSubset{TS1}{lmtt} {1} % missing TM, SM and pertenthousand
% \end{macrocode}
%
+% The next three families have been removed from TeX Live, but we
+% keep the definitions
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{ptmx} {2}
\DeclareEncodingSubset{TS1}{ptmj} {2}
\DeclareEncodingSubset{TS1}{ul8} {2}
% \end{macrocode}
%
+% The next set are the early PostScript font implementations, these
+% days there are better alternatives, but \ldots. Note that, their
+% virtual fonts contain a lot of ``tofu'' in form of black squares,
+% thus they don't even give a missing character warning if you
+% select such a glyph. This is why they are set as sub-encoding 5.
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{bch} {5} % tofu for blank, ohm
\DeclareEncodingSubset{TS1}{futj}{5} % tofu for blank, interrobang/down, ohm
@@ -1009,12 +1024,11 @@
\DeclareEncodingSubset{TS1}{ul9} {5} % tofu for blank, interrobang/down, ohm
% \end{macrocode}
%
+% The next set suffers from the same problem and they contain even
+% fewer real glyphs.
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{dayroms}{6} % tofu for blank, interrobang/down, ohm
\DeclareEncodingSubset{TS1}{dayrom} {6} % tofu for blank, interrobang/down, ohm
-% \end{macrocode}
-%
-% \begin{macrocode}
\DeclareEncodingSubset{TS1}{augie}{8} % really only missing euro
\DeclareEncodingSubset{TS1}{put} {8}
\DeclareEncodingSubset{TS1}{uag} {8} % probably (currently broken distrib)
@@ -1024,6 +1038,7 @@
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{zi4} {9}
% \end{macrocode}
+%
% LucidaBright (sold through TUG) probably not quite correct, I
% guess as I have the older fonts \ldots
% \begin{macrocode}
@@ -1041,44 +1056,72 @@
% Below are the newer fonts that have support files for
% \LaTeX{}. With very few exceptions the classifications are done
% so that all characters are correctly produced (either being
-% available in the font or substituted.
+% available in the font or substituted).
%
% There are a few fonts that contain ``tofu'' squares in places
% (instead of a real glyph) and in a few cases some really seldom
% needed chars are unavailable, i.e., produce missing glyphs (to
% avoid that a large number of available chars are unnecessarily
-% substituted.
+% substituted).
%
+% Encoding declarations for these font families shouldn't really be
+% in the kernel, but part of the \texttt{.fd} files for the
+% family. When we introduced the concept in 2021 we had some hope
+% that this would happen over time and that we could take the
+% declarations out---after all it is nearly impossible to maintain
+% it correctly in the kernel, given that fonts may get new glyphs
+% added (happened for several of them in the recent year) which is
+% something we wouldn't notice. However, so far this hasn't
+% happened, so in 2024, I went through the current set and adjusted
+% the declarations in several places.
+%
+% Next four are wrong and still need adjustment:
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{lato-*} {0} % with a bunch of tofu inside
\DeclareEncodingSubset{TS1}{opensans-*} {0} % with a bunch of tofu inside
\DeclareEncodingSubset{TS1}{cantarell-*} {0} % with a bunch of tofu inside
-\DeclareEncodingSubset{TS1}{fbb-*} {0} % missing centoldstyle
+\DeclareEncodingSubset{TS1}{tli} {1} % with lots of tofu inside
% \end{macrocode}
%
% \begin{macrocode}
-\DeclareEncodingSubset{TS1}{tli} {1} % with lots of tofu inside
+\DeclareEncodingSubset{TS1}{fbb-*} {2} % missing centoldstyle
% \end{macrocode}
%
+%
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{Alegreya-*} {2}
\DeclareEncodingSubset{TS1}{AlegreyaSans-*} {2}
+\DeclareEncodingSubset{TS1}{BaskervilleF-*} {2}
\DeclareEncodingSubset{TS1}{DejaVuSans-TLF} {2}
\DeclareEncodingSubset{TS1}{DejaVuSansCondensed-TLF} {2}
+% \end{macrocode}
+% Next one is missing \cs{textfractionsolidus} but is otherwise
+% completely sub-encoding 2 so we use that sub-encoding.
+% \begin{macrocode}
\DeclareEncodingSubset{TS1}{DejaVuSansMono-TLF} {2}
+% \end{macrocode}
+%
+% \begin{macrocode}
\DeclareEncodingSubset{TS1}{EBGaramond-*} {2}
+\DeclareEncodingSubset{TS1}{Merriwthr-OsF} {2}
+\DeclareEncodingSubset{TS1}{MerriwthrSans-OsF} {2}
+\DeclareEncodingSubset{TS1}{Montserrat-*} {2}
+\DeclareEncodingSubset{TS1}{MontserratAlternates-*} {2}
+\DeclareEncodingSubset{TS1}{NotoSansMono-TLF} {2}
+\DeclareEncodingSubset{TS1}{NotoSansMono-TOsF} {2}
\DeclareEncodingSubset{TS1}{Tempora-TLF} {2}
\DeclareEncodingSubset{TS1}{Tempora-TOsF} {2}
+\DeclareEncodingSubset{TS1}{XCharter-TLF} {2}
+\DeclareEncodingSubset{TS1}{XCharter-TOsF} {2}
+\DeclareEncodingSubset{TS1}{erewhon-*} {2}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{Arimo-TLF} {3}
-\DeclareEncodingSubset{TS1}{Carlito-*} {3}
-\DeclareEncodingSubset{TS1}{FiraSans-*} {3}
+\DeclareEncodingSubset{TS1}{Crlt-*} {3}
+\DeclareEncodingSubset{TS1}{IBMPlexMono-TLF} {3}
\DeclareEncodingSubset{TS1}{IBMPlexSans-TLF} {3}
-\DeclareEncodingSubset{TS1}{Merriweather-OsF} {3}
-\DeclareEncodingSubset{TS1}{Montserrat-*} {3}
-\DeclareEncodingSubset{TS1}{MontserratAlternates-*} {3}
+\DeclareEncodingSubset{TS1}{IBMPlexSerif-TLF} {3}
\DeclareEncodingSubset{TS1}{SourceCodePro-TLF} {3}
\DeclareEncodingSubset{TS1}{SourceCodePro-TOsF} {3}
\DeclareEncodingSubset{TS1}{SourceSansPro-*} {3}
@@ -1096,6 +1139,7 @@
\DeclareEncodingSubset{TS1}{CrimsonPro-*} {4}
\DeclareEncodingSubset{TS1}{FiraMono-TLF} {4}
\DeclareEncodingSubset{TS1}{FiraMono-TOsF} {4}
+\DeclareEncodingSubset{TS1}{FiraSans-*} {4}
\DeclareEncodingSubset{TS1}{Go-TLF} {4}
\DeclareEncodingSubset{TS1}{GoMono-TLF} {4}
\DeclareEncodingSubset{TS1}{InriaSans-*} {4}
@@ -1108,7 +1152,6 @@
\DeclareEncodingSubset{TS1}{LinguisticsPro-OsF} {4}
\DeclareEncodingSubset{TS1}{LinuxBiolinumT-*} {4}
\DeclareEncodingSubset{TS1}{LinuxLibertineT-*} {4}
-\DeclareEncodingSubset{TS1}{MerriweatherSans-OsF} {4}
\DeclareEncodingSubset{TS1}{MintSpirit-*} {4}
\DeclareEncodingSubset{TS1}{MintSpiritNoTwo-*} {4}
\DeclareEncodingSubset{TS1}{PTMono-TLF} {4}
@@ -1128,66 +1171,64 @@
% \end{macrocode}
%
% \begin{macrocode}
-\DeclareEncodingSubset{TS1}{Almendra-OsF} {5}
+\DeclareEncodingSubset{TS1}{Almndr-OsF} {5}
\DeclareEncodingSubset{TS1}{Baskervaldx-*} {5}
-\DeclareEncodingSubset{TS1}{BaskervilleF-*} {5}
-\DeclareEncodingSubset{TS1}{Bitter-TLF} {5}
+\DeclareEncodingSubset{TS1}{Bttr-TLF} {5}
\DeclareEncodingSubset{TS1}{Cinzel-LF} {5}
\DeclareEncodingSubset{TS1}{CinzelDecorative-LF} {5}
+\DeclareEncodingSubset{TS1}{Cochineal-*} {5}
\DeclareEncodingSubset{TS1}{DejaVuSerif-TLF} {5}
\DeclareEncodingSubset{TS1}{DejaVuSerifCondensed-TLF} {5}
\DeclareEncodingSubset{TS1}{GilliusADF-LF} {5}
\DeclareEncodingSubset{TS1}{GilliusADFCond-LF} {5}
\DeclareEncodingSubset{TS1}{GilliusADFNoTwo-LF} {5}
\DeclareEncodingSubset{TS1}{GilliusADFNoTwoCond-LF} {5}
-\DeclareEncodingSubset{TS1}{LobsterTwo-LF} {5}
\DeclareEncodingSubset{TS1}{OldStandard-TLF} {5}
-\DeclareEncodingSubset{TS1}{PlayfairDisplay-TLF} {5}
-\DeclareEncodingSubset{TS1}{PlayfairDisplay-TOsF} {5}
+\DeclareEncodingSubset{TS1}{PlyfrDisplay-TLF} {5}
+\DeclareEncodingSubset{TS1}{PlyfrDisplay-TOsF} {5}
\DeclareEncodingSubset{TS1}{TheanoDidot-TLF} {5}
\DeclareEncodingSubset{TS1}{TheanoDidot-TOsF} {5}
\DeclareEncodingSubset{TS1}{TheanoModern-TLF} {5}
\DeclareEncodingSubset{TS1}{TheanoModern-TOsF} {5}
\DeclareEncodingSubset{TS1}{TheanoOldStyle-TLF} {5}
\DeclareEncodingSubset{TS1}{TheanoOldStyle-TOsF} {5}
+\DeclareEncodingSubset{TS1}{charssil-TLF} {5}
% \end{macrocode}
%
% \begin{macrocode}
\DeclareEncodingSubset{TS1}{Crimson-TLF} {6}
-\DeclareEncodingSubset{TS1}{IBMPlexMono-TLF} {6}
-\DeclareEncodingSubset{TS1}{IBMPlexSerif-TLF} {6}
-\DeclareEncodingSubset{TS1}{LibertinusMono-TLF} {6}
\DeclareEncodingSubset{TS1}{LibertinusSerifDisplay-LF}{6}
\DeclareEncodingSubset{TS1}{LinuxLibertineDisplayT-*} {6}
\DeclareEncodingSubset{TS1}{LinuxLibertineMonoT-LF} {6}
\DeclareEncodingSubset{TS1}{LinuxLibertineMonoT-TLF} {6}
-\DeclareEncodingSubset{TS1}{Overlock-LF} {6}
+\DeclareEncodingSubset{TS1}{Ovrlck-LF} {6}
% \end{macrocode}
%
% \begin{macrocode}
+\DeclareEncodingSubset{TS1}{ComicNeue-TLF} {7}
+\DeclareEncodingSubset{TS1}{ComicNeueAngular-TLF} {7}
\DeclareEncodingSubset{TS1}{CormorantGaramond-*} {7}
\DeclareEncodingSubset{TS1}{Heuristica-TLF} {7}
\DeclareEncodingSubset{TS1}{Heuristica-TOsF} {7}
\DeclareEncodingSubset{TS1}{IMFELLEnglish-TLF} {7}
-\DeclareEncodingSubset{TS1}{LibreBaskerville-TLF} {7}
-\DeclareEncodingSubset{TS1}{LibreCaslon-*} {7}
-\DeclareEncodingSubset{TS1}{Marcellus-LF} {7}
+\DeclareEncodingSubset{TS1}{LibreBskrvl-TLF} {7}
+\DeclareEncodingSubset{TS1}{LibreCsln-*} {7}
+\DeclareEncodingSubset{TS1}{Lbstr-LF} {7}
+\DeclareEncodingSubset{TS1}{Mrcls-LF} {7}
+% \end{macrocode}
+% Strangely enough NotoSerif and NotoSans are sub-encoding 7 as
+% they are missing \cs{textminus} and several other glyphs. In
+% contrast the NotoSansMono is far more complete.
+% \begin{macrocode}
\DeclareEncodingSubset{TS1}{NotoSans-*} {7}
-\DeclareEncodingSubset{TS1}{NotoSansMono-TLF} {7}
-\DeclareEncodingSubset{TS1}{NotoSansMono-TOsF} {7}
\DeclareEncodingSubset{TS1}{NotoSerif-*} {7}
-\DeclareEncodingSubset{TS1}{Quattrocento-TLF} {7}
-\DeclareEncodingSubset{TS1}{QuattrocentoSans-TLF} {7}
-\DeclareEncodingSubset{TS1}{XCharter-TLF} {7}
-\DeclareEncodingSubset{TS1}{XCharter-TOsF} {7}
-\DeclareEncodingSubset{TS1}{erewhon-*} {7}
-\DeclareEncodingSubset{TS1}{ComicNeue-TLF} {7}
-\DeclareEncodingSubset{TS1}{ComicNeueAngular-TLF} {7}
-\DeclareEncodingSubset{TS1}{Forum-LF} {7} % the superiors are missing
+\DeclareEncodingSubset{TS1}{Quattro-LF} {7}
+\DeclareEncodingSubset{TS1}{QuattroSans-LF} {7}
+\DeclareEncodingSubset{TS1}{Frm-LF} {7} % the superiors are missing
% \end{macrocode}
%
% \begin{macrocode}
-\DeclareEncodingSubset{TS1}{Cochineal-*} {8}
+\DeclareEncodingSubset{TS1}{LibertinusMono-TLF} {8}
% \end{macrocode}
%
% \begin{macrocode}
@@ -1231,7 +1272,7 @@
%
% Here are new names for the legacy symbols that \LaTeX{} used to
% pick up from the \texttt{OMS} encoded fonts (and used for itemize
-% lists or footnote symbols.
+% lists or footnote symbols).
%
% We go the roundabout way via separate OMS declarations so that
%\begin{verbatim}
@@ -1481,20 +1522,22 @@
%
%
%
-%
% \section{The \texttt{textcomp} package}
%
%
+% For any rollback request before 2018-08-11 we make an attempt by
+% loading the 2018 version.
+% \changes{v2.1b}{2024/04/24}
+% {Load the 2018 version when rolling back prior to 2018-08-11
+% (gh/1333)}
% \begin{macrocode}
%<*TS1sty>
-\providecommand\DeclareRelease[3]{}
-\providecommand\DeclareCurrentRelease[2]{}
-
+\DeclareRelease{}{1997-12-01}{textcomp-2018-08-11.sty}
\DeclareRelease{}{2018-08-11}{textcomp-2018-08-11.sty}
\DeclareCurrentRelease{}{2020-02-02}
\ProvidesPackage{textcomp}
- [2020/02/02 v2.0n Standard LaTeX package]
+ [2024/04/24 v2.1b Standard LaTeX package]
% \end{macrocode}
%
% A precaution in case this is used without rebuilding the format.
@@ -1550,8 +1593,8 @@
}
% \end{macrocode}
%
+% \changes{v2.1a}{2024/04/22}{Drop default option \texttt{info} (gh/1333)}
% \begin{macrocode}
-\ExecuteOptions{info}
\ProcessOptions\relax
% \end{macrocode}
%
@@ -1706,7 +1749,7 @@
% The default is ``almostfull'' which means that old documents will
% work except that |\textcircled| and |\t| will use the kernel
% defaults (with the advantage that this also works if the current
-% font (as often the case) doesn't implement these glyphs.
+% font, as often the case, doesn't implement these glyphs).
%
% The ``force'' option simply sets the switch to true.
% \begin{macrocode}
@@ -2301,8 +2344,547 @@
% \begin{macrocode}
%</TS1oldsty>
% \end{macrocode}
+%
+%
+%
+%
+% \section{The \texttt{checkencodingsubset.tex} file}
+%
+% This is a simple file that asks for a name of a font family and
+% then displays information about the TS1 encoding for this family
+% and recommends the right encoding subset (to be used with
+% \cs{DeclareEncodingsubset}) for this family.
+% \changes{v1.1a}{2024/01/27}{Added check file for encoding subset}
+% \begin{macrocode}
+%<*TS1check>
+\Providesfile{checkencodingsubset.tex}
+ [2024/01/27 v0.5a Figure out safe TS1 encoding subsets]
+% \end{macrocode}
+%
+% \begin{macrocode}
+\let\typeoutdetails\typeout
+%\def\typeoutdetails#1{} % alternative definition used below
+% \end{macrocode}
+%
+% For the purpose of this check a glyph exists if the font slot is
+% occupied---too bad if that contains the wrong glyph or some tofu.
+% If it ``exists'' we return 0 otherwise 1. This way we can call
+% this macro several times in a row and obtain a number that is 0
+% if all glyphs are existing or greater than 0 if any of them is
+% missing.
+%
+% The second argument (holding the command name for a symbol) is
+% not used during these tests.
+% \begin{macrocode}
+\def\doesglyphexist#1#2{\iffontchar\testFont #1 0\else 1\relax \fi}
+% \end{macrocode}
+%
+% This macro also tests and outputs some information about the
+% symbol if it is missing. This time we make use of the second
+% argument.
+% \begin{macrocode}
+\def\glyphmissingdetails#1#2{\iffontchar\testFont #1 \else
+ \typeoutdetails{\space\space\space ==> \string#2 (#1) is missing}\fi}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\newif\ifsafesubencodingfound
+\newif\ifcoremisses
+% \end{macrocode}
+%
+% Testing a group of symbols that belong to one sub-encoding. More
+% precisely, the symbols that become unavailable if you change from
+% sub-encoding $x$ (\texttt{\#2}) to $x+1$ (\texttt{\#3}). As far
+% as the code is concerned, the
+% symbols that are supposed to be always available (the core)
+% become available if we test the group \texttt{-1} and \texttt{0}.
+%
+% The first argument contains the testing code and is supposed to
+% return a single number greater or equal to zero.
+% \begin{macrocode}
+\def\testgroup#1#2#3{%
+ \ifnum 0 = #1%
+ \ifnum #2<0
+ \typeoutdetails{All glyphs in core exist}%
+ \else
+ \typeoutdetails{All glyphs between sub-encoding #2 and #3 exist}%
+ \fi
+ \else
+ \ifnum #2<0
+ \typeoutdetails{**********************************}%
+ \typeoutdetails{Some glyphs are missing from core:}%
+ \coremissestrue
+ \ifsafesubencodingfound \else
+ \def\subencodingresult{#2}%
+ \fi
+ \else
+ \typeoutdetails{Some glyphs are missing from sub-encoding #2:}%
+ \ifsafesubencodingfound \else
+ \def\subencodingresult{#3}%
+ \fi
+ \fi
+% \end{macrocode}
+% If some glyphs are missing, we rerun the test code but this time
+% using \cs{glyphmissingdetails}.
+% \begin{macrocode}
+ {\let\doesglyphexist \glyphmissingdetails #1}%
+% \end{macrocode}
+% And because we had misses we have definitely found the subset.
+% \begin{macrocode}
+ \safesubencodingfoundtrue
+ \fi
+}
+% \end{macrocode}
+%
+% The currently defined subset for the family is either stored in
+% \cs{TS1:\meta{family}} if it was declared, or it is the default
+% subset which is stored in \cs{TS1:?}.
+% \begin{macrocode}
+\def\currsubencoding#1{\csname TS1:\ifcsname TS1:#1\endcsname #1\else ?\fi\endcsname}
+% \end{macrocode}
+%
+% If a font family is not found when declaring it with
+% \cs{DeclareFixedFont} we end up with the following font. This can
+% then be used as a simple test if we failed loading the TS1 font.
+% \begin{macrocode}
+\DeclareFixedFont\cmrFont{TS1}{cmr}{m}{n}{10pt}
+% \end{macrocode}
+%
+% Check for all glyphs in all encoding subsets \ldots
+% \begin{macrocode}
+\def\testallgroups#1{%
+ \DeclareFixedFont\testFont{TS1}{#1}{m}{n}{10pt}%
+ \ifx\testFont\cmrFont
+ \typeout{***** Font family #1 not found ****}%
+ \else
+% \end{macrocode}
+% We haven't checked anything yet.
+% \begin{macrocode}
+ \safesubencodingfoundfalse
+ \coremissesfalse
+ \typeoutdetails{^^J-----------------------------------------}%
+ \typeoutdetails{Testing font family #1^^J(currently TS1-sub-encoding
+ \currsubencoding{#1})}%
+ \typeout{-----------------------------------------}%
+% \end{macrocode}
+% Then we start testing the groups beginning with the glyphs
+% between sub-encoding 8 and 9. If any of them is missing (checked
+% with \cs{doesglyphexist}) then we already know that 9 is the
+% correct answer.
+% \begin{macrocode}
+ \testgroup{%
+ \doesglyphexist{21}{\texttwelveudash}%
+ \doesglyphexist{22}{\textthreequartersemdash}%
+ \doesglyphexist{134}{\textbardbl}%
+ \doesglyphexist{137}{\textcelsius}%
+ \doesglyphexist{178}{\texttwosuperior}%
+ \doesglyphexist{179}{\textthreesuperior}%
+ \doesglyphexist{185}{\textonesuperior}%
+ }{8}{9}%
+% \end{macrocode}
+% Nevertheless we go on with further groups so that the output
+% lists all missing glyphs.
+% \begin{macrocode}
+ \testgroup{%
+ \doesglyphexist{32}{\textblank}%
+ \doesglyphexist{148}{\textinterrobang}%
+ \doesglyphexist{149}{\textinterrobangdown}%
+ \doesglyphexist{191}{\texteuro}%
+ }{7}{8}%
+ \testgroup{%
+ \doesglyphexist{47}{\textfractionsolidus}%
+ \doesglyphexist{61}{\textminus}%
+ \doesglyphexist{87}{\textohm}%
+ \doesglyphexist{181}{\textmu}%
+ }{6}{7}%
+ \testgroup{%
+ \doesglyphexist{140}{\textflorin}%
+ \doesglyphexist{164}{\textcurrency}%
+ }{5}{6}%
+ \testgroup{%
+ \doesglyphexist{155}{\textnumero}%
+ \doesglyphexist{157}{\textestimated}%
+ }{4}{5}%
+ \testgroup{%
+ \doesglyphexist{24}{\textleftarrow}%
+ \doesglyphexist{25}{\textrightarrow}%
+ \doesglyphexist{94}{\textuparrow}%
+ \doesglyphexist{95}{\textdownarrow}%
+ \doesglyphexist{141}{\textcolonmonetary}%
+ \doesglyphexist{142}{\textwon}%
+ \doesglyphexist{146}{\textlira}%
+ \doesglyphexist{150}{\textdong}%
+ }{3}{4}%
+ \testgroup{%
+ \doesglyphexist{60}{\textlangle}%
+ \doesglyphexist{62}{\textrangle}%
+ }{2}{3}%
+ \testgroup{%
+ \doesglyphexist{0}{\capitalgrave}%
+ \doesglyphexist{1}{\capitalacute}%
+ \doesglyphexist{2}{\capitalcircumflex}%
+ \doesglyphexist{3}{\capitaltilde}%
+ \doesglyphexist{4}{\capitaldieresis}%
+ \doesglyphexist{5}{\capitalhungarumlaut}%
+ \doesglyphexist{6}{\capitalring}%
+ \doesglyphexist{7}{\capitalcaron}%
+ \doesglyphexist{8}{\capitalbreve}%
+ \doesglyphexist{9}{\capitalmacron}%
+ \doesglyphexist{10}{\capitaldotaccent}%
+ \doesglyphexist{11}{\capitalcedilla}%
+ \doesglyphexist{12}{\capitalogonek}%
+ \doesglyphexist{26}{\t}%
+ \doesglyphexist{27}{\capitaltie}%
+ \doesglyphexist{28}{\newtie}%
+ \doesglyphexist{29}{\capitalnewtie}%
+ \doesglyphexist{45}{\textdblhyphen}%
+ \doesglyphexist{48}{\textzerooldstyle}%
+ \doesglyphexist{49}{\textoneoldstyle}%
+ \doesglyphexist{50}{\texttwooldstyle}%
+ \doesglyphexist{51}{\textthreeoldstyle}%
+ \doesglyphexist{52}{\textfouroldstyle}%
+ \doesglyphexist{53}{\textfiveoldstyle}%
+ \doesglyphexist{54}{\textsixoldstyle}%
+ \doesglyphexist{55}{\textsevenoldstyle}%
+ \doesglyphexist{56}{\texteightoldstyle}%
+ \doesglyphexist{57}{\textnineoldstyle}%
+ \doesglyphexist{77}{\textmho}%
+ \doesglyphexist{79}{\textbigcircle}%
+ \doesglyphexist{91}{\textlbrackdbl}%
+ \doesglyphexist{93}{\textrbrackdbl}%
+ \doesglyphexist{96}{\textasciigrave}%
+ \doesglyphexist{98}{\textborn}%
+ \doesglyphexist{99}{\textdivorced}%
+ \doesglyphexist{100}{\textdied}%
+ \doesglyphexist{108}{\textleaf}%
+ \doesglyphexist{109}{\textmarried}%
+ \doesglyphexist{110}{\textmusicalnote}%
+ \doesglyphexist{126}{\texttildelow}%
+ \doesglyphexist{127}{\textdblhyphenchar}%
+ \doesglyphexist{128}{\textasciibreve}%
+ \doesglyphexist{129}{\textasciicaron}%
+ \doesglyphexist{175}{\textasciimacron}%
+ \doesglyphexist{130}{\textacutedbl}%
+ \doesglyphexist{131}{\textgravedbl}%
+ \doesglyphexist{138}{\textdollaroldstyle}%
+ \doesglyphexist{139}{\textcentoldstyle}%
+ \doesglyphexist{143}{\textnaira}%
+ \doesglyphexist{144}{\textguarani}%
+ \doesglyphexist{145}{\textpeso}%
+ \doesglyphexist{147}{\textrecipe}%
+ \doesglyphexist{152}{\textpertenthousand}%
+ \doesglyphexist{153}{\textpilcrow}%
+ \doesglyphexist{154}{\textbaht}%
+ \doesglyphexist{156}{\textdiscount}%
+ \doesglyphexist{158}{\textopenbullet}%
+ \doesglyphexist{159}{\textservicemark}%
+ \doesglyphexist{160}{\textlquill}%
+ \doesglyphexist{161}{\textrquill}%
+ \doesglyphexist{168}{\textasciidieresis}%
+ \doesglyphexist{171}{\textcopyleft}%
+ \doesglyphexist{173}{\textcircledP}%
+ \doesglyphexist{180}{\textasciiacute}%
+ \doesglyphexist{184}{\textreferencemark}%
+ \doesglyphexist{187}{\textsurd}%
+ }{1}{2}%
+% \end{macrocode}
+% All fonts (up to now) that belong to sub-encoding 1 do have the
+% \cs{textcircled} glyph, but it is too small to be usable. So this
+% test for this group currently doesn't do much good---but who
+% knows maybe one day a font shows up in which this glyph is
+% actually missing.
+% \begin{macrocode}
+ \testgroup{%
+ \doesglyphexist{79}{\textcircled}% this is not a proper test because the symbol is
+ % usually available but not usable
+ }{0}{1}%
+ \testgroup{%
+ \doesglyphexist{13}{\textquotestraightbase}%
+ \doesglyphexist{18}{\textquotestraightdblbase}%
+ \doesglyphexist{23}{\textcapitalcompwordmark}%
+ \doesglyphexist{31}{\textascendercompwordmark}%
+ \doesglyphexist{36}{\textdollar}%
+ \doesglyphexist{39}{\textquotesingle}%
+ \doesglyphexist{42}{\textasteriskcentered}%
+ \doesglyphexist{132}{\textdagger}%
+ \doesglyphexist{133}{\textdaggerdbl}%
+ \doesglyphexist{135}{\textperthousand}%
+ \doesglyphexist{136}{\textbullet}%
+ \doesglyphexist{151}{\texttrademark}%
+ \doesglyphexist{162}{\textcent}%
+ \doesglyphexist{163}{\textsterling}%
+ \doesglyphexist{165}{\textyen}%
+ \doesglyphexist{166}{\textbrokenbar}%
+ \doesglyphexist{167}{\textsection}%
+ \doesglyphexist{169}{\textcopyright}%
+ \doesglyphexist{170}{\textordfeminine}%
+ \doesglyphexist{172}{\textlnot}%
+ \doesglyphexist{174}{\textregistered}%
+ \doesglyphexist{176}{\textdegree}%
+ \doesglyphexist{177}{\textpm}%
+ \doesglyphexist{182}{\textparagraph}%
+ \doesglyphexist{183}{\textperiodcentered}%
+ \doesglyphexist{186}{\textordmasculine}%
+ \doesglyphexist{188}{\textonequarter}%
+ \doesglyphexist{189}{\textonehalf}%
+ \doesglyphexist{190}{\textthreequarters}%
+ \doesglyphexist{214}{\texttimes}%
+ \doesglyphexist{246}{\textdiv}%
+ }{-1}{0}%
+% \end{macrocode}
+% If all groups have all glyphs then we have the full encoding
+% (subset 0).
+% \begin{macrocode}
+ \ifsafesubencodingfound\else
+ \def\subencodingresult{0}%
+ \fi
+% \end{macrocode}
+% If the font is missing some of the core glyphs we make a remark
+% about this, because they will never display.
+% \begin{macrocode}
+ \typeoutdetails{-----------------------------------------}%
+ \typeout{TS1 encoding subset for #1\ifcoremisses \space(ignoring core misses)\fi
+ \space (\ifnum\subencodingresult =
+ \currsubencoding{#1} ok\else bad\fi)}%
+ \typeout{Use sub-encoding \subencodingresult
+ \ifnum\subencodingresult = \currsubencoding{#1}\else
+ \space (not \currsubencoding{#1})\fi}
+ \typeout{-----------------------------------------^^J}%
+ \fi
+}
+% \end{macrocode}
+%
+% This tests all declarations (or most of them) that have been
+% added to the kernel. It is called if no family is given interactively.
+% \begin{macrocode}
+\long\def\testallkerneldefinedfamilies{%
+\testallgroups{ccr}% {0}
+\testallgroups{cmbr}% {0}
+%%\testallgroups{cmr}% {0} % don't test this one as it is the fallback
+ % thus reports that the family is not found
+\testallgroups{cmss}% {0}
+\testallgroups{cmtl}% {0}
+\testallgroups{cmtt}% {0}
+\testallgroups{cmvtt}% {0}
+\testallgroups{pxr}% {0}
+\testallgroups{pxss}% {0}
+\testallgroups{pxtt}% {0}
+\testallgroups{qag}% {0}
+\testallgroups{qbk}% {0}
+\testallgroups{qcr}% {0}
+\testallgroups{qcs}% {0}
+\testallgroups{qhvc}% {0}
+\testallgroups{qhv}% {0}
+\testallgroups{qpl}% {0}
+\testallgroups{qtm}% {0}
+\testallgroups{qzc}% {0}
+\testallgroups{txr}% {0}
+\testallgroups{txss}% {0}
+\testallgroups{txtt}% {0}
+%
+% Next would claim to be 0 (or 2)
+%
+%\testallgroups{lmr}% {1}
+%\testallgroups{lmdh}% {1}
+%\testallgroups{lmss}% {1}
+%\testallgroups{lmssq}% {1}
+%\testallgroups{lmvtt}% {1}
+%\testallgroups{lmtt}% {1} % missing TM, SM and pertenthousand so really 2
+%
+% these are no longer in TeX Live
+%
+%\testallgroups{ptmx}% {2} % gone for a long time it seems
+%\testallgroups{ptmj}% {2} % ditto
+%\testallgroups{ul8}% {2} % ditto
+%
+% next block has tofu chars so results are wrong
+%
+%\testallgroups{bch}% {5} % tofu for blank, ohm
+%\testallgroups{futj}%{5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{futs}%{5} % tofu for blank, ohm
+%\testallgroups{futx}%{5} % probably (currently broken distrib)
+%\testallgroups{pag}% {5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{pbk}% {5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{pcr}% {5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{phv}% {5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{pnc}% {5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{pplj}%{5} % tofu for blank
+%\testallgroups{pplx}%{5} % tofu for blank
+%\testallgroups{ppl}% {5} % tofu for blank interrobang/down
+%\testallgroups{ptm}% {5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{pzc}% {5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{ul9}% {5} % tofu for blank, interrobang/down, ohm
+%\testallgroups{dayroms}%{6} % tofu for blank, interrobang/down, ohm
+%\testallgroups{dayrom}% {6} % tofu for blank, interrobang/down, ohm
+%\testallgroups{augie}%{8} % really only missing euro and full of tofu
+%\testallgroups{put}% {8}
+%\testallgroups{uag}% {8} % probably (currently broken distrib)
+%\testallgroups{ugq}% {8}
+%
+\testallgroups{zi4}% {9}
+%
+%% not installed normally
+%
+%\testallgroups{hls}% {5}
+%\testallgroups{hlst}% {5}
+%\testallgroups{hlct}% {5}
+%\testallgroups{hlh}% {5}
+%\testallgroups{hlx}% {8}
+%\testallgroups{hlce}% {8}
+%\testallgroups{hlcn}% {8}
+%\testallgroups{hlcw}% {8}
+%\testallgroups{hlcf}% {8}
-
+\testallgroups{lato-LF}% {0} % with a bunch of tofu inside --- should probably be changed
+\testallgroups{opensans-TLF}%{0} % with a bunch of tofu inside --- should probably be changed
+\testallgroups{cantarell-TLF}% {0} % with a bunch of tofu inside --- should probably be changed
+\testallgroups{fbb-LF}% {0} % missing centoldstyle ---> 2
+\testallgroups{tli}% {1} % with lots of tofu inside --- should probably be changed
+\testallgroups{Alegreya-OsF}% {2}
+\testallgroups{AlegreyaSans-OsF}% {2}
+\testallgroups{DejaVuSans-TLF}% {2}
+\testallgroups{DejaVuSansCondensed-TLF}% {2}
+\testallgroups{DejaVuSansMono-TLF}% {2} this is missing \textfractionsolidus which makes it 7 really
+\testallgroups{EBGaramond-LF}% {2}
+\testallgroups{Tempora-TLF}% {2}
+\testallgroups{Tempora-TOsF}% {2}
+\testallgroups{Arimo-TLF}% {3}
+\testallgroups{Crlt-TLF}% {3} changed from Carlito-
+\testallgroups{FiraSans-LF}% {3} should be 4
+\testallgroups{IBMPlexSans-TLF}% {3}
+\testallgroups{Merriwthr-OsF}% {3} changed from Merriweather- and should be 2
+\testallgroups{Montserrat-LF}% {3} now 2
+\testallgroups{MontserratAlternates-LF}%{3} now 2
+\testallgroups{SourceCodePro-TLF}% {3}
+\testallgroups{SourceCodePro-TOsF}% {3}
+\testallgroups{SourceSansPro-OsF}% {3}
+\testallgroups{SourceSerifPro-LF}% {3}
+\testallgroups{Tinos-TLF}% {3}
+\testallgroups{AccanthisADFStdNoThree-LF}%{4}
+\testallgroups{Cabin-TLF}% {4}
+\testallgroups{Caladea-TLF}% {4}
+\testallgroups{Chivo-LF}% {4}
+\testallgroups{ClearSans-TLF}% {4}
+\testallgroups{Coelacanth-LF}% {4}
+\testallgroups{CrimsonPro-LF}% {4}
+\testallgroups{FiraMono-TLF}% {4}
+\testallgroups{FiraMono-TOsF}% {4}
+\testallgroups{Go-TLF}% {4}
+\testallgroups{GoMono-TLF}% {4}
+\testallgroups{InriaSans-LF}% {4}
+\testallgroups{InriaSerif-LF}% {4}
+\testallgroups{LibertinusSans-LF}% {4}
+\testallgroups{LibertinusSerif-LF}% {4}
+\testallgroups{LibreBodoni-TLF}% {4}
+\testallgroups{LibreFranklin-TLF}% {4}
+\testallgroups{LinguisticsPro-LF}% {4}
+\testallgroups{LinguisticsPro-OsF}% {4}
+\testallgroups{LinuxBiolinumT-LF}% {4}
+\testallgroups{LinuxLibertineT-LF}% {4}
+\testallgroups{MerriwthrSans-OsF}% {4} name change and now 2
+\testallgroups{MintSpirit-LF}% {4}
+\testallgroups{MintSpiritNoTwo-LF}% {4}
+\testallgroups{PTMono-TLF}% {4}
+\testallgroups{PTSans-TLF}% {4}
+\testallgroups{PTSansCaption-TLF}% {4}
+\testallgroups{PTSansNarrow-TLF}% {4}
+\testallgroups{PTSerif-TLF}% {4}
+\testallgroups{PTSerifCaption-TLF}% {4}
+\testallgroups{Raleway-TLF}% {4}
+\testallgroups{Raleway-TOsF}% {4}
+\testallgroups{Roboto-LF}% {4}
+\testallgroups{RobotoMono-TLF}% {4}
+\testallgroups{RobotoSlab-TLF}% {4}
+\testallgroups{Rosario-LF}% {4}
+\testallgroups{SticksTooText-LF}% {4}
+\testallgroups{UniversalisADFStd-LF}%{4}
+\testallgroups{Almndr-OsF}% {5} name change
+\testallgroups{Baskervaldx-LF}% {5}
+\testallgroups{BaskervilleF-LF}% {5} now 2
+\testallgroups{Bttr-TLF}% {5} name changed from Bitter-...
+\testallgroups{Cinzel-LF}% {5}
+\testallgroups{CinzelDecorative-LF}%{5}
+\testallgroups{DejaVuSerif-TLF}% {5}
+\testallgroups{DejaVuSerifCondensed-TLF}% {5}
+\testallgroups{GilliusADF-LF}% {5}
+\testallgroups{charssil-TLF} %% missing should be 5
+\testallgroups{GilliusADFCond-LF}%{5}
+\testallgroups{GilliusADFNoTwo-LF}%{5}
+\testallgroups{GilliusADFNoTwoCond-LF}%{5}
+\testallgroups{Lbstr-LF}% {5} name change and should be 7
+\testallgroups{OldStandard-TLF}% {5}
+\testallgroups{PlyfrDisplay-LF}%{5} name change
+\testallgroups{PlyfrDisplay-OsF}% {5} name change
+\testallgroups{TheanoDidot-TLF}% {5}
+\testallgroups{TheanoDidot-TOsF}% {5}
+\testallgroups{TheanoModern-TLF}% {5}
+\testallgroups{TheanoModern-TOsF}%{5}
+\testallgroups{TheanoOldStyle-TLF}%{5}
+\testallgroups{TheanoOldStyle-TOsF}%{5}
+\testallgroups{Crimson-TLF}% {6}
+\testallgroups{IBMPlexMono-TLF}% {6} now 3
+\testallgroups{IBMPlexSerif-TLF}% {6} now 3
+\testallgroups{LibertinusMono-TLF}%{6} should be 8
+\testallgroups{LibertinusSerifDisplay-LF}%{6}
+\testallgroups{LinuxLibertineDisplayT-LF}%{6}
+\testallgroups{LinuxLibertineMonoT-LF}%{6}
+\testallgroups{LinuxLibertineMonoT-TLF}%{6}
+\testallgroups{Ovrlck-LF}% {6} name changed
+\testallgroups{CormorantGaramond-LF}%{7}
+\testallgroups{Heuristica-TLF}% {7}
+\testallgroups{Heuristica-TOsF}% {7}
+\testallgroups{IMFELLEnglish-TLF}%{7}
+\testallgroups{LibreBskvl-LF}% {7} %% wrong name LibreBaskerville-TLF
+\testallgroups{LibreCsln-LF}% {7} changed from LibreCaslon-
+\testallgroups{Mrcls-LF}% {7} %% wrong name Marcellus-LF
+\testallgroups{NotoSans-LF}% {7}
+\testallgroups{NotoSansMono-TLF}%{7} now 2
+\testallgroups{NotoSansMono-TOsF}%{7} now 2
+\testallgroups{NotoSerif-LF}% {7}
+\testallgroups{Quattro-LF}% {7} changed from Quattrocento-
+\testallgroups{QuattroSans-LF}% {7} changed from QuattrocentoSans-
+\testallgroups{XCharter-TLF}% {7} now 2
+\testallgroups{XCharter-TOsF}% {7} now 2
+\testallgroups{erewhon-LF}% {7} now 2
+\testallgroups{ComicNeue-TLF}% {7}
+\testallgroups{ComicNeueAngular-TLF}%{7}
+\testallgroups{Frm-LF}%{7} % the superiors are missing; name changed from Forum-LF
+\testallgroups{Cochineal-TLF}% {8} now 5
+\testallgroups{AlgolRevived-TLF}%{9}
+}
+% \end{macrocode}
+%
+% There interaction with the user.
+% \begin{macrocode}
+\typeout{^^J=====================================================================}
+\typeout{| Enter font family to check (or <enter> for kernel defined families)}
+\typeout{=====================================================================}
+\typein[\FontFamilyToCheck]{}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\if!\FontFamilyToCheck!
+ \typeout{=====================================================================}
+ \typeout{| Detailed output? (default no)}
+ \typeout{=====================================================================}
+ \typein[\Details]{}
+ \if!\Details!
+ \def\typeoutdetails#1{}
+ \else
+ \let\typeoutdetails\typeout
+ \fi
+ \testallkerneldefinedfamilies
+\else
+ \let\typeoutdetails\typeout
+ \testallgroups\FontFamilyToCheck
+\fi
+% \end{macrocode}
+%
+% \begin{macrocode}
+\stop
+%</TS1check>
+% \end{macrocode}
+%
% \Finale
%
diff --git a/Master/texmf-dist/source/latex/base/ltthm.dtx b/Master/texmf-dist/source/latex/base/ltthm.dtx
index 180b8accfe4..c900f519dd5 100644
--- a/Master/texmf-dist/source/latex/base/ltthm.dtx
+++ b/Master/texmf-dist/source/latex/base/ltthm.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltthm.dtx}
- [2014/09/29 v1.0f LaTeX Kernel (Theorems)]
+ [2024/03/18 v1.0g LaTeX Kernel (Theorems)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltthm.dtx}
@@ -237,16 +237,31 @@
% \end{macro}
%
% \begin{macro}{\@thm}
+% \changes{v1.0c}{1994/04/17}{Use new std counter error message (FMi)}
+% \changes{v1.0g}{2024/03/18}{Use \cs{@kernel@refstepcounter} to avoid an unwanted target (UFi)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2024/03/18}%
+%<latexrelease> {\@thm}{no link target}%
\def\@thm#1#2{%
- \refstepcounter{#1}%
+ \@kernel@refstepcounter{#1}%
\@ifnextchar[{\@ythm{#1}{#2}}{\@xthm{#1}{#2}}}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@thm}{no link target}%
+%<latexrelease>\def\@thm#1#2{%
+%<latexrelease> \refstepcounter{#1}%
+%<latexrelease> \@ifnextchar[{\@ythm{#1}{#2}}{\@xthm{#1}{#2}}}
+%<latexrelease>\EndIncludeInRelease
+%</2ekernel|latexrelease>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@xthm}
% \begin{macro}{\@ythm}
% \begin{macrocode}
+%<*2ekernel>
\def\@xthm#1#2{%
\@begintheorem{#2}{\csname the#1\endcsname}\ignorespaces}
\def\@ythm#1#2[#3]{%
@@ -273,11 +288,26 @@
% NFSS}
% Providing theorem defaults.
% \task{???}{add `reset@font?}
+% % \changes{v1.0g}{2024/03/18}{Insert link target in the label (UFi)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2024/03/18}%
+%<latexrelease> {\@begintheorem}{add link targets}%
\def\@begintheorem#1#2{\trivlist
- \item[\hskip \labelsep{\bfseries #1\ #2}]\itshape}
+ \item[\MakeLinkTarget{\@currentcounter}\hskip \labelsep{\bfseries #1\ #2}]\itshape}
\def\@opargbegintheorem#1#2#3{\trivlist
- \item[\hskip \labelsep{\bfseries #1\ #2\ (#3)}]\itshape}
+ \item[\MakeLinkTarget{\@currentcounter}\hskip \labelsep{\bfseries #1\ #2\ (#3)}]\itshape}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@begintheorem}{add link targets}%
+%<latexrelease>\def\@begintheorem#1#2{\trivlist
+%<latexrelease> \item[\hskip \labelsep{\bfseries #1\ #2}]\itshape}
+%<latexrelease>\def\@opargbegintheorem#1#2#3{\trivlist
+%<latexrelease> \item[\hskip \labelsep{\bfseries #1\ #2\ (#3)}]\itshape}
+%<latexrelease>\EndIncludeInRelease
+%</2ekernel|latexrelease>
+%<*2ekernel>
\def\@endtheorem{\endtrivlist}
%</2ekernel>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltvers.dtx b/Master/texmf-dist/source/latex/base/ltvers.dtx
index bf5dce4ca18..5031ef83073 100644
--- a/Master/texmf-dist/source/latex/base/ltvers.dtx
+++ b/Master/texmf-dist/source/latex/base/ltvers.dtx
@@ -112,10 +112,10 @@
%</2ekernel>
%<latexrelease>\edef\latexreleaseversion
%<*2ekernel|latexrelease>
- {2023-11-01}
+ {2024-06-01}
%</2ekernel|latexrelease>
%<*2ekernel>
-\def\patch@level{1}
+\def\patch@level{0}
% \end{macrocode}
%
% \begin{macro}{\development@branch@name}
diff --git a/Master/texmf-dist/source/latex/base/ltxdoc.dtx b/Master/texmf-dist/source/latex/base/ltxdoc.dtx
index 584f4f51f64..5e8b4946926 100644
--- a/Master/texmf-dist/source/latex/base/ltxdoc.dtx
+++ b/Master/texmf-dist/source/latex/base/ltxdoc.dtx
@@ -30,7 +30,7 @@
%
%<class>\NeedsTeXFormat{LaTeX2e}
%<class>\ProvidesClass{ltxdoc}
-%<class> [2023/03/28 v2.1j Standard LaTeX documentation class]
+%<class> [2024/02/08 v2.1j Standard LaTeX documentation class]
%
%<*driver>
\documentclass{ltxdoc}
@@ -288,12 +288,13 @@
% \section{Useful abbreviations}
%
% |\cmd{\foo}| Prints |\foo| verbatim. It may be used inside moving
-% arguments. It can \emph{not} be use to record commands that are defined as
+% arguments. It can \emph{not} be used to record commands that are defined as
% ``|\outer|'' nor is it possible to use it on conditionals such as
% |\iftrue| or defined by |\newif|.
-% |\cs{foo}| already available with the \texttt{doc} package also prints |\foo|, for those who prefer that
+% |\cs{foo}| Already available with the \texttt{doc} package and also prints |\foo|,
+% for those who prefer that
% syntax. (This second form can be used to record all types of command so the
-% above restrictions do not apply.
+% above restrictions do not apply.)
% \begin{macro}{\cmd}
% \changes{v2.0k}{1994/05/21}{New definition, so \cmd\{ works.}
% \begin{macro}{\cs}
diff --git a/Master/texmf-dist/source/latex/base/nfssfont.dtx b/Master/texmf-dist/source/latex/base/nfssfont.dtx
index ae91abf671c..0464053c10f 100644
--- a/Master/texmf-dist/source/latex/base/nfssfont.dtx
+++ b/Master/texmf-dist/source/latex/base/nfssfont.dtx
@@ -26,8 +26,8 @@
% extension .ins) which are part of the distribution.
%
% \fi
-\def\nfssfontfileversion{v2.2e}
-\def\nfssfontfiledate{2020/11/26}
+\def\nfssfontfileversion{v2.2f}
+\def\nfssfontfiledate{2023/11/07}
%
% \iffalse
@@ -197,7 +197,7 @@
{\PackageWarningNoLine{nfssfont}%
{Encoding file `\next' not found.%
\MessageBreak
- You might have misspelt the name of the encoding
+ You might have misspelled the name of the encoding
\MessageBreak
or perhaps this encoding is not a text encoding,
\MessageBreak
diff --git a/Master/texmf-dist/source/latex/base/slifonts.fdd b/Master/texmf-dist/source/latex/base/slifonts.fdd
index 8ddd639d50a..b35cd07a8be 100644
--- a/Master/texmf-dist/source/latex/base/slifonts.fdd
+++ b/Master/texmf-dist/source/latex/base/slifonts.fdd
@@ -45,7 +45,7 @@
%<*driver, >
\ProvidesFile{sfonts.drv}
%</driver, >
- [2019/07/09 v2.2f Standard LaTeX slide font definitions]
+ [2023/12/02 v2.2f Standard LaTeX slide font definitions]
%
%<*driver>
\documentclass{ltxdoc}
@@ -95,7 +95,7 @@
% \section{Introduction}
%
% This file contains the external font information for special
-% variants of the the Computer Modern fonts to be used for overhead
+% variants of the Computer Modern fonts to be used for overhead
% slides. They allow to produce slides in a similar fashion as it was
% originally done by \SliTeX{}.
%
@@ -103,7 +103,7 @@
% format. Instead the standard format may be used and internally only
% different font definition files come into play.
%
-% Note, that that you therefore can easily produce slides in different
+% Note that you therefore can easily produce slides in different
% fonts just by calling an appropriate package (like |times|) in
% your |\usepackage| command. This works, for example, with all
% fonts that are defined to be scalable (eg PostScript fonts) since
diff --git a/Master/texmf-dist/source/latex/base/syntonly.dtx b/Master/texmf-dist/source/latex/base/syntonly.dtx
index 9d3baaa0245..9844585fa56 100644
--- a/Master/texmf-dist/source/latex/base/syntonly.dtx
+++ b/Master/texmf-dist/source/latex/base/syntonly.dtx
@@ -71,7 +71,7 @@
\ProvidesFile{syntonly.dtx}
%</dtx>
%<*package|dtx>
- [2017/06/30 v2.1e Standard LaTeX2e package]
+ [2024/02/08 v2.1e Standard LaTeX2e package]
%</package|dtx>
% \end{macrocode}
%
@@ -150,7 +150,7 @@
\repeat
% \end{macrocode}
% Since all font changes occur either via |\selectfont| (in
-% text or |\mathversion| (for math mode) it is sufficient
+% text) or |\mathversion| (for math mode), it is sufficient
% to change these to no-ops. In addition we must prevent
% the loading of math fonts, this is done by making
% |\getanddefine@fonts| a no-op.
@@ -184,7 +184,7 @@
% The |\nopages@| macro disables the \LaTeX{} output routine.
% To this end we define a very simple output routine that empties
% the output \emph{and} footnote boxes (remember that the latter
-% are insertions.
+% are insertions).
% \begin{macrocode}
\def\nopages@{%
\output {\setbox\z@\box\@cclv
diff --git a/Master/texmf-dist/source/latex/base/utf8ienc.dtx b/Master/texmf-dist/source/latex/base/utf8ienc.dtx
index b7dfe4b0c0b..a2701ac5c87 100644
--- a/Master/texmf-dist/source/latex/base/utf8ienc.dtx
+++ b/Master/texmf-dist/source/latex/base/utf8ienc.dtx
@@ -886,7 +886,8 @@
\else
% \end{macrocode}
%
-% If the input is malformed UTF-8 there may not be enough closing ) so
+% If the input is malformed UTF-8 there may not be enough closing
+% \iffalse(\fi ) so
% add 5 so there are always some remaining then cleanup and remove
% any remaining ones at the end. This avoids |\numexpr| parse errors
% while outputting a package error.
@@ -1660,7 +1661,7 @@
% \end{macrocode}
% According to the Unicode standard Ux04C5 should be an L with ``tail'' not
% with descender (which also exists as Ux04A2) but it looks as if the char
-% names do not make this distinction). Should they?
+% names do not make this distinction. Should they?
% \begin{macrocode}
%<all,x2,t2c,t2b>\DeclareUnicodeCharacter{04C5}{\CYRLDSC}
%<all,x2,t2c,t2b>\DeclareUnicodeCharacter{04C6}{\cyrldsc}
diff --git a/Master/texmf-dist/source/latex/cyrillic/cyoutenc.dtx b/Master/texmf-dist/source/latex/cyrillic/cyoutenc.dtx
index 89304a754f8..7bd6b945462 100644
--- a/Master/texmf-dist/source/latex/cyrillic/cyoutenc.dtx
+++ b/Master/texmf-dist/source/latex/cyrillic/cyoutenc.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright 1993-2022
+% Copyright 1993-2023
% The LaTeX3 Project and any individual authors listed elsewhere
% in this file.
%
@@ -65,7 +65,7 @@
%<T2A>\ProvidesFile{t2aenc.def}
%<T2B>\ProvidesFile{t2benc.def}
%<T2C>\ProvidesFile{t2cenc.def}
- [2022/06/11 v1.0j Cyrillic encoding definition file]
+ [2023/11/07 v1.0k Cyrillic encoding definition file]
% \end{macrocode}
%
% To assure that |\MakeUppercase| and |\MakeLowercase| will work
@@ -118,8 +118,13 @@
\DeclareTextCommand{\d}{\LastDeclaredEncoding}[1]
{\hmode@bgroup
\o@lign{\relax#1\crcr\hidewidth\ltx@sh@ft{-1ex}.\hidewidth}\egroup}
+% \end{macrocode}
+%
+% \changes{v1.0k}{2023/11/07}{Add \cs{hmode@bgroup} to \cs{k} to match
+% other encoding definitions (gh/1148)}
+% \begin{macrocode}
\DeclareTextCommand{\k}{\LastDeclaredEncoding}[1]
- {\oalign{\null#1\crcr\hidewidth\char12}}
+ {\hmode@bgroup\oalign{\null#1\crcr\hidewidth\char12}\egroup}
\DeclareTextCommand{\textperthousand}{\LastDeclaredEncoding}
{\%\char 24 }
\DeclareTextCommand{\textpertenthousand}{\LastDeclaredEncoding}
diff --git a/Master/texmf-dist/source/latex/firstaid/firstaid.ins b/Master/texmf-dist/source/latex/firstaid/firstaid.ins
index 22067390cd1..5de510ba513 100644
--- a/Master/texmf-dist/source/latex/firstaid/firstaid.ins
+++ b/Master/texmf-dist/source/latex/firstaid/firstaid.ins
@@ -3,7 +3,7 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 2020-2023
+%% Copyright (C) 2020-2024
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -44,7 +44,7 @@ reports for it can be opened at https://latex-project.org/bugs/
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 2020-2023
+Copyright (C) 2020-2024
The LaTeX Project and any individual authors listed elsewhere
in this file.
diff --git a/Master/texmf-dist/source/latex/firstaid/latex2e-first-aid-for-external-files.dtx b/Master/texmf-dist/source/latex/firstaid/latex2e-first-aid-for-external-files.dtx
index 2317c051412..152737eaf77 100644
--- a/Master/texmf-dist/source/latex/firstaid/latex2e-first-aid-for-external-files.dtx
+++ b/Master/texmf-dist/source/latex/firstaid/latex2e-first-aid-for-external-files.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex2e-first-aid-for-external-files.dtx (C) Copyright 2020-2023
+%% File: latex2e-first-aid-for-external-files.dtx (C) Copyright 2020-2024
%%
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
@@ -111,8 +111,8 @@
% \end{macrocode}
%
% \begin{macrocode}
-\def\LaTeXFirstAidDate{2024/02/29}
-\def\LaTeXFirstAidVersion{v1.1c}
+\def\LaTeXFirstAidDate{2024/03/20}
+\def\LaTeXFirstAidVersion{v1.1e}
% \end{macrocode}
%
% \begin{macrocode}
@@ -612,8 +612,21 @@
% routines in \pkg{expl3}.
% \begin{macrocode}
\AddToHook{package/acro/after}[firstaid]{%
- \FirstAidNeededT{acro}{sty}{2022/04/01 v3.8 typeset acronyms and other abbreviations (CN)}
- {\UseName{prop_new:c}{l__acro_tmpa_prop}}%
+ \FirstAidNeededT{acro}{sty}{2022/04/01 v3.8 typeset acronyms
+ and other abbreviations (CN)}
+ {\UseName{prop_new:c}{l__acro_tmpa_prop}%
+% \end{macrocode}
+% With the 2024 June release of \LaTeX{} it will also fail to patch
+% \cs{endlongtable} and therefore errors when loading. However, the
+% patch it tries never worked (because it was setting a local
+% boolean at a point where it was more or less immediately
+% reset). Thus, rather than fixing the patch approach (which
+% requires to surround the patch with \cs{ExplSyntaxOn}
+% \verb*/\catcode`\ =10 / and \cs{ExplSyntaxOff}) we simply disable
+% the patch for now.
+% \begin{macrocode}
+ \acsetup{patch/longtable=false}%
+ }%
}
% \end{macrocode}
%
@@ -636,11 +649,78 @@
% routines in \pkg{expl3}.
% \begin{macrocode}
\AddToHook{package/chemnum/after}[firstaid]{%
- \FirstAidNeededT{chemnum}{sty}{2021/01/21 v1.3a a comprehensive approach for the numbering of chemical compounds (CN)}
+ \FirstAidNeededT{chemnum}{sty}{2021/01/21 v1.3a a comprehensive
+ approach for the numbering of chemical compounds (CN)}
{\UseName{prop_new:c}{l__chemnum_tmpa_prop}}%
}
% \end{macrocode}
%
+% \subsection{The \pkg{cleveref} package first aid}
+%
+% The \pkg{cleveref} package expects only two data containers
+% for its internal \cs{newlabel} command. This fails if
+% \pkg{xr-hyper} is used which expands every \cs{newlabel} to
+% five data container and puts the file name into the last one.
+% \begin{macrocode}
+\AddToHook{package/cleveref/after}[firstaid]{%
+ \FirstAidNeededT{cleveref}{sty}{2018/03/27 v0.21.4 Intelligent cross-referencing}
+ {%
+% \end{macrocode}
+% This are the two commands which retrieve the data from the label info.
+% We change them to expect five arguments.
+% \begin{macrocode}
+ \def\cref@getref#1#2{%
+ \expandafter\let\expandafter#2\csname r@#1@cref\endcsname%
+ \expandafter\expandafter\expandafter\def%
+ \expandafter\expandafter\expandafter#2%
+ \expandafter\expandafter\expandafter{%
+ \expandafter\@firstoffive#2}}% <-------- five
+ \def\cpageref@getref#1#2{%
+ \expandafter\let\expandafter#2\csname r@#1@cref\endcsname%
+ \expandafter\expandafter\expandafter\def%
+ \expandafter\expandafter\expandafter#2%
+ \expandafter\expandafter\expandafter{%
+ \expandafter\@secondoffive#2}}% <----------- five
+% \end{macrocode}
+% We also need to redefine the internal label commands of cleveref.
+% This must be done after \pkg{cleveref} has made its changes
+% in \texttt{begindocument} so we add it to the same hook using
+% the hook label used by \pkg{cleveref}.
+% This way it is guaranteed to overwrite the definitions.
+% \begin{macrocode}
+ \AddToHook{begindocument}[cleveref]{%
+ \def\label@noarg#1{%
+ \cref@old@label{#1}%
+ \@bsphack%
+ \edef\@tempa{{page}{\the\c@page}}%
+ \setcounter{page}{1}%
+ \edef\@tempb{\thepage}%
+ \expandafter\setcounter\@tempa%
+ \cref@constructprefix{page}{\cref@result}%
+ \protected@write\@auxout{}%
+ {\string\newlabel{#1@cref}{{\cref@currentlabel}%
+ {[\@tempb][\arabic{page}][\cref@result]\thepage}{}{}{}}}% <----- five
+ \@esphack}%
+ \def\label@optarg[#1]#2{%
+ \cref@old@label{#2}%
+ \@bsphack%
+ \edef\@tempa{{page}{\the\c@page}}%
+ \setcounter{page}{1}%
+ \edef\@tempb{\thepage}%
+ \expandafter\setcounter\@tempa%
+ \cref@constructprefix{page}{\cref@result}%
+ \protected@edef\cref@currentlabel{%
+ \expandafter\cref@override@label@type%
+ \cref@currentlabel\@nil{#1}}%
+ \protected@write\@auxout{}%
+ {\string\newlabel{#2@cref}{{\cref@currentlabel}%
+ {[\@tempb][\arabic{page}][\cref@result]\thepage}{}{}{}}}% <------- five
+ \@esphack}%
+ }
+ }%
+}
+% \end{macrocode}
+%
% \begin{macrocode}
%</kernel>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/graphics/color.dtx b/Master/texmf-dist/source/latex/graphics/color.dtx
index cf3a7efbcf0..130a960d099 100644
--- a/Master/texmf-dist/source/latex/graphics/color.dtx
+++ b/Master/texmf-dist/source/latex/graphics/color.dtx
@@ -2,7 +2,7 @@
% \iffalse
%
%% color.dtx Copyright (C) 1994--1999 David Carlisle
-%% Copyright (C) 2005-2022 LaTeX Project
+%% Copyright (C) 2005-2024 LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -21,7 +21,7 @@
%<driver> \ProvidesFile{color.drv}
% \fi
% \ProvidesFile{color.dtx}
- [2022/01/06 v1.3d Standard LaTeX Color (DPC)]
+ [2024/01/14 v1.3d Standard LaTeX Color (DPC)]
%
% \iffalse
%<*driver>
@@ -168,7 +168,7 @@
%
% \begin{option}{dvips}
% \begin{option}{xdvi}
-% Tom Rokicki's dvips driver, and the X Windows previewer, xdvi which uses
+% Tom Rokicki's dvips driver, and the X Windows previewer, xdvi, which uses
% (a subset of) the same |\specials|.
% \begin{macrocode}
\DeclareOption{dvips}{\def\Gin@driver{dvips.def}%
@@ -248,7 +248,7 @@
% \changes{v0.3k}{1995/09/07}
% {Merge dviwindo and dvipsone options}
% The drivers of the Y\&Y \TeX\ system.
-% (Which use the same |\specials|).
+% (Which use the same |\specials|.)
% \begin{macrocode}
\DeclareOption{dvipsone}{\def\Gin@driver{dvipsone.def}}
\DeclareOption{dviwindo}{\ExecuteOptions{dvipsone}}
@@ -360,7 +360,7 @@
% The |dvipsnames| option predeclares all the names in the colour
% prologue of dvips. The |dvips| option automatically implies
% |dvipsnames| unless this choice is overruled with the |nodvipsnames|
-% option. For other drivers, eg |textures| you may use this option to
+% option. For other drivers, eg |textures|, you may use this option to
% explicitly request that these names be declared.
% \begin{macrocode}
\DeclareOption{dvipsnames}{\def\c@lor@namefile{dvipsnam.def}}
@@ -371,7 +371,7 @@
%
% \begin{option}{usenames}
% The |usenames| option modifies the behaviour of |\DefineNamedColor|
-% So that it declares the same name as a ```user's colour'' for use in
+% so that it declares the same name as a ``user's colour'' for use in
% a |\color| command, as well as a name in the |named| colour model.
% The normal behaviour is just to declare the name in the named colour
% model.
@@ -530,7 +530,7 @@
% |\color| or |\textcolor| commands to refer to a colour specified by
% \emph{colour-spec} in the colour model \emph{model}.
%
-% |\definecolor| associates the \emph{name} the to a colour in
+% |\definecolor| associates the \emph{name} to a colour in
% \emph{model}. So |\color{|\emph{name}|}| would check \emph{name}
% then issue a |\special| for the colour model \emph{model}.
%
@@ -579,12 +579,12 @@
% names.
%
% The `color1' drivers (dvips) currently ignore the specification of
-% the colour, and once a name is defined, just put the colour name in
-% the dvi file. For dvips, The header file \texttt{color.pro} is used to
+% the colour and, once a name is defined, just put the colour name in
+% the dvi file. For dvips, the header file \texttt{color.pro} is used to
% give the cmyk equivalents of the names.
%
% The `color2' drivers (textures) use a special postscript operator
-% that takes both the name and the cmyk equivalent. so if the names are
+% that takes both the name and the cmyk equivalent, so if the names are
% not being used, `fall back' definitions in the cmyk model are available.
% These drivers also allow a numeric value to affect the `density'
% of the colour to use.
@@ -688,9 +688,9 @@
%
% \begin{macro}{\normalcolor}
% Early versions of this package redefined |\reset@font| to reset the
-% color as well. Current versions do not do this (there are too many
-% |\reset@font| commands hidden in strange places) and so defines a
-% separate command, |\normalcolor| to reset the colour to the colour in
+% color as well. Current versions do not do this (since there are too many
+% |\reset@font| commands hidden in strange places) and so they define a
+% separate command, |\normalcolor|, to reset the colour to the colour in
% effect at the start of the document.
%
% |\normalcolor| is defined (to |\relax|) in the \LaTeX\ kernel, so it
@@ -722,9 +722,9 @@
% the truth as the `macro layer' of \TeX\ does not know where the output
% routine is going to re-insert floats. This is why drivers must
% maintain their own stack of colours in order to fully support these
-% commands.
+% commands.)
%
-% For dvips, the |\current@color| it is something like `|Black|' or
+% For dvips, the |\current@color| is something like `|Black|' or
% `|rgb 0 1 0|', but other packages should not rely on any particular
% format for this macro.
%
@@ -755,7 +755,7 @@
% definition of this command. A graphics package may want to define it
% using a special to produce (for example) a PostScript line. Producing
% the line in the |\special| has the advantage that on a preview that
-% does not understand |\special|s, the line is automatically omited,
+% does not understand |\special|s, the line is automatically omitted,
% without needing to modify the source of the document (for instance by
% adding the |monochrome| option).
%
@@ -894,7 +894,7 @@
% \end{macro}
%
% \begin{macro}{\color@vbox}
-% To be used to open a `coloured hbox'
+% To be used to open a `coloured vbox'
% \changes{v0.3h}{1994/11/22}
% {Macro added}
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/graphics/drivers.dtx b/Master/texmf-dist/source/latex/graphics/drivers.dtx
index e1c19e0296f..fb5132272b9 100644
--- a/Master/texmf-dist/source/latex/graphics/drivers.dtx
+++ b/Master/texmf-dist/source/latex/graphics/drivers.dtx
@@ -3,7 +3,7 @@
%
%% drivers.dtx Copyright (C) 1994 David Carlisle Sebastian Rahtz
%% Copyright (C) 1995 1996 1997 1998 1999 David Carlisle
-%% Copyright (C) 2000-2022 LaTeX Project
+%% Copyright (C) 2000-2024 LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
diff --git a/Master/texmf-dist/source/latex/graphics/epsfig.dtx b/Master/texmf-dist/source/latex/graphics/epsfig.dtx
index b8927f2da55..46dc36d0bf8 100644
--- a/Master/texmf-dist/source/latex/graphics/epsfig.dtx
+++ b/Master/texmf-dist/source/latex/graphics/epsfig.dtx
@@ -2,7 +2,7 @@
% \iffalse
%
%% epsfig.dtx Copyright (C) 1994-1996 1999 Sebastian Rahtz
-%% Copyright (C) 2000-2022 LaTeX Project
+%% Copyright (C) 2000-2024 LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -19,7 +19,7 @@
%<driver> \ProvidesFile{epsfig.drv}
% \fi
% \ProvidesFile{epsfig.dtx}
- [2017/06/25 v1.7b (e)psfig emulation (SPQR)]
+ [2024/01/14 v1.7b (e)psfig emulation (SPQR)]
%
% \iffalse
%<*driver>
@@ -51,7 +51,7 @@
\RequirePackage{graphicx}
% \end{macrocode}
% \subsection{Emulation of `psfig' syntax}
-% Emulate "epsfig.sty", and most varieties of psfig
+% Emulate \texttt{epsfig.sty}, and most varieties of psfig
% \begin{macro}{\psfig,\epsfig}
% \begin{macrocode}
\def\psfig#1{%
@@ -83,7 +83,7 @@
% \end{macrocode}
% \end{macro}
% \subsection{Emulation of `epsf' syntax}
-% Emulate Rokicki's "epsf.tex" supplied with the ever-popular dvips.
+% Emulate Rokicki's \texttt{epsf.tex}, supplied with the ever-popular dvips.
% \begin{macro}{\epsfbox,\epsffile}
% \begin{macrocode}
\newdimen\epsfxsize
diff --git a/Master/texmf-dist/source/latex/graphics/graphics.dtx b/Master/texmf-dist/source/latex/graphics/graphics.dtx
index 92b3c8f335a..2392ac09d10 100644
--- a/Master/texmf-dist/source/latex/graphics/graphics.dtx
+++ b/Master/texmf-dist/source/latex/graphics/graphics.dtx
@@ -2,7 +2,7 @@
% \iffalse
%
%% graphics.dtx Copyright (C) 1994 David Carlisle Sebastian Rahtz
-%% Copyright (C) 1995-2022 LaTeX Project
+%% Copyright (C) 1995-2024 LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -17,9 +17,9 @@
\ProvidesFile{graphics.dtx}
%</dtx>
%<+package>\NeedsTeXFormat{LaTeX2e}[1995/12/01]
-%<+package>\providecommand\DeclareRelease[3]{}
-%<+package>\providecommand\DeclareCurrentRelease[2]{}
%<+package>
+% Try to fulfill rollback requests to early years by using the 2017 version:
+%<+package>\DeclareRelease{}{1994-06-01}{graphics-2017-06-25.sty}
%<+package>\DeclareRelease{}{2017-06-25}{graphics-2017-06-25.sty}
%<+package>\DeclareCurrentRelease{}{2019-10-01}
%<+package>
@@ -27,7 +27,7 @@
%<driver> \ProvidesFile{graphics.drv}
% \fi
% \ProvidesFile{graphics.dtx}
- [2022/03/10 v1.4e Standard LaTeX Graphics (DPC,SPQR)]
+ [2024/05/23 v1.4g Standard LaTeX Graphics (DPC,SPQR)]
%
% \iffalse
%<*driver>
@@ -69,18 +69,18 @@
% \section{Introduction}
%
% This package implements various `graphics' functions. The main
-% features are a) inclusion of `graphics' files. b) Rotation of sections
-% of the page, c) Scaling of sections of the page.
+% features are: a) inclusion of `graphics' files; b) rotation of sections
+% of the page; c) scaling of sections of the page.
%
% The design is split into three `levels'.
% \begin{itemize}
% \item The user interface. This is the collection of commands designed
-% to appear in a document text. Actually two separate user interface
+% to appear in a document text. Actually two separate user interfaces
% have been implemented. The `standard' interface, described here, and a
% more powerful, and more `user-friendly' interface provided by the
% |graphicx| package.
% \item The core functions. These functions, which are also implemented
-% in this file do all the `main work'. The `user-interface functions
+% in this file, do all the `main work'. The `user-interface functions'
% just collect together the information from any optional-arguments or
% star-forms, and then call one of these functions.
% \item The driver files. It is not possible to achieve the
@@ -90,7 +90,7 @@
% and the syntax required to pass instructions to the drivers is also
% not standardised. So the `core functions' never access |\special|
% directly, but rather call a series of commands that must be defined in
-% a special file customised for each driver. The accompanying file,
+% a special file customised for each driver. The accompanying file
% |drivers.dtx| has suitable files for a range of popular drivers.
% \end{itemize}
%
@@ -99,9 +99,9 @@
% driver that is to be used to print the document. You may wish to set
% up a configuration file so that this option always takes effect, even
% if not specified in the document. To do this, produce a file
-% |graphics.cfg| containing the line:\\
+% |graphics.cfg| containing the line\\
% |\ExecuteOptions{dvips}|\\
-% (or whichever other driver you wish.)
+% (or whichever other driver you wish).
%
% Apart from the driver options there are a few other options to control
% the behaviour of the package.
@@ -166,7 +166,7 @@
% |\graphicspath{{eps/}{tiff/}}|
% would cause the system to look in the subdirectories |eps| and |tiff|
% of the current directory. The default setting of this path is
-% |\input@path| that is: graphics files will be found wherever \TeX\
+% |\input@path|, so that graphics files will be found wherever \TeX\
% files are found.
%
% \DescribeMacro
@@ -204,7 +204,7 @@
% \emph{default rule}. For instance the |dvips| driver file declares all
% files to be of type |eps| unless a more specific rule is declared.
%
-% Since Version v0.6, extensions should be specified including the |.|
+% Since Version v0.6, extensions should be specified including the |.|,
% that is, |.eps| not |eps|.
%
% \emph{type} is the `type' of file involved. All files of the same type
@@ -241,7 +241,7 @@
% used to denote the filename. Thus using the dvips driver, one may
% use\\
% |\DeclareGraphicsRule{.ps.gz}{eps}{.ps.bb}{`zcat #1}|\\
-% the final argument causes dvips to use the |zcat| command to unzip the
+% The final argument causes dvips to use the |zcat| command to unzip the
% file before inserting it into the PostScript output.
%
% \subsection{Rotation}
@@ -297,18 +297,18 @@
% \DescribeMacro
% {\Gread@eps}\marg{file}\\
% For each \emph{type} of graphics file supported, the driver file must
-% define |\Ginclude@|\emph{type} and, optionally |\Gread@|\emph{type}.
+% define |\Ginclude@|\emph{type} and, optionally, |\Gread@|\emph{type}.
% The read command is responsible for obtaining size information from
-% the file specified in the |\DeclareGraphicsRule| command. However the
+% the file specified in the |\DeclareGraphicsRule| command. However, the
% kernel defines a function, |\Gread@eps|, which can read PostScript
% files to find the
% |%%BoundingBox| comment. This function will be used for any type for
% which a specific function has not been declared. |\Gread@eps| accepts
% a generalised version of the bounding box comment. \TeX\ units may be
% used (but there must be no space before the unit). If the unit is
-% omitted |bp| is assumed. So\\
+% omitted, |bp| is assumed. So\\
% |%%BoundingBox 0 0 2in 3in|\\
-% Would be accepted by this function, to produce a 2in wide, by 3in high
+% would be accepted by this function, to produce a 2in wide by 3in high
% graphic.
%
% \subsection{Rotation}
@@ -334,7 +334,7 @@
% \DescribeMacro
% {\Gscale@box@dddd}
% \marg{dima}\marg{dimb}\marg{dimc}\marg{dimd}\marg{text}\\
-% Scale \emph{text} in horizontally by a factor \emph{dima}/\emph{dimb},
+% Scale \emph{text} horizontally by a factor \emph{dima}/\emph{dimb},
% and vertically by a factor of \emph{dimc}/\emph{dimd}.
%
% \DescribeMacro
@@ -353,7 +353,7 @@
% |\Ginclude@|\emph{type}\\
% The Graphics kernel function will call this driver-defined function
% with the filename as argument, and certain additional information will
-% be provided as follows.:
+% be provided as follows:
%
% \noindent\begin{tabular}{p{.4\textwidth}p{.5\textwidth}}
% |\Gin@llx|, |\Gin@lly|,\newline
@@ -362,7 +362,7 @@
% Registers storing the natural size.\\
% |\Gin@req@width|\newline |\Gin@req@height| &
% Registers storing the required size, after scaling.\\
-% |\Gin@scalex|, |\Gin@scaley| & macros with the scale factors. A value
+% |\Gin@scalex|, |\Gin@scaley| & Macros with the scale factors. A value
% of |!| means: Scale by the same amount as the other direction.\\
% |\ifGin@clip| & |\newif| token, true if the graphic should be
% `clipped' to the bounding box.
@@ -371,11 +371,11 @@
% Optionally the driver may define a command of the form:\\
% |\Gread@|\emph{type}\\
% This is responsible for reading an external file to find the bounding
-% box information. If such a command is not declared, but a read-file is
-% specified the command |\Gread@eps|, which is defined in the Graphics
-% Kernel will be used.
+% box information. If such a command is not declared but a read-file is
+% specified, the command |\Gread@eps|, which is defined in the Graphics
+% Kernel, will be used.
%
-% \subsection{Literal Postscript}
+% \subsection{Literal PostScript}
% Drivers that are producing PostScript output may want to define
% the following macros. They each take one argument which should be
% passed to an appropriate special. They are not used directly by this
@@ -384,7 +384,7 @@
% |\Gin@PS@raw|, Literal PostScript special.\\
% |\Gin@PS@restored|, Literal PostScript special, the driver will
% surround this with a save-restore pair.\\
-% |\Gin@PS@literal@header|, Postscript to be inserted in the header
+% |\Gin@PS@literal@header|, PostScript to be inserted in the header
% section of the PostScript file.\\
% |\Gin@PS@file@header|, external file to be inserted in the header
% section of the PostScript file.
@@ -550,7 +550,7 @@
% \changes{v0.3g}{1994/03/15}
% {Use dvips def file not development version}
% \begin{option}{xdvi}
-% Tomas Rockicki's PostScript driver (unix, MSDOS, VMS\ldots).
+% Tomas Rokicki's PostScript driver (unix, MSDOS, VMS\ldots).
% The |X11| previewer |xdvi| supports basically the same set of
% |\specials|.
% \begin{macrocode}
@@ -672,7 +672,7 @@
% \begin{option}{pctex32}
% \changes{v1.0b}{1996/10/29}
% {pctex32 option added}
-% PC\TeX\ (MSDOS/Windows) .
+% PC\TeX\ (MSDOS/Windows).
% \begin{macrocode}
\DeclareOption{pctexps}{\def\Gin@driver{pctexps.def}}
\DeclareOption{pctexwin}{\def\Gin@driver{pctexwin.def}}
@@ -913,7 +913,7 @@
% \end{macro}
%
% \begin{macro}{\Gin@iii}
-% Set the coordinates of the {\bfseries l}lower {\bfseries l}eft corner,
+% Set the coordinates of the {\bfseries l}ower {\bfseries l}eft corner,
% and the coordinates of the {\bfseries u}pper {\bfseries r}ight
% corner. The coordinates may be any \TeX\ dimension, defaulting to |bp|.
% \changes{v0.6c}{1994/12/15}
@@ -944,8 +944,8 @@
% is invisibly small but files conforming to Adobe DSC should have
% \emph{integer} Bounding Box Coordinates, and conceivably some drivers
% might demand integer values.
-% (Although most seem to accept real values (if they accept bounding box
-% coordinates at all) in the |\special|. This is the reason why the
+% Although most seem to accept real values (if they accept bounding box
+% coordinates at all) in the |\special|, this is the reason why the
% mechanism uses |\def| and not \TeX\ lengths, as in earlier releases of
% the package.
% \begin{macrocode}
@@ -1454,8 +1454,8 @@
% {New macro}
% \begin{macro}{\Gread@generic@aux}
% \begin{macro}{\Gread@eps}
-% Read an EPS file (|#1|) and search for a line
-% starting with |%%BoundingBox| and returns the result
+% Read an EPS file (|#1|), search for a line
+% starting with |%%BoundingBox|; then return the result
% by setting four dimension registers
% |\Gin@llx|, |\Gin@lly|, |\Gin@urx| and |\Gin@ury|.
% \changes{v0.5e}{1994/11/02}
@@ -1701,7 +1701,7 @@
% \begin{macro}{\Grot@left}
% \begin{macro}{\Grot@right}
% \begin{macro}{\Grot@depth}
-% Final Rotated box dimensions
+% Final rotated box dimensions
% \begin{macrocode}
\let\Grot@height\@ovxx
\let\Grot@left\@ovyy
@@ -1920,8 +1920,8 @@
% \end{macrocode}
% Now we should translate back by $(O_x,O_y)$, but \TeX\ can not really
% deal with boxes that do not have the reference point at the left edge.
-% (Everything with a $-$ve $x$-coordinate would over-print earlier
-% text). So we modify the horizontal translation so that the
+% (Everything with a negative $x$-coordinate would over-print earlier
+% text.) So we modify the horizontal translation so that the
% reference point as understood by \TeX\ \emph{is} at the left edge.
% This means that the `centre of rotation' is not fixed by |\rotatebox|,
% but typically moves horizontally. We also need to find the image of
@@ -2157,7 +2157,7 @@
% \end{macrocode}
% \end{macro}
%
-% Restore Catcodes
+% Restore catcodes.
% \begin{macrocode}
\Gin@codes
\let\Gin@codes\relax
diff --git a/Master/texmf-dist/source/latex/graphics/graphicx.dtx b/Master/texmf-dist/source/latex/graphics/graphicx.dtx
index 8c200915859..92f1af1d396 100644
--- a/Master/texmf-dist/source/latex/graphics/graphicx.dtx
+++ b/Master/texmf-dist/source/latex/graphics/graphicx.dtx
@@ -2,7 +2,7 @@
% \iffalse
%
%% graphicx.dtx Copyright (C) 1994 David Carlisle Sebastian Rahtz
-%% Copyright (C) 1995-2022 LaTeX Project
+%% Copyright (C) 1995-2024 LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
diff --git a/Master/texmf-dist/source/latex/graphics/keyval.dtx b/Master/texmf-dist/source/latex/graphics/keyval.dtx
index 9fce6267e06..02f9a15ec7c 100644
--- a/Master/texmf-dist/source/latex/graphics/keyval.dtx
+++ b/Master/texmf-dist/source/latex/graphics/keyval.dtx
@@ -1,7 +1,7 @@
%
% \iffalse
%% keyval.dtx Copyright (C) 1993 1994 1995 1997 1998 1999 David Carlisle
-%% Copyright (C) 2000-2022 David Carlisle, LaTeX Project
+%% Copyright (C) 2000-2024 David Carlisle, LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
diff --git a/Master/texmf-dist/source/latex/graphics/lscape.dtx b/Master/texmf-dist/source/latex/graphics/lscape.dtx
index d173af6468a..eca5aa432bd 100644
--- a/Master/texmf-dist/source/latex/graphics/lscape.dtx
+++ b/Master/texmf-dist/source/latex/graphics/lscape.dtx
@@ -2,7 +2,7 @@
% \iffalse
%
%% lscape.dtx Copyright (C) 1994 1999-2000 David Carlisle
-%% Copyright (C) 2000-2022 LaTeX Project
+%% Copyright (C) 2000-2024 LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
diff --git a/Master/texmf-dist/source/latex/graphics/rotating.dtx b/Master/texmf-dist/source/latex/graphics/rotating.dtx
index ac64086082a..bac5759956a 100644
--- a/Master/texmf-dist/source/latex/graphics/rotating.dtx
+++ b/Master/texmf-dist/source/latex/graphics/rotating.dtx
@@ -5,7 +5,7 @@
% File: rotating.dtx
%% Copyright (C) 1995-1999 Sebastian Rahtz and Leonor Barroca
%% Copyright (C) 2001-2003,2007-2009 Robin Fairbairns
-%% Copyright (C) 2016-2022 LaTeX Project
+%% Copyright (C) 2016-2024 LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%
diff --git a/Master/texmf-dist/source/latex/graphics/trig.dtx b/Master/texmf-dist/source/latex/graphics/trig.dtx
index 4b673494aff..d2fa91f91f7 100644
--- a/Master/texmf-dist/source/latex/graphics/trig.dtx
+++ b/Master/texmf-dist/source/latex/graphics/trig.dtx
@@ -1,6 +1,6 @@
% \iffalse
%% File: trig.dtx Copyright (C) 1993-1999 David Carlisle
-%% Copyright (C) 2000-2022 LaTeX Project
+%% Copyright (C) 2000-2024 LaTeX Project
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -19,7 +19,7 @@
%<driver> \ProvidesFile{trig.drv}
% \fi
% \ProvidesFile{trig.dtx}
- [2021/08/11 v1.11 sin cos tan (DPC)]
+ [2023/12/02 v1.11 sin cos tan (DPC)]
%
% \iffalse
%</!plain>
@@ -214,7 +214,7 @@
% \end{macro}
%
% \begin{macro}{\TG@reduce}
-% Repeatedly use one of the the relations
+% Repeatedly use one of the relations
% $\sin(x)=\sin(180-x)=\sin(-180-x)$ to get $x$ in the range $-90 \leq
% x\leq 90$. Then call |\TG@series|.
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/latex-lab/documentmetadata-support.dtx b/Master/texmf-dist/source/latex/latex-lab/documentmetadata-support.dtx
index b37ae6c9d79..a629d9c5515 100644
--- a/Master/texmf-dist/source/latex/latex-lab/documentmetadata-support.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/documentmetadata-support.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
%% File: documentmetadata-support.dtx
-% Copyright (C) 2021-2023 The LaTeX Project
+% Copyright (C) 2021-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -18,8 +18,8 @@
% for those people who are interested or want to report an issue.
%
% \begin{macrocode}
-\def\documentmetadatasupportversion{1.0f}
-\def\documentmetadatasupportdate{2023-09-01}
+\def\documentmetadatasupportversion{1.0h}
+\def\documentmetadatasupportdate{2024-03-26}
% \end{macrocode}
%
%
@@ -84,8 +84,17 @@
% features developed as part of the multi-year ``Tagged PDF''
% project~\cite{blueprint}.
%
-%
-%
+% \section{The \cs{DocumentMetadata} command}
+%
+% \begin{function}{\DocumentMetadata}
+% \begin{syntax}
+% \cs{DocumentMetadata}\Arg{key-value list}
+% \end{syntax}
+%
+% The command should be used as the first command in a document, before
+% \cs{documentclass}. It takes a key-value argument.
+% \end{function}
+
% \section{Currently supported key/values}
%
%
@@ -116,7 +125,8 @@
% e.g., \texttt{lang=de-DE}. If not given the default value used is |en-US|.
%
% \item[\texttt{pdfstandard}] Choice key to set the pdf standard.
-% Currently |A-1b|, |A-2a|, |A-2b|, |A-2u|, |A-3a|, |A-3b|, |A-3u| and |A-4| are accepted as
+% Currently |A-1b|, |A-2a|, |A-2b|, |A-2u|, |A-3a|, |A-3b|, |A-3u|, |A-4|, |A-4E|
+% and |A-4F| are accepted as
% values. The casing is irrelevant, |a-1b| works too.
% Note that using these
% key doesn't mean that the document actually follows the standard. \LaTeX{}
@@ -162,12 +172,12 @@
% \item[\texttt{phase-I}]
% This value loads code implementing the first phase of the project~\cite{blueprint}, i.e., it
% will load the tagpdf package. It will also activate tagging by issuing
-% |\tagpdfsetup{activate,interwordspace}|. This phase
+% |\tagpdfsetup{activate,activate/spaces}|. This phase
% is frozen.
% \item[\texttt{phase-II}]
% It differs from \texttt{phase-I} only in one point: It will
% additionally activate tagging of paragraphs with
-% |\tagpdfsetup{paratagging}|. In the upcoming months it will
+% |\tagpdfsetup{para/tagging}|. In the upcoming months it will
% also enable automatic tagging of other basic document elements.
% \item[\texttt{phase-III}]
% This is the current development phase.
@@ -179,7 +189,7 @@
% and it supports only a limited number of add-on packages.
% \end{description}
%
-% The various testphase modules can also be loaded individually (and least in theory,
+% The various testphase modules can also be loaded individually (at least in theory,
% there can be hidden dependencies). If loaded like this, the tagpdf package is not
% loaded and tagging is not activated! The list of modules will change over time.
% \begin{description}
@@ -213,8 +223,19 @@
% \item[\texttt{text}] This module adds tagging support to the \LaTeX{} logo and
% to the \cs{emph} command.
% This code is also loaded by the \texttt{phase-III} key.
+% \item[\texttt{marginpar}] This module adds tagging support to the \cs{marginpar}
+% command. This code is also loaded by the \texttt{phase-III} key.
+% \item[\texttt{title}] This module add tagging support to the \cs{maketitle}
+% command if a standard class is used. It also enhances the \cs{title}
+% and \cs{author} commands to fill the XMP-metadata and set the window title.
+% It is not compatible with packages and classes which redefine these commands
+% too. The module is currently not loaded by any \texttt{phase} key.
% \item[\texttt{math}] This adapts math for tagging. This is only a prototype.
% The module is currently not loaded by any \texttt{phase} key.
+% \item[\texttt{table}] This provides basic tagging for
+% \texttt{tabular}, \texttt{longtable} and similar table environments.
+% The module is currently not loaded by any \texttt{phase} key. Its use and
+% restrictions is documented in \texttt{latex-lab-table.pdf}.%
% \item[\texttt{firstaid}] This contains small adjustments to external packages.
% The module is currently not loaded by any \texttt{phase} key.
% \end{description}
@@ -274,8 +295,28 @@
\ExplSyntaxOn\makeatletter
% \end{macrocode}
+% \subsection{Variables}
+% These variable definitions are currently also done in ltdocinit.
+% They can be removed from there once latex-lab has been updated to
+% provide them too.
+% \begin{variable}{\g_@@_firstaidoff_clist}
+% A list to store the firstaid code which should be disabled
+% \begin{macrocode}
+\clist_if_exist:NF \g_@@_firstaidoff_clist
+ { \clist_new:N \g_@@_firstaidoff_clist }
+% \end{macrocode}
+% \end{variable}
+% \begin{variable}{\g_@@_testphase_tl}
+% a tl to store the testphase loading code so that we can load them at
+% the end of the command.
+% \begin{macrocode}
+\tl_if_exist:NF \g_@@_testphase_tl
+ { \tl_new:N \g_@@_testphase_tl }
+% \end{macrocode}
+% \end{variable}
-
+% \subsection{\cs{DocumentMetadata}}
+%
% \begin{macro}{\DocumentMetadata}
%
% \cs{DocumentMetadata} should not be used after
@@ -309,14 +350,35 @@
\file_input:n {l3backend-testphase-\c_sys_backend_str.def}
\ExplSyntaxOff\makeatother
% \end{macrocode}
-% Set the default language (this requires that the backend has been loaded),
-% process the rest of the keys,
-% and setup the generic driver.
+%
+% Process the init keys and setup the generic driver.
% \begin{macrocode}
- \keys_set_filter:nnn { document / metadata } { init } { lang=en-US, #1 }
+ \keys_set_filter:nnn { document / metadata } { init } { #1 }
\bool_if:NT \g_@@_active_bool
{
\PassOptionsToPackage{customdriver=hgeneric-testphase}{hyperref}
+% \end{macrocode}
+% Finally we setup the language default.
+% This is done after the begindocument hook so that it can pick up settings
+% from babel. If the Catalog dictionary already contains a lang value we do nothing,
+% otherwise we use the value stored in \cs{BCPdata}, either the main language
+% (if its exists) or the fall back language.
+% Note: if babel is loaded without a language this gives the language \texttt{und}.
+% \begin{macrocode}
+ \g@addto@macro\@kernel@after@begindocument
+ {
+ \pdfdict_get:nnN {g__pdf_Core/Catalog}{Lang}\l_@@_tmpa_tl
+ \quark_if_no_value:NT\l_@@_tmpa_tl
+ {
+ \tl_if_empty:eTF { \BCPdata{main.language} }
+ { \tl_set:Ne \l_@@_tmpb_tl { \BCPdata{language} } }
+ { \tl_set:Ne \l_@@_tmpb_tl { \BCPdata{main.language} } }
+ \msg_warning:nne { meta } { lang-missing }{ \l_@@_tmpb_tl }
+ \exp_last_unbraced:Ne
+ \AddToDocumentProperties{[document]{lang}{\l_@@_tmpb_tl}}
+ \pdfmanagement_add:nne {Catalog} {Lang}{(\l_@@_tmpb_tl)}
+ }
+ }
}
% \end{macrocode}
% \cs{pdfmanagement_add:nnn} has collected values in this hook.
@@ -348,15 +410,8 @@
% \end{macrocode}
% \end{macro}
-
-
-
+%\subsection{\cs{DocumentMetadata} keys}
% \begin{macrocode}
-%FMi defined elsewhere
-%FMi
-%FMi \clist_new:N \g_@@_firstaidoff_clist
-%FMi \tl_new:N \g_@@_testphase_tl
-% UFi should the definition move to here?
\keys_define:nn { document / metadata }
{
backend .choices:nn =
@@ -388,7 +443,7 @@
% this uses internal command from pdfmeta, it should probably move there ...
,pdfstandard .code:n =
{
- \exp_args:Nnx
+ \exp_args:Nne
\keys_set:nn {document / metadata} {_pdfstandard=\str_uppercase:n{#1}}
}
,_pdfstandard .choices:nn =
@@ -400,6 +455,30 @@
}
\AddToDocumentProperties [document]{pdfstandard}{#1}
}
+ ,_pdfstandard / A-4F .code:n =
+ {
+ \prop_if_exist:cTF { g__pdfmeta_standard_pdf/A-4F_prop }
+ {
+ \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/A-4F_prop }
+ }
+ {
+ \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/A-4_prop }
+ \prop_gput:Nnn \g__pdfmeta_standard_prop{conformance}{F}
+ }
+ \AddToDocumentProperties [document]{pdfstandard}{A-4F}
+ }
+ ,_pdfstandard / A-4E .code:n =
+ {
+ \prop_if_exist:cTF { g__pdfmeta_standard_pdf/A-4E_prop }
+ {
+ \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/A-4E_prop }
+ }
+ {
+ \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/A-4_prop }
+ \prop_gput:Nnn \g__pdfmeta_standard_prop{conformance}{E}
+ }
+ \AddToDocumentProperties [document]{pdfstandard}{A-4E}
+ }
,_pdfstandard / unknown .code:n =
{
\msg_warning:nnn{pdf}{unknown-standard}{#1}
@@ -413,7 +492,7 @@
{
\RequirePackage{tagpdf}
\AddToDocumentProperties [document]{testphase/tagpdf}{loaded}
- \tagpdfsetup{activate,paratagging,interwordspace}
+ \tagpdfsetup{activate,para/tagging,activate/spaces}
\AddToDocumentProperties [document]{tagging}{active}
\AddToDocumentProperties [document]{tagging/para}{active}
\AddToDocumentProperties [document]{tagging/interwordspace}{active}
@@ -450,7 +529,7 @@
package/tagpdf/after
}
{
- \tagpdfsetup{paratagging-show}
+ \tagpdfsetup{debug/show=para}
}
}
,debug / log .code:n =
@@ -460,7 +539,7 @@
package/tagpdf/after
}
{
- \tagpdfsetup{log=#1}
+ \tagpdfsetup{debug/log=#1}
}
}
,debug / tagpdf .code:n =
@@ -498,6 +577,11 @@
{
LaTeX-lab~package~'#1'~not~found.
}
+\msg_new:nnn { meta } { lang-missing }
+ {
+ The~language~has~not~been~set~in~\token_to_str:N
+ \DocumentMetadata.\\Setting~it~to~'#1'~as~fallback.
+ }
% \end{macrocode}
%
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-amsmath.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-amsmath.dtx
index e1f95730fae..57e27067cbf 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-amsmath.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-amsmath.dtx
@@ -2,7 +2,7 @@
%
%% File: latex-lab-amsmath.dtx
%
-% Copyright (C) 2022,2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -66,7 +66,7 @@
% \subsection{File declaration}
% \begin{macrocode}
\ProvidesFile{latex-lab-amsmath.ltx}
- [2023-01-05 v0.1a amsmath adaptions]
+ [2024-02-12 v0.1b amsmath adaptions]
% \end{macrocode}
% \subsection{Tagpdf support}
% To make the code independent from tagging being loaded and active
@@ -90,7 +90,11 @@
\def\intertext##1{%
\ifvmode\else\\\@empty\fi
\noalign{%
- \penalty\postdisplaypenalty\vskip\belowdisplayskip
+% \end{macrocode}
+% we have to flip the sign and use a negative \cs{belowdisplayskip}
+% as we flipped the sign at the outside.
+% \begin{macrocode}
+ \penalty\postdisplaypenalty\vskip-\belowdisplayskip
\vbox{
% \end{macrocode}
% Stop tagging when measuring:
@@ -105,9 +109,13 @@
% \begin{macrocode}
\tag_mc_end_push:
% \end{macrocode}
-% We are already in a par so we change now to Span:
+% We are already in a par so we change now to text:
+% \begin{macrocode}
+ \tagpdfsetup{para/tag=P}%
+% \end{macrocode}
+% TODO why \cs{tagpdfparaOn} needed?
% \begin{macrocode}
- \tagpdfsetup{paratag=Span}%
+ \tagpdfparaOn
\noindent\ignorespaces##1\par
% \end{macrocode}
% Restart the MC
@@ -119,6 +127,110 @@
}
% \end{macrocode}
%
+% \subsection{\cs{text}}
+%
+% The \cs{text} command uses \cs{mathchoice} which \enquote{typesets} the argument
+% four times. This makes it quite problematic for tagging. Without precautions
+% structure objects would be created four times and would get MC-chunks as kids
+% that doesn't really exist. amsmath contains a switch that allows to execute code
+% only in the first (displaymath) branch, but that isn't usable here. At first because
+% we don't know if the first branch creates the same structure as the one that is
+% actually used. At second because the engines executes some commands like \cs{label}
+% and \cs{pdfannot} only at shipout from the branch that really was used. So we would
+% get structure data from one \cs{mathchoice}-branch and MC-labels and links from another
+% one and that gets very messy.
+%
+% We therefore have to avoid that tagging is active in unused branches. In pdflatex it
+% is not possible to detect the mathstyle before, so we use a label. With lualatex is
+% is possible to redefine \cs{text} not to use \cs{mathchoice}
+%
+% \begin{macrocode}
+\AddToHook{package/amstext/after}
+ {
+% \end{macrocode}
+% currently amsmath is loaded in a begindocument hook, so this
+% test is fine. If amstext is loaded earlier (in the kernel), this needs perhaps a change.
+% \begin{macrocode}
+ \tag_if_active:T
+ {
+ \sys_if_engine_luatex:TF
+ {
+ \def\text@#1{{%
+ \ifcase\mathstyle
+ \hbox{{#1}}\or
+ \hbox{{#1}}\or
+ \hbox{{#1}}\or
+ \hbox{{#1}}\or
+ \hbox{{\let\f@size\sf@size\selectfont#1}}\or
+ \hbox{{\let\f@size\sf@size\selectfont#1}}\or
+ \hbox{{\let\f@size\ssf@size\selectfont#1}}\or
+ \hbox{{\let\f@size\ssf@size\selectfont#1}}\or
+ \ERROR
+ \fi
+ \check@mathfonts
+ }}
+ }
+ {
+ \def\text@#1
+ {{
+ \int_gincr:N\g__math_mathchoice_int
+ \tag_stop:
+ \mathchoice
+ {
+ \@@_tag_if_mathstyle:en{mathchoice-\int_use:N\g__math_mathchoice_int}{0}
+ \textdef@\displaystyle\f@size{#1}
+ }
+ {
+ \@@_tag_if_mathstyle:en{mathchoice-\int_use:N\g__math_mathchoice_int}{2}
+ \textdef@\textstyle\f@size{\firstchoice@false #1}
+ }
+ {
+ \@@_tag_if_mathstyle:en{mathchoice-\int_use:N\g__math_mathchoice_int}{4}
+ \textdef@\textstyle\sf@size{\firstchoice@false #1}
+ }
+ {
+ \@@_tag_if_mathstyle:en{mathchoice-\int_use:N\g__math_mathchoice_int}{6}
+ \textdef@\textstyle \ssf@size{\firstchoice@false #1}
+ }
+ \check@mathfonts
+ }}
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \subsection{\cs{pmb}}
+% \cs{pmb} prints is argument three times. For tagging we must mark
+% two of occurences as artifact.
+% For luatex the attributes in the box must be reset, for this
+% we switch to expl3-boxes.
+% \begin{macrocode}
+\AddToHook{package/amsbsy/after}
+ {
+ \def\pmb@@@@#1#2#3{\leavevmode\hbox_set:Nn\l_@@_tmpa_box{xxx#3}
+ \dimen@-\box_wd:N\l_@@_tmpa_box
+ \kern-.5\ex@\box_use:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{artifact}
+ \tag_mc_reset_box:N\l_@@_tmpa_box
+ \kern\dimen@\kern.25\ex@\raise.4\ex@\box_use:N\l_@@_tmpa_box
+ \kern\dimen@\kern.25\ex@\box_use_drop:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{}
+ }
+ \def\pmb@#1#2{\hbox_set:Nn\l_@@_tmpa_box{$\m@th#1{#2}$}
+ \setboxz@h{$\m@th#1\mkern.5mu$}\pmbraise@\wdz@
+ \binrel@{#2}
+ \dimen@-\box_wd:N\l_@@_tmpa_box
+ \binrel@@@@{
+ \mkern-.8mu\box_use:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{artifact}
+ \tag_mc_reset_box:N\l_@@_tmpa_box
+ \kern\dimen@\mkern.4mu\raise\pmbraise@\box_use:N\l_@@_tmpa_box
+ \kern\dimen@\mkern.4mu\box_use_drop:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{}
+ }
+ }
+ }
+% \end{macrocode}
% \begin{macrocode}
\ExplSyntaxOff
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx
index a467bf31582..e8ee192a7b2 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabbibdate{2023-07-20}
-\def\ltlabbibversion{0.81a}
+\def\ltlabbibdate{2024-02-12}
+\def\ltlabbibversion{0.81b}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -124,6 +124,17 @@
% but has to test if this anchor is already known.
% \end{description}
%
+% \section{Provided or redefined commands}
+%
+% \begin{function}{\@extra@binfo,\@extra@b@citeb}
+%
+% These are taken from hyperref, they are for chapterbib compability (and also
+% signal to chapterbib not to change the citation commands)
+% \end{function}
+%
+% \begin{function}{\@bibitem,\@lbibitem}
+% The internal item commands.
+% \end{function}
%
% \section{Implementation}
% \begin{macrocode}
@@ -264,7 +275,7 @@
\AddToHookWithArguments{bibcite/before}
{
\tag_mc_end_push:
- \exp_args:Nx\tagstructbegin{tag=Reference,ref=cite.#1\@extra@b@citeb}
+ \exp_args:Ne\tagstructbegin{tag=Reference,ref=cite.#1\@extra@b@citeb}
\tagmcbegin{}
}
\AddToHookWithArguments{bibcite/after}[tag]
@@ -318,7 +329,7 @@
{
\leavevmode
\tag_mc_end_push:
- \exp_args:Nx\tag_struct_begin:n{tag=Reference,ref=cite.#1\@extra@b@citeb}
+ \exp_args:Ne\tag_struct_begin:n{tag=Reference,ref=cite.#1\@extra@b@citeb}
\tag_mc_begin:n{}
}
\AddToHook{cmd/hyper@natlinkend/after}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-block.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-block.dtx
index e0a723ca87c..7d08b270d25 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-block.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-block.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-block.dtx (C) Copyright 2021-2023 LaTeX Project
+%% File: latex-lab-block.dtx (C) Copyright 2021-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -9,10 +9,10 @@
%
% https://www.latex-project.org/lppl.txt
%
-\def\ltlabblockdate{2023-09-01}
-\def\ltlabblockversion{0.8h}
+\def\ltlabblockdate{2024-03-23}
+\def\ltlabblockversion{0.8n}
%<*driver>
-\documentclass{l3doc}
+\documentclass[kernel]{l3doc}
\usepackage{amstext}
\EnableCrossrefs
\CodelineIndex
@@ -308,7 +308,7 @@
% \end{TemplateDescription}
%
% The maximum number of \xt{blockenv}s that can be nested into each
-% other is is restricted by the \LaTeX{} counter
+% other is restricted by the \LaTeX{} counter
% \texttt{maxblocklevels} with a default value of \texttt{6}. If this
% value is increased then it is necessary to provide additional
% instances, e.g., \texttt{displayblock-7}, etc. Decreasing is, of
@@ -646,11 +646,59 @@
%
% \end{description}
%
+% \section{Debugging}
+%
+% \begin{function}{\DebugBlocksOn,\DebugBlocksOff, \block_debug_on:, \block_debug_off:}
+%
+% These commands enable/disable debugging messages.
+%
+% \end{function}
%
+% \section{New and redefined kernel command}
+%
+% \begin{function}{\@doendpe}
+% The original \LaTeXe{} command is augmented to allow for tagging.
+% \end{function}
%
+% \begin{function}{\legacyverbatimsetup,\legacylistsetupcode}
+% \emph{to be documented}
+% \end{function}
+%
+% \begin{function}{\@setupverbinvisiblespace}
+% A counterpart definition to the kernel command \cs{@setupverbinvisiblespace},
+% needed as we need to handle real space chars in verbatim.
+% \end{function}
+%
+% \begin{function}{endblockenv,\g_block_nesting_depth_int}
+% \emph{to be documented}
+% \end{function}
+%
+% \begin{function}{\newtheorem,\@thm,\@begintheorem}
+% Redefined to make theorems tagging aware.
+% \end{function}
%
+% \begin{function}{\item,\@itemlabel}
+% The \cs{item} is redefined.
+% \end{function}
%
-%
+% \begin{function}{\c@maxblocklevels}
+% A counter to increase or decrease the number of supported
+% level. If increased, one needs to supply additional level instances.
+% \end{function}
+%
+% \begin{function}{\begin}
+% The \cs{begin} is slightly redefine to handle \cs{@doendpe} better.
+% TODO: move to kernel
+% \end{function}
+%
+% \begin{function}{\para_end:}
+% TODO: consider name, document
+% \end{function}
+%
+% \begin{function}{para/begin}
+% The para/begin hook is enhanced to support list ends
+% \end{function}
+%
% \end{documentation}
%
% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
@@ -674,10 +722,6 @@
blockenv implementation]
% \end{macrocode}
%
-% We make use of templates:
-% \begin{macrocode}
-\RequirePackage{xtemplate}
-% \end{macrocode}
% Generell kernel changes, also loaded by the sec and toc code.
% \begin{macrocode}
\RequirePackage{latex-lab-kernel-changes}
@@ -691,7 +735,7 @@
\tl_new:N \l_@@_item_align_tl
\tl_new:N\l_@@_legacy_env_params_tl
% \end{macrocode}
-
+%
% \subsection{Handling \cs{par} after the end of the list}
%
% An empty line (or a \cs{par}) after a list has semantic meaning as
@@ -767,11 +811,11 @@
% given use in the document. This section is devoted to template
% interfaces, and the template code is covered later.
% \begin{macrocode}
-\DeclareObjectType{blockenv}{1}
-\DeclareObjectType{block}{1}
-\DeclareObjectType{para}{1}
-\DeclareObjectType{list}{1}
-\DeclareObjectType{item}{1}
+\NewTemplateType{blockenv}{1}
+\NewTemplateType{block}{1}
+\NewTemplateType{para}{1}
+\NewTemplateType{list}{1}
+\NewTemplateType{item}{1}
% \end{macrocode}
% \end{objecttype}
%
@@ -854,7 +898,7 @@
item-instance : instance{item} = basic ,
item-skip : skip = \itemsep ,
item-penalty : integer = \UseName{@itempenalty} ,
- item-indent : length = 0pt , % was \itemindent
+ item-indent : length = \itemindent ,
label-width : length = \labelwidth ,
label-sep : length = \labelsep ,
legacy-support : boolean = false ,
@@ -893,8 +937,8 @@
% This section collects \pkg{expl3} commands that will be useful.
%
% \begin{macro}{\@@_skip_set_to_last:N,\@@_skip_remove_last:}
-% Set a skiip register to the value of an immediately preceding
-% skip or zero if there was none
+% Set a skip register to the value of an immediately preceding
+% skip or zero if there was none.
% \begin{macrocode}
\cs_new_protected:Npn \@@_skip_set_to_last:N #1 {
\skip_set:Nn #1 { \tex_lastskip:D }
@@ -907,12 +951,9 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\tl_if_novalue:nTF}
-%
% \begin{macrocode}
\cs_generate_variant:Nn \tl_if_novalue:nTF { o }
% \end{macrocode}
-% \end{macro}
%
%
% \subsubsection{Debugging}
@@ -1342,14 +1383,14 @@
\@definecounter {#2}
\IfNoValueTF {#4}
{ % @ynthm
- \tl_gset:cx { the #2 }
+ \tl_gset:ce { the #2 }
{
\@thmcounter{#2}
}
}
{ % @xnthm
\@newctr{#1}[#4]
- \tl_gset:cx { the #2 }
+ \tl_gset:ce { the #2 }
{
\expandafter\noexpand\csname the#4\endcsname
\@thmcountersep
@@ -1802,7 +1843,7 @@
fixed-word-spaces = \l__par_fixed_word_spaces_bool , % name??
final-hyphen-demerits = \finalhyphendemerits ,
cr-cmd = \\ ,
- para-class = \l_tag_para_attr_class_tl ,
+ para-class = \l__tag_para_attr_class_tl ,
}
{
\tl_if_empty:nF {#1} { \SetTemplateKeys{para}{std}{#1} }
@@ -2260,6 +2301,9 @@
\exp_after:wN \use_ii:nn \l_@@_item_align_tl
}
}
+% \end{macrocode}
+% Add another box level to the label box:
+% \begin{macrocode}
\hbox_set:Nn \l_@@_one_label_box
{ \box_use_drop:N \l_@@_one_label_box }
}
@@ -2488,10 +2532,13 @@
{
\@inmatherr \item
% \end{macrocode}
-% TODO: Test for being outside of a list needs updating!
+% TODO: Check if test for being outside of a list is sensible
% \begin{macrocode}
- \tl_if_empty:oTF \@@_item_instance:n %%FMi?
- { \msg_error:nnn { @@ } { item-in-nonlist } { \item[{#1}] } }
+ \cs_if_free:NTF \@@_item_instance:n
+ {
+ \@latex@error{Lonely~\string\item--perhaps~a~missing~
+ list~environment}\@ehc
+ }
{
\legacy_if:nTF { @newlist }
{ \__kernel_list_item_begin: }
@@ -2630,7 +2677,7 @@
%
% \item Then open an new (inner) structure (by default
% \texttt{Figure} but typically the one specified on the instance).
-% \item At the end of the block close the the inner structure
+% \item At the end of the block close the inner structure
% (\texttt{Figure} or explicit one)
% but leave the \texttt{text-unit} open to be either continued or closed due to a
% following \cs{par}.
@@ -3290,6 +3337,7 @@
\DeclareInstance{item}{description}{std}
{
label-format = \normalfont\bfseries #1 ,
+ label-align = left
}
% \end{macrocode}
% \end{instance}
@@ -3303,10 +3351,10 @@
{
\tagpdfsetup
{
- newattribute = {justify} {/O /Layout /TextAlign/Justify},
- newattribute = {center} {/O /Layout /TextAlign/Center},
- newattribute = {raggedright}{/O /Layout /TextAlign/Start},
- newattribute = {raggedleft} {/O /Layout /TextAlign/End},
+ role/new-attribute = {justify} {/O /Layout /TextAlign/Justify},
+ role/new-attribute = {center} {/O /Layout /TextAlign/Center},
+ role/new-attribute = {raggedright}{/O /Layout /TextAlign/Start},
+ role/new-attribute = {raggedleft} {/O /Layout /TextAlign/End},
}
}
% \end{macrocode}
@@ -3389,9 +3437,7 @@
%
% In this section we provide code to the various kernel hooks to support
% the tagging of the different displayblock environments.
-%
-%
-%
+%
% All of the following definitions should only be made if tagging
% is active!
% \begin{macrocode}
@@ -3424,8 +3470,13 @@
{
\int_compare:nNnT \l_@@_flattened_level_int < 2
{
- \int_gincr:N \g__tag_para_main_begin_int
- \tagstructbegin{tag=\l__tag_para_main_tag_tl}
+ \__tag_gincr_para_main_begin_int:
+ \tag_struct_begin:n
+ {
+ tag=\l__tag_para_main_tag_tl,
+ attribute-class=\l__tag_para_main_attr_class_tl,
+ }
+ \__tag_para_main_store_struct:
}
}
}
@@ -3445,7 +3496,7 @@
\cs_set:Npn \@@_beginpar_hmode:N #1
{
\tag_mc_end:
- \int_gincr:N \g__tag_para_end_int
+ \__tag_gincr_para_end_int:
\@@_debug_typeout:n{increment~ /P \on@line }
\bool_if:NT \l__tag_para_show_bool
{ \tag_mc_begin:n{artifact}
@@ -3492,7 +3543,7 @@
{
\@@_debug_typeout:n{Structure-end~
\l__tag_para_main_tag_tl\space after~ displayblock \on@line }
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tag_struct_end: %text-unit
}
}
@@ -3551,16 +3602,21 @@
{
\bool_if:NF \l__tag_para_flattened_bool
{
- \int_gincr:N \g__tag_para_main_begin_int
- \tag_struct_begin:n{tag=\l__tag_para_main_tag_tl}
+ \__tag_gincr_para_main_begin_int:
+ \tag_struct_begin:n
+ {
+ tag=\l__tag_para_main_tag_tl,
+ attribute-class=\l__tag_para_main_attr_class_tl,
+ }
+ \__tag_para_main_store_struct:
}
}
- \int_gincr:N \g__tag_para_begin_int
+ \__tag_gincr_para_begin_int:
\@@_debug_typeout:n{increment~ P \on@line }
\tag_struct_begin:n
{
tag=\l__tag_para_tag_tl
- ,attribute-class=\l_tag_para_attr_class_tl
+ ,attribute-class=\l__tag_para_attr_class_tl
}
\__tag_check_para_begin_show:nn {green}{#1}
\tag_mc_begin:n {}
@@ -3572,15 +3628,20 @@
\cs_new_protected:Npn \@@_start_para_structure_unconditionally:n #1 {
\bool_if:NF \l__tag_para_flattened_bool
{
- \int_gincr:N \g__tag_para_main_begin_int
- \tag_struct_begin:n{tag=\l__tag_para_main_tag_tl}
+ \__tag_gincr_para_main_begin_int:
+ \tag_struct_begin:n
+ {
+ tag=\l__tag_para_main_tag_tl,
+ attribute-class=\l__tag_para_main_attr_class_tl,
+ }
+ \__tag_para_main_store_struct:
}
- \int_gincr:N \g__tag_para_begin_int
+ \__tag_gincr_para_begin_int:
\@@_debug_typeout:n{increment~ P \on@line }
\tag_struct_begin:n
{
tag=\l__tag_para_tag_tl
- ,attribute-class=\l_tag_para_attr_class_tl
+ ,attribute-class=\l__tag_para_attr_class_tl
}
\__tag_check_para_begin_show:nn {green}{#1}
\tag_mc_begin:n {}
@@ -3594,14 +3655,14 @@
{
\bool_if:NT \l__tag_para_bool
{
- \int_gincr:N \g__tag_para_end_int
+ \__tag_gincr_para_end_int:
\@@_debug_typeout:n{increment~ /P \on@line }
\tag_mc_end:
\__tag_check_para_end_show:nn {red}{}
\tag_struct_end:
\bool_if:NF \l__tag_para_flattened_bool
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tag_struct_end:
}
}
@@ -3657,7 +3718,7 @@
\DeclareRobustCommand*\begin[1]{%
\UseHook{env/#1/before}%
\@ifundefined{#1}%
- {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}%
+ {\def\reserved@a{\@latex@error{Environment~#1~undefined}\@eha}}%
{\def\reserved@a{\def\@currenvir{#1}%
\edef\@currenvline{\on@line}%
\@execute@begin@hook{#1}%
@@ -3680,7 +3741,7 @@
{
\bool_if:NF \l__tag_para_flattened_bool
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tag_struct_end:
}
\@endpefalse
@@ -3722,7 +3783,7 @@
\@@_debug_typeout:n{block-end \on@line}
\legacy_if:nT { @endpe }
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\@@_debug_typeout:n{close~ /text-unit \on@line}
\tagstructend
}
@@ -3752,11 +3813,17 @@
{
\tagpdfsetup
{
+ role/new-attribute = {itemize}{/O /List /ListNumbering/Unordered},
+ role/new-attribute = {enumerate}{/O /List /ListNumbering/Ordered},
+ role/new-attribute = {description}{/O /List /ListNumbering/Description},
+% \end{macrocode}
+% Initially, we had \texttt{/None} for the basic \env{list}
+% environment, but that is not allowed in PDF/UA-2 if the list
+% contains any Lbl tags. So now we default to
+% \texttt{Unordered}.
+% \begin{macrocode}
% default if unknown
- newattribute = {list}{/O /List /ListNumbering/None},
- newattribute = {itemize}{/O /List /ListNumbering/Unordered},
- newattribute = {enumerate}{/O /List /ListNumbering/Ordered},
- newattribute = {description}{/O /List /ListNumbering/Description},
+ role/new-attribute = {list}{/O /List /ListNumbering/Unordered},
}
}
% \end{macrocode}
@@ -3792,7 +3859,7 @@
\cs_set:Npn \__kernel_list_label_begin: {
%
% FMi: this needs a different logic to decide when to make the label
-% an artifact (after cleaning up the the \item code ), therefore
+% an artifact (after cleaning up the \item code ), therefore
% disabled for now
% \tl_if_empty:oTF \@itemlabel
% {
@@ -3835,7 +3902,7 @@
\cs_set:Npn \@@_list_item_end: {
\legacy_if:nT { @endpe }
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tagstructend % text-unit
% \@@_debug_typeout:n{Structure-end~ P~ at~ item-end \on@line }
}
@@ -3854,7 +3921,7 @@
\cs_set:Npn \@@_list_end: {
\legacy_if:nT { @endpe }
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tagstructend % text-unit
\@@_debug_typeout:n{Structure-end~ P~ at~ list-end \on@line }
}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-firstaid.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-firstaid.dtx
index e2ee78b2fff..ce0d46f8155 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-firstaid.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-firstaid.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-firstaid.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-firstaid.dtx (C) Copyright 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabfirstaiddate{2023-07-20}
-\def\ltlabfirstaidversion{0.85a}
+\def\ltlabfirstaiddate{2024-05-25}
+\def\ltlabfirstaidversion{0.85d}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -55,6 +55,7 @@
% patches once the packages have been updated.
% \section{Implementation}
+%
% \begin{macrocode}
%<*package>
%<@@=tag>
@@ -64,8 +65,153 @@
\ltlabfirstaiddate\space v\ltlabfirstaiddate\space
Temporary patches to external packages needed for the tagging project]
% \end{macrocode}
+% \begin{macro}{\FirstAidNeededT}
+% This is a very simple help to ensure that we only apply first aid
+% to an unmodified package or class. It only works in the case the
+% file has already been loaded and the csname \cs{ver@\#1.\#2} got
+% defined (holding the current date, version, and short description
+% info). We then compare its content to a frozen string and make
+% the modification \verb=#3= only if both agree. If they differ we
+% assume that the package/class in question got updated by its
+% maintainer.
+% \begin{macrocode}
+\ExplSyntaxOn
+\providecommand\FirstAidNeededT[3]{
+ \exp_args:Ncx\str_if_eq:onF{ver@#1.#2}{#3}
+ { \typeout{==>~ First~ Aid~ for~ #1.#2~ no~ longer~ applied!^^J
+ \@spaces Expected:^^J
+ \@spaces\@spaces #3^^J
+ \@spaces but~ found:^^J
+ \@spaces\@spaces \use:c{ver@#1.#2}^^J
+ \@spaces so~ I'm~ assuming~ it~ got~ fixed.
+ } }
+ \exp_args:Ncx\str_if_eq:onT{ver@#1.#2}{#3}
+}
+\ExplSyntaxOff
+% \end{macrocode}
+% \end{macro}
+% \subsection{ams classes}
+% The amsart and amsbook classes do not use \cs{@author} to store the author list
+% but a command \cs{authors}. To be able to nevertheless use the authors in the
+% xmp-metadata we map \cs{@author} to this new command.
+%
+% \begin{macrocode}
+\AddToHook{class/amsart/after}
+ {\def\@author{\authors}}
+\AddToHook{class/amsbook/after}
+ {\def\@author{\authors}}
+% \end{macrocode}
+%
+%
+%
+% \subsection{verse}
+%
+% The \pkg{verse} package has its own definition of the
+% \env{verse} environment, which would tag correctly, except that
+% it is overwritten by the block code in the hook
+% \texttt{begindocument/before}. So the simplest way to make
+% tagging work is to reinstall the package version afterwards,
+% which is what we are doing here.
+% \begin{macrocode}
+\AddToHook{package/verse/after}[latex-lab-firstaid]{%
+ \FirstAidNeededT{verse}{sty}{2014/05/10 v2.4b verse typesetting}%
+ {%
+ \AtBeginDocument{%
+ \renewenvironment{verse}[1][\linewidth]{%
+ \stepcounter{verse@envctr}%
+ \setcounter{poemline}{0}\refstepcounter{poemline}%
+ \setcounter{vslineno}{1}%
+ \let\\=\@vscentercr
+ \list{}{\itemsep \z@
+ \itemindent -\vindent
+ \listparindent\itemindent
+ \parsep \stanzaskip
+ \ifdim #1 < \linewidth
+ \rightmargin \z@
+ \setlength{\leftmargin}{\linewidth}%
+ \addtolength{\leftmargin}{-#1}%
+ \addtolength{\leftmargin}{-0.5\leftmargin}%
+ \else
+ \rightmargin \leftmargin
+ \fi
+ \addtolength{\leftmargin}{\vindent}}%
+ \item[]%
+ }%
+ {\endlist}%
+ }%
+ }%
+}
+% \end{macrocode}
+% Of course, this means that the
+% optional argument of the environment then only accepts a length
+% value and not any more a key value list for altering the
+% environment settings.
+%
+% A more elabroate version could be something like this that allows
+% key/val and legacy interface. Or one could extend the list
+% template to support a \texttt{list-width} key.
+%\begin{verbatim}
+% \ExplSyntaxOn
+% \cs_new_protected:Npn \ExtractAndDropKey #1#2#3#4#5 {
+% \tl_set_eq:NN #4 \c_novalue_tl % or empty?
+% \keys_define:nn { #1 } { #2 .code:n = \tl_set:Nn #4{##1} }
+% \keys_set_known:nnN { #1 } { #3 } #5
+% }
+% \ExplSyntaxOff
+%
+% % Change the env definition for verse matching verse.sty
+% % This keeps the verse.sty interface as it is and only adjusts the
+% % main environment to use the basic list env with the verse.sty
+% % specific settings.
+% \makeatletter
+%
+% \AddToHook{package/verse/after}{%
+% \AtBeginDocument{%
+% \RenewDocumentEnvironment{verse}{={verse-width}!O{\linewidth}}%
+% {%
+% \stepcounter{verse@envctr}%
+% \setcounter{poemline}{0}\refstepcounter{poemline}%
+% \setcounter{vslineno}{1}%
+% \let\\=\@vscentercr
+% %
+% \ExtractAndDropKey{verse}{verse-width}{#1}\@vswidth\@vsremainingkvlist
+% % If other keys have been specified but not verse-width we have no
+% % default for \@vswidth and need to set it again
+% \ExpandArgs{o}\IfNoValueT \@vswidth
+% {\def\@vswidth{\linewidth}}%
+% %
+% % This is a bit ugly but we can't stick \cs{@vsremainingkvlist} into
+% % the instance argument as keys are expected to be visible on
+% % top-level not hidden inside a macro. The alternative is to push
+% % in \verb=#1= but then the key/value \verb/verse-width=.../ is
+% % passed into the instance which is not known there (not harmful as
+% % it will get ignored but noticeably more and unnecessary
+% % processing).
+% %
+% \def\next##1{%
+% \UseInstance{blockenv}{list}%
+% {%
+% item-indent =-\vindent,%
+% parindent =-\vindent,%
+% par-skip =\stanzaskip,%
+% item-skip =0pt,%
+% leftmargin = (\linewidth-\@vswidth)/2+\vindent,%
+% rightmargin = \ifdim\@vswidth<\linewidth 0pt
+% \else (\linewidth-\@vswidth)/2\fi,%
+% ##1%
+% }}%
+% \ExpandArgs{o}\next\@vsremainingkvlist
+% \item\relax
+% }{\endblockenv}%
+% }%
+% }
+% \makeatother
+%\end{verbatim}
+%
+%
% \subsection{blindtext}
+%
% The blindtext package generates lists with nested \cs{loop} command.
% The inner loop introduces a group around the list which error when lists are tagged
% as \cs{@doendpe} is lost.
@@ -106,7 +252,10 @@
}%
}
% \end{macrocode}
+%
+%
% \subsection{cleveref}
+%
% The cleveref package redefines \cs{@makefntext} and this means that the patches in
% the new footnote code fails. We use a hook instead
% \begin{macrocode}
@@ -130,9 +279,48 @@
}%
}
% \end{macrocode}
+%
+% \subsection{booktabs}
+% In some cases booktabs inserts a
+% \cs{multispan} into the table (through the commands \cs{@cmidruleb}
+% and \cs{@cmidrulea} and this then errors
+% with the tagging code.
+% This affects both tabular and longtable
+% (but longtable more as booktabs handles lines in longtable differently).
+% See also issue \url{https://github.com/latex3/tagging-project/issues/69}
+%
+%
+\ExplSyntaxOn
+\AddToHook{package/booktabs/after}
+ {
+ \def\@cmidrulea{
+ \multispan\@cmidla
+ &\multispan\@cmidlb
+ \unskip\hskip\cmrkern@l
+ {
+ \tag_mc_begin:n{artifact}
+ \CT@arc@\leaders\hrule \@height\@thisrulewidth\hfill\kern\z@}
+ \hskip\cmrkern@r
+ \tag_mc_end: \int_gdecr:N \g__tbl_row_int
+ \cr}
+
+ \def\@cmidruleb{%
+ \multispan\@cmidlb
+ \unskip\hskip \cmrkern@l%
+ {
+ \tag_mc_begin:n{artifact}
+ \CT@arc@\leaders\hrule \@height\@thisrulewidth\hfill\kern\z@}
+ \hskip\cmrkern@r
+ \tag_mc_end: \int_gdecr:N \g__tbl_row_int
+ \cr}
+ }
+\ExplSyntaxOff
+%
% \begin{macrocode}
%</package>
% \end{macrocode}
+%
+%
% \begin{macrocode}
%<*latex-lab>
\ProvidesFile{firstaid-latex-lab-testphase.ltx}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-float.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-float.dtx
index 3bd34836008..a8171337133 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-float.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-float.dtx
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabfloatdate{2023-07-20}
-\def\ltlabfloatversion{0.81a}
+\def\ltlabfloatdate{2024-03-23}
+\def\ltlabfloatversion{0.81e}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -86,8 +86,8 @@
% In PDF~2.0 there is the suitable \texttt{Aside} tag which hopefully will
% be handled correctly regarding the reading order once processor actually support
% PDF~2.0. But in PDF~1.7 we rolemap it to \texttt{Note} and this doesn't lead to
-% a good reading order. The code therefore collect the float structures and moves
-% them to a \texttt{Sect} the end of the document or the chapter
+% a good reading order. The code therefore collects the float structures and moves
+% them to a \texttt{Sect} at the end of the document or the chapter
% (H-floats once they are handled will not be moved).
%
% To fulfill the requirement that a \texttt{Caption} should be at the begin or end, we always
@@ -106,6 +106,8 @@
%
% The code add two keys for the \cs{tagtool} command
%
+%
+% \begin{function}{flush-floats,split-float}
% \begin{description}
% \item[flush-floats] This will flush out the collected floats sofar (currently
% table and figure. The value is a sectioning level, e.g. \texttt{section} or \texttt{chapter},
@@ -117,9 +119,19 @@
% \item[split-float] This can be used inside a float if there are two captions.
% It will only work reasonably well if the content of the float parts are in a sensible order
% and can be separated by this command. More complex setups with tabulars will need more
-% thoughts
+% thoughts.
+% \end{description}
+% \end{function}
+%
+% \section{Kernel commands}
+% \begin{function}{\@current@float@struct}
+% This variable holds the structure number of current float structure.
+% \end{function}
%
-% \end{description}
+% \begin{function}{\@makecaption}
+% \cs{@makecaption} is defined by the classes so we overwrite it for now
+% at begin document.
+% \end{function}
%
%
% \begin{macrocode}
@@ -182,7 +194,7 @@
\seq_map_inline:Nn\g_@@_float_types_seq
{
\tag_struct_begin:n{tag=##1s,stash}
- \prop_gput:Nnx\g_@@_float_sect_prop {##1-struct}{\int_use:N\c@g__tag_struct_abs_int}
+ \prop_gput:Nne\g_@@_float_sect_prop {##1-struct}{\int_use:N\c@g__tag_struct_abs_int}
\tag_struct_end:
}
}
@@ -239,6 +251,7 @@
{\par\__tag_sec_end:n{-10}\@@_float_stop_sect:}
\DeclareHookRule{tagpdf/finish/before}{latex-lab/float}{before}{tagpdf}
% \end{macrocode}
+%
% \subsection{Splitting floats}
% \begin{macro}{split-float}
% TODO: check if the target affect spacing!!
@@ -249,7 +262,7 @@
{
\@@_float_end:
\@@_float_begin:
- \MakeLinkTarget[tagstructure]{g__tag_struct_abs_int}
+ \MakeLinkTarget*{floatstructure.\int_use:N\c@g__tag_struct_abs_int}
}
}
% \end{macrocode}
@@ -290,12 +303,12 @@
{
\exp_args:Ne
\tag_struct_begin:n{tag=float,parent=0\prop_item:No\g_@@_float_sect_prop{\@captype-struct}}%
- \prop_gput:Nxx \g_@@_float_sect_prop {\@captype-used}{true}
+ \prop_gput:Nee \g_@@_float_sect_prop {\@captype-used}{true}
}
{
\tag_struct_begin:n{tag=float}
}
- \tl_set:Nx\@current@float@struct{\tag_get:n{struct_num}}%
+ \tl_set:Ne\@current@float@struct{\tag_get:n{struct_num}}%
\typeout{Float structure: \@current@float@struct}
}
@@ -324,7 +337,7 @@
% \end{macrocode}
% If the float is in hmode we have to interrupt the P
% \begin{macrocode}
- \@nameuse{@@_float_stoppar:} %<---end P
+ \@nameuse{@@_float_stop_par:}% <---end P
\@floatpenalty -\@Mii
\else
\@floatpenalty-\@Miii
@@ -381,7 +394,7 @@
% \end{macrocode}
% We add a target for links. TODO: check that it doesn't affect spacing!!
% \begin{macrocode}
- \MakeLinkTarget[tagstructure]{g__tag_struct_abs_int}%
+ \MakeLinkTarget*{floatstructure.\number\value{g__tag_struct_abs_int}}%
}%
% \end{macrocode}
% The end code of the float ...
@@ -400,7 +413,7 @@
\penalty\@floatpenalty
\else
\vadjust{\penalty -\@Miv \vbox{}\penalty\@floatpenalty}\@Esphack
- \@nameuse{@@_float_start_par:} %restart P safe here??
+ \@nameuse{@@_float_start_par:}% restart P safe here??
\fi
\fi
}
@@ -423,7 +436,7 @@
\penalty\@floatpenalty
\else
\vadjust{\penalty -\@Miv \vbox{}\penalty\@floatpenalty}\@Esphack
- \@nameuse{@@_float_start_par:} %restart P safe here??
+ \@nameuse{@@_float_start_par:}% restart P safe here??
\fi
\fi
\else
@@ -446,10 +459,24 @@
\let\@kernel@refstepcounter\refstepcounter %as long it is not in the kernel
\def\caption{%
\ifx\@captype\@undefined
- \@latex@error{\noexpand\caption outside float}\@ehd
+ \@latex@error{\noexpand\caption\c_space_tl outside~float}\@ehd
\expandafter\@gobble
- \else
- \@kernel@refstepcounter\@captype
+ \else
+% \end{macrocode}
+% if a caption is used outside a float no
+% target has been set and \cs{@current@float@struct} is empty
+% \begin{macrocode}
+ \tl_if_empty:NTF\@current@float@struct
+ {
+ \refstepcounter\@captype
+ }
+ {
+ \@kernel@refstepcounter\@captype
+% \end{macrocode}
+% we need to reset the target for \cs{addcontentsline}.
+% \begin{macrocode}
+ \xdef\@currentHref{floatstructure.\@current@float@struct}%
+ }
\expandafter\@firstofone
\fi
{\@dblarg{\@caption\@captype}}%
@@ -471,7 +498,6 @@
{
\long\def\@makecaption#1#2{%
\vskip\abovecaptionskip
- \xdef\@currentHref{tagstructure.\@current@float@struct}%
% \end{macrocode}
% we don't want tagging when storing the caption for the singleline check
% \begin{macrocode}
@@ -482,12 +508,21 @@
% we stop paratagging. TODO: check
% \begin{macrocode}
\tagtool{para=false}
- \tag_struct_begin:n{tag=Caption,parent=\@current@float@struct}
+% \end{macrocode}
+% if caption is used outside a float there is perhaps no number, then we use
+% the parent structure and hope ...
+% \begin{macrocode}
+ \tl_if_empty:NT \@current@float@struct
+ { \tl_set:Ne \@current@float@struct {\tag_get:n{struct_num}} }
+ \tag_struct_begin:n{tag=Caption,parent=\@current@float@struct}
% \end{macrocode}
% move the caption to the begin of the float structure:
% \begin{macrocode}
- \seq_gpop_right:cN {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl
- \seq_gput_left:cV {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl
+ \tag_if_active:T
+ {
+ \seq_gpop_right:cN {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl
+ \seq_gput_left:cV {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl
+ }
\ifdim \wd\@tempboxa >\hsize
\tag_struct_begin:n{tag=Lbl}
\tag_mc_begin:n{}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx
index 2389906c5ac..a3d044ab87d 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-footnotes.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
%% File: latex-lab-footnotes.dtx
-% Copyright (C) 2022-2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -17,8 +17,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabfootnotedate{2023-09-04}
-\def\ltlabfootnoteversion{0.8c}
+\def\ltlabfootnotedate{2024-03-12}
+\def\ltlabfootnoteversion{0.8d}
%<*driver>
\documentclass{l3doc}
@@ -454,6 +454,14 @@
% option.
% \end{itemize}
%
+% \subsection{Debugging sockets and hooks}
+%
+% For some rudimentary debugging we currently have \cs{DebugFNotesOn}
+% (and \cs{DebugFNotesOff}). At the moment \cs{DebugFNotesOn} only
+% shows the current settings for hooks and sockets related to the
+% footnote code and then
+% automatically turns itself off again.
+%
%
% \section{Tagging and hyperlinking support}
%
@@ -978,13 +986,22 @@
% \end{hookdecl}
%
% \subsection{Debugging code}
-% the debugging code is just temporary
+% The debugging code is just temporary
%
-% For now we have debugging turned on by default
% \begin{macrocode}
\bool_new:N \g_fnote_debug_bool
-\bool_gset_true:N \g_fnote_debug_bool
% \end{macrocode}
+
+% \begin{macro}{\DebugFNotesOn,\DebugFNotesOff}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \DebugFNotesOn { \bool_gset_true:N \g_fnote_debug_bool }
+\cs_new_protected:Npn \DebugFNotesOff { \bool_gset_false:N \g_fnote_debug_bool }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
% We log the hooks in the footnote mark command, but only once
% \begin{macrocode}
\cs_new_protected:Npn \@@_debug_footnotemark:
@@ -1485,10 +1502,18 @@
\tl_if_in:NnTF \l_@@_patch_tl { \hb@xt@ }
{ \cs_set_eq:NN \@@_tmp:w \@@_patch_hb@xt@:w }
{
- \tl_if_in:NnTF \l_@@_patch_tl { \@makefnmark }
- { \cs_set_eq:NN \@@_tmp:w \@@_patch_@makefnmark:w }
- { \ERROR
- \cs_set_eq:NN \@@_tmp:w \exp_stop_f: }
+% \end{macrocode}
+% Some styles/classes use \verb=\makebox[...][...]= instead of \cs{hb@xt@}
+% so try to patch those too.
+% \begin{macrocode}
+ \tl_if_in:NnTF \l_@@_patch_tl { \makebox }
+ { \cs_set_eq:NN \@@_tmp:w \@@_patch_makebox:w }
+ {
+ \tl_if_in:NnTF \l_@@_patch_tl { \@makefnmark }
+ { \cs_set_eq:NN \@@_tmp:w \@@_patch_@makefnmark:w }
+ { \ERROR
+ \cs_set_eq:NN \@@_tmp:w \exp_stop_f: }
+ }
}
}
\tl_set:Nf \l_@@_patch_tl
@@ -1512,6 +1537,17 @@
% \begin{macrocode}
\cs_new:Npn \@@_patch_hb@xt@:w #1 \hb@xt@ #2 #
{ \exp_stop_f: #1 \@makefntext@processX { \hb@xt@ #2 } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_patch_makebox:w #1 \makebox #2 #
+ { \exp_stop_f: #1 \@makefntext@processX { \makebox #2 } }
+% \end{macrocode}
+%
+% If the definition contains neither \cs{hbox}, \cs{hb@xt@} nor \cs{makebox},
+% we see if it contains \cs{@makefnmark} and if so put the socket
+% before that.
+% \begin{macrocode}
\cs_new:Npn \@@_patch_@makefnmark:w #1 \@makefnmark
{ \exp_stop_f: #1 \@makefntext@processX { \use:n } { \@makefnmark } }
% \end{macrocode}
@@ -1539,7 +1575,12 @@
\cs_set_eq:NN \@makefntext \fnote_makefntext:n
}
{
- \@@_patch:
+% \end{macrocode}
+% If \cs{@makefntext} contains the definition from \pkg{footmisc}
+% we do nothing, otherwise we try to patch.
+% \begin{macrocode}
+ \cs_if_eq:NNF \@makefntext \footmisc@hang@makefntext
+ { \@@_patch: }
}
}
@@ -2421,8 +2462,9 @@
\else
\ifFN@hangfoot
- \long\def\@makefntext#1{%
+ \long\def\footmisc@hang@makefntext#1{%
\bgroup
+ \SuspendTagging{footmisc}%
\setbox\@tempboxa\hbox{%
\ifdim\footnotemargin>\z@
\hb@xt@\footnotemargin{\@makefnmark\hss}%
@@ -2437,14 +2479,33 @@
\parshape \@ne \leftmargin \linewidth
\footnotesize
\@setpar{{\@@par}}%
+ \ResumeTagging{footmisc}%
\leavevmode
- \llap{\box\@tempboxa}%
+% \end{macrocode}
+% Typesetting the mark twice means that one can't have any material
+% inside that gets unhappy in that case. Tha shouldn't be a
+% problem, but perhaps we have to come up with a more elaborate
+% solution in the end.
+% \begin{macrocode}
+ \UseSocket{tagsupport/fntext/mark}%
+ {\llap{%
+ \ifdim\footnotemargin>\z@
+ \hb@xt@\footnotemargin{\@makefnmark\hss}%
+ \else
+ \@makefnmark
+ \fi
+ }}%
\parskip\hangfootparskip\relax
\parindent\hangfootparindent\relax
\footnotelayout#1%
\par
\egroup
}
+% \end{macrocode}
+% Defined in a roundabout way so that we can test for it when
+% patching classes that are not updated.
+% \begin{macrocode}
+ \let \@makefntext \footmisc@hang@makefntext
\else
@@ -2723,9 +2784,8 @@
\@footnotemark
}
% \end{macrocode}
-% TEMP PATCHES FOR TESTING
+%
% \begin{macrocode}
-
\endinput
%</footmisc>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-graphic.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-graphic.dtx
index 158b0d2a9c4..5ea4a2db9c7 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-graphic.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-graphic.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-graphic.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-graphic.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -15,8 +15,8 @@
% https://github.com/latex3/latex2e/required/latex-lab
%
% for those people who are interested or want to report an issue.
-\def\ltlabgraphicdate{2023-10-13}
-\def\ltlabgraphicversion{0.80b}
+\def\ltlabgraphicdate{2024-03-13}
+\def\ltlabgraphicversion{0.80d}
%
%<*driver>
\documentclass{l3doc}
@@ -184,7 +184,10 @@
\RequirePackage{l3opacity}
% \end{macrocode}
%
-%
+% Needed during switch to e-type:
+% \begin{macrocode}
+\cs_generate_variant:Nn \@@_prop_gput:Nnn {cne}
+% \end{macrocode}
% \begin{macro}{\@@_graphic_savepos:n}
% this is the command which stores the position. Similar to
% zref-savepos it uses two savepos commands
@@ -323,7 +326,7 @@
\msg_new:nnn {tag}{alt-text-missing}
{
Alternative~text~for~graphic~is~missing.\\
- Using~'#1'~instead
+ Using~the~file~name~'#1'~instead.
}
\cs_new_protected:Npn\Gin@tag@struct@begin
{
@@ -449,8 +452,9 @@
% \end{macrocode}
% and here the tagging stops.
% \begin{macrocode}
+ \fi
\Gin@tag@struct@end %new
- \fi}
+ }
}
% \end{macrocode}
%
@@ -894,7 +898,7 @@
% The structure and the mc must be open earlier, before the \cs{setbox} (at least
% for luatex it has to). TODO: think about interface if more attributes are needed.
% \begin{macrocode}
- \@@_prop_gput:cnx
+ \@@_prop_gput:cne
{ g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop }
{ A }
{
@@ -970,7 +974,7 @@
{red}
{\int_use:N\g_@@_graphic_int}
}
- \@@_prop_gput:cnx
+ \@@_prop_gput:cne
{ g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop }
{ A }
{
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-marginpar.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-marginpar.dtx
new file mode 100644
index 00000000000..ca79d8a67fa
--- /dev/null
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-marginpar.dtx
@@ -0,0 +1,259 @@
+% \iffalse meta-comment
+%
+%% File: latex-lab-marginpar.dtx
+%%
+% Copyright (C) 2024 LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% https://www.latex-project.org/lppl.txt
+%
+%
+% The development version of the bundle can be found below
+%
+% https://github.com/latex3/latex2e/required/latex-lab
+%
+% for those people who are interested or want to report an issue.
+%
+\def\ltlabmarginpardate{2024-02-12}
+\def\ltlabmarginparversion{0.85b}
+
+%<*driver>
+\documentclass[kernel]{l3doc}
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{latex-lab-marginpar.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+% \title{The \textsf{latex-lab-marginpar} package\\
+% Changes related to the tagging of margin notes}
+% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}}
+% \date{v\ltlabmarginparversion\ \ltlabmarginpardate}
+%
+% \maketitle
+%
+% \newcommand{\xt}[1]{\textsl{\textsf{#1}}}
+% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}}
+% \newcommand{\docclass}{document class \marginpar{\raggedright document class
+% customizations}}
+%
+% \providecommand\hook[1]{\texttt{#1\DescribeHook[noprint]{#1}}}
+% \providecommand\socket[1]{\texttt{#1\DescribeSocket[noprint]{#1}}}
+% \providecommand\plug[1]{\texttt{#1\DescribePlug[noprint]{#1}}}
+%
+% \NewDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+% \NewDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl}
+% \NewDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
+%
+% \begin{abstract}
+% \end{abstract}
+%
+% \section{Introduction}
+%
+% This module contains changes to improve the tagging (in the standard classes) of
+% margin notes created with the \cs{marginpar} command.
+%
+% Such margin notes are rather small but nevertheless tagging is not trivial and poses
+% a number of interesting problems both regarding the structure and the implementation.
+%
+% \subsection{Structure}
+% \cs{marginpar} creates small boxes in the margin of a page.
+% While they are technically floats they also typically
+% relate to the paragraph beside them, so their structure element should be placed near
+% such a paragraph.
+%
+% They can be tagged either as artifacts (if they are merely distracting decoration),
+% as small headings before the paragraph, or as |Aside|. Unlike the PDF 1.7 fallback |Note|
+% the structure |Aside| is not allowed inside |P|,
+% so if |Aside| is used, it must be placed before or after the current |P| in the surounding |text-unit|,
+% or it must split the |P|. Splitting is probably not so good as
+% |\marginpar| is often used somewhere in the middle of sentence.
+% The best default is probably to use |Aside|, find the parent |text-unit| and add it there.
+%
+% \subsection{Implementation}
+%
+% |marginpar| has an optional argument which allows to define a different content
+% on left/right margins for odd/even pages (depending on twoside and \cs{reversemarginpar}).
+%
+% The current implementation stores *both* arguments in boxes and
+% decides in the output routine which
+% one to use. This is quite problematic for tagging, as the unused box produces
+% structure objects, literals, labels, MCID numbers,
+% and perhaps OBJR-objects from links
+% which must be later thrown away again (or are thrown away by the engine).
+% While it is theoretically not impossible to create
+% both boxes while taging is active but to keep everything on hold and insert
+% the real structure only when the box is used it is in practice quite difficult,
+% slow and error prone.
+%
+% There are a number of options to avoid this hassle.
+%
+% \begin{description}
+% \item[Minimal tagging] One option is to disable tagging when the boxes
+% are built and when the box is used to surround them with a simple Aside.
+%
+% \begin{description}
+% \item[Pro:] easy to implement
+% \item[Contra:]
+% Content that perhaps needed tagging (|\LaTeX| logo with /ActualText, images, links) is not tagged.
+% \end{description}
+%
+% \item[Remaking the box]
+% Tagging is deactivated when the boxes are created.
+% The arguments are stored and when the box should be used in the output routine
+% (and when it is known which one will be used) the box is (re)created, now with proper tagging.
+%
+% Contra: The content can change e.g. if it uses counters or macros that are redefine later before the
+% output routine is called. As tagging is done later, it is not trivial to insert the
+% |Aside| in the right place in the paragraph structure.
+%
+% \item[Two pass compilation]
+% A label is used to detect which argument/boxed is used and
+% tagging is activated only for this one.
+%
+% Contra: costs a |label| and requires a two pass compilation (which is needed anyway).
+% This should be ok. |\marginnote| uses a label too, and the same
+% label could also be used to resolve problems if a margin note
+% moves to a new page (and so replace the mparhack package).
+% \end{description}
+%
+% The last option seems the best and is therefore implemented.
+%
+%
+% \section{Implementation}
+% \begin{macrocode}
+%<*package>
+%<@@=tag>
+% \end{macrocode}
+% \begin{macrocode}
+\ProvidesExplPackage {latex-lab-testphase-marginpar} {\ltlabmarginpardate} {\ltlabmarginparversion}
+ {Changes related to the tagging of the margin notes}
+% \end{macrocode}
+% \subsection{Variables}
+% We need a variable to make the label unique.
+% Todo: Not sure about the name.
+% \begin{macro}{\g__kernel_marginpar_int}
+% \begin{macrocode}
+\int_new:N \g__kernel_marginpar_int
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Tagging sockets}
+%
+% \begin{socketdecl}{tagsupport/marginpar/begin,tagsupport/marginpar/end}
+% \begin{macrocode}
+\socket_new:nn {tagsupport/marginpar/begin}{0}
+\socket_new:nn {tagsupport/marginpar/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+% \begin{plugdecl}{tagsupport/marginpar/begin,tagsupport/marginpar/end}
+% \begin{macrocode}
+\socket_new_plug:nnn {tagsupport/marginpar/begin}{default}
+ {
+ \if_mode_horizontal:
+ \tag_mc_end:
+ \tag_struct_begin:n{tag=Aside,parent=\g__tag_para_main_struct_tl}%
+ \else:
+ \tag_struct_begin:n{tag=Aside}%
+ \fi:
+ }
+\socket_new_plug:nnn {tagsupport/marginpar/end}{default}
+ {
+ \tag_struct_end:
+ \if_mode_horizontal: \tag_mc_begin:n{} \fi:
+ }
+\socket_assign_plug:nn {tagsupport/marginpar/begin}{default}
+\socket_assign_plug:nn {tagsupport/marginpar/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+
+% \subsection{Kernel command changes}
+% \begin{macro}{\@savemarbox }
+% We add sockets that add a tagging structure Aside:
+% \begin{macrocode}
+\long\def \@savemarbox #1#2{%
+ \UseTaggingSocket{marginpar/begin}
+ \global\setbox #1%
+ \color@vbox
+ \vtop{%
+ \hsize\marginparwidth
+ \@parboxrestore
+ \@marginparreset
+ #2\par
+ \@minipagefalse
+ \outer@nobreak
+ }%
+ \color@endbox
+ \UseTaggingSocket{marginpar/end}
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@ympar}
+% We must avoid that \cs{@xympar} creates tagging structure:
+% \begin{macrocode}
+\long\def\@ympar#1{%
+ \@savemarbox\@marbox{#1}%
+ \global\setbox\@currbox\copy\@marbox
+ \tag_stop:
+ \@xympar
+ \tag_start:}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@xmpar}
+% \cs{@xmpar} is the command used if an optional argument is present.
+% In this case we must stop tagging for \cs{@xympar} as above
+% but also decide which of the two @savemarbox should have tagging active.
+% We add a label to \cs{@marbox}. If that exist tagging is activated for this
+% box else for the other one.
+% \begin{macrocode}
+\long\def\@xmpar[#1]#2{%
+ \int_gincr:N\g__kernel_marginpar_int
+ \property_if_recorded:eTF { tag_marginpar-opt-\int_use:N\g__kernel_marginpar_int }
+ {
+ \@savemarbox\@marbox {#1
+ \property_record:ee
+ { tag_marginpar-opt-\int_use:N\g__kernel_marginpar_int }{page}
+ }%
+ \tag_stop:
+ \@savemarbox\@currbox{#2}%
+ \tag_start:
+ }
+% \end{macrocode}
+% order matters! the tagged box should be first so that it can pick up
+% the correct text-unit number.
+% \begin{macrocode}
+ {
+ \@savemarbox\@currbox{#2}%
+ \tag_stop:
+ \@savemarbox\@marbox{#1
+ \property_record:ee
+ { tag_marginpar-opt-\int_use:N\g__kernel_marginpar_int }{page}}
+ \tag_start:
+ }
+ \tag_stop:
+ \@xympar
+ \tag_start:
+ }
+%</package>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<*latex-lab>
+\ProvidesFile{marginpar-latex-lab-testphase.ltx}
+ [\ltlabmarginpardate\space v\ltlabmarginparversion\space
+ Changes related to the tagging of the margin notes]
+
+\RequirePackage{latex-lab-testphase-marginpar}
+
+%</latex-lab>
+% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-math.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-math.dtx
index 285471addc3..0dbc5911852 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-math.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-math.dtx
@@ -2,7 +2,7 @@
%
%% File: latex-lab-math.dtx
%
-% Copyright (C) 2022-2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -19,8 +19,8 @@
% for those people who are interested or want to report an issue.
%
%
-\def\ltlabmathdate{2023-09-11}
-\def\ltlabmathversion{0.5c}
+\def\ltlabmathdate{2024-04-16}
+\def\ltlabmathversion{0.5j}
%
%<*driver>
\documentclass{l3doc}
@@ -46,7 +46,14 @@
% \newcommand\NEW[1]{\marginpar{\mbox{}\hfill\fbox{New: #1}}}
% \providecommand\class[1]{\texttt{#1.cls}}
% \providecommand\pkg[1]{\texttt{#1}}
-% \providecommand\hook[1]{\texttt{#1}}
+%
+% \providecommand\hook[1]{\texttt{#1\DescribeHook[noprint]{#1}}}
+% \providecommand\socket[1]{\texttt{#1\DescribeSocket[noprint]{#1}}}
+% \providecommand\plug[1]{\texttt{#1\DescribePlug[noprint]{#1}}}
+%
+% \NewDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+% \NewDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl}
+% \NewDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
%
% ^^A \car {...} for marginal comments
% ^^A \car*{...} for longer inline comments
@@ -59,8 +66,6 @@
% {\IfBooleanTF{#1}{\todo[inline,#2]{#3}}^^A
% {\todo[#2]{#3}}}
%
-%
-%
% \begin{abstract}
% This is an experimental prototype. It captures math material
% (basically okay, but the interfaces for packages aren't yet
@@ -75,6 +80,18 @@
% \car*{Todo: update all the documentation! Both here and
% (what little there is!) in the implementation section.}
%
+% Tagging math involves a variety of tasks that require that math is captured before the
+% typesetting
+% \begin{itemize}
+% \item When typesetting the math MC-tags and structure commands must
+% be inserted at the begin and the end, and perhaps also around lines
+% or other subparts of the equation.
+% \item The source and/or a mathml-representation of the source must be available
+% so that it can be (perhaps after some preprocessing) be used in an associated file
+% or in an alternate text
+% \item It must be possible to measure the math for e.g. a bbox setting.
+% \end{itemize}
+%
% This file implements capture of all math mode material at the outer
% level, i.e., a formula is captured in its entirety with inner text
% blocks (possibly containing further math) absorbed as part of the
@@ -84,7 +101,24 @@
%\end{verbatim}
% would only result in a single capture of the tokens
% ``\verb*/a \in A \text{ for all $a<5$}/''.
+%
%
+% \section{Math capture} \label{sec:mathcapture}
+% In the current setup
+% \begin{itemize}
+% \item |$|, |\(...\)| and |$$| grab (through a command in \cs{everymath}/cs{everydisplay})
+% if the boolean \cs{l_@@_collected_bool} is false.
+% If the boolean is true they behave normally and can for example contain verbatim.
+%
+% \item All (registered) environments grab their body
+% regardless of the state of the boolean. For
+% |equation|, |equation*| and |math| this is a change as they no longer can
+% contain verbatim.
+%
+% \item BUG: |\[...\]| grabs if \cs{l_@@_collected_bool} is false. If it is
+% true it falls back to |equation*| and then errors because this can't find the end.
+% \end{itemize}
+%
% \subsection{Code level interfaces}
%
% \begin{function}{\math_register_env:n, \math_register_env:nn}
@@ -109,7 +143,8 @@
% \end{syntax}
% Declares that the captured math content should be passed to the
% \meta{tokens}, which will receive the environment type as |#1| and
-% the content as |#2|.
+% the content as |#2|. The processing is done before the typesetting. It is not
+% applied if \cs{ifmeasuring@} is true.
% \end{function}
%
% \subsection{Document level interfaces}
@@ -129,38 +164,275 @@
% \end{itemize}
% \end{function}
%
+% \section{Math tagging}
+%
+% The tagging code has to handle
+% \begin{itemize}
+% \item the embedding into the surrounding. This means
+% \begin{itemize}
+% \item closing and reopening MC-chunks
+% \item closing and reopening text/P-structures
+% \item handling interferences of the tagging code with penalties and spacing.
+% \end{itemize}
+% \item the actual tagging which means to do some or all of the following tasks:
+% \begin{itemize}
+% \item setup content for an associated source file
+% \item setup content for an associated mathml file
+% \item setup content for the /Alt key
+% \item setup content for the /ActualText key
+% \item setup attributes
+% \item add associated files
+% \item add a Formula structure
+% \item surround subparts (e.g. lines) with Formula sub structures
+% (perhaps with their own set of additional content)
+% \item surround elements of the equation with mathml structure elements
+% (currently only luatex with luamml)
+% \end{itemize}
+% \end{itemize}
+%
+% \subsection{Inline math}
+%
+% The embedding code is added through
+% the sockets
+% \begin{itemize}
+% \item |tagsupport/math/inline/begin|
+% \item |tagsupport/math/inline/end|
+% \end{itemize}
+% The sockets simply push and pop the MC currently. Without
+% tagging they use the noop-plug.
+%
+% The actual tagging is in done through the sockets
+% \begin{itemize}
+% \item |tagsupport/math/inline/formula/begin|
+% This socket takes the math as argument and its code
+% should output it for typesetting. Without tagging the
+% socket uses the identity plug.
+% The |default| plug of the socket calls these three internal sockets
+% for the tagging support:
+% \begin{itemize}
+% \item |tagsupport/math/content| This should set up the various
+% content variables (empty variables are ignored by the structure code
+% and so can be used to suppress a setting).
+% \item |tagsupport/math/struct/begin| This calls \cs{tag_struct_begin:n}.
+% It should also write the associated files if needed.
+% \item |tagsupport/math/substruct/begin| this handles subparts.
+% TODO: does it really make sense in inline math to have that??
+% \end{itemize}
+% \item |tagsupport/math/inline/formula/end|
+% This socket ends the formula structure(s). The |default|
+% plug calls these internal sockets:
+% \begin{itemize}
+% \item |tagsupport/math/substruct/end|
+% \item |tagsupport/math/struct/end|
+% \end{itemize}
+% \end{itemize}
+%
+% \subsection{Display math}
+%
+% \textit{to be written}
+%
+% \subsection{Associated Files}
+%
+% The current code allows the attachment of two types of associated file to the
+% Formula structure:
+% the \LaTeX\ source and a MathML representation.
+% Technically both can be attached---AF is an array
+% of file references---practically there can be problems with PDF consumers:
+% e.g. ngpdf used both and so showed the equation twice
+% (this has been corrected in the newest version) and
+% Foxit seems to see only the first AF in the array (so we attach the
+% mathml as first file).
+%
+% The \LaTeX\ source can be (and is) attached automatically.
+% It can be suppressed by an option with
+% \texttt{math/tex/AF=false}, see below.
+%
+% The MathML is attached if a file |\jobname-mathml.html| is found and
+% if it contains a suitable MathML snippet for the current formula.
+% The MathML processing can be suppressed globally by emptying the list of
+% mathml files with |math/mathml/sources=|. Locally for a formula |math/mathml/AF=false|
+% can be used.
+%
+% For a MathML representation a file with such representations must be provided.
+% If the equation is numbered the numbering should be part of the MathML as
+% the |Lbl| substructure is ignored if an MathML is used (see https://github.com/foxitsoftware/PDF_UA-2).
+%
+% The MathML representation is given in a special format.
+% It is meant to be a valid html file
+% that can be viewed in a browser.
+% For this it can start with |<!DOCTYPE html><html>| and end with |</html>|
+% It should have the extension \texttt{.html}. The \meta{mathml} content
+% is read with special catcodes, so can contain ambersands, hashes, comment chars
+% and unmatched braces such as |<mo>{</mo>|
+%
+% The file should contain a number of representations in this format:
+% \begin{quote}
+% |<div>| \\
+% | <h2>\mml| \meta{key}|</h2>|\\
+% | <p>|\meta{source}|</p>| \\
+% | <p>|\meta{hash}|</p>| \\
+% | <math | \meta{attributes} |>|\\
+% \meta{mathml}\\
+% | </math>|\\
+% |</div>|
+% \end{quote}
+% The keywords |<div>|, |<h2>\mml|, |<p>|, |<math|, |</math>| |</div>| are required as
+% they are used to delimit the arguments by the \LaTeX{} code.
+%
+% \meta{key} and \meta{source} are only used for debugging, they help to identify
+% the equation referred by this representation. The source should be used correctly escaped
+% |&| and |<| so that if gives valid html!
+%
+% \meta{attributes} is not required either, but can e.g. contain attributes
+% to improve the display in a browser:
+% \begin{verbatim}
+% <math alttext="\mathbf{G}" class="ltx_Math" display="inline">
+% \end{verbatim}
+% It can also contain the name space declaration: |xmlns="http://www.w3.org/1998/Math/MathML"|%
+% \footnote{But it is probably not needed and only blows up the PDF.}
+%
+%
+% By default the code tries at the begin of the document
+% to read a file |\jobname-mathml.html| in the |html|-format.
+% The file name can be changed with |mathml/setfiles={filename1,filename2}|
+% (without extension, |html| is added automatically).
+% If there is a list, all files are loaded.
+% If a file doesn't exist it is ignored, only an info is written to the log.
+%
+% Currently every MathML-snippet from a file is embedded into the PDF,
+% it is not checked first if it is actually used (simply writing everything to the PDF
+% is a bit easier than keeping everything in memory and also means that
+% the snippets are one after the other in the PDF).
+%
+% As mentioned above the MathML-AF can be suppressed for the equations in a group with
+% |math/mathml/AF=false|, or
+% completly by setting |math/mathml/sources=| in the preamble.
+%
+% Files embedded in a PDF can be listed in the attachments panel of a PDF viewer.
+% This is probably not so useful for lots of small files (but one could create
+% collections), but as long as PDF editors or viewers don't offer
+% proper support to access the AF it can help so have them there. The MathML are
+% added by default, but the \LaTeX{} source not. This can be changed with
+% |viewer/pane/mathsource=true| (anywhere in the document) and |viewer/pane/mathml=false| (in the
+% preamble, before the external file is read).
+%
+% \subsection{Options}
+%
+%
% \section{Known current bugs, etc.}
% \car*{New Section, now with subsections.\\
% As indicated, these lists are probably incomplete.\\
% Some of these have been addressed in a more recent branch.}
%
% \subsection{Capture/grabbing problems}
-%
+%
% \begin{enumerate}
% \item Incorrect grabbing of |$|-math when there is also
% explicit |$|-math within a \textit{text environment}
% that is itself within the math that should all be grabbed.
+% For example,
+% \begin{verbatim}
+% $a\begin{minipage}{1cm}$b$\end{minipage}$
+% \end{verbatim}
+% would only result in the capture of the tokens
+% ``\verb*/a\begin {minipage}{1cm}/''.
+% This can be avoided by an additional brace group:
+% \begin{verbatim}
+% $a{\begin{minipage}{1cm}$b$\end{minipage}}$
+% \end{verbatim}
+%
% \item Similar incorrect grabbing with |$$| also.
+%
% \item The grabbing, for all the display environments (and |\) \]|), needs
% to deal with nesting: \pkg{amsmath} contains code for this.
-% \item
+%
+% \item The math can't contain verbatim and verbatim-like commands. This is
+% nothing new for the \pkg{amsmath} environments but changes |$| and |\[\]|
+% and |equation*| (see e.g. tagging-project issue \#30).
+%
+% \item Begin and end of the math or math environment can not be hidden in commands.
+% For example \verb+>{$}l<{$}+ in a tabular would lead to errors.
+% Defining |\[| to fall back to |equation*| doesn't work if |equation*| is
+% a grabbing environment.
+%
+% \item The behaviour of |\[...\]| is faulty. See above.
% \end{enumerate}
%
+% \subsection{Fake math}
+% In a number of places in \LaTeX{} math commands (mainly |$|) is used
+% only for technical reason, e.g. to access a math font, to setup a symbol
+% or to use \cs{vcenter}.
+%
+% The code identifies such fake math mostly by making use of the \cs{m@th} command
+% where two methods are used for the automatic detection:
+%
+% \begin{itemize}
+% \item After grabbing math content the code checks if the content contains the token
+% \cs{m@th} and if yes it doesn't call the processor before reinserting
+% the content and perhaps adding tagging code.
+% This method requires that the math can be grabbed (e.g. that the end dollar is visible)
+% and that the \cs{m@th} is visible. It applies for example in \cs{@iiiparbox} where the
+% code from |$\vcenter| to |\m@th$| is grabbed an put back. It does not work for
+% example for |tabular| where the dollars and the \cs{m@th} token are spread around
+% over three commands. |tabular| needs therefore manual intervention.
+%
+% A look in the list of usages (in \texttt{usage-of-m@th.md}) justifies this approach.
+% All usages are either not math at all, or related to small elements that probably
+% shouldn't be grabbed and processed on their own.
+%
+% \item \cs{m@th} is redefined so that it sets the boolean \cs{l_@@_collected_bool}
+% to true. If \cs{m@th} is used inside math that has been grabbed
+% this doesn't change much as the boolean is set by the grabbing anyway. For usages
+% outside math the benefit is not so clear: The setting avoids that in \cs{LaTeXe}
+% the epsilon is processed as math, but it also prevents that the content of the amsmath
+% command \cs{boxed} is processed as math.
+% It means that if one wants to reenable math processing inside some (fake) math
+% one has to do it after \cs{m@th} calls.
+% \end{itemize}
+%
+% Open problems
+% \begin{enumerate}
+% \item The grabbing code doesn't pass the info that it detected a \cs{m@th} token.
+% This means that the tagging code has to do the same check (and doesn't do this
+% in all cases yet).
+%
+% \item Commands are missing to locally disable the grabbing and processing, e.g.
+% to handle |tabular|.
+%
+% \item It must be checked if setting the boolean in \cs{m@th} really makes sense
+% or if commands like \cs{LaTeXe} should be handled manually.
+%
+% \end{enumerate}
+%
+% \subsection{Processor}
+%
+% The grabbed math is at first passed to the processor. The processor is not called
+% in a measuring phase (from the amsmath \cs{ifmeasuring@}) and if the \cs{m@th}
+% token is detected.
+% It is not quite clear what purpose the processor has. As it is a public interface
+% it can't be used for internal code. And typesetting happens later and the processor
+% can't really change this. Currently it is mostly used for debugging and messages.
+% If the \cs{m@th} is found the \cs{l_@@_fakemath_bool} is set, so if the code
+% is changed this must be preserved.
+%
% \subsection{Other problems}
%
% \begin{enumerate}
% \item
-% The presence of \cs{m@th} in association with \cs{ensuremath}
+% The presence of \cs{m@th} in association with \cs{ensuremath}
% does not necessarily indicate fakemath. This is because
% wanting mathsurround to be zero is very reasonable and common,
% \emph{even when the math is genuine} (and hence needs to be collected).
+%
+% TODO: this claim needs some examples.
+%
% \item User-defined environments can create problems; but this area, of
% new, copied and changed environments, has not yet been developed.
%
% \car*{Joseph wrote, inter alia:\\
% My thinking [regarding] \cs{RegisterMathEnvironment}\\
% - (New) Math environments should not be created-then-patched, but only
-% generated by a [(future)] dedicated command (\cs{DeclareMathEnviornment},
+% generated by a [(future)] dedicated command (\cs{DeclareMathEnvironment},
% presumably)\\
% - Math environments created with \pkg{ltcmd} [commands] should not be copied, . . .\\
% - Package authors should be able to manually set up math environments with a public boolean.}
@@ -172,7 +444,10 @@
% \begin{enumerate}
% \item Add (some of) the math display commands that were \enquote{lifted from
% plain}, e.g., \cs{displaylines} \cs{eqalign}(??).
-% \item
+% \item The breqn packages changes catcodes and that isn't yet covered
+% by our mechanism.
+% \item \cs{intertext} is not correctly taken into account by the
+% code splitting multiline math into subformulas.
% \end{enumerate}
%
%
@@ -218,36 +493,823 @@
% have conditional definitions and deals with how to define \cs{[}/\cs{]}
% neatly.
% \begin{macrocode}
-\tl_gput_right:Nn \@kernel@before@begindocument
- { \RequirePackage { amsmath } }
+\AddToHook{begindocument/before}{ \RequirePackage { amsmath } }
% \end{macrocode}
%
%
% \subsection{Data structures}
%
-%
-%
-% \begin{variable}{\l_@@_collected_bool}
+% \begin{variable}{\l_@@_collected_bool}
% Tracks whether math mode material has been collected, which happens inside
% \pkg{amsmath} environments as well as those handled directly here.
+% If true following math will not grab and/or process.
+% See \ref{sec:mathcapture} for details.
+% \begin{macrocode}
+\bool_new:N \l_@@_collected_bool
+% \end{macrocode}
+% \end{variable}
%
+% \begin{variable}{\l_@@_fakemath_bool}
+% Tracks whether math mode material has been identified as fake math during
+% the grabbing phase, which happens currently if the
+% grabbed contents contains the \cs{m@th} token.
%
% \begin{macrocode}
-\bool_new:N \l_@@_collected_bool
+\bool_new:N \l_@@_fakemath_bool
% \end{macrocode}
% \end{variable}
-%
+%
+%
% \car{Change first tl name below: `env' $=>$ `info'?\\
% Or do we need an extra storage tl?}
%
% \begin{variable}{\g_@@_grabbed_env_tl, \g_@@_grabbed_math_tl}
-% \cs{g_@@_grabbed_env_tl} contains the name of the math environment (\texttt{math} in the case
-% of inline math, \cs{g_@@_grabbed_math_tl} the math content.
+% \cs{g_@@_grabbed_env_tl} contains the name of the math environment
+% (\texttt{math} in the case of inline math,
+% \cs{g_@@_grabbed_math_tl} the math content.
% \begin{macrocode}
\tl_new:N \g_@@_grabbed_env_tl
\tl_new:N \g_@@_grabbed_math_tl
% \end{macrocode}
% \end{variable}
+%
+% \begin{variable}{\l_@@_tmpa_tl,\l_@@_tmpa_skip,\l_@@_tmpa_str}
+% Temporary variables
+% \begin{macrocode}
+\tl_new:N \l_@@_tmpa_tl
+\skip_new:N \l_@@_tmpa_skip
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_content_alt_tl,
+% \l_@@_content_actual_tl,
+% \l_@@_content_AF_tl}
+% Temporary variables to hold math content that should
+% be used in actual or alt text and stored as AF.
+% \begin{macrocode}
+\tl_new:N \l_@@_content_alt_tl
+\tl_new:N \l_@@_content_actual_tl
+\tl_new:N \l_@@_content_AF_source_tl
+\tl_new:N \l_@@_content_AF_source_tmpa_tl
+\tl_new:N \l_@@_content_AF_mathml_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Tagging tools}
+% The following commands implement small tagging code chunks.
+% This should probably be collected and moved into tagpdf later.
+% \begin{macro}{\__tag_tool_close_P:}
+% This closes a P/text-chunk, both the MC and the structure and
+% increases the counter manually.
+% \begin{macrocode}
+\cs_new_protected:Npn \__tag_tool_close_P:
+ {
+ \tag_if_active:T
+ {
+ \tag_mc_end: %end P-chunk, should perhaps be \tag_mc_end_push: ...
+ \__tag_gincr_para_end_int:
+ \__tag_check_para_end_show:nn{red}{} %debug: show para
+ \tag_struct_end:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% We add also an attribute.
+% \begin{macrocode}
+\tl_new:N\l_@@_attribute_class_tl
+\tagpdfsetup
+ {role/new-attribute = {inline} {/O /Layout /Placement/Inline},
+ role/new-attribute = {display} {/O /Layout /Placement/Block},
+ }
+% \end{macrocode}
+%
+% \subsection{Code related to AF}
+% Booleans to handle the options.
+% \begin{variable}{
+% \l__tag_math_texsource_AF_bool,
+% \l__tag_math_texsource_pane_bool,
+% \l__tag_math_mathml_AF_bool,
+% \g__tag_math_mathml_AF_bool,
+% \l__tag_math_mathml_pane_bool,
+% \l__tag_math_alt_bool
+% }
+% \begin{macrocode}
+\bool_new:N\l__tag_math_texsource_AF_bool
+\bool_new:N\l__tag_math_texsource_pane_bool
+\bool_new:N\l__tag_math_mathml_AF_bool
+\bool_new:N\g__tag_math_mathml_AF_bool
+\bool_new:N\l__tag_math_mathml_pane_bool
+\bool_new:N\l__tag_math_alt_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{
+% \g_@@_mathml_total_int,
+% \g_@@_mathml_int,
+% \g_@@_math_total_int,
+% \g_@@_mathml_AF_found_int,
+% \g_@@_mathml_AF_attached_int,
+% }
+% \cs{g_@@_mml_total_int} records the mathml fragments read in.
+% \cs{g_@@_mml_int} records the mathml fragments read in with a different hash.
+% \cs{g_@@_AF_total_int} records the number of math structures that try to
+% attach a mathml AF.
+% \cs{g_@@_AF_found_int} records the number of math structures for which a fitting
+% mathml is found.
+% \cs{g_@@_AF_attached_int} records the number of math structures which got a mathml fragment
+% (if mathml-AF are not disabled locally this should be the equal to the previous number.
+%
+% \begin{macrocode}
+\int_new:N\g_@@_mathml_total_int
+\int_new:N\g_@@_mathml_int
+\int_new:N\g_@@_math_total_int
+\int_new:N\g_@@_mathml_AF_found_int
+\int_new:N\g_@@_mathml_AF_attached_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l__tag_math_mathml_files_clist}
+% A sequence to store the file list for the mathml.
+% \begin{macrocode}
+\clist_new:N\l__tag_math_mathml_files_clist
+\clist_put_right:Ne\l__tag_math_mathml_files_clist {\c_sys_jobname_str-mathml}
+% \end{macrocode}
+% \end{variable}
+
+% This is the internal variant of the \cs{mml} command.
+% \begin{macro}{\@@_AF_mml:nnnn}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_AF_mml:nnnn #1 #2 #3 #4
+%#1 number, #2 tex source for debugging, #3 hash, #4 mathml
+ {
+ \int_gincr:N \g_@@_mathml_total_int
+% \end{macrocode}
+% mathml with the same hash should be included only once:
+% \begin{macrocode}
+ \tl_if_exist:cF { g_@@_mathml_#3_tl }
+ {
+ \int_gincr:N \g_@@_mathml_int
+% \end{macrocode}
+% a simple Desc key, take care that it is a valid string!
+% \begin{macrocode}
+ \pdfdict_put:nne {l_pdffile/Filespec} {Desc}{(mathml-#1)}
+ \pdffile_embed_stream:nnN {#4}{mathml-#1.xml}\l_@@_tmpa_tl
+% \end{macrocode}
+% not strictly necessary but makes the files visible in the file attachment
+% page
+% \begin{macrocode}
+ \bool_if:NT \l__tag_math_mathml_pane_bool
+ {\pdfmanagement_add:nne {Catalog/Names}{EmbeddedFiles}{\l_@@_tmpa_tl}}
+ \tl_new:c{g_@@_mathml_#3_tl}
+ \tl_gset_eq:cN{g_@@_mathml_#3_tl}\l_@@_tmpa_tl
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% The html reader.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_AF_html_reader:w#1</h2>#2<p>#3</p>#4<p>#5</p>#6<math{
+ \begingroup
+ \char_set_catcode_other:N\{
+ \char_set_catcode_other:N\}
+ \char_set_catcode_other:N\#
+ \char_set_catcode_other:N\%
+ \@@_AF_html_reader_verb:w{#1}{#3}{#5}<math
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new_protected:Npn\@@_AF_html_reader_verb:w#1#2#3#4~</div>{
+ \endgroup
+ \@@_AF_mml:nnnn{#1}{#2}{#3}{#4}
+ }
+% \end{macrocode}
+
+%
+% \begin{socketdecl}{tagsupport/math/mathml/write}
+% This writes a html-dummy with the hash and the math content.
+% This should be optional, so it uses a socket that can be disabled
+%
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/mathml/write}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{plugdecl}{On}
+% \begin{macrocode}
+\socket_new_plug:nnn{tagsupport/math/mathml/write}{On}
+ {
+ \str_set:NV\l_@@_tmpa_str\l_@@_content_AF_source_tl
+ \str_replace_all:Nnn\l_@@_tmpa_str{&}{&amp;}
+ \str_replace_all:Nnn\l_@@_tmpa_str{<}{&lt;}
+ \iow_now:Ne \g_@@_writedummy_iow
+ {
+ \iow_newline:
+ <div>
+ \iow_newline:
+ <h2>\c_backslash_str mml\c_space_tl \int_use:N \g_@@_math_total_int </h2>
+ \iow_newline:
+ <p>\l_@@_tmpa_str</p>
+ \iow_newline:
+ <p>\l_@@_content_hash_tl </p>
+ \iow_newline:
+ <math></math>
+ \iow_newline:
+ </div>
+ \iow_newline:
+ }
+ }
+% \end{macrocode}
+% \end{plugdecl}
+% And now a key to activate the socket.
+% \begin{macrocode}
+
+\keys_define:nn { __tag / setup }
+ {
+ math/mathml/write-dummy .code:n =
+ {
+ \bool_gset_true:N \g__tag_math_mathml_AF_bool
+ \tl_if_exist:NF\g_@@_writedummy_iow
+ {
+ \iow_new:N \g_@@_writedummy_iow
+ \iow_open:Nn \g_@@_writedummy_iow
+ {
+ \c_sys_jobname_str-mathml-dummy.html
+ }
+ \iow_now:Ne \g_@@_writedummy_iow
+ {
+ <!DOCTYPE~html>
+ \iow_newline:
+ <html>
+ }
+ \AssignSocketPlug {tagsupport/math/mathml/write}{On}
+ \AddToHook{enddocument/afterlastpage}
+ {
+ \iow_now:Nn \g_@@_writedummy_iow {</html>}
+ \iow_close:N \g_@@_writedummy_iow
+ }
+ }
+ },
+ math/mathml/write-dummy .usage:n=preamble
+ }
+% \end{macrocode}
+%
+% \begin{macro}{\@@_AF_process_mathml_files:}
+% \begin{macrocode}
+\box_new:N\l_@@_tmpa_box
+\cs_new_protected:Npn \@@_AF_process_mathml_files:
+ {
+ \hbox_set:Nn \l_@@_tmpa_box
+ {
+ \pdfdict_put:nnn { l_pdffile/Filespec }{AFRelationship} { /Supplement }
+ \pdfdict_put:nne
+ { l_pdffile }{Subtype}
+ { \pdf_name_from_unicode_e:n{application/mathml+xml} }
+ \char_set_catcode_other:N \#
+ \cs_set_eq:NN\mml \@@_AF_html_reader:w
+ \clist_map_inline:Nn \l__tag_math_mathml_files_clist
+ {
+ \file_if_exist:nTF {##1.html}
+ {
+ \typeout{Info:~reading~mathml~file~##1}
+ \file_input:n {##1.html}
+ \bool_gset_true:N\g__tag_math_mathml_AF_bool
+ }
+ {
+ \typeout{Info:~mathml~file~##1~does~not~exist}%info message
+ }
+ }
+ }
+ \bool_if:NT\g__tag_math_mathml_AF_bool
+ {
+ \typeout{Info:~Activating~mathml~support}
+ \AssignSocketPlug{tagsupport/math/struct/begin}{test-mathml}
+ \AssignSocketPlug{tagsupport/math/struct/end}{test-mathml}
+% \end{macrocode}
+% mathml handling doesn't like subparts, so we disable them for now:
+% \begin{macrocode}
+ \AssignSocketPlug{tagsupport/math/substruct/begin}{single}
+ \AssignSocketPlug{tagsupport/math/substruct/end}{single}
+ \AddToHook{enddocument/info}
+ {
+ \iow_term:n{MathML~statistic}
+ \iow_term:n{================}
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_total_int\c_space_tl
+ MathML~fragments~read}
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_int\c_space_tl
+ different~MathML~fragments}
+ \iow_term:e{==>~\int_use:N\g_@@_math_total_int\c_space_tl
+ math~fragments~found}
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_AF_found_int\c_space_tl
+ fitting~MathML~AF~found}
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_AF_attached_int\c_space_tl
+ MathML~AF~attached}
+ }
+ }
+ }
+\AddToHook{begindocument}{\@@_AF_process_mathml_files:}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Mathstyle detection}
+% In some cases we need to detect the mathstyle used in a \cs{mathchoice}
+% command and to disable/enable tagging in the unused branches.
+% This is currently only used in the amstext command \cs{text}
+% but is perhaps also needed in other cases, so we create a general command.
+%
+%\begin{macro}{\l_@@_mathstyle_int,\g_@@_mathchoice_int,mathstyle}
+% \begin{macrocode}
+\int_new:N \l_@@_mathstyle_int
+\int_new:N \g_@@_mathchoice_int
+\property_new:nnnn{mathstyle}{now}{-1}{\int_use:N \l_@@_mathstyle_int }
+% \end{macrocode}
+%\end{macro}
+% For now internal, but perhaps will need a public version.
+% The command should be used in every branch of a \cs{mathchoice}
+% (with the correct mathstyle number) and with an unique label (which should
+% be the same in every branch).
+% \cs{g_@@_mathchoice_int} can be e.g. increased before the mathchoice and
+% then used.
+% \begin{macro}{\@@_tag_if_mathstyle:nn}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_tag_if_mathstyle:nn #1 #2
+ %#1 refers to label
+ %#2 is a number for the mathstyle (typically 0,2,4,6)
+ {
+ \int_set:Nn \l_@@_mathstyle_int {#2}
+ \property_record:nn {#1} { mathstyle }
+ \int_compare:nNnTF { \property_ref:nn {#1}{ mathstyle} } = { #2 }
+ { \tag_start: }{ \tag_stop: }
+ }
+\cs_generate_variant:Nn \@@_tag_if_mathstyle:nn {en}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Tagging options}
+% \begin{macrocode}
+\keys_define:nn { __tag / setup }
+ {
+ math/mathml/sources .clist_set:N = \l__tag_math_mathml_files_clist,
+ math/alt/use .bool_set:N = \l__tag_math_alt_bool,
+ viewer/pane/mathml .bool_set:N = \l__tag_math_mathml_pane_bool,
+ viewer/pane/mathml .initial:n = true,
+ viewer/pane/mathsource .bool_set:N = \l__tag_math_texsource_pane_bool,
+ math/mathml/AF .bool_set:N = \l__tag_math_mathml_AF_bool,
+ math/mathml/AF .initial:n = true,
+ math/tex/AF .bool_set:N = \l__tag_math_texsource_AF_bool,
+ math/tex/AF .initial:n = true
+ }
+% \end{macrocode}
+%
+% \subsection{Sockets}
+% \subsubsection{Main inline math sockets}
+%
+% \begin{socketdecl}
+% {
+% tagsupport/math/inline/begin,
+% tagsupport/math/inline/end,
+% tagsupport/math/inline/formula/begin,
+% tagsupport/math/inline/formula/end,
+% }
+% The first two sockets are meant to embed inline
+% math into the surrounding (so to close/reopen e.g. MC-chunks).
+% The other two implement the actual formula structure.
+% The formula sockets are despite their naming not symmetric:
+% the begin socket is issued after the math has started, while
+% the end socket is after the math!
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/inline/begin}{0}
+\socket_new:nn {tagsupport/math/inline/end}{0}
+\socket_new:nn {tagsupport/math/inline/formula/begin}{1} %
+\socket_new:nn {tagsupport/math/inline/formula/end}{0}
+% \end{macrocode}
+%\end{socketdecl}
+%
+%
+% \begin{plugdecl}{MC}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/inline/begin}
+ {MC}
+ {\tag_mc_end_push:}
+\socket_new_plug:nnn
+ {tagsupport/math/inline/end}
+ {MC}
+ {\tag_mc_begin_pop:n{}}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% We probably will want to test different tagging receipes.
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/inline/formula/begin}
+ {default}
+ {
+ \socket_use:n{tagsupport/math/content}
+ \socket_use:n{tagsupport/math/struct/begin}
+% \end{macrocode}
+% TODO: does inline math need subformula handling?
+% \begin{macrocode}
+ % inner formula if multiple parts (not really implemented yet)
+ \socket_use:n{tagsupport/math/substruct/begin}
+ #1
+ \socket_use:n{tagsupport/math/end}
+ }
+\socket_new_plug:nnn
+ {tagsupport/math/inline/formula/end}
+ {default}
+ {
+ \socket_use:n{tagsupport/math/substruct/end}
+ \socket_use:n{tagsupport/math/struct/end}
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \subsubsection{Main display math sockets}
+%
+% \begin{socketdecl}
+% {
+% tagsupport/math/display/begin,
+% tagsupport/math/display/end,
+% tagsupport/math/display/formula/begin,
+% tagsupport/math/display/formula/end,
+% }
+% The first two sockets are meant to embed display
+% math into the surrounding (so to close/reopen e.g. MC-chunks and
+% P-structure).
+% The other two implement the actual formula structure.
+% The formula sockets are despite their naming not symmetric:
+% the begin socket is issued after the math has started, while
+% the end socket is after the math!
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/display/begin}{0}
+\socket_new:nn {tagsupport/math/display/end}{0}
+\socket_new:nn {tagsupport/math/display/formula/begin}{1} %
+\socket_new:nn {tagsupport/math/display/formula/end}{0}
+% \end{macrocode}
+%\end{socketdecl}
+
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/display/begin}
+ {default}
+ { \__tag_tool_close_P: }
+\socket_new_plug:nnn
+ {tagsupport/math/display/end}
+ {default}
+ {
+ }
+% \end{macrocode}
+% \end{plugdecl}
+
+
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/display/formula/begin}
+ {default}
+ {
+ \socket_use:n{tagsupport/math/content}
+ \socket_use:n{tagsupport/math/struct/begin}
+ \socket_use:n{tagsupport/math/substruct/begin}
+ #1
+ \socket_use:n{tagsupport/math/end}
+ }
+\socket_new_plug:nnn
+ {tagsupport/math/display/formula/end}
+ {default}
+ {
+ \socket_use:n{tagsupport/math/substruct/end}
+ \socket_use:n{tagsupport/math/struct/end}
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \subsubsection{Internal sockets}
+%
+% \begin{variable}{\l_@@_content_template_tl}
+% The default text used as alt or actual text.
+% \begin{macrocode}
+\tl_new:N\l_@@_content_template_tl
+\tl_set:Nn \l_@@_content_template_tl
+ {
+ LaTeX~ formula~ starts~
+ \exp_not:N\begin{\g_@@_grabbed_env_tl}
+ \c_space_tl
+ \exp_not:V\g_@@_grabbed_math_tl
+ \c_space_tl
+ \exp_not:N\end{\g_@@_grabbed_env_tl}
+ \c_space_tl LaTeX~ formula~ ends~
+ }
+% \end{macrocode}
+% \end{variable}
+
+% \begin{variable}{\l_@@_texsource_template_tl}
+% The default text used as texsource
+% \begin{macrocode}
+\tl_new:N\l_@@_texsource_template_tl
+\tl_const:Nn\c_@@_inline_env_tl {math}
+\tl_set:Nn \l_@@_texsource_template_tl
+ {
+ \tl_if_eq:NNTF\g_@@_grabbed_env_tl\c_@@_inline_env_tl
+ {
+ $
+ \exp_not:V\g_@@_grabbed_math_tl
+ $
+ }
+ {
+ \exp_not:N\begin{\g_@@_grabbed_env_tl}
+ \exp_not:V\g_@@_grabbed_math_tl
+ \exp_not:N\end{\g_@@_grabbed_env_tl}
+ }
+ }
+% \end{macrocode}
+% \end{variable}
+
+%
+% \begin{socketdecl}{tagsupport/math/content}
+% The math content is stored in associated files and used for
+% actual and alternative text. As the exact text is still
+% unclear we use a socket to be able to test variants.
+% The socket should set all four tl vars above, if needed
+% to identical values. It can use the two variables
+% \cs{g_@@_grabbed_env_tl} and \cs{g_@@_grabbed_math_tl}
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/content}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% Some default sockets to set the contents.
+% TODO: think about naming convention.
+% TODO: think how this should organized so that one
+% has options to change from the outside and so that
+% there are less repetitions.
+% \begin{plugdecl}{actual+source}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/content}
+ {actual+source}
+ {
+ \tl_set:Ne\l_@@_content_actual_tl
+ {
+ \l_@@_content_template_tl
+ }
+ \tl_set:Ne \l_@@_content_AF_source_tl
+ {
+ \l_@@_texsource_template_tl
+ }
+ \tl_set:Nn \l_@@_content_AF_mathml_tl {}
+ \tl_set:Nn \l_@@_content_alt_tl {}
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{alt+source}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/content}
+ {alt+source}
+ {
+ \tl_set:Ne\l_@@_content_alt_tl
+ {
+ \l_@@_content_template_tl
+ }
+ \tl_set:Ne \l_@@_content_AF_source_tl
+ {
+ \l_@@_texsource_template_tl
+ }
+ \tl_set:Nn \l_@@_content_AF_mathml_tl {}
+ \tl_set:Nn \l_@@_content_actual_tl {}
+ }
+% \end{macrocode}
+% \end{plugdecl}
+% \begin{macrocode}
+\socket_assign_plug:nn {tagsupport/math/content}{alt+source}
+% \end{macrocode}
+%
+% \begin{socketdecl}{tagsupport/math/struct/begin,
+% tagsupport/math/struct/end}
+% For the main structure we use a socket too.
+% This allow e.g. to create a special one for luamml
+% which setups additional objects.
+% The begin socket can use the two variables
+% \cs{g_@@_grabbed_env_tl} and \cs{g_@@_grabbed_math_tl}
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/struct/begin}{0}
+\socket_new:nn {tagsupport/math/struct/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{plugdecl}{default}
+% TODO: think about some naming convention ...
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/struct/begin}
+ {default}
+ {
+ \bool_if:NTF\l__tag_math_texsource_AF_bool
+ { \tl_set_eq:NN \l_@@_content_AF_source_tmpa_tl \l_@@_content_AF_source_tl }
+ { \tl_clear:N \l_@@_content_AF_source_tmpa_tl }
+ \tag_struct_begin:n
+ {
+ tag=Formula,
+ texsource = \l_@@_content_AF_source_tmpa_tl,
+ title-o = \g_@@_grabbed_env_tl,
+ actualtext = \l_@@_content_actual_tl,
+ alt = \l_@@_content_alt_tl
+ }
+ }
+\socket_new_plug:nnn
+ {tagsupport/math/struct/end}
+ {default}
+ { \tag_struct_end: }
+
+\socket_assign_plug:nn {tagsupport/math/struct/begin}{default}
+\socket_assign_plug:nn {tagsupport/math/struct/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{test-mathml}
+% This (test-)socket tries to add a mathml-AF to formula.
+% It is activated if a mathml.html has been found and loaded.
+% Additionally it also sets an attribute
+% (this can perhaps be done by default anyway.)
+% As it disturbs the reading of the AF it currently deactivates the /Alt key,
+% unless it has been reenabled with |math/alt/use=true|
+% \begin{macrocode}
+\cs_generate_variant:Nn \str_mdfive_hash:n {o}
+\tl_new:N\l_@@_content_hash_tl
+% \end{macrocode}
+% we need to save the grabbed math:
+% \begin{macrocode}
+\tl_new:N\l_@@_grabbed_math_tl
+% \end{macrocode}
+% the socket definition
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/struct/begin}
+ {test-mathml}
+ {
+ \int_gincr:N\g_@@_math_total_int
+ \tl_set:Ne\l_@@_content_hash_tl
+ {\str_mdfive_hash:o { \l_@@_content_AF_source_tl }}
+ \tl_set_eq:NN\l_@@_grabbed_math_tl\g_@@_grabbed_math_tl
+ \tl_if_eq:NnTF\g_@@_grabbed_env_tl {math}
+ {
+ \tl_set:Nn\l_@@_attribute_class_tl{inline}
+ }
+ {
+ \tl_set:Nn\l_@@_attribute_class_tl{display}
+ }
+ \bool_if:NF\l__tag_math_alt_bool
+ { \tl_set:Nn \l_@@_content_alt_tl{} }
+% \end{macrocode}
+% debugging option. TODO: hide in debug key.
+% \begin{macrocode}
+ \tl_if_exist:cTF { g_@@_mathml_ \l_@@_content_hash_tl _tl }
+ {
+ \int_gincr:N\g_@@_mathml_AF_found_int
+ \bool_if:NTF \l__tag_math_mathml_AF_bool
+ {
+ \int_gincr:N\g_@@_mathml_AF_attached_int
+ \typeout {Inserting~mathml~with~Hash~\l_@@_content_hash_tl}
+ }
+ {
+ \typeout {Ignoring~mathml~with~Hash~\l_@@_content_hash_tl}
+ }
+ }
+ {
+ \typeout{WARNING:~mathml~missing~for~hash~\l_@@_content_hash_tl}
+ }
+ \socket_use:n {tagsupport/math/mathml/write} % write hash if request
+ \bool_if:NTF\l__tag_math_texsource_AF_bool
+ { \tl_set_eq:NN \l_@@_content_AF_source_tmpa_tl \l_@@_content_AF_source_tl }
+ { \tl_clear:N \l_@@_content_AF_source_tmpa_tl }
+ \tag_struct_begin:n
+ {
+ tag=Formula,
+ attribute-class=\l_@@_attribute_class_tl, %
+ AFref =
+ \bool_if:NT\l__tag_math_mathml_AF_bool
+ {
+ \cs_if_exist_use:c {g_@@_mathml_ \l_@@_content_hash_tl _tl}
+ },
+ texsource = \l_@@_content_AF_source_tmpa_tl, % should be after mathml AF!
+ title-o = \g_@@_grabbed_env_tl, %
+ alt = \l_@@_content_alt_tl
+ }
+ }
+% \end{macrocode}
+% not really needed but looks more symmetric:
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/struct/end}
+ {test-mathml}
+ {
+ \tag_struct_end:
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{socketdecl}{tagsupport/math/substruct/begin,
+% tagsupport/math/substruct/end}
+% This holds the code to handle subparts of the formula.
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/substruct/begin}{0}
+\socket_new:nn {tagsupport/math/substruct/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/substruct/begin}
+ {default}
+ { \grabaformulapartandstart }
+\socket_new_plug:nnn
+ {tagsupport/math/substruct/end}
+ {default}
+ {
+ \tagmcend
+ \if@subformulas
+ \tagstructend
+ \fi
+ }
+\socket_assign_plug:nn {tagsupport/math/substruct/begin}{default}
+\socket_assign_plug:nn {tagsupport/math/substruct/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+
+% \begin{plugdecl}{single}
+% We need an option to disable subparts as it is unclear
+% if consumers can handle them:
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/substruct/begin}
+ {single}
+ {
+ \typeout{====>subpart~splitting~deactivated}
+ \typeout{====>grabbed~math=\meaning\g_@@_grabbed_math_tl}
+ \tag_mc_begin:n{}
+ }
+\socket_new_plug:nnn
+ {tagsupport/math/substruct/end}
+ {single}
+ { \tag_mc_end:}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{socketdecl}{tagsupport/math/end}
+% A socket used at the end of the math (before the closing dollar(s))
+% which can e.g. set a flag for luamml.
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+
+%
+% \begin{macro}{\__tag_math_disable:}
+% Similar to the table code we collect the plugs that should be
+% assigned to do nothing if we don't want tagging
+% \begin{macrocode}
+\cs_new_protected:Npn \__tag_math_disable:
+ {
+ \socket_assign_plug:nn {tagsupport/math/inline/begin}{noop}
+ \socket_assign_plug:nn {tagsupport/math/inline/end}{noop}
+ \socket_assign_plug:nn {tagsupport/math/inline/formula/begin}{identity}
+ \socket_assign_plug:nn {tagsupport/math/inline/formula/end}{noop}
+ \socket_assign_plug:nn {tagsupport/math/display/begin}{noop}
+ \socket_assign_plug:nn {tagsupport/math/display/end}{noop}
+ \socket_assign_plug:nn {tagsupport/math/display/formula/begin}{identity}
+ \socket_assign_plug:nn {tagsupport/math/display/formula/end}{noop}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\__tag_math_enable:}
+% Similar to the table code we collect the default plugs that should be
+% assigned if we want tagging
+% \begin{macrocode}
+\cs_new_protected:Npn \__tag_math_enable:
+ {
+ \socket_assign_plug:nn {tagsupport/math/inline/begin}{MC}
+ \socket_assign_plug:nn {tagsupport/math/inline/end}{MC}
+ \socket_assign_plug:nn {tagsupport/math/inline/formula/begin}{default}
+ \socket_assign_plug:nn {tagsupport/math/inline/formula/end}{default}
+ \socket_assign_plug:nn {tagsupport/math/display/begin}{default}
+ \socket_assign_plug:nn {tagsupport/math/display/end}{default}
+ \socket_assign_plug:nn {tagsupport/math/display/formula/begin}{default}
+ \socket_assign_plug:nn {tagsupport/math/display/formula/end}{default}
+ }
+% \end{macrocode}
+% \end{macro}
+% At begin document we can activate:
+% \begin{macrocode}
+\AtBeginDocument{\tag_if_active:T{\__tag_math_enable: }}
+% \end{macrocode}
%
% \subsection{Interface commands}
%
@@ -260,7 +1322,8 @@
{
\legacy_if:nF { measuring@ }
{
- \tl_if_in:nnF {#2} { \m@th }
+ \tl_if_in:nnTF {#2} { \m@th }
+ { \bool_set_true:N\l_@@_fakemath_bool }
{ \tl_trim_spaces_apply:nN {#2} \@@_process_auxi:nn {#1} }
}
}
@@ -287,15 +1350,15 @@
%
% \begin{macro}{\@@_grab_dollar:w}
% Grab up to a single |$|, for inline math mode, suppressing
-% any processing if the first token is \tn{m@th}.
+% any processing if the token is \tn{m@th} found in the content.
+%
+% \fmi{what's that test doing?}
%
-% \fmi{what's that test doing?}
+% \car{It is some kind of fix, to avoid the remote
+% possibility that the math is empty, making the code
+% produce an unwanted \texttt{\$\$}.}
%
-% \car{It is some kind of fix, to avoid the remote
-% possibility that the math is empty, making the code
-% produce an unwanted \texttt{\$\$}.}
-%
-%\car{cf.~the code for this in \cs{@ensuredmath}}
+%\car{cf.~the code for this in \cs{@ensuredmath}}
%
%\car{It is harmless but unnecessary in the dollardollar grabbing below.}
%
@@ -309,91 +1372,62 @@
\tl_if_blank:nF {#1}
{
\@@_process:nn { math } {#1} % $
-% fairly simple this one
% \end{macrocode}
-% We do not want math tagging in fakemath or when measuring,
-% so we imitate the test inside \cs{@@_process:nn} for now,
-% see https://github.com/latex3/tagging-project/issues/5
-% TODO: use socket to get more control about typesetting variants (tagged, drop etc)?
+% We do not want math tagging in fakemath or when measuring,
+% We also do not want math tagging if tagging has been suspended.
% \begin{macrocode}
- \legacy_if:nTF { measuring@ }
- { #1 $ }
- {
- \tl_if_in:nnTF {#1} { \m@th }
- { #1 $ }
- {
- \tagmcend %end P-chunk, in code: \tag_mc_end_push:
- \@kernel@math@begin
- #1 $
- \@kernel@math@end
- \tagmcbegin{} % restart P-chunk (whatsits in pdftex)
- }
- }
+ \bool_lazy_or:nnTF
+ {\legacy_if_p:n { measuring@ }}
+ { \l_@@_fakemath_bool }
+ { #1 $ }
+ {
+ \tag_socket_use:n {math/inline/begin} %end P-MC
+ \tag_socket_use:nn {math/inline/formula/begin}{#1}
+ $
+ \tag_socket_use:n {math/inline/formula/end}
+ \tag_socket_use:n {math/inline/end} % restart P-MC
+ }
}
}
% \end{macrocode}
% \end{macro}
+%
% \begin{macro}{\@@_grab_dollardollar:w}
% And for the classical \TeX{} display structure.
% \begin{macrocode}
-
-\skip_new:N \l_@@_tmpa_skip
-
\cs_new_protected:Npn \@@_grab_dollardollar:w % $$
#1 $$
{
\tl_if_blank:nF {#1}
{
- \@@_tag_dollardollar_display:nn { equation* }{#1}
- #1
+ \@@_process:nn { equation* } {#1}
+ \socket_use:n {tagsupport/math/display/begin}
+ \socket_use:nn{tagsupport/math/display/formula/begin}{#1}
$$
}
}
% \end{macrocode}
-% To allow to use the code without tagging we guard. But probably tagpdf should
-% provide some tools for such manual para-ends.
+%
+% The end code is added through a \cs{aftergroup} so we
+% store it inside a command.
% \begin{macrocode}
-\cs_new_protected:Npn \@kernel@close@P {
- \tag_if_active:T
- {
- \tagmcend %end P-chunk, should perhaps be \tag_mc_end_push: ...
- \int_gincr:N \g__tag_para_end_int
- \bool_if:NT \l__tag_para_show_bool
- { \tag_mc_begin:n{artifact}
- \rlap{\color_select:n{red}\tiny\ \int_use:N\g__tag_para_end_int}
- \tag_mc_end:
- }
- \tag_struct_end:
- }
-}
-
-
-
-\cs_new_protected:Npn \@@_tag_dollardollar_display:nn #1#2 {
- \@@_process:nn {#1} {#2}
- \@kernel@close@P
- \@kernel@math@begin
-% \skip_set:Nn \belowdisplayskip {-\belowdisplayskip}
-% \skip_set:Nn \belowdisplayshortskip {-\belowdisplayshortskip}
-% \int_set:Nn \postdisplaypenalty {10000}
-%%
-% \group_insert_after:N \@@_tag_dollardollar_display_end:
-}
-
-\cs_new_protected:Npn \@@_tag_dollardollar_display_end: {
-% \typeout{== tag dollarldollar display end}
-% \ShowTagging{struct-stack}
- \tagpdfparaOff
- \para_raw_end:
- \tagpdfparaOn
- \l_@@_tmpa_skip \lastskip
- \@kernel@math@end
- \penalty \postdisplaypenalty
+\cs_new_protected:Npn \@@_tag_dollardollar_display_end:
+ {
+ % \typeout{== tag dollarldollar display end}
+ % \ShowTagging{struct-stack}
+ \para_raw_end:
+% \end{macrocode}
+% TODO why is that needed? where is para-tagging disabled?
+% \begin{macrocode}
+ \tagpdfparaOn
+ \l_@@_tmpa_skip \lastskip
+ \socket_use:n{tagsupport/math/display/formula/end}
+ \penalty \postdisplaypenalty
% \end{macrocode}
% This reinserts the below display skips. It must be doubled to
% get the right amount:
% \begin{macrocode}
- \skip_vertical:n { -\l_@@_tmpa_skip * 2 }
+ \skip_vertical:n { -\l_@@_tmpa_skip * 2 }
%
\@doendpe % this has no \end{...} to take care of it
}
@@ -410,13 +1444,13 @@
{
\tl_if_blank:nF {#1}
{
- \@@_process:nn { math } {#1}
$ #1 $
}
\bool_set_false:N \l_@@_collected_bool
}
% \end{macrocode}
% \end{macro}
+%
% \begin{macro}{\@@_grab_eqn:w}
% For the most common use of \cs{[}/\cs{]}: turn into an environment.
% \begin{macrocode}
@@ -463,7 +1497,7 @@
% \begin{macro}{\math_register_env:n}
% \begin{macro}{\RegisterMathEnvironment}
% Set up to capture environment content and make available.
-%
+%
% \begin{macrocode}
\cs_new_protected:Npn \math_register_env:nn #1#2
{
@@ -472,15 +1506,8 @@
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
- \ExpandArgs { nnx } \RenewDocumentEnvironment {#1} { b }
+ \ExpandArgs { nne } \RenewDocumentEnvironment {#1} { b }
{
-% \bool_set_true:N \exp_not:N \l_@@_collected_bool
-% \cs_if_exist:cTF { @@_env #1 _aux: }
-% {
-% \exp_not:c { @@_env #1 _aux: }
-% ####1 \exp_not:N \@@_env_end: {#1}
-% }
-% { \exp_not:N \@@_process:nn {#1} {####1} }
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
% \typeout{===>B1}
@@ -490,34 +1517,22 @@
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
- ####1 \exp_not:N \@@_env_end: {#1}
+ ##1 \exp_not:N \@@_env_end: {#1}
}
- { \exp_not:N \@@_process:nn {#1} {####1} }
+ { \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
-% \exp_not:N \tracingall
+% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
- ####1
+ ##1
\exp_not:c { @@_env_ #1 _end: }
-% \exp_not:c { @@_env_ #1 _end: }
% \exp_not:N \tracingnone
-% \exp_not:n { \@kernel@math@registered@end }
}
- {
- }
+ {
+ }
}
-\cs_set_protected:Npn \__cs_tmp:w #1
- {
- \group_begin:
- \exp_args:No \__cs_generate_internal_variant:n
- { \tl_to_str:n {#1} }
- \group_end:
- }
-\__cs_tmp:w { nnxx }
-
-
\cs_new_protected:Npn \math_register_halign_env:nn #1#2
{
\tl_set:Nn \l_@@_env_name_tl {#1}
@@ -525,15 +1540,8 @@
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
- \ExpandArgs { nnxx } \RenewDocumentEnvironment {#1} { b }
+ \ExpandArgs { nnee } \RenewDocumentEnvironment {#1} { b }
{
-% \bool_set_true:N \exp_not:N \l_@@_collected_bool
-% \cs_if_exist:cTF { @@_env #1 _aux: }
-% {
-% \exp_not:c { @@_env #1 _aux: }
-% ####1 \exp_not:N \@@_env_end: {#1}
-% }
-% { \exp_not:N \@@_process:nn {#1} {####1} }
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
% \typeout{===>B1}
@@ -543,23 +1551,24 @@
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
- ####1 \exp_not:N \@@_env_end: {#1}
+ ##1 \exp_not:N \@@_env_end: {#1}
}
- { \exp_not:N \@@_process:nn {#1} {####1} }
+ { \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
-% \exp_not:N \tracingall
+% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
- ####1
-% \exp_not:c { @@_env_ #1 _end: }
+ ##1
% \exp_not:N \tracingnone
}
- {
- \exp_not:c { @@_env_ #1 _end: }
- }
+ {
+ \exp_not:c { @@_env_ #1 _end: }
+ }
}
-
+% \end{macrocode}
+% TODO: the following command is neither documented nor used. Is is needed?
+% \begin{macrocode}
\cs_new_protected:Npn \math_register_odd_env:nn #1#2
{
\tl_set:Nn \l_@@_env_name_tl {#1}
@@ -567,7 +1576,7 @@
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
- \ExpandArgs { nnxx } \RenewDocumentEnvironment {#1} { b }
+ \ExpandArgs { nnee } \RenewDocumentEnvironment {#1} { b }
{
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
@@ -578,19 +1587,19 @@
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
- ####1 \exp_not:N \@@_env_end: {#1}
+ ##1 \exp_not:N \@@_env_end: {#1}
}
- { \exp_not:N \@@_process:nn {#1} {####1} }
+ { \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
-% \exp_not:N \tracingall
+% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
- ####1
+ ##1
}
{
\exp_not:c { @@_env_ #1 _end: }
-% needed if we don't have $$...$$
+% needed if we don't have $$...$$
% \exp_not:n { \typeout{---> @kernel@math@registered@end }}
\exp_not:n { \@kernel@math@registered@end }
}
@@ -614,7 +1623,7 @@
\cs_new:Npn \@kernel@math@registered@begin {
-% \ShowTagging{struct-stack}
+% \ShowTagging{struct-stack}
%\typeout{==>A1}\ShowTagging{struct-stack,mc-current}
\mode_if_vertical:TF
{
@@ -623,19 +1632,21 @@
% { \__block_list_beginpar_vmode: }
%
% \typeout{==>~ at:~ \g__tag_struct_tag_tl}
-%
- \exp_args:Noo\str_if_eq:nnF \g__tag_struct_tag_tl { \l__tag_para_main_tag_tl } % needs correction!
+%
+ \tag_if_active:T
+ {
+ \exp_args:Noo\str_if_eq:nnF \g__tag_struct_tag_tl { \l__tag_para_main_tag_tl } % needs correction!
{
% \typeout{==>A2}
\__block_beginpar_vmode:
} % needs correction!
+ }
}
{
% \typeout{==>A3}
- \@kernel@close@P
-% \tagmcend % needs correction!
+ \__tag_tool_close_P:
}
- \@kernel@math@begin
+ \socket_use:nn{tagsupport/math/display/formula/begin}{}
\tagpdfparaOff
% \typeout{==>MC1}\ShowTagging{mc-current}
}
@@ -644,13 +1655,14 @@
% \typeout{==>MC2}\ShowTagging{mc-current}
\para_raw_end:
\tagpdfparaOn
- \@kernel@math@end
+ \socket_use:n{tagsupport/math/display/formula/end}
% \typeout{==>MC3}\ShowTagging{mc-current}
\@endpetrue
}
-
+
\cs_new_protected:Npn \math_register_env:n #1
{ \math_register_env:nn {#1} { } }
+
\NewDocumentCommand \RegisterMathEnvironment { O{} m }
{ \math_register_env:nn {#2} {#1} }
% \end{macrocode}
@@ -660,12 +1672,12 @@
%
% \begin{macro}{\@@_env_forward:w}
% \begin{macrocode}
-\cs_new_protected:Npn \@@_env_forward:w #1 \@@_env_end: #2
+\cs_new_protected:Npn \@@_env_forward:w #1 \@@_env_end: #2
{ \@@_process:nn {#2} {#1} }
% \end{macrocode}
% \end{macro}
-%
-% \subsection{Document commands}
+%
+% \subsection{Document commands}
%
% \car*{Add one more here: \texttt{displaymath}, which
% is equivalent to \cs{[} , \cs{]}\\
@@ -692,9 +1704,9 @@
% at the moment register_env can only do display math
% \math_register_env:n { math }
\RenewDocumentEnvironment{math} {b}{$#1$}{}
-% and this one doesn't work either
+% and this one doesn't work either
% \math_register_env:n { displaymath }
- \RenewDocumentEnvironment{displaymath} {b}{\[#1\]}{}
+ \RenewDocumentEnvironment{displaymath} {b}{\[#1\]}{}
}
% \end{macrocode}
% \end{macro}
@@ -737,29 +1749,31 @@
{
\cs_gset_protected:Npn \[ % \]
{
- \bool_if:NTF \l_@@_collected_bool
- { \begin { equation* } }
- { \@@_grab_eqn:w }
+ \@@_grab_eqn:w
+ % \bool_if:NTF \l_@@_collected_bool
+% { \begin { equation* } }
+% { \@@_grab_eqn:w }
} % \[
\cs_gset_protected:Npn \]
{
- \bool_if:NTF \l_@@_collected_bool
- { \end{ equation* } }
- { \@badmath }
+ \@badmath
+% \bool_if:NTF \l_@@_collected_bool
+% { \end{ equation* } }
+% { \@badmath }
}
}
% \end{macrocode}
% \end{macro}
-%
+%
%
% \begin{macro}{\ensuremath}
% A bit of nesting fun to make sure we collect only if required.
% \fmi{why does ensuremath need handling at all?}
-%
-% \car{Indeed! Currently, this is setup to process the math that
-% it has anyways already captured as its argument; thus it is more
+%
+% \car{Indeed! Currently, this is setup to process the math that
+% it has anyways already captured as its argument; thus it is more
% efficient than leaving the capture to be repeated by the \cs{everymath}}
-%
+%
% \begin{macrocode}
%\cs_gset_protected:Npn \ensuremath #1
% {
@@ -786,47 +1800,6 @@
% have macro control.
% \begin{macrocode}
-\tl_new:N\tmpmathcontent
-
-
-\def\@kernel@math@begin {
-% \typeout{==>~math~begin}
-% needs different handling if we support nesting
- \tl_gset:Nx\tmpmathcontent
- {
- LaTeX~ formula~ starts~
- \exp_not:N\begin{\g_@@_grabbed_env_tl}
- \space
- \exp_not:V\g_@@_grabbed_math_tl
- \space
- \exp_not:N\end{\g_@@_grabbed_env_tl}
- \space LaTeX~ formula~ ends~
- }
- \tagstructbegin{tag=Formula,
- AFinline-o=\tmpmathcontent,
- title-o=\g_@@_grabbed_env_tl,
- actualtext=\tmpmathcontent
-% alt=\tmpmathcontent
- }
-% inner formula if multiple parts (not really implemented yet)
- \grabaformulapartandstart
-% the above does:
-% \tagstructbegin{tag=Formula}\tagmcbegin{}
-% or just
-% \tagmcbegin{}
-}
-\def\@kernel@math@end {
-% \typeout{==>~math~end}
-% \ShowTagging{struct-stack}
- \tagmcend
- \if@subformulas
- \tagstructend
- \else
- \fi
- \tagstructend
-% \ShowTagging{struct-stack}
-}
-
\exp_args:No \tex_everymath:D
{
\tex_the:D \tex_everymath:D
@@ -841,24 +1814,21 @@
{
\tex_the:D \tex_everydisplay:D
\iftrue % this may have to be a settable flag!
-% {
% \typeout{==>~ in~ everydisplay}
% \end{macrocode}
-% flipping the \cs{belowdisplay} values is done so that we get (assumption)
-% a negative skip and not make the page bigger then we take that out,
-% then we add the tagging code (in \cs{@@_tag_dollardollar_display_end} ) and
-% then we put a real \cs{postdisplaypenalty} in and
-% the right skip (of which we don't know if it is short or a
-% normal \cs{belowdisplayskip}). This might need some refinement if that skip
-% is actually negative from the start
+% flipping the \cs{belowdisplay} values is done so that we get (assumption)
+% a negative skip and not make the page bigger then we take that out,
+% then we add the tagging code (in \cs{@@_tag_dollardollar_display_end} ) and
+% then we put a real \cs{postdisplaypenalty} in and
+% the right skip (of which we don't know if it is short or a
+% normal \cs{belowdisplayskip}). This might need some refinement if that skip
+% is actually negative from the start
% (not sure it ever is and is worth bothering about)
% \begin{macrocode}
\skip_set:Nn \belowdisplayskip {-\belowdisplayskip}
\skip_set:Nn \belowdisplayshortskip {-\belowdisplayshortskip}
\int_set:Nn \postdisplaypenalty {10000}
-%
\group_insert_after:N \@@_tag_dollardollar_display_end:
-% }
\fi
\bool_if:NF \l_@@_collected_bool
{
@@ -876,14 +1846,23 @@
\math_register_env:n { eqnarray* }
% \end{macrocode}
%
-% Places where math mode is (ab)used.
+% Tabulars currently contain a \$ that shouldn't trigger math
+% tagging.
% \begin{macrocode}
-\clist_map_inline:nn
- { tabular }
- {
- \AddToHook{ env / #1 / begin }
- { \bool_set_true:N \l_@@_collected_bool }
- }
+\RequirePackage{array}
+\tl_if_in:NnT\@tabular{$}
+ {
+ \def\@tabular{%
+ \leavevmode
+ \UseTaggingSocket{tbl/hmode/begin}%
+ \hbox \bgroup
+ \bool_set_true:N \l_@@_collected_bool
+ $
+ \bool_set_false:N \l_@@_collected_bool
+ \col@sep\tabcolsep \let\d@llarbegin\begingroup
+ \let\d@llarend\endgroup
+ \@tabarray}
+ }
% \end{macrocode}
%
% \begin{macro}{\@@_m@th:, \m@th}
@@ -898,6 +1877,20 @@
}
% \end{macrocode}
% \end{macro}
+%
+% \subsection{Disable math grabbing in the begindocument hook}
+% For example amsart uses math to measure text there.
+%
+% \begin{macrocode}
+\tl_gput_right:Nn\@kernel@before@begindocument
+ {
+ \bool_set_true:N\l_@@_collected_bool
+ }
+\tl_gput_right:Nn\@kernel@after@begindocument
+ {
+ \bool_set_false:N\l_@@_collected_bool
+ }
+% \end{macrocode}
%
% \subsection{Modifying \pkg{amsmath}}
%
@@ -934,7 +1927,7 @@
$$\ignorespacesafterend
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\def\common@align@ending {
\math@cr \black@\totwidth@
@@ -1007,9 +2000,11 @@
% \end{macrocode}
%
% \begin{macrocode}
-%
+%
\math_register_halign_env:nn {align}{}
\math_register_halign_env:nn {align*}{}
+ \math_register_halign_env:nn {alignat}{}
+ \math_register_halign_env:nn {alignat*}{}
\math_register_halign_env:nn {flalign}{}
\math_register_halign_env:nn {flalign*}{}
\math_register_halign_env:nn {gather}{}
@@ -1032,44 +2027,8 @@
\fi
}
% \end{macrocode}
-%
-% \begin{macrocode}
- \def\intertext@{%
- \def\intertext##1{%
- \ifvmode\else\\\@empty\fi
- \noalign{%
-% we have to flip the sign on the skip because we flipped it on the outside
- \penalty\postdisplaypenalty\vskip-\belowdisplayskip
- \vbox{
-% \end{macrocode}
-% Stop tagging when measuring:
-% \begin{macrocode}
- \ifmeasuring@\tag_stop:\fi
- \normalbaselines
- \ifdim\linewidth=\columnwidth
- \else \parshape\@ne \@totalleftmargin \linewidth
- \fi
-% \end{macrocode}
-% End the previous mc:\fmi{if we use 2 levels of formulas this would
-% need changing}
-% \begin{macrocode}
- \tag_mc_end_push:
-% \end{macrocode}
-% We are already in a par so we change now to Span:\fmi{not true any longer}
-% \begin{macrocode}
- \tagpdfsetup{paratag=P}%
- \tagpdfparaOn
- \noindent\ignorespaces##1\par
-% \end{macrocode}
-% Restart the MC
-% \begin{macrocode}
- \tag_mc_begin_pop:n{}}%
- \penalty\predisplaypenalty\vskip\abovedisplayskip%
- }%
- }
- }
-% \end{macrocode}
-%
+%
+%
% \begin{macrocode}
\@namedef{math@cr @ @ @ gather}{%
\ifst@rred\nonumber\fi
@@ -1083,7 +2042,7 @@
\cr
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\@namedef{math@cr @ @ @ align}{%
\ifst@rred\nonumber\fi
@@ -1104,7 +2063,7 @@
\cr
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\def\restore@math@cr{\@namedef{math@cr @ @ @}{
%
@@ -1113,7 +2072,7 @@
\cr}}
\restore@math@cr
% \end{macrocode}
-%
+%
% \begin{macrocode}
}
% \end{macrocode}
@@ -1125,9 +2084,18 @@
%
%
-% \begin{macro}{}
+% \begin{macro}{\@@_split_at_nl:NN}
+% This splits grabbed math at newlines.
%
% \begin{macrocode}
+\cs_new:Npn \@@_split_at_nl:NN #1#2 {
+ \tl_set:Nf \l_@@_tmpa_tl {
+ \exp_after:wN \@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop }
+ \exp_after:wN \@@_split_at_nl_aux:nnNN \l_@@_tmpa_tl #1 #2
+}
+% \end{macrocode}
+% and the auxiliary commands
+% \begin{macrocode}
\cs_new:Npn \@@_split_at_nl_first:w #1 \\ #2 \\ #3 \s_stop
{
\quark_if_nil:nTF {#2}
@@ -1137,8 +2105,15 @@
#2 \\ #3 \s_stop
}
}
-\cs_new:Npn \@@_split_chk_if_begin:ww #1 \begin #2 #3 \s_mark
- #4 \\ \q_nil \\ \s_stop
+
+\cs_new_protected:Npn \@@_split_at_nl_aux:nnNN #1 #2 #3 #4
+ {
+ \tl_gset:Nn #4 {#1}
+ \tl_gset:Nn #3 {#2}
+ }
+
+\cs_new:Npn \@@_split_chk_if_begin:ww
+ #1 \begin #2 #3 \s_mark #4 \\ \q_nil \\ \s_stop
{
\quark_if_nil:nTF {#2}
{ {#1} {#4} }
@@ -1148,7 +2123,9 @@
{ } { 1 }
}
}
+
\cs_new:Npn \@@_split_cleanup_begin_q_nil:w #1 \begin \q_nil {#1}
+
\cs_new:Npn \@@_split_collect_one_end:w #1 \end #2 #3 \s_stop #4 #5
{
\exp_args:Nf \@@_split_check_count_begins:nnnn
@@ -1157,14 +2134,16 @@
}
\cs_new:Npn \@@_split_count_begins:n #1
{ \int_eval:n { 0 \@@_split_count_begins:w #1 \begin \q_nil } }
+
\cs_new:Npn \@@_split_count_begins:w #1 \begin #2
{ \quark_if_nil:nF {#2} { +1 \@@_split_count_begins:w } }
+
\cs_new:Npn \@@_split_check_count_begins:nnnn #1 #2 #3 #4
{
\int_compare:nNnTF {#1} = {#2}
{
\exp_last_unbraced:Nf \@@_split_final_cleanup:nn
- { \split:n { \@@_split_guard:n {#3} #4 } }
+ { \@@_split:n { \@@_split_guard:n {#3} #4 } }
}
{
\exp_args:No \use_ii_i:nn
@@ -1184,29 +2163,17 @@
{ \exp_end: { #4 #1 } }
{ \@@_split_final_cleanup:w #3 \s_mark { #4 #1 #2 } }
}
-\NewDocumentCommand \splitnl { mm +m }
- {
- \tl_set:Nf \l_tmpa_tl { \split:n {#3} }
- \show \l_tmpa_tl
- \exp_after:wN \__splitnl_aux:nnNN \l_tmpa_tl #1 #2
- }
-
-
-\cs_new:Npn \split:n #1 {
+
+\cs_new:Npn \@@_split:n #1 {
\@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop }
-
-\cs_new:Npn \@@_split_at_nl:NN #1#2 {
- \tl_set:Nf \l_tmpa_tl {
- \exp_after:wN \@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop }
- \exp_after:wN \@@_split_at_nl_aux:nnNN \l_tmpa_tl #1 #2
-}
-
-\cs_new_protected:Npn \@@_split_at_nl_aux:nnNN #1 #2 #3 #4
- {
- \tl_gset:Nn #4 {#1}
- \tl_gset:Nn #3 {#2}
-}
-
+
+% this looks unused.
+%\NewDocumentCommand \splitnl { mm +m }
+% {
+% \tl_set:Nf \l_@@_tmpa_tl { \split:n {#3} }
+% \show \l_@@_tmpa_tl
+% \exp_after:wN \__splitnl_aux:nnNN \l_@@_tmpa_tl #1 #2
+% }
% \end{macrocode}
% \end{macro}
%
@@ -1233,9 +2200,11 @@
\edef\resulttitle{\g_@@_grabbed_env_tl\space (part)}
\tagstructbegin{tag=Formula,
% \end{macrocode}
-% For now we don't put anything in /alt or /ActualText on subformulas
+% For now we don't put real content in /alt or /ActualText on subformulas
+% but we add a short text to satisfy the pdf/ua-2 validator
% \begin{macrocode}
% alt=\result,
+ alt = subformula,
title-o=\resulttitle
}
}
@@ -1301,10 +2270,6 @@
% \end{macrocode}
%
% \begin{macrocode}
-%
-% \end{macrocode}
-%
-% \begin{macrocode}
%</kernel>
% \end{macrocode}
%
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-mathpkg.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-mathpkg.dtx
index 14d8e943624..31e7d31ef62 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-mathpkg.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-mathpkg.dtx
@@ -2,7 +2,7 @@
%
%% File: latex-lab-mathpkg.dtx
%
-% Copyright (C) 2022,2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -68,15 +68,8 @@
\ProvidesFile{latex-lab-mathpkg.ltx}
[2023-01-05 v0.1a mathpkg adaptions]
% \end{macrocode}
-% \subsection{Tagpdf support}
-% To make the code independent from tagging being loaded and active
-% we load the \pkg{tagpdf-base} package:
-%
-% \begin{macrocode}
-\RequirePackage{tagpdf-base}
-% \end{macrocode}
-%
%
+% \subsection{breqn}
% \begin{macrocode}
\AddToHook{package/breqn/after}{
\RegisterMathEnvironment{dmath}
@@ -86,6 +79,7 @@
}
% \end{macrocode}
%
+% \subsection{cases}
% Force loading of \pkg{amsmath} before \pkg{cases}.
% \begin{macrocode}
\AddToHook {package/cases/before}{\RequirePackage{amsmath}}
@@ -94,6 +88,29 @@
}
% \end{macrocode}
%
+% \subsection{bm}
+% Similar to the amsbsy code in latex-lab-amsmath for \cs{pmb} we need to mark up
+% copies as artifact:
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+\AddToHook{package/bm/after}
+ {
+ \def\bm@pmb@@@@#1#2#3{{%
+ \hbox_set:Nn\l_@@_tmpa_box{$\m@th#1#3$}%
+ \dimen@#2\wd\tw@
+ \rlap{\box_use:N\l_@@_tmpa_box}%
+ \tag_mc_end:\tag_mc_begin:n{artifact}
+ \tag_mc_reset_box:N\l_@@_tmpa_box
+ \kern\dimen@
+ \raise1.5\dimen@\rlap{\box_use:N\l_@@_tmpa_box}%
+ \kern\dimen@
+ \box_use_drop:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{}%
+ }}
+ }
+\ExplSyntaxOff
+% \end{macrocode}
% \begin{macrocode}
%</kernel>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-mathtools.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-mathtools.dtx
index c3f43243b10..aa27cbf01d9 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-mathtools.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-mathtools.dtx
@@ -2,7 +2,7 @@
%
%% File: latex-lab-mathtools.dtx
%
-% Copyright (C) 2022,2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -109,7 +109,7 @@
\def\intertext##1{%
\ifvmode\else\\\@empty\fi
\noalign{%
- \penalty\postdisplaypenalty\vskip\belowdisplayskip
+ \penalty\postdisplaypenalty\vskip-\belowdisplayskip
\vskip-\lineskiplimit % CCS
\vskip\normallineskiplimit % CCS
\vskip\l_MT_above_intertext_sep
@@ -135,7 +135,7 @@
% \end{macrocode}
% We are already in a par so we change now to Span:
% \begin{macrocode}
- \tagpdfsetup{paratag=Span}
+ \tagpdfsetup{para/tag=Span}
\noindent\ignorespaces##1\par
% \end{macrocode}
% Restart the MC
@@ -169,7 +169,8 @@
\parshape\@ne \@totalleftmargin \linewidth
\MH_fi:
\tag_mc_end_push:
- \tagpdfsetup{paratag=Span}
+ \tagpdfsetup{para/tag=Span}
+ \tagpdfparaOn
\noindent\ignorespaces#1\par
\tag_mc_begin_pop:n{}}
\penalty\predisplaypenalty\vskip\abovedisplayshortskip%
@@ -197,7 +198,11 @@
\parshape\@ne \@totalleftmargin \linewidth
\MH_fi:
\tag_mc_end_push:
- \tagpdfsetup{paratag=Span}
+ \tagpdfsetup{para/tag=P}
+% \end{macrocode}
+% Why is it needed to enable paratagging??
+% \begin{macrocode}
+ \tagpdfparaOn
\noindent\ignorespaces#1\par
\tag_mc_begin_pop:n{}}%
\penalty\predisplaypenalty\vskip\abovedisplayshortskip%
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-minipage.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-minipage.dtx
index 1d3ee828aa4..ffbe5357e76 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-minipage.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-minipage.dtx
@@ -1,6 +1,8 @@
% \iffalse meta-comment
%
-%% File: latex-lab-minipage.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-minipage.dtx
+%%
+% Copyright (C) 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-namespace.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-namespace.dtx
index 2ec9b0584bf..cfc06c7b093 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-namespace.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-namespace.dtx
@@ -1,6 +1,8 @@
% \iffalse meta-comment
%
-%% File: latex-lab-namespace.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-namespace.dtx
+%%
+% Copyright (C) 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -24,7 +26,7 @@
% \fi
% \title{Prototype reimplementation of \LaTeXe{}'s role mapping}
% \author{\LaTeX{} Project, initial implementation Ulrike Fischer}
-% \date{v0.8 2023-09-04}
+% \date{v0.8b 2024-03-24}
%
% \maketitle
%
@@ -60,18 +62,33 @@
% \begin{macrocode}
title, Title, pdf2,
part, Title, pdf2,
+% \end{macrocode}
+% Headings differ in article and book class. This here is for article:
+% \begin{macrocode}
section, H1, pdf2,
subsection, H2, pdf2,
subsubsection,H3, pdf2,
paragraph, H4, pdf2,
subparagraph, H5, pdf2,
+% \end{macrocode}
+% And this here is used in book:
+% \begin{macrocode}
+%chapter, H1, pdf2,
+%section, H2, pdf2,
+%subsection, H3, pdf2,
+%subsubsection, H4, pdf2,
+%paragraph, H5, pdf2,
+%subparagraph, H6, pdf2,
+% \end{macrocode}
+%
+% \begin{macrocode}
list, L, pdf2,
itemize, L, pdf2,
enumerate, L, pdf2,
description, L, pdf2,
quote, BlockQuote,pdf,
quotation, BlockQuote,pdf,
-verbatim, Div, pdf2,
+verbatim, Div, pdf2, % overwritten by block
item, LI, pdf2,
itemlabel, Lbl, pdf2,
itembody, LBody, pdf2,
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-1.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-1.dtx
index cc60f50de01..9994b15cb8d 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-1.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-1.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-new-or-1.dtx (C) Copyright 2020-2023 Frank Mittelbach
+%% File: latex-lab-new-or-1.dtx (C) Copyright 2020-2024 Frank Mittelbach
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-2.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-2.dtx
index d2011256b1a..ee20331a8f4 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-2.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-new-or-2.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
%% File: latex-lab-new-or-2.dtx
-% Copyright (C) 2022-2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-sec.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-sec.dtx
index ae7a0b85c30..f3786c2ddb8 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-sec.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-sec.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-sec.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-sec.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,10 +16,10 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabsecdate{2023-10-16}
-\def\ltlabsecversion{0.84b}
+\def\ltlabsecdate{2024-02-12}
+\def\ltlabsecversion{0.84c}
%<*driver>
-\documentclass{l3doc}
+\documentclass[kernel]{l3doc}
\EnableCrossrefs
\CodelineIndex
\begin{document}
@@ -214,11 +214,11 @@
\fi
\IfBooleanTF {#1}
{
- \tl_gset:Nx \@currentHref {#3}
+ \tl_gset:Ne \@currentHref {#3}
}
{
\int_gincr:N\g__kernel_target_int
- \tl_gset:Nx \@currentHref {target*.\int_use:N\g__kernel_target_int}
+ \tl_gset:Ne \@currentHref {target*.\int_use:N\g__kernel_target_int}
}
}
\ExplSyntaxOff
@@ -260,7 +260,7 @@
tag= {\int_compare:nNnTF {#1}={-1}{Part}{Sect}}
,#2
}
- \seq_gpush:Nx \g__tag_sec_stack_seq {{\g__tag_struct_tag_tl}{\int_eval:n{#1}}}
+ \seq_gpush:Ne \g__tag_sec_stack_seq {{\g__tag_struct_tag_tl}{\int_eval:n{#1}}}
}
% \end{macrocode}
% \end{macro}
@@ -289,7 +289,7 @@
\__tag_sec_end:n {#1}
}
{
- \msg_warning:nnxx {tag}{wrong-sect-nesting}
+ \msg_warning:nnee {tag}{wrong-sect-nesting}
{ \exp_last_unbraced:NV\use_i:nn \l__tag_tmpa_tl }
{ \exp_last_unbraced:NV\use_i:nn \l__tag_tmpb_tl }
}
@@ -670,6 +670,7 @@
\cs_new_protected:Npn \@kernel@tag@hangfrom #1
{
\tagstructbegin{tag=\l__tag_para_tag_tl}
+ \cs_if_exist_use:N \__tag_gincr_para_begin_int:
\tagstructbegin{tag=Lbl}
\setbox\@tempboxa
\hbox
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-table.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-table.dtx
index 700d4ce6c17..38596478aeb 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-table.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-table.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-table.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-table.dtx (C) Copyright 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabtbldate{2023-10-30}
-\def\ltlabtblversion{0.85d}
+\def\ltlabtbldate{2024-05-25}
+\def\ltlabtblversion{0.85i}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -115,9 +115,20 @@
% Such tables can be nested.
%
% If a table should not be tagged as table, for example because it is merely used
-% to produce a layout or because it is a not yet (fully) supported table structure,
+% as a layout to ensure that the content is properly aligned
+% or because it is a not yet (fully) supported table structure,
% the tagging can be disabled with
-% \verb|\tagpdfsetup{table-tagging=false}|.
+% \verb|\tagpdfsetup{table/tagging=false}| or with \verb|\tagpdfsetup{table/tagging=presentation}|%
+% \footnote{The key has been renamed. The old name `table-tagging` still works but is
+% deprecated. The value \texttt{presentation} refers to the ARIA role \enquote{presentation}.}
+% The first option disables the table tagging code and the content of the tabular
+% is then treated more or less like running text. This works ok for simple tables using
+% only hmode-cells (l/c/r) with normal text content, but fails if the table uses vmode-cells
+% (p/m/b). In such cases the second option works better: it keeps the tagging code active
+% but changes the tag names to \texttt{Div} and the grouping structure \texttt{NonStruct}. It also
+% (re)sets the \texttt{table/header-rows} key to empty.
+% The key should currently only be used in a group as there is no key (yet) to reset to the default
+% tag names.
%
% Inside cells the automatic tagging of paragraphs is disabled with the exception of
% p/m/b-type cells.
@@ -126,9 +137,10 @@
% added with an empty TD-structure.
%
% There is some basic support\footnote{This is not meant to be the
-% final interface, though.} for headers. With
+% final interface, though.} for headers. With\footnote{The old key name \texttt{table-header-rows} still
+% works but is deprecated.}
% \begin{quote}
-% \verb|\tagpdfsetup{table-header-rows={|\meta{list of row numbers}\verb|}|
+% \verb|\tagpdfsetup{table/header-rows={|\meta{list of row numbers}\verb|}|
% \end{quote}
% you can
% declare which (absolute) row numbers should be tagged as header rows.
@@ -139,7 +151,7 @@
% for header columns yet. In a \env{longtable} the code will currently use the \cs{endhead} or
% \cs{endfirsthead} rows as header if one of these commands has been
% used and in that case the code
-% ignores a \texttt{table-header-rows} setting.
+% ignores a \texttt{table/header-rows} setting.
%
% You should not insert meaningful text with \verb+!{...}+ or \verb+@{...}+ or \cs{noalign}
% between the rows or columns of the table.
@@ -193,7 +205,8 @@
%
% \item Not every table should be tagged as a Table structure, often they are
% only used as layout help, e.g. to align authors in a title pages. In such uses
-% the tagging of the table must be deactivated with \verb|\tagpdfsetup{table-tagging=false}|.
+% the tagging of the table must be deactivated with \verb|\tagpdfsetup{table/tagging=false}|
+% or \verb|\tagpdfsetup{table/tagging=presentation}|.
%
% \item Only simple header rows are currently supported. Columns and complex headers with
% subheaders will be handled later as that needs some syntax changes. Tables
@@ -210,6 +223,8 @@
%
% \item The \env{longtable} environment supports footnotes in p-type columns, but it hasn't been
% tested yet if this works also with the tagging code.
+%
+% \item Vertical boxes (\cs{parbox}, \texttt{minipage}, \ldots) inside cells can be problematic.
%
% \item The code is quite noisy and fills the log with lots of
% messages.\footnote{Helpful for us at this stage.}
@@ -271,10 +286,11 @@
% \begin{macro}
% {
% \l_@@_celltag_tl
+% \l_@@_pcelltag_tl
% ,\l_@@_rowtag_tl
+% ,\l_@@_table_tl
% ,\l_@@_cellattribute_tl
% ,\l_@@_rowattribute_tl
-% ,\g_@@_missingcells_int
% ,\l_@@_tmpa_clist
% ,\l_@@_tmpa_seq
% ,\l_@@_tmpa_tl
@@ -283,12 +299,19 @@
% \begin{macrocode}
\tl_new:N \l_@@_celltag_tl
\tl_set:Nn \l_@@_celltag_tl {TD}
+\tl_new:N \l_@@_pcelltag_tl
+\tl_set:Nn \l_@@_pcelltag_tl {TD}
% \end{macrocode}
% For the rowtag, probably always TR:
% \begin{macrocode}
\tl_new:N \l_@@_rowtag_tl
\tl_set:Nn \l_@@_rowtag_tl {TR}
% \end{macrocode}
+% For the tabletag, probably always Table:
+% \begin{macrocode}
+\tl_new:N \l_@@_tabletag_tl
+\tl_set:Nn \l_@@_tabletag_tl {Table}
+% \end{macrocode}
% And here cell and row attributes:
% \begin{macrocode}
\tl_new:N \l_@@_cellattribute_tl
@@ -296,94 +319,27 @@
\tl_new:N \l_@@_rowattribute_tl
\tl_set:Nn \l_@@_rowattribute_tl {}
% \end{macrocode}
-% This will contain the number of missing cells used:
-% \begin{macrocode}
-\int_new:N \g_@@_missing_cells_int
-% \end{macrocode}
% Temp variables
% \begin{macrocode}
\clist_new:N \l_@@_tmpa_clist
-\seq_new:N \l_@@_tmpa_seq
\tl_new:N \l_@@_tmpa_tl
% \end{macrocode}
% \end{macro}
%
-% \subsection{Sockets}
-%
-% The code uses a number of sockets to inject the tagging
-% commands. These can be easily set to a noop-plug in case the
-% automated tagging is not wanted At first sockets for the begin and
-% end of cells and rows
-%
-% \begin{socketdecl}{tagsupport/tblcell/begin,
-% tagsupport/tblcell/end,
-% tagsupport/tblrow/begin,
-% tagsupport/tblrow/end,
-% }
-% \begin{macrocode}
-\NewSocket{tagsupport/tblcell/begin}{0}
-\NewSocket{tagsupport/tblcell/end}{0}
-\NewSocket{tagsupport/tblrow/begin}{0}
-\NewSocket{tagsupport/tblrow/end}{0}
-% \end{macrocode}
-% \end{socketdecl}
-%
-% \begin{socketdecl}{tagsupport/tbl/init}
-% This socket should be at the begin of the table, inside a group.
-% It is meant for settings like disabling paratagging. This socket
-% can perhaps be merged later into the begin-sockets when they are
-% no longer added as hooks but in the environment definitions.
-% \begin{macrocode}
-\NewSocket{tagsupport/tbl/init}{0}
-% \end{macrocode}
-% \end{socketdecl}
-%
-%
-% \begin{socketdecl}{tagsupport/tbl/finalize}
-% To fine tune the structure (change cells to header cells, remove
-% unwanted structures, move a foot to the end, etc.) we also need a
-% socket that is executed at the end of the table but \emph{before}
-% all the variables are restored to the outer or default values.
-% The code in the socket can make assignments, but probably
-% shouldn't do typesetting and not write whatsits.
-% \begin{macrocode}
-\NewSocket{tagsupport/tbl/finalize}{0}
-% \end{macrocode}
-% \end{socketdecl}
+% \subsection{Tagging support sockets}
%
-% \begin{socketdecl}{tagsupport/tbl/finalize/longtable}
-% \env{longtable} needs its own socket to fine tune the structure.
-% Simply switching the plug in the previous socket interferes with
-% enabling/disabling the tagging.
-% \begin{macrocode}
-\NewSocket{tagsupport/tbl/finalize/longtable}{0}
-% \end{macrocode}
-% \end{socketdecl}
-%
-% \begin{socketdecl}{tagsupport/tblhmode/begin,
-% tagsupport/tblhmode/end,
-% tagsupport/tblvmode/begin,
-% tagsupport/tblvmode/end
-% }
-%
-% These sockets are used in the begin and end code of environments,
-% to allow a fast enabling and disabling of the tagging. We
-% distinguish between tables that can be used inside paragraphs and
-% standalone tables like longtable.
-% \begin{macrocode}
-\NewSocket{tagsupport/tblhmode/begin}{0}
-\NewSocket{tagsupport/tblhmode/end}{0}
-\NewSocket{tagsupport/tblvmode/begin}{0}
-\NewSocket{tagsupport/tblvmode/end}{0}
-% \end{macrocode}
-% \end{socketdecl}
%
% This are the standard plugs for tagging of cells and rows.
%
% \begin{plugdecl}{TD}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblcell/begin}{TD}
+\NewSocketPlug{tagsupport/tbl/cell/begin}{TD}
{
+% \end{macrocode}
+% Next line was previously outside of the plug, so if we want to execute it
+% always even if the noop plug is in force this needs a different solution.
+% \begin{macrocode}
+ \@@_show_curr_cell_data:
\tag_struct_begin:n
{
tag =\l_@@_celltag_tl,
@@ -405,7 +361,7 @@
%
% \begin{plugdecl}{TD}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblcell/end}{TD}
+\NewSocketPlug{tagsupport/tbl/cell/end}{TD}
{
\tag_mc_end:
\tag_struct_end:
@@ -415,14 +371,14 @@
%
% In p-columns we need a slightly different plug which reactivates the
% paragraph tagging.
-% tagging
-% \begin{plugdecl}{TD}
+% \begin{plugdecl}{TDpbox}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblcell/begin}{TDpbox}
+\NewSocketPlug{tagsupport/tbl/pcell/begin}{TDpbox}
{
+ \@@_show_curr_cell_data:
\tag_struct_begin:n
{
- tag =\l__tbl_celltag_tl,
+ tag =\l__tbl_pcelltag_tl,
attribute-class =\l__tbl_cellattribute_tl
}
\seq_gput_right:Ne \g__tbl_struct_cur_seq { \tag_get:n {struct_num} }
@@ -436,9 +392,9 @@
% \end{macrocode}
% \end{plugdecl}
%
-% \begin{plugdecl}{TD}
+% \begin{plugdecl}{TDpbox}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblcell/end}{TDpbox}
+\NewSocketPlug{tagsupport/tbl/pcell/end}{TDpbox}
{
\tag_struct_end:
}
@@ -447,7 +403,7 @@
%
% \begin{plugdecl}{TR}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblrow/begin}{TR}
+\NewSocketPlug{tagsupport/tbl/row/begin}{TR}
{
\seq_gclear:N \g_@@_struct_cur_seq
\tag_struct_begin:n
@@ -462,24 +418,28 @@
%
% \begin{plugdecl}{TR}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblrow/end}{TR}
+\NewSocketPlug{tagsupport/tbl/row/end}{TR}
{
- \__tag_tbl_add_missing_cells:n { \g_@@_missing_cells_int }
+ \tag_if_active:T
+ {
+ \@@_add_missing_cells:
\seq_gput_right:Ne \g_@@_struct_cells_seq
{
\seq_use:Nn \g_@@_struct_cur_seq {,}
}
- \int_compare:nNnTF { \g_@@_row_int } = { \seq_count:N\g_@@_struct_cells_seq }
+ \int_compare:nNnTF { \g_@@_row_int } =
+ { \seq_count:N \g_@@_struct_cells_seq }
{
- \typeout
+ \@@_trace:n
{==>~
stucture~stored~for~row~\int_use:N\g_@@_row_int :~
\seq_use:Nn \g_@@_struct_cur_seq {,}
}
}
- { \ERROR } % should not happen ...
+ { \ERRORtbl/row } % should not happen ...
\tag_struct_end:
}
+ }
% \end{macrocode}
% \end{plugdecl}
%
@@ -497,6 +457,10 @@
\tag_if_active:T
{
\bool_set_false:N \l__tag_para_bool
+% \end{macrocode}
+% We also initialize the structure data variables a this point.
+% \begin{macrocode}
+ \@@_init_struct_data:
}
}
% \end{macrocode}
@@ -509,14 +473,41 @@
\NewSocketPlug{tagsupport/tbl/finalize}{Table}
{
\@@_set_header_rows:
+% \end{macrocode}
+% Similarly, we restore the outer values of the structure data when
+% we leave the table.
+% \begin{macrocode}
+ \@@_restore_struct_data:
}
% \end{macrocode}
% \end{plugdecl}
%
+%
+%
+%
+% \begin{plugdecl}{Table}
+% This plug will initialize the structure in longtable.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/tbl/longtable/init}{Table}
+ {
+ \seq_gclear:N\g_@@_struct_rows_seq
+ \seq_gclear:N\g_@@_struct_cells_seq
+ \seq_gclear:N\g_@@_struct_cur_seq
+ \seq_gclear:N\g_@@_LT@firsthead_rows_seq
+ \seq_gclear:N\g_@@_LT@head_rows_seq
+ \seq_gclear:N\g_@@_LT@lastfoot_rows_seq
+ \seq_gclear:N\g_@@_LT@foot_rows_seq
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+%
+
+
% \begin{plugdecl}{Table}
-% This plug will fine tune the structure of longtable.
+% This plug will fine tune the structure in longtable.
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tbl/finalize/longtable}{Table}
+\NewSocketPlug{tagsupport/tbl/longtable/finalize}{Table}
{
% \end{macrocode}
% If neither \cs{endhead} nor \cs{endfirsthead} has been used
@@ -582,7 +573,7 @@
\prop_if_exist:cT
{ g__tag_struct_ \l_@@_tmpa_tl _prop }
{
- \@@_struct_prop_gput:Vnn \l_@@_tmpa_tl {S}{/Artifact}
+ \exp_args:No \__tag_struct_prop_gput:nnn {\l_@@_tmpa_tl} {S}{/Artifact}
}
}
}
@@ -673,7 +664,7 @@
\prop_if_exist:cT
{ g__tag_struct_ \l_@@_tmpa_tl _prop }
{
- \@@_struct_prop_gput:Vnn \l_@@_tmpa_tl {S}{/Artifact}
+ \exp_args:No\__tag_struct_prop_gput:nnn {\l_@@_tmpa_tl} {S}{/Artifact}
}
}
}
@@ -683,11 +674,40 @@
% \end{macrocode}
% \end{plugdecl}
%
+%
+%
+% \begin{plugdecl}{Table}
+%
+% We must avoid that the reuse of the header foot box leads to duplicated
+% content, thus reset attribute of the box:
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/tbl/longtable/head}{Table}
+ {
+ \tagmcbegin{artifact}
+ \tag_mc_reset_box:N\LT@head
+ \tagmcend
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
% \begin{plugdecl}{Table}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblhmode/begin}{Table}
+\NewSocketPlug{tagsupport/tbl/longtable/foot}{Table}
+ {
+ \tagmcbegin{artifact}
+ \tag_mc_reset_box:N \LT@foot
+ \tagmcend
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+%
+%
+%
+% \begin{plugdecl}{Table}
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/tbl/hmode/begin}{Table}
{
- \mode_leave_vertical:
\tag_mc_end_push:
% \end{macrocode}
% Close the P-chunk. This assumes that para-tagging is active.
@@ -696,7 +716,7 @@
\bool_lazy_and:nnT
{ \bool_if_exist_p:N \l__tag_para_bool } { \l__tag_para_bool }
{ \tag_struct_end:n { text } }
- \tag_struct_begin:n {tag=Table}
+ \tag_struct_begin:n {tag=\l_@@_tabletag_tl}
\tl_gset:Ne \g_@@_struct_table_tl { \tag_get:n {struct_num} }
}
% \end{macrocode}
@@ -704,7 +724,7 @@
%
% \begin{plugdecl}{Table}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblhmode/end}{Table}
+\NewSocketPlug{tagsupport/tbl/hmode/end}{Table}
{
\tag_struct_end:
% \end{macrocode}
@@ -721,9 +741,9 @@
%
% \begin{plugdecl}{Table}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblvmode/begin}{Table}
+\NewSocketPlug{tagsupport/tbl/vmode/begin}{Table}
{
- \tag_struct_begin:n {tag=Table}
+ \tag_struct_begin:n {tag=\l_@@_tabletag_tl}
\tl_gset:Ne \g_@@_struct_table_tl { \tag_get:n {struct_num} }
}
% \end{macrocode}
@@ -731,7 +751,7 @@
%
% \begin{plugdecl}{Table}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblvmode/end}{Table}
+\NewSocketPlug{tagsupport/tbl/vmode/end}{Table}
{
\tag_struct_end:
\par
@@ -740,30 +760,50 @@
% \end{plugdecl}
%
%
+% \begin{plugdecl}{code}
+% This socket takes a number, checks if is larger than one,
+% checks if the colspan attribute already exists (we can't predefine an
+% arbitrary number), and updates \cs{l_@@_cellattribute_tl}.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/tbl/colspan}{code}
+ {
+ \int_compare:nNnT {#1}>{1}
+ {
+ \prop_get:NeNF \g__tag_attr_entries_prop
+ {colspan-\int_eval:n{#1}}
+ \l_@@_tmpa_tl
+ {
+ \__tag_attr_new_entry:ee
+ {colspan-\int_eval:n{#1}}
+ {/O /Table /ColSpan~\int_eval:n{#1}}
+ }
+ \tl_set:Ne \l_@@_cellattribute_tl
+ {colspan-\int_eval:n{#1}}
+ }
+ }
+% \end{macrocode}
+% TODO: move to tagpdf
+% \begin{macrocode}
+\tag_if_active:T
+ { \cs_generate_variant:Nn \__tag_attr_new_entry:nn {ee} }
+
+% \end{macrocode}
+% \end{plugdecl}
%
%
%
%\subsection{Environments}
%
-% Currently only tabular, tabular*, tabularx and longtable.
-% We must use the \texttt{before} and \texttt{after} hooks as the \texttt{end}
-% hook is executed before the end of the last row and then MC are messed up.
-% This means that this sockets should only contain code that doesn't needs to be
-% grouped!
-% \begin{macrocode}
-\AddToHook{env/tabular/before} {\UseSocket{tagsupport/tblhmode/begin}}
-\AddToHook{env/tabular/after} {\UseSocket{tagsupport/tblhmode/end}}
-\AddToHook{env/tabular*/before} {\UseSocket{tagsupport/tblhmode/begin}}
-\AddToHook{env/tabular*/after} {\UseSocket{tagsupport/tblhmode/end}}
-\AddToHook{env/tabularx/before} {\UseSocket{tagsupport/tblhmode/begin}}
-\AddToHook{env/tabularx/after} {\UseSocket{tagsupport/tblhmode/end}}
-\AddToHook{env/longtable/before}{\UseSocket{tagsupport/tblvmode/begin}}
-\AddToHook{env/longtable/after} {\UseSocket{tagsupport/tblvmode/end}}
-% \end{macrocode}
+% Currently we support only tabular, tabular*, tabularx and longtable
+% (and possibly environments build directly on top of them).
%
% The \env{array} environment is math. So we disable table tagging for now.
+% We use the command hook to catch also cases where \cs{array} is used directly
+% in other environments like matrix environments.
+% Perhaps table tagging should be disable for math generally, but then
+% we have to handle text insertions.
% \begin{macrocode}
-\AddToHook{env/array/begin} {\__tag_tbl_disable:}
+\AddToHook{cmd/array/before}{\__tag_tbl_disable:}
% \end{macrocode}
%
%
@@ -771,34 +811,6 @@
%
% \subsubsection{Tagging helper commands}
%
-% \begin{macro}{\@@_set_colspan:n}
-% This commands takes a number, checks if is larger than one,
-% checks if the colspan attribute exists (we can't predefine an
-% arbitrary number), and updates \cs{l_@@_cellattribute_tl}.
-% \begin{macrocode}
-\tag_if_active:T
- { \cs_generate_variant:Nn \__tag_attr_new_entry:nn {ee} }
-\cs_new_protected:Npn \@@_set_colspan:n #1
- {
- \tag_if_active:T
- {
- \int_compare:nNnT {#1}>{1}
- {
- \prop_get:NeNF \g__tag_attr_entries_prop
- {colspan-\int_eval:n{#1}}
- \l_@@_tmpa_tl
- {
- \__tag_attr_new_entry:ee
- {colspan-\int_eval:n{#1}}
- {/O /Table /ColSpan~\int_eval:n{#1}}
- }
- \tl_set:Ne \l_@@_cellattribute_tl
- {colspan-\int_eval:n{#1}}
- }
- }
- }
-% \end{macrocode}
-% \end{macro}
%
% \subsubsection{Disabling/enabling}
%
@@ -810,17 +822,23 @@
% \begin{macrocode}
\cs_new_protected:Npn \__tag_tbl_disable:
{
- \AssignSocketPlug{tagsupport/tblcell/begin}{noop}
- \AssignSocketPlug{tagsupport/tblcell/end}{noop}
- \AssignSocketPlug{tagsupport/tblrow/begin}{noop}
- \AssignSocketPlug{tagsupport/tblrow/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/cell/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/cell/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/pcell/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/pcell/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/row/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/row/end}{noop}
\AssignSocketPlug{tagsupport/tbl/init}{noop}
\AssignSocketPlug{tagsupport/tbl/finalize}{noop}
- \AssignSocketPlug{tagsupport/tbl/finalize/longtable}{noop}
- \AssignSocketPlug{tagsupport/tblhmode/begin}{noop}
- \AssignSocketPlug{tagsupport/tblhmode/end}{noop}
- \AssignSocketPlug{tagsupport/tblvmode/begin}{noop}
- \AssignSocketPlug{tagsupport/tblvmode/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/longtable/init}{noop}
+ \AssignSocketPlug{tagsupport/tbl/longtable/head}{noop}
+ \AssignSocketPlug{tagsupport/tbl/longtable/foot}{noop}
+ \AssignSocketPlug{tagsupport/tbl/longtable/finalize}{noop}
+ \AssignSocketPlug{tagsupport/tbl/hmode/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/hmode/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/vmode/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/vmode/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/colspan}{noop}
}
% \end{macrocode}
% \end{macro}
@@ -831,46 +849,59 @@
% \begin{macrocode}
\cs_new_protected:Npn \__tag_tbl_enable:
{
- \AssignSocketPlug{tagsupport/tblcell/begin}{TD}
- \AssignSocketPlug{tagsupport/tblcell/end}{TD}
- \AssignSocketPlug{tagsupport/tblrow/begin}{TR}
- \AssignSocketPlug{tagsupport/tblrow/end}{TR}
+ \AssignSocketPlug{tagsupport/tbl/cell/begin}{TD}
+ \AssignSocketPlug{tagsupport/tbl/cell/end}{TD}
+ \AssignSocketPlug{tagsupport/tbl/pcell/begin}{TDpbox}
+ \AssignSocketPlug{tagsupport/tbl/pcell/end}{TDpbox}
+ \AssignSocketPlug{tagsupport/tbl/row/begin}{TR}
+ \AssignSocketPlug{tagsupport/tbl/row/end}{TR}
\AssignSocketPlug{tagsupport/tbl/init}{Table}
\AssignSocketPlug{tagsupport/tbl/finalize}{Table}
- \AssignSocketPlug{tagsupport/tbl/finalize/longtable}{Table}
- \AssignSocketPlug{tagsupport/tblhmode/begin}{Table}
- \AssignSocketPlug{tagsupport/tblhmode/end}{Table}
- \AssignSocketPlug{tagsupport/tblvmode/begin}{Table}
- \AssignSocketPlug{tagsupport/tblvmode/end}{Table}
+ \AssignSocketPlug{tagsupport/tbl/longtable/head}{Table}
+ \AssignSocketPlug{tagsupport/tbl/longtable/foot}{Table}
+ \AssignSocketPlug{tagsupport/tbl/longtable/init}{Table}
+ \AssignSocketPlug{tagsupport/tbl/longtable/finalize}{Table}
+ \AssignSocketPlug{tagsupport/tbl/hmode/begin}{Table}
+ \AssignSocketPlug{tagsupport/tbl/hmode/end}{Table}
+ \AssignSocketPlug{tagsupport/tbl/vmode/begin}{Table}
+ \AssignSocketPlug{tagsupport/tbl/vmode/end}{Table}
+ \AssignSocketPlug{tagsupport/tbl/colspan}{code}
}
% \end{macrocode}
% \end{macro}
% \begin{macrocode}
-% TODO decide about key name
+% See tagpdfsetup-keys.md in tagpdf/doc for the naming scheme.
\keys_define:nn { __tag / setup }
{
- table-tagging .choices:nn = { true, on }
+ table/tagging .choices:nn = { true, on }
{ \__tag_tbl_enable: },
- table-tagging .choices:nn = { false, off }
+ table/tagging .choices:nn = { false, off }
{ \__tag_tbl_disable: },
- table-tagging .default:n = true,
- table-tagging .initial:n = true
+ table/tagging .choice:,
+ table/tagging / presentation .code:n =
+ {
+ \__tag_tbl_enable:
+ \tl_set:Nn\l_@@_rowtag_tl {NonStruct}
+ \tl_set:Nn\l_@@_pcelltag_tl {NonStruct}
+ \tl_set:Nn\l_@@_celltag_tl {text}
+ \tl_set:Nn\l_@@_tabletag_tl {Div}
+ \clist_clear:N \l_@@_header_rows_clist
+ },
+ table/tagging .default:n = true,
+ table/tagging .initial:n = true
}
% \end{macrocode}
-%
-% Table tagging should be disabled in the head and foot.
+% This are the old key names kept for now for
+% compability. They will got at some time.
% \begin{macrocode}
-\AddToHook{begindocument}
- {
- \cs_if_exist:NT \@kernel@before@head
- {
- \tl_put_right:Nn \@kernel@before@head {\__tag_tbl_disable:}
- \tl_put_right:Nn \@kernel@before@foot {\__tag_tbl_disable:}
- }
- }
+\keys_define:nn { __tag / setup }
+ {
+ table-tagging .meta:n = {table/tagging={#1}}
+ }
% \end{macrocode}
%
+%
% \subsubsection{Header support}
%
% Accessible table must have header cells declaring the meaning of the
@@ -900,17 +931,17 @@
{
\tagpdfsetup
{
- newattribute =
+ role/new-attribute =
{TH-col}{/O /Table /Scope /Column},
- newattribute =
+ role/new-attribute =
{TH-row}{/O /Table /Scope /Row},
- newattribute =
+ role/new-attribute =
{TH-both}{/O /Table /Scope /Both},
}
% \end{macrocode}
%
% And we put all three into the class map (perhaps the next tagpdf
-% should do that directly with newattribute):
+% should do that directly with role/new-attribute):
%
% \begin{macrocode}
\seq_gput_left:Ne\g__tag_attr_class_used_seq
@@ -926,28 +957,13 @@
%
% \begin{variable}{\l_@@_header_rows_clist}
% This holds the numbers of the header rows. Negative numbers are
-% possible and count from the back.
+% possible and count from the last column backwards.
% \begin{macrocode}
\clist_new:N \l_@@_header_rows_clist
% \end{macrocode}
% \end{variable}
%
% \begin{macro}{\@@_set_header_rows:}
-% TEMP: Next tagpdf will have the right command which also updates
-% the debug info.
-% For now a temporary command:
-% \begin{macrocode}
-\cs_if_free:NTF \__tag_struct_prop_gput:nnn
- {
- \cs_new_protected:Npn \@@_struct_prop_gput:nnn #1#2#3
- { \prop_gput:cnn { g__tag_struct_#1_prop }{#2}{#3} }
- }
- { \cs_new_protected:Npn \@@_struct_prop_gput:nnn #1#2#3
- { \__tag_struct_prop_gput:nnn {#1}{#2}{#3} }
- }
-\cs_generate_variant:Nn \@@_struct_prop_gput:nnn {nne,Vnn}
-% \end{macrocode}
-%
% \begin{macrocode}
\cs_new_protected:Npn \@@_set_header_rows:
{
@@ -964,7 +980,7 @@
% \begin{macrocode}
\prop_if_exist:cT { g__tag_struct_####1_prop }
{
- \@@_struct_prop_gput:nnn{ ####1 }{S}{/TH}
+ \__tag_struct_prop_gput:nnn{ ####1 }{S}{/TH}
% \end{macrocode}
% This need refinement once row headers (and perhaps other attributes)
% are used too, but for now it should be ok.
@@ -973,8 +989,8 @@
{ g__tag_struct_####1_prop }
{ C }
\l_@@_tmpa_tl
- {\@@_struct_prop_gput:nne{ ####1 }{C}{[/TH-col~\l_@@_tmpa_tl]} }
- {\@@_struct_prop_gput:nnn{ ####1 }{C}{/TH-col}}
+ {\__tag_struct_prop_gput:nne{ ####1 }{C}{[/TH-col~\l_@@_tmpa_tl]} }
+ {\__tag_struct_prop_gput:nnn{ ####1 }{C}{/TH-col}}
}
}
}
@@ -983,261 +999,68 @@
% \end{macro}
%
% And some key support:
+% (See tagpdfsetup-keys.md for the naming scheme.)
% \begin{macrocode}
-% TODO decide about key name
\keys_define:nn { __tag / setup }
{
- table-header-rows .clist_set:N = \l_@@_header_rows_clist
+ table/header-rows .clist_set:N = \l_@@_header_rows_clist,
+% \end{macrocode}
+% obsolete older name:
+% \begin{macrocode}
+ table-header-rows .meta:n = {table/header-rows={#1}}
}
% \end{macrocode}
%
-% \subsection{Changes to \pkg{array} commands}
%
%
+% \subsection{Misc stuff}
%
% \begin{macro}{\@@_show_curr_cell_data:}
% Show the row/column index and span count for current table cell
% for debugging.
% \begin{macrocode}
\cs_new_protected:Npn \@@_show_curr_cell_data: {
- \typeout { ==>~ current~cell~data:~
- \int_use:N \g_@@_row_int ,
- \int_use:N \g_@@_col_int ,
- \g_@@_span_tl
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-%
-%
-% \begin{macro}{\insert@column}
-% \cs{insert@column} is defined in \pkg{array}, here only the two
-% sockets are inserted.
-% \begin{macrocode}
-\def\insert@column{%
- \@@_show_curr_cell_data:
- \UseSocket{tagsupport/tblcell/begin}%
- \the@toks \the \@tempcnta
- \ignorespaces \@sharp \unskip
- \the@toks \the \count@ \relax
- \UseSocket{tagsupport/tblcell/end}%
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\@classz}
-% \begin{macrocode}
-\def\@classz{\@classx
- \@tempcnta \count@
- \prepnext@tok
- \@addtopreamble{\ifcase \@chnum
- \hfil
- \hskip1sp%
- \d@llarbegin
- \insert@column
- \d@llarend \do@row@strut \hfil \or
- \hskip1sp\d@llarbegin \insert@column \d@llarend \do@row@strut \hfil \or
- \hfil\hskip1sp\d@llarbegin \insert@column \d@llarend \do@row@strut \or
- \setbox\ar@mcellbox\vbox
- \@startpbox{\@nextchar}
- \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox}
- \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox}
- \insert@column \@endpbox
- \ar@align@mcell
- \do@row@strut \or
- \vtop \@startpbox{\@nextchar}
- \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox}
- \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox}
- \insert@column \@endpbox\do@row@strut \or
- \vbox \@startpbox{\@nextchar}
- \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox}
- \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox}
- \insert@column \@endpbox\do@row@strut
- \fi}\prepnext@tok}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@array,\@@@@array}
-% We modificate the \cs{@array} from \pkg{array}.
-% \begin{macrocode}
-\def\@array[#1]#2{%
- \@tempdima \ht \strutbox
- \advance \@tempdima by\extrarowheight
- \setbox \@arstrutbox \hbox{\vrule
- \@height \arraystretch \@tempdima
- \@depth \arraystretch \dp \strutbox
- \@width \z@}%
-% \end{macrocode}
-% The total number of table columns of the current table is
-% determined in \cs{@@_determine_table_cols:} but this is called in
-% a group, so local settings do not survive. Thus, to save away the
-% outer value of \cs{g_@@_table_cols_tl} we do it before the group.
-% \begin{macrocode}
- \tl_set_eq:NN \l_@@_saved_table_cols_tl \g_@@_table_cols_tl
-% \end{macrocode}
-%
-% \begin{macrocode}
- \begingroup
- \@mkpream{#2}
-% \end{macrocode}
-% Next call has to happen immediately after \cs{@mkpream} because
-% it uses implementation details from that.
-% \begin{macrocode}
- \@@_determine_table_cols:
-% \end{macrocode}
-%
-% \begin{macrocode}
- \xdef\@preamble{%
- \noexpand
-% \end{macrocode}
-% \cs{ialign} in the original definition is replaced by
-% \cs{ar@ialign} defined below.
-% \begin{macrocode}
- \ar@ialign
- \@halignto
- \bgroup \@arstrut
-% \end{macrocode}
-% A socket is inserted
-% \begin{macrocode}
- \UseSocket{tagsupport/tblrow/begin}%
-% \end{macrocode}
-% At the start of the preamble for the first column we set
-% \cs{g_@@_col_int} to \texttt{1} as we are no longer "at" but "in"
-% the first column. This is done in \cs{@@_init_cell_data:}. In
-% later columns this data is updated via \cs{@@_update_cell_data:}.
-% \begin{macrocode}
- \@@_init_cell_data:
- \@preamble
- \tabskip \z@ \cr}%
- \endgroup
- \@arrayleft
-% \end{macrocode}
-% Another socket for tagging. TODO: what about \cs{arrayleft}?
-% \begin{macrocode}
- \UseSocket{tagsupport/tbl/init}
- \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi \fi
- \bgroup
- \let \@sharp ##\let \protect \relax
- \lineskip \z@
- \baselineskip \z@
- \m@th
- \let\\\@arraycr \let\tabularnewline\\\let\par\@empty
-%\show\@preamble
- \@preamble}
-% \end{macrocode}
-% Finally, also set \cs{@@@@array} to the new definition:
-% \begin{macrocode}
-\let\@@@@array\@array
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\@@_init_cell_data:}
-%
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_init_cell_data: {
- \int_gset:Nn \g_@@_col_int {1}
- \tl_gset:Nn \g_@@_span_tl {1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_update_cell_data:}
-% Updating cell data in columns after the first means we have to
-% increment the \cs{g_@@_col_int} by the span count of the previous
-% cell (in case it was a \cs{multicolumn} and then reset the
-% \cs{g_@@_span_tl} to one (as the default).
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_update_cell_data: {
- \int_gadd:Nn \g_@@_col_int { \g_@@_span_tl }
- \tl_gset:Nn \g_@@_span_tl {1}
+ \@@_trace:n { ==>~ current~cell~data:~
+ \int_use:N \g_@@_row_int ,
+ \int_use:N \g_@@_col_int ,
+ \g_@@_span_tl
+ }
}
% \end{macrocode}
% \end{macro}
%
%
%
-% \begin{macro}{\@@_determine_table_cols:}
-% Current implementation of \cs{@mkpream} uses the scratch counter
-% \cs{count@} to keep track of the number of toks registers it needs
-% (2 per column), but this can't be used as it counts also
-% insertings made with \verb+!{}+ and \verb+@{}+.
-% So similar as does longtable for \cs{LT@cols} we count the
-% numbers of ambersands instead.
-% \begin{macrocode}
-\cs_new:Npn \@@_determine_table_cols: {
- \seq_set_split:NnV\l_@@_tmpa_seq {&}\@preamble
- \tl_gset:Ne \g_@@_table_cols_tl { \seq_count:N \l_@@_tmpa_seq }
- \typeout{ ==>~ Table~ has~ \g_@@_table_cols_tl \space columns }
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\@arraycr}
-% Add code that figures out if the current table row is incomplete
-% (not enough \verb=&=s). It can then do extra actions, such as
-% inserting missing cell tags.
+% \begin{macro}{\@@_add_missing_cells:}
+% The storing and use of the number of missing cells must happen at
+% different places as the testing happens at the end of the last
+% cell of a row, but still inside that cell, so we use two
+% commands. The one adding is used in the row/end socket.
% \begin{macrocode}
-\protected\def\@arraycr{
- \relax
- \@@_store_missing_cells:n{@arraycr}
- %
- \iffalse{\fi\ifnum 0=`}\fi
- \@ifstar \@xarraycr \@xarraycr}
-% \end{macrocode}
-% \end{macro}
-%
-%
-%
-% \begin{macro}{\@@_store_missing_cells:n,
-% \__tag_tbl_add_missing_cells:n}
-% The storing and use of the number of missing cells
-% must happen at different places as the testing happens at
-% the end of the last cell of a row, but
-% still inside that cell, so we use two commands. The second is used in
-% the endrow socket.
-% \begin{macrocode}
-\cs_new:Npn \@@_store_missing_cells:n #1 {
- \int_compare:nNnT \g_@@_col_int > 0
- {
- \int_gset:Nn \g_@@_missing_cells_int
- {
- \g_@@_table_cols_tl
- - \g_@@_col_int
- - \g_@@_span_tl
- + 1
- }
- \int_compare:nNnT \g_@@_missing_cells_int < 0 \ERROR % should not happen
- \typeout{==>~
- (#1)~
- This~ row~ needs~
- \int_use:N \g_@@_missing_cells_int \space
- additional~ cell(s)
- }
- }
-}
+\NewSocket{tbl/celldata/missingcount}{1}
+\NewSocketPlug{tbl/celldata/missingcount}{code}{\tbl_count_missing_cells:n{#1}}
+\AssignSocketPlug{tbl/celldata/missingcount}{code}
+
% \end{macrocode}
%
% \begin{macrocode}
-\cs_new:Npn \__tag_tbl_add_missing_cells:n #1
+\cs_new:Npn \@@_add_missing_cells:
{
% \end{macrocode}
-% The TD-socket messages are issued after the message about the end-row socket,
-% but the structure is ok, so better issue a message for now to avoid confusion:
+% The TD-socket messages are issued after the message about the
+% end-row socket, but the structure is ok, so better issue a
+% message for now to avoid confusion:
% \begin{macrocode}
- \int_compare:nNnT {#1}>{0}
+ \int_compare:nNnT \g_@@_missing_cells_int > 0
{
- \typeout{==>~
- ~Inserting~\int_eval:n{#1}~additional~cell(s)~into~previous~row:}
- }
- \int_step_inline:nn { #1 }
- {
- \UseSocket{tagsupport/tblcell/begin}
- \UseSocket{tagsupport/tblcell/end}
+ \@@_trace:n {==>~
+ ~Inserting~\int_use:N \g_@@_missing_cells_int \space
+ additional~cell(s)~into~previous~row:}
+ \int_step_inline:nn { \g_@@_missing_cells_int }
+ {
+ \UseTaggingSocket{tbl/cell/begin}
+ \UseTaggingSocket{tbl/cell/end}
+ }
}
}
% \end{macrocode}
@@ -1245,119 +1068,8 @@
%
%
%
-% \begin{macro}{\endarray}
-% If tables are nested into another then it is necessary to
-% restore information about the cell the inner table started
-% in. Otherwise, \cs{g_@@_row_int}, \cs{g_@@_col_int}, and
-% \cs{g_@@_span_tl} reflect the status in the outer table as they
-% are globally manipulated. We restore in all cases even if we are
-% not in a nesting situation as that makes the code simpler (and
-% probably faster).
-%
-% \cs{endtabular} and \cs{endtabular*} inherit from \cs{endarray}
-% so we only need to change that. \texttt{tabularx} is handled
-% below.
-% \begin{macrocode}
-\def\endarray{
- \@@_store_missing_cells:n{endarray}
- \crcr \egroup
- \UseSocket{tagsupport/tbl/finalize}
- \int_gset:Nn \g_@@_col_int { \l_@@_saved_col_tl }
- \int_gset:Nn \g_@@_row_int { \l_@@_saved_row_tl }
- \tl_gset_eq:NN \g_@@_span_tl \l_@@_saved_span_tl
- \tl_gset_eq:NN \g_@@_table_cols_tl \l_@@_saved_table_cols_tl
- \tl_gset_eq:NN \g_@@_struct_table_tl \l_@@_saved_struct_table_tl
- \seq_gset_eq:NN \g_@@_struct_rows_seq \l_@@_saved_struct_rows_seq
- \seq_gset_eq:NN \g_@@_struct_cells_seq\l_@@_saved_struct_cells_seq
- \seq_gset_eq:NN \g_@@_struct_cur_seq \l_@@_saved_struct_cur_seq
- \typeout{==>~ restored~cell~data:~
- \int_use:N \g_@@_row_int,
- \int_use:N \g_@@_col_int,
- \l_@@_saved_span_tl \space
- (
- \int_compare:nNnTF \g_@@_table_cols_tl = 0
- { outer~ level }
- { max:~ \g_@@_table_cols_tl }
- )
- }
- \egroup
- \@arrayright \gdef\@preamble{}%
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\@addamp}
-% If we are after the first column we have to insert a \verb=&= and
-% also update the cell data.
-% \begin{macrocode}
-\def\@addamp {
- \if@firstamp
- \@firstampfalse
- \else
- \edef\@preamble{\@preamble &
- \@@_update_cell_data:
- }
- \fi
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-%
-% \begin{macro}{
-% \g_@@_col_int,
-% \g_@@_row_int,
-% \g_@@_span_tl,
-% \g_@@_table_cols_tl}
-% \cs{g_@@_row_int} holds the current row number in the table. The value
-% \texttt{0} means we haven't yet processed the table preamble. It
-% is incremented by every \cs{cr} including the one ending the
-% table preamble.
%
-% \cs{g_@@_col_int} holds the current column number. The value
-% \texttt{0} means we have not yet started the table or just finished a table row
-% (with \verb=\\= typically); any other positive value means we
-% are currently typesetting a cell in that column in some row
-% (denoted by the \cs{g_@@_row_int}.
%
-% In a \cs{multicolumn} it holds the column number of the first
-% spanned column and \cs{g_@@_span_tl} the info how many cells are
-% spanned.
-%
-% \cs{g_@@_span_tl} is normally \texttt{1} except in a
-% \cs{multicolumn} cell.
-% \begin{macrocode}
-\int_new:N \g_@@_col_int
-\int_new:N \g_@@_row_int
-\tl_new:N \g_@@_span_tl
-\tl_new:N \g_@@_table_cols_tl
-
-\tl_gset:Nn \g_@@_span_tl {1}
-\tl_gset:Nn \g_@@_table_cols_tl {0} % indicates outer level
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\l_@@_saved_col_tl,\l_@@_saved_row_tl,
-% \l_@@_saved_span_tl,\l_@@_saved_table_cols_tl}
-%
-% Saving the outer values if we are nesting tables is necessary (as
-% the above variables are globally altered. For this we use always
-% token lists because they don't change and we do not need to blow
-% additional integer registers.
-% \begin{macrocode}
-\tl_new:N \l_@@_saved_col_tl
-\tl_new:N \l_@@_saved_row_tl
-\tl_new:N \l_@@_saved_span_tl
-\tl_new:N \l_@@_saved_table_cols_tl
-
-\tl_set:Nn \l_@@_saved_col_tl{0}
-\tl_set:Nn \l_@@_saved_row_tl{0}
-\tl_set:Nn \l_@@_saved_span_tl{1}
-\tl_set:Nn \l_@@_saved_table_cols_tl{0} % indicates outer level
-% \end{macrocode}
-% \end{macro}
%
% \begin{macro}
% {
@@ -1390,474 +1102,53 @@
\seq_new:N \l_@@_saved_struct_cur_seq
% \end{macrocode}
% \end{macro}
+
+
+
+% \begin{macro}{\@@_init_struct_data:}
+% Save the global structure data variables locally so the we can
+% restore them when the table ends (important in case of nested
+% tables).
%
-% \begin{macro}{\ar@ialign}
-% A new command that replaces \cs{ialign} above. \cs{everycr} is
-% also applied to the \cs{cr} ending the preamble so we have to
-% program around that.
+% This is also the right point to initialize
+% them. \cs{g_@@_struct_table_tl} is set elsewhere.
% \begin{macrocode}
-\def\ar@ialign{%
-% \end{macrocode}
-% Before starting a table we locally stored the information related
-% to the current cell (if any) so that we can restore it once the
-% table is finished.
-% \begin{macrocode}
- \tl_set:No \l_@@_saved_col_tl {\int_use:N \g_@@_col_int }
- \tl_set:No \l_@@_saved_row_tl {\int_use:N \g_@@_row_int }
- \tl_set_eq:NN \l_@@_saved_span_tl \g_@@_span_tl
+\cs_new_protected:Npn \@@_init_struct_data: {
\tl_set_eq:NN \l_@@_saved_struct_table_tl \g_@@_struct_table_tl
\seq_set_eq:NN \l_@@_saved_struct_rows_seq \g_@@_struct_rows_seq
\seq_set_eq:NN \l_@@_saved_struct_cells_seq \g_@@_struct_cells_seq
\seq_set_eq:NN \l_@@_saved_struct_cur_seq \g_@@_struct_cur_seq
%
- \typeout{==>~ saved~cell~data:~
- \l_@@_saved_row_tl,
- \l_@@_saved_col_tl,
- \l_@@_saved_span_tl \space
- (
- \int_compare:nNnTF \l_@@_saved_table_cols_tl = 0
- { outer~ level }
- { max:~ \l_@@_saved_table_cols_tl }
- )
- }
-% \end{macrocode}
-% These are the initial values when starting a table:
-% \begin{macrocode}
- \int_gzero:N \g_@@_row_int
- \int_gzero:N \g_@@_col_int
- \tl_gset:Nn \g_@@_span_tl {1}
\seq_gclear:N\g_@@_struct_rows_seq
\seq_gclear:N\g_@@_struct_cells_seq
\seq_gclear:N\g_@@_struct_cur_seq
+}
% \end{macrocode}
-%
-% \begin{macrocode}
- \everycr{%
- \noalign{%
-% \end{macrocode}
-% We use \cs{g_@@_col_int} equal zero to indicate that we are just
-% after a TR (or at the very beginning of the table). Using the row
-% count is not so good as longtable may split the table in chunks.
-% \begin{macrocode}
- \int_compare:nNnT \g_@@_col_int > 0
- { \UseSocket{tagsupport/tblrow/end} }
- \int_gincr:N \g_@@_row_int % this row about to start
- \int_gzero:N \g_@@_col_int % we are before first col
- }%
- }%
- \tabskip\z@skip\halign}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\multicolumn}
-%
-% \cs{multicolumn} is also defined in \pkg{array}. The redefinition
-% has to solve two problems: it must handle the row begin if it is
-% used there, and it must save the numbers of cells it spans so
-% that we can add a suitable ColSpan attribute.\footnote{FMi: This can
-% now perhaps cleaned up somewhat}
-% \begin{macrocode}
-\long\def\multicolumn#1#2#3{%
- % alternative: determine first col with vmode test ...
- % \ifvmode
- % \multispan{#1}\typeout{A==> vmode}%
- % \else
- % \multispan{#1}\typeout{A==> not vmode}
- % \fi
- % but this makes the \crcr handling really complicated which would
- % then need to become something like
- % \ifvmode \expandafter \@gobble
- % \else \expandafter \@iden \fi {\cr\noalign{do something}}%
- % so not used.
- % Instead:
- \multispan{#1}\begingroup
-% \end{macrocode}
-% Insert rowbegin socket only if this multicolumn
-% replaces the preamble of the first column. In that case we have
-% to set \cs{g_@@_col_int} to 1 since this is no longer done in the
-% preamble for the cell.
-% \begin{macrocode}
- \int_compare:nNnTF \g_@@_col_int = 0
- {
- \UseSocket{tagsupport/tblrow/begin}
- \int_gset:Nn \g_@@_col_int {1}
- }
-% \end{macrocode}
-% If we are in a later column we use \cs{g_@@_span_tl} from the
-% previous column to update.
-% \begin{macrocode}
- {
- \int_gadd:Nn \g_@@_col_int { \g_@@_span_tl }
- }
-% \end{macrocode}
-% Then we set the span value so that it can be use in the next column.
+% \end{macro}
+
+
+
+
+% \begin{macro}{\@@_restore_struct_data:}
+%
% \begin{macrocode}
- \tl_gset:Nn \g_@@_span_tl {#1}
+\cs_new_protected:Npn \@@_restore_struct_data: {
+ \tl_gset_eq:NN \g_@@_struct_table_tl \l_@@_saved_struct_table_tl
+ \seq_gset_eq:NN \g_@@_struct_rows_seq \l_@@_saved_struct_rows_seq
+ \seq_gset_eq:NN \g_@@_struct_cells_seq\l_@@_saved_struct_cells_seq
+ \seq_gset_eq:NN \g_@@_struct_cur_seq \l_@@_saved_struct_cur_seq
+}
% \end{macrocode}
+% \end{macro}
+
+
%
-% \begin{macrocode}
- \def\@addamp{\if@firstamp\@firstampfalse \else
- \@preamerr 5\fi}%
- \@mkpream{#2}\@addtopreamble\@empty
- \endgroup
-% \end{macrocode}
-% Now we update the colspan attribute. This needs setting after
-% the group as it is hidden inside the plug in \cs{insert@column}.
-% \begin{macrocode}
- \@@_set_colspan:n {#1}
-% \end{macrocode}
-% \begin{macrocode}
- \def\@sharp{#3}%
- \@arstrut \@preamble
- \null
- \ignorespaces}
-% \end{macrocode}
-% \end{macro}
%
% \subsection{longtable}
%
-% Longtable is complicated. When at the begin the \cs{endhead},
-% \cs{endfirsthead}, \cs{endfoot} and \cs{endlastfoot} are used to
-% setup head and foot they create each a structure subtree with one or
-% more rows. From this structures we want to keep at most two (head
-% and foot) and move the foot to the end of the table. When the head
-% and foot boxes are (re)inserted on following pages we want to mark
-% them up as artifact with the exception of the head at the begin and
-% the foot box at the end.
-%
-% TODO: When a line is killed the structure subtree is there already
-% too and must be removed.
-%
-% Hyperref patches longtable. This must be disabled and replace with
-% genuine code
-% \begin{macrocode}
-\let\@kernel@refstepcounter\refstepcounter
-\def\hyper@nopatch@longtable{}
-% \end{macrocode}
-% \begin{macrocode}
-\def\@@_patch_LT@array[#1]#2{%
-% \end{macrocode}
-% \cs{LT@array} is executed in a group, so we can disable para-tagging here.
-% \begin{macrocode}
- \UseSocket{tagsupport/tbl/init}%
- \@kernel@refstepcounter{table}\stepcounter{LT@tables}%
-% \end{macrocode}
-% The target is created rather late and a \cs{label} can come earlier,
-% so we have to define \cs{@currentHref} explicitly. We can't currently
-% assume that \cs{theHtable} is defined always.
-% \begin{macrocode}
- \tl_gset:Ne \@currentHref {table.\cs_if_exist_use:N\theHtable}
- \int_gzero:N \g_@@_row_int
- \seq_gclear:N\g_@@_struct_rows_seq
- \seq_gclear:N\g_@@_struct_cells_seq
- \seq_gclear:N\g_@@_struct_cur_seq
- \seq_gclear:N\g_@@_LT@firsthead_rows_seq
- \seq_gclear:N\g_@@_LT@head_rows_seq
- \seq_gclear:N\g_@@_LT@lastfoot_rows_seq
- \seq_gclear:N\g_@@_LT@foot_rows_seq
- \if l#1%
- \LTleft\z@ \LTright\fill
- \else\if r#1%
- \LTleft\fill \LTright\z@
- \else\if c#1%
- \LTleft\fill \LTright\fill
- \fi\fi\fi
- \let\LT@mcol\multicolumn
- \let\LT@@@@tabarray\@tabarray
- \let\LT@@@@hl\hline
- \def\@tabarray{%
- \let\hline\LT@@@@hl
- \LT@@@@tabarray}%
- \let\\\LT@tabularcr
- \let\tabularnewline\\%
- \def\newpage{\noalign{\break}}%
- \def\pagebreak{\noalign{\ifnum`}=0\fi\@testopt{\LT@no@pgbk-}4}%
- \def\nopagebreak{\noalign{\ifnum`}=0\fi\@testopt\LT@no@pgbk4}%
- \let\hline\LT@hline \let\kill\LT@kill\let\caption\LT@caption
- \@tempdima\ht\strutbox
- \let\@endpbox\LT@endpbox
- \ifx\extrarowheight\@undefined
- \let\@acol\@tabacol
- \let\@classz\@tabclassz \let\@classiv\@tabclassiv
- \def\@startpbox{\vtop\LT@startpbox}%
- \let\@@@@startpbox\@startpbox
- \let\@@@@endpbox\@endpbox
- \let\LT@LL@FM@cr\@tabularcr
- \else
- \advance\@tempdima\extrarowheight
- \col@sep\tabcolsep
- \let\@startpbox\LT@startpbox\let\LT@LL@FM@cr\@arraycr
- \fi
- \setbox\@arstrutbox\hbox{\vrule
- \@height \arraystretch \@tempdima
- \@depth \arraystretch \dp \strutbox
- \@width \z@}%
- \let\@sharp##\let\protect\relax
- \begingroup
- \@mkpream{#2}%
- \@@_determine_table_cols:
- \xdef\LT@bchunk{%
-% \end{macrocode}
-% At the start of a chunk we set \cs{g_@@_col_int} to zero to make
-% sure that we aren't generating /TR with the \cs{cr} ending the
-% chunk preamble.
-% \begin{macrocode}
- \int_gzero:N \g_@@_col_int
- \global\advance\c@LT@chunks\@ne
- \global\LT@rows\z@\setbox\z@\vbox\bgroup
- \LT@setprevdepth
- \tabskip\LTleft \noexpand\halign to\hsize\bgroup
- \tabskip\z@ \@arstrut
-% \end{macrocode}
-% Insert the socket and the setting of the conditional
-% \begin{macrocode}
- \UseSocket{tagsupport/tblrow/begin}%
- \@@_init_cell_data:
-% \end{macrocode}
-% \begin{macrocode}
- \@preamble \tabskip\LTright \cr}%
- \endgroup
- \expandafter\LT@nofcols\LT@bchunk&\LT@nofcols
- \LT@make@row
- \m@th\let\par\@empty
-% \end{macrocode}
-% Socket and conditional
-% \begin{macrocode}
- \everycr{%
- \noalign{%
-% \end{macrocode}
-% In \pkg{longtable} we have a bunch of extra \cs{cr}s that are
-% executed whenever a chunk ends. In that case they should not
-% increment the main row counter, sigh.
-% \begin{macrocode}
- \typeout{--longtable-->~chunk~row:~ \the\LT@rows \space
- row:~ \the\g_@@_row_int \space
- column:~ \the\g_@@_col_int
- }
- \int_compare:nNnT \g_@@_col_int > 0
- {
- \UseSocket{tagsupport/tblrow/end}
- }
-% \end{macrocode}
-% This prevents any of the additional \cs{cr}s at the end of the
-% chunk to add another /TR. Then once we really start a new chunk
-% it gets incremented so\ldots
-% \begin{macrocode}
- \int_gzero:N \g_@@_col_int % before first col
-% \end{macrocode}
-% And for the same reason such \cs{cr}s should not increment the
-% main row counter (but it has to be incremented after the preamble
-% of a chunk), so here we test against \cs{LT@rows} which is
-% \cs{LTchunksize} at the end of a chunk.
-% \begin{macrocode}
- \int_compare:nNnT \LT@rows < \LTchunksize
- { \int_gincr:N \g_@@_row_int } % this row about to start
- }%
- }%
-% \end{macrocode}
-% \begin{macrocode}
- \lineskip\z@\baselineskip\z@
- \LT@bchunk}
-% \end{macrocode}
-% The end code most stop to insert the endrow too.
-% \begin{macrocode}
-\def\@@_patch_endlongtable{%
- \@@_store_missing_cells:n{endlongtable}
- \crcr
- \noalign{%
- \UseSocket{tagsupport/tbl/finalize/longtable}
- \int_gzero:N \g_@@_row_int % this prevents considering the next
- % \crcr as another row end.
- \let\LT@entry\LT@entry@chop
- \xdef\LT@save@row{\LT@save@row}}%
- \LT@echunk
- \LT@start
- \unvbox\z@
- \LT@get@widths
- \if@filesw
- {\let\LT@entry\LT@entry@write\immediate\write\@auxout{%
- \gdef\expandafter\noexpand
- \csname LT@\romannumeral\c@LT@tables\endcsname
- {\LT@save@row}}}%
- \fi
- \ifx\LT@save@row\LT@@@@save@row
- \else
- \LT@warn{Column~\@width s~have~changed\MessageBreak
- in~table~\thetable}%
- \LT@final@warn
- \fi
- \endgraf\penalty -\LT@end@pen
- \ifvoid\LT@foot\else
- \global\advance\vsize\ht\LT@foot
- \global\advance\@colroom\ht\LT@foot
- \dimen@\pagegoal\advance\dimen@\ht\LT@foot\pagegoal\dimen@
- \fi
- \endgroup
- \global\@mparbottom\z@
- \endgraf\penalty\z@\addvspace\LTpost
- \ifvoid\footins\else\insert\footins{}\fi}
-% \end{macrocode}
-%
-%
-%
-% \begin{macro}{\@@_patch_LT@t@bularcr}
-%
-% \begin{macrocode}
-\def\@@_patch_LT@t@bularcr{%
- \global\advance\LT@rows\@ne
- \ifnum\LT@rows=\LTchunksize
-% \end{macrocode}
-% At the end of the chunk \verb=\\= is doing something special and
-% so we loose \cs{@@_store_missing_cells:n}. Below is about the
-% right place to add it do this code branch.
-% \begin{macrocode}
- \@@_store_missing_cells:n{echunk}
- \gdef\LT@setprevdepth{%
- \prevdepth\z@
- \global\let\LT@setprevdepth\relax}%
- \expandafter\LT@xtabularcr
- \else
- \ifnum0=`{}\fi
- \expandafter\LT@LL@FM@cr
- \fi}
-
-% \end{macrocode}
-% \end{macro}
%
%
%
-% \begin{macro}{\@@_patch_LT@end@hd@ft}
-% This command is used to store the head and foot boxes.
-% We need to retrieve and store the row so that we can clean
-% up the structure in the finalize code.
-% \begin{macrocode}
-\def\@@_patch_LT@end@hd@ft#1{%
-% \end{macrocode}
-% To handle missing columns in the header we need this:
-% \begin{macrocode}
- \__tbl_store_missing_cells:n{head/foot}
- \int_step_inline:nn
- { \LT@rows + 1 }
- {
- \seq_gput_left:ce
- {g_@@_\cs_to_str:N #1 _rows_seq }
- { \int_eval:n {\g_@@_row_int + 1 - ##1 } }
- }
-% \end{macrocode}
-% We also have to set the chunk rows to its max value before
-% calling \cs{LTechunk} so that we don't get extra increments of
-% the main row counter due to \cs{everycr}.
-% \begin{macrocode}
- \int_gset:Nn \LT@rows { \LTchunksize }
- \LT@echunk
- \ifx\LT@start\endgraf
- \LT@err
- {Longtable head or foot not at start of table}%
- {Increase LTchunksize}%
- \fi
- \setbox#1\box\z@
- \LT@get@widths
- \LT@bchunk}
-% \end{macrocode}
-% \end{macro}
-
-% \begin{macro}{\@@_patch_LT@start}
-% \begin{macrocode}
-\def\@@_patch_LT@start{%
- \let\LT@start\endgraf
- \endgraf\penalty\z@\vskip\LTpre\endgraf
- \ifdim \pagetotal<\pagegoal \else
- \dimen@=\pageshrink
- \advance \dimen@ 1sp %
- \kern\dimen@\penalty 9999\endgraf \kern-\dimen@
- \fi
- \dimen@\pagetotal
- \advance\dimen@ \ht\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi
- \advance\dimen@ \dp\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi
- \advance\dimen@ \ht\LT@foot
- \edef\LT@reset@vfuzz{\vfuzz\the\vfuzz\vbadness\the\vbadness\relax}%
- \vfuzz\maxdimen
- \vbadness\@M
- \setbox\tw@\copy\z@
- \setbox\tw@\vsplit\tw@ to \ht\@arstrutbox
- \setbox\tw@\vbox{\unvbox\tw@}%
- \LT@reset@vfuzz
- \advance\dimen@ \ht
- \ifdim\ht\@arstrutbox>\ht\tw@\@arstrutbox\else\tw@\fi
- \advance\dimen@\dp
- \ifdim\dp\@arstrutbox>\dp\tw@\@arstrutbox\else\tw@\fi
- \advance\dimen@ -\pagegoal
- \ifdim \dimen@>\z@
- \vfil\break
- \else
- \ifdim\pageshrink>\z@\pageshrink\z@\fi
- \fi
- \global\@colroom\@colht
- \ifvoid\LT@foot\else
- \global\advance\vsize-\ht\LT@foot
- \global\advance\@colroom-\ht\LT@foot
- \dimen@\pagegoal\advance\dimen@-\ht\LT@foot\pagegoal\dimen@
- \maxdepth\z@
- \fi
- \MakeLinkTarget{table}
- \ifvoid\LT@firsthead\copy\LT@head\else\box\LT@firsthead\fi\nobreak
-% \end{macrocode}
-% Avoid that following uses of the box add content:
-% \begin{macrocode}
- \tagmcbegin{artifact}
- \tag_mc_reset_box:N\LT@head
- \tagmcend
- \output{\LT@output}}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\@@_patch_LT@output}
-% We must also avoid that the reuse of the foot box leads to
-% duplicated content:
-% \begin{macrocode}
-\def\@@_patch_LT@output{%
- \ifnum\outputpenalty <-\@Mi
- \ifnum\outputpenalty > -\LT@end@pen
- \LT@err{floats and marginpars not allowed in a longtable}\@ehc
- \else
- \setbox\z@\vbox{\unvbox\@cclv}%
- \ifdim \ht\LT@lastfoot>\ht\LT@foot
- \dimen@\pagegoal
- \advance\dimen@\ht\LT@foot
- \advance\dimen@-\ht\LT@lastfoot
- \ifdim\dimen@<\ht\z@
- \setbox\@cclv\vbox{\unvbox\z@\copy\LT@foot\vss}%
- \@makecol
- \@outputpage
- \global\vsize\@colroom
- \setbox\z@\vbox{\box\LT@head}%
- \fi
- \fi
- \unvbox\z@\box\ifvoid\LT@lastfoot\LT@foot\else\LT@lastfoot\fi
-% \end{macrocode}
-% Reset attribute of foot box:
-% \begin{macrocode}
- \tagmcbegin{artifact}
- \tag_mc_reset_box:N \LT@foot
- \tagmcend
- \fi
- \else
- \setbox\@cclv\vbox{\unvbox\@cclv\copy\LT@foot\vss}%
-% \end{macrocode}
-% Reset attribute of foot box:
-% \begin{macrocode}
- \tagmcbegin{artifact}
- \tag_mc_reset_box:N \LT@foot
- \tagmcend
- \@makecol
- \@outputpage
- \global\vsize\@colroom
- \copy\LT@head\nobreak
- \fi}
-% \end{macrocode}
-% \end{macro}
%
% \begin{macro}{\@@_patch_\LT@makecaption}
% This patch is quite similar to the one for LaTeX's \cs{@makecaption}
@@ -1893,74 +1184,11 @@
% \begin{macrocode}
\AddToHook{package/longtable/after}
{
- \seq_new:N \g_@@_LT@firsthead_rows_seq
- \seq_new:N \g_@@_LT@head_rows_seq
- \seq_new:N \g_@@_LT@lastfoot_rows_seq
- \seq_new:N \g_@@_LT@foot_rows_seq
- \cs_set_eq:NN \LT@array\@@_patch_LT@array
- \cs_set_eq:NN \endlongtable\@@_patch_endlongtable
- \cs_set_eq:NN \LT@start\@@_patch_LT@start
- \cs_set_eq:NN \LT@output\@@_patch_LT@output
- \cs_set_eq:NN \LT@t@bularcr\@@_patch_LT@t@bularcr
- \cs_set_eq:NN \LT@end@hd@ft\@@_patch_LT@end@hd@ft
\cs_set_eq:NN \LT@makecaption\@@_patch_LT@makecaption
}
% \end{macrocode}
-
-
-
-% \subsection{tabularx}
-%
-% In tabularx we mainly need to ensure that no tagging is done during
-% the trial.
-%
-% \begin{macrocode}
-\def\@@_patch_TX@endtabularx{%
- \expandafter\expandafter\expandafter
- \TX@find@endtabularxa\csname end\TX@\endcsname
- \endtabularx\TX@\endtabularx\TX@find@endtabularxa
- \expandafter\TX@newcol\expandafter{\tabularxcolumn{\TX@col@width}}%
- \let\verb\TX@verb
- \def\@elt##1{\global\value{##1}\the\value{##1}\relax}%
- \edef\TX@ckpt{\cl@@@@ckpt}%
- \let\@elt\relax
- \TX@old@table\maxdimen
- \TX@col@width\TX@target
- \global\TX@cols\@ne
- \TX@typeout@
- {\@spaces Table Width\@spaces Column Width\@spaces X Columns}%
-% \end{macrocode}
-% Here we stop tagging:
-% \begin{macrocode}
- \tag_stop:n{tabularx}
- \TX@trial{\def\NC@rewrite@X{%
- \global\advance\TX@cols\@ne\NC@find p{\TX@col@width}}}%
- \loop
- \TX@arith
- \ifTX@
- \TX@trial{}%
- \repeat
-% \end{macrocode}
-% And now we restart it again.
-% \begin{macrocode}
- \tag_start:n{tabularx}
- {\let\@footnotetext\TX@ftntext\let\@xfootnotenext\TX@xftntext
- \csname tabular*\expandafter\endcsname\expandafter\TX@target
- \the\toks@
- \csname endtabular*\endcsname}%
- \global\TX@ftn\expandafter{\expandafter}\the\TX@ftn
- \ifnum0=`{\fi}%
- \expandafter\expandafter\expandafter
- \TX@find@endtabularxbb
- \expandafter\end\expandafter{\TX@}%
- \endtabularx\TX@\endtabularx\TX@find@endtabularxb
-}
-
-\AddToHook{package/tabularx/after}
- {\cs_set_eq:NN \TX@endtabularx\@@_patch_TX@endtabularx }
-% \end{macrocode}
% \begin{macrocode}
%</package>
% \end{macrocode}
@@ -1973,3 +1201,11 @@
\RequirePackage{latex-lab-testphase-table}
%</latex-lab>
% \end{macrocode}
+
+% \begin{macrocode}
+%<*latex-lab-alias>
+\ProvidesFile{tabular-latex-lab-testphase.ltx}
+ [\ltlabtbldate\space v\ltlabtblversion\space latex-lab wrapper tabular]
+\RequirePackage{latex-lab-testphase-table}
+%</latex-lab-alias>
+% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-testphase.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-testphase.dtx
index b2ed5ecf8a4..f0a6fe65d0c 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-testphase.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-testphase.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
%% File: latex-lab-testphase.dtx
-% Copyright (C) 2021-2023 The LaTeX Project
+% Copyright (C) 2021-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -79,7 +79,7 @@
% \begin{macrocode}
%<*phase-III>
\ProvidesFile{phase-III-latex-lab-testphase.ltx}
- [2023-07-20 v0.1b latex-lab wrapper phase-III]
+ [2024-02-12 v0.1c latex-lab wrapper phase-III]
\input{phase-II-latex-lab-testphase.ltx}
\IfFormatAtLeastTF{2023-06-01}
{
@@ -91,6 +91,7 @@
\RequirePackage{latex-lab-testphase-float}
\RequirePackage{latex-lab-testphase-bib}
\RequirePackage{latex-lab-testphase-text}
+ \RequirePackage{latex-lab-testphase-marginpar}
}
{\PackageWarning{latex-lab}{Testphase III needs newer format}{}}
%</phase-III>
@@ -122,9 +123,9 @@
\RequirePackage{tagpdf}
\AddToDocumentProperties [document]{testphase/tagpdf}{loaded}
%</tagpdf|phase-I|phase-II>
-%<tagpdf|phase-II>\tagpdfsetup{activate,paratagging,interwordspace}
+%<tagpdf|phase-II>\tagpdfsetup{activate,para/tagging,activate/spaces}
%<tagpdf|phase-II>\AddToDocumentProperties [document]{tagging/para}{active}
-%<phase-I>\tagpdfsetup{activate,interwordspace}
+%<phase-I>\tagpdfsetup{activate,activate/spaces}
%<*tagpdf|phase-I|phase-II>
\AddToDocumentProperties [document]{tagging}{active}
\AddToDocumentProperties [document]{tagging/interwordspace}{active}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-text.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-text.dtx
index 4041336ecbf..fe9b6ababc7 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-text.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-text.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-text.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-text.dtx (C) Copyright 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-title.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-title.dtx
new file mode 100644
index 00000000000..757bb284a45
--- /dev/null
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-title.dtx
@@ -0,0 +1,518 @@
+% \iffalse meta-comment
+%
+%% File: latex-lab-title.dtx (C) Copyright 2023-2024 LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% https://www.latex-project.org/lppl.txt
+%
+%
+% The development version of the bundle can be found below
+%
+% https://github.com/latex3/latex2e/required/latex-lab
+%
+% for those people who are interested or want to report an issue.
+%
+\def\ltlabtitledate{2024-02-09}
+\def\ltlabtitleversion{0.85c}
+
+%<*driver>
+\documentclass{l3doc}
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{latex-lab-title.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+% \title{The \textsf{latex-lab-title} package\\
+% Changes related to the tagging of the title}
+% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}}
+% \date{v\ltlabtitleversion\ \ltlabtitledate}
+%
+% \maketitle
+%
+% \newcommand{\xt}[1]{\textsl{\textsf{#1}}}
+% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}}
+% \newcommand{\docclass}{document class \marginpar{\raggedright document class
+% customizations}}
+%
+% \providecommand\hook[1]{\texttt{#1}}
+%
+% \begin{abstract}
+% \end{abstract}
+%
+% \section{Introduction}
+%
+% This module contains changes to improve the tagging (in the standard classes) of
+% the title created with the \cs{maketitle} command. It also improves the
+% setting of the metadata related to the title and the author.
+%
+% For basic tagging of the printed title there are basically three things to do:
+%
+% \begin{itemize}
+% \item The actual title should be tagged with the \texttt{Title} tag.
+% \item The tabular used to format the author list should \emph{not} be tagged as a tabular.
+% \item \cs{maketitle} redefines footnote internals. These must be made tagging aware.
+% \end{itemize}
+%
+% A second task related to title is to store the authors and the title text
+% (or a shorter version) inside the XMP-metadata and (in PDF 1.7 or lower) in
+% the Info dictionary. Currently this can only be set if hyperref
+% is loaded and requires the use of the \texttt{pdftitle} and \texttt{pdfauthor} keys.
+% The new code therefore extends the \cs{title} and \cs{author} commands: They
+% stores their argument and use them at the end of the document
+% for the PDF metadata if the data hasn't been given in another way.
+% The code also gives \cs{title} and \cs{author}
+% an optional argument where the PDF title or author can be given with
+% in a key-value syntax. As with hyperref it is possible to store titles
+% in more than one language:
+%
+% \begin{verbatim}
+% \title
+% [pdftitle =
+% {[en]English Title,[de] Deutscher Titel,[fr]{titre français, avec comma}}]
+% {Document title}
+% \end{verbatim}
+%
+% It is also possible to set a subtitle which is then stored in the XMP-metadata:
+%
+% \begin{verbatim}
+% \title
+% [pdfsubtitle =
+% {[en]English Subtitle,[de] Deutscher Subtitel,[fr]{subtitre français, avec comma}}]
+% {Document title}
+% \end{verbatim}
+
+%
+% If using the \texttt{pdfauthor} key authors should be separated
+% by commas, and to hide commas in a name inside braces if needed:
+%
+% \begin{verbatim}
+% \author[pdfauthor = {Bär, Peter Anteater, {Riley, the sloth}}]{\ldots}
+% \end{verbatim}
+%
+% If hyperref is loaded there is no difference to the \texttt{pdftitle} and
+% \texttt{pdfauthor} key used in \cs{hypersetup}. Both can be used (and the last
+% key used will win).
+%
+% \subsection{Open questions and TODOs}
+%
+% \begin{itemize}
+% \item Writing into the Info dictionary needs to convert the input into a PDF string.
+% This is here done with a simple version of hyperref's \cs{pdfstringdef}, similar code
+% exist also in in the generic hyperref driver. This should be moved into a better place
+% module.
+%
+% \item Is it sensible to enhance \cs{author} and \cs{title} with an optional argument as done here?
+% An advantage is that it is rather light-weight and
+% doesn't require to decide how this values should be set in \cs{DocumentMetadata} (and would also work
+% without \cs{DocumentMetadata}. But a problem could be that various classes and packages already
+% extend this commands with other optional arguments.
+%
+% \item Some of the definitions related to metadata should perhaps be moved into l3pdfmeta.
+%
+% \item Are the names \texttt{pdftitle} and \texttt{pdfauthor} ok?
+%
+% \item The patch for \cs{thanks} to get a rlap-footnotemarker looks wrong. This
+% probably means that some configuration option is missing in the footnote code.
+% \end{itemize}
+%
+%
+%
+% \section{Implementation}
+% \begin{macrocode}
+%<*package>
+%<@@=tag>
+% \end{macrocode}
+% \begin{macrocode}
+\ProvidesExplPackage {latex-lab-testphase-title} {\ltlabtitledate} {\ltlabtitleversion}
+ {Changes related to the tagging of the title}
+% \end{macrocode}
+%
+% \subsection{\cs{maketitle} in article class}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_thanks:n #1
+ {
+ \rlap{\footnotemark}
+ \protected@xdef\@thanks{\@thanks
+ \protect\footnotetext[\the\c@footnote]{#1}}
+ }
+% \end{macrocode}
+% The no-titlepage version of article, report and book
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_maketitle:
+ {
+ \par
+ \begingroup
+% \end{macrocode}
+% Disable table tagging
+% \begin{macrocode}
+ \cs_if_exist_use:N\__tag_tbl_disable:
+ \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
+% \end{macrocode}
+% the original definition redefines \cs{@makefnmark} and
+% \cs{@makefntext} to get an rlap-mark in the text without
+% affecting the mark in the note (which gives by the way
+% a wrong link area with hyperref). There seem to be currently
+% no good way in the footnote to configure this, so we redefine
+% \cs{thanks} instead
+% \begin{macrocode}
+ \cs_set_eq:NN \thanks \@@_patch_thanks:n
+ \if@twocolumn
+ \ifnum \col@number=\@ne
+ \@maketitle
+ \else
+ \twocolumn[\@maketitle]%
+ \fi
+ \else
+ \newpage
+ \global\@topnum\z@ % Prevents figures from going at top of page.
+ \@maketitle
+ \fi
+ \thispagestyle{plain}\@thanks
+ \endgroup
+ \setcounter{footnote}{0}%
+ \global\let\thanks\relax
+ \global\let\maketitle\relax
+ \global\let\@maketitle\relax
+ \global\let\@thanks\@empty
+ \global\let\@author\@empty
+ \global\let\@date\@empty
+ \global\let\@title\@empty
+ \global\let\title\relax
+ \global\let\author\relax
+ \global\let\date\relax
+ \global\let\and\relax
+ }
+% \end{macrocode}
+% We must also change \cs{@maketitle} to insert a Title tag
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_@maketitle:
+ {
+ \newpage
+ \null
+ \vskip 2em%
+ \begin{center}%
+ \let \footnote \thanks
+% \end{macrocode}
+% use Title around the title. As in PDF 1.7 this is
+% rolemapped to P we change the text-unit tag there.
+% \begin{macrocode}
+ \pdf_version_compare:NnTF > {1.7}
+ {{\LARGE \tag_struct_begin:n{tag=Title}\@title \par\tag_struct_end:}}
+ {{\LARGE \tagtool{paratag=Title}\@title \par}}%
+ \vskip 1.5em%
+ {\large
+ \lineskip .5em%
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par}%
+ \vskip 1em%
+ {\large \@date}%
+ \end{center}%
+ \par
+ \vskip 1.5em
+ }
+
+% \end{macrocode}
+% The titlepage variant
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_maketitle_page:
+ {\begin{titlepage}%
+% \end{macrocode}
+% disable table tagging
+% \begin{macrocode}
+ \cs_if_exist_use:N\__tag_tbl_disable:
+ \let\footnotesize\small
+ \let\footnoterule\relax
+ \let \footnote \thanks
+ \null\vfil
+ \vskip 60\p@
+% \end{macrocode}
+% use Title around the title. As in PDF 1.7 this is
+% rolemapped to P we change the text-unit tag there.
+% \begin{macrocode}
+ \begin{center}%
+ \pdf_version_compare:NnTF > {1.7}
+ {{\LARGE \tag_struct_begin:n{tag=Title}\@title \par\tag_struct_end:}}
+ {{\LARGE \tagtool{paratag=Title}\@title \par}}%
+ \vskip 3em%
+ {\large
+ \lineskip .75em%
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par}%
+ \vskip 1.5em%
+ {\large \@date \par}% % Set date in \large size.
+ \end{center}\par
+ \@thanks
+ \vfil\null
+ \end{titlepage}%
+ \setcounter{footnote}{0}%
+ \global\let\thanks\relax
+ \global\let\maketitle\relax
+ \global\let\@thanks\@empty
+ \global\let\@author\@empty
+ \global\let\@date\@empty
+ \global\let\@title\@empty
+ \global\let\title\relax
+ \global\let\author\relax
+ \global\let\date\relax
+ \global\let\and\relax
+ }
+
+% \end{macrocode}
+% Map the new commands onto \cs{maketitle}:
+% \begin{macrocode}
+\AddToHook{class/article/after}
+ {
+ \if@titlepage
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle_page:
+ \else
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle:
+ \cs_set_eq:NN \@maketitle \@@_patch_@maketitle:
+ \fi
+ }
+\AddToHook{class/report/after}
+ {
+ \if@titlepage
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle_page:
+ \else
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle:
+ \cs_set_eq:NN \@maketitle \@@_patch_@maketitle:
+ \fi
+ }
+\AddToHook{class/book/after}
+ {
+ \if@titlepage
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle_page:
+ \else
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle:
+ \cs_set_eq:NN \@maketitle \@@_patch_@maketitle:
+ \fi
+ }
+% \end{macrocode}
+%
+% \subsection{Helper commands to set metadata}
+%
+% Some temp variables
+% \begin{macrocode}
+\str_new:N \g_@@_title_tmpa_str
+\str_new:N \l_@@_title_tmpa_str
+\tl_new:N \l_@@_title_tmpa_tl
+\seq_new:N \l_@@_title_tmpa_seq
+% \end{macrocode}
+% Support for \cs{texorpdfstring}
+% \begin{macrocode}
+\providecommand\texorpdfstring[2]{#1}%
+% \end{macrocode}
+%
+% A helper command to convert the title into a pdfstring similar to
+% \cs{pdfstringdef}.
+% As we use \cs{text_purify} we must ensure that the default definitions
+% of \cs{@title} and \cs{@author} are robust:
+% \begin{macrocode}
+\protected\def\@title{\@latex@error{No \noexpand\title given}\@ehc}
+\protected\def\@author{\@latex@warning@no@line{No \noexpand\author given}}
+% \end{macrocode}
+% TODO: This should be improved and moved into the pdf module so that
+% it is generally available.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_title_pdfstring:nnN #1 #2 #3 % #1 text, #2 e.g. utf16/hex
+ {
+ \group_begin:
+% \end{macrocode}
+% TODO: we need probably a common boolean to handle
+% \cs{texorpdfstring} also without hyperref.
+% \begin{macrocode}
+ \cs_set_eq:NN\texorpdfstring\use_ii:nn
+ \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { #1 } }
+ \pdf_string_from_unicode:nVN { #2 } \l_@@_title_tmpa_str \l_@@_title_tmpa_str
+ \str_gset_eq:NN \g_@@_title_tmpa_str\l_@@_title_tmpa_str
+ \group_end:
+ \str_set_eq:NN #3 \g_@@_title_tmpa_str
+ }
+\cs_generate_variant:Nn\@@_title_pdfstring:nnN {e}
+% \end{macrocode}
+
+% \subsection{Extend title to set metadata}
+% At first a variable to store the title, as \cs{@title} is emptied by \LaTeX.
+% \begin{macrocode}
+\tl_new:N \g_@@_title_title_tl
+% \end{macrocode}
+% Now we redefine \cs{title} so that it stores the title, and processes
+% keys in the optional argument. We use \texttt{hyp} as module
+% name for the key as this means that if hyperref is loaded its definition
+% of \texttt{pdftitle} will be used -- at some time probably this
+% should be moved out of hyperref so that we have only one definition.
+%
+% \begin{macrocode}
+\RenewDocumentCommand\title{O{}m}
+ {
+ \gdef\@title{#2}
+ \tl_gset_eq:NN\g_@@_title_title_tl\@title
+ \keys_set:nn {hyp}{#1}
+ }
+% \end{macrocode}
+% Now we define the \texttt{pdftitle} key. This is more or less
+% the same definition as in the generic hyperref driver.
+% \begin{macrocode}
+\regex_new:N\l_@@_title_optlang_regex
+\regex_set:Nn\l_@@_title_optlang_regex {\A\[([A-Za-z\-]+)\](.*)}
+\cs_generate_variant:Nn \regex_extract_once:NnN{NVN}
+\cs_generate_variant:Nn \clist_item:nn {on}
+% \end{macrocode}
+% and now the keys.
+% \begin{macrocode}
+\keys_define:nn { hyp }
+ {
+ pdftitle .code:n =
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \pdfmanagement_remove:nn {Info}{Title}
+ }
+ {
+ \tl_set:Ne\l_@@_title_tmpa_tl {\clist_item:on{#1}{1}}
+ \regex_extract_once:NVN
+ \l_@@_title_optlang_regex
+ \l_@@_title_tmpa_tl
+ \l_@@_title_tmpa_seq
+ \seq_if_empty:NTF\l_@@_title_tmpa_seq
+ {
+ \@@_title_pdfstring:nnN {#1}{utf16/hex}\l_@@_title_tmpa_str
+ }
+ {
+ \@@_title_pdfstring:enN
+ {\seq_item:Nn \l_@@_title_tmpa_seq{3}}{utf16/hex}\l_@@_title_tmpa_str
+ }
+ \str_if_eq:VnF\l_@@_title_tmpa_str{<FEFF>}
+ {
+ \pdfmanagement_add:nne {Info}{Title}{\l_@@_title_tmpa_str}
+ }
+ }
+ \AddToDocumentProperties[hyperref]{pdftitle}{#1}
+ }
+ ,pdfsubtitle .code:n = { \AddToDocumentProperties[hyperref]{pdfsubtitle}{#1} }
+ }
+% \end{macrocode}
+%
+% \subsection{Extend \cs{author} to set metadata}
+%
+% At first a variable to store the authors, as \cs{@author} is emptied by \LaTeX.
+% \begin{macrocode}
+\tl_new:N \g_@@_title_author_tl
+% \end{macrocode}
+% Now we redefine \cs{author} so that it stores the authors, and processes
+% keys in the optional argument. We use \texttt{hyp} as module
+% name for the key as this means that if hyperref is loaded its definition
+% of \texttt{pdfauthor} will be used -- at some time probably this
+% should be moved out of hyperref so that we have only one definition.
+%
+% \begin{macrocode}
+\RenewDocumentCommand\author{O{}m}
+ {
+ \gdef\@author{#2}
+ \tl_gset_eq:NN\g_@@_title_author_tl\@author
+ \keys_set:nn {hyp}{#1}
+ }
+% \end{macrocode}
+%
+% Now we define the \texttt{pdfauthor} key. This is more or less
+% the same definition as in the generic hyperref driver.
+
+% \begin{macrocode}
+\keys_define:nn { hyp }
+ {
+ pdfauthor .code:n =
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \pdfmanagement_remove:nn {Info}{Author}
+ }
+ {
+ \tl_set:Ne\l_@@_title_tmpa_tl {\clist_item:on{#1}{1}}
+ \regex_extract_once:NVN
+ \l_@@_title_optlang_regex
+ \l_@@_title_tmpa_tl
+ \l_@@_title_tmpa_seq
+ \seq_if_empty:NTF\l_@@_title_tmpa_seq
+ {
+ \@@_title_pdfstring:nnN {#1}{utf16/hex}\l_@@_title_tmpa_str
+ }
+ {
+ \@@_title_pdfstring:enN
+ {\seq_item:Nn \l_@@_title_tmpa_seq{3}}{utf16/hex}\l_@@_title_tmpa_str
+ }
+ \str_if_eq:VnF\l_@@_title_tmpa_str{<FEFF>}
+ {
+ \pdfmanagement_add:nne {Info}{Author}{\l_@@_title_tmpa_str}
+ }
+ }
+ \AddToDocumentProperties[hyperref]{pdfauthor}{#1}
+ }
+ }
+% \end{macrocode}
+% \subsection{Fallback for classes and packages that redefine \cs{title} or \cs{author}}
+% If a class redefines \cs{author} and \cs{title} again, we try to retrieve at
+% least the values.
+% \begin{macrocode}
+\AddToHook{cmd/maketitle/before}
+ {
+ \tl_gset_eq:NN \g_@@_title_author_tl\@author
+ \tl_gset_eq:NN \g_@@_title_title_tl\@title
+ }
+% \end{macrocode}
+%
+% \subsection{Finalize document}
+% At last we set the title and the author at the end of document
+% if that hasn't happened yet:
+% \begin{macrocode}
+\AddToHook{shipout/lastpage}
+ {
+ \tl_if_empty:eT{\GetDocumentProperties{hyperref/pdftitle}}
+ {
+ \group_begin:
+ \cs_set_eq:NN\thanks \use_none:n
+ \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { \g_@@_title_title_tl } }
+ \keys_set:ne{hyp}{pdftitle={\exp_not:V\l_@@_title_tmpa_str}}
+ \group_end:
+ }
+ \tl_if_empty:eT{\GetDocumentProperties{hyperref/pdfauthor}}
+ {
+ \group_begin:
+ \cs_set_eq:NN\thanks \use_none:n
+ \cs_set:Npn \and {,}
+ \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { \g_@@_title_author_tl } }
+ \keys_set:ne{hyp}{pdfauthor={\exp_not:V\l_@@_title_tmpa_str}}
+ \group_end:
+ }
+% \end{macrocode}
+% force display title, if an UA-standard is detected.
+% \begin{macrocode}
+ \tl_if_empty:eF{\GetDocumentProperties{document/pdfstandard-UA}}
+ {
+ \pdfmanagement_add:nnn {Catalog / ViewerPreferences } { DisplayDocTitle } { true }
+ }
+ }
+\DeclareHookRule{shipout/lastpage}{latex-lab-testphase-title}{before}{pdfmanagement-testphase}
+%</package>
+% \end{macrocode}
+
+% \begin{macrocode}
+%<*latex-lab>
+\ProvidesFile{title-latex-lab-testphase.ltx}
+ [\ltlabtitledate\space v\ltlabtitleversion\space
+ Changes related to the tagging of the title]
+
+\RequirePackage{latex-lab-testphase-title}
+
+%</latex-lab>
+% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-hyperref-changes.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-hyperref-changes.dtx
index 2f00b83c059..ff9dd950b76 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-hyperref-changes.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-hyperref-changes.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-toc-hyperref-changes.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-toc-hyperref-changes.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-kernel-changes.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-kernel-changes.dtx
index 81c9edfe4dc..bb88ffdcb03 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-kernel-changes.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc-kernel-changes.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-toc-kernel-changes.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-toc-kernel-changes.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -17,8 +17,8 @@
% for those people who are interested or want to report an issue.
%
% dates for latex-lab-kernel-changes.sty (pulled from various sources, see ins)
-\def\ltlabkerneldate{2023-10-16}
-\def\ltlabkernelversion{0.85b}
+\def\ltlabkerneldate{2024-02-12}
+\def\ltlabkernelversion{0.85c}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -235,7 +235,7 @@
\makeatletter
\@starttoc@cfgpoint@before{#1}%
\@input{\jobname.#1}%
- \@starttoc@cfgpoint@after{#1}
+ \@starttoc@cfgpoint@after{#1}%
\if@filesw
\expandafter\newwrite\csname tf@#1\endcsname
\immediate\openout \csname tf@#1\endcsname \jobname.#1\relax
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc.dtx
index 6def505e113..7235eb9ed95 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc.dtx
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-toc.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-toc.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-toc.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -271,7 +271,7 @@
{ \int_compare_p:nNn { \g_@@_toc_level_int } > {-100} }
{ \int_compare_p:nNn { \use:c{toclevel@#1} } > { \g_@@_toc_level_int } }
{
- \seq_gpush:Nx \g_@@_toc_stack_seq {{TOC}\use:c{toclevel@#1}}
+ \seq_gpush:Ne \g_@@_toc_stack_seq {{TOC}\use:c{toclevel@#1}}
\tag_struct_begin:n{tag=TOC}
}
% \end{macrocode}
@@ -298,7 +298,7 @@
% \begin{macrocode}
\group_begin:
\text_declare_expand_equivalent:Nn \numberline \use_none:n
- \exp_args:Nx \tag_struct_begin:n{tag=TOCI,title={\text_purify:n {#2}}}
+ \exp_args:Ne \tag_struct_begin:n{tag=TOCI,title={\text_purify:n {#2}}}
% \end{macrocode}
% The TOCI structure should get a /Ref, so we put a request with its destination
% name into the prop.
@@ -307,9 +307,9 @@
% need to store fake names.
% \end{NOTE}
% \begin{macrocode}
- \prop_gput:Nxx \g_@@_struct_ref_by_dest_prop
+ \prop_gput:Nee \g_@@_struct_ref_by_dest_prop
{ \tag_get:n {struct_num} }{#3}
- \seq_gpush:Nx \g_@@_toc_stack_seq {{TOCI}\use:c{toclevel@#1}}
+ \seq_gpush:Ne \g_@@_toc_stack_seq {{TOCI}\use:c{toclevel@#1}}
\group_end:
}
}
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab.ins b/Master/texmf-dist/source/latex/latex-lab/latex-lab.ins
index 548f18a6fa7..7071ed6e3dc 100644
--- a/Master/texmf-dist/source/latex/latex-lab/latex-lab.ins
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab.ins
@@ -154,8 +154,16 @@ where one can also log issues in case there are any.
%table
\generate{\file{table-latex-lab-testphase.ltx}{\from{latex-lab-table.dtx}{latex-lab}}}
+\generate{\file{tabular-latex-lab-testphase.ltx}{\from{latex-lab-table.dtx}{latex-lab-alias}}}
\generate{\file{latex-lab-testphase-table.sty}{\from{latex-lab-table.dtx}{package}}}
+%title
+\generate{\file{title-latex-lab-testphase.ltx}{\from{latex-lab-title.dtx}{latex-lab}}}
+\generate{\file{latex-lab-testphase-title.sty}{\from{latex-lab-title.dtx}{package}}}
+
+%marginpar
+\generate{\file{marginpar-latex-lab-testphase.ltx}{\from{latex-lab-marginpar.dtx}{latex-lab}}}
+\generate{\file{latex-lab-testphase-marginpar.sty}{\from{latex-lab-marginpar.dtx}{package}}}
% stop docstrip adding \endinput
\preamble
diff --git a/Master/texmf-dist/source/latex/tools/afterpage.dtx b/Master/texmf-dist/source/latex/tools/afterpage.dtx
index 518b70761d9..72df39402c9 100644
--- a/Master/texmf-dist/source/latex/tools/afterpage.dtx
+++ b/Master/texmf-dist/source/latex/tools/afterpage.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/afterpage.ins b/Master/texmf-dist/source/latex/tools/afterpage.ins
index 6fec5edc6f6..17792ddfa13 100644
--- a/Master/texmf-dist/source/latex/tools/afterpage.ins
+++ b/Master/texmf-dist/source/latex/tools/afterpage.ins
@@ -3,7 +3,7 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2023
+%% Copyright (C) 1993-2024
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug
reports for it can be opened at https://latex-project.org/bugs/
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2023
+Copyright (C) 1993-2024
The LaTeX Project and any individual authors listed elsewhere
in this file.
diff --git a/Master/texmf-dist/source/latex/tools/array.dtx b/Master/texmf-dist/source/latex/tools/array.dtx
index 6e4e34ea260..e77ef0a3bf1 100644
--- a/Master/texmf-dist/source/latex/tools/array.dtx
+++ b/Master/texmf-dist/source/latex/tools/array.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
@@ -25,15 +25,21 @@
%% Package `array' to use with LaTeX 2e
%% Copyright (C) 1989-1998 Frank Mittelbach, all rights reserved.
%<+package>\NeedsTeXFormat{LaTeX2e}[1995/06/01]
-%<+package>\providecommand\DeclareRelease[3]{}
-%<+package>\providecommand\DeclareCurrentRelease[2]{}
%<+package>
+% For anything before 2016-10-06 we load the 2016 version and hope for the best:
+%<+package>\DeclareRelease{}{1994-06-01}{array-2016-10-06.sty}
+%
%<+package>\DeclareRelease{}{2016-10-06}{array-2016-10-06.sty}
%<+package>\DeclareRelease{v2.4}{2020-02-10}{array-2020-02-10.sty}
-%<+package>\DeclareCurrentRelease{}{2020-10-01}
+%<+package>\DeclareRelease{v2.5}{2023-11-01}{array-2023-11-01.sty}
+%<+package>\DeclareCurrentRelease{}{2024-06-01}
%<+package>
+% \end{macrocode}
+% Current version needs a new kernel.
+% \begin{macrocode}
+%<+package>\NeedsTeXFormat{LaTeX2e}[2024/06/01]
%<+package>\ProvidesPackage{array}
-%<+package> [2023/10/16 v2.5g Tabular extension package (FMi)]
+%<+package> [2024/05/23 v2.6c Tabular extension package (FMi)]
%
% \fi
%
@@ -177,6 +183,18 @@
% \DoNotIndex{\xdef}
% \DoNotIndex{\z@}
%
+%
+% \providecommand\env[1]{\texttt{#1}}
+%
+% \providecommand\hook[1]{\texttt{#1\DescribeHook[noprint]{#1}}}
+% \providecommand\socket[1]{\texttt{#1\DescribeSocket[noprint]{#1}}}
+% \providecommand\plug[1]{\texttt{#1\DescribePlug[noprint]{#1}}}
+%
+% \NewDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+% \NewDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl}
+% \NewDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
+%
+%
% \GetFileInfo{array.sty}
%
% \title{A new implementation of \LaTeX's \textsf{tabular}
@@ -195,6 +213,8 @@
% \MaintainedByLaTeXTeam{tools}
% \maketitle
%
+%
+%
% \MakeShortVerb{\=}
%
% \begin{abstract}
@@ -750,12 +770,29 @@
% \end{itemize}
%
%
+% \section{Support for tagged PDF}
%
-% \changes{v2.2b}{1994/02/04}{Removed interactive prompt}
+% With version 2.6a the package is made tagging aware, which means that
+% it will automatically produce tagged tables (necessary, for example, for
+% accessibility) if tagging is requested via \cs{DocumentMetadata}.
%
-% \MaybeStop{
+% More granular control, e.g., explicitly deciding which cells are
+% header cells, etc., is currently under development, but syntax for
+% this will not appear in this package. Instead it will become
+% available across all tabular-generating packages and then
+% automatically apply here as well.
+%
+% Enabling \LaTeX{} to automatically produce tagged PDF is a long-term
+% project and this is a tiny step in this puzzle. For more information
+% on the project and already available functionality, see
+% \url{https://latex-project.org/publications/indexbytopic/pdf} and
+% \url{https://github.com/latex3/tagging-project}.
%
%
+%
+% \changes{v2.2b}{1994/02/04}{Removed interactive prompt}
+%
+% \MaybeStop{
% \begin{thebibliography}{1}
% \bibitem{bk:GMS94} \textsc{M.~Goossens}, \textsc{F.~Mittelbach}
% and \textsc{A.~Samarin}.
@@ -772,7 +809,6 @@
% \newblock
% Addison-Wesley, Reading, Massachusetts, 1986.
% \end{thebibliography}
-%
% } ^^A end of \MaybeStop
%
%
@@ -786,8 +822,49 @@
% \texttt{docstrip} program.
% \begin{macrocode}
%<*driver>
-\NeedsTeXFormat{LaTeX2e}[1995/12/01]
-\documentclass{ltxdoc}
+\NeedsTeXFormat{LaTeX2e}[2024/06/01]
+% \end{macrocode}
+%
+% We switched from \cls{ltxdoc} to \cls{l3doc} to get support for
+% code written in the L3 programming layer. The first is that we
+% are currently missing \cs{MaintainedByLaTeXTeam}, so we have to
+% provide that for now.
+% \begin{macrocode}
+\documentclass{l3doc}
+
+% currently missing in l3doc
+\makeatletter
+\def\MaintainedBy#1{\gdef\@maintainedby{#1}}
+\let\@maintainedby\@empty
+\def\MaintainedByLaTeXTeam#1{%
+{\gdef\@maintainedby{%
+This file is maintained by the \LaTeX{} Project team.\\%
+Bug reports can be opened (category \texttt{#1}) at\\%
+\url{https://latex-project.org/bugs.html}.}}}
+\def\@maketitle{%
+ \newpage
+ \null
+ \vskip 2em%
+ \begin{center}%
+ \let \footnote \thanks
+ {\LARGE \@title \par}%
+ \vskip 1.5em%
+ {\large
+ \lineskip .5em%
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par}%
+ \vskip 1em%
+ {\large \@date}%
+ \ifx\@maintainedby\@empty
+ \else
+ \vskip 1em%
+ \fbox{\fbox{\begin{tabular}{@{}l@{}}\@maintainedby\end{tabular}}}%
+ \fi
+ \end{center}%
+ \par
+ \vskip 1.5em}
+\makeatother
% undo the default is not used:
@@ -817,6 +894,29 @@
% \end{macrocode}
%
%
+% \section{A note on the updates done December 2023}
+%
+% We introduced support for tagged PDf and at the same time we added
+% code to determine row and column numbers for each cell in
+% preparation for supporting formatting or type specifications for individual
+% cells (or group of cells) from the outside, e.g., \enquote{rows 1,
+% 2, and 10 are header rows} (syntax to be decided).
+%
+% This new code is already written with L3 programming layer conventions
+% while most of the legay code is still as it was before. This make the code
+% currently somewhat clattered, unfortunately. Eventually this will all move to L3
+% programming layer but this will take time.
+%
+%
+% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
+% \end{macrocode}
+%
+%
+%
+%
+%
% \section{The construction of the preamble}
%
% \DeleteShortVerb{\"}
@@ -972,6 +1072,7 @@
% =\@chclass= and =\@chnum=.
% \changes{v2.0f}{1992/02/29}{Argument removed since implicitly known}
% \begin{macrocode}
+\ExplSyntaxOff
\def\@testpach{\@chclass
% \end{macrocode}
% First we deal with the cases in which the \textsf{token}
@@ -981,7 +1082,7 @@
\ifnum \@lastchclass=6 \@ne \@chnum \@ne \else
\ifnum \@lastchclass=7 5 \else
\ifnum \@lastchclass=8 \tw@ \else
- \ifnum \@lastchclass=9 \thr@@
+ \ifnum \@lastchclass=9 \thr@@@@
% \end{macrocode}
% Otherwise we will assume that the \textsf{token} belongs to the
% class $0$
@@ -1032,7 +1133,7 @@
% \begin{macrocode}
10
\@chnum
- \if \@nextchar m\thr@@\else
+ \if \@nextchar m\thr@@@@ \else
\if \@nextchar p4 \else
\if \@nextchar b5 \else
% \end{macrocode}
@@ -1042,6 +1143,7 @@
% \begin{macrocode}
\z@ \@chclass \z@ \@preamerr \z@ \fi \fi \fi \fi
\fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi}
+\ExplSyntaxOn
% \end{macrocode}
% \end{macro}
%
@@ -1062,10 +1164,10 @@
% they are in explicit braces, as in =@{*}=.
%
% This macro is called via
-% =\@xexpast=\meta{preamble}=*0x\@@=.
+% =\@xexpast=\meta{preamble}=*0x\@@@@=.
% The $*$--expression =*0x= is being used to terminate the
% recursion,
-% as we shall see later, and =\@@= serves as an argument
+% as we shall see later, and =\@@@@= serves as an argument
% delimiter. =\@xexpast= has four arguments. The first
% one is the part of the
% user preamble before the first $*$--expression while the second
@@ -1074,7 +1176,7 @@
% above).
% The fourth argument is the rest of the preamble.
% \begin{macrocode}
-\def\@xexpast#1*#2#3#4\@@{%
+\def\@xexpast#1*#2#3#4\@@@@{%
% \end{macrocode}
% The number of copies of \textit{String} (=#2=) that are to be
% produced will be saved in a \textsf{count} register.
@@ -1111,7 +1213,7 @@
% \end{macrocode}
% If \textit{N\/} was greater than zero we prepare for another call
% of =\@xexpast=. Otherwise we assume we have reached the end of
-% the user preamble, because we had appended =*0x\@@= when we first
+% the user preamble, because we had appended =*0x\@@@@= when we first
% called =\@xexpast=. In other words: if the user inserts
% =*{0}{..}= in his preamble, \LaTeX\ ignores the rest of it.
% \begin{macrocode}
@@ -1133,7 +1235,7 @@
% $*$--expression is handled, or to the macro =\@xexnoop=,
% which only ends the recursion by deleting its argument.
% \begin{macrocode}
- \expandafter \@tempb \@tempa #4\@@}
+ \expandafter \@tempb \@tempa #4\@@@@}
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1142,10 +1244,10 @@
% \begin{macro}{\@xexnoop}
% So the first big problem is solved. Now it is easy to
% specify =\@xexnoop=.
-% Its argument is delimited by =\@@= and it simply expands to
+% Its argument is delimited by =\@@@@= and it simply expands to
% nothing.
% \begin{macrocode}
-% \def\@xexnoop#1\@@{}
+% \def\@xexnoop#1\@@@@{}
% \end{macrocode}
% \end{macro}
%
@@ -1270,11 +1372,19 @@
%
% \begin{macro}{\insert@column}
% \begin{macro}{\@sharp}
+% \begin{macro}{\textonly@unskip}
% We now define the macro =\insert@column= which will do
% this work for us.
% \begin{macrocode}
\def\insert@column{%
% \end{macrocode}
+%
+% For tagging we insert as special socket, that adds the necessary
+% PDF tag at the beginning of the cell if tagging is enabled.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/cell/begin}%
+% \end{macrocode}
% Here, we assume that the \textsf{count} register
% =\@tempcnta= has saved the value $=\count@= - 1$.
% \begin{macrocode}
@@ -1291,8 +1401,9 @@
% \changes{v2.0e}{1991/02/07}{Added \{\} around \cs{@sharp} for new ftsel}
% \changes{v2.0h}{1992/06/22}{Removed \{\} again in favour of
% \cs{d@llarbegin}}
+% \changes{v2.6b}{2024/04/08}{Do not \cs{unskip} if in math mode (gh/1323)}
% \begin{macrocode}
- \ignorespaces \@sharp \unskip
+ \ignorespaces \@sharp \textonly@unskip
% \end{macrocode}
% Then the second \textsf{token} register follows whose number should
% be saved in =\count@=.
@@ -1302,12 +1413,42 @@
% \changes{v2.0c}{1990/08/14}{\cs{relax} added to avoid problem
% \cs{the}\cs{toks0}\cs{the}\cs{toks1}.}
% \begin{macrocode}
- \the@toks \the \count@ \relax}
+ \the@toks \the \count@ \relax
% \end{macrocode}
+%
+% And another socket for tagging that adds the necessary closing tag
+% if enabled.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/cell/end}%
+}
+% \end{macrocode}
+% Do the unskip only if we are in hmode:
+% \changes{v2.6b}{2024/04/08}{Do not \cs{unskip} if in math mode (gh/1323)}
+% \begin{macrocode}
+\protected\def\textonly@unskip{\ifhmode\unskip\fi}
+% \end{macrocode}
+% \end{macro}
% \end{macro}
% \end{macro}
%
%
+% \begin{macro}{\insert@pcolumn}
+% Handling pcolumn-cells needs slightly different handling when
+% doing tagging. Rather than changing the plugs in
+% \cs{insert@column} back and forth, we simply use a different
+% version of \cs{insert@column} that has its own sockets.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+\def\insert@pcolumn{%
+ \UseTaggingSocket{tbl/pcell/begin}%
+ \the@toks \the \@tempcnta
+ \ignorespaces \@sharp \unskip
+ \the@toks \the \count@ \relax
+ \UseTaggingSocket{tbl/pcell/end}%
+}
+% \end{macrocode}
+% \end{macro}
%
%
% \subsection{The separation of columns}
@@ -1321,11 +1462,24 @@
% =\@addamp=, the macro that inserts the =&=.
% \begin{macrocode}
% \newif \@iffirstamp
-% \def\@addamp{\if@firstamp \@firstampfalse
-% \else \@addtopreamble &\fi}
+\def\@addamp {
+ \if@firstamp
+ \@firstampfalse
+ \else
+% \end{macrocode}
+% If we are after the first column we have to insert a \verb=&= and
+% also update the cell data.
+% \changes{v2.6a}{2023/12/11}{Managing cell indexes}
+% \begin{macrocode}
+ \edef\@preamble{\@preamble &
+ \noexpand\tbl_update_cell_data: }
+ \fi
+}
% \end{macrocode}
% \end{macro}
%
+%
+%
% \begin{macro}{\@acol}
% \begin{macro}{\@acolampacol}
% \begin{macro}{\col@sep}
@@ -1393,7 +1547,7 @@
% command =\@xexpast=. As we already know, this command saves
% its result in the macro =\@tempa=.
% \begin{macrocode}
-% \@xexpast #1*0x\@@
+% \@xexpast #1*0x\@@@@
% \end{macrocode}
% Afterwards we initialize all registers and macros, that we need
% for the build-up of the preamble.
@@ -1477,7 +1631,7 @@
% \texttt{r}, \texttt{p},\texttt{m} or \texttt{b}. We report an
% error and ignore the declaration given by ={..}=.
% \begin{macrocode}
-% \@preamerr \thr@@ \or
+% \@preamerr \thr@@@@ \or
% \end{macrocode}
% If =\@lastchclass= is $4$ the user preamble has been empty.
% To continue, we insert a =#= in the preamble.
@@ -1671,18 +1825,17 @@
\setbox\ar@mcellbox\vbox
% \end{macrocode}
% The part of the templates which is the same in all three cases
-% (\texttt{p}, \texttt{m} and \texttt{b})
-% is built by the macros =\@startpbox= and
-% =\@endpbox=. =\@startpbox= has an argument:
-% the width of the column which is stored in the current
-% \textsf{token} (i.e.\ =\@nextchar=).
-% Between these two macros we find the well known
-% =\insert@column=.
-% The strut is places after the box
+% (\texttt{p}, \texttt{m} and \texttt{b}) is built by the macros
+% =\@startpbox= and =\@endpbox=. =\@startpbox= has an argument: the
+% width of the column which is stored in the current \textsf{token}
+% (i.e.\ =\@nextchar=). Between these two macros we find the well
+% known =\insert@column= or rather the variant for tagging:
+% \cs{insert@pcolumn}. The strut is placed after the box.
% \changes{v2.4e}{2016/10/07}{Fixing SX68732}
% \changes{v2.4f}{2017/11/04}{Managing m-cells without \cs{vcenter}}
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
% \begin{macrocode}
- \@startpbox{\@nextchar}\insert@column \@endpbox
+ \@startpbox{\@nextchar}\insert@pcolumn \@endpbox
\ar@align@mcell
\do@row@strut \or
% \end{macrocode}
@@ -1690,9 +1843,10 @@
% same way though we do not need the =$= characters because we use
% =\vtop= or =\vbox=.
% \changes{v2.4e}{2016/10/07}{Fixing SX68732}
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
% \begin{macrocode}
- \vtop \@startpbox{\@nextchar}\insert@column \@endpbox\do@row@strut \or
- \vbox \@startpbox{\@nextchar}\insert@column \@endpbox\do@row@strut
+ \vtop \@startpbox{\@nextchar}\insert@pcolumn \@endpbox\do@row@strut \or
+ \vbox \@startpbox{\@nextchar}\insert@pcolumn \@endpbox\do@row@strut
% \end{macrocode}
% Other values for =\@chnum= are impossible. Therefore we
% end the arguments to =\@addtopreamble= and =\ifcase=.
@@ -1783,8 +1937,8 @@
% So the declarations defined by the first =>{...}=
% are ignored.
% \begin{macrocode}
-%\def\@classix{\ifnum \@lastchclass = \thr@@
-% \@preamerr \thr@@ \fi
+%\def\@classix{\ifnum \@lastchclass = \thr@@@@
+% \@preamerr \thr@@@@ \fi
% \end{macrocode}
% Furthermore, we call up =\@class10= because afterwards always a
% new column is started by \texttt{c}, \texttt{l}, \texttt{r},
@@ -1836,14 +1990,14 @@
% We only check if the last \textsf{token} was of class $3$ which is
% forbidden.
% \begin{macrocode}
-\def\@classvii{\ifnum \@lastchclass = \thr@@
+\def\@classvii{\ifnum \@lastchclass = \thr@@@@
% \end{macrocode}
% If this is true we output an error message and
% ignore the declarations stored
% by the last =>{...}=, because these are overwritten
% by the argument of \texttt{@}.
% \begin{macrocode}
- \@preamerr \thr@@ \fi}
+ \@preamerr \thr@@@@ \fi}
% \end{macrocode}
% \end{macro}
%
@@ -2032,7 +2186,7 @@
% second one describes the wanted preamble,
% e.g.\ it has the form =|c|c|c|=.
% \begin{macrocode}
-\def\@array[#1]#2{%
+\def\@array[#1]#2{
% \end{macrocode}
% First we define a \textsf{strut} whose size basically corresponds
% to a normal \textsf{strut} multiplied by the factor
@@ -2051,6 +2205,14 @@
\@depth \arraystretch \dp \strutbox
\@width \z@}%
% \end{macrocode}
+% The total number of table columns of the current table is
+% determined in \cs{tbl_count_table_cols:} but this is called in
+% a group, so local settings do not survive. Thus, to save away the
+% outer value of \cs{g_@@_table_cols_tl} we do it before the group.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \tbl_save_outer_table_cols:
+% \end{macrocode}
% Then we open a group, in which the user preamble is evaluated by
% the macro =\@mkpream=. As we know this must happen locally.
% This macro creates a preamble for a =\halign= and saves
@@ -2059,6 +2221,11 @@
\begingroup
\@mkpream{#2}%
% \end{macrocode}
+% Figure out how many columns this table has:
+% \changes{v2.6a}{2023/12/11}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_count_table_cols:
+% \end{macrocode}
% We again redefine =\@preamble= so that a call up of =\@preamble=
% now starts the =\halign=. Thus also the arguments of \texttt{>},
% \texttt{<}, \texttt{@} and \texttt{!}, saved in the
@@ -2085,13 +2252,38 @@
% unsupported redefinition of a \TeX{} primitive for the moment (as people rely
% on that experimental code).
% \begin{macrocode}
- \xdef\@preamble{\noexpand \ialign \@halignto
- \bgroup \@arstrut \@preamble
- \tabskip \z@ \cr}%
+ \xdef\@preamble{
+% \end{macrocode}
+% \cs{ialign} in the original definition is replaced by
+% \cs{ar@ialign} defined below. This does what \cs{ialign} does but
+% additionally handles the tagging structure for the whole table if necessary.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \noexpand \ar@ialign
+ \@halignto
+ \bgroup \@arstrut
% \end{macrocode}
% What we have not explained yet is the macro =\@halignto=
% that was just used. Depending on its replacement text the
% =\halign= becomes a =\halign= \texttt{to} \meta{dimen}.
+%
+% Next, a tagging support socket is inserted adding the start row tag.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/row/begin}
+% \end{macrocode}
+% At the start of the preamble for the first column we call
+% \cs{tbl_init_cell_data_for_row:} to initialize the cell index data. In
+% later columns this data is updated via \cs{tbl_update_cell_data:}.
+% \changes{v2.6a}{2023/12/11}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_init_cell_data_for_row:
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \@preamble
+ \tabskip \z@ \cr}
+% \end{macrocode}
% Now we close the group again. Thus
% =\@startpbox= and =\@endpbox= as well as all
% \textsf{token} registers get their former meaning back.
@@ -2128,12 +2320,16 @@
% around every column in the \textsf{array}--environment
% the parameter =\mathsurround= should
% also be set to \textsf{0pt}. This prevents additional space between
-% the rows. The
-% \PlainTeX--macro =\m@th= does this.
+% the rows.
% \begin{macrocode}
\lineskip \z@
\baselineskip \z@
- \m@th
+% \end{macrocode}
+% Don't use \cs{m@th} here as that signals to the math taggingg
+% code that this is fake math that should not be tagged.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \mathsurround \z@
% \end{macrocode}
% Beside, we have to assign a special meaning (which we still have
% to specify) to the line separator =\\=. We also have to
@@ -2144,10 +2340,61 @@
% start the wanted =\halign=.
% \changes{1994/12/08}{v2.3b}{add \cs{tabularnewline}}
% \begin{macrocode}
- \let\\\@arraycr \let\tabularnewline\\\let\par\@empty \@preamble}
+ \let\\\@arraycr \let\tabularnewline\\\let\par\@empty
+% \end{macrocode}
+% Another socket for tagging. TODO: what about \cs{arrayleft} above?
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/init}
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \@preamble
+}
% \end{macrocode}
% \end{macro}
%
+%
+%
+% \begin{macro}{\ar@ialign}
+% A new command that replaces \cs{ialign} used previously. \cs{everycr} is
+% also applied to the \cs{cr} ending the preamble so we have to
+% program around that.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+\def\ar@ialign{%
+% \end{macrocode}
+% Before starting a table we have to initialize the variables
+% holding row and column information for cells. We also have
+% locally store the information related to the current cell (if we
+% are already inside a table) so that we can restore it once the
+% inner table is finished.
+% \changes{v2.6a}{2023/12/11}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_init_cell_data_for_table:
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \everycr{%
+ \noalign{%
+% \end{macrocode}
+% If this \cs{cr} was at the end of a real row (e.g., not at the
+% end of the table preamble) we have add a row end tag.
+% \begin{macrocode}
+ \tbl_if_row_was_started:T { \UseTaggingSocket{tbl/row/end} }
+% \end{macrocode}
+% The we prepare for the next row.
+% \begin{macrocode}
+ \tbl_update_cell_data_for_next_row:
+ }%
+ }%
+ \tabskip\z@skip\halign}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
% \begin{macro}{\arraybackslash}
% \changes{v2.4a}{2003/12/17}{(DPC) Macro added (from tabularx)}
% Restore =\\= for use in array and tabular environment (after
@@ -2182,7 +2429,27 @@
% \begin{macro}{\@arraycr}
% In the macro =\@array= the line separator =\\= is
% =\let= to the command =\@arraycr=.
-% Its definition starts with a special brace which I have directly
+% \changes{v2.3c}{1995/04/23}{Avoid adding an ord atom in math}
+% \changes{v2.5e}{2021/04/20}{Use \cs{protected} for \cs{\bslash} variant (gh/548)}
+% \begin{macrocode}
+\protected\def\@arraycr {
+% \end{macrocode}
+% Add code that figures out if the current table row is incomplete
+% (not enough \verb=&=s). It can then do extra actions, such as
+% inserting missing cell tags.
+% \changes{v2.6a}{2023/12/11}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_count_missing_cells:n {@arraycr}
+% \end{macrocode}
+% TODO: maybe this is also the right place to add a socket that
+% could be used to actually enter missing cells instead of just
+% adding tagging structures for them later. This would be optional
+% but in many cases it would be the right thing to do (for example
+% if tables contain vertical lines or similar visual structures
+% that require fully specified rows.
+%
+%
+% We then start a special brace which I have directly
% copied from the original definition. It is
% necessary, because the =\futurlet= in =\@ifnextchar=
% might
@@ -2198,10 +2465,8 @@
% =\halign= while we are looking for a =*= or =[=.
% For further information see
% \cite[Appendix D]{bk:knuth}.
-% \changes{v2.3c}{1995/04/23}{Avoid adding an ord atom in math}
-% \changes{v2.5e}{2021/04/20}{Use \cs{protected} for \cs{\bslash} variant (gh/548)}
% \begin{macrocode}
-\protected\def\@arraycr{\relax\iffalse{\fi\ifnum 0=`}\fi
+ \iffalse{\fi\ifnum 0=`}\fi
% \end{macrocode}
% Then we test whether the user is using the star form and ignore
% a possible star (I also disagree with this procedure, because a
@@ -2210,6 +2475,11 @@
\@ifstar \@xarraycr \@xarraycr}
% \end{macrocode}
% \end{macro}
+
+
+
+
+
%
% \begin{macro}{\@xarraycr}
% In the command =\@xarraycr= we test if an optional argument
@@ -2301,6 +2571,7 @@
% the result column and the actual column entry.
% \changes{v2.3j}{1998/01/29}{Command made \cs{long} to match
% kernel change for pr/2180}
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
% \begin{macrocode}
\long\def\multicolumn#1#2#3{%
% \end{macrocode}
@@ -2310,6 +2581,16 @@
% \begin{macrocode}
\multispan{#1}\begingroup
% \end{macrocode}
+% For tagging support we have to solve two problems:
+% \cs{multicolumn} must handle the row begin if it is used there,
+% and it must save the numbers of cells it spans so that we can add
+% a suitable ColSpan attribute. We do this in the next macro
+% (which in turn calls the \texttt{tbl/row/begin} socket, if
+% necessary).
+% \changes{v2.6a}{2023/12/11}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_update_multicolumn_cell_data:n {#1}
+% \end{macrocode}
% Since a =\multicolumn= should only describe the format of a
% result column, we redefine =\@addamp= in such a way that one gets
% an error message if one uses more than one \texttt{c},
@@ -2336,6 +2617,12 @@
% \begin{macrocode}
\endgroup
% \end{macrocode}
+% Now we update the colspan attribute. This needs setting after
+% the group as it is hidden inside the plug in \cs{insert@column}.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/colspan}{#1}%
+% \end{macrocode}
% In the special situation of =\multicolumn= =\@preamble=
% is not needed as preamble for a =\halign= but it is directly
% inserted into our table. Thus instead of =\sharp=
@@ -2458,6 +2745,12 @@
% \begin{macrocode}
\leavevmode
% \end{macrocode}
+% Now that we know we are in hmode we can add the start tag for the
+% whole table.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/hmode/begin}%
+% \end{macrocode}
% It should be taken into consideration that the macro =\@array=
% must be called in math mode. Therefore we open a \textsf{box},
% insert a =$= and then assign the correct values to =\col@sep= and
@@ -2486,11 +2779,41 @@
% =\@array=. To save \textsf{token} space we then redefine
% =\@preamble=
% because its replacement text isn't longer needed.
+%
+% To handle cell indexes, we do not use \cs{crcr} but a variant
+% that also handles missing cells as necessary.
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
% \begin{macrocode}
-%\def\endarray{\crcr \egroup \egroup \gdef\@preamble{}}
+\def\endarray {
+ \tbl_crcr:n{endarray} \egroup
+ \UseTaggingSocket{tbl/finalize}
+% \end{macrocode}
+%
+% If tables are nested into another then it is necessary to
+% restore information about the cell the inner table started
+% in. Otherwise, the cell index data structures reflect the
+% status in the outer table as they
+% are globally manipulated. We restore in all cases even if we are
+% not in a nesting situation as that makes the code simpler (and
+% probably faster).
+%
+% \cs{endtabular} and \cs{endtabular*} inherit from \cs{endarray}
+% so we only need to change that. \texttt{tabularx} uses a similar method.
+% \changes{v2.6a}{2023/12/11}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_restore_outer_cell_data:
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \egroup
+ \@arrayright \gdef\@preamble{}%
+}
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
% \begin{macro}{\endtabular}
% \begin{macro}{\endtabular*}
% To end a \textsf{tabular} or \textsf{tabular$*$} environment we
@@ -2499,7 +2822,13 @@
% any =\mathsurround= so we cancel that with =\m@th=.
% \changes{v2.5f}{2021/07/12}{Cancel any outside \cs{mathsurround} (gh/614)}
% \begin{macrocode}
-\def\endtabular{\endarray\m@th $\egroup}
+\def\endtabular{\endarray\m@th $\egroup
+% \end{macrocode}
+%
+% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/hmode/end}%
+}
\expandafter\let\csname endtabular*\endcsname=\endtabular
% \end{macrocode}
% \end{macro}
@@ -2518,7 +2847,7 @@
\let\@arrayclassiv=\relax \let\@arrayclassz=\relax
\let\@tabclassiv=\relax \let\@tabclassz=\relax
\let\@arrayacol=\relax \let\@tabacol=\relax
-\let\@tabularcr=\relax \let\@@endpbox=\relax
+\let\@tabularcr=\relax \let\@@@@endpbox=\relax
\let\@argtabularcr=\relax \let\@xtabularcr=\relax
% \end{macrocode}
%
@@ -2576,6 +2905,7 @@
% to define letters, to be used in the same way as the primitive
% column specifiers, `c' `p' etc.
% \begin{macrocode}
+\ExplSyntaxOff % this is really oldstyle using \@tfor :=
\def\newcolumntype#1{%
% \end{macrocode}
% "\NC@char" was added in V2.01 so that active characters, like "@" in
@@ -2615,6 +2945,7 @@
% If an optional argument was not given, give a default argument of 0.
% \begin{macrocode}
\@ifnextchar[{\newcol@{\NC@char}}{\newcol@{\NC@char}[0]}}
+\ExplSyntaxOn
% \end{macrocode}
% \end{macro}
% \begin{macro}{\newcol@}
@@ -2710,16 +3041,18 @@
% produced and then "\typeout" the required string.
% \begin{macrocode}
\def\NC@show#1{%
- \typeout{Column #1\expandafter\expandafter\expandafter\NC@strip
- \expandafter\meaning\csname NC@rewrite@#1\endcsname\@@}}
+ \typeout{Column~ #1\expandafter\expandafter\expandafter\NC@strip
+ \expandafter\meaning\csname NC@rewrite@#1\endcsname\@@@@}}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\NC@strip}
% Delimit the arguments to "\NC@strip" with `\texttt{:}', `\texttt{->}',
-% a space, and "\@@" to pull out the required parts of the output from
+% a space, and "\@@@@" to pull out the required parts of the output from
% "\meaning".
% \begin{macrocode}
-\def\NC@strip#1:#2->#3 #4\@@{#2 -> #4}
+\ExplSyntaxOff
+\def\NC@strip#1:#2->#3 #4\@@@@{#2 -> #4}
+\ExplSyntaxOn
% \end{macrocode}
% \end{macro}
% \begin{macro}{\NC@list}
@@ -2807,6 +3140,7 @@
% \changes{v2.4e}{2016/10/07}{Fixing SX68732}
% \changes{v2.4f}{2017/11/04}{Managing m-cells without \cs{vcenter}}
% \begin{macrocode}
+\ExplSyntaxOff % really oldstyle using \@tfor :=
\def\@mkpream#1{\gdef\@preamble{}\@lastchclass 4 \@firstamptrue
\let\@sharp\relax
% \end{macrocode}
@@ -2869,11 +3203,12 @@
\@acol \or
\or
\@acol \or
- \@preamerr \thr@@ \or
+ \@preamerr \thr@@@@ \or
\@preamerr \tw@ \@addtopreamble\@sharp \or
\or
\else \@preamerr \@ne \fi
\def\the@toks{\the\toks}}
+\ExplSyntaxOn
% \end{macrocode}
% \end{macro}
%
@@ -2908,7 +3243,7 @@
% \texttt{array.sty} 2.0h.
% \begin{macrocode}
\def\@classv{\save@decl
- \expandafter\NC@ecs\@nextchar\extracolsep{}\extracolsep\@@@
+ \expandafter\NC@ecs\@nextchar\extracolsep{}\extracolsep\@@@@@@
\@addtopreamble{\d@llarbegin\the@toks\the\count@\relax\d@llarend}%
\prepnext@tok}
% \end{macrocode}
@@ -2920,7 +3255,7 @@
% second "\extracolsep", there is no point in the user entering two of
% these commands anyway, so this is not really a restriction.
% \begin{macrocode}
-\def\NC@ecs#1\extracolsep#2#3\extracolsep#4\@@@{\def\@tempa{#2}%
+\def\NC@ecs#1\extracolsep#2#3\extracolsep#4\@@@@@@{\def\@tempa{#2}%
\ifx\@tempa\@empty\else\toks\count@={#1\tabskip#2\relax#3}\fi}
%</ncols>
% \end{macrocode}
@@ -2936,28 +3271,27 @@
%
% \begin{macro}{\@tabarray}
% This macro tests for an optional bracket and then calls up
-% "\@@array" or "\@@array[c]" (as default).
+% "\@@@@array" or "\@@@@array[c]" (as default).
% \begin{macrocode}
%<*package>
-\def\@tabarray{\@ifnextchar[{\@@array}{\@@array[c]}}
+\def\@tabarray{\@ifnextchar[{\@@@@array}{\@@@@array[c]}}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\@@array}
+% \begin{macro}{\@@@@array}
% This macro tests could then test an optional delimiter before the
% left brace of the main preamble argument. Here in the main package
% it simply is let to be "\@array".
% \begin{macrocode}
-\let\@@array\@array
+\let\@@@@array\@array
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\endarray}
+% \begin{macro}{\@arrrayleft}
% \begin{macro}{\@arrayright}
% We have to declare the hook we put into "\@array" above.
-% A similar hook `"\@arrayright"' will be inserted into the
+% A similar hook \cs{@arrayright} will be inserted into the
% "\endarray" to gain control. Both defaults to empty.
% \begin{macrocode}
-\def\endarray{\crcr \egroup \egroup \@arrayright \gdef\@preamble{}}
\let\@arrayleft\@empty
\let\@arrayright\@empty
% \end{macrocode}
@@ -3182,6 +3516,14 @@
% \end{macro}
%
%
+%
+%
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+%
% \PrintIndex
% \PrintChanges
%
diff --git a/Master/texmf-dist/source/latex/tools/bm.dtx b/Master/texmf-dist/source/latex/tools/bm.dtx
index a608c6aeb58..d7d6eb54ee2 100644
--- a/Master/texmf-dist/source/latex/tools/bm.dtx
+++ b/Master/texmf-dist/source/latex/tools/bm.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
@@ -22,7 +22,7 @@
% \fi
%
% \iffalse
-%% Copyright 1996 1997 1998 1999 2002 2003 2004 2016 2017 2019 2021 2022
+%% Copyright 1996 1997 1998 1999 2002 2003 2004 2016 2017 2019 2021 2022 2023
%% David Carlisle Frank Mittelbach
%%
%% Development of this package was commissioned by Y&Y Inc.
@@ -36,7 +36,7 @@
%<driver>\ProvidesFile{bm.drv}
% \fi
% \ProvidesFile{bm.dtx}
- [2023/07/08 v1.2f Bold Symbol Support (DPC/FMi)]
+ [2023/12/19 v1.2f Bold Symbol Support (DPC/FMi)]
%
% \iffalse
%<*driver>
@@ -178,14 +178,14 @@
% spacing). So the third example produces identical output to the first
% (but \TeX\ takes more time producing it).
%
-% In the fourth example the |\mathrm{\bm{g}}| is essentially
+% In the fourth example the |\mathrm{\bm{{g}}}| is essentially
% equivalent to |\mathrm{\mbox{\boldmath$g$}}|. Currently math alphabet
% settings are not passed down to `nested' math lists, and so in this
% example, the |\mathrm| has no effect, and a bold math italic $\bm g$
% is obtained.
%
% Similarly the last example is equivalent to
-% |$\mbox{\boldmath$\mathrm{g}$}}| and so in this case, one obtains a
+% |$\mbox{\boldmath$\mathrm{g}$}$| and so in this case, one obtains a
% bold roman \textbf{g}.
%
% \subsection{Delimiters}
diff --git a/Master/texmf-dist/source/latex/tools/bm.ins b/Master/texmf-dist/source/latex/tools/bm.ins
index a7424a0e675..c0c8125d101 100644
--- a/Master/texmf-dist/source/latex/tools/bm.ins
+++ b/Master/texmf-dist/source/latex/tools/bm.ins
@@ -3,7 +3,7 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2023
+%% Copyright (C) 1993-2024
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug
reports for it can be opened at https://latex-project.org/bugs/
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2023
+Copyright (C) 1993-2024
The LaTeX Project and any individual authors listed elsewhere
in this file.
diff --git a/Master/texmf-dist/source/latex/tools/calc.dtx b/Master/texmf-dist/source/latex/tools/calc.dtx
index 2c4cecbf038..154c6ba26a8 100644
--- a/Master/texmf-dist/source/latex/tools/calc.dtx
+++ b/Master/texmf-dist/source/latex/tools/calc.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/dcolumn.dtx b/Master/texmf-dist/source/latex/tools/dcolumn.dtx
index c8ddaf4ce6b..feb3096ccec 100644
--- a/Master/texmf-dist/source/latex/tools/dcolumn.dtx
+++ b/Master/texmf-dist/source/latex/tools/dcolumn.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/delarray.dtx b/Master/texmf-dist/source/latex/tools/delarray.dtx
index 86a1a6203f6..61d40b5c744 100644
--- a/Master/texmf-dist/source/latex/tools/delarray.dtx
+++ b/Master/texmf-dist/source/latex/tools/delarray.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/enumerate.dtx b/Master/texmf-dist/source/latex/tools/enumerate.dtx
index 2818a73a09b..c3889a9157a 100644
--- a/Master/texmf-dist/source/latex/tools/enumerate.dtx
+++ b/Master/texmf-dist/source/latex/tools/enumerate.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/fileerr.dtx b/Master/texmf-dist/source/latex/tools/fileerr.dtx
index eef222bb6eb..0e8eeb1ffb1 100644
--- a/Master/texmf-dist/source/latex/tools/fileerr.dtx
+++ b/Master/texmf-dist/source/latex/tools/fileerr.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/fontsmpl.dtx b/Master/texmf-dist/source/latex/tools/fontsmpl.dtx
index 525065cde5f..6e9835e20eb 100644
--- a/Master/texmf-dist/source/latex/tools/fontsmpl.dtx
+++ b/Master/texmf-dist/source/latex/tools/fontsmpl.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/ftnright.dtx b/Master/texmf-dist/source/latex/tools/ftnright.dtx
index 663fa304a94..a3826376dbb 100644
--- a/Master/texmf-dist/source/latex/tools/ftnright.dtx
+++ b/Master/texmf-dist/source/latex/tools/ftnright.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/hhline.dtx b/Master/texmf-dist/source/latex/tools/hhline.dtx
index 49ac1ae2082..b2d833d965d 100644
--- a/Master/texmf-dist/source/latex/tools/hhline.dtx
+++ b/Master/texmf-dist/source/latex/tools/hhline.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/indentfirst.dtx b/Master/texmf-dist/source/latex/tools/indentfirst.dtx
index 2314db1c70c..9bbe1871e15 100644
--- a/Master/texmf-dist/source/latex/tools/indentfirst.dtx
+++ b/Master/texmf-dist/source/latex/tools/indentfirst.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/l3sys-query.dtx b/Master/texmf-dist/source/latex/tools/l3sys-query.dtx
new file mode 100644
index 00000000000..3cba5da4a62
--- /dev/null
+++ b/Master/texmf-dist/source/latex/tools/l3sys-query.dtx
@@ -0,0 +1,545 @@
+% \iffalse
+%% Source File: l3sys-query.dtx
+%% Copyright (C) 2024
+%%
+%% The LaTeX Project and any individual authors listed elsewhere
+%% in this file.
+%%
+%% This file may be distributed under the terms of the LPPL.
+%% See README for details.
+%
+%<*dtx>
+ \ProvidesFile{l3sys-query.dtx}
+%</dtx>
+%<package>\ProvidesPackage{l3sys-query}
+%<driver> \ProvidesFile{l3sys-query.drv}
+% \fi
+% \ProvidesFile{l3sys-query.dtx}
+ [2024-03-28 v1.0a LaTeX2e interface for l3sys file queries]
+%
+% \iffalse
+%<*driver>
+\documentclass{l3doc}%{ltxdoc}
+\begin{document}
+\DocInput{l3sys-query.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \GetFileInfo{l3sys-query.dtx}
+%
+% \title{\LaTeX\ document interface to the \pkg{l3sys-query} script:
+% System queries for LaTeX using Lua\thanks{This file
+% has version number \fileversion, last
+% revised \filedate.}}
+% \author{\LaTeX\ project}
+% \date{\filedate}
+%
+%
+% \maketitle
+%
+% \tableofcontents
+%
+% \section{Introduction}
+%
+% \TeX{} engines provide only very limited access to information about the system
+% they are used on: using primitives, one can for example get the size of a single
+% file, but not a list of files in a given location. For most documents, this is
+% not an issue as they are self-contained. However, for cases where
+% \enquote{dynamic} construction of parts of a document is needed based on file
+% lists or other system-dependent data, methods to obtain this from (restricted)
+% shell escape are desirable.
+%
+% Security considerations mean that directly querying the system shell is
+% problematic for general use. Instead, \emph{restricted} shell escape may be used
+% to get many details, provided a suitable tool is available to provide the
+% information in a platform-neutral and security-conscious way. The Java program
+% \texttt{texosquery}, written by Nicola Talbot, has been available for a number
+% of years to provide this facility. As well as file system insight,
+% \texttt{texosquery} also provides for example locale data and other system
+% information. However, the requirement for Java means that the script is not
+% automatically usable when a \TeX{} system is installed.
+%
+% The \LaTeX{} team have therefore provided a Lua-based script,
+% \texttt{l3sys-query}, which conforms to the security requirements of \TeX{} Live
+% using Lua to obtain the system information. This means that it can be used
+% \enquote{out of the box} across platforms. The facilities provided by
+% \texttt{l3sys-query} are more limited than \texttt{texosquery}, partly as some
+% information is available in modern \TeX{} systems using primitives, and partly
+% as the aim of \texttt{l3sys-query} is to provide information where there are
+% defined use cases. Requests for additional data interfaces are welcome.
+%
+% This package provides a document level \textit{Key-Value} interface
+% to The \texttt{l3sys-query} functionality, although as a convenience
+% it also summarizes the documentation for the L3 programming
+% interface layer (prvided by the \pkg{l3sys} module of
+% \pkg{l3kernel}, and of the command line Lua script
+% \texttt{l3sys-query} which is distributed separately and provides
+% the underlying functionality.
+%
+%
+%
+% \section{The document level key-value interface\label{sec:kv}}
+%
+% This provides an interface to \texttt{l3sys-query} based on
+% \pkg{l3keys} that allows the options to be specified and checked
+% individually. Internally the supplied key values are used to build
+% up the arguments to the commands described above in the L3
+% programming layer commands described in section~\ref{sec:expl3}
+%
+% Results containing path separators \emph{always}
+% use~|/|, irrespective of the platform in use.
+%
+%
+% \begin{function}
+% {\QueryWorkingDirectory}
+% \begin{syntax}
+% \cs{QueryWorkingDirectory} \Arg{result cmd}
+% \end{syntax}
+% Defines supplied command \meta{result cmd} to hold
+% the absolute path to the current working directory of the
+% \TeX\ system.
+% This is the directory (folder) from which \TeX\ was started, so usually
+% the location of the main document file.
+% \end{function}
+%
+% \begin{function}
+% {\QueryFiles, \QueryFilesTF}
+% \begin{syntax}
+% \cs{QueryFiles} \oarg{options} \Arg{spec} \Arg{function}
+% \cs{QueryFilesTF} \oarg{options} \Arg{spec} \Arg{function} \Arg{pre code} \Arg{empty list code}
+% \end{syntax}
+% This generates a file list based on the \meta{spec} and \meta{options}.
+% The command then applies \meta{function} to each item in the sequence of filenames.
+% The \meta{function} should be a macro body which will be passed the file path as |#1|.
+%
+% The TF version executes the T (\meta{pre code}) argument before iterating over the list
+% and the F (\meta{empty list code}) argument if the list is empty.
+% \end{function}
+%
+% Note that this interface in mapping directly over the sequence of
+% filenames does not allow some uses which are provided by the
+% programming interface described in the following section, which allows
+% the sequence to be manipulated before being used.
+%
+% The defined keys map very closely to the options of the
+% \texttt{l3sys-query} command which is described in
+% section~\ref{sec:lua}.
+%
+% \begin{itemize}
+% \item
+% The keys \texttt{recursive}, \texttt{ignore-case}, \texttt{reverse}, \texttt{pattern}
+% take no values and map directly to the command line options of the same name.
+%
+% \item
+% The key \texttt{sort} accepts the values \texttt{date} and \texttt{name}.
+%
+% \item
+% The key \texttt{type} accepts \texttt{d} or \texttt{f}.
+%
+% \item
+% The key \texttt{exclude} accepts a glob (or Lua pattern) matching
+% files to be excluded. The package arranges that the quoting of the
+% argument is automatically added if unrestricted shell escape is
+% enabled.
+%
+% \end{itemize}
+%
+% Within the main \meta{spec} argument, and the value of the \texttt{exclude} key,
+% the following characters may need special handling.
+% |~| may be used (which \texttt{kpathsea} uses to denote the users home directory).
+% |\%|, or at the top level |%|, may be used to produce a literal |%|
+% which may be especially useful if the \texttt{pattern} key is used
+% as \% is the escape character in Lua patterns.
+%
+% \subsection{Examples\label{sec:examples2e}}
+%
+% \begin{itemize}
+% \item
+% Include every |png| file in the current directory.
+% \begin{verbatim}
+% \QueryFiles{*.png}{\includegraphics{#1}\par}
+% \end{verbatim}
+%
+% \item
+% Input every \TeX\ file with a filename matching \texttt{chapter[0-9].tex}.
+% \begin{verbatim}
+% \QueryFiles[pattern]{chapter%d.*%.tex}{\input{#1}}
+% \end{verbatim}
+% \end{itemize}
+%
+% \section{The L3 programming layer interface\label{sec:expl3}}
+%
+% \begin{function}
+% {\sys_get_query:nN, \sys_get_query:nnN, \sys_get_query:nnnN}
+% \begin{syntax}
+% \cs{sys_get_query:nN} \Arg{cmd} \Arg{tl var}
+% \cs{sys_get_query:nnN} \Arg{cmd} \Arg{spec} \Arg{tl var}
+% \cs{sys_get_query:nnnN} \Arg{cmd} \Arg{options} \Arg{spec} \Arg{tl var}
+% \end{syntax}
+% Sets the \meta{tl var} to the information returned by the
+% \texttt{l3sys-query} \meta{cmd}, potentially supplying the \meta{options}
+% and \meta{spec} to the query call. The valid \meta{cmd} names are at present
+% \begin{itemize}
+% \item \texttt{pwd} Returns the absolute path to the current working directory
+% \item \texttt{ls} Returns a directory listing, using the \meta{spec} to
+% select files and applying the \meta{options} if given
+% \end{itemize}
+% The \meta{spec} should be a file glob and will automatically be passed to
+% the script without shell expansion.
+% \end{function}
+%
+% \begin{function}
+% {\sys_split_query:nN, \sys_split_query:nnN, \sys_split_query:nnnN}
+% \begin{syntax}
+% \cs{sys_split_query:nN} \Arg{cmd} \Arg{seq}
+% \cs{sys_split_query:nnN} \Arg{cmd} \Arg{spec} \Arg{seq}
+% \cs{sys_split_query:nnnN} \Arg{cmd} \Arg{options} \Arg{spec} \Arg{seq}
+% \end{syntax}
+% Works as described for \cs{sys_get_query:nnnN}, but sets the \meta{seq}
+% to contain one entry for each line returned by \texttt{l3sys-query}.
+% \end{function}
+%
+% \section{The \texttt{l3sys-query} Lua script\label{sec:lua}}
+% \subsection{The command line interface}
+%
+% The command line interface to
+% \begin{center}
+% \ttfamily
+% l3sys-query \meta{cmd} [\meta{option(s)}] [\meta{args}]
+% \end{center}
+% where \texttt{\meta{cmd}} can be one of the following:
+% \begin{itemize}[noitemsep]\ttfamily
+% \item ls
+% \item ls \meta{args}
+% \item pwd
+% \end{itemize}
+% The \meta{cmd} are described below. The result of the \meta{cmd} will be printed
+% to the terminal in an interactive run; in normal usage, this will be piped to
+% the calling \TeX{} process. Results containing path separators \emph{always}
+% use~|/|, irrespective of the platform in use.
+%
+% As well as these targets, the script recognizes the options
+% \begin{itemize}
+% \item |--exclude| Specification for directory entries to exclude
+% \item |--ignore-case| Ignores case when sorting directory listings
+% \item |--pattern| (|-p|) Treat the \meta{args} as Lua patterns rather
+% than converting from wildcards
+% \item |--recursive| (|-r|) Enables recursive searching during directory
+% listings
+% \item |--reverse| Causes sorting to go from highest to lowest rather
+% than lowest to highest
+% \item |--sort| Sets the method used to sort entries returned by |ls|
+% \item |--type| Selects the type of entry returned by |ls|
+% \end{itemize}
+% The action of these options on the appropriate \meta{cmd(s)} is detailed below.
+%
+% \subsubsection{\texttt{ls [\meta{args}]}}
+%
+% Lists the contents of one or more directories, in a manner somewhat reminiscent
+% of the Unix command |ls| or the Windows command |dir|. The exact nature of the
+% output will depend on the \meta{args}, if given, along with the prevailing
+% options. Note that the options names are inspired by ideas from the Unix
+% commands |ls| and |find| as well as the Windows command |dir|: they therefore do
+% not map directly to those of any one of the command line tools that they
+% somewhat mirror.
+%
+% When no \meta{args} are given, all entries in the current directory will be
+% listed, one per line in the output. This will include both files and
+% subdirectories. Each entry will include a path relative to the current
+% directory: for files \emph{in} the current directory, this will be |./|. The
+% order of results will be determined by the underlying operating system process:
+% unless requested \emph{via} an option, no sorting takes place.
+%
+% As standard, the \meta{args} are treated as a file/path name potentially
+% including |?| and |*| as wildcards, for example |*.png| or |file?.txt|.
+% \begin{verbatim}
+% l3sys-query ls '*.png'
+% \end{verbatim}
+% Some care is needed in preventing expansion of such wildcards by the shell or
+% \texttt{texlua} process: these are detailed in Section~\ref{sec:wildcard}. In
+% this section, |'| is used to indicate a character being used to suppress
+% expansion: this is for example normal on macOS and Linux.
+%
+% Removal of entries from the listing can be achieved using the |--exclude|
+% option, which should be given with a \meta{xarg}, for example
+% \begin{verbatim}
+% l3sys-query ls --exclude '*.bak' 'graphics/*'
+% \end{verbatim}
+% Directory entries starting |.| are traditionally hidden on Linux and macOS
+% systems: these \enquote{dot} entries are excluded from the output of
+% \texttt{l3sys-query}. The entries |.| and |..| for the current and parent
+% directory are also excluded from the results returned by \texttt{l3sys-query} as
+% they can always be assumed.
+%
+% For more complex matching, the \meta{args} can be treated as a Lua pattern using
+% the |--pattern| (|-p|) option; this also applies to the \meta{xarg} argument to
+% the |--exclude| option. For example, the equivalent to wildcard |*.png| could be
+% obtained using
+% \begin{verbatim}
+% l3sys-query ls --pattern '^.*%.png$'
+% \end{verbatim}
+%
+% The results returned by |ls| can be sorted using the |--sort| option. This can
+% be set to |none| (use the order from the file system: the default), |name| (sort
+% by file name) or |date| (sort by date last modified). The sorting order can be
+% reversed using |--reverse|. Sorting normally takes account of case: this can be
+% suppressed with the |--ignore-case| option.
+%
+% The listing can be filtered based on the type of entry using the |--type|
+% option. This takes a string argument, one of |d| (directory) or |f| (file).
+%
+% As standard, only the path specified as part of the \meta{args} is queried.
+% However, if the |--recursive| (|-r|) option is set, the query is applied within
+% all subdirectories. Subdirectories starting with~|.| (macOS and Linux hidden)
+% are excluded from recursion.
+%
+% For security reasons, only paths within the current working directory can be
+% queried, thus for example |graphics/*.png| will list all |png| files in the
+% |graphics| subdirectory, but |../graphics/*.png| will yield no output.
+%
+% \subsubsection{\texttt{pwd}}
+%
+% Returns the current working directory from which \texttt{l3sys-query} is run.
+% From within a \TeX{} run, this will (usually) be the directory containing the
+% main file, assuming a command such as
+% \begin{verbatim}
+% pdflatex main.tex
+% \end{verbatim}
+% The \texttt{pwd} command is unaffected by any options.
+%
+% \subsection{Spaces in arguments}
+%
+% Since \texttt{l3sys-query} is intended primarily for use with restricted shell
+% escape calls from \TeX{} processes, handling of spaces is unusual. It is not
+% possible to quote spaces in such a call, so for example whilst
+% \begin{verbatim}
+% l3sys-query ls "foo *"
+% \end{verbatim}
+% does work from the command prompt to find all files with names starting
+% \verb*|foo |, it would not work \emph{via} restricted shell escape. To
+% circumvent this, \texttt{l3sys-query} will collect all command line arguments
+% after any \meta{options}, and combine these as a space-separated \meta{args},
+% for example allowing
+% \begin{verbatim}
+% l3sys-query ls foo '*'
+% \end{verbatim}
+% to achieve the same result as the first example. The result is that the
+% \meta{args} will only every be interpreted by \texttt{l3sys-query} as a single
+% argument. It also means that spaces cannot be used at the start or end of the
+% argument, nor can multiple spaces appear between non-space arguments.
+%
+% \subsection{Wildcard expansion handling\label{sec:wildcard}}
+%
+% The handling of wildcards needs some further comment for those using
+% \texttt{l3sys-query} from the command line: the \pkg{expl3} interface described
+% in Section~\ref{sec:expl3} handles this aspect automatically for the user.
+%
+% On macOS and Linux, the shell normally expands globs, which include the
+% wildcards |*| and |?|, before passing arguments to the appropriate command.
+% This can be suppressed by surrounding the argument with |'| characters, hence
+% the formulation
+% \begin{verbatim}
+% l3sys-query ls '*.png'
+% \end{verbatim}
+% earlier.
+%
+% On Windows, the shell does no expansion, and thus arguments are passed as-is to
+% the relevant command. As such, |'| has no special meaning here. However, to
+% allow quoting of wildcards from the shell in a platform-neutral manner,
+% \texttt{l3sys-query} will strip exactly one set of |'| characters around each
+% argument before further processing.
+%
+% It is not possible to use |"| quotes at all in the argument passed to
+% \texttt{l3sys-query} from \TeX{}, as the \TeX{} system removes all |"| in
+% |\input| while handling space quoting.
+%
+% Restricted shell escape prevents shell expansion of wildcards entirely. On
+% non-Windows systems, it does this by ensuring that each argument is |'| quoted
+% to ensure further expansion. Thus a \TeX{} call such as
+% \begin{verbatim}
+% \input|"l3sys-query ls '*.png'"
+% \end{verbatim}
+% will work if |--shell-escape| is used as the argument is passed directly to the
+% shell, but in restricted shell escape will give an error such as:
+% \begin{verbatim}
+% ! I can't find file `"|l3sys-query ls '*.png'"'.
+% \end{verbatim}
+% The \LaTeX{} interfaces described above adjust the quoting used depending on the
+% |shell-escape| status.
+%
+%
+% \MaybeStop{}
+%
+% \section{The \LaTeXe\ package implementation}
+%
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+%<@@=queryfiles>
+% \end{macrocode}
+%
+% The package should eventually work in restricted shell escape but will do
+% nothing useful if the process was started with |--no-shell-escape|.
+% \begin{macrocode}
+\sys_if_shell:F{
+ \PackageWarningNoLine{l3sys-query}
+ {Shell ~Escape ~is ~disabled.\MessageBreak All ~queries ~will ~return ~empty ~results}
+ }
+% \end{macrocode}
+%
+% \subsection{\cs{QueryWorkingDirectory}}
+% |\QueryWorkingDirectory| is a direct call to the |pwd| command provided by \texttt{l3sys-query}.
+% \begin{macrocode}
+\NewDocumentCommand\QueryWorkingDirectory {m} {
+ \sys_get_query:nN {pwd} #1
+}
+% \end{macrocode}
+%
+% \subsection{\cs{QueryFiles} and \cs{QueryFilesTF}}
+%
+% The declarations of these commands are done in two steps to allow catcode chanes
+% before the arguments are read. This allows the use of |%| and |^^| in patterns
+% at least if the command is not nested in another command argument. (|\%| may be used
+% to generate |%| in all cases).
+%
+% Variables for saving the current definition of |\%| and |~|.
+% \begin{macrocode}
+\tl_new:N\l_query_percent_tl
+\tl_new:N\l_query_tilde_tl
+% \end{macrocode}
+%
+% Allow |%| and |^^| at the top level.
+% \begin{macrocode}
+\NewDocumentCommand\QueryFiles {} {
+ \group_begin:
+ \char_set_catcode_other:N \%
+ \char_set_catcode_other:N \^
+ \QueryFiles_inner
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\char_set_catcode_active:N \~
+% \end{macrocode}
+%
+% \begin{macrocode}
+\NewDocumentCommand\QueryFiles_inner {O{}m}{
+ \group_end:
+ \tl_set:Nn\l_tmpa_tl{}
+ \cs_set_eq:NN \l_query_percent_tl \%
+ \cs_set_eq:NN \% \c_percent_str
+ \cs_set_eq:NN \l_query_tilde_tl ~
+ \cs_set_eq:NN ~ \c_tilde_str
+ \keys_set:nn{QueryFiles}{#1}
+ \exp_args:NnV\sys_split_query:nnnN {ls} \l_tmpa_tl {#2} \l_tmpa_seq
+ \cs_set_eq:NN \% \l_query_percent_tl
+ \cs_set_eq:NN ~ \l_query_tilde_tl
+ \seq_map_inline:Nn\l_tmpa_seq
+}
+% \end{macrocode}
+%
+% This duplicates rather than shares code so as to read the function
+% and TF arguments with normal catcode regime.
+% (This could probably be optimised.)
+% \begin{macrocode}
+\NewDocumentCommand\QueryFilesTF {} {
+ \group_begin:
+ \char_set_catcode_other:N \%
+ \QueryFilesTF_inner
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\NewDocumentCommand\QueryFilesTF_inner {O{}m}{
+ \group_end:
+ \tl_set:Nn\l_tmpa_tl{}
+ \cs_set_eq:NN \l_query_percent_tl \%
+ \cs_set_eq:NN \% \c_percent_str
+ \cs_set_eq:NN \l_query_tilde_tl ~
+ \cs_set_eq:NN ~ \c_tilde_str
+ \keys_set:nn{QueryFiles}{#1}
+ \exp_args:NnV\sys_split_query:nnnN {ls} \l_tmpa_tl {#2} \l_tmpa_seq
+ \cs_set_eq:NN \% \l_query_percent_tl
+ \cs_set_eq:NN ~ \l_query_tilde_tl
+ \seq_if_empty:NTF \l_tmpa_seq \use_iii:nnn \__queryfiles_aux:nnn
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\char_set_catcode_space:N \~
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Npn \__queryfiles_aux:nnn #1#2#3 {
+ #2
+ \seq_map_inline:Nn\l_tmpa_seq {#1}
+ }
+% \end{macrocode}
+%
+% Defining the keys. Most take no value and simply add a \texttt{l3sys-query} \texttt{-{}-}
+% option to the command linebeing constructed.
+% \begin{macrocode}
+\keys_define:nn {QueryFiles} {
+% \end{macrocode}
+%
+% \begin{macrocode}
+recursive .code:n =\tl_put_right:Nn \l_tmpa_tl {--recursive ~ } ,
+recursive .value_forbidden:n = true ,
+% \end{macrocode}
+%
+% \begin{macrocode}
+ignore-case .code:n =\tl_put_right:Nn \l_tmpa_tl {--ignore-case ~ } ,
+ignore-case .value_forbidden:n = true ,
+% \end{macrocode}
+%
+% \begin{macrocode}
+reverse .code:n =\tl_put_right:Nn \l_tmpa_tl {--reverse ~ } ,
+reverse .value_forbidden:n = true ,
+% \end{macrocode}
+%
+% \begin{macrocode}
+exclude .code:n =\tl_put_right:Ne \l_tmpa_tl {
+ --exclude ~
+ \sys_if_shell_restricted:F'
+ \exp_not:n{#1}
+ \sys_if_shell_restricted:F'
+ ~ } ,
+exclude .value_required:n = true ,
+% \end{macrocode}
+%
+% The |type| key checks the supplied value is valid |d| for directories
+% or |f| for files The default behaviour lists both.
+% \begin{macrocode}
+type .choices:nn = {d,f}
+ {\tl_put_right:Nn \l_tmpa_tl {--type ~ #1 ~ }} ,
+% \end{macrocode}
+%
+% The |sort| key checks the supplied value is valid |date| or |name|.
+% \begin{macrocode}
+sort .choices:nn = {date,name}
+{\tl_put_right:Nn \l_tmpa_tl {--sort ~ #1 ~ }} ,
+% \end{macrocode}
+%
+% \begin{macrocode}
+pattern .code:n =\tl_put_right:Nn \l_tmpa_tl {--pattern ~ } ,
+pattern .value_forbidden:n = true ,
+% \end{macrocode}
+%
+% \begin{macrocode}
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \Finale
+%
diff --git a/Master/texmf-dist/source/latex/tools/l3sys-query.ins b/Master/texmf-dist/source/latex/tools/l3sys-query.ins
new file mode 100644
index 00000000000..163eec0058c
--- /dev/null
+++ b/Master/texmf-dist/source/latex/tools/l3sys-query.ins
@@ -0,0 +1,76 @@
+%%
+%% This file will generate fast loadable files and documentation
+%% driver files from the doc files in this package when run through
+%% LaTeX or TeX.
+%%
+%% Copyright (C) 1993-2024
+%% The LaTeX Project and any individual authors listed elsewhere
+%% in this file.
+%%
+%% This file is part of the Standard LaTeX `Tools Bundle'.
+%% -------------------------------------------------------
+%%
+%% It may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3c
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% https://www.latex-project.org/lppl.txt
+%% and version 1.3c or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% As this file contains legal notices, it is NOT PERMITTED to modify
+%% this file in any way that the legal information placed into
+%% generated files is changed (i.e., the files generated when the
+%% original file is executed). This restriction does not apply if
+%% (parts of) the content is reused in a different WORK producing its
+%% own generated files.
+%%
+%% The list of all files belonging to the `Tools Bundle' is
+%% given in the file `manifest.txt'.
+%%
+%%
+%% --------------- start of docstrip commands ------------------
+%%
+\input docstrip
+
+\keepsilent
+
+\usedir{tex/latex/tools}
+
+\preamble
+
+This is a generated file.
+
+The source is maintained by the LaTeX Project team and bug
+reports for it can be opened at https://latex-project.org/bugs/
+(but please observe conditions on bug reports sent to that address!)
+
+Copyright (C) 1993-2024
+The LaTeX Project and any individual authors listed elsewhere
+in this file.
+
+This file was generated from file(s) of the Standard LaTeX `Tools Bundle'.
+--------------------------------------------------------------------------
+
+It may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3c
+of this license or (at your option) any later version.
+The latest version of this license is in
+ https://www.latex-project.org/lppl.txt
+and version 1.3c or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+This file may only be distributed together with a copy of the LaTeX
+`Tools Bundle'. You may however distribute the LaTeX `Tools Bundle'
+without such generated files.
+
+The list of all files belonging to the LaTeX `Tools Bundle' is
+given in the file `manifest.txt'.
+
+\endpreamble
+
+\keepsilent
+
+\generate{\file{l3sys-query.sty}{\from{l3sys-query.dtx}{package}}}
+
+\endbatchfile
diff --git a/Master/texmf-dist/source/latex/tools/layout.dtx b/Master/texmf-dist/source/latex/tools/layout.dtx
index 2798bd4f60d..a2fc87a6a51 100644
--- a/Master/texmf-dist/source/latex/tools/layout.dtx
+++ b/Master/texmf-dist/source/latex/tools/layout.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/longtable.dtx b/Master/texmf-dist/source/latex/tools/longtable.dtx
index 2a61ab0c87e..cc3a939e7ad 100644
--- a/Master/texmf-dist/source/latex/tools/longtable.dtx
+++ b/Master/texmf-dist/source/latex/tools/longtable.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
@@ -27,8 +27,9 @@
\ProvidesFile{longtable.dtx}
%</dtx>
%<package>\NeedsTeXFormat{LaTeX2e}[1995/06/01]
-%<package>\providecommand\DeclareRelease[3]{}
-%<package>\providecommand\DeclareCurrentRelease[2]{}
+%<package>
+% Try the 2020 version for any rollback before that date:
+%<package>\DeclareRelease{}{1994-06-01}{longtable-2020-01-07.sty}
%<package>
%<package>\DeclareRelease{v4.13}{2020-01-02}{longtable-2020-01-07.sty}
%<package>\DeclareCurrentRelease{}{2020-02-07}
@@ -37,7 +38,7 @@
%<driver> \ProvidesFile{longtable.drv}
% \fi
% \ProvidesFile{longtable.dtx}
- [2023-11-01 v4.19 Multi-page Table package (DPC)]
+ [2024-04-26 v4.20 Multi-page Table package (DPC)]
%
% \iffalse
%<*driver>
@@ -1048,6 +1049,14 @@
\if@twocolumn
\LT@err{longtable not in 1-column mode}\@ehc
\fi
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/vmode/begin}%
+% \end{macrocode}
+%
+% \begin{macrocode}
\begingroup
% \end{macrocode}
% Check for an optional argument.
@@ -1056,7 +1065,14 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
% \begin{macro}{\LT@array}
+% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
+% \end{macrocode}
+%
% Start setting the alignment.
% Based on "\@array" from the \LaTeX\ kernel
% and the \package{array} package.
@@ -1066,7 +1082,43 @@
% so that "\caption" works correctly.
% \begin{macrocode}
\def\LT@array[#1]#2{%
- \refstepcounter{table}\stepcounter{LT@tables}%
+% \end{macrocode}
+%
+% With respect to tagging we have a complicated situation with
+% longtable. When at the begin the \cs{endhead},
+% \cs{endfirsthead}, \cs{endfoot} and \cs{endlastfoot} are used to
+% setup head and foot they create each a structure subtree with one or
+% more rows. From these structures we want to keep at most two (head
+% and foot) and move the foot to the end of the table. When the head
+% and foot boxes are (re)inserted on following pages we want to mark
+% them up as artifact with the exception of the head at the begin and
+% the foot box at the end.
+%
+% TODO: When a line is killed the structure subtree is there already
+% too and must be removed. If hard to do, then maybe at first warn if the
+% construction is used.
+%
+% \cs{LT@array} is executed in a group, so we can disable para-tagging here.
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/init}
+ \@kernel@refstepcounter{table}\stepcounter{LT@tables}
+% \end{macrocode}
+% The target is created rather late and a \cs{label} can come earlier,
+% so we have to define \cs{@currentHref} explicitly. We can't currently
+% assume that \cs{theHtable} is defined always.
+% \begin{macrocode}
+ \tl_gset:Ne \@currentHref {table.\cs_if_exist_use:N\theHtable}
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_gzero_row_count:
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/longtable/init}
% \end{macrocode}
% Set up the glue around the table if an optional argument given.
% \begin{macrocode}
@@ -1101,17 +1153,18 @@
% here so that you can load the \package{array} package before or after
% \package{longtable}.
% \begin{macrocode}
- \let\LT@@tabarray\@tabarray
- \let\LT@@hl\hline
+ \let\LT@@@@tabarray\@tabarray
+ \let\LT@@@@hl\hline
\def\@tabarray{%
- \let\hline\LT@@hl
+ \let\hline\LT@@@@hl
% \end{macrocode}
%\begin{verbatim}
% \let\multicolumn\LT@mcol
%\end{verbatim}
% \begin{macrocode}
- \LT@@tabarray}%
- \let\\\LT@tabularcr\let\tabularnewline\\%
+ \LT@@@@tabarray}%
+ \let\\\LT@tabularcr
+ \let\tabularnewline\\%
\def\newpage{\noalign{\break}}%
% \end{macrocode}
% \changes{v4.05}{1996/11/12}
@@ -1128,8 +1181,8 @@
% \end{macrocode}
%
% \changes{v4.08}{1998/01/20}
-% {Move \cs{@endpbox} definition earlier and define \cs{@@endpbox}
-% and \cs{@@startpbox} for non-array case. tools/2736}
+% {Move \cs{@endpbox} definition earlier and define \cs{@@@@endpbox}
+% and \cs{@@@@startpbox} for non-array case. tools/2736}
% \begin{macrocode}
\let\@endpbox\LT@endpbox
% \end{macrocode}
@@ -1142,8 +1195,8 @@
\let\@acol\@tabacol
\let\@classz\@tabclassz \let\@classiv\@tabclassiv
\def\@startpbox{\vtop\LT@startpbox}%
- \let\@@startpbox\@startpbox
- \let\@@endpbox\@endpbox
+ \let\@@@@startpbox\@startpbox
+ \let\@@@@endpbox\@endpbox
\let\LT@LL@FM@cr\@tabularcr
\else
% \end{macrocode}
@@ -1172,6 +1225,11 @@
\begingroup
\@mkpream{#2}%
% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_count_table_cols:
+% \end{macrocode}
% We need to rename "\@preamble" here as F.M.'s scheme uses
% "\global", and we may need to nest "\@mkpream", eg for
% "\multicolumn"
@@ -1180,6 +1238,11 @@
% \begin{macrocode}
\xdef\LT@bchunk{%
% \end{macrocode}
+% We aren't inside any row when a chunk starts.
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_inbetween_rows:
+% \end{macrocode}
% \changes{v4.00}{1996/04/08}
% {(DK) Increment Chunk counter}
% \begin{macrocode}
@@ -1205,7 +1268,21 @@
% \begin{macrocode}
\tabskip\LTleft \noexpand\halign to\hsize\bgroup
% \tabskip\LTleft\halign to\hsize\bgroup
- \tabskip\z@ \@arstrut \@preamble \tabskip\LTright \cr}%
+ \tabskip\z@ \@arstrut
+% \end{macrocode}
+% Insert the tagging socket to start the row and initialize the cell
+% data for the row.
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/row/begin}%
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_init_cell_data_for_row:
+% \end{macrocode}
+% \begin{macrocode}
+ \@preamble \tabskip\LTright \cr}%
\endgroup
% \end{macrocode}
% Find out how many columns we have (store in "\LT@cols").
@@ -1220,11 +1297,57 @@
% A few more internal commands for \env{longtable}.
% \begin{macrocode}
\m@th\let\par\@empty
- \everycr{}\lineskip\z@\baselineskip\z@
+% \end{macrocode}
+% Tagging socket and conditional
+% \begin{macrocode}
+ \everycr{%
+ \noalign{%
+% \end{macrocode}
+% In \pkg{longtable} we have a bunch of extra \cs{cr}s that are
+% executed whenever a chunk ends. In that case they should not
+% increment the main row counter, sigh.
+%
+% TODO: At the moment this tracing still exposes the internal row counter!
+% \begin{macrocode}
+ \@@_trace:n {--longtable-->~chunk~row:~ \the\LT@rows \space
+ row:~ \the\g_@@_row_int \space
+ column:~ \the\g_@@_col_int
+ }
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \tbl_if_row_was_started:T
+ {
+ \UseTaggingSocket{tbl/row/end}
+% \end{macrocode}
+% The next setting prevents any of the additional \cs{cr}s at the end of the
+% chunk to add another /TR. Then once we really start a new chunk
+% it gets incremented so\ldots
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_inbetween_rows:
+ }
+% \end{macrocode}
+% And for the same reason such \cs{cr}s should not increment the
+% main row counter (but it has to be incremented after the preamble
+% of a chunk), so here we test against \cs{LT@rows} which is
+% \cs{LTchunksize} at the end of a chunk.
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \int_compare:nNnT \LT@rows < \LTchunksize
+ { \tbl_gincr_row_count: } % next is row about to start
+ }%
+ }%
+% \end{macrocode}
+% \begin{macrocode}
+ \lineskip\z@\baselineskip\z@
% \end{macrocode}
% Start the first chunk.
% \begin{macrocode}
\LT@bchunk}
+\ExplSyntaxOff
+%<@@=>
% \end{macrocode}
% \end{macro}
%
@@ -1251,6 +1374,11 @@
% force the page-breaker to wake up. The second "\endgraf" is there so
% that "\pagetotal" is updated and so takes "\LTpre" into account.
% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% \begin{macrocode}
\def\LT@start{%
\let\LT@start\endgraf
\endgraf\penalty\z@\vskip\LTpre\endgraf
@@ -1334,7 +1462,7 @@
% \changes{v3.14}{1995/05/02}
% {Set \cs{@colroom}, for tools/1584}
% \begin{macrocode}
- \global\@colroom\@colht
+ \global\@colroom\@colht
% \end{macrocode}
% If the foot is non empty, reduce the "\vsize" and "\@colroom"
% accordingly.
@@ -1342,24 +1470,46 @@
% {Rearrange vertical space tests for tools/3512 (floats on same page)}
% \begin{macrocode}
\ifvoid\LT@foot\else
-% \advance\vsize-\ht\LT@foot
\global\advance\vsize-\ht\LT@foot
\global\advance\@colroom-\ht\LT@foot
\dimen@\pagegoal\advance\dimen@-\ht\LT@foot\pagegoal\dimen@
\maxdepth\z@
\fi
% \end{macrocode}
+%
+% \begin{macrocode}
+ \MakeLinkTarget{table}
+% \end{macrocode}
% Put the table head on the page, and then switch to the new output
% routine.
% \changes{v4.11}{2004/02/01}
% {\cs{nobreak}, for tools/3484}
% \begin{macrocode}
\ifvoid\LT@firsthead\copy\LT@head\else\box\LT@firsthead\fi\nobreak
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/longtable/head}
+% \end{macrocode}
+%
+% \begin{macrocode}
\output{\LT@output}}
+\ExplSyntaxOff
+%<@@=>
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
% \begin{macro}{\endlongtable}
+%
+% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
+% \end{macrocode}
+%
% Called by "\end{longtable}".
% \begin{macrocode}
\def\endlongtable{%
@@ -1370,11 +1520,23 @@
% been shortened, or the table numbering has gone awry). In that case
% we at least start collecting valid new information with the last
% chunk of this table, by removing the width constraint.
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \tbl_crcr:n {endlongtable}
+% \end{macrocode}
+%
% \changes{v4.01}{1996/04/11}
% {(DPC) use \cs{noalign} to sneak in \cs{LT@entry@chop}}
% \begin{macrocode}
- \crcr
\noalign{%
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/longtable/finalize}
+% \end{macrocode}
+%
+% \begin{macrocode}
\let\LT@entry\LT@entry@chop
\xdef\LT@save@row{\LT@save@row}}%
\LT@echunk
@@ -1414,10 +1576,10 @@
% \changes{v4.04}{1996/05/24}
% {Use \cs{LT@final@warn}}
% \begin{macrocode}
- \ifx\LT@save@row\LT@@save@row
+ \ifx\LT@save@row\LT@@@@save@row
\else
- \LT@warn{Column \@width s have changed\MessageBreak
- in table \thetable}%
+ \LT@warn{Column~ widths~ have~ changed\MessageBreak
+ in~ table~ \thetable}%
\LT@final@warn
\fi
% \end{macrocode}
@@ -1449,7 +1611,15 @@
% \end{macrocode}
% Footnotes. As done in the \package{multicol} package.
% \begin{macrocode}
- \ifvoid\footins\else\insert\footins{}\fi}
+ \ifvoid\footins\else\insert\footins{}\fi
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/vmode/end}%
+}
+\ExplSyntaxOff
+%<@@=>
% \end{macrocode}
% \end{macro}
%
@@ -1518,6 +1688,10 @@
\protected\def\LT@tabularcr{%
\relax\iffalse{\fi\ifnum0=`}\fi
\@ifstar
+% \end{macrocode}
+% TODO: as we replace crcr later in one case, we probably have to
+% implement some further logic there!
+% \begin{macrocode}
{\def\crcr{\LT@crcr\noalign{\nobreak}}\let\cr\crcr
\LT@t@bularcr}%
{\LT@t@bularcr}}
@@ -1544,8 +1718,13 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
% \begin{macro}{\LT@t@bularcr}
% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
\def\LT@t@bularcr{%
% \end{macrocode}
% Increment the counter, and do \env{tabular}'s "\\" or finish the
@@ -1555,6 +1734,13 @@
% \begin{macrocode}
\global\advance\LT@rows\@ne
\ifnum\LT@rows=\LTchunksize
+% \end{macrocode}
+% At the end of the chunk \verb=\\= is doing something special and
+% so we lose \verb=\tbl_count_missing_cells:n=. Below is about the
+% right place to add it do this code branch.
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_count_missing_cells:n {echunk}
\gdef\LT@setprevdepth{%
\prevdepth\z@
\global\let\LT@setprevdepth\relax}%
@@ -1563,6 +1749,8 @@
\ifnum0=`{}\fi
\expandafter\LT@LL@FM@cr
\fi}
+\ExplSyntaxOff
+%<@@=>
% \end{macrocode}
% \end{macro}
%
@@ -1943,7 +2131,9 @@
% This code is based on "\cline". Two copies of the line are produced,
% as described above.
% \begin{macrocode}
-\def\LT@@hline{%
+%<@@=tbl>
+\ExplSyntaxOn
+\def\LT@@@@hline{%
\ifx\@let@token\hline
\global\let\@gtempa\@gobble
\gdef\LT@sep{\penalty-\@medpenalty\vskip\doublerulesep}%
@@ -1954,11 +2144,25 @@
\ifnum0=`{\fi}%
\multispan\LT@cols
\unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr
- \noalign{\LT@sep}%
+% \end{macrocode}
+% Don't update the row counter, or rather undo the update done in \cs{everycr}:
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \noalign{
+ \tbl_gdecr_row_count:
+ \LT@sep}
\multispan\LT@cols
\unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr
- \noalign{\penalty\@M}%
+% \end{macrocode}
+% Same here.
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \noalign{
+ \tbl_gdecr_row_count:
+ \penalty\@M}
\@gtempa}
+\ExplSyntaxOff
+%<@@=>
% \end{macrocode}
% \end{macro}
%
@@ -2049,13 +2253,15 @@
% \begin{macro}{\LT@output}
% Actually this is not so bad, with FM leading the way.
% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
\def\LT@output{%
\ifnum\outputpenalty <-\@Mi
\ifnum\outputpenalty > -\LT@end@pen
% \end{macrocode}
% If this was a float or a marginpar we complain.
% \begin{macrocode}
- \LT@err{floats and marginpars not allowed in a longtable}\@ehc
+ \LT@err{floats~ and~ marginpars~ not~ allowed~ in~ a~ longtable}\@ehc
\else
% \end{macrocode}
% We have reached the end of the table, on the scroll at least,
@@ -2103,6 +2309,13 @@
% \begin{macrocode}
\unvbox\z@\box\ifvoid\LT@lastfoot\LT@foot\else\LT@lastfoot\fi
% \end{macrocode}
+% Handle foot box when tagging:
+%
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/longtable/foot}
+% \end{macrocode}
+%
% End of "\ifnum\outputpenalty > -\LT@end@pen".
% \begin{macrocode}
\fi
@@ -2114,6 +2327,15 @@
% If we have not reached the end of the table,
% \begin{macrocode}
\setbox\@cclv\vbox{\unvbox\@cclv\copy\LT@foot\vss}%
+% \end{macrocode}
+%
+% Handle foot box when tagging:
+% \changes{v4.19}{2023/12/16}{Support for tagged PDF}
+% \begin{macrocode}
+ \UseTaggingSocket{tbl/longtable/foot}
+% \end{macrocode}
+%
+% \begin{macrocode}
\@makecol
\@outputpage
% \end{macrocode}
@@ -2133,8 +2355,15 @@
% \begin{macrocode}
\fi}
% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+%<@@=>
+% \end{macrocode}
% \end{macro}
%
+%
+%
% \subsection{Commands for the table head and foot}
%
% \begin{macro}{\LT@end@hd@ft}
@@ -2142,20 +2371,86 @@
% box specified by "#1". Issue an error if the table has already
% started. Then start a new chunk.
% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
\def\LT@end@hd@ft#1{%
+% \end{macrocode}
+%
+% This command is used to store the head and foot boxes.
+% We need to retrieve and store the row so that we can clean
+% up the structure in the finalize code.
+%
+% To handle missing columns in the header we need this:
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_if_row_was_started:TF
+ {
+% \end{macrocode}
+% TODO: This is exposing internal counters, so it should be encapsulated
+% in some interface command (but I'm not sure what that should be
+% called, so not done yet.
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_count_missing_cells:n {head/foot}
+ \int_step_inline:nn
+ { \LT@rows + 1 }
+ {
+ \seq_gput_left:ce
+ {g_@@_\cs_to_str:N #1 _rows_seq }
+ { \int_eval:n {\g_@@_row_int + 1 - ##1 } }
+ }
+% \end{macrocode}
+% We also have to set the chunk rows to its max value before
+% calling \cs{LTechunk} so that we don't get extra increments of
+% the main row counter due to \cs{everycr}.
+% \begin{macrocode}
+ \int_gset:Nn \LT@rows { \LTchunksize }
+ }
+% \end{macrocode}
+
+% If we are still in column zero then we had an empty \cs{endhead}
+% and so making any assignment, etc., would start a row --- something we don't want.
+% To get out of this trap we run \cs{crcr} (which would normally
+% come inside \cs{LT@echunk}. That will then trigger \cs{everycr}
+% and update row counter unnecessarily, but now we have a defined state, so
+% we can use \cs{noalign} to undo that.
+% We also change \cs{LT@rows} so that further \cs{cr}s do not do
+% any harm (as explained above.
+%
+% The \cs{crcr} inside \cs{LT@echunk} will be bypassed in that case
+% as we have just executed a \cs{crcr} and are still in scanning modus for
+% \cs{omit} or \cs{noalign}.
+% \begin{macrocode}
+ {
+ \crcr
+ \noalign{
+% \end{macrocode}
+%
+% \changes{v4.19}{2023/12/16}{Managing cell indexes}
+% \begin{macrocode}
+ \tbl_gdecr_row_count: % undo the increment
+ \int_gset:Nn \LT@rows { \LTchunksize }
+ }
+ }
\LT@echunk
% \end{macrocode}
% Changed from "\relax" to "\endgraf" at V3.04, see "\LT@start".
% \begin{macrocode}
\ifx\LT@start\endgraf
\LT@err
- {Longtable head or foot not at start of table}%
- {Increase LTchunksize}%
+ {Longtable~ head~ or~ foot~ not~ at~ start~ of~ table}%
+ {Increase~ LTchunksize}%
\fi
\setbox#1\box\z@
+ \@@_trace:n {-->>~ Saving~\noexpand#1}
\LT@get@widths
\LT@bchunk}
% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+%<@@=>
+% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\endfirsthead}
@@ -2255,6 +2550,24 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
+%
+% Some variables need for the tagging support.
+% \begin{macrocode}
+%<@@=tbl>
+\ExplSyntaxOn
+ \seq_new:N \g_@@_LT@firsthead_rows_seq
+ \seq_new:N \g_@@_LT@head_rows_seq
+ \seq_new:N \g_@@_LT@lastfoot_rows_seq
+ \seq_new:N \g_@@_LT@foot_rows_seq
+\ExplSyntaxOff
+%<@@=>
+% \end{macrocode}
+%
+%
+%
% \begin{macrocode}
%</package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/tools/longtable.ins b/Master/texmf-dist/source/latex/tools/longtable.ins
index 5c3ad270638..60b74615718 100644
--- a/Master/texmf-dist/source/latex/tools/longtable.ins
+++ b/Master/texmf-dist/source/latex/tools/longtable.ins
@@ -3,7 +3,7 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2023
+%% Copyright (C) 1993-2024
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug
reports for it can be opened at https://latex-project.org/bugs/
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2023
+Copyright (C) 1993-2024
The LaTeX Project and any individual authors listed elsewhere
in this file.
diff --git a/Master/texmf-dist/source/latex/tools/multicol.dtx b/Master/texmf-dist/source/latex/tools/multicol.dtx
index 2676d03aa18..4d864480029 100644
--- a/Master/texmf-dist/source/latex/tools/multicol.dtx
+++ b/Master/texmf-dist/source/latex/tools/multicol.dtx
@@ -86,11 +86,10 @@
%<*dtx>
\ProvidesFile{multicol.dtx}
%</dtx>
-%<package>\NeedsTeXFormat{LaTeX2e}[2018-04-01]
-%<package>
-%<package>\providecommand\DeclareRelease[3]{}
-%<package>\providecommand\DeclareCurrentRelease[2]{}
%<package>
+% For any rollback before 2017 load the 2017 version and hope for the best:
+%<package>\DeclareRelease{}{1994-06-01}{multicol-2017-04-11.sty}
+%
%<package>\DeclareRelease{}{2017-04-11}{multicol-2017-04-11.sty}
%<package>\DeclareRelease{v1.8}{2019-10-01}{multicol-2019-10-01.sty}
%<package>\DeclareCurrentRelease{}{2021-11-15}
@@ -99,10 +98,10 @@
%<driver> \ProvidesFile{multicol.drv}
% \fi
% \ProvidesFile{multicol.dtx}
- [2023/03/30 v1.9f multicolumn formatting (FMi)]
+ [2024/05/23 v1.9h multicolumn formatting (FMi)]
+%
%
%
-%%
%
% \changes{v1.9c}{2021/11/30}{Added rollback to v1.8}
% \changes{v1.5n}{1997/06/05}{Applied improvement of documentation,
@@ -919,9 +918,22 @@
% And we don't show macro names in the margin.
% \begin{macrocode}
\setcounter{IndexColumns}{4}
-\let\DescribeMacro\SpecialUsageIndex
-\let\DescribeEnv\SpecialEnvIndex
-\renewcommand\PrintMacroName[1]{}
+% \end{macrocode}
+%
+% The following redefinitions have to be moved until after the
+% preamble because version 3 of \pkg{doc} resets them after the
+% premable (this is tmp, because \pkg{hypdoc} is not yet
+% integrated, but as we all know, tmp solutions have a tendency to
+% survive for a long time\ldots).
+% \begin{macrocode}
+\AddToHook{begindocument}{%
+ \let\DescribeMacro\SpecialUsageIndex
+ \let\DescribeEnv\SpecialEnvIndex
+ \renewcommand\PrintMacroName[1]{}%
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
\CodelineIndex
%\DisableCrossrefs % Partial index
\RecordChanges % Change log
@@ -1082,7 +1094,7 @@
% better test for this situation. Otherwise, we will get a \TeX{}
% stack overflow as this would generate a self-referencing definition.
% \changes{v1.6e}{2004/02/14}{Avoid self-referencing definition of
-% \cs{@footnotetext} (pr/3618)}.
+% \cs{@footnotetext} (pr/3618)}
% \begin{macrocode}
\ifx\@footnotetext\mult@footnotetext
\else
@@ -2376,7 +2388,7 @@
% If |\raggedcolumns| is in force we add a |vfill| at the bottom by
% unboxing the split box.
% But we need to unbox anyway to ensure that at the end of the box
-% we do not have unwanted space. This can sneak in in certain
+% we do not have unwanted space. This can sneak in, in certain
% situations, for example, if two lists follow each other and we
% break between them. While such space is usually zero it still has
% an effect because it hides depth of the last line in the column
@@ -2925,7 +2937,11 @@
% We start by setting the kept marks by updating them with any
% marks from this box. This has to be done \emph{before} we add a
% penalty of $-10000$ to the top of the box, otherwise only an
-% empty box will be considered.
+% empty box will be considered. But even that is not enough: the box
+% may contain \cs{columnbreak}s in which case doing some artifical
+% splitting to get the marks out still fails to see all marks
+% unless we take some special precaution in \cs{get@keptmarks}
+% (which is now done).
% \changes{v1.5h}{1994/08/26}{Get kept marks first}
% \begin{macrocode}
\get@keptmarks\mult@box
@@ -3751,8 +3767,15 @@
% everything is split off. As a result |\splitfirstmark| and
% |\splitbotmark| will contain the first and last mark in the box
% respectively.
+%
+% Unfortunately, a simple \cs{vsplit} is not enough if the material
+% contains forced breaks in that case we first have to get rid of
+% those which is why we do this work in a separate macro that can
+% call itself recursively.
+% \changes{v1.9g}{2023/11/10}{Get rid of forced breaks for mark
+% extraction (gh/1130)}
% \begin{macrocode}
- \setbox#1\vsplit#1to\maxdimen
+ \mc@get@all@box@marks #1%
% \end{macrocode}
% Therefore we can now set the kept marks which is a global
% operation and afterwards close the group. This will restore the
@@ -3773,6 +3796,29 @@
% \end{macro}
%
%
+% \begin{macro}{\mc@get@all@box@marks}
+% This macro splits a box to \cs{maxdimen} in order to get at the
+% marks inside. If it turns out that we have a remainder after the
+% split (e.g., if there was a \cs{columnbreak} in the material) we
+% stitch the two parts together again (which omits the forced
+% break) and recurse. Eventually, everything is split off and the
+% split marks will then have the appropriate values.
+% \changes{v1.9g}{2023/11/10}{Get rid of forced breaks for mark
+% extraction (gh/1130)}
+% \begin{macrocode}
+\def\mc@get@all@box@marks #1{%
+ \setbox\@tempboxa\vsplit#1to\maxdimen
+ \ifvoid#1\else
+ \setbox#1\vbox{\unvbox\@tempboxa \unvbox#1}%
+ \mc@get@all@box@marks #1%
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
% \begin{macro}{\set@keptmarks}
% The macro |\set@keptmarks| is responsible for setting
% |\kept@firstmark| and |\kept@botmark|, by checking the current
diff --git a/Master/texmf-dist/source/latex/tools/multicol.ins b/Master/texmf-dist/source/latex/tools/multicol.ins
index fa561e0bb1e..7a7ef27d248 100644
--- a/Master/texmf-dist/source/latex/tools/multicol.ins
+++ b/Master/texmf-dist/source/latex/tools/multicol.ins
@@ -3,7 +3,7 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2023
+%% Copyright (C) 1993-2024
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug
reports for it can be opened at https://latex-project.org/bugs/
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2023
+Copyright (C) 1993-2024
The LaTeX Project and any individual authors listed elsewhere
in this file.
diff --git a/Master/texmf-dist/source/latex/tools/rawfonts.dtx b/Master/texmf-dist/source/latex/tools/rawfonts.dtx
index 4b930f3ea70..3ffa2032c38 100644
--- a/Master/texmf-dist/source/latex/tools/rawfonts.dtx
+++ b/Master/texmf-dist/source/latex/tools/rawfonts.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/shellesc.dtx b/Master/texmf-dist/source/latex/tools/shellesc.dtx
index aa707fe550a..8a556de9229 100644
--- a/Master/texmf-dist/source/latex/tools/shellesc.dtx
+++ b/Master/texmf-dist/source/latex/tools/shellesc.dtx
@@ -1,6 +1,6 @@
% \iffalse
%% Source File: shellesc.dtx
-%% Copyright (C) 2015-2023
+%% Copyright (C) 2015-2024
%%
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/showkeys.dtx b/Master/texmf-dist/source/latex/tools/showkeys.dtx
index c90b3863e1a..b6717950a77 100644
--- a/Master/texmf-dist/source/latex/tools/showkeys.dtx
+++ b/Master/texmf-dist/source/latex/tools/showkeys.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
@@ -22,16 +22,15 @@
% \fi
% \iffalse
%% File: showkeys.dtx Copyright (C) 1992-1997 David Carlisle
-%% File: showkeys.dtx Copyright (C) 2006-2019 David Carlisle, LaTeX Project
+%% File: showkeys.dtx Copyright (C) 2006-2024 David Carlisle, LaTeX Project
%
%<*dtx>
\ProvidesFile{showkeys.dtx}
%</dtx>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>
-%<package>\providecommand\DeclareRelease[3]{}
-%<package>\providecommand\DeclareCurrentRelease[2]{}
-%<package>
+% For every rollback request before 2022 use the 2014 version:
+%<package>\DeclareRelease{}{1994-06-01}{showkeys-2014-10-28.sty}
%<package>\DeclareRelease{}{2014-10-28}{showkeys-2014-10-28.sty}
%<package>\DeclareCurrentRelease{}{2022-06-01}
%<package>
@@ -39,7 +38,7 @@
%<driver> \ProvidesFile{showkeys.drv}
% \fi
% \ProvidesFile{showkeys.dtx}
- [2023/07/08 v3.19 Show cite and label keys (DPC, MH)]
+ [2024/05/23 v3.21 Show cite and label keys (DPC, MH)]
%
% \iffalse
%<*driver>
@@ -417,6 +416,8 @@
% \end{macrocode}
% \changes{v3.02}{1995/03/17}
% {New code for `in label' case.}
+% \changes{v3.20}{2023/12/16}
+% {Avoid adding an extra box layer github/1123}
% If the |\label| is straight after |\item| (|\bibitem| is handled by
% this case as well) then the item label has not been added to the page
% yet. It is hanging around in the box |\@labels| waiting for the
@@ -425,7 +426,7 @@
\global\setbox\@labels\hbox{%
\llap{\SK@lab\SK@lab@relax
\kern\@totalleftmargin\kern\marginparsep}%
- \box\@labels}%
+ \unhbox\@labels}%
% \end{macrocode}
%
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/tools/somedefs.dtx b/Master/texmf-dist/source/latex/tools/somedefs.dtx
index 02653a13939..156621d70e2 100644
--- a/Master/texmf-dist/source/latex/tools/somedefs.dtx
+++ b/Master/texmf-dist/source/latex/tools/somedefs.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/tabularx.dtx b/Master/texmf-dist/source/latex/tools/tabularx.dtx
index 6d59ca4c228..52ee62cad90 100644
--- a/Master/texmf-dist/source/latex/tools/tabularx.dtx
+++ b/Master/texmf-dist/source/latex/tools/tabularx.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
@@ -31,7 +31,7 @@
%<driver> \ProvidesFile{tabularx.drv}
% \fi
% \ProvidesFile{tabularx.dtx}
- [2023/07/08 v2.11c `tabularx' package (DPC)]
+ [2023/12/11 v2.12a `tabularx' package (DPC)]
% \iffalse
%<*driver>
\documentclass{ltxdoc}
@@ -261,6 +261,25 @@
% This behaviour of the package can be customised slightly
% as noted in the documentation of the code section.
%
+% \section{Support for tagged PDF}
+%
+% With version 2.12a the package is made tagging aware, which means that
+% it will automatically produce tagged tables (necessary, for example, for
+% accessibility) if tagging is requested via \cs{DocumentMetadata}.
+%
+% More granular control, e.g., explicitly deciding which cells are
+% header cells, etc., is currently under development, but syntax for
+% this will not appear in this package. Instead it will become
+% available across all tabular-generating packages and then
+% automatically apply here as well.
+%
+% Enabling \LaTeX{} to automatically produce tagged PDF is a long-term
+% project and this is a tiny step in this puzzle. For more information
+% on the project and already available functionality, see
+% \url{https://latex-project.org/publications/indexbytopic/pdf} and
+% \url{https://github.com/latex3/tagging-project}.
+%
+%
% \MaybeStop{}
%
% \section{The Macros}
@@ -269,6 +288,14 @@
%<*package>
% \end{macrocode}
%
+% We only need two changes for tagging support, but they require
+% that a recent \LaTeX{} kernel is used (which should be no problem
+% if \texttt{tools} is distributed in parallel with the kernel.
+% \changes{v2.12a}{2023/12/11}{Require newer LaTeX kernel}
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}[2024/06/01]
+% \end{macrocode}
+%
% \changes{v2.00}{1994/02/07}
% {New Option Handling}
% \begin{macrocode}
@@ -506,7 +533,15 @@
% \begin{macrocode}
\TX@typeout@
{\@spaces Table Width\@spaces Column Width\@spaces X Columns}%
-% \end{macrocode}%
+% \end{macrocode}
+%
+% While we do trial typesetting we suspend any tagging if that is
+% active:
+% \changes{v2.12a}{2023/12/11}
+% {Suspend any tagging while doing trial typesetting}
+% \begin{macrocode}
+ \SuspendTagging {tabularx}%
+% \end{macrocode}
% First attempt. Modify the {\ttfamily X} definition to count {\ttfamily
% X} columns.
% \begin{macrocode}
@@ -523,6 +558,12 @@
\TX@trial{}%
\repeat
% \end{macrocode}
+%
+% And here we restart it again:
+% \begin{macrocode}
+ \ResumeTagging {tabularx}%
+% \end{macrocode}
+%
% One last time, with warnings back on (see appendix D)
% use {\ttfamily tabular*} to put it in a box of the right size, in case
% the algorithm failed to find the correct size.
@@ -737,8 +778,9 @@
% Make the table, and finish the hbox.
% Since v1.06, "\toks@" contains the preamble specification,
% and possible optional argument, as well as the table body.
+%
% \begin{macrocode}
- \expandafter\tabular\the\toks@
+ \expandafter\tabular\the\toks@
\endtabular}%
% \end{macrocode}
% Since v1.05 reset all \LaTeX\ counters, by executing "\TX@ckpt".
@@ -961,6 +1003,7 @@
% \end{macrocode}
% \end{macro}
%
+%
% \begin{macrocode}
%</package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/tools/tabularx.ins b/Master/texmf-dist/source/latex/tools/tabularx.ins
index 6e81e934325..fdce598d379 100644
--- a/Master/texmf-dist/source/latex/tools/tabularx.ins
+++ b/Master/texmf-dist/source/latex/tools/tabularx.ins
@@ -3,7 +3,7 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2023
+%% Copyright (C) 1993-2024
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug
reports for it can be opened at https://latex-project.org/bugs/
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2023
+Copyright (C) 1993-2024
The LaTeX Project and any individual authors listed elsewhere
in this file.
diff --git a/Master/texmf-dist/source/latex/tools/theorem.dtx b/Master/texmf-dist/source/latex/tools/theorem.dtx
index e3a8e90b8c2..a9c3ccae3ed 100644
--- a/Master/texmf-dist/source/latex/tools/theorem.dtx
+++ b/Master/texmf-dist/source/latex/tools/theorem.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/tools.ins b/Master/texmf-dist/source/latex/tools/tools.ins
index 6898faead37..8687d49d7f7 100644
--- a/Master/texmf-dist/source/latex/tools/tools.ins
+++ b/Master/texmf-dist/source/latex/tools/tools.ins
@@ -3,7 +3,7 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2023
+%% Copyright (C) 1993-2024
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -49,7 +49,7 @@ reports for it can be opened at https://latex-project.org/bugs/
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2023
+Copyright (C) 1993-2024
The LaTeX Project and any individual authors listed elsewhere
in this file.
@@ -178,6 +178,13 @@ given in the file `manifest.txt'.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\SimplePackage{shellesc}
+
+% Shell Filee System Queries
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\batchinput{l3sys-query.ins}
+
+
+
% File-Error files
%%%%%%%%%%%%%%%%%%
\generate{%
diff --git a/Master/texmf-dist/source/latex/tools/trace.dtx b/Master/texmf-dist/source/latex/tools/trace.dtx
index 788f8316204..27a39c776b4 100644
--- a/Master/texmf-dist/source/latex/tools/trace.dtx
+++ b/Master/texmf-dist/source/latex/tools/trace.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
diff --git a/Master/texmf-dist/source/latex/tools/varioref.dtx b/Master/texmf-dist/source/latex/tools/varioref.dtx
index e801c54f818..40b3038074f 100644
--- a/Master/texmf-dist/source/latex/tools/varioref.dtx
+++ b/Master/texmf-dist/source/latex/tools/varioref.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
@@ -33,14 +33,15 @@
%%
%
%<package>\NeedsTeXFormat{LaTeX2e}[1995/05/16]
-%<package>\providecommand\DeclareRelease[3]{}
-%<package>\providecommand\DeclareCurrentRelease[2]{}
%<package>
+%
+% For any rollback before 2019 load the 2016 version and hope for the best:
+%<package>\DeclareRelease{}{1994-06-01}{varioref-2016-02-16.sty}
%<package>\DeclareRelease{}{2016-02-16}{varioref-2016-02-16.sty}
%<package>\DeclareCurrentRelease{}{2019-10-01}
%<package>
%<package>\ProvidesPackage{varioref}
-%<package> [2022/01/09 v1.6f package for extended references (FMi)]
+%<package> [2024/05/23 v1.6g package for extended references (FMi)]
% \fi
%
%%
@@ -144,8 +145,8 @@
%\DescribeMacro\vref The implementation of |\vref| below produces only
% a |\ref| when reference and |\label| are on the same page. It will
% additionally produce one of the strings `on the facing page', `on
-% the preceding page', or `on the following page', if label and
-% reference differ by one and it will produce both |\ref| and
+% the preceding page', or `on the following page' if label and
+% reference differ by one; and it will produce both |\ref| and
% |\pageref| when the difference is larger. The word `facing' is used
% when label and reference both fall onto a double spread. However,
% if a special page numbering scheme is used instead of the usual
@@ -169,7 +170,7 @@
% comes out as ``\ldots~see the example which shows~\ldots'', which
% could be misleading.
%
-% A space in front of |\vpageref| it will be ignored if
+% A space in front of |\vpageref| will be ignored if
% the command doesn't produce any text at all.
%
% But in fact |\vpageref| allows even more control. It has two
@@ -210,7 +211,7 @@
% \DescribeMacro\vrefrange
% This command is similar to |\vref| but it
% takes two mandatory arguments denoting a range to refer to (e.g., a
-% sequences of figures or a sequence of equations, etc.). So if
+% sequence of figures or a sequence of equations, etc.). So if
% |fig:a| is your first figure in the sequence and |fig:c| your last
% you can write
%\begin{verbatim}
@@ -273,8 +274,8 @@
% \DescribeMacro\vpagerefcompare
% \NewIn{2019}
% For this kind of application the package also provides
-% |\vpagerefcompare| as a command that takes four argument: two labels for
-% comparison and a \meta{true} and \meta{false} argument. One of them
+% |\vpagerefcompare| as a command that takes four arguments: two labels
+% for comparison and a \meta{true} and \meta{false} argument. One of them
% is executed depending on whether the two labels are on the same page
% or on different pages. With its help the above definition could be
% shortened to
@@ -293,8 +294,9 @@
% Another command for conditional processing is |\vpagerefnearby|. It
% takes three arguments: a label and a \meta{true} and \meta{false}
% argument. It compares the page reference to the label with the
-% current page number and if both are Arabic number and only differ by
-% $\pm1$ the \meta{true} argument is executed otherwise the
+% current page number; if each of these is a positive integer
+% (expressed in Arabic numerals) and they differ by at most
+% $\pm1$, the \meta{true} argument is executed, otherwise the
% \meta{false} argument. In other words it tells you if a |\vpageref|
% to the label would result in a textual reference to the previous,
% current or next page.\footnote{There is also a
@@ -320,11 +322,11 @@
% versions of the macros which do not add any space before the
% generated text (they do nevertheless remove space at the left).
%
-% However, that too has problems (one is that \pkg{hyperref}
+% However, that too has problems: one is that \pkg{hyperref}
% \ChangedIn{2019}
-% introduced the star forms as a means to generating references
-% without hyperlinks (which is clearly the more important
-% application).
+% introduced the star forms as a means of generating references
+% without hyperlinks, which is clearly the more important
+% application.
% So these days I recommend to always call the package with the option
% \option{nospace} which prevents \pkg{varioref} from messing with the
% space in front. Of course you are then responsible to always add it
@@ -381,7 +383,7 @@
% label and reference fall onto the same page, but prefer reference to
% page numbers otherwise then |\thevpagerefnum| can be used. This macro
% hold the current page ``number'' when |\vpageref| and friends are
-% executed. Thus, by defining, for example
+% executed. Thus, by defining, for example,
%\begin{verbatim}
%\renewcommand\reftextfaceafter {on page~\thevpagerefnum}
%\renewcommand\reftextfacebefore{on page~\thevpagerefnum}
@@ -436,7 +438,7 @@
%\DescribeMacro\reftextafter
%\DescribeMacro\reftextfaceafter Backward references use
% |\reftextbefore| if the label is on the preceding page but invisible
-% and |\reftextfacebefore| if it is one the facing page (i.e., if the
+% and |\reftextfacebefore| if it is on the facing page (i.e., if the
% current page number is odd). Similarly |\reftextafter| is used
% when the label comes on the next page but one has to turn the page
% and |\reftextfaceafter| if it is on the following but facing page.
@@ -447,7 +449,7 @@
%\DescribeMacro\reftextfaraway Finally we have |\reftextfaraway| which
% is used whenever label and reference differ by more than one or when
% they aren't numeric. This macro is a bit different because it takes
-% one argument, the symbolic reference string so that one cane make
+% one argument, the symbolic reference string, so that one can make
% use of |\pageref| in its replacement text.
%
%
@@ -521,7 +523,7 @@
% and \option{nospace}. While the former is the default to allow
% \NewIn{2019}
% documents written in the last twenty years to continue to work
-% correctly, I nowadays, suggest that you always use the package with
+% correctly, I nowadays suggest that you always use the package with
% the option \option{nospace}. This will stop \pkg{varioref} from
% meddling with the spaces preceding commands and thus make the star
% forms |\vref*| and |\vpageref*| unnecessary.
@@ -536,7 +538,7 @@
% Defining commands like the ones described above poses some
% interesting problems. Suppose, for example, that a generated text
% like `on the next page' gets broken across pages. If this happens it
-% is very difficult to find an acceptable solution and in fact can
+% is very difficult to find an acceptable solution and it can, in fact,
% even result in a document that will always change from one state to
% another (i.e., inserting one string, finding that this is wrong,
% inserting another string on the next run which makes the first
@@ -699,7 +701,7 @@
% \begin{macro}{\reftextbefore}
% \begin{macro}{\reftextcurrent}
% \label{reftextbefore} The options do set the macros that
-% generate the textual strings. Note, that they do not start with a
+% generate the textual strings. Note that they do not start with a
% space, the space is already added in the main macro below.
% \changes{v1.2a}{1998/08/22}{Added American defaults for
% \cs{reftextpagerange} and \cs{reftextlabelrange}}
@@ -838,7 +840,7 @@
% the noun (clause); bertentangan is ``opposite'' in the sense of
% ``facing''; berikutnya is ``next'' (in this context - actually
% next-to-this, literally); berikutnya also translates as ``following
-% this'' sebelumnya is ``preceding''; also ``previous'' ``ini'' translates,
+% this''; sebelumnya is ``preceding'', also ``previous''; ``ini'' translates,
% literally, as ``this'' but is also used in the sense of current page.
% \changes{v1.4o}{2005/12/02}{Bahasa Malaysia defaults added.}
% \begin{macrocode}
@@ -1036,7 +1038,7 @@
\let\vrefrangeformat\vrefrangedefaultformat
}}
% \end{macrocode}
-% Default string for dutch have been contributed by Frank Poppe
+% Default strings for Dutch have been contributed by Frank Poppe
% (\verb=POPPE@SWOV.NL=).
% This option currently supports one additional string macro
% |\refpagename| so that you can easily change to |bladzijde|
@@ -1124,9 +1126,9 @@
\let\vrefrangeformat\vrefrangedefaultformat
}}
% \end{macrocode}
-% The finnish strings were suggested by Matti Rintala
+% The Finnish strings were suggested by Matti Rintala
% (\verb=bitti@cs.tut.fi=) and Hillevi Gavel
-% \verb=Hillevi.Gavel@mdh.se=.
+% (\verb=Hillevi.Gavel@mdh.se=).
% \changes{v1.0m}{1994/09/23}{Added finnish strings}
% \changes{v1.4o}{2005/11/07}{Added a few more finnish strings}
% \begin{macrocode}
@@ -1200,10 +1202,10 @@
}}
% \end{macrocode}
% There are no good variants for German (I think and still think but
-% this is a matter of taste :-).
+% this is a matter of taste :-)).
% \changes{v1.0b}{1994/01/31}{Replace in incorrect `def by `let}
% The following definitions were recently suggested to me but since
-% the original are in for a long time i don't want to change them
+% the originals have been there for a long time I don't want to change them
% now since that could make a lot of documents change their formatting.
% If you fancy them, add a redefinition of the corresponding macro(s)
% to the preamble of your document.
@@ -1935,7 +1937,7 @@
% \end{macrocode}
% But if \texttt{nospace} is in force we simply use the same space
% value that was used in the source document (unless that was zero
-% or non-existent.
+% or non-existent).
% \begin{macrocode}
\ifdim\@tempskipa=\z@ \else
\hskip\@tempskipa
@@ -1978,7 +1980,7 @@
% \begin{macrocode}
\vrefpagenum\thevpagerefnum{#3}%
% \end{macrocode}
-% Now after the internal label has served its purpose if would be
+% Now after the internal label has served its purpose it would be
% nice to free the memory it occupies by using something like
% \begin{verbatim}
% \global\expandafter\let
@@ -2008,7 +2010,7 @@
\fi
\else
% \end{macrocode}
-% If |#2| is empty we do nothing otherwise we insert it followed by
+% If |#2| is empty we do nothing, otherwise we insert it followed by
% a space.
% \begin{macrocode}
\def\@tempc{#2}%
@@ -2017,7 +2019,7 @@
\fi
% \end{macrocode}
% Now we check if the page number of the referenced object (stored
-% in |\thevpagerefnum| is a single positive number.
+% in |\thevpagerefnum|) is a single positive number.
% \begin{macrocode}
\is@pos@number\thevpagerefnum
{%
@@ -2032,7 +2034,7 @@
}%
% \end{macrocode}
% If it is not a positive number we assign the largest possible
-% number to |\@tempcnta| and thereby pretending that label and
+% number to |\@tempcnta|, thereby pretending that label and
% reference are miles away from each other.
% \begin{macrocode}
{\@tempcnta\maxdimen}%
@@ -2049,7 +2051,7 @@
% Thus if the object falls onto an odd page then the reference is
% on the facing even page (and so we insert |\reftextfaceafter|),
% otherwise the object can not be seen from the reference (and we
-% in insert |\reftextafter|). Don't be surprised if we are not
+% insert |\reftextafter|). Don't be surprised if we are not
% using |\thevpagerefnum| in the check. Since |\@tempcnta| has the same
% value it is faster to use the register instead of parsing the
% macro contents anew.
@@ -2061,7 +2063,7 @@
% used.
% Since the value of |\if@twoside| is evaluated before reading in
% packages we could do better (saving some tokens) by defining
-% the current macro in dependence of this boolean.
+% the current macro depending on this boolean.
% \begin{macrocode}
\if@twoside
\reftextfaceafter
@@ -2075,11 +2077,11 @@
% If the object is not on the page following the reference we check
% if it is on the page before the reference. In \LaTeX{} this
% situation is not too common, for example with floats it normally
-% does not occur, but of course it isn't impossible if you more
+% does not occur, but of course it isn't impossible if you have more
% than one reference to the same object, or if you have back
% references to sections, theorems, etc. To test this we now
% subtract two from the current value of |\@tempcnta| (which was
-% set to one higher as the reference page number). Note, that
+% set to one higher as the reference page number). Note that
% subtraction is also possible if the value was |\maxdimen| --- we
% still get something that is much larger than any sensible page
% number.
@@ -2131,7 +2133,7 @@
\reftextfaraway{#3}}%
\fi
% \end{macrocode}
-% Finally we generate the internal label so that it can be check on
+% Finally, we generate the internal label so that it can be checked on
% the next run. This means that we compare the position after the
% string with the position of the referenced object. There is one
% thing to note: to conserve space we locally make |\@currentlabel|
@@ -2252,8 +2254,8 @@
% The star form is easy (and just a convenient shortcut), just call
% |\ref| followed by |\vpageref| and pass the optional argument to
% the latter. We don't support the second optional argument of
-% |\vpageref|, it that is needed one has to call both commands
-% explicitly
+% |\vpageref|, if that is needed one has to call both commands
+% explicitly.
% \changes{v1.6a}{2019/08/25}{Command added to support hyperref better}
% \changes{v1.6e}{2020/07/25}{Changed for Japanese (gh/352)}
% \begin{macrocode}
@@ -2264,7 +2266,7 @@
%
% \begin{macro}{\vrefformat,\vrefdefaultformat}
% Japanese needs a different word order in \cs{vref@star} so this
-% is separated out o that it can be changed on language level.
+% is separated out so that it can be changed at the language level.
% \changes{v1.6e}{2020/07/25}{Macro added (gh/352)}
% \begin{macrocode}
\def\vrefdefaultformat#1#2{%
@@ -2293,7 +2295,7 @@
\unskip \nobreakspace
\fi
% \end{macrocode}
-% The use of|\nobreakspace| or |~| after the |\unskip| means that
+% The use of |\nobreakspace| or |~| after the |\unskip| means that
% this command will always produce a normal space while
% something like |\nobreak\space| will
% react to settings of |\nonfrenchspacing|.
@@ -2341,10 +2343,10 @@
% Now we have to check whether or not the whole string was parsed
% into that register or some remainder was left over. Since we have
% added a |\@nil| token at the very end we can use that to delimit
-% the argument of |\is@pos@num@|. Note, that the added space in
+% the argument of |\is@pos@num@|. Note that the added space in
% |\is@pos@number| \vpageref[above]{isposnumber} gets parsed away
% by the counter assignment. If it would be missing, and the full
-% string would consist of a number, \TeX{}would try to replace
+% string would consist of a number, \TeX{} would try to replace
% |\@nil| by its definition to see if it would contain additional
% digits and thus we would be in trouble at this point.
% \begin{macrocode}
@@ -2389,7 +2391,7 @@
%
% \begin{macro}{\fullrefformat,\fullrefdefaultformat}
% Japanese needs a different word order in \cs{fullref} so this
-% is separated out o that it can be changed on language level.
+% is separated out so that it can be changed at the language level.
% \changes{v1.6e}{2020/07/25}{Macro added (gh/352)}
% \begin{macrocode}
\def\fullrefdefaultformat#1{%
@@ -2523,7 +2525,7 @@
%
% \begin{macro}{\vrefrangeformat,\vrefrangedefaultformat}
% Japanese needs a different word order in \cs{vrefrange} so this
-% is separated out o that it can be changed on language level.
+% is separated out so that it can be changed at the language level.
% \changes{v1.6d}{2020/07/20}{Macro added (gh/352)}
% \begin{macrocode}
\def\vrefrangedefaultformat#1#2#3{%
@@ -2558,7 +2560,7 @@
%
% \begin{macro}{\Vrefformat,\Vrefdefaultformat}
% Japanese needs a different word order in \cs{Vref} so this
-% is separated out o that it can be changed on language level.
+% is separated out so that it can be changed at the language level.
% \changes{v1.6e}{2020/07/25}{Macro added (gh/352)}
% \begin{macrocode}
\def\Vrefdefaultformat#1#2{%
diff --git a/Master/texmf-dist/source/latex/tools/varioref.ins b/Master/texmf-dist/source/latex/tools/varioref.ins
index dcc41d01766..88527a20ba1 100644
--- a/Master/texmf-dist/source/latex/tools/varioref.ins
+++ b/Master/texmf-dist/source/latex/tools/varioref.ins
@@ -3,7 +3,7 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2023
+%% Copyright (C) 1993-2024
%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
@@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug
reports for it can be opened at https://latex-project.org/bugs/
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2023
+Copyright (C) 1993-2024
The LaTeX Project and any individual authors listed elsewhere
in this file.
diff --git a/Master/texmf-dist/source/latex/tools/verbatim.dtx b/Master/texmf-dist/source/latex/tools/verbatim.dtx
index ebcc010a807..468dead3e83 100644
--- a/Master/texmf-dist/source/latex/tools/verbatim.dtx
+++ b/Master/texmf-dist/source/latex/tools/verbatim.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
@@ -69,6 +69,8 @@
%\fi
%
%
+%
+% \changes{v1.5x}{2024/01/22}{Added TAB marking support to \cs{verbatiminput*}}
% \changes{v1.5u}{2020-07-07}{Typo repair and added a missing comment
% character}
% \changes{v1.5q}{2003/08/22}{Reintroduced \cs{@noligs}, by popular
@@ -508,7 +510,7 @@
%<*package>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{verbatim}
- [2023-11-06 v1.5v LaTeX2e package for verbatim enhancements]
+ [2024-01-22 v1.5x LaTeX2e package for verbatim enhancements]
\@ifundefined{verbatim@@@}{}{\endinput}
% \end{macrocode}
%
@@ -1570,7 +1572,14 @@
% arguments, depending on whether an asterisk follows.
% \begin{macrocode}
\def\verbatiminput{\begingroup
- \@ifstar{\verbatim@input\relax}%
+% \end{macrocode}
+%
+% \changes{v1.5x}{2024/01/22}{Added TAB marking support into the
+% starred version (gh/1245)}
+% If starred, we mark spaces and TABs, the two
+% added pieces are the same as for verbatim*.
+% \begin{macrocode}
+ \@ifstar{\verbatim@input{\@setupverbvisiblespace\@vobeyspaces}}%
{\verbatim@input{\frenchspacing\@vobeyspaces}}}
% \end{macrocode}
% \end{macro}
diff --git a/Master/texmf-dist/source/latex/tools/xr.dtx b/Master/texmf-dist/source/latex/tools/xr.dtx
index be48f5a01b2..daa0778b363 100644
--- a/Master/texmf-dist/source/latex/tools/xr.dtx
+++ b/Master/texmf-dist/source/latex/tools/xr.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
@@ -21,14 +21,49 @@
%
% \fi
% \iffalse
-%% File: xr.dtx Copyright (C) 1993-2019 David Carlisle
+%% File: xr.dtx Copyright (C) 1993-2024 David Carlisle
%
%<package>\NeedsTeXFormat{LaTeX2e}
+%<package>\DeclareRelease{v5}{2023-07-04}{xr-2023-07-04.sty}
+%<package>\DeclareCurrentRelease{}{2024-04-10}
%<package>\ProvidesPackage{xr}
-%<package> [2023-07-04 v5.06 eXternal References (DPC)]
+%<package> [2024-04-10 v6.00 eXternal References (DPC)]
%
%<*driver>
-\documentclass{ltxdoc}
+\documentclass{l3doc}
+% currently missing in l3doc, copied from array.dtx
+\makeatletter
+\def\MaintainedBy#1{\gdef\@maintainedby{#1}}
+\let\@maintainedby\@empty
+\def\MaintainedByLaTeXTeam#1{%
+{\gdef\@maintainedby{%
+This file is maintained by the \LaTeX{} Project team.\\%
+Bug reports can be opened (category \texttt{#1}) at\\%
+\url{https://latex-project.org/bugs.html}.}}}
+\def\@maketitle{%
+ \newpage
+ \null
+ \vskip 2em%
+ \begin{center}%
+ \let \footnote \thanks
+ {\LARGE \@title \par}%
+ \vskip 1.5em%
+ {\large
+ \lineskip .5em%
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par}%
+ \vskip 1em%
+ {\large \@date}%
+ \ifx\@maintainedby\@empty
+ \else
+ \vskip 1em%
+ \fbox{\fbox{\begin{tabular}{@{}l@{}}\@maintainedby\end{tabular}}}%
+ \fi
+ \end{center}%
+ \par
+ \vskip 1.5em}
+\makeatother
\usepackage{xr}
\GetFileInfo{xr.sty}
\begin{document}
@@ -50,44 +85,113 @@
%
% \changes{v5.00}{1993/07/07}
% {First DPC version (by agreement with J-PD). New mechanism
-% (\cmd{\read} instead of \cmd\input).}
+% (\cs{read} instead of \cs{input}).}
%
% \changes{v5.01}{1993/07/20}{Fix bug added by DPC, v5.00 did not import
-% aux files of \cmd\include'ed files. (Reported by J-PD)}
+% aux files of \cs{include}'ed files. (Reported by J-PD)}
%
% \changes{v5.02}{1994/05/28}{Update for LaTeX2e}
% \changes{v5.03}{2018/10/01}{Fix for conditionals in aux file}
% \changes{v5.05}{2019/07/20}{include xcite}
+% \changes{v6.00}{2024/04/10}{merge with xr-hyper}
%
%
% This package implements a system for eXternal References.
-%
+% Version 6.00 merges the \pkg{xr} package and the \pkg{xr-hyper} package.
+% \pkg{xr-hyper} was developed to support the
+% extended label syntax of the \pkg{hyperref} package and to enable active links
+% to the external documents.
+% In the \LaTeX{} release 2023-06-01 the label syntax of \pkg{hyperref}
+% and the \LaTeX{} kernel have been synchronized and there is no longer
+% a need for two packages. The package \pkg{xr-hyper} will be
+% deprecated.
+%
+% The previous version before the merge can be accessed with
+% \begin{verbatim}
+% \usepackage{xr}[=v5]
+% \end{verbatim}
+% or with a rollback date between 2023-07-04 and 2024-04-09
+% \begin{verbatim}
+% \usepackage{xr}[=2024-04-09]
+% \end{verbatim}
+%
+% \section{Usage}
+%
+% \begin{syntax}
+% \cs{externaldocument}\oarg{prefix}\texttt[nocite\texttt]\marg{document}\oarg{url}
+% \end{syntax}
+%
% If one document needs to refer to sections of another, say |aaa.tex|,
% then this package may be loaded in the main file, and the command\\
% |\externaldocument{aaa}|\\
% given in the preamble.
%
-% Then you may use |\ref| and |\pageref| to refer to anything which has
+% Then you may use |\ref| and |\pageref| (or |\nameref| if the
+% package \pkg{nameref} has been loaded to refer to anything which has
% been given a |\label| in either |aaa.tex| or the main document.
+% It is also possible to refer to properties stored with \cs{RecordProperties}.
% You may declare any number of such external documents.
%
% If any of the external documents, or the main document, use the same
% |\label| then an error will occur as the label will be multiply
% defined. To overcome this problem |\externaldocument| has an optional
-% argument. If you declare |\externaldocument[A-]{aaa}|, then all
+% argument \meta{prefix}.
+% If you declare |\externaldocument[A-]{aaa}|, then all
% references from |aaa| are prefixed by |A-|. So for instance, if a
% section of |aaa| had |\label{intro}|, then this could be referenced
% with |\ref{A-intro}|. The prefix need not be |A-|, it can be any
% string chosen to ensure that all the labels imported from external
-% files are unique. Note however that if your style declares certain
-% active characters (|:| in French, |"| in German) then these
-% characters can not usually be used in |\label|, and similarly may not
-% be used in the optional argument to |\externaldocument|.
+% files are unique. Note however that the prefix is expanded and
+% so should not contain commands that are not safe in this context.
%
% As first suggested in Enrico Gregorio's |xcite| package, the current version
% also allows |\cite| to reference |\bibitem| in the external document.
% For compatibility with |xcite|, |\externalcitedocument| is made available
% as an alias for |\externaldocument|
+%
+% Many packages have variant citation commands (natbib,
+% biblatex,....) and the external document may or may not have used
+% hyperref. Because of these differences the citation linking may not
+% always work, it can be disabled by specifying \texttt{[nocite]} after the
+% \meta{prefix}:
+% \begin{verbatim}
+% \externaldocument[][nocite]{aaa}
+% \end{verbatim}
+%
+% The `document' referred to by the main argument \meta{document} is the file
+% \file{document.aux} which must be somewhere on TeX's input path.
+% Some packages (eg hyperref) really need to know the location of the
+% final document rather than the aux file. By default this is assumed
+% to be \file{document.pdf}. A package may redefine the command \cs{XR@ext} to
+% change this default extension. However sometimes the final
+% document may be in a position unrelated to the aux file, or the
+% browser may not be able to find files at an arbitrary point in
+% TeX's input path, so the final optional argument \meta{url} allows a full
+% URL to the final document to be specified.
+% \begin{verbatim}
+% \externaldocument{aaa}[https://example.com/this/path/to/aaa.pdf]
+% \end{verbatim}
+%
+% The package stores the url of the external document in the label data. It can
+% e.g. be retrieved with the \pkg{refcount} package
+%
+% \begin{verbatim}
+% \usepackage{refcount,xr}
+% \externaldocument{aaa}
+% ...
+% \getrefbykeydefault{intro}{url}{??} %prints aaa.pdf or ??
+% \end{verbatim}
+%
+% \pkg{xr} supports also the properties introduced in \LaTeX{} 2023-11-01.
+% Here the url of the external document is stored in the \texttt{xr-url} property.
+%
+% \begin{verbatim}
+% \usepackage{xr}
+% \externaldocument{aaa} %aaa contains \RecordProperties{intro}{page}
+% ...
+% \RefProperty{intro}{page} %gives page number
+% \RefProperty{intro}{xr-url} %gives aaa.pdf
+% \end{verbatim}
%
% \MaybeStop{}
%
@@ -98,20 +202,74 @@
% \end{macrocode}
%
% Check for the optional argument.
+% \changes{v6.00}{2024-04-10}{Copied over extended definition of xr-hyper}
% \begin{macrocode}
-\def\externaldocument{\@ifnextchar[\XR@{\XR@[]}}
+\def\externaldocument{\@testopt\XR@cite{}}
\let\externalcitedocument\externaldocument
+\def\XR@cite[#1]{\@testopt{\XR@[#1]}{}}
+\def\XR@[#1][#2]#3{\@testopt{\XR@@{#1}{#2}{#3}}{#3.\XR@ext}}
+% \end{macrocode}
+%
+% \subsection{helper definitions}
+% \changes{v6.00}{2024-04-10}{new, copied over from xr-hyper}
+% To test the second optional argument
+% \begin{macrocode}
+\def\XR@@nocite{nocite}
+% \end{macrocode}
+% Needed in the processing
+% \begin{macrocode}
+\long\def\@gobblefour #1#2#3#4{}
+\long\def\@firstoffour #1#2#3#4{#1}
+\long\def\@secondoffour#1#2#3#4{#2}
+\long\def\@thirdoffour #1#2#3#4{#3}
+\long\def\@fourthoffour #1#2#3#4{#4}
+% \end{macrocode}
+% The url is added as fifth argument. The command used here is
+% \cs{XR@addURL}. The command is more complicated as needed
+% as it tries to handle also older documents with
+% \cs{newlabel}'s with two arguments.
+% \begin{macrocode}
+\def\XR@addURL#1{\XR@@dURL#1{}{}{}{}\\}
+\def\XR@@dURL#1#2#3#4#5\\{%
+ \unexpanded{{#1}{#2}{#3}{#4}}{\XR@URL}%
+ }%
+% \end{macrocode}
+%
+% \subsection{Variables}
+% \changes{v6.00}{2024-04-10}{new, copied over from xr-hyper}
+% Default file extension:
+% \begin{macrocode}
+\providecommand\XR@ext{pdf}
% \end{macrocode}
%
-% Save the optional prefix. Start processing the first |aux| file.
-% \changes{v5.06}{2020-05-10}{Remove leading and trailing sapces from
+% Save the optional prefix. Start processing the first |aux| file.
+% \changes{v6.00}{2024-04-10}{copied over the new extended internal command from xr-hyper.
+% It prepends the directory name.}
+% Olivier Michel pointed out that
+% if the aux file was not on texinputs you could not always go
+% \cs{externaldocument}{/some/path/to/file}
+% specifically that worked if file.aux was a `simple' document with
+% one aux file, but if \cs{include} had been used, the `sub' aux files
+% would not be found by xr in the remote directory.
+% This version calls \cs{filename@parse} to get the directory name of the
+% remote directory, which is then explicitly prepended to the names of
+% any included aux files.
+% \changes{v5.06}{2020-05-10}{Remove leading and trailing spaces from
% the filename (gh/2223)}
% \begin{macrocode}
-\def\XR@[#1]#2{{%
+\def\XR@@#1#2#3[#4]{{%
\makeatletter
\def\XR@prefix{#1}%
- \set@curr@file{#2}%
- \expandafter\XR@next\@curr@file.aux\relax\\}}
+ \def\XR@nocite{#2}%
+ \ifx\XR@nocite\XR@@nocite
+ \let\XR@bibcite\vadjust
+ \else
+ \let\XR@bibcite\bibcite
+ \fi
+ \def\XR@URL{#4}%
+ \set@curr@file{#3}%
+ \filename@parse\@curr@file
+ \XR@next\@curr@file.aux\relax\\}}
% \end{macrocode}
%
% Process the next |aux| file in the list and remove it from the head of
@@ -161,23 +319,40 @@
% \end{macrocode}
%
% Look at the first token of the line.
-% If it is |\newlabel|, do the |\newlabel|. If it is |\@input|, add the
-% filename to the list of files to process. Otherwise ignore.
+% If it is |\newlabel|, define \cs{r@}\meta{label}, ensure that it has
+% five label data argument and add the url as the last one.
+% If it is |\@input|, add the
+% filename to the list of files to process.
+% If it is |\bibcite|, call a |\bibcite|.
+% If it is |\new@label@record| add the url and then call it.
+% Otherwise ignore.
% Go around the loop if not at end of file. Finally process the next
% file in the list.
%
% 2018 update: make sure the arguments are handled outside the |\ifx| test,
+% \changes{v6.00}{2024-04-10}{copied over extended definition from xr-hyper}
% \begin{macrocode}
\long\def\XR@test#1#2#3#4\XR@{%
- \let\XR@tempa\@gobbletwo
+ \let\XR@tempa\@gobblefour
\ifx#1\newlabel
- \let\XR@tempa\@firstoftwo
- \else\ifx#1\bibcite
- \let\XR@tempa\@firstoftwo
+ \let\XR@tempa\@firstoffour
+ \else\ifx#1\XR@bibcite
+ \let\XR@tempa\@secondoffour
\else\ifx#1\@input
- \let\XR@tempa\@secondoftwo
- \fi\fi\fi
- \XR@tempa{#1{\XR@prefix#2}{#3}}{\edef\XR@list{\XR@list#2\relax}}%
+ \let\XR@tempa\@thirdoffour
+ \else\ifx#1\new@label@record
+ \let\XR@tempa\@fourthoffour
+ \fi\fi\fi\fi
+ \XR@tempa
+ {%
+ \expandafter\protected@xdef\csname r@\XR@prefix#2\endcsname{\XR@addURL{#3}}%
+ }%
+ {\expandafter\bibcite\expandafter{\XR@prefix#2}{#3}}%
+ {\edef\XR@list{\XR@list\filename@area#2\relax}}%
+ {%
+ \edef\next{\noexpand\new@label@record{\XR@prefix#2}{\unexpanded{#3}{xr-url}{\XR@URL}}}%
+ \next
+ }
\ifeof\@inputcheck\expandafter\XR@aux
\else\expandafter\XR@read\fi}
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/tools/xspace.dtx b/Master/texmf-dist/source/latex/tools/xspace.dtx
index 807fc9c5df3..be20fc9e522 100644
--- a/Master/texmf-dist/source/latex/tools/xspace.dtx
+++ b/Master/texmf-dist/source/latex/tools/xspace.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2023
+% Copyright (C) 1993-2024
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.