summaryrefslogtreecommitdiff
path: root/macros/latex/base
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-06-02 03:04:23 +0000
committerNorbert Preining <norbert@preining.info>2021-06-02 03:04:23 +0000
commit138d0a6cfd5f2187973fb6b83ad2fb0dcf5a8348 (patch)
treea95fba7d01d57bba550f5114c936ec76d57a49ac /macros/latex/base
parent0f69e2fd4a9928663f0cc64b8cac1f0d8baee9d6 (diff)
CTAN sync 202106020304
Diffstat (limited to 'macros/latex/base')
-rw-r--r--macros/latex/base/README.md2
-rw-r--r--macros/latex/base/alltt.dtx27
-rw-r--r--macros/latex/base/alltt.ins8
-rw-r--r--macros/latex/base/alltt.pdfbin173080 -> 214710 bytes
-rw-r--r--macros/latex/base/bugs.txt8
-rw-r--r--macros/latex/base/cfgguide.pdfbin220226 -> 242886 bytes
-rw-r--r--macros/latex/base/cfgguide.tex12
-rw-r--r--macros/latex/base/changes.txt399
-rw-r--r--macros/latex/base/classes.dtx137
-rw-r--r--macros/latex/base/classes.ins8
-rw-r--r--macros/latex/base/classes.pdfbin520818 -> 550002 bytes
-rw-r--r--macros/latex/base/clsguide.pdfbin372576 -> 402779 bytes
-rw-r--r--macros/latex/base/clsguide.tex6
-rw-r--r--macros/latex/base/cmextra.ins8
-rw-r--r--macros/latex/base/cmfonts.fdd2
-rw-r--r--macros/latex/base/cmfonts.ins8
-rw-r--r--macros/latex/base/cmfonts.pdfbin264510 -> 292317 bytes
-rw-r--r--macros/latex/base/cyrguide.pdfbin216995 -> 239681 bytes
-rw-r--r--macros/latex/base/cyrguide.tex8
-rw-r--r--macros/latex/base/doc-v3beta.sty1241
-rw-r--r--macros/latex/base/doc.dtx27
-rw-r--r--macros/latex/base/doc.pdfbin631278 -> 676501 bytes
-rw-r--r--macros/latex/base/docstrip.dtx22
-rw-r--r--macros/latex/base/docstrip.ins8
-rw-r--r--macros/latex/base/docstrip.pdfbin479441 -> 503186 bytes
-rw-r--r--macros/latex/base/ec.ins8
-rw-r--r--macros/latex/base/encguide.pdfbin1532142 -> 1316472 bytes
-rw-r--r--macros/latex/base/encguide.tex10
-rw-r--r--macros/latex/base/exscale.dtx4
-rw-r--r--macros/latex/base/exscale.ins8
-rw-r--r--macros/latex/base/exscale.pdfbin195882 -> 212307 bytes
-rw-r--r--macros/latex/base/fix-cm.dtx8
-rw-r--r--macros/latex/base/fix-cm.ins8
-rw-r--r--macros/latex/base/fix-cm.pdfbin262057 -> 287672 bytes
-rw-r--r--macros/latex/base/fntguide.pdfbin418347 -> 493957 bytes
-rw-r--r--macros/latex/base/fntguide.tex15
-rw-r--r--macros/latex/base/fontdef.dtx16
-rw-r--r--macros/latex/base/format.ins22
-rw-r--r--macros/latex/base/graphpap.dtx4
-rw-r--r--macros/latex/base/graphpap.ins8
-rw-r--r--macros/latex/base/graphpap.pdfbin156276 -> 169323 bytes
-rw-r--r--macros/latex/base/idx.tex4
-rw-r--r--macros/latex/base/ifthen.dtx10
-rw-r--r--macros/latex/base/ifthen.ins8
-rw-r--r--macros/latex/base/ifthen.pdfbin205204 -> 220417 bytes
-rw-r--r--macros/latex/base/inputenc.dtx12
-rw-r--r--macros/latex/base/inputenc.ins8
-rw-r--r--macros/latex/base/inputenc.pdfbin294927 -> 318168 bytes
-rw-r--r--macros/latex/base/lablst.tex4
-rw-r--r--macros/latex/base/latex209.dtx8
-rw-r--r--macros/latex/base/latex209.ins8
-rw-r--r--macros/latex/base/latexchanges.pdfbin247704 -> 468043 bytes
-rw-r--r--macros/latex/base/latexchanges.tex8
-rw-r--r--macros/latex/base/latexrelease.dtx350
-rw-r--r--macros/latex/base/latexrelease.ins16
-rw-r--r--macros/latex/base/latexrelease.pdfbin246192 -> 290495 bytes
-rw-r--r--macros/latex/base/latexsym.dtx4
-rw-r--r--macros/latex/base/latexsym.ins12
-rw-r--r--macros/latex/base/latexsym.pdfbin192295 -> 208359 bytes
-rw-r--r--macros/latex/base/lb2.err7
-rw-r--r--macros/latex/base/lb2.pdfbin138221 -> 252154 bytes
-rw-r--r--macros/latex/base/legal.txt5
-rw-r--r--macros/latex/base/letter.dtx32
-rw-r--r--macros/latex/base/letter.ins8
-rw-r--r--macros/latex/base/letter.pdfbin306166 -> 328728 bytes
-rw-r--r--macros/latex/base/lgc2.err7
-rw-r--r--macros/latex/base/lgc2.pdfbin101335 -> 215091 bytes
-rw-r--r--macros/latex/base/lppl.pdfbin125830 -> 132373 bytes
-rw-r--r--macros/latex/base/ltalloc.dtx4
-rw-r--r--macros/latex/base/ltbibl.dtx63
-rw-r--r--macros/latex/base/ltboxes.dtx118
-rw-r--r--macros/latex/base/ltclass.dtx271
-rw-r--r--macros/latex/base/ltcmd.dtx4034
-rw-r--r--macros/latex/base/ltcmdhooks-code.pdfbin0 -> 693019 bytes
-rw-r--r--macros/latex/base/ltcmdhooks-code.tex4
-rw-r--r--macros/latex/base/ltcmdhooks-doc.pdfbin0 -> 479331 bytes
-rw-r--r--macros/latex/base/ltcmdhooks-doc.tex6
-rw-r--r--macros/latex/base/ltcmdhooks.dtx1094
-rw-r--r--macros/latex/base/ltcntrl.dtx8
-rw-r--r--macros/latex/base/ltcounts.dtx8
-rw-r--r--macros/latex/base/ltdefns.dtx32
-rw-r--r--macros/latex/base/ltdirchk.dtx30
-rw-r--r--macros/latex/base/lterror.dtx4
-rw-r--r--macros/latex/base/ltexpl.dtx107
-rw-r--r--macros/latex/base/ltfilehook-code.pdfbin745530 -> 795324 bytes
-rw-r--r--macros/latex/base/ltfilehook-doc.pdfbin516657 -> 545883 bytes
-rw-r--r--macros/latex/base/ltfilehook.dtx133
-rw-r--r--macros/latex/base/ltfiles.dtx179
-rw-r--r--macros/latex/base/ltfinal.dtx136
-rw-r--r--macros/latex/base/ltfloat.dtx122
-rw-r--r--macros/latex/base/ltfntcmd.dtx12
-rw-r--r--macros/latex/base/ltfssaxes.dtx402
-rw-r--r--macros/latex/base/ltfssbas.dtx56
-rw-r--r--macros/latex/base/ltfsscmp.dtx8
-rw-r--r--macros/latex/base/ltfssdcl.dtx18
-rw-r--r--macros/latex/base/ltfssini.dtx146
-rw-r--r--macros/latex/base/ltfsstrc.dtx176
-rw-r--r--macros/latex/base/lthooks-code.pdfbin929193 -> 1029072 bytes
-rw-r--r--macros/latex/base/lthooks-doc.pdfbin626829 -> 683789 bytes
-rw-r--r--macros/latex/base/lthooks.dtx1210
-rw-r--r--macros/latex/base/lthyphen.dtx6
-rw-r--r--macros/latex/base/ltidxglo.dtx4
-rw-r--r--macros/latex/base/ltlength.dtx8
-rw-r--r--macros/latex/base/ltlists.dtx16
-rw-r--r--macros/latex/base/ltlogos.dtx4
-rw-r--r--macros/latex/base/ltluatex.dtx36
-rw-r--r--macros/latex/base/ltluatex.pdfbin305355 -> 325289 bytes
-rw-r--r--macros/latex/base/ltmath.dtx16
-rw-r--r--macros/latex/base/ltmiscen.dtx45
-rw-r--r--macros/latex/base/ltnews.cls6
-rw-r--r--macros/latex/base/ltnews.pdfbin989349 -> 1074364 bytes
-rw-r--r--macros/latex/base/ltnews.tex15
-rw-r--r--macros/latex/base/ltnews01.pdfbin150020 -> 161518 bytes
-rw-r--r--macros/latex/base/ltnews01.tex10
-rw-r--r--macros/latex/base/ltnews02.pdfbin134751 -> 150466 bytes
-rw-r--r--macros/latex/base/ltnews02.tex4
-rw-r--r--macros/latex/base/ltnews03.pdfbin134739 -> 150493 bytes
-rw-r--r--macros/latex/base/ltnews03.tex4
-rw-r--r--macros/latex/base/ltnews04.pdfbin128773 -> 143686 bytes
-rw-r--r--macros/latex/base/ltnews04.tex4
-rw-r--r--macros/latex/base/ltnews05.pdfbin157182 -> 174488 bytes
-rw-r--r--macros/latex/base/ltnews05.tex4
-rw-r--r--macros/latex/base/ltnews06.pdfbin133141 -> 142909 bytes
-rw-r--r--macros/latex/base/ltnews06.tex4
-rw-r--r--macros/latex/base/ltnews07.pdfbin124030 -> 138044 bytes
-rw-r--r--macros/latex/base/ltnews07.tex4
-rw-r--r--macros/latex/base/ltnews08.pdfbin144483 -> 155055 bytes
-rw-r--r--macros/latex/base/ltnews08.tex4
-rw-r--r--macros/latex/base/ltnews09.pdfbin120221 -> 129032 bytes
-rw-r--r--macros/latex/base/ltnews09.tex6
-rw-r--r--macros/latex/base/ltnews10.pdfbin147944 -> 159313 bytes
-rw-r--r--macros/latex/base/ltnews10.tex4
-rw-r--r--macros/latex/base/ltnews11.pdfbin104939 -> 111955 bytes
-rw-r--r--macros/latex/base/ltnews11.tex6
-rw-r--r--macros/latex/base/ltnews12.pdfbin137922 -> 147587 bytes
-rw-r--r--macros/latex/base/ltnews12.tex7
-rw-r--r--macros/latex/base/ltnews13.pdfbin161063 -> 173323 bytes
-rw-r--r--macros/latex/base/ltnews13.tex4
-rw-r--r--macros/latex/base/ltnews14.pdfbin150913 -> 161405 bytes
-rw-r--r--macros/latex/base/ltnews14.tex4
-rw-r--r--macros/latex/base/ltnews15.pdfbin122092 -> 130447 bytes
-rw-r--r--macros/latex/base/ltnews15.tex4
-rw-r--r--macros/latex/base/ltnews16.pdfbin130689 -> 146533 bytes
-rw-r--r--macros/latex/base/ltnews16.tex6
-rw-r--r--macros/latex/base/ltnews17.pdfbin149848 -> 166368 bytes
-rw-r--r--macros/latex/base/ltnews17.tex4
-rw-r--r--macros/latex/base/ltnews18.pdfbin36004 -> 38031 bytes
-rw-r--r--macros/latex/base/ltnews18.tex4
-rw-r--r--macros/latex/base/ltnews19.pdfbin235075 -> 245818 bytes
-rw-r--r--macros/latex/base/ltnews19.tex4
-rw-r--r--macros/latex/base/ltnews20.pdfbin283324 -> 297070 bytes
-rw-r--r--macros/latex/base/ltnews20.tex2
-rw-r--r--macros/latex/base/ltnews21.pdfbin233489 -> 244869 bytes
-rw-r--r--macros/latex/base/ltnews21.tex2
-rw-r--r--macros/latex/base/ltnews22.pdfbin302831 -> 318399 bytes
-rw-r--r--macros/latex/base/ltnews22.tex4
-rw-r--r--macros/latex/base/ltnews23.pdfbin274456 -> 287125 bytes
-rw-r--r--macros/latex/base/ltnews23.tex4
-rw-r--r--macros/latex/base/ltnews24.pdfbin252643 -> 265211 bytes
-rw-r--r--macros/latex/base/ltnews24.tex4
-rw-r--r--macros/latex/base/ltnews25.pdfbin196325 -> 205162 bytes
-rw-r--r--macros/latex/base/ltnews25.tex4
-rw-r--r--macros/latex/base/ltnews26.pdfbin362839 -> 379735 bytes
-rw-r--r--macros/latex/base/ltnews26.tex4
-rw-r--r--macros/latex/base/ltnews27.pdfbin239759 -> 252432 bytes
-rw-r--r--macros/latex/base/ltnews27.tex4
-rw-r--r--macros/latex/base/ltnews28.pdfbin368231 -> 387987 bytes
-rw-r--r--macros/latex/base/ltnews28.tex6
-rw-r--r--macros/latex/base/ltnews29.pdfbin433003 -> 454808 bytes
-rw-r--r--macros/latex/base/ltnews29.tex6
-rw-r--r--macros/latex/base/ltnews30.pdfbin491245 -> 511855 bytes
-rw-r--r--macros/latex/base/ltnews30.tex2
-rw-r--r--macros/latex/base/ltnews31.pdfbin500928 -> 526312 bytes
-rw-r--r--macros/latex/base/ltnews31.tex2
-rw-r--r--macros/latex/base/ltnews32.pdfbin520917 -> 546162 bytes
-rw-r--r--macros/latex/base/ltnews32.tex4
-rw-r--r--macros/latex/base/ltnews33.pdfbin0 -> 522411 bytes
-rw-r--r--macros/latex/base/ltnews33.tex942
-rw-r--r--macros/latex/base/ltoutenc.dtx112
-rw-r--r--macros/latex/base/ltoutenc.ins8
-rw-r--r--macros/latex/base/ltoutput.dtx38
-rw-r--r--macros/latex/base/ltpage.dtx8
-rw-r--r--macros/latex/base/ltpageno.dtx8
-rw-r--r--macros/latex/base/ltpar.dtx20
-rw-r--r--macros/latex/base/ltpara-code.pdfbin0 -> 664444 bytes
-rw-r--r--macros/latex/base/ltpara-code.tex4
-rw-r--r--macros/latex/base/ltpara-doc.pdfbin0 -> 560166 bytes
-rw-r--r--macros/latex/base/ltpara-doc.tex6
-rw-r--r--macros/latex/base/ltpara.dtx1223
-rw-r--r--macros/latex/base/ltpictur.dtx11
-rw-r--r--macros/latex/base/ltplain.dtx222
-rw-r--r--macros/latex/base/ltsect.dtx8
-rw-r--r--macros/latex/base/ltshipout-code.pdfbin750800 -> 818625 bytes
-rw-r--r--macros/latex/base/ltshipout-doc.pdfbin504019 -> 564572 bytes
-rw-r--r--macros/latex/base/ltshipout.dtx730
-rw-r--r--macros/latex/base/ltspace.dtx4
-rw-r--r--macros/latex/base/lttab.dtx14
-rw-r--r--macros/latex/base/lttextcomp.dtx545
-rw-r--r--macros/latex/base/ltthm.dtx4
-rw-r--r--macros/latex/base/ltvers.dtx153
-rw-r--r--macros/latex/base/ltx3info.pdfbin191531 -> 219354 bytes
-rw-r--r--macros/latex/base/ltx3info.tex4
-rw-r--r--macros/latex/base/ltxcheck.tex6
-rw-r--r--macros/latex/base/ltxdoc.dtx8
-rw-r--r--macros/latex/base/ltxdoc.pdfbin215098 -> 238577 bytes
-rw-r--r--macros/latex/base/ltxguide.cls4
-rw-r--r--macros/latex/base/ltxref.dtx12
-rw-r--r--macros/latex/base/makeindx.dtx6
-rw-r--r--macros/latex/base/makeindx.ins8
-rw-r--r--macros/latex/base/makeindx.pdfbin160668 -> 173682 bytes
-rw-r--r--macros/latex/base/manifest.txt2
-rw-r--r--macros/latex/base/manual.pdfbin151352 -> 160521 bytes
-rw-r--r--macros/latex/base/minimal.cls2
-rw-r--r--macros/latex/base/modguide.pdfbin220389 -> 243601 bytes
-rw-r--r--macros/latex/base/modguide.tex6
-rw-r--r--macros/latex/base/newdc.ins8
-rw-r--r--macros/latex/base/newlfont.dtx4
-rw-r--r--macros/latex/base/nfssfont.dtx10
-rw-r--r--macros/latex/base/nfssfont.ins8
-rw-r--r--macros/latex/base/nfssfont.pdfbin202447 -> 218782 bytes
-rw-r--r--macros/latex/base/olddc.ins8
-rw-r--r--macros/latex/base/oldlfont.dtx4
-rw-r--r--macros/latex/base/preload.dtx4
-rw-r--r--macros/latex/base/proc.dtx12
-rw-r--r--macros/latex/base/proc.ins8
-rw-r--r--macros/latex/base/proc.pdfbin216876 -> 233995 bytes
-rw-r--r--macros/latex/base/slides.dtx22
-rw-r--r--macros/latex/base/slides.ins16
-rw-r--r--macros/latex/base/slides.pdfbin351590 -> 374051 bytes
-rw-r--r--macros/latex/base/slifonts.fdd4
-rw-r--r--macros/latex/base/slifonts.pdfbin214706 -> 234008 bytes
-rw-r--r--macros/latex/base/source2e.pdfbin4360837 -> 5275730 bytes
-rw-r--r--macros/latex/base/source2e.tex10
-rw-r--r--macros/latex/base/source2edoc.cls31
-rw-r--r--macros/latex/base/syntonly.dtx4
-rw-r--r--macros/latex/base/syntonly.ins8
-rw-r--r--macros/latex/base/syntonly.pdfbin181862 -> 197187 bytes
-rw-r--r--macros/latex/base/testpage.tex4
-rw-r--r--macros/latex/base/texpert.txt2
-rw-r--r--macros/latex/base/tlc2.err5
-rw-r--r--macros/latex/base/tlc2.pdfbin164952 -> 289245 bytes
-rw-r--r--macros/latex/base/tulm.fdd6
-rw-r--r--macros/latex/base/tulm.ins8
-rw-r--r--macros/latex/base/tulm.pdfbin156546 -> 170529 bytes
-rw-r--r--macros/latex/base/unpack.ins4
-rw-r--r--macros/latex/base/usrguide.pdfbin399074 -> 430996 bytes
-rw-r--r--macros/latex/base/usrguide.tex10
-rw-r--r--macros/latex/base/usrguide3.pdfbin181816 -> 325299 bytes
-rw-r--r--macros/latex/base/usrguide3.tex24
-rw-r--r--macros/latex/base/utf8ienc.dtx41
-rw-r--r--macros/latex/base/utf8ienc.pdfbin331005 -> 361477 bytes
-rw-r--r--macros/latex/base/webcomp.err7
-rw-r--r--macros/latex/base/webcomp.pdfbin136162 -> 146200 bytes
253 files changed, 13775 insertions, 1844 deletions
diff --git a/macros/latex/base/README.md b/macros/latex/base/README.md
index f9394d0f3b..694eedb2db 100644
--- a/macros/latex/base/README.md
+++ b/macros/latex/base/README.md
@@ -1,7 +1,7 @@
The LaTeX kernel
================
-Release 2020-10-01 patch level 4
+Release 2021-06-01
Overview
--------
diff --git a/macros/latex/base/alltt.dtx b/macros/latex/base/alltt.dtx
index 2c9e22a124..350229ab40 100644
--- a/macros/latex/base/alltt.dtx
+++ b/macros/latex/base/alltt.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -30,7 +30,7 @@
%%
%% File `alltt.dtx'.
%% Copyright (C) 1987 by Leslie Lamport
-%% Copyright (C) 1994--1997 LaTeX3 project, Johannes Braams
+%% Copyright (C) 1994-2021 LaTeX Project, Johannes Braams
%% all rights reserved.
%%
%<*dtx>
@@ -40,10 +40,11 @@
%<package>\ProvidesPackage{alltt}
%<driver>\ProvidesFile{alltt.drv}
%\ProvidesFile{alltt.dtx}
- [1997/06/16 v2.0g defines alltt environment]
+ [2021/01/29 v2.0g defines alltt environment]
%
%<*driver>
\documentclass{ltxdoc}
+\usepackage{alltt}
\begin{document}
\providecommand{\Lenv}[1]{\textsf{#1}}
\providecommand{\pkg}[1]{\texttt{#1}}
@@ -55,6 +56,8 @@
%
% \changes{v2.0g}{1997/06/16}{A few documentation fixes (PR 2520)}
% \changes{v2.0d}{1995/04/02}{A few documentation fixes (PR 1517)}
+% \changes{v2.0g}{2021-01-29}{Added a warning about OT1 versus T1 font
+% encoding}
%
% \GetFileInfo{alltt.dtx}
% \title{The \texttt{alltt} environment\thanks{This file
@@ -88,11 +91,19 @@
% extra blank line if you're not careful.
%
% \item Insert a math formula. Note that |$| just produces a dollar
-% sign, so you'll have to type |\(...\)| or |\[...\]|. Also, |^|
-% and |_| just produce their characters; use |\sp| or |\sb| for
-% super- and subscripts, as in |\(x\sp{2}\)|.
+% sign, so you'll have to type |\(...\)| or |\[...\]|. Also, |^|
+% and |_| just produce their characters; use |\sp| or |\sb| for
+% super- and subscripts, as in |\(x\sp{2}\)|.
% \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
+% a different set of glyphs:
+% \begin{alltt}
+% The glyph at the position of the $ in a slanted font: \textsl{$}.
+% The glyph at the position of the $ in an italic font: \textit{$}.
+% \end{alltt}
+%
% \StopEventually{}
%
% \section{The Implementation}
@@ -173,7 +184,7 @@
% control sequence |\do| between the characters. We use that to
% check whether a character has to be removed.
%
-% The macro |\g@remfrom@specials| takes one argument, the chracter
+% The macro |\g@remfrom@specials| takes one argument, the character
% to be removed from the list.
% \begin{macrocode}
\def\g@remfrom@specials#1{%
diff --git a/macros/latex/base/alltt.ins b/macros/latex/base/alltt.ins
index adb3838a47..7ce2103207 100644
--- a/macros/latex/base/alltt.ins
+++ b/macros/latex/base/alltt.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/alltt.pdf b/macros/latex/base/alltt.pdf
index d31e7c526b..1191cad564 100644
--- a/macros/latex/base/alltt.pdf
+++ b/macros/latex/base/alltt.pdf
Binary files differ
diff --git a/macros/latex/base/bugs.txt b/macros/latex/base/bugs.txt
index 8fd071c8a7..bbb78d8c22 100644
--- a/macros/latex/base/bugs.txt
+++ b/macros/latex/base/bugs.txt
@@ -21,7 +21,7 @@ Before you report an error, please check that:
https://www.latex-project.org/bugs.html
* The error is not caused by software other than the core LaTeX
- software that is produced and maintained by the LaTeX3 project
+ software that is produced and maintained by the LaTeX Project
team. Please report problems with other software to the authors
or suppliers of that software, and not to us!
@@ -30,9 +30,9 @@ Before you report an error, please check that:
Also, the test file demonstrating the error should not use any
classes or packages other than those authored and supported by the
- LaTeX3 team. The files for the package or class will tell you how
+ LaTeX Project team. The files for the package or class will tell you how
it is supported. The test file should use the package latexbug to
- check that all packages in the file are supported by the LaTeX3
+ check that all packages in the file are supported by the LaTeX
Project (see the discussion on the website why this is important).
* The error is not caused by using an obsolete version of any file or
@@ -85,4 +85,4 @@ given in that corresponding errata file.
Please *do not* send such reports to the latex-bugs address.
---- Copyright 1997,1998,2006,2008,2017,2020 the LaTeX3 project. All rights reserved ---
+--- Copyright (C) 1997-2021 the LaTeX Project. All rights reserved ---
diff --git a/macros/latex/base/cfgguide.pdf b/macros/latex/base/cfgguide.pdf
index c4a7ad4323..5725de20a5 100644
--- a/macros/latex/base/cfgguide.pdf
+++ b/macros/latex/base/cfgguide.pdf
Binary files differ
diff --git a/macros/latex/base/cfgguide.tex b/macros/latex/base/cfgguide.tex
index 84cde10c84..66c02e4c33 100644
--- a/macros/latex/base/cfgguide.tex
+++ b/macros/latex/base/cfgguide.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -39,7 +39,7 @@
\title{Configuration options for \LaTeXe}
-\author{\copyright~Copyright 1998, 2001, 2003 \LaTeX3 Project Team.\\
+\author{\copyright~Copyright 1998, 2001, 2003 \LaTeX\ Project Team.\\
All rights reserved.}
\date{14 February 2003}
@@ -146,7 +146,7 @@ configuration files has the following consequences.
portable only in the sense of being processable at a different
site---the actual formatting will not be the same if different
fonts are used.
- \item The \LaTeX3 project team will not be able to support you in
+ \item The \LaTeX\ Project team will not be able to support you in
diagnosing problems if these cannot be reproduced with a format
that does not use any configuration files.
\end{itemize}
@@ -288,7 +288,7 @@ following consequences.
portable only in the sense of being processable at a different
site---the actual formatting will not be the same if different
fonts are used.
- \item The \LaTeX3 project team will not be able to support you in
+ \item The \LaTeX\ Project team will not be able to support you in
diagnosing problems if these cannot be reproduced with a format
that does not use any customised font definition files.
\end{itemize}
@@ -370,7 +370,7 @@ consequences.
\item Documents are portable only in the sense of being processable
at a different site---the actual formatting will not be the same
if different fonts are used.
- \item The \LaTeX3 project team will not be able to support you in
+ \item The \LaTeX\ Project team will not be able to support you in
diagnosing problems if these cannot be reproduced with a format
that does not use this configuration file.
\end{itemize}
diff --git a/macros/latex/base/changes.txt b/macros/latex/base/changes.txt
index e86d28740d..634eb0e351 100644
--- a/macros/latex/base/changes.txt
+++ b/macros/latex/base/changes.txt
@@ -1,4 +1,4 @@
-================================================================================
+================================================================================
This file lists changes to the LaTeX2e files in reverse chronological order of
publication (therefore the dates might be out of sequence if there are hotfixes).
It is provided for convenience only. It therefore makes no claims to
@@ -10,6 +10,397 @@ are not part of the distribution.
All changes above are only part of the development branch for the next release.
================================================================================
+#########################
+# 2020-06-01 Release
+#########################
+
+2021-05-31 David Carlisle <David.Carlisle@latex-project.org>
+
+ * ltclass.dtx: Initialise \@raw@classoptionslist to \relax to
+ match \@classoptionslist
+
+2021-05-30 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * doc.dtx (subsection{Macros for the `documentation parts'}):
+ Use same error message text as in format
+
+2021-05-26 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltdefns.dtx (subsection{Robust commands and protect}):
+ Normalize error message in \MakeRobust
+
+2021-05-26 Phelype Oleinik <phelype.oleinik@latex-project.org>
+
+ * lthooks.dtx:
+ Remove deprecated \DeclareDefaultHookLabel for good.
+
+2021-05-25 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * lthooks.dtx, ltfilehook.dtx:
+ Normalized some error message texts
+
+2021-05-24 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltcmd.dtx, ltcmdhooks.dtx, ltfilehook.dtx, lthooks.dtx, ltpara.dtx:
+ Use \msg_... instead of \__kernel_msg... commands for normalized
+ error and warning commands.
+
+2021-05-14 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltoutput.dtx: normalize the error commands, always use
+ \@latex@error not \@latexerr
+
+2021-04-29 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * lthooks.dtx (subsection{\LaTeXe{} package interface commands}):
+ Add \ProvideHook and related commands.
+
+2021-04-29 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * lthooks.dtx, ltfilehook.dtx:
+ Switch to kernel (not package) errors.
+
+2021-04-29 Marcel Krüger <Marcel.Krueger@latex-project.org>
+
+ * ltoutenc.dtx (subsection{Definitions for the TU encoding}):
+ Declare Unicode composites for \'\ae, \'\AE and add æ/Æ equivalents for
+ \ae/\AE composites
+
+
+2021-04-26 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfsstrc.dtx (subsection{General font loading}):
+ Unset the forced series boolean when reaching \selectfont (gh/444)
+
+ * ltfssini.dtx (subsection{Miscellaneous}):
+ Unconditionally switch to the requested font face with \normalfont (gh/444)
+
+ * ltfssbas.dtx (subsection{Macros for the user}):
+ Unconditionally switch to the requested font face with \usefont (gh/444)
+
+
+2021-04-20 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltexpl.dtx (subsection{Loader}): Don't empty kernel hooks on rollback
+
+ * ltcmd.dtx (subsection{Utilities}):
+ Renamed \__cmd_cmd_if_xparse:NTF to \__kernel_cmd_if_xparse:NTF
+ for cross-module usage
+
+ * ltcmdhooks.dtx: Module added to provide support for cmd hooks
+
+ * lthooks.dtx: Support for cmd hooks added
+
+
+2021-04-20 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * lttab.dtx (subsection{array and tabular environments}):
+ Use \protected for \\ variant (gh/548)}
+
+ * ltmath.dtx (subsection{Math Environments}):
+ Use \protected for \\ variant (gh/548)}
+
+ * ltpictur.dtx (section{Picture Mode}):
+ Use \protected for \\ variant (gh/548)}
+
+
+2021-04-18 Phelype Oleinik <phelype.oleinik@latex-project.org>
+
+ * ltfilehook.dtx:
+ Ensure that ~ expands to the character ~ in file names.
+
+2021-04-18 Phelype Oleinik <phelype.oleinik@latex-project.org>
+
+ * ltplain.dtx:
+ Add support for \tracingstacklevels and \tracinglostchars=3.
+
+2021-04-16 Phelype Oleinik <phelype.oleinik@latex-project.org>
+
+ * latexrelease.dtx, ltcmd.dtx, lthooks.dtx, ltpara.dtx,
+ lttextcomp.dtx, ltvers.dtx:
+ Change argument signature of \NewModuleRelease to be the same
+ as \IncludeInRelease (date, name, message).
+
+2021-04-13 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltpara.dtx: Updated the integration of ltpara module;
+ enabled rollback; some command name changes compared to the initial
+ prototype.
+
+2021-03-18 Phelype Oleinik <phelype.oleinik@latex-project.org>
+
+ * ltclass.dtx:
+ Do not rollback expl3 file stack management (gh/504).
+
+2021-03-26 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltplain.dtx (section{Plain \TeX}):
+ Allocate \@inputcheck and \@unused early
+ so that they are before expl3 allocates more streams.
+ In the past this was done in ltfiles (gh/538).
+
+2021-03-18 Phelype Oleinik <phelype.oleinik@latex-project.org>
+
+ * ltvers.dtx:
+ Add \NewModuleRelease and support mechanism to define a new module
+ for proper behaviour when rolling backwards/forwards (gh/479).
+
+ * latexrelease.dtx:
+ Avoid errors when defining commands that already exist.
+
+ * ltcmd.dtx:
+ Use \NewModuleRelease to declare itself in latexrelease.sty.
+
+ * lthooks.dtx:
+ Use \NewModuleRelease to declare itself in latexrelease.sty.
+ Take care when reloading not to mess with the default name stack.
+
+ * ltfilehook.dtx:
+ Take care when reloading not to mess with the default name stack.
+
+ * ltfssaxes.dtx, ltfssini.dtx:
+ Minor corrections to rollback and rollforward.
+
+2021-03-12 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfiles.dtx (subsection{Safe Input Macros}):
+ Allow for unbalanced conditionals inside arguments #2 and #3
+ of \IfFileExists (gh/530)
+
+2021-03-05 David Carlisle <David.Carlisle@latex-project.org>
+
+ * base/ltclass.dtx: Modify \ProcessOption* handling so key=value
+ terms can be safely skipped (gh/513)
+
+2021-03-03 Phelype Oleinik <phelype.oleinik@latex-project.org>
+
+ * ltclass.dtx:
+ Fix overwrite check for files with UTF-8 (gh/415).
+
+2021-02-25 Marcel Krüger <Marcel.Krueger@latex-project.org>
+
+ * ltfinal.dtx:
+ Improve speed of compatibility code for preloading \pdfglyphtounicode
+ into \everyjob
+
+2021-02-19 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltoutenc.dtx (subsection{Definitions for the TU encoding}):
+ Add \textnonbreakinghyphen, \textfiguredash and \texthorizontalbar
+ to OT1, T1 and TU encoding (gh/404)
+
+ * doc-v3beta.sty: File added, currently for internal documentation
+ only; to be replaced in a later release.
+
+2021-02-18 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltclass.dtx: save raw package/class option lists to improve
+ key/val usage in optional argument of \usepackage and
+ \documentclass.
+
+2021-02-17 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltoutenc.dtx (subsection{Definitions for the TS1 encoding}):
+ Special definition for \textasteriskcentered when missing in TS1 (gh/502)
+
+ * ltoutenc.dtx (subsection{Definitions for the TU encoding}):
+ Adjust values for \textasteriskcentered To match TS1 definition (gh/502)
+
+2021-02-16 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltpara.dtx: providing paragraph hooks,; full integration into
+ latex.ltx will happen at a later point in time. For documentation
+ see ltpara-doc.pdf.
+
+2021-02-16 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfloat.dtx (subsection{Footnotes}):
+ \footref added
+
+2021-02-15 David Carlisle <David.Carlisle@latex-project.org>
+
+ * ltfssdcl.dtx: two additional \expandafter to avoid infinite
+ loop on not in math error. (gh/501)
+
+2021-02-11 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * classes.dtx (subsubsection{Itemize}):
+ Drop incorrect space in \labelitemiv (gh/496)
+ Document use of \labelitemfont in ltnews33 (gh/497)
+
+2021-02-10 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltoutenc.dtx (subsection{Definitions for the TU encoding}):
+ Add \textnonbreakinghyphen}, \textfiguredash and
+ \texthorizontalbar (gh/404)
+
+2021-02-10 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltboxes.dtx (section{\LaTeX\ Box commands}):
+ Explicitly run \par at the end of footnote text in preparation
+ for paragraph hooks
+
+ * ltfloat.dtx (subsection{Footnotes}):
+ Explicitly run \par at the end of footnote text in preparation
+ for paragraph hooks
+
+2021-02-08 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfilehook.dtx (subsection{Patching \LaTeX{}'s \InputIfFileExists command}):
+ Undo the internal for robust \InputIfFileExists in rollback (gh/494)
+
+2021-02-08 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltmiscen.dtx (subsection{Environments}):
+ Undo the internals for \begin and \end as well when
+ rolling back (gh/494)
+
+2021-02-04 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltboxes.dtx (section{\LaTeX\ Box commands}):
+ Always add the color groups (gh/488)
+
+2021-02-03 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfloat.dtx (subsection{Floating Environments}):
+ Explicitly end the \marginpar argument with \par to support
+ tagging (gh/489)
+
+2021-01-31 David Carlisle <David.Carlisle@latex-project.org>
+
+ * ltfilehook.dtx: set \protect to \string to avoid bad
+ expansion and possible non termination. github/481
+
+2021-01-27 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * utf8ienc.dtx (subsection{The mapping table}):
+ Support various Unicode characters with dot accents for
+ Indic transliterations (gh/484)
+
+2021-01-22 Marcel Krüger <Marcel.Krueger@latex-project.org>
+
+ * ltshipout.dtx:
+ Define and call Lua callback pre_shipout_filter.
+
+2021-01-21 Marcel Krüger <Marcel.Krueger@latex-project.org>
+
+ * ltfinal.dtx:
+ For pdfTeX enable automatic generation of ToUnicode maps.
+ For pdfTeX versions which do not support dumping these into the format,
+ all \pdfglyphtounicode instructions will be dumped into \everyjob
+
+2021-01-19 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltshipout.dtx: Reordered execution of shipout hooks so that code
+ in one can influence code in later ones in a more natural manner.
+
+2020-01-16 Joseph Wright <Joseph.Wright@latex-project.org>
+
+ * ltexpl.dtx
+ Adjust for full xparse integration
+
+ * ltcmd.dtx
+ New file to replace loading xparse
+
+2021-01-12 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltshipout.dtx: Make sure that the shipout/firstpage hook material
+ is not stored inside \ShipoutBox, in case that gets reused, e.g. via
+ \RawShipout but is only ever added to the very first page shipped out.
+
+2021-01-10 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltshipout.dtx:
+ Added internal \@kernel@after@shipout@background hook.
+ Added public shipout/after hook
+
+ (subsection{Overloading the \shipout primitive}):
+ Add \RawShipout for shipping out while bypassing most hooks.
+
+ (subsection{Emulating atbegshi}): Added
+ \AtBeginShipoutOriginalShipout to the emulation of atbegshi.
+
+2021-01-08 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltshipout.dtx (subsection{Package \pkg{everyshi} emulation}):
+ The emulation is no longer needed so taken out (gh440)
+
+2020-12-22 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfssaxes.dtx (subsection{Changing to a new series}):
+ Distangle series and shape update by delaying the font series
+ and font shape merging (gh/444)
+
+ Move the rollback info for \normalshape after its main definition
+ otherwise it will not be undone (gh/458)
+
+2020-12-22 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfsstrc.dtx (subsection{General font loading}):
+ Alter \selectfont to do the delayed merging of font series
+ and font shape (gh/444)
+
+2020-12-27 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * letter.dtx (subsubsection{Page breaking control}):
+ The \opening argument was splitting name and address using \\
+ but did not allow to use \\[...] for this (gh/427)
+
+2020-12-10 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltbibl.dtx (section{Bibliography Generation}):
+ Delay any \cs{nocite} in the preamble instead of raising
+ an error (gh/424)
+
+2020-12-06 Johannes Braams <Johannes.Braams@latex-project.org>
+
+ * miscelaneous files: gh/428, gh/429 and gh/430 list a number of
+ typing mistakes and missing documentation that have crept in over
+ the years. The following files were affected and have been
+ corrected:
+ alltt.dtx, classes.dtx, doc.dtx, docstrip.dtx, fix-cm.dtx,
+ fontdef.dtx, ifthen.dtx, inputenc.dtx, latex209.dtx,
+ latexrelease.dtx, ltbibl.dtx, ltboxes.dtx, ltclass.dtx,
+ ltcntrl.dtx, ltcounts.dtx, ltdefns.dtx, ltdirchk.dtx, ltexpl.dtx,
+ ltfilehook.dtx, ltfiles.dtx, ltfinal.dtx, ltfloat.dtx,
+ ltfntcmd.dtx, ltfssaxes.dtx, ltfssbas.dtx, ltfsscmp.dtx,
+ ltfssdcl.dtx, ltfssini.dtx, ltfsstrc.dtx, lthooks.dtx,
+ ltlength.dtx, ltlists.dtx, ltluatex.dtx, ltmath.dtx, ltmiscen.dtx,
+ ltoutenc.dtx, ltoutput.dtx, ltpage.dtx, ltpageno.dtx,
+ ltpictur.dtx, ltplain.dtx, ltsect.dtx, ltshipout.dtx,
+ lttextcomp.dtx, ltvers.dtx, ltxdoc.dtx, ltxref.dtx, nfssfont.dtx,
+ proc.dtx, slides.dtx, utf8ienc.dtx.
+
+2020-12-04 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfilehook.dtx (subsection{Declaring a file substitution}):
+ Don't drop file substitution declarations when rolling back
+ just render them no-ops
+
+2020-12-04 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+ Add a hook to \selectfont to be executed after the switch to the
+ new font. This implements the functionality formerly in the everysel
+ package.
+
+2020-12-04 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfinal.dtx (subsection{File substitutions}):
+ Emulate everysel package
+
+2020-12-04 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltfssini.dtx (subsection{Miscellaneous}):
+ Setting up \f@series and \f@shape default values directly (gh/444)
+
+2020-11-23 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltshipout.dtx:
+ Check for both kernel and user hooks and execute if either is non-empty (gh/431)}
+
+2020-10-26 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * ltmiscen.dtx (subsection{Environments}):
+ \enddocument should always start out in vmode (gh/385)
#########################
# 2020-10-01 PL 4 Release
@@ -33,8 +424,8 @@ All changes above are only part of the development branch for the next release.
2020-12-03 Joseph Wright <Joseph.Wright@latex-project.org>
- * usrguide3.tex
- New file to cover creation of document commands
+ * usrguide3.tex
+ New file to cover creation of document commands
#########################
@@ -495,7 +886,7 @@ All changes above are only part of the development branch for the next release.
* ltclass.dtx (section{Implementation}):
Add \IfFormatAtLeastTF to test if the current format is equal or later than
- the given date (gh/168)
+ the given date (gh/186)
Also add \IfClassAtLeastTF and \IfPackageAtLeastTF as a suggested
alternative to \@ifpackagelater and \@ifclasslater (which have a wrong
name, because it is really "later or equal") (gh/186)
diff --git a/macros/latex/base/classes.dtx b/macros/latex/base/classes.dtx
index d6f2bb64e6..ffe04c620f 100644
--- a/macros/latex/base/classes.dtx
+++ b/macros/latex/base/classes.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -53,7 +53,7 @@
%<*driver>
\ProvidesFile{classes.drv}
%</driver>
- [2020/04/10 v1.4m
+ [2021/02/12 v1.4n
%<article|report|book> Standard LaTeX document class]
%<10pt|11pt|12pt> Standard LaTeX file (size option)]
% \end{macrocode}
@@ -116,7 +116,7 @@
\DoNotIndex{\viipt,\vipt,\vskip,\vspace}
\DoNotIndex{\wd,\xiipt,\year,\z@}
% \end{macrocode}
-% We do want an index, using linenumbers
+% We do want an index, using line numbers
% \begin{macrocode}
\EnableCrossrefs
\CodelineIndex
@@ -199,7 +199,7 @@
% \changes{v1.2o}{1994/05/24}{Changed file information}
% \changes{v1.2p}{1994/05/27}{Moved identification and driver to the
% front of the file}
-% \changes{v1.2t}{1994/06/22}{Refrased a few sentences to prevent
+% \changes{v1.2t}{1994/06/22}{Rephrased a few sentences to prevent
% overfull hboxes}
% \changes{v1.2v}{1994/12/01}{Made the oneside option work for the
% book class}
@@ -221,9 +221,9 @@
% file has version number \fileversion, last revised \filedate.}}
%
% \author{%
-% Copyright (C) 1992 by Leslie Lamport \and
-% Copyright (C) 1994-2020 by Frank Mittelbach \and Johannes Braams \and
-% \LaTeX3 Project Team
+% Copyright (C) 1992 by Leslie Lamport and
+% Copyright (C) 1994-2020 by Frank Mittelbach and Johannes Braams and
+% LaTeX Project Team
% }
% \date{\filedate}
% \MaintainedByLaTeXTeam{latex}
@@ -423,7 +423,7 @@
%<!article>\fi
% \end{macrocode}
%
-% \subsection{Twocolumn printing}
+% \subsection{Two-column printing}
%
% Two-column and one-column printing is again realized via a switch.
% \begin{macrocode}
@@ -788,7 +788,7 @@
% \begin{macro}{\parindent}
% |\parskip| gives extra vertical space between paragraphs and
% |\parindent| is the width of the paragraph indentation. The value
-% of |\parindent| depends on whether we are in two column mode.
+% of |\parindent| depends on whether we are in two-column mode.
% \changes{v1.0m}{1994/01/12}{\cs{parindent} should be different,
% depending on the pointsize}
% \begin{macrocode}
@@ -998,7 +998,7 @@
% Now we can set the |\textwidth|, depending on whether we will be
% setting one or two columns.
%
-% In two column mode each \emph{column} shouldn't be wider than
+% In two-column mode each \emph{column} shouldn't be wider than
% |\@tempdimb| (which could happen on \textsc{a3} paper for
% instance).
% \begin{macrocode}
@@ -1010,7 +1010,7 @@
\fi
% \end{macrocode}
%
-% In one column mode the text should not be wider than the minimum
+% In one-column mode the text should not be wider than the minimum
% of the paperwidth (minus 2 inches for the margins) and the
% maximum length of a line as defined by the number of characters.
% \begin{macrocode}
@@ -1168,7 +1168,7 @@
\fi
%</!bk>
% \end{macrocode}
-% And values for two column mode:
+% And values for two-column mode:
% \begin{macrocode}
\if@twocolumn
\setlength\oddsidemargin {30\p@}
@@ -1389,7 +1389,7 @@
%
% \begin{macro}{\c@dbltopnumber}
% The \Lcount{dbltopnumber} counter holds the maximum number of
-% two column floats that can appear on the top of a two column text
+% two-column floats that can appear on the top of a two-column text
% page.
% \begin{macrocode}
\setcounter{dbltopnumber}{2}
@@ -1397,8 +1397,8 @@
% \end{macro}
%
% \begin{macro}{\dbltopfraction}
-% This indicates the maximum part of a two column text page that
-% can be occupied by two column floats at the top.
+% This indicates the maximum part of a two-column text page that
+% can be occupied by two-column floats at the top.
% \changes{v1.0h}{1993/12/18}{Replaced \cs{newcommand} with
% \cs{renewcommand}. ASAJ.}
% \begin{macrocode}
@@ -1408,7 +1408,7 @@
%
% \begin{macro}{\dblfloatpagefraction}
% This indicates the minimum part of a page that has to be
-% occupied by two column wide floating objects before a `float
+% occupied by two-column wide floating objects before a `float
% page' is produced.
% \changes{v1.0h}{1993/12/18}{Replaced \cs{newcommand} with
% \cs{renewcommand}. ASAJ.}
@@ -1459,7 +1459,7 @@
% \begin{macro}{\dblfloatsep}
% \begin{macro}{\dbltextfloatsep}
% When floating objects that span the whole |\textwidth| are placed
-% on a text page when we are in twocolumn mode the separation
+% on a text page when we are in two-column mode the separation
% between the float and the text is controlled by |\dblfloatsep|
% and |\dbltextfloatsep|.
%
@@ -1498,7 +1498,7 @@
% whitespace. Between adjacent floats the |\@fpsep| is inserted.
%
% These parameters are used for the placement of floating objects
-% in one column mode, or in single column floats in two column
+% in one-column mode, or in single-column floats in two-column
% mode.
%
% Note that at least one of the two parameters |\@fptop| and
@@ -1528,7 +1528,7 @@
% \begin{macro}{\@dblfptop}
% \begin{macro}{\@dblfpsep}
% \begin{macro}{\@dblfpbot}
-% Double column floats in two column mode are handled with similar
+% Double-column floats in two-column mode are handled with similar
% parameters.
% \begin{macrocode}
%<*10pt>
@@ -1809,7 +1809,7 @@
\let \footnote \thanks
% \end{macrocode}
% We center the entire title vertically; the centering is set off a
-% little by adding a |\vskip|. (In compatibility mode the pagenumber
+% little by adding a |\vskip|. (In compatibility mode the page number
% is set to 0 by the titlepage environment to keep the behaviour
% of \LaTeX\ 2.09 style files.)
% \changes{v1.0g}{1993/12/09}{Removed the setting of the page number,
@@ -1872,7 +1872,7 @@
% \end{macrocode}
% When the title is not on a page of its own, the layout of the
% title is a little different. We use symbols to mark the footnotes
-% and we have to deal with two column documents.
+% and we have to deal with two-column documents.
%
% Therefore we first start a new group to keep changes local. Then
% we redefine |\thefootnote| to use |\fnsymbol|; and change
@@ -1893,7 +1893,7 @@
\hb@xt@1.8em{%
\hss\@textsuperscript{\normalfont\@thefnmark}}##1}%
% \end{macrocode}
-% If this is a twocolumn document we start a new page in twocolumn
+% If this is a two-column document we start a new page in two-column
% mode, with the title set to the full width of the text. The
% actual printing of the title information is left to
% |\@maketitle|.
@@ -1908,7 +1908,7 @@
\fi
\else
% \end{macrocode}
-% When this is not a twocolumn document we just start a new page,
+% When this is not a two-column document we just start a new page,
% prevent floating objects from appearing on the top of this page
% and print the title information.
% \begin{macrocode}
@@ -2133,10 +2133,10 @@
% \Lcount{COUNTER} as an arabic numeral.
%
% |\roman{|\Lcount{COUNTER}|}| prints the value of
-% \Lcount{COUNTER} as a lowercase roman numberal.
+% \Lcount{COUNTER} as a lowercase roman numeral.
%
% |\Roman{|\Lcount{COUNTER}|}| prints the value of
-% \Lcount{COUNTER} as an uppercase roman numberal.
+% \Lcount{COUNTER} as an uppercase roman numeral.
%
% |\alph{|\Lcount{COUNTER}|}| prints the value of \Lcount{COUNTER}
% as a lowercase letter: $1 =$~a, $2 =$~ b, etc.
@@ -2144,7 +2144,7 @@
% |\Alph{|\Lcount{COUNTER}|}| prints the value of \Lcount{COUNTER}
% as an uppercase letter: $1 =$~A, $2 =$~B, etc.
%
-% Actually to save space the internal counter repesentations
+% Actually to save space the internal counter representations
% and the commands operating on those are used.
% \begin{macrocode}
\renewcommand \thepart {\@Roman\c@part}
@@ -2281,7 +2281,7 @@
\fi
\thispagestyle{plain}%
% \end{macrocode}
-% When we are making a two column document, this will be a one
+% When we are making a two-column document, this will be a one
% column page. We use |@tempswa| to remember to switch back to two
% columns.
% \begin{macrocode}
@@ -2453,8 +2453,8 @@
\fi
\fi
% \end{macrocode}
-% When this was a two column document we have to switch back to two
-% column mode.
+% When this was a two-column document we have to switch back to
+% two-column mode.
% \begin{macrocode}
\if@tempswa
\twocolumn
@@ -2522,8 +2522,8 @@
% \end{macrocode}
% Then we call upon |\@makechapterhead| to format the actual
% chapter title. We have to do this in a special way when we are in
-% twocolumn mode in order to have the chapter title use the entire
-% |\textwidth|. In one column mode we call |\@afterheading| which
+% two-column mode in order to have the chapter title use the entire
+% |\textwidth|. In one-column mode we call |\@afterheading| which
% takes care of suppressing the indentation.
% \begin{macrocode}
\if@twocolumn
@@ -2705,7 +2705,7 @@
% \changes{v1.3q}{1995/12/20}{Temporary(?) fix: revert to setting
% \cs{leftmargin} at outer level}
%
-% When we are in two column mode some of the margins are set somewhat
+% When we are in two-column mode some of the margins are set somewhat
% smaller.
% \begin{macrocode}
\if@twocolumn
@@ -2953,11 +2953,12 @@
% the labels of the various itemization levels: the symbols used are
% bullet, bold en-dash, centered asterisk and centred dot.
%
+% \changes{v1.4n}{2021/06/11}{Drop incorrect space in \cs{labelitemiv} (gh/496)}
% \begin{macrocode}
\newcommand\labelitemi {\labelitemfont \textbullet}
\newcommand\labelitemii {\labelitemfont \bfseries \textendash}
\newcommand\labelitemiii{\labelitemfont \textasteriskcentered}
-\newcommand\labelitemiv{ \labelitemfont \textperiodcentered}
+\newcommand\labelitemiv {\labelitemfont \textperiodcentered}
% \end{macrocode}
%
% \begin{macro}{\labelitemfont}
@@ -2966,13 +2967,16 @@
% produced regardless of surrounding conditions.
%
% \changes{v1.4l}{2019/12/20}{Normalize label fonts}
-% A possible alternative would be
+% Possible alternatives would be, for example,
%\begin{verbatim}
-%\renewcommand\labelitemfont{%
-% \fontseries\seriesdefault
-% \fontshape\shapedefault\selectfont}
+% \renewcommand\labelitemfont
+% {\normalfont\fontfamily{lmss}\selectfont}
+% \renewcommand\labelitemfont
+% {\rmfamily\normalshape}
%\end{verbatim}
-% which resets series and shape doesn't touch the family.
+% the first would use symbols from Latin Modern Sans, the second
+% would only allow changes in the font series so that an
+% \texttt{itemize} in a bold context would produce bolder symbols.
% \begin{macrocode}
\newcommand\labelitemfont{\normalfont}
% \end{macrocode}
@@ -3036,7 +3040,7 @@
{\par\vfil\null\endtitlepage}
% \end{macrocode}
% When we are not making a separate titlepage --the default for the
-% article document class-- we have to check if we are in twocolumn
+% article document class-- we have to check if we are in two-column
% mode. In that case the abstract is as a |\section*|, otherwise
% the quotation environment is used to typeset the abstract.
% \begin{macrocode}
@@ -3125,13 +3129,16 @@
%
% \begin{environment}{titlepage}
% In the normal environments, the titlepage environment does nothing
-% but start and end a page, and inhibit page numbers. In the report
-% style, it also resets the page number to one, and then sets it
-% back to one at the end. In compatibility mode, it sets the
-% page number to zero. This is incorrect since it results in using
-% the page parameters for a right-hand page but it is the way it was.
-% In two-column style, it still makes a
-% one-column page.
+% but start and end a page, and inhibit page numbers. When \LaTeX\ is
+% in two-column mode, the environmont temporarily switches to
+% one-column mode.
+% In the report class, it also resets the page number to one, and
+% then, in two-column mode, sets it back to one at the end.
+% For the book class the environment makes sure that the title page
+% is on a recto page by issueing a \cs{cleardouplepage}-command.
+% In compatibility mode, it sets the page number to zero. This is
+% incorrect since it results in using the page parameters for a
+% right-hand page but it is the way it was.
%
% \changes{v1.0g}{1993/12/09}{Moved the setting of
% \cs{@restonecolfalse}}
@@ -3291,7 +3298,7 @@
% \begin{macro}{\@minipagerestore}
% The macro |\@minipagerestore| is called upon entry to a minipage
% environment to set up things that are to be handled differently
-% inside a minipage environment. In the current styles, it does
+% inside a minipage environment. In the current classes, it does
% nothing.
% \end{macro}
%
@@ -3397,7 +3404,7 @@
% a figure is defined using the macros |\@float| and |\end@float|,
% which are defined in \file{latex.dtx}.
%
-% An environment that implements a single column floating object is
+% An environment that implements a single-column floating object is
% started with |\@float{|\texttt{TYPE}|}[|\meta{placement}|]| of type
% \texttt{TYPE} with \meta{placement} as the placement specifier.
% The default value of \meta{PLACEMENT} is defined by |\fps@TYPE|.
@@ -3449,7 +3456,7 @@
% \begin{environment}{figure}
% \begin{environment}{figure*}
% And the definition of the actual environment. The form with the
-% |*| is used for double column figures.
+% |*| is used for double-column figures.
% \begin{macrocode}
\newenvironment{figure}
{\@float{figure}}
@@ -3506,7 +3513,7 @@
% \begin{environment}{table}
% \begin{environment}{table*}
% And the definition of the actual environment. The form with the
-% |*| is used for double column tables.
+% |*| is used for double-column tables.
% \begin{macrocode}
\newenvironment{table}
{\@float{table}}
@@ -3743,7 +3750,7 @@
% \begin{macro}{\tableofcontents}
% This macro is used to request that \LaTeX{} produces a table of
% contents. In the report and book document classes the tables of
-% contents, figures etc. are always set in single-column style.
+% contents, figures etc. are always set in single-column mode.
%
% \changes{v1.0g}{1993/12/09}{Moved the setting of
% \cs{@restonecolfalse}}
@@ -3778,7 +3785,7 @@
\MakeUppercase\contentsname}{\MakeUppercase\contentsname}}%
% \end{macrocode}
% The actual table of contents is made by calling
-% |\@starttoc{toc}|. After that we restore twocolumn mode if
+% |\@starttoc{toc}|. After that we restore two-column mode if
% necessary.
% \begin{macrocode}
\@starttoc{toc}%
@@ -3823,13 +3830,13 @@
\begingroup
% \end{macrocode}
% We set |\parindent| to 0pt and use |\rightskip| to leave
-% enough room for the pagenumbers.\footnote{^^A
+% enough room for the page numbers.\footnote{^^A
% We should really set \cs{rightskip} to \cs{@tocrmarg} instead
% of \cs{@pnumwidth} (no version of {\LaTeX} ever did this),
% otherwise the \cs{rightskip} is too small.
% Unfortunately this can't be changed in {\LaTeXe} as we don't
% want to create different versions of {\LaTeXe} which produce
-% different typset output unless this is absolutely necessary;
+% different typeset output unless this is absolutely necessary;
% instead we suspend it for \LaTeX3.}
% To prevent overfull box messages the |\parfillskip| is set to a
% negative value.
@@ -3838,7 +3845,7 @@
\parfillskip -\@pnumwidth
% \end{macrocode}
% Now we can set the entry, in a large bold font. We make sure to
-% leave vertical mode, set the part title and add the pagenumber,
+% leave vertical mode, set the part title and add the page number,
% set flush right.
% \begin{macrocode}
{\leavevmode
@@ -4238,9 +4245,9 @@
\columnsep 35\p@
\let\item\@idxitem}
% \end{macrocode}
-% When the document continues after the index and it was a one
-% column document we have to switch back to one column after the
-% index.
+% When the document continues after the index and it was a
+% one-column document we have to switch back to one column after
+% the index.
% \begin{macrocode}
{\if@restonecol\onecolumn\else\clearpage\fi}
% \end{macrocode}
@@ -4293,7 +4300,7 @@
%
% \begin{macro}{\c@footnote}
% Footnotes are numbered within chapters in the report and book
-% document styles.
+% document classes.
% \begin{macrocode}
%<!article>\@addtoreset{footnote}{chapter}
% \end{macrocode}
@@ -4433,18 +4440,18 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Two column mode}
+% \subsection{Two-column mode}
%
% \begin{macro}{\columnsep}
-% This gives the distance between two columns in two column mode.
+% This gives the distance between two columns in two-column mode.
% \begin{macrocode}
\setlength\columnsep{10\p@}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\columnseprule}
-% This gives the width of the rule between two columns in two
-% column mode. We have no visible rule.
+% This gives the width of the rule between two columns in
+% two-column mode. We have no visible rule.
% \begin{macrocode}
\setlength\columnseprule{0\p@}
% \end{macrocode}
@@ -4454,7 +4461,7 @@
% We have \pstyle{plain} pages in the document classes article and
% report unless the user specified otherwise. In the `book'
% document class we use the page style \pstyle{headings} by
-% default. We use arabic pagenumbers.
+% default. We use arabic page numbers.
% \begin{macrocode}
%<!book>\pagestyle{plain}
%<book>\pagestyle{headings}
diff --git a/macros/latex/base/classes.ins b/macros/latex/base/classes.ins
index 13d4974727..be0dcaf8ff 100644
--- a/macros/latex/base/classes.ins
+++ b/macros/latex/base/classes.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/classes.pdf b/macros/latex/base/classes.pdf
index 7158ffe5e8..14c42c316e 100644
--- a/macros/latex/base/classes.pdf
+++ b/macros/latex/base/classes.pdf
Binary files differ
diff --git a/macros/latex/base/clsguide.pdf b/macros/latex/base/clsguide.pdf
index 39a99b0d26..b9d90891ef 100644
--- a/macros/latex/base/clsguide.pdf
+++ b/macros/latex/base/clsguide.pdf
Binary files differ
diff --git a/macros/latex/base/clsguide.tex b/macros/latex/base/clsguide.tex
index d778bf9ff4..3667210e5f 100644
--- a/macros/latex/base/clsguide.tex
+++ b/macros/latex/base/clsguide.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -34,7 +34,7 @@
\title{\LaTeXe~for class and package writers}
-\author{Copyright \copyright~1995--2006 The \LaTeX3 Project\\
+\author{Copyright \copyright~1995--2006 The \LaTeX\ Project\\
All rights reserved}
\date{15 February 2006}
diff --git a/macros/latex/base/cmextra.ins b/macros/latex/base/cmextra.ins
index 05776a6807..c530e04d0b 100644
--- a/macros/latex/base/cmextra.ins
+++ b/macros/latex/base/cmextra.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/cmfonts.fdd b/macros/latex/base/cmfonts.fdd
index 1eb318b049..f991ee564e 100644
--- a/macros/latex/base/cmfonts.fdd
+++ b/macros/latex/base/cmfonts.fdd
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 1993-2019
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/cmfonts.ins b/macros/latex/base/cmfonts.ins
index b5ed3e3f10..d54a325f42 100644
--- a/macros/latex/base/cmfonts.ins
+++ b/macros/latex/base/cmfonts.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/cmfonts.pdf b/macros/latex/base/cmfonts.pdf
index 18f18adb32..845b56d2ae 100644
--- a/macros/latex/base/cmfonts.pdf
+++ b/macros/latex/base/cmfonts.pdf
Binary files differ
diff --git a/macros/latex/base/cyrguide.pdf b/macros/latex/base/cyrguide.pdf
index 2ae5f0aae3..bc4155b431 100644
--- a/macros/latex/base/cyrguide.pdf
+++ b/macros/latex/base/cyrguide.pdf
Binary files differ
diff --git a/macros/latex/base/cyrguide.tex b/macros/latex/base/cyrguide.tex
index 44c30b1153..07d4bc0b3f 100644
--- a/macros/latex/base/cyrguide.tex
+++ b/macros/latex/base/cyrguide.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
\title{Cyrillic languages support in \LaTeX}
\author{\copyright~Copyright 1998--1999,\\ Vladimir Volovich,
- Werner Lemberg and \LaTeX3 Project Team.\\ All rights reserved.}
+ Werner Lemberg and \LaTeX\ Project Team.\\ All rights reserved.}
\date{12 March 1999}
@@ -381,7 +381,7 @@ font encoding definition files, then you could try using the
experimental \textsf{mathtext} package, which is also in the
\textsf{T2}~bundle. Note that this package uses up at least one
additional math alphabet per font encoding. For this and other
-reasons, The \LaTeX3 Project Team considers that this experimental
+reasons, The \LaTeX\ Project Team considers that this experimental
extension to \LaTeX{}'s glyph-handling mechanisms should be used with
caution; but please try it out and send us your opinions and ideas.
Note that it is not included in the core of \LaTeX{} because both the
diff --git a/macros/latex/base/doc-v3beta.sty b/macros/latex/base/doc-v3beta.sty
new file mode 100644
index 0000000000..eeac71568c
--- /dev/null
+++ b/macros/latex/base/doc-v3beta.sty
@@ -0,0 +1,1241 @@
+%%
+%% This is file `doc-v3beta.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% doc.dtx (with options: `package,beta')
+%%
+%% 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.html
+%% (but please observe conditions on bug reports sent to that address!)
+%%
+%%
+%% Copyright 1993-2018
+%% The LaTeX3 Project and any individual authors listed elsewhere
+%% in this file.
+%%
+%% This file was generated from file(s) 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 2005/12/01 or later.
+%%
+%% This file has the LPPL maintenance status "maintained".
+%%
+%% This file may only be distributed together with a copy of the LaTeX
+%% base system. You may however distribute the LaTeX base system without
+%% such generated files.
+%%
+%% 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.
+\NeedsTeXFormat{LaTeX2e}[1994/12/01]
+
+\providecommand\DeclareRelease[3]{}
+\providecommand\DeclareCurrentRelease[2]{}
+
+\DeclareRelease{v2}{2016-02-15.sty}
+ {doc-2016-02-15.sty}
+\DeclareCurrentRelease{v3}{2018-04-16}
+
+\ProvidesPackage{doc-v3beta}
+ [2021/02/07 v3.0e
+ Standard LaTeX documentation package V3 (FMi)]
+%%
+%% Package `doc' to use with LaTeX 2e
+%% Copyright (C) 1989-2018 Frank Mittelbach, all rights reserved.
+
+
+
+
+
+\@ifundefined{macro@cnt}{}{\endinput}
+\catcode`\^^A=14
+\AtBeginDocument{\catcode`\^^A=14\relax}
+\RequirePackage{kvoptions}
+\SetupKeyvalOptions{family=doc,prefix=doc@}
+\DeclareBoolOption{noprint}
+\DeclareBoolOption{noindex}
+\DeclareBoolOption[true]{hyperref}
+\DeclareBoolOption[true]{multicol}
+\DeclareBoolOption[false]{debugshow}
+\DeclareBoolOption[true]{toplevel}
+\DeclareComplementaryOption{notoplevel}{toplevel}
+\DeclareBoolOption{macrolike}
+\DeclareComplementaryOption{envlike}{macrolike}
+\DeclareStringOption{idxtype}
+\DeclareStringOption{idxgroup}
+\DeclareStringOption{printtype}
+\DeclareBoolOption[false]{outer}
+\ProcessKeyvalOptions*
+\newif\ifscan@allowed \scan@allowedtrue
+\def\SetupDoc#1{%
+ \setkeys{doc}{#1}%
+ \edef\doc@noprintdefault{\ifdoc@noprint true\else false\fi}%
+ \ifdoc@noindex
+ \def\doc@noindexdefault{true}%
+ \scan@allowedfalse
+ \else
+ \def\doc@noindexdefault{false}%
+ \fi
+}
+\SetupDoc{} % just save the default values
+\def\macrocode{\macro@code
+ \frenchspacing \@vobeyspaces
+ \xmacro@code}
+\def\macro@code{%
+ \topsep \MacrocodeTopsep
+ \@beginparpenalty \predisplaypenalty
+ \if@inlabel\leavevmode\fi
+ \trivlist \parskip \z@ \item[]%
+ \macro@font
+ \leftskip\@totalleftmargin \advance\leftskip\MacroIndent
+ \rightskip\z@ \parindent\z@ \parfillskip\@flushglue
+ \blank@linefalse \def\par{\ifblank@line
+ \leavevmode\fi
+ \blank@linetrue\@@par
+ \penalty\interlinepenalty}
+ \obeylines
+ \let\do\do@noligs \verbatim@nolig@list
+ \let\do\@makeother \dospecials
+ \global\@newlistfalse
+ \global\@minipagefalse
+ \ifcodeline@index
+ \everypar{\global\advance\c@CodelineNo\@ne
+ \llap{\theCodelineNo\ \hskip\@totalleftmargin}%
+ \check@module}%
+ \else \everypar{\check@module}%
+ \fi
+ \init@crossref}
+\newif\ifblank@line
+\def\endmacrocode{%
+ \ifpm@module \endgroup \pm@modulefalse \fi
+ \everypar{}%
+ \global\@inlabelfalse
+ \endtrivlist
+ \close@crossref}
+\@ifundefined{MacroFont}{%
+ \if@compatibility
+ \def\MacroFont{\small
+ \usefont\encodingdefault
+ \ttdefault
+ \mddefault
+ \updefault
+ }%
+ \else
+ \def\MacroFont{\fontencoding\encodingdefault
+ \fontfamily\ttdefault
+ \fontseries\mddefault
+ \fontshape\updefault
+ \small}%
+ \fi
+ }{}
+\@ifundefined{AltMacroFont}{%
+ \if@compatibility
+ \def\AltMacroFont{\small
+ \usefont\encodingdefault
+ \ttdefault
+ \mddefault
+ \sldefault
+ }%
+ \else
+ \def\AltMacroFont{\fontencoding\encodingdefault
+ \fontfamily\ttdefault
+ \fontseries\mddefault
+ \fontshape\sldefault
+ \small
+ }%
+ \fi
+ }{}
+\AtBeginDocument{\let\macro@font\MacroFont}
+\def\check@module{%
+ \ifcheck@modules
+ \ifpm@module \endgroup \pm@modulefalse \fi
+ \expandafter\futurelet\expandafter\next\expandafter\ch@percent
+ \fi}
+\newif\ifpm@module
+\def\DontCheckModules{\check@modulesfalse}
+\def\CheckModules{\check@modulestrue}
+\newif\ifcheck@modules \check@modulestrue
+\def\ch@percent{%
+ \if \percentchar\next
+ \expandafter\check@angle
+ \fi}
+\def\check@angle#1{\futurelet\next\ch@angle}
+\begingroup
+\catcode`\<\active
+\gdef\ch@angle{\ifx<\next
+ \expandafter\ch@plus@etc
+ \else \percentchar \fi}
+\gdef\ch@plus@etc<{\futurelet\next\check@plus@etc}
+\gdef\check@plus@etc{%
+ \if +\next
+ \let\next\pm@module
+ \else\if -\next
+ \let\next\pm@module
+ \else\if *\next
+ \let\next\star@module
+ \else\if /\next
+ \let\next\slash@module
+ \else\ifx <\next
+ \percentchar
+ \else
+ \let\next\pm@module
+ \fi\fi\fi\fi\fi
+ \next}
+\endgroup
+\begingroup
+\catcode`\~=\active
+\lccode`\~=`\>
+\lowercase{\gdef\pm@module#1~}{\pm@moduletrue
+ \Module{#1}\begingroup
+ \advance\guard@level\@ne
+ \ifnum\guard@level>\c@StandardModuleDepth\AltMacroFont\fi
+}
+\lowercase{\gdef\star@module#1~}{%
+ \Module{#1}%
+ \global \advance \guard@level\@ne
+ \ifnum \guard@level>\c@StandardModuleDepth
+ \global\let\macro@font=\AltMacroFont \macro@font
+ \fi}
+\catcode`\>=\active
+\gdef\slash@module#1>{%
+ \Module{#1}%
+ \global \advance \guard@level\m@ne
+ \ifnum \guard@level=\c@StandardModuleDepth
+ \global\let\macro@font\MacroFont \macro@font
+ \fi
+}
+\endgroup
+\newcounter{StandardModuleDepth}
+\newcount \guard@level
+
+\@ifundefined{Module}{%
+ \def\Module#1{\mod@math@codes$\langle\mathsf{#1}\rangle$}
+ }{}
+\def\mod@math@codes{\mathcode`\|="226A \mathcode`\&="2026
+ \mathcode`\-="702D \mathcode`\+="702B
+ \mathcode`\:="703A \mathcode`\=="703D }
+\newskip\MacrocodeTopsep \MacrocodeTopsep = 3pt plus 1.2pt minus 1pt
+\newdimen\MacroIndent
+\settowidth\MacroIndent{\rmfamily\scriptsize 00\ }
+\@namedef{macrocode*}{\macro@code\sxmacro@code}
+\expandafter\let\csname endmacrocode*\endcsname = \endmacrocode
+\catcode`\!=\catcode`\% ^^A In this section there must not be
+ ^^A any exclamation marks.
+ ^^A
+\begingroup
+\catcode`\|=\z@ \catcode`\[=\@ne \catcode`\]=\tw@
+\catcode`\{=12 \catcode`\}=12
+\catcode`\%=12 \catcode`\ =\active \catcode`\\=\active
+!% \end{macrocode*}
+! Next follows the actual definition of |\macro@code|;
+! notice the
+! use of the new escape character. We manage to get the argument
+! surrounded by the string |\end{macrocode}|, but at the end
+! however, in spite of the actual characters used during the
+! definition of
+! this macro, |\end| with the argument |{macrocode}|
+! will be executed, to ensure a balanced environment.
+! \begin{macrocode*}
+|gdef|xmacro@code#1% \end{macrocode}[#1|end[macrocode]]
+!% \end{macrocode*}
+! \begin{macro}{\sxmacro@code}
+! The definition of |\sxmacro@code| is completely analogous,
+! only
+! here a slightly different terminating string will be used.
+! Note that the space is not active in this environment.
+! \begin{macrocode}
+|catcode`| =12
+|gdef|sxmacro@code#1% \end{macrocode*}[#1|end[macrocode*]]
+!% \end{macrocode}
+! because the |\catcode| changes have been made local by
+! commencing a
+! new group, there now follows the matching |\endgroup|
+! in a rather
+! unusual style of writing.
+! \begin{macrocode}
+|endgroup
+!% \end{macrocode}
+\catcode`\!=12
+
+\reversemarginpar
+\setlength\marginparpush{0pt} \setlength\marginparwidth{8pc}
+\setlength\marginparsep{\labelsep}
+{\catcode`\|=\z@ \catcode`\\=12
+|gdef|bslash{\}}
+\def\verbatim{\@beginparpenalty \predisplaypenalty \@verbatim
+ \MacroFont \frenchspacing \@vobeyspaces \@xverbatim}
+\@namedef{verbatim*}{\@beginparpenalty \predisplaypenalty \@verbatim
+ \MacroFont \@sxverbatim}
+\def\@verbatim{\trivlist \item[]\if@minipage\else\vskip\parskip\fi
+ \leftskip\@totalleftmargin\rightskip\z@
+ \parindent\z@\parfillskip\@flushglue\parskip\z@
+ \@@par
+ \@tempswafalse
+ \def\par{\if@tempswa\hbox{}\fi\@tempswatrue\@@par
+ \penalty\interlinepenalty
+ \check@percent}%
+ \obeylines
+ \let\do\do@noligs \verbatim@nolig@list
+ \let\do\@makeother \dospecials}
+{\catcode`\%=12
+ \long\gdef\check@percent#1{\ifx #1%\let\next\@empty \else
+ \let\next=#1\fi \next}}
+\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}}
+\let\verb@balance@group\@empty
+
+\def\verb@egroup{\global\let\verb@balance@group\@empty\egroup}
+
+\begingroup
+ \obeylines%
+ \gdef\verb@eol@error{\obeylines%
+ \def^^M{\verb@egroup\@latex@error{%
+ Text for \noexpand\verb command ended by end of line}\@ehc}}%
+\endgroup
+\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}}
+\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}}}
+\newcount\macro@cnt \macro@cnt=0
+\newskip\MacroTopsep \MacroTopsep = 7pt plus 2pt minus 2pt
+\begingroup
+\catcode`\~\active
+\gdef\SpecialEscapechar#1{%
+ \begingroup
+ \uccode`\~`#1%
+ \uppercase{\gdef\active@escape@char{~}}%
+ \escapechar\m@ne \xdef\special@escape@char{\string#1}%
+ \endgroup}
+\endgroup
+\begingroup \catcode`\|=\z@ \catcode`\\=\active
+|gdef|init@crossref{|catcode`|\|active |let\|bslash
+ |MakePrivateLetters
+ |catcode|expandafter`|special@escape@char|active
+ |expandafter|let|active@escape@char|scan@macro}
+|endgroup
+\SpecialEscapechar{\\}
+\@ifundefined{MakePrivateLetters}
+ {\let\MakePrivateLetters\makeatletter}{}
+\def\close@crossref{\SpecialEscapechar\\}
+\def\scan@macro{%
+ \special@escape@char
+ \step@checksum
+ \ifscan@allowed
+ \let\macro@namepart\@empty
+ \def\next{\futurelet\next\macro@switch}%
+ \else \let\next\@empty \fi
+ \next}
+\def\DisableCrossrefs{\@bsphack\scan@allowedfalse\@esphack}
+\def\EnableCrossrefs{\@bsphack\scan@allowedtrue
+ \def\DisableCrossrefs{\@bsphack\@esphack}\@esphack}
+\def\macro@switch{\ifcat\noexpand\next a%
+ \let\next\macro@name
+ \else \let\next\short@macro \fi
+ \next}
+\begingroup
+\catcode`\&=12
+\gdef\short@macro#1{\begingroup
+ \uccode`\&=\expandafter`\string#1%
+ \uppercase{\def\x{\def\macro@namepart{&}}}%
+ \expandafter\endgroup\x
+ \maybe@index@short@macro\macro@namepart
+ \scan@allowedfalse#1%
+ \scan@allowedtrue }
+\endgroup
+\def\macro@name#1{\edef\macro@namepart{\macro@namepart#1}%
+ \futurelet\next\more@macroname}
+\def\more@macroname{\ifcat\noexpand\next a%
+ \let\next\macro@name
+ \else \let\next\macro@finish \fi
+ \next}
+\def\macro@finish{%
+ \macro@namepart
+ \maybe@index@macro \macro@namepart
+}
+
+\RequirePackage{expl3}
+\ExplSyntaxOn
+\seq_new:N \l__doc_donotindex_seq
+\prop_new:N \g__doc_idxtype_prop
+\cs_new:Npn\__doc_trace:x {
+ \ifdoc@debugshow
+ \expandafter \iow_term:x
+ \else
+ \expandafter \use_none:n
+ \fi
+}
+\cs_new:Npn \doc_dont_index:n {
+ \group_begin:
+ \MakePrivateLetters
+ \__doc_dont_index:n
+}
+\cs_new:Npn \__doc_dont_index:n #1 {
+ \group_end:
+ \__doc_trace:x{Disable~ indexing~ for~ '\tl_to_str:n{#1}' }
+ \clist_map_function:nN {#1} \__doc_dont_index_aux:n
+}
+\cs_new:Npn \__doc_dont_index_aux:n #1 {
+ \seq_put_right:Nx \l__doc_donotindex_seq {\expandafter\@gobble \string#1}
+}
+\cs_set_eq:NN \DoNotIndex \doc_dont_index:n
+\def \ShowIndexingState {
+ \__doc_trace:x{Show~ doc~ indexing~ state:}
+ \seq_show:N \l__doc_donotindex_seq
+ \prop_show:N \g__doc_idxtype_prop
+}
+
+\cs_new:Npn \__doc_idxtype_put:Nn #1#2 {
+ \exp_args:Nx \__doc_idxtype_put:nn { \cs_to_str:N #1 }{#2}
+ \protected@write\@auxout{}
+ {\string\RecordIndexTypeAux {\string#1 }{#2} }
+}
+\cs_new:Npn \RecordIndexTypeAux #1#2 {
+ \exp_args:Nx \__doc_idxtype_put:nn { \cs_to_str:N #1 }{#2}
+}
+\AtEndDocument{
+ \cs_set_eq:NN \RecordIndexTypeAux \use_none:nn
+}
+\cs_set_eq:NN \RecordIndexType \__doc_idxtype_put:Nn
+\cs_new:Npn \__doc_idxtype_put_scan:nn #1#2 {
+ \exp_args:Nf \__doc_idxtype_put:nn { \tl_to_str:n {#1} }{#2}
+ \protected@write\@auxout{}
+ {\string\RecordIndexTypeAux {\bslash #1 }{#2} }
+}
+\cs_generate_variant:Nn \__doc_idxtype_put_scan:nn {o}
+\cs_set_eq:NN \record@index@type@save \__doc_idxtype_put_scan:on
+\cs_new:Npn \__doc_idxtype_put:nn #1#2 {
+ \exp_args:NNf
+ \seq_if_in:NnTF \l__doc_donotindex_seq {\tl_to_str:n{#1}}
+ {
+ \__doc_trace:x{Not~ recording~ index~ type~ for~ '\bslash #1' }
+ }
+ {
+ \__doc_trace:x{Recording~ index~ type~ for~ '\bslash #1' ~ as~ #2 }
+ \prop_gput:Nnn \g__doc_idxtype_prop {#1}{#2}
+ }
+}
+\cs_new:Npn \exp_args:co #1#2
+ { \cs:w #1 \exp_after:wN \cs_end:\exp_after:wN {#2} }
+\cs_generate_variant:Nn \tl_to_str:n {o}
+
+\cs_new:Npn \__doc_maybe_index:o #1 {
+ \exp_args:Nf \__doc_maybe_index_aux:nN { \tl_to_str:o {#1} }
+ \SpecialIndex
+}
+\cs_set_eq:NN \maybe@index@macro \__doc_maybe_index:o
+\cs_new:Npn \__doc_maybe_index_short:o #1 {
+ \exp_args:Nf \__doc_maybe_index_aux:nN { \tl_to_str:o {#1} }
+ \SpecialShortIndex
+}
+\cs_set_eq:NN \maybe@index@short@macro \__doc_maybe_index_short:o
+\cs_new:Npn \__doc_maybe_index_aux:nN #1#2 {
+ \__doc_trace:x{Searching~ for~ '\bslash #1'}
+ \seq_if_in:NnTF \l__doc_donotindex_seq {#1}
+ {
+ \__doc_trace:x{Not~ indexing~ '\bslash #1' }
+ }
+ {
+ \prop_get:NnNTF \g__doc_idxtype_prop {#1} \l__doc_idxtype_tl
+ {
+ \exp_args:Ncno \__doc_maybe_index_aux:Nnn
+ { Code \tl_use:N \l__doc_idxtype_tl Index }
+ {code} {\bslash #1}
+ }
+ {
+ \__doc_trace:x{Indexing~ '\bslash #1'\space (\string #2)}
+ \exp_args:No #2 {\bslash #1}
+ }
+ }
+}
+\cs_new:Npn \SpecialShortIndex #1 {
+ \@SpecialIndexHelper@ #1\@nil
+ \@bsphack
+ \ifdoc@noindex \else
+ \str_case_e:nnF {\@gtempa }
+ {
+ {\cs_to_str:N \^^M } {\def\reserved@a{ \string \space \actualchar }
+ \def\reserved@b { \space }
+ \let\reserved@c \@empty }
+ { } {\def\reserved@a{ \string \space \actualchar }
+ \def\reserved@b { \space }
+ \let\reserved@c \@empty }
+ {\c_left_brace_str} { \def\reserved@a{ \bgroup \actualchar }
+ \def\reserved@b { \c_left_brace_str }
+ \def\reserved@c { \noexpand\iffalse
+ \c_right_brace_str
+ \noexpand\fi } }
+ {\c_right_brace_str} { \def\reserved@a{ \egroup \actualchar
+ \noexpand\iffalse
+ \c_left_brace_str
+ \noexpand\fi }
+ \def\reserved@b { \c_right_brace_str }
+ \let\reserved@c \@empty }
+ {\verbatimchar} { \def\reserved@a{ \quotechar\verbatimchar
+ \actualchar }
+ \let\reserved@b \@empty
+ \def\reserved@c
+ { \string\texttt{\string\string\verbatimchar} } }
+ }
+ { \def\reserved@a {\quotechar \@gtempa \actualchar }
+ \def\reserved@b {\quotechar \@gtempa }
+ \let\reserved@c \@empty }
+ \special@index {
+ \reserved@a
+ \string\verb
+ \quotechar *\verbatimchar \quotechar \bslash
+ \reserved@b
+ \verbatimchar
+ \reserved@c
+ \encapchar code}
+ \fi
+ \@esphack
+}
+
+\cs_new:Npn \__doc_maybe_index_aux:Nnn #1#2#3 {
+ \cs_if_exist:NTF #1
+ {
+ \__doc_trace:x{Indexing~ '#3'\space as~
+ \tl_use:N \l__doc_idxtype_tl }
+ #1{#2}{#3}
+ }
+ {
+ \PackageError{doc}{Doc~ element~
+ '\tl_use:N \l__doc_idxtype_tl'~ unknown}%
+
+ {When~ using~ '\string\RecordIndexType'~ the~ type~ must~
+ be~ known~\MessageBreak
+ to~ the~ system,~ i.e.,~ declared~ via~
+ '\string\NewDocElement'\MessageBreak
+ before~ it~ can~ be~ used~ in~ indexing.}
+ }
+}
+\ExplSyntaxOff
+\@ifundefined{actualchar}{\def\actualchar{=}}{}
+\@ifundefined{quotechar}{\def\quotechar{!}}{}
+\@ifundefined{levelchar}{\def\levelchar{>}}{}
+\@ifundefined{encapchar}{\def\encapchar{|}}{}
+\@ifundefined{verbatimchar}{\def\verbatimchar{+}}{}
+\begingroup
+ \catcode`\|=0
+ \catcode`\\=12
+ |gdef|@SpecialIndexHelper@#1#2|@nil{%
+ |if |noexpand#1\%
+ |gdef|@gtempa{#2}%
+ |else
+ |begingroup
+ |escapechar|m@ne
+ |expandafter|gdef|expandafter|@gtempa|expandafter{|string#1#2}%
+ |endgroup
+ |fi}
+|endgroup
+\def\SortIndex#1#2{%
+ \ifdoc@noindex\else
+ \index{#1\actualchar#2}%
+ \fi
+}
+\@ifundefined{LeftBraceIndex}{\def\LeftBraceIndex{%
+ \special@index{\bgroup\actualchar
+ \string\verb% % to fool emacs highlighting
+ \quotechar*\verbatimchar
+ \quotechar\bslash{\verbatimchar\string\iffalse}\string\fi}}}{}
+
+\@ifundefined{RightBraceIndex}{\def\RightBraceIndex{%
+ \special@index{\egroup\actualchar\string\iffalse{\string\fi
+ \string\verb% % to fool emacs highlighting
+ \quotechar*\verbatimchar\quotechar\bslash}\verbatimchar}}}{}
+\@ifundefined{PercentIndex}
+ {\def\PercentIndex{\it@is@a\percentchar}}{}
+\def\OldMakeindex{\def\PercentIndex{%
+ \special@index{\quotechar\percentchar\actualchar
+ \string\verb% % to fool emacs highlighting
+ \quotechar*\verbatimchar\quotechar\bslash
+ \percentchar\percentchar\verbatimchar}}}
+{\catcode`\%=12 \gdef\percentchar{%}}
+\def\it@is@a#1{\special@index{\quotechar #1\actualchar
+ \string\verb% % to fool emacs highlighting
+ \quotechar*\verbatimchar
+ \quotechar\bslash\quotechar#1\verbatimchar}}
+
+\newdimen\IndexMin \IndexMin = 80pt
+\newcount\c@IndexColumns \c@IndexColumns = 3
+\ifdoc@multicol
+ \RequirePackage{multicol}
+ \renewenvironment{theindex}
+ {\begin{multicols}\c@IndexColumns[\index@prologue][\IndexMin]%
+ \IndexParms \let\item\@idxitem \ignorespaces}%
+ {\end{multicols}}
+\else
+ \def\theindex{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi
+ \columnseprule \z@ \columnsep 35\p@
+ \twocolumn[\index@prologue]%
+ \IndexParms \let\item\@idxitem \ignorespaces}
+ \def\endtheindex{\if@restonecol\onecolumn\else\clearpage\fi}
+\fi
+\long\def\IndexPrologue#1{\@bsphack\def\index@prologue{#1}\@esphack}
+\@ifundefined{index@prologue}
+ {\def\index@prologue{\section*{Index}%
+ \markboth{Index}{Index}%
+ Numbers written in italic refer to the page
+ where the corresponding entry is described;
+ numbers underlined refer to the
+ \ifcodeline@index
+ code line of the
+ \fi
+ definition; numbers in roman refer to the
+ \ifcodeline@index
+ code lines
+ \else
+ pages
+ \fi
+ where the entry is used.
+ }}{}
+\@ifundefined{IndexParms}
+ {\def\IndexParms{%
+ \parindent \z@
+ \columnsep 15pt
+ \parskip 0pt plus 1pt
+ \rightskip 15pt
+ \mathsurround \z@
+ \parfillskip=-15pt
+ \small
+ \def\@idxitem{\par\hangindent 30pt}%
+ \def\subitem{\@idxitem\hspace*{15pt}}%
+ \def\subsubitem{\@idxitem\hspace*{25pt}}%
+ \def\indexspace{\par\vspace{10pt plus 2pt minus 3pt}}%
+ }}{}
+\def\efill{\hfill\nopagebreak}%
+\def\pfill{\unskip~%
+ \leaders\hbox to.6em{\hss .\hss}\hfill
+ \penalty500\strut\nobreak
+ \leaders\hbox to.6em{\hss .\hss}\hfil
+ ~\ignorespaces}%
+\def\*{\leavevmode\lower.8ex\hbox{$\,\widetilde{\ }\,$}}
+\@ifundefined{main}{\def\main#1{\underline{#1}}}{}
+\@ifundefined{usage}{\def\usage#1{\textit{#1}}}{}
+\@ifundefined{code}{\def\code#1{#1}}{}
+\def\PrintIndex{\@input@{\jobname.ind}%
+ \global\let\PrintIndex\@empty}
+\def\changes{\@bsphack\begingroup\@sanitize
+ \catcode`\\\z@ \catcode`\ 10 \MakePercentIgnore
+ \changes@}
+\def\changes@#1#2#3{%
+ \protected@edef\@tempa{\noexpand\glossary{#1\levelchar
+ \ifx\saved@macroname\@empty
+ \quotechar!%
+ \actualchar
+ \generalname
+ \else
+ \saved@indexname
+ \actualchar
+ \string\verb% % to fool emacs highlighting
+ \quotechar*%
+ \verbatimchar\saved@macroname
+ \verbatimchar
+ \fi
+ :\levelchar #3}}%
+ \@tempa\endgroup\@esphack}
+\def\saved@macroname{}
+\def\saved@indexname{}
+\def\generalname{General}
+\let\RecordChanges\makeglossary
+\newdimen\GlossaryMin \GlossaryMin = 80pt
+\newcount\c@GlossaryColumns \c@GlossaryColumns = 2
+\ifdoc@multicol
+ \newenvironment{theglossary}{%
+ \begin{multicols}\c@GlossaryColumns
+ [\glossary@prologue][\GlossaryMin]%
+ \GlossaryParms \let\item\@idxitem \ignorespaces}%
+ {\end{multicols}}
+\else
+ \newenvironment{theglossary}{%
+ \@restonecoltrue\if@twocolumn\@restonecolfalse\fi
+ \columnseprule \z@ \columnsep 35\p@
+ \twocolumn[\glossary@prologue]%
+ \GlossaryParms \let\item\@idxitem \ignorespaces}
+ {\if@restonecol\onecolumn\else\clearpage\fi}
+\fi
+\long\def\GlossaryPrologue#1{\@bsphack
+ \def\glossary@prologue{#1}%
+ \@esphack}
+\@ifundefined{glossary@prologue}
+ {\def\glossary@prologue{\section*{{Change History}}%
+ \markboth{{Change History}}{{Change History}}%
+ }}{}
+\@ifundefined{GlossaryParms}{\let\GlossaryParms\IndexParms
+ \expandafter\def\expandafter\GlossaryParms\expandafter{\GlossaryParms
+ \rightskip 15pt plus 1fil
+ \parfillskip -15pt plus -1fil\relax}
+}{}
+\def\PrintChanges{\@input@{\jobname.gls}%
+ \global\let\PrintChanges\@empty}
+\newcommand\AlsoImplementation{%
+ \long\def\MaybeStopHere##1{\@bsphack\gdef\Finale{##1%
+ \check@checksum}%
+ \init@checksum
+ \@esphack}%
+ }
+\AlsoImplementation
+\def\OnlyDescription{\@bsphack\long\def\MaybeStopHere##1{%
+ ##1\endinput}\@esphack}
+\let\Finale\relax
+\def\StopEventually{\MaybeStopHere}
+\ifx\l@nohyphenation\undefined
+ \newlanguage\l@nohyphenation
+\fi
+\DeclareRobustCommand\meta[1]{%
+ \ensuremath\langle
+ \ifmmode \expandafter \nfss@text \fi
+ {%
+ \meta@font@select
+ \edef\meta@hyphen@restore
+ {\hyphenchar\the\font\the\hyphenchar\font}%
+ \hyphenchar\font\m@ne
+ \language\l@nohyphenation
+ #1\/%
+ \meta@hyphen@restore
+ }\ensuremath\rangle
+}
+\def\meta@font@select{\itshape}
+\def\IndexInput#1{%
+ \begingroup \macro@code
+ \frenchspacing \@vobeyspaces
+ \input{#1}\endmacrocode
+ \endgroup}
+\def\maketitle{\par
+ \begingroup \def \thefootnote {\fnsymbol {footnote}}%
+ \setcounter {footnote}\z@
+ \def\@makefnmark{\hbox to\z@{$\m@th^{\@thefnmark}$\hss}}%
+ \long\def\@makefntext##1{\parindent 1em\noindent
+ \hbox to1.8em{\hss$\m@th^{\@thefnmark}$}##1}%
+ \if@twocolumn \twocolumn [\@maketitle ]%
+ \else \newpage \global \@topnum \z@ \@maketitle \fi
+ \thispagestyle{titlepage}\@thanks \endgroup
+ \setcounter {footnote}\z@
+ \gdef\@date{\today}\gdef\@thanks{}%
+ \gdef\@author{}\gdef\@title{}}
+\@ifundefined{ps@titlepage}
+ {\let\ps@titlepage=\ps@plain}{}
+\def\MakeShortVerb{%
+ \@ifstar
+ {\def\@shortvrbdef{\verb*}\@MakeShortVerb}%
+ {\def\@shortvrbdef{\verb}\@MakeShortVerb}}
+\def\@MakeShortVerb#1{%
+ \expandafter\ifx\csname cc\string#1\endcsname\relax
+ \@shortvrbinfo{Made }{#1}\@shortvrbdef
+ \add@special{#1}%
+ \expandafter
+ \xdef\csname cc\string#1\endcsname{\the\catcode`#1}%
+ \begingroup
+ \catcode`\~\active \lccode`\~`#1%
+ \lowercase{%
+ \global\expandafter\let
+ \csname ac\string#1\endcsname~%
+ \expandafter\gdef\expandafter~\expandafter{\@shortvrbdef~}}%
+ \endgroup
+ \global\catcode`#1\active
+ \else
+ \@shortvrbinfo\@empty{#1 already}%
+ {\@empty\verb% % to fool emacs highlighting
+ (*)}%
+ \fi}
+\def\DeleteShortVerb#1{%
+ \expandafter\ifx\csname cc\string#1\endcsname\relax
+ \@shortvrbinfo\@empty{#1 not}%
+ {\@empty\verb% % to fool emacs highlighting
+ (*)}%
+ \else
+ \@shortvrbinfo{Deleted }{#1 as}%
+ {\@empty\verb% % to fool emacs
+ % highlighting
+ (*)}%
+ \rem@special{#1}%
+ \global\catcode`#1\csname cc\string#1\endcsname
+ \global \expandafter\let \csname cc\string#1\endcsname \relax
+ \ifnum\catcode`#1=\active
+ \begingroup
+ \catcode`\~\active \lccode`\~`#1%
+ \lowercase{%
+ \global\expandafter\let\expandafter~%
+ \csname ac\string#1\endcsname}%
+ \endgroup \fi \fi}
+\def\@shortvrbinfo#1#2#3{%
+ \PackageInfo{doc}{%
+ #1\expandafter\@gobble\string#2 a short reference
+ for \expandafter\string#3}}
+\def\add@special#1{%
+ \rem@special{#1}%
+ \expandafter\gdef\expandafter\dospecials\expandafter
+ {\dospecials \do #1}%
+ \expandafter\gdef\expandafter\@sanitize\expandafter
+ {\@sanitize \@makeother #1}}
+\def\rem@special#1{%
+ \def\do##1{%
+ \ifnum`#1=`##1 \else \noexpand\do\noexpand##1\fi}%
+ \xdef\dospecials{\dospecials}%
+ \begingroup
+ \def\@makeother##1{%
+ \ifnum`#1=`##1 \else \noexpand\@makeother\noexpand##1\fi}%
+ \xdef\@sanitize{\@sanitize}%
+ \endgroup}
+\def\init@checksum{\relax
+ \global\bslash@cnt\z@}
+\def\check@checksum{\relax
+ \ifnum\check@sum>\m@ne
+ \ifnum\check@sum=\z@
+ \typeout{**********************************}%
+ \typeout{* This macro file has no checksum!}%
+ \typeout{* The checksum should be \the\bslash@cnt!}%
+ \typeout{**********************************}%
+ \else
+ \ifnum\check@sum=\bslash@cnt
+ \typeout{*******************}%
+ \typeout{* Checksum passed *}%
+ \typeout{*******************}%
+ \else
+ \PackageError{doc}{Checksum not passed
+ (\the\check@sum<>\the\bslash@cnt)}%
+ {The file currently documented seems to be wrong.^^J%
+ Try to get a correct version.}%
+ \fi
+ \fi
+ \fi
+ \global\check@sum\m@ne}
+\newcount\check@sum \check@sum = \m@ne
+\newcount\bslash@cnt \bslash@cnt = \z@
+\def\CheckSum#1{\@bsphack\global\check@sum#1\relax\@esphack}
+\def\step@checksum{\global\advance\bslash@cnt\@ne}
+\def\CharacterTable{\begingroup \CharTableChanges \character@table}
+\begingroup
+ \catcode`\~=11
+ \gdef\character@table#1{\def\used~table{#1}%
+ \ifx\used~table\default~table
+ \typeout{***************************}%
+ \typeout{* Character table correct *}%
+ \typeout{***************************}%
+ \else
+ \PackageError{doc}{Character table corrupted}
+ {\the\wrong@table}
+ \show\default~table
+ \show\used~table
+ \fi
+ \endgroup}
+ \global\let\CharTableChanges\@empty
+ \makeatother
+ \gdef\default~table
+ {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+ Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+ Digits \0\1\2\3\4\5\6\7\8\9
+ Exclamation \! Double quote \" Hash (number) \#
+ Dollar \$ Percent \% Ampersand \&
+ Acute accent \' Left paren \( Right paren \)
+ Asterisk \* Plus \+ Comma \,
+ Minus \- Point \. Solidus \/
+ Colon \: Semicolon \; Less than \<
+ Equals \= Greater than \> Question mark \?
+ Commercial at \@ Left bracket \[ Backslash \\
+ Right bracket \] Circumflex \^ Underscore \_
+ Grave accent \` Left brace \{ Vertical bar \|
+ Right brace \} Tilde \~}
+\endgroup
+ \newhelp\wrong@table{Some of the ASCII characters are corrupted.^^J
+ I now \string\show\space you both tables for comparison.}
+\newif\ifcodeline@index \codeline@indexfalse
+\let\CodelineNumbered\codeline@indextrue
+\def\codeline@wrindex#1{\if@filesw
+ \begingroup
+ \set@display@protect
+ \immediate\write\@indexfile
+ {\string\indexentry{#1}%
+ {\number\c@CodelineNo}}%
+ \endgroup
+ \fi}
+\let\special@index = \@gobble
+\def\CodelineIndex{\makeindex
+ \codeline@indextrue
+ \let\special@index\codeline@wrindex}
+\def\PageIndex{\makeindex
+ \codeline@indexfalse
+ \let\special@index\index}
+\newcount\c@CodelineNo \c@CodelineNo\z@
+\@ifundefined{theCodelineNo}
+ {\ifx\selectfont\undefined
+ \def\theCodelineNo{\rmfamily\scriptsize\arabic{CodelineNo}}%
+ \else
+ \def\theCodelineNo{\reset@font\scriptsize\arabic{CodelineNo}}%
+ \fi}
+ {}
+ \tolerance=1000\relax
+{ \catcode`\"=12
+ \global\mathcode`\\="705C \global\mathcode`\@="7040 }
+\@ifundefined{DocstyleParms}{}{\DocstyleParms}
+ \let\DocstyleParms\relax
+\@ifundefined{AmSTeX}
+ {\def\AmSTeX{\leavevmode\hbox{$\mathcal A\kern-.2em\lower.376ex%
+ \hbox{$\mathcal M$}\kern-.2em\mathcal S$-\TeX}}}{}
+\@ifundefined{BibTeX}
+ {\def\BibTeX{{\rmfamily B\kern-.05em%
+ \textsc{i\kern-.025em b}\kern-.08em%
+ T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}}{}
+\@ifundefined{SliTeX}
+ {\def\SliTeX{{\rmfamily S\kern-.06emL\kern-.18em\raise.32ex\hbox
+ {\scshape i}\kern -.03em\TeX}}}{}
+\@ifundefined{PlainTeX}{\def\PlainTeX{\textsc{Plain}\kern2pt\TeX}}{}
+\@ifundefined{Web}{\def\Web{\textsc{Web}}}{}
+\def\MakePercentIgnore{\catcode`\%9\relax}
+\def\MakePercentComment{\catcode`\%14\relax}
+\def\DocInput#1{\MakePercentIgnore\input{#1}\MakePercentComment}
+\def\GetFileInfo#1{%
+ \def\filename{#1}%
+ \def\@tempb##1 ##2 ##3\relax##4\relax{%
+ \def\filedate{##1}%
+ \def\fileversion{##2}%
+ \def\fileinfo{##3}}%
+ \edef\@tempa{\csname ver@#1\endcsname}%
+ \expandafter\@tempb\@tempa\relax? ? \relax\relax}
+
+\ifdoc@hyperref
+ \let\PrintDescribeMacro \@empty
+ \let\PrintDescribeEnv \@empty
+ \let\PrintMacroName \@empty
+ \let\PrintEnvName \@empty
+ \let\SpecialUsageIndex \@empty
+ \let\SpecialEnvIndex \@empty
+ \expandafter\let\expandafter\doc@eoph@@k\csname doc.sty-h@@k\endcsname
+ \RequirePackage{hypdoc}
+ \expandafter\let\csname doc.sty-h@@k\endcsname\doc@eoph@@k
+ \let\PrintDescribeMacro \relax
+ \let\PrintDescribeEnv \relax
+ \let\PrintMacroName \relax
+ \let\PrintEnvName \relax
+ \def\doc@providetarget{\HD@target}
+ \def\doc@handleencap#1{\encapchar hdclindex{\the\c@HD@hypercount}{#1}}
+\else
+ \let\doc@providetarget\@empty
+ \def\doc@handleencap#1{\encapchar #1}
+ \def\hdclindex#1#2{\ifx\@nil#2\@nil\else\csname #2\expandafter\endcsname\fi}
+ \def\hdpindex #1{\ifx\@nil#1\@nil\else\csname #1\expandafter\endcsname\fi}
+\fi
+
+
+\ExplSyntaxOn
+
+\long\def\@doc@env#1#2#3{
+ \endgroup
+ \clist_map_inline:nn {#3} { \@doc@env@{#1}{#2}{##1} }
+}
+
+\ExplSyntaxOff
+\long\def\@doc@env@#1#2#3{%
+ \topsep\MacroTopsep
+ \trivlist
+ \edef\saved@macroname{\string#3}%
+ \if #1%
+ \edef\saved@indexname{\expandafter\@gobble\saved@macroname}%
+ \expandafter\ifx
+ \csname Code#2Index\endcsname
+ \CodeMacroIndex
+ \else
+ \record@index@type@save
+ {\saved@indexname}{#2}%
+ \fi
+ \else
+ \let\saved@indexname\saved@macroname
+ \fi
+ \def\makelabel##1{\llap{##1}}%
+ \if@inlabel
+ \let\@tempa\@empty
+ \count@\macro@cnt
+ \loop\ifnum\count@>\z@
+ \edef\@tempa{\@tempa\hbox{\strut}}\advance\count@\m@ne
+ \repeat
+ \edef\makelabel##1{\llap{\vtop to\baselineskip{\@tempa\hbox{##1}\vss}}}%
+ \advance\macro@cnt\@ne
+ \else
+ \macro@cnt\@ne
+ \fi
+ \ifdoc@noprint
+ \item
+ \else
+ \edef\@tempa{%
+ \noexpand\item[%
+ \noexpand\doc@providetarget
+ \noexpand\strut
+ \noexpand\@nameuse{Print#2Name}{\saved@macroname}]}%
+ \@tempa
+ \fi
+ \ifdoc@noindex\else
+ \global\advance\c@CodelineNo\@ne
+ \csname SpecialMain#2Index\expandafter\endcsname
+ \expandafter{\saved@macroname}\nobreak
+ \global\advance\c@CodelineNo\m@ne
+ \fi
+ \if#1\expandafter\DoNotIndex \expandafter {\saved@macroname}\fi
+ \ignorespaces}
+
+\def\doc@env#1#2[#3]{%
+ \@nameuse{doc@noprint\doc@noprintdefault}%
+ \@nameuse{doc@noindex\doc@noindexdefault}%
+ \setkeys{doc}{#3}%
+ \begingroup
+ \ifdoc@outer
+ \catcode`\\12
+ \fi
+ \MakePrivateLetters
+ \@doc@env{#1}{#2}%
+}
+
+\def\@doc@describe#1#2{%
+ \ifdoc@noprint\else
+ \marginpar{\raggedleft
+ \strut
+ \doc@providetarget
+ \@nameuse{PrintDescribe#1}{#2}}%
+ \fi
+ \ifdoc@noindex\else
+ \@nameuse{Special#1Index}{#2}%
+ \fi
+ \@esphack
+ \endgroup
+ \ignorespaces}
+\def\doc@describe#1[#2]{%
+ \leavevmode\@bsphack
+ \setkeys{doc}{#2}%
+ \@doc@describe{#1}}
+\@ifundefined{temptokenb}{\newtoks\@temptokenb}{}
+\def\doc@createspecialindexes#1#2#3{%
+ \@temptokena{\space (#2)}%
+ \@temptokenb{#3:}%
+ \@nameedef{SpecialMain#1Index}##1{%
+ \noexpand\@bsphack
+ \ifdoc@toplevel
+ \noexpand\special@index{##1\noexpand\actualchar
+ {\string\ttfamily\space##1}%
+ \ifx\@nil#2\@nil\else \the\@temptokena \fi
+ \noexpand\encapchar main}%
+ \fi
+ \ifx\@nil#3\@nil\else
+ \noexpand\special@index{\the\@temptokenb\noexpand\levelchar
+ ##1\noexpand\actualchar{\string\ttfamily\space##1}%
+ \noexpand\encapchar main}%
+ \fi
+ \noexpand\@esphack}%
+ \@nameedef{Special#1Index}##1{%
+ \noexpand\@bsphack
+ \ifdoc@toplevel
+ \noexpand\doc@providetarget
+ \noexpand\index{##1\noexpand\actualchar{\string\ttfamily\space##1}%
+ \ifx\@nil#2\@nil\else \the\@temptokena \fi
+ \noexpand\doc@handleencap{usage}}%
+ \fi
+ \ifx\@nil#3\@nil\else
+ \noexpand\index{\the\@temptokenb\noexpand\levelchar
+ ##1\noexpand\actualchar{\string\ttfamily\space##1}%
+ \noexpand\doc@handleencap{usage}}%
+ \fi
+ \noexpand\@esphack}}
+\def\doc@createspecialmacrolikeindexes#1#2#3{%
+ \@temptokena{\space (#2)}%
+ \@temptokenb{#3:}%
+ \@nameedef{Code#1Index}##1##2{%
+ \noexpand\@SpecialIndexHelper@##2\noexpand\@nil
+ \noexpand\@bsphack
+ \noexpand\ifdoc@noindex\noexpand\else
+ \ifdoc@toplevel
+ \noexpand\special@index{\noexpand\@gtempa\noexpand\actualchar
+\string\verb% % to fool emacs highlighting
+\noexpand\quotechar*\noexpand\verbatimchar
+\noexpand\bslash\noexpand\@gtempa\noexpand\verbatimchar
+\ifx\@nil#2\@nil\else \the\@temptokena \fi
+\noexpand\encapchar ##1}%
+ \fi
+ \ifx\@nil#3\@nil\else
+ \noexpand\special@index{\the\@temptokenb\noexpand\levelchar
+\noexpand\@gtempa\noexpand\actualchar
+\string\verb% % to fool emacs highlighting
+\noexpand\quotechar*\noexpand\verbatimchar
+\noexpand\bslash\noexpand\@gtempa\noexpand\verbatimchar
+\noexpand\encapchar ##1}%
+ \fi
+ \noexpand\fi
+ \noexpand\@esphack}%
+ \@nameedef{SpecialMain#1Index}##1{%
+ \expandafter\noexpand\csname Code#1Index\endcsname
+ {main}{##1}}%
+ \@nameedef{Special#1Index}##1{%
+ \noexpand\@SpecialIndexHelper@##1\noexpand\@nil
+ \noexpand\@bsphack
+ \noexpand\ifdoc@noindex\noexpand\else
+ \ifdoc@toplevel
+ \noexpand\doc@providetarget
+ \noexpand\index{\noexpand\@gtempa\noexpand\actualchar
+\string\verb% % to fool emacs highlighting
+\noexpand\quotechar*\noexpand\verbatimchar
+\noexpand\bslash\noexpand\@gtempa\noexpand\verbatimchar
+\ifx\@nil#2\@nil\else \the\@temptokena \fi
+\noexpand\doc@handleencap{usage}}%
+ \fi
+ \ifx\@nil#3\@nil\else
+ \noexpand\index{\the\@temptokenb\noexpand\levelchar
+\noexpand\@gtempa\noexpand\actualchar
+\string\verb% % to fool emacs highlighting
+\noexpand\quotechar*\noexpand\verbatimchar
+\noexpand\bslash\noexpand\@gtempa\noexpand\verbatimchar
+\noexpand\doc@handleencap{usage}}%
+ \fi
+ \noexpand\fi
+ \noexpand\@esphack}}
+
+\def\doc@createdescribe#1{%
+ \@namedef{Describe#1}{%
+ \begingroup
+ \MakePrivateLetters
+ \@ifnextchar[%]
+ {\doc@describe{#1}}{\doc@describe{#1}[]}}}
+\def\doc@createenv#1#2#3{%
+ \@namedef{#3}{%
+ \@ifnextchar[%]
+ {\doc@env{#1}{#2}}{\doc@env{#1}{#2}[]}}%
+ \@namedef{end#3}{\endtrivlist}%
+}
+
+\def\@nameedef#1{\expandafter\edef\csname #1\endcsname}
+
+
+\def\doc@declareerror#1#2{%
+ \PackageError{doc}{Doc element '#1/#2' already defined?\@gobble}%
+ {There is already a definition for
+ '\string\Print#1Name',\MessageBreak
+ '\string\PrintDescribe#1'
+ or the environment '#2'.\MessageBreak
+ Maybe you are overwriting something by mistake!\MessageBreak
+ Otherwise use '\string\RenewDocElement' instead.}%
+}
+
+\def\doc@notdeclarederror#1#2{%
+ \PackageError{doc}{Doc element '#1/#2' unknown}%
+ {I expected an existing definition for
+ '\string\Print#1Name',\MessageBreak
+ '\string\PrintDescribe#1' and
+ the environment '#2' but\MessageBreak
+ not all of them are defined.\MessageBreak
+ Maybe you wanted to use
+ '\string\NewDocElement'?}%
+}
+\newcommand\NewDocElement[3][]{%
+ \@ifundefined{Print#2Name}%
+ {\@ifundefined{PrintDescribe#2}%
+ {\@ifundefined{#3}%
+ {\@ifundefined{end#3}%
+ {\@NewDocElement{#1}}%
+ \doc@declareerror
+ }\doc@declareerror
+ }\doc@declareerror
+ }\doc@declareerror
+ {#2}{#3}%
+}
+\newcommand\RenewDocElement[3][]{%
+ \@ifundefined{Print#2Name}\doc@notdeclarederror
+ {\@ifundefined{PrintDescribe#2}\doc@notdeclarederror
+ {\@ifundefined{#3}\doc@notdeclarederror
+ {\@ifundefined{end#3}\doc@notdeclarederror
+ {\@NewDocElement{#1}}%
+ }%
+ }%
+ }%
+ {#2}{#3}%
+}
+\def\@NewDocElement#1#2#3{%
+ \doc@macrolikefalse
+ \doc@topleveltrue
+ \def\doc@idxtype{#3}%
+ \def\doc@idxgroup{#3s}%
+ \let\doc@printtype\@empty
+ \setkeys{doc}{#1}%
+ \ifx\doc@printtype\@empty
+ \@temptokena{}%
+ \else
+ \@temptokena\expandafter{\expandafter
+ \textnormal\expandafter{\expandafter
+ \space\expandafter
+ (\doc@printtype)}}%
+ \fi
+ \@nameedef{Print#2Name}##1{%
+ {\noexpand\MacroFont
+ \ifdoc@macrolike
+ \noexpand\string
+ \fi
+ ##1%
+ \the\@temptokena
+ }}%
+ \expandafter\let\csname PrintDescribe#2\expandafter\endcsname
+ \csname Print#2Name\endcsname
+ \edef\doc@expr{%
+ \ifdoc@macrolike
+ \noexpand\doc@createspecialmacrolikeindexes
+ \else
+ \noexpand\doc@createspecialindexes
+ \fi
+ {#2}%
+ }%
+ \expandafter\expandafter\expandafter
+ \doc@expr
+ \expandafter\expandafter\expandafter
+ {\expandafter\doc@idxtype\expandafter}\expandafter
+ {\doc@idxgroup}%
+ \doc@createdescribe{#2}%
+ \ifdoc@macrolike
+ \doc@createenv{TT}{#2}{#3}%
+ \else
+ \doc@createenv{TF}{#2}{#3}%
+ \fi
+}
+
+
+\NewDocElement[macrolike = true ,
+ idxtype = ,
+ idxgroup = ,
+ printtype =
+ ]{Macro}{macro}
+
+\def\SpecialMainIndex{\SpecialMainMacroIndex}
+
+\def\SpecialUsageIndex{\SpecialMacroIndex}
+
+\def\SpecialIndex {\CodeMacroIndex{code}}
+
+\NewDocElement[macrolike = false ,
+ idxtype = env. ,
+ idxgroup = environments ,
+ printtype = \textit{env.}
+ ]{Env}{environment}
+
+
+\DeclareRobustCommand\cs[1]{\texttt{\bslash #1}}
+
+\endinput
+%%
+%% End of file `doc-v3beta.sty'.
diff --git a/macros/latex/base/doc.dtx b/macros/latex/base/doc.dtx
index 7e7817153c..fb3412f21f 100644
--- a/macros/latex/base/doc.dtx
+++ b/macros/latex/base/doc.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -35,7 +35,7 @@
%<+package|shortvrb>\NeedsTeXFormat{LaTeX2e}[1994/12/01]
%<+package> \ProvidesPackage{doc}
%<+shortvrb>\ProvidesPackage{shortvrb}
-%<+package|shortvrb> [2020/06/15 v2.1m
+%<+package|shortvrb> [2021/05/28 v2.1n
%<+package|shortvrb> Standard LaTeX documentation package (FMi)]
%\catcode`\<=12
%
@@ -47,7 +47,7 @@
%
%
%% Package `doc' to use with LaTeX 2e
-%% Copyright (C) 1989-1999 Frank Mittelbach, all rights reserved.
+%% Copyright (C) 1989-2020 Frank Mittelbach, all rights reserved.
%
%
% Version: Date: Changes:
@@ -751,7 +751,7 @@
% in your package file. Precede it by any bibliography commands
% necessary for your citations.
% Alternatively, it may be more convenient to put all such calls
-% amongst the arguments of the |\StopEventually| macro, in
+% amongt the arguments of the |\StopEventually| macro, in
% which case a |\Finale| command should appear at the end of
% your file.
%
@@ -949,7 +949,7 @@
% macro.}
% \DescribeMacro\changes
% To maintain a change history within the file, the |\changes|
-% command may be placed amongst the description part of the changed
+% command may be placed amongt the description part of the changed
% code. It takes three arguments, thus:
% \begin{quote}
% |\changes{|\meta{version}|}{|\meta{date}|}{|^^A
@@ -2117,6 +2117,7 @@
% \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.}
+% \changes{v2.1n}{2021/05/28}{Use same error message text as in format}
% \begin{macrocode}
\let\verb@balance@group\@empty
@@ -2126,7 +2127,7 @@
\obeylines%
\gdef\verb@eol@error{\obeylines%
\def^^M{\verb@egroup\@latex@error{%
- Text for \noexpand\verb command ended by end of line}\@ehc}}%
+ \noexpand\verb ended by end of line}\@ehc}}%
\endgroup
% \end{macrocode}
% \end{macro}
@@ -2200,7 +2201,7 @@
%
% \begin{environment}{environment}
% \changes{v1.8c}{1993/10/25}{Environment added}
-% The ``environment'' envrionment will be implemented just like the
+% The ``environment'' environment will be implemented just like the
% ``macro'' environment flagging any differences in the code by
% passing |\iffalse| or |\iftrue| to the |\m@cro@| environment
% doing the actual work.
@@ -3029,7 +3030,7 @@
% \begin{macro}{\addto@hook}
% The code for adding tokens (the second argument) to a token list
% (the first argument) is taken from~\cite{art:verbatim}, but it needs
-% to be "\long" in case "\par" is amongst the tokens.
+% to be "\long" in case "\par" is amongt the tokens.
% \begin{macrocode}
\long\def\addto@hook#1#2{#1\expandafter{\the#1#2}}
% \end{macrocode}
@@ -3149,7 +3150,7 @@
% of an `index style file'; the character selected for this function
% is |=|, and therefore this character too must be specially treated
% when it is met in a \TeX\ command. A suitable index style file is
-% provided amongst the supporting files for this style file in
+% provided amongt the supporting files for this style file in
% \texttt{gind.ist} and is generated from this source by processing
% with \texttt{docstrip} to extract the module \textbf{gind}. A
% similar style file \texttt{gglo.ist} is supplied for sorting the
@@ -4219,7 +4220,7 @@
%
% \begin{macro}{\meta@font@select}
% \changes{v2.0k}{2000/05/26}{Macro added (pr/3170)}
-% Maske font used inside |\meta| customizable.
+% Make font used inside |\meta| customizable.
% \begin{macrocode}
\def\meta@font@select{\itshape}
% \end{macrocode}
@@ -4431,7 +4432,7 @@
\global\catcode`#1\csname cc\string#1\endcsname
% \end{macrocode}
% \changes{v1.9e.2}{1994/02/07}{-js: Reset `cc`\protect\meta{c} in
-% in \cs{DeleteShortVerb}}
+% \cs{DeleteShortVerb}}
% We must not forget to reset "\cc\"\meta{c}, otherwise the check in
% "\MakeShortVerb" for a repeated definition will not work.
% \begin{macrocode}
@@ -4532,7 +4533,7 @@
%
% \begin{macro}{\init@checksum}
% The checksum mechanism works by counting backslashes in the
-% macrocode. This initialises the count (when called from
+% macrocode. This initializes the count (when called from
% "\StopEventually").
% \changes{v1.5k}{1989/09/04}{Macro added to support checksum.}
% \begin{macrocode}
diff --git a/macros/latex/base/doc.pdf b/macros/latex/base/doc.pdf
index 8815f83c0b..69994495f4 100644
--- a/macros/latex/base/doc.pdf
+++ b/macros/latex/base/doc.pdf
Binary files differ
diff --git a/macros/latex/base/docstrip.dtx b/macros/latex/base/docstrip.dtx
index a0a06311ed..c7480988b4 100644
--- a/macros/latex/base/docstrip.dtx
+++ b/macros/latex/base/docstrip.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -30,8 +30,8 @@
\catcode`\}=2
\def\filename{docstrip.dtx}
\def\fileversion{v2.6a}
-\def\filedate{2020-07-07}
-\def\docdate {2020-07-11}
+\def\filedate{2020-11-23}
+\def\docdate {2020-11-23}
%%
%
%\iffalse
@@ -42,7 +42,7 @@
%% Frank Mittelbach
%% Copyright (C) 1995 Marcin Woli\'nski
%% Copyright (C) 1996-1997 Mark Wooding, Marcin Woli\'nski
-%% Copyright (C) 1998-2020 LaTeX3 project and the above authors
+%% Copyright (C) 1998-2021 LaTeX Project and the above authors.
%% All rights are reserved.
%%
%
@@ -77,7 +77,7 @@
% less/more dirty---all uses of \cs{afterfi}}
% \changes{2.3e}{1995/09/25}{Directories support}
% \changes{2.3e}{1995/10/24}{added \cs{makepathname} to support
-% systems with bizzare pathnames}
+% systems with bizare pathnames}
% \changes{2.3e}{1995/10/25}{batch files work by \cs{input}}
% \changes{2.3e}{1996/10/02}{Introduced ``open lists''}
% \changes{2.4a}{1996/06/06}{Add stream limits (MDW)}
@@ -122,7 +122,7 @@
%
% \changes{2.1b}{1993/02/23}{modified mailaddress of Johannes}
% \changes{2.4i}{1998/01/18}{removed mail addresses as it is hopeless
-% to keep them uptodate}
+% to keep them up-to-date}
% \author{%
% Frank Mittelbach
% \and
@@ -789,7 +789,7 @@
%
% \section{Internal functions and variables}
%
-% An important consideration for \LaTeX3 development is separating
+% An important consideration for \LaTeX\ development is separating
% out public and internal functions. Functions and variables which
% are private to one module should not be used or modified by any
% other module. As \TeX{} does not have any formal namespacing
@@ -809,7 +809,7 @@
% \end{verbatim}
%
% To extract the code using \ds, the original `guard'
-% mecahnism is extended by the introduction of the syntax
+% mechanism is extended by the introduction of the syntax
% \texttt{\%<@@=\meta{module}>}. The \meta{module} name then
% replaces the |@@| when the code is extracted, so that
% \begin{verbatim}
@@ -2305,7 +2305,7 @@ Z
% delimited with |\endLine|) on all active output files i.e.
% those with off-counters equal to zero. It uses the
% search-and-replace macro \cs{replaceModuleInLine} to replace any
-% occurences of \texttt{@@} with the current module name.
+% occurrences of \texttt{@@} with the current module name.
% If statistics are included, the counter
% |\codeLinesPassed| is incremented by $1$.
% \begin{macrocode}
@@ -4310,7 +4310,7 @@ for copying and modification in the file \inFileName.
% \begin{macro}{\WriteToDir}
% Macro |\WriteToDir| is either empty or holds the prefix
% necessary to read a file from the current directory. Under UNIX
-% this is |./| but a lot of other systems addopted this concept.
+% this is |./| but a lot of other systems adopted this concept.
% This macro is a default value for |\destdir|.
%
% The definition of this macro is now delayed until |\@setwritedir|
diff --git a/macros/latex/base/docstrip.ins b/macros/latex/base/docstrip.ins
index 281a376761..e34281fc36 100644
--- a/macros/latex/base/docstrip.ins
+++ b/macros/latex/base/docstrip.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -52,8 +52,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/docstrip.pdf b/macros/latex/base/docstrip.pdf
index 9688ffddef..c212a95d70 100644
--- a/macros/latex/base/docstrip.pdf
+++ b/macros/latex/base/docstrip.pdf
Binary files differ
diff --git a/macros/latex/base/ec.ins b/macros/latex/base/ec.ins
index 4283ef1ddd..90b7b2e61f 100644
--- a/macros/latex/base/ec.ins
+++ b/macros/latex/base/ec.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/encguide.pdf b/macros/latex/base/encguide.pdf
index 141c91cc81..4977c826d2 100644
--- a/macros/latex/base/encguide.pdf
+++ b/macros/latex/base/encguide.pdf
Binary files differ
diff --git a/macros/latex/base/encguide.tex b/macros/latex/base/encguide.tex
index 339bce1eb3..d70233eab4 100644
--- a/macros/latex/base/encguide.tex
+++ b/macros/latex/base/encguide.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -188,7 +188,7 @@
\title{\LaTeX{} font encodings}
\author{Frank Mittelbach \and Robin
- Fairbairns \and Werner Lemberg \and \LaTeX3 Project Team.}
+ Fairbairns \and Werner Lemberg \and \LaTeX\ Project Team.}
\date{\copyright~Copyright 1995--2016 \\[5pt] 18 February 2016}
@@ -286,7 +286,7 @@ known needs of researchers in mathematics and the mathematical sciences.
Independently, a first proposal (the so-called \emph{Aston proposal}) was worked
out by Justin Ziegler together with Frank Mittelbach and other members of the
-\LaTeX3 project team~\cite{ziegler}. A first implementation of
+\LaTeX\ Project team~\cite{ziegler}. A first implementation of
this propsal was realized by Matthias Clasen und Ulrik
Vieth~\cite{clasen,clasen-vieth}.
@@ -345,7 +345,7 @@ fonts.
Names for encoding schemes are strings of up to three letters (all
upper case) plus digits.
-The \LaTeX3 project reserves the use of encoding names starting with the
+The \LaTeX\ Project reserves the use of encoding names starting with the
following letters: |T| (standard 256-long text encodings), |TS|
(symbols that are designed to extend a corresponding |T| encoding),
|X| (text encodings that do not conform to the strict requirements for
diff --git a/macros/latex/base/exscale.dtx b/macros/latex/base/exscale.dtx
index f13e0116cd..ea67cb6fb7 100644
--- a/macros/latex/base/exscale.dtx
+++ b/macros/latex/base/exscale.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/exscale.ins b/macros/latex/base/exscale.ins
index d504b056cb..cfd2c535a7 100644
--- a/macros/latex/base/exscale.ins
+++ b/macros/latex/base/exscale.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/exscale.pdf b/macros/latex/base/exscale.pdf
index 0ebbe07a05..ef34516e04 100644
--- a/macros/latex/base/exscale.pdf
+++ b/macros/latex/base/exscale.pdf
Binary files differ
diff --git a/macros/latex/base/fix-cm.dtx b/macros/latex/base/fix-cm.dtx
index e4c384ee70..1be2e16cc0 100644
--- a/macros/latex/base/fix-cm.dtx
+++ b/macros/latex/base/fix-cm.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -37,7 +37,7 @@
%<driver>\ProvidesFile{fix-cm.drv}
% \fi
% \ProvidesFile{fix-cm.dtx}
- [2015/01/14 v1.1t fixes to LaTeX]
+ [2020/11/24 v1.1t fixes to LaTeX]
%
% \iffalse
%<*driver>
@@ -446,7 +446,7 @@
{<->sub * cmtt/m/sl}{}
% \end{macrocode}
%
-% \paragraph{CM Typewiter (var.)}
+% \paragraph{CM Typewriter (var.)}
% \begin{macrocode}
\DeclareFontFamily{T1}{cmvtt}{}
\DeclareFontShape{T1}{cmvtt}{m}{n}{
diff --git a/macros/latex/base/fix-cm.ins b/macros/latex/base/fix-cm.ins
index 0407d39630..95931970f4 100644
--- a/macros/latex/base/fix-cm.ins
+++ b/macros/latex/base/fix-cm.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/fix-cm.pdf b/macros/latex/base/fix-cm.pdf
index d72171f772..54def7c13b 100644
--- a/macros/latex/base/fix-cm.pdf
+++ b/macros/latex/base/fix-cm.pdf
Binary files differ
diff --git a/macros/latex/base/fntguide.pdf b/macros/latex/base/fntguide.pdf
index 5faab35979..bdf6d4a12e 100644
--- a/macros/latex/base/fntguide.pdf
+++ b/macros/latex/base/fntguide.pdf
Binary files differ
diff --git a/macros/latex/base/fntguide.tex b/macros/latex/base/fntguide.tex
index 7e0928c51b..a4b872a261 100644
--- a/macros/latex/base/fntguide.tex
+++ b/macros/latex/base/fntguide.tex
@@ -1,8 +1,8 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
+% Copyright (C) 1993-2021
%
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -37,12 +37,12 @@
\title{\LaTeXe{} font selection}
-\author{\copyright~Copyright 1995--2020, \LaTeX3 Project
+\author{\copyright~Copyright 1995--2021, \LaTeX\ Project
Team.\thanks{Thanks to Arash Esbati for documenting the
newer NFSS features of 2020}\\
All rights reserved.}
-\date{November 2020}
+\date{March 2021}
\begin{document}
@@ -311,6 +311,11 @@ A less common value for font shape is:
\end{tabular}
\end{minipage}
\end{center}
+and there is also |ui| for upright italic, i.e., an italic shape but
+artifically turned upright. This is sometimes useful and available in
+some fonts.
+
+
The font size is specified as a dimension, for example |10pt| or |1.5in|
or |3mm|; if no unit is specified, |pt| is assumed. These five
parameters specify every \LaTeX{} font, for example:
@@ -1800,7 +1805,7 @@ typesetting, as will the default declarations such as |\bfseries|.
Names for encoding schemes are strings of up to three letters (all
upper case) plus digits.
- The \LaTeX3 project reserves the use of encodings starting with the
+ The \LaTeX\ Project reserves the use of encodings starting with the
following letters: |T| (standard 256-long text encodings), |TS|
(symbols that are designed to extend a corresponding |T| encoding),
|X| (text encodings that do not conform to the strict requirements for
diff --git a/macros/latex/base/fontdef.dtx b/macros/latex/base/fontdef.dtx
index 632f1c9be5..581cfeb789 100644
--- a/macros/latex/base/fontdef.dtx
+++ b/macros/latex/base/fontdef.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -39,13 +39,13 @@
%<driver, >\ProvidesFile{fontdef.drv}
% \fi
% \ProvidesFile{fontdef.dtx}
-%<-latexrelease> [2020/08/01 v3.0i LaTeX Kernel
+%<-latexrelease> [2021/01/15 v3.0i LaTeX Kernel
% \iftrue (\else
%<text, >(Text
%<math, >(Math
-%<+cfgtext>(Uncustomised text
-%<+cfgmath>(Uncustomised math
-%<+cfgprel>(Uncustomised preload
+%<+cfgtext>(Uncustomized text
+%<+cfgmath>(Uncustomized math
+%<+cfgprel>(Uncustomized preload
% \fi
%<-latexrelease> font setup)]
%
@@ -110,7 +110,7 @@
% If you don't plan to use Computer Modern much or at all, it might
% (!) be a good idea to make your own \texttt{fonttext.cfg}. Look at
% the comments below (docstrip module `text') to see what should
-% should go into such a file.
+% go into such a file.
%
% To change the math font setup use a copy of \texttt{fontmath.ltx}
% under the name \texttt{fontmath.cfg} and change this copy. However,
@@ -227,7 +227,7 @@
% described in \texttt{ltoutenc.dtx}.
%
% By convention, text encoding specific declarations, including the
-% declaration |\DeclareFontEncoding|, are kept in separate file of
+% |\DeclareFontEncoding| declaration, are kept in separate file of
% the form \meta{enc}\texttt{enc.def}, e.g.~\texttt{ot1enc.def}. This
% allows other applications to make use of the declarations as
% well.
diff --git a/macros/latex/base/format.ins b/macros/latex/base/format.ins
index 8796d16d3e..eece2f57ef 100644
--- a/macros/latex/base/format.ins
+++ b/macros/latex/base/format.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
@@ -88,8 +88,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright 2015
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 2015-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
@@ -123,8 +123,8 @@ extension .ins) which are part of the distribution.
This is a generated file.
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
@@ -166,11 +166,14 @@ the system are in the document `cfgguide.tex'.
% we have the extensions as soon as possible.
\from{ltexpl.dtx}{2ekernel} % expl3-based extensions
\from{ltdefns.dtx}{2ekernel}
+ \from{ltcmd.dtx}{2ekernel} % L3 layer module (used to be xparse)
\from{lthooks.dtx}{2ekernel} % L3 layer module
+ \from{ltcmdhooks.dtx}{2ekernel} % L3 layer module
\from{ltalloc.dtx}{2ekernel}
\from{ltcntrl.dtx}{2ekernel}
\from{lterror.dtx}{2ekernel}
\from{ltpar.dtx}{2ekernel}
+ \from{ltpara.dtx}{2ekernel} % L3 layer module
\from{ltspace.dtx}{2ekernel}
\from{ltlogos.dtx}{2ekernel}
\from{ltfiles.dtx}{2ekernel}
@@ -233,15 +236,12 @@ the system are in the document `cfgguide.tex'.
% hook management support
-\generate{\file{everyshi-ltx.sty}{\from{ltshipout.dtx}{everyshi-ltx}}} % emulating everyshi
\generate{\file{atbegshi-ltx.sty}{\from{ltshipout.dtx}{atbegshi-ltx}}} % emulating atbegshi
\generate{\file{atveryend-ltx.sty}{\from{ltfilehook.dtx}{atveryend-ltx}}} % emulating atveryend
\generate{\file{structuredlog.sty}{\from{ltfilehook.dtx}{structuredlog}}}
-
-
% luatex support (TeX part)
\generate{\file{ltluatex.tex}{\from{ltluatex.dtx}{tex,plain}}}
diff --git a/macros/latex/base/graphpap.dtx b/macros/latex/base/graphpap.dtx
index ac72f4dca5..cc9f4da3cb 100644
--- a/macros/latex/base/graphpap.dtx
+++ b/macros/latex/base/graphpap.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/graphpap.ins b/macros/latex/base/graphpap.ins
index b5bb800122..65156ad917 100644
--- a/macros/latex/base/graphpap.ins
+++ b/macros/latex/base/graphpap.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/graphpap.pdf b/macros/latex/base/graphpap.pdf
index 4bc57dc7db..c1d687ef3c 100644
--- a/macros/latex/base/graphpap.pdf
+++ b/macros/latex/base/graphpap.pdf
Binary files differ
diff --git a/macros/latex/base/idx.tex b/macros/latex/base/idx.tex
index cbc233f63a..8257396f81 100644
--- a/macros/latex/base/idx.tex
+++ b/macros/latex/base/idx.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ifthen.dtx b/macros/latex/base/ifthen.dtx
index f2157e094a..acb5cf1967 100644
--- a/macros/latex/base/ifthen.dtx
+++ b/macros/latex/base/ifthen.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -30,7 +30,7 @@
%%
%% File `ifthen.dtx'.
%% Copyright (C) 1991 by Leslie Lamport
-%% Copyright (C) 1994-2001 LaTeX3 project, David Carlisle
+%% Copyright (C) 1994-2001 LaTeX project, David Carlisle
%% all rights reserved.
%%
%
@@ -42,7 +42,7 @@
%<driver>\ProvidesFile{ifthen.drv}
% \fi
% \ProvidesFile{ifthen.dtx}
- [2014/09/29 v1.1c Standard LaTeX ifthen package (DPC)]
+ [2020/11/24 v1.1c Standard LaTeX ifthen package (DPC)]
%
% \iffalse
%<*driver>
@@ -368,7 +368,7 @@
% \end{macro}
%
% \begin{macro}{\TE@endeval}
-% Finalise a term. (Expanded on the first pass).
+% Finalize a term. (Expanded on the first pass).
% \begin{macrocode}
\def\TE@endeval{\relax
\noexpand\TE@setvaltrue\noexpand
diff --git a/macros/latex/base/ifthen.ins b/macros/latex/base/ifthen.ins
index 0e813cd5de..42e1d3f5d9 100644
--- a/macros/latex/base/ifthen.ins
+++ b/macros/latex/base/ifthen.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/ifthen.pdf b/macros/latex/base/ifthen.pdf
index 32e87c1326..478a68c22f 100644
--- a/macros/latex/base/ifthen.pdf
+++ b/macros/latex/base/ifthen.pdf
Binary files differ
diff --git a/macros/latex/base/inputenc.dtx b/macros/latex/base/inputenc.dtx
index c1d08b4830..1b8691d30f 100644
--- a/macros/latex/base/inputenc.dtx
+++ b/macros/latex/base/inputenc.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -123,7 +123,7 @@
% THIS MAY CHANGE}
% \changes{v0.95}{1997/12/20}{Updated documentation}
% \changes{v0.97}{1998/03/05}{Spanish ords changed to text chars, pr/2579}
-% \changes{v1.1b}{2006/03/04}{Number of normalisations in the LICR
+% \changes{v1.1b}{2006/03/04}{Number of normalizations in the LICR
% representation (pr/3849)}
% \changes{v1.1c}{2006/11/18}{Added missing \cs{ProvidesFile} line for cp1257 (pr/3892)}
%
@@ -283,7 +283,7 @@
% with the |utf8| option.
%
% The |\DeclareUnicodeCharacter| takes UTF-8 code point as its first argument
-% (in form of a a hexadecimal number) and the definition that this maps to as
+% (in form of a hexadecimal number) and the definition that this maps to as
% its second argument. For example, the code point |00E4| which is
% ``LATIN SMALL LETTER A WITH DIAERESIS'' would be set up via:
%\begin{verbatim}
@@ -410,7 +410,7 @@
%<cp1252&!ansinew> \ProvidesFile{cp1252.def}
%<cp1250> \ProvidesFile{cp1250.def}
%<cp1257> \ProvidesFile{cp1257.def}
- [2020/08/01 v1.3d Input encoding file]
+ [2021/02/14 v1.3d Input encoding file]
%<cp850>%%
%<cp850>%% If you need a Euro symbol, try cp858 instead.
%<cp850>%%
@@ -1053,7 +1053,7 @@
%
% The ISO Latin-3 encoding file defines the characters
% in the ISO 8859-3 encoding. It was contributed by
-% by J\"org Knappen (\texttt{joerg.knappen@uni-mainz.de}) and
+% J\"org Knappen (\texttt{joerg.knappen@uni-mainz.de}) and
% adapted by Chris Rowley.
%
% It can be used for general purpose applications in
diff --git a/macros/latex/base/inputenc.ins b/macros/latex/base/inputenc.ins
index 6494a689ea..920a585bff 100644
--- a/macros/latex/base/inputenc.ins
+++ b/macros/latex/base/inputenc.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/inputenc.pdf b/macros/latex/base/inputenc.pdf
index 857279fa41..76b03a2a67 100644
--- a/macros/latex/base/inputenc.pdf
+++ b/macros/latex/base/inputenc.pdf
Binary files differ
diff --git a/macros/latex/base/lablst.tex b/macros/latex/base/lablst.tex
index 195d578f8c..da2d7dbceb 100644
--- a/macros/latex/base/lablst.tex
+++ b/macros/latex/base/lablst.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/latex209.dtx b/macros/latex/base/latex209.dtx
index d08a8001b5..bf92f8ef1e 100644
--- a/macros/latex/base/latex209.dtx
+++ b/macros/latex/base/latex209.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -200,7 +200,7 @@
% \end{macrocode}
% Describe the file.
% \begin{macrocode}
-\ProvidesFile{latex209.def}[2020/08/21 v0.55 Standard LaTeX file]
+\ProvidesFile{latex209.def}[2020/11/26 v0.55 Standard LaTeX file]
% \end{macrocode}
% \changes{v0.24}{1994/05/14}{Removed date.}
% \changes{v0.40}{1995/03/21}
@@ -712,7 +712,7 @@
%
% \changes{v0.18}{1994/03/11}{Added the catcode changes}
%
-% By default, \LaTeXe{} makes the input charactes 0--8, 11, 14--31 and
+% By default, \LaTeXe{} makes the input characters 0--8, 11, 14--31 and
% 128--255 illegal. In compatibility mode, we restore their old
% meanings.
% \begin{macrocode}
diff --git a/macros/latex/base/latex209.ins b/macros/latex/base/latex209.ins
index bb72f344f1..33ebc2488c 100644
--- a/macros/latex/base/latex209.ins
+++ b/macros/latex/base/latex209.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/latexchanges.pdf b/macros/latex/base/latexchanges.pdf
index 3b20501afd..cd61fcfc24 100644
--- a/macros/latex/base/latexchanges.pdf
+++ b/macros/latex/base/latexchanges.pdf
Binary files differ
diff --git a/macros/latex/base/latexchanges.tex b/macros/latex/base/latexchanges.tex
index a00ca99d4f..bc8e8dd07b 100644
--- a/macros/latex/base/latexchanges.tex
+++ b/macros/latex/base/latexchanges.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2015-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2015-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -38,7 +38,7 @@
\title{Changes to the \LaTeXe{} format}
-\author{\copyright~Copyright 2015--2021, \LaTeX3 Project Team.\\
+\author{\copyright~Copyright 2015--2021, \LaTeX\ Project Team.\\
All rights reserved.}
\date{2021-01-08}
@@ -985,7 +985,7 @@ we face an age old problem and unsolvable problem in \TeX: A
reliable test for math mode that doesn't destroy
kerning. Fortunately this problem can be solved when using e\TeX\ so
if you use this as engine for your \LaTeX\ format, as recommended by
-the \LaTeX3 Project, you will get a fully functioning |\TextOrMath|
+the \LaTeX\ Project, you will get a fully functioning |\TextOrMath|
command with no side effects. If you use regular \TeX\ as engine for
your \LaTeX\ format then we have to choose between the lesser of two
evils: 1)~breaking ligatures and preventing kerning or 2)~face the
diff --git a/macros/latex/base/latexrelease.dtx b/macros/latex/base/latexrelease.dtx
index 5ee39a3a2d..7d2290f4d8 100644
--- a/macros/latex/base/latexrelease.dtx
+++ b/macros/latex/base/latexrelease.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -37,13 +37,13 @@
%<fixltx2e>\ProvidesPackage{fixltx2e}
%<fixltx2e> [2016/12/29 v2.1a fixes to LaTeX (obsolete)]
%<latexrelease>\ProvidesPackage{latexrelease}
-%<*!fixltx2e>
+%<*latexrelease>
% \fi
% \ProvidesFile{latexrelease.dtx}
- [2018/05/08 v1.0k LaTeX release emulation and tests
+ [2021/04/29 v1.0n LaTeX release emulation and tests
(including releases up to \latexreleaseversion)]
% \iffalse
-%</!fixltx2e>
+%</latexrelease>
%<*driver>
\documentclass{ltxdoc}
\newcommand\Lopt[1]{\textsf{#1}}
@@ -51,6 +51,8 @@
\providecommand{\file}[1]{\texttt{#1}}
\providecommand{\MF}{\textsf{Metafont}}
\providecommand{\danger}{\marginpar[\hfill\protect\Huge!!]{\protect\Huge!!\hfill}}
+ \DeclareRobustCommand\cs[2][]{\texttt{\char`\\\detokenize{#2}}}
+ \DeclareRobustCommand\pkg[1]{\textsf{#1}}
\begin{document}
\DocInput{latexrelease.dtx}
\end{document}
@@ -69,7 +71,7 @@
% \title{The \Lpack{latexrelease} package\thanks{This file
% has version number \fileversion, last
% revised \filedate.}}
-% \author{The \LaTeX3 Project}
+% \author{The \LaTeX{} Project}
% \date{\filedate}
% \MaintainedByLaTeXTeam{latex}
% \maketitle
@@ -129,7 +131,6 @@
% package has no information will generate a warning. Dates
% earlier than 2015 will work but will roll back to some point in 2015
% when the method was introduced.
-% |\IncludeInRelease| command is defined.
% The |\requestedLaTeXdate| is set to the normalized date argument
% so that package rollback defaults to the specified date.
%
@@ -137,9 +138,6 @@
% |current| This is the default behaviour, it does not change the
% effective date of the format but does ensure that the
% |\IncludeInRelease| command is defined.
-% the |\requestedLaTeXdate| is reset to 0 so that package rollback
-% does not use the implicit date.
-% |\IncludeInRelease| command is defined.
% The |\requestedLaTeXdate| macro is reset to 0 so that package rollback
% does not use the implicit date.
%
@@ -147,11 +145,16 @@
% |latest| sets the effective date of the format to the release date
% of this file, so in an older format applies all patches currently
% available.
-% |\IncludeInRelease| command is defined.
% The |\requestedLaTeXdate| macro is reset to 0 so that package rollback
% does not use the implicit date.
% \end{itemize}
%
+% In all cases, when the package is loaded, the |\sourceLaTeXdate| is
+% defined to be the numerical representation of |\fmtversion| before the
+% rollback/forward actually happens, so it is possible to test from which
+% was the original \LaTeX{} version before \Lpack{latexrelease} was loaded.
+% This is particularly useful when some code in a package has to be
+% redefined differently if rolling backwards in time or forwards.
%
% \section{Release Specific Code}
%
@@ -345,7 +348,7 @@
%
% Now if you make a further change to |\widget| in the future you
% simply copy the current definition into the empty block and add a new
-% empty declaration with todays date and the current format date. This
+% empty declaration with today's date and the current format date. This
% way your main code stays readable and the old versions accumulate at
% the end of the package.\footnote{Of course there may be some cases
% in which the old code has to be in a specific place within the
@@ -363,6 +366,99 @@
% necessary as the new code only gets defined if that release is
% chosen.
%
+% \section{Declaring entire modules}
+%
+% Sometimes a large chunk of code is added as a module to another larger
+% code base. As example of that in the 2020-10-01 release \LaTeX{} got
+% a new hook management system, \pkg{lthooks}, which was added in one go
+% and, as with all changes to the kernel, it was added to
+% \pkg{latexrelease}. However rolling back from a future date to the
+% 2020-10-01 release didn't work because \pkg{latexrelease} would try to
+% define again all those commands, which would result in many
+% ``already defined'' errors and similar issues.
+%
+% To solve that problem, completely new modules can be defined in
+% \pkg{latexrelease} using the commands:
+% \begin{quote}
+% \cs{NewModuleRelease}%^^A
+% \verb|{|\meta{initial release date}%^^A
+% \verb|}{|\meta{name}\verb|}{|\meta{message}\verb|}|\\
+% \null\quad\meta{module code}\\
+% \cs{IncludeInRelease}%^^A
+% \verb|{0000/00/00}{|\meta{name}\verb|}{|\meta{message}\verb|}|\\
+% \null\quad\meta{undefine module code}\\
+% \cs{EndModuleRelease}
+% \end{quote}
+% With that setup, the module \meta{name} will be declared to exist only
+% in releases equal or later \meta{initial release date}.
+%
+% If \pkg{latexrelease} is rolling backwards or forwards between dates
+% after \meta{initial release date}, then all the \meta{module code} is
+% skipped, except when inside \meta{IncludeInRelease} guards, in which
+% case the code is applied or skipped as discussed above.
+%
+% If rolling forward from a date before the module's \meta{initial
+% release date} to a date after that, then all the \meta{module code} is
+% executed to define the module, and \cs{IncludeInRelease} guards are
+% executed accordingly, depending on the date declared and the target
+% date.
+%
+% If \pkg{latexrelease} is rolling back to a date before \meta{release
+% date}, then the code in the \cs{IncludeInRelease} guard dated
+% \verb|0000/00/00| is executed instead to undefine the module. This
+% guard \emph{is not} ended by the usual \cs{EndIncludeInRelease}, but
+% instead by \cs{EndModuleRelease}.
+%
+% Finally, if rolling backwards or forwards between dates both before
+% \meta{initial release date}, the entire code between
+% \meta{NewModuleRelease} and \meta{EndModuleRelease} is entirely
+% skipped.
+%
+% \subsection{Example}
+%
+% Here is an example usage of the structure described above, as it would
+% be used in the \LaTeX{} kernel, taking \pkg{lthooks} as example:
+% \begin{verbatim}
+% %<*2ekernel|latexrelease>
+% \ExplSyntaxOn
+% %<latexrelease>\NewModuleRelease{2020/10/01}{lthooks}%
+% %<latexrelease> {The~hook~management~system}
+% \NewDocumentCommand \NewHook { m }
+% { \hook_new:n {#1} }
+% %<latexrelease>\IncludeInRelease{2021/06/01}{\AddToHook}{Long~argument}
+% \NewDocumentCommand \AddToHook { m o +m }
+% { \hook_gput_code:nnn {#1} {#2} {#3} }
+% %<latexrelease>\EndIncludeInRelease
+% %<latexrelease>
+% %<latexrelease>\IncludeInRelease{2020/10/01}{\AddToHook}{Long~argument}
+% %<latexrelease>\NewDocumentCommand \AddToHook { m o m }
+% %<latexrelease> { \hook_gput_code:nnn {#1} {#2} {#3} }
+% %<latexrelease>\EndIncludeInRelease
+% %<latexrelease>
+% %<latexrelease>\IncludeInRelease{0000/00/00}{lthooks}{Undefine~lthooks}
+% %<latexrelease>\cs_undefine:N \NewHook
+% %<latexrelease>\cs_undefine:N \AddToHook
+% %<latexrelease>\EndModuleRelease
+% \ExplSyntaxOff
+% %</2ekernel|latexrelease>
+% \end{verbatim}
+%
+% In the example above, \cs{NewHook} is declared only once, and
+% unchanged in the next release (2021/06/01 in the example), so it has
+% no \cs{IncludeInRelease} guards, and will only be defined if needed.
+% \cs{AddToHook}, on the other hand, changed between the two releases
+% (made up for the example; it didn't really happen)
+% and has an \cs{IncludeInRelease} block for the current release (off
+% \pkg{docstrip} guards, so it goes into the kernel too), and another
+% for the previous release (in \pkg{docstrip} guards so it goes only
+% into \pkg{latexrelease}).
+%
+% Note that in the example above, \cs{ExplSyntaxOn} and
+% \cs{ExplSyntaxOff} were added \emph{outside} the module code because,
+% as discussed above, sometimes the code outside \cs{IncludeInRelease}
+% guards may be skipped, but not the code inside them, and in that case
+% the catcodes would be wrong when defining the code.
+%
% \section{fixltx2e}
%
% As noted above, prior to the 2015 \LaTeX\ release updates to the
@@ -386,17 +482,34 @@
\NeedsTeXFormat{LaTeX2e}[1996/06/01]
% \end{macrocode}
%
-% \section{Setup}
+% \subsection{Setup}
+%
+% \begin{macro}{\sourceLaTeXdate}
+% \changes{v1.0l}{2021/01/23}{\cs{sourceLaTeXdate} added}
+% \changes{v1.0m}{2021/03/18}{Define \cs{sourceLaTeXdate} conditionally}
+% Store the original \LaTeX{} format version
+% as a number in the format |YYYYMMDD|. This macro has to
+% be defined conditionally, so that it isn't changed in case
+% \file{latexrelease.sty} is loaded twice (for tests), but it
+% can't be defined in the kernel only, otherwise
+% \file{latexrelease.sty} wouldn't work in older \LaTeX{} due
+% to the missing macro.
+% \begin{macrocode}
+\@ifundefined{sourceLaTeXdate}{%
+ \edef\sourceLaTeXdate{%
+ \expandafter\@parse@version\fmtversion//00\@nil}}{}%
+% \end{macrocode}
+% \end{macro}
%
% \begin{macro}{\IncludeInRelease}
% \begin{macro}{\EndIncludeInRelease}
-% \begin{macrocode}
-% \end{macrocode}
+% These are defined in \file{ltvers.dtx}.
% \end{macro}
% \end{macro}
%
% \changes{v1.0c}{2015/02/19}{Swap argument order}
-% \changes{v1.0k}{2018/05/08}{reset \cs{\requestedLaTeXdate} for current and latest options, gitub issue 43}
+% \changes{v1.0k}{2018/05/08}{reset \cs{\requestedLaTeXdate} for current
+% and latest options, github issue 43}
% \begin{macrocode}
\DeclareOption*{%
\def\@IncludeInRelease#1[#2]{\@IncludeInRele@se{#1}}%
@@ -483,16 +596,213 @@ of this package available from CTAN}
% \end{macrocode}
%
%
-% \section{Individual Changes}
+% \subsection{Ignoring \texttt{\string_new} errors when rolling back}
%
-% The code for each change will be inserted at this point, extracted
-% from the kernel source files.
+% Enforce \cs{ExplSyntaxOn} and \cs{ExplSyntaxOff} to be \cs{relax} in
+% \pkg{latexrelease} if they are not yet defined. They are later
+% restored to be undefined if needed.
+% \begin{macrocode}
+\csname ExplSyntaxOn\endcsname
+\csname ExplSyntaxOff\endcsname
+% \end{macrocode}
+%
+% \changes{v1.0m}{2021/03/18}
+% {Make \texttt{\string_new} definitions harmless}
+%
+% Define a set of changes here, but we'll only use them later to make
+% sure they are applied after \pkg{expl3} is loaded. If loading from a
+% rather old format, we don't have \cs{ExplSyntaxOn} yet.
+% \begin{macrocode}
+\begingroup
+ \endlinechar=-1
+ \catcode95=11 % _
+ \catcode58=11 % :
+ \catcode126=10 % ~
+ \catcode32=09 % <space>
+ \xdef\latexrelease@postexpl{\unexpanded{%
+%<@@=latexrelease>
+% \end{macrocode}
+%
+% First we'll define a \cs{declarecommand} that does \cs{renewcommand}
+% if the command being defined already exists, and \cs{newcommand}
+% otherwise.
+% \begin{macrocode}
+\cs_gset_protected:Npn \@@_declare_command:w
+ { \@star@or@long \@@_declare_command:Nw }
+\cs_gset_protected:Npn \@@_declare_command:Nw #1
+ { \cs_if_exist:NTF #1 { \renew@command } { \new@command } #1 }
+% \end{macrocode}
+%
+% Then define a version of \cs{e@alloc} that checks if the control
+% sequence being defined already exists, and if so, checks if its
+% meaning is the same as the one that would be defined with the call to
+% \cs{e@alloc}. If both tests pass, nothing is defined to save a
+% register. This version also takes care of setting
+% \cs{allocationnumber} to the value it would have after the register is
+% allocated.
+% \begin{macrocode}
+\cs_gset_protected:Npn \@@_e@alloc:NnnnnN #1 #2 #3 #4 #5 #6
+ {
+ \cs_if_free:NTF #6
+ { \use:n }
+ {
+ \exp_after:wN \@@_e@alloc:N
+ \token_to_meaning:N #6 \scan_stop: {#2} #6
+ }
+ { \@@_e@alloc #1 {#2} {#3} {#4} {#5} #6 }
+ }
+% \end{macrocode}
+% Walk through the meaning of the control sequence token by token,
+% looking for the register allocation number.
+% \begin{macrocode}
+\cs_gset_protected:Npn \@@_e@alloc:N #1
+ {
+ \if_int_compare:w 0 < 0
+ \if_int_compare:w 10 < 9#1 ~ 1 \fi:
+ \if_charcode:w " #1 1 \fi: \exp_stop_f:
+ \tex_afterassignment:D \@@_e@alloc:w
+ \@tempcnta #1
+ \use_i:nnn
+ \fi:
+ \use:n
+ {
+ \if_meaning:w \scan_stop: #1
+ \exp_after:wN \use_iv:nnnn
+ \fi:
+ \@@_e@alloc:N
+ }
+ }
+% \end{macrocode}
+% When found, check if it is the exact same register as it would be
+% allocated, and if it is, set \cs{allocationnumber} accordingly and
+% exit, otherwise undefine the register and allocate from scratch.
+% \begin{macrocode}
+\cs_gset_protected:Npn \@@_e@alloc:w #1 \scan_stop: #2 #3
+ {
+ #2 \@@_tmp:w = \@tempcnta
+ \token_if_eq_meaning:NNTF #3 \@@_tmp:w
+ { \int_set_eq:NN \allocationnumber \@tempcnta \use_none:n }
+ { \cs_set_eq:NN #3 \tex_undefined:D \use:n }
+ }
+% \end{macrocode}
%
+% Now create a token list to hold the list of changed commands, and
+% define a temporary macro that will loop through the command list,
+% store each in \cs{l_@@_restores_tl}, save a copy, and redefine each.
% \begin{macrocode}
+\tl_clear_new:N \l_@@_restores_tl
+\cs_gset:Npn \@@_tmp:w #1 #2
+ {
+ \quark_if_recursion_tail_stop_do:Nn #1
+ { \cs_undefine:N \@@_tmp:w }
+ \tl_put_right:Nn \l_@@_restores_tl {#1}
+ \cs_set_eq:cN { @@_ \cs_to_str:N #1 } #1
+ \cs_set_eq:NN #1 #2
+ \@@_tmp:w
+ }
+% \end{macrocode}
+%
+% The redefinitions below are needed because:
+% \begin{description}
+% \def\makelabel#1{\cs{#1}}
+% \item[__kernel_chk_if_free_cs:N] This function is used ubiquitously
+% in the \pkg{l3kernel} to check if a control sequence is definable,
+% and give an error otherwise (similar to \cs{@ifdefinable}).
+% Making it a no-op is enough for most cases (except when defining
+% new registers);
+% \item[e@alloc] In the case of new registers, we waste an allocation
+% number if we do \cs[no-index]{new\meta{thing}} in a register
+% that's already allocated, so the redefinition of \cs{e@alloc}
+% checks if the new register is really necessary. This code does
+% not clear the register, which might cause problems in the future,
+% if a register is allocated but not properly cleared before using;
+% \item[__kernel_msg_error:nnx] This command is used to error on
+% already defined scan marks. Just making the error do nothing is
+% enough, as no action is taken in that case;
+% \item[msg_new:nnnn] Used to define new messages. Making it
+% \texttt{\string_gset} is enough. Other msg commands like
+% \cs{msg_new:nnn} and \cs[no-index]{__kernel_msg_new:nnn(n)} are
+% defined in terms of \cs{msg_new:nnnn}, so there is no need to
+% change the other ones;
+% \item[NewDocumentCommand] Used to define user-level commands in the
+% kernel. Making it equal to \cs{DeclareDocumentCommand} solves the
+% problem;
+% \item[newcommand] Same as above.
+% \end{description}
+% And here we go:
+% \begin{macrocode}
+\@@_tmp:w
+ \__kernel_chk_if_free_cs:N \use_none:n
+ \e@alloc \@@_e@alloc:NnnnnN
+ \__kernel_msg_error:nnx \use_none:nnn
+ \msg_new:nnnn \msg_gset:nnnn
+ \NewDocumentCommand \DeclareDocumentCommand
+ \newcommand \@@_declare_command:w
+% \end{macrocode}
+% Temp addition \ldots
+% \begin{macrocode}
+ \__kernel_msg_error:nnn \use_none:nnn % needed while redirect for kernel msgs doesn't work
+ \q_recursion_tail \q_recursion_tail
+ \q_recursion_stop
+% \end{macrocode}
+%
+% Finally, redirect the error thrown by \cs{NewHook} to nowhere so it
+% can be safely reused (the hook isn't redeclared if it already exists).
+% \begin{macrocode}
+\msg_redirect_name:nnn { hooks } { exists } { none }
+% \end{macrocode}
+%
+% \begin{macrocode}
+ }}%
+\endgroup
%</latexrelease>
% \end{macrocode}
%
-% \section{fixltx2e}
+% \subsection{Undoing the temp modifications}
+%
+% If \cs{ExplSyntaxOn} exists (defined and not equal \cs{relax}), then
+% use the \pkg{expl3} restore code, otherwise restore \cs{ExplSyntaxOn}
+% and \cs{ExplSyntaxOff} to be undefined.
+% \begin{macrocode}
+%<*latexrelease-finish>
+\@ifundefined{ExplSyntaxOn}%
+ {\let\ExplSyntaxOn\@undefined
+ \let\ExplSyntaxOff\@undefined
+ \@gobble}%
+ {\ExplSyntaxOn
+ \@firstofone}%
+ {%
+% \end{macrocode}
+%
+% Now just loop through the list of redefined commands and restore their
+% previous meanings.
+% \begin{macrocode}
+\tl_map_inline:Nn \l_@@_restores_tl
+ {
+ \cs_set_eq:Nc #1 { @@_ \cs_to_str:N #1 }
+ \cs_undefine:c { @@_ \cs_to_str:N #1 }
+ }
+\tl_clear:N \l_@@_restores_tl
+% \end{macrocode}
+%
+% And restore the hook error message.
+% \begin{macrocode}
+\msg_redirect_name:nnn { hooks } { exists } { }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=>
+ \ExplSyntaxOff}%
+%</latexrelease-finish>
+% \end{macrocode}
+%
+% \subsection{Individual Changes}
+%
+% The code for each change will be inserted at this point, extracted
+% from the kernel source files.
+%
+%
+% \subsection{fixltx2e}
%
% Generate a stub \Lpack{fixltx2e} package:
% \begin{macrocode}
diff --git a/macros/latex/base/latexrelease.ins b/macros/latex/base/latexrelease.ins
index ffc92374c3..0b65114a2f 100644
--- a/macros/latex/base/latexrelease.ins
+++ b/macros/latex/base/latexrelease.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
@@ -93,13 +93,16 @@ extension .ins) which are part of the distribution.
\from{ltluatex.dtx} {latexrelease}% empty
\from{ltexpl.dtx} {latexrelease}% empty
\from{ltdefns.dtx} {latexrelease}%
- \from{lthooks.dtx} {latexrelease}% empty % L3 layer module
+ \from{ltcmd.dtx} {latexrelease}%
+ \from{lthooks.dtx} {latexrelease}% L3 layer module
+ \from{ltcmdhooks.dtx} {latexrelease}% L3 layer module
\from{ltalloc.dtx} {latexrelease}% empty
\from{ltcntrl.dtx} {latexrelease}% empty
\from{lterror.dtx} {latexrelease}% empty
\from{ltpar.dtx} {latexrelease}% empty
+ \from{ltpara.dtx} {latexrelease}% empty
\from{ltspace.dtx} {latexrelease}%
- \from{ltlogos.dtx} {latexrelease}% empty
+ \from{ltlogos.dtx} {latexrelease}% L3 layer module
\from{ltfiles.dtx} {latexrelease}%
\from{ltoutenc.dtx} {latexrelease}%
\from{ltcounts.dtx} {latexrelease}%
@@ -132,6 +135,7 @@ extension .ins) which are part of the distribution.
\from{ltoutput.dtx} {latexrelease}%
\from{ltfsscmp.dtx} {latexrelease}% only in latexrelease!
\from{ltfinal.dtx} {latexrelease}%
+ \from{latexrelease.dtx}{latexrelease-finish}%
}
diff --git a/macros/latex/base/latexrelease.pdf b/macros/latex/base/latexrelease.pdf
index 313eb94505..e50393e3bd 100644
--- a/macros/latex/base/latexrelease.pdf
+++ b/macros/latex/base/latexrelease.pdf
Binary files differ
diff --git a/macros/latex/base/latexsym.dtx b/macros/latex/base/latexsym.dtx
index 908f11e124..7a97aa4318 100644
--- a/macros/latex/base/latexsym.dtx
+++ b/macros/latex/base/latexsym.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/latexsym.ins b/macros/latex/base/latexsym.ins
index 9e9901b879..902bbfc9e8 100644
--- a/macros/latex/base/latexsym.ins
+++ b/macros/latex/base/latexsym.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
@@ -87,8 +87,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/latexsym.pdf b/macros/latex/base/latexsym.pdf
index 1ad33cec9d..eca06019fc 100644
--- a/macros/latex/base/latexsym.pdf
+++ b/macros/latex/base/latexsym.pdf
Binary files differ
diff --git a/macros/latex/base/lb2.err b/macros/latex/base/lb2.err
index 47dc4010c2..767cc86a05 100644
--- a/macros/latex/base/lb2.err
+++ b/macros/latex/base/lb2.err
@@ -19,7 +19,7 @@
\begin{filecontents}{ttcterrata.cls}
%%
-%% Copyright (C) 1997,2004,2005,2007, 2014 Frank Mittelbach
+%% Copyright (C) 1997-2021 Frank Mittelbach
%% This class file is licenced under LPPL latest version;
%% see https://www.latex-project.org/lppl
%
@@ -35,9 +35,10 @@
% Changes:
%
% v1.0a - changed name from errata.cls to ttcterrata.cls
+% v1.0b - added \arraybackslash
\ProvidesClass{ttcterrata}
- [2007/11/10 v1.0a Mini class for errata files; subject to change (FMi)]
+ [2021/04/22 v1.0b Mini class for errata files; subject to change (FMi)]
\LoadClass{article}
@@ -164,7 +165,7 @@
\multicolumn{4}{l}{\framebox[10cm][l]{\textbf{\normalsize\strut#1}}} \\}
\newenvironment{erratalist}
- {\begin{longtable}{r>{\raggedright}p{2cm}l>{\raggedright}p{10cm}l}}
+ {\begin{longtable}{r>{\raggedright\arraybackslash}p{2cm}l>{\raggedright\arraybackslash}p{10cm}l}}
{\endgobble\end{longtable}}
\newcommand\erratatitle[2]
diff --git a/macros/latex/base/lb2.pdf b/macros/latex/base/lb2.pdf
index 89e748bed0..2bf5c3afa4 100644
--- a/macros/latex/base/lb2.pdf
+++ b/macros/latex/base/lb2.pdf
Binary files differ
diff --git a/macros/latex/base/legal.txt b/macros/latex/base/legal.txt
index 5e20be289d..2fec428b91 100644
--- a/macros/latex/base/legal.txt
+++ b/macros/latex/base/legal.txt
@@ -7,9 +7,8 @@ COPYRIGHT
=========
This distribution is
-Copyright 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005
- 2006 2007 2008 2009 2011 2014 2015 2016
-The LaTeX3 Project and the individual authors:
+Copyright (C) 1993-2021
+The LaTeX Project and the individual authors:
Leslie Lamport
Johannes Braams
diff --git a/macros/latex/base/letter.dtx b/macros/latex/base/letter.dtx
index 7b31dfbbc9..6beee81735 100644
--- a/macros/latex/base/letter.dtx
+++ b/macros/latex/base/letter.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -45,7 +45,7 @@
%<*driver>
\ProvidesFile{letter.drv}
%</driver>
- [2020/03/11 v1.3b
+ [2021/03/05 v1.3c
%<+letter> Standard LaTeX document class]
% \end{macrocode}
%
@@ -165,7 +165,7 @@
% \changes{v1.3a}{2020/03/07}{merged changes to classes.dtx into letter.dtx}
%
% \iffalse
-% Copyright (C) 1994 LaTeX3 project, Frank Mittelbach
+% Copyright (C) 1994 LaTeX Project, Frank Mittelbach
% and Rainer Sch\"opf, all rights reserved.
% \fi
%
@@ -1019,7 +1019,29 @@
\@date \end{tabular}\par}%
\fi
\vspace{2\parskip}%
- {\raggedright \toname \\ \toaddress \par}%
+% \end{macrocode}
+% If the address field used \verb=\\[...]= then we have
+% \cs{toaddress} starting with the bracket argument as the split
+% was done simply at \verb=\\=. So we add \cs{expandafter} here so
+% that is will be used and not typeset. A better fix would be to do
+% a proper parsing but \ldots
+%
+% Other classes based on \texttt{letter.cls} could benefit from the same fix, e.g.,
+% \texttt{akletter.cls},
+% \texttt{bletter.cls},
+% \texttt{letter.cls},
+% \texttt{chletter.cls},
+% \texttt{extletter.cls},\\
+% \texttt{frletter.cls},
+% \texttt{hletter.cls},
+% \texttt{scrlttr2.cls} (change rejected),
+% \texttt{lettre.cls},
+% \texttt{beletter.cls},\\
+% \texttt{brief.cls} and perhaps others.
+%
+% \changes{v1.3c}{2020/12/28}{Add \cs{expandafter} (gh/427)}
+% \begin{macrocode}
+ {\raggedright \toname \expandafter\\\toaddress \par}%
\vspace{2\parskip}%
#1\par\nobreak}
% \end{macrocode}
diff --git a/macros/latex/base/letter.ins b/macros/latex/base/letter.ins
index 8e8ed4ef7b..44777393eb 100644
--- a/macros/latex/base/letter.ins
+++ b/macros/latex/base/letter.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/letter.pdf b/macros/latex/base/letter.pdf
index f229f68d3b..195adf6684 100644
--- a/macros/latex/base/letter.pdf
+++ b/macros/latex/base/letter.pdf
Binary files differ
diff --git a/macros/latex/base/lgc2.err b/macros/latex/base/lgc2.err
index e9a1de4ea5..cbee8d6f35 100644
--- a/macros/latex/base/lgc2.err
+++ b/macros/latex/base/lgc2.err
@@ -17,7 +17,7 @@
\begin{filecontents}{ttcterrata.cls}
%%
-%% Copyright (C) 1997,2004,2005,2007 Frank Mittelbach
+%% Copyright (C) 1997-2021 Frank Mittelbach
%% This class file is licenced under LPPL latest version;
%% see https://www.latex-project.org/lppl
%
@@ -33,9 +33,10 @@
% Changes:
%
% v1.0a - changed name from errata.cls to ttcterrata.cls
+% v1.0b - added \arraybackslash
\ProvidesClass{ttcterrata}
- [2007/11/10 v1.0a Mini class for errata files; subject to change (FMi)]
+ [2021/04/22 v1.0b Mini class for errata files; subject to change (FMi)]
\LoadClass{article}
@@ -162,7 +163,7 @@
\multicolumn{4}{l}{\framebox[10cm][l]{\textbf{\normalsize\strut#1}}} \\}
\newenvironment{erratalist}
- {\begin{longtable}{r>{\raggedright}p{2cm}l>{\raggedright}p{10cm}l}}
+ {\begin{longtable}{r>{\raggedright\arraybackslash}p{2cm}l>{\raggedright\arraybackslash}p{10cm}l}}
{\endgobble\end{longtable}}
\newcommand\erratatitle[2]
diff --git a/macros/latex/base/lgc2.pdf b/macros/latex/base/lgc2.pdf
index d6032fe6a0..a1a3348bca 100644
--- a/macros/latex/base/lgc2.pdf
+++ b/macros/latex/base/lgc2.pdf
Binary files differ
diff --git a/macros/latex/base/lppl.pdf b/macros/latex/base/lppl.pdf
index 58364d502b..88e9e68c8c 100644
--- a/macros/latex/base/lppl.pdf
+++ b/macros/latex/base/lppl.pdf
Binary files differ
diff --git a/macros/latex/base/ltalloc.dtx b/macros/latex/base/ltalloc.dtx
index d18df9ad89..59c492836f 100644
--- a/macros/latex/base/ltalloc.dtx
+++ b/macros/latex/base/ltalloc.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltbibl.dtx b/macros/latex/base/ltbibl.dtx
index a3a25308fe..cda0fa160a 100644
--- a/macros/latex/base/ltbibl.dtx
+++ b/macros/latex/base/ltbibl.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltbibl.dtx}
- [2018/11/09 v1.1r LaTeX Kernel (Bibliography)]
+ [2020/12/10 v1.1s LaTeX Kernel (Bibliography)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltbibl.dtx}
@@ -104,7 +104,7 @@
% but puts nothing in the text.
%
% |\nocite{*}| is special: it tells \BibTeX{} to put the whole of a
-% collection of references into the bibiography.
+% collection of references into the bibliography.
%
% \StopEventually{}
%
@@ -253,7 +253,7 @@
% year citations it becomes more than questionable.
%
% So Chris added yet another hook here, as suggested by, at least,
-% Donald Arsenau. Note that this one is inside the first argument
+% Donald Arseneau. Note that this one is inside the first argument
% of the |\@cite| hook.
% This decouples the top-level typesetting of the citation from
% the details of the other business conducted here. All this really
@@ -327,6 +327,10 @@
% \changes{v1.1g}{1995/05/08}{Use \cs{@firstofone}}
% \changes{v1.1k}{1995/10/20}{Removed refundefined flag}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\nocite}{Allow nocite in preamble}%
\def\nocite#1{\@bsphack
% \end{macrocode}
% With the implementation designed already in \LaTeX\,2.09 the
@@ -335,10 +339,15 @@
% that point. As a result the ``reference'' will appear on the
% terminal and nothing else will happen.
%
-% This would be easy to fix, but then a document using the fix will
+% [This would be easy to fix, but then a document using the fix will
% silently fail on an older release of \LaTeX{}, missing all
% citations done with |\nocite|. Thus we do only generate an error
-% message and leave the fix for a \LaTeXe{} successor.
+% message and leave the fix for a \LaTeXe{} successor.]
+%
+% Given that we are now a quarter century into using \LaTeXe{}
+% there is no good reason any more do limit ourself to 2.09
+% conciderations. So we now simply delay the \cs{nocide} if it is
+% issued in the preamble.
%
% \changes{v1.1o}{2003/05/18}{Check if we are after \cs{document}}
% \changes{v1.1p}{2004/01/04}{Changed error message}
@@ -354,18 +363,48 @@
\@latex@warning{Citation `\@citeb' undefined}}{}}%
\else
% \end{macrocode}
-% But before |\begin{document}| we raise an error message:
+% But before |\begin{document}| we raised an error message in the
+% past but as of 2021/05 not any longer.
% \begin{macrocode}
- \@latex@error{Cannot be used in preamble}\@eha
+% \@latex@error{Cannot be used in preamble}\@eha
% \end{macrocode}
-% Without the compatibility problems we could fix the problem as follows:
+% Instead we delay the declaration to the start of the document.
+% We have to use a late hook for this, so that it comes after the
+% \texttt{.aux} file is open for writing and after
+% \cs{@preamblecmds} was executed to change the above
+% test. Therefore \cs{AtBeginDocument} would still be too early.
+% \changes{v1.1s}{2020/12/10}{Delay any \cs{nocite} in the preamble
+% instead of raising an error}
% \begin{macrocode}
- % \AtBeginDocument{\nocite{#1}}
+ \AddToHook{begindocument/end}[kernel]{\nocite{#1}}%
\fi
\@esphack}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\nocite}{Allow nocite in preamble}%
+%<latexrelease>
+%<latexrelease>\def\nocite#1{\@bsphack
+%<latexrelease> \ifx\@onlypreamble\document
+%<latexrelease> \@for\@citeb:=#1\do{%
+%<latexrelease> \edef\@citeb{\expandafter\@firstofone\@citeb}%
+%<latexrelease> \if@filesw\immediate\write\@auxout{\string\citation{\@citeb}}\fi
+%<latexrelease> \@ifundefined{b@\@citeb}{\G@refundefinedtrue
+%<latexrelease> \@latex@warning{Citation `\@citeb' undefined}}{}}%
+%<latexrelease> \else
+%<latexrelease> \@latex@error{Cannot be used in preamble}\@eha
+%<latexrelease> \fi
+%<latexrelease> \@esphack}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
+%
% Since |\nocite{*}| should not produce a warning about undefined
-% citation keys (seee PR 557), we need to set the control sequence
+% citation keys (see PR 557), we need to set the control sequence
% `|\b@*|' to something other than |\relax|. As a result |\cite{*}|
% will not warn either (but that never worked with \BibTeX{} in the
% first place).
diff --git a/macros/latex/base/ltboxes.dtx b/macros/latex/base/ltboxes.dtx
index 39c134b3bf..8499d3ab8b 100644
--- a/macros/latex/base/ltboxes.dtx
+++ b/macros/latex/base/ltboxes.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltboxes.dtx}
- [2020/09/27 v1.4a LaTeX Kernel (Box Commands)]
+ [2021/02/10 v1.4b LaTeX Kernel (Box Commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltboxes.dtx}
@@ -222,7 +222,7 @@
% \changes{v1.0j}{1994/10/18}
% {stuff from ltpatch done}
% \changes{v1.0p}{1994/11/09}
-% {more colour changes\ldots}
+% {more color changes\ldots}
% \changes{v1.0q}{1994/11/17}
% {\cs{@tempa} to \cs{reserved@a}}
% \changes{v1.0t}{1995/05/07}{Use \cs{hb@xt@}}
@@ -422,7 +422,7 @@
% {macro added}
% \changes{v0.1a}{1993/12/03}
% {color support}
-% This macro is initially a no-op, but the colour package will redefine
+% This macro is initially a no-op, but the color package will redefine
% it to insert a |\special|.
% \begin{macrocode}
\let\set@color\relax
@@ -431,38 +431,66 @@
%
% \begin{macro}{\color@begingroup}
% \changes{v1.0b}{1994/03/14}
-% {macro added for colour support}
+% {macro added for color support}
% \begin{macro}{\color@endgroup}
% \changes{v1.0b}{1994/03/14}
-% {macro added for colour support}
+% {macro added for color support}
% \begin{macro}{\color@setgroup}
% \changes{v1.0f}{1994/05/11}
-% {macro added for colour support}
+% {macro added for color support}
% \begin{macro}{\normalcolor}
% \changes{v1.0g}{1994/05/12}
-% {macro added for colour support}
+% {macro added for color support}
% \begin{macro}{\color@hbox}
% \changes{v1.0n}{1994/11/05}
-% {macro added for colour support}
+% {macro added for color support}
% \begin{macro}{\color@vbox}
% \changes{v1.0r}{1994/11/18}
-% {macro added for colour support}
+% {macro added for color support}
% \begin{macro}{\color@endbox}
% \changes{v1.0n}{1994/11/05}
-% {macro added for colour support}
-% These macros are initially a no-op, but the colour package will
+% {macro added for color support}
+% \changes{v1.4b}{2021/02/04}
+% {Always add the color groups (gh/488)}
+% In the past these macros were initially no-ops, and the \pkg{color}
+% package redefined
% redefine them to be |\begingroup|, |\endgroup|,
% |\begingroup\set@color|,\\ |\hbox\bgroup\color@begingroup|,
% |\color@endgroup\egroup|.
-% and \meta{set to main document colour} respectively.
+% and \meta{set to main document color} respectively.
+%
+% Nowadays we always set the group already in the kernel as this makes the
+% coding simpler.
% \begin{macrocode}
-\let\color@begingroup\relax
-\let\color@endgroup\relax
-\let\color@setgroup\relax
-\let\normalcolor\relax
-\let\color@hbox\relax
-\let\color@vbox\relax
-\let\color@endbox\relax
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\color@begingroup}{color group settings}%
+\let\color@begingroup\begingroup
+\def\color@endgroup{\endgraf\endgroup}
+\def\color@setgroup{\color@begingroup} % changed further in color package
+\let\normalcolor\relax % remains untouched; only changed in a color package
+\def\color@hbox{\hbox\bgroup\color@begingroup}
+\def\color@vbox{\vbox\bgroup\color@begingroup}
+\def\color@endbox{\color@endgroup\egroup}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\color@begingroup}{color group settings}%
+%<latexrelease>
+%<latexrelease>\let\color@begingroup\relax
+%<latexrelease>\let\color@endgroup\relax
+%<latexrelease>\let\color@setgroup\relax
+%<latexrelease>\let\normalcolor\relax
+%<latexrelease>\let\color@hbox\relax
+%<latexrelease>\let\color@vbox\relax
+%<latexrelease>\let\color@endbox\relax
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -539,7 +567,7 @@
% \changes{v1.0b}{1994/03/14}
% {Use \cs{color@setgroup}}
% \changes{v1.0d}{1994/04/15}
-% {Added missing procent character.}
+% {Added missing percent character.}
% \changes{v1.0v}{1995/07/20}
% {Use \cs{sbox}}
% \begin{macrocode}
@@ -888,7 +916,7 @@
%
% The rational for allowing two normally global flags to be set
% locally here was stated originally by
-% Donald Arsenau and extended by Chris Rowley.
+% Donald Arseneau and extended by Chris Rowley.
% It is because these flags are only set globally to
% true by section commands, and these should never appear within
% boxes or, indeed, in any group; and they are only ever
@@ -1016,7 +1044,7 @@
%
% \begin{macro}{\@iiiminipage}
% \changes{v1.0e}{1994/04/21}
-% {Extra \cs{bgroup} for colour}
+% {Extra \cs{bgroup} for color}
% \changes{v1.0f}{1994/05/11}
% {Use new \cs{color@setgroup} concept.}
% Internal form of |minipage|.
@@ -1054,11 +1082,11 @@
% {(RmS) replaced \cs{vskip}-\cs{lastskip} by \cs{unskip}
% (proposed by FMi)}
% \changes{v1.0e}{1994/04/21}
-% {Extra \cs{egroup} for colour}
+% {Extra \cs{egroup} for color}
% \changes{v1.0f}{1994/05/11}
% {Use new \cs{color@setgroup} concept.}
% \changes{v1.0n}{1994/11/05}
-% {Colour resetting for footnotes moved to here: as for main
+% {Color resetting for footnotes moved to here: as for main
% page.}
% \begin{macrocode}
\def\endminipage{%
@@ -1093,9 +1121,9 @@
% Final |\strut| added 27 Mar 89, on suggestion by Don Hosek
% \changes{LaTeX2.09}{1991/09/29}{(RmS) added \cs{reset@font}}
% \changes{LaTeX2.09}{1992/11/26}{(RmS) added protection for \cs{edef}}
-% \changes{v0.1a}{1994/03/07}{Extra group for colour}
+% \changes{v0.1a}{1994/03/07}{Extra group for color}
% \changes{v1.0e}{1994/04/21}
-% {Extra \cs{endgraf} for colour}
+% {Extra \cs{endgraf} for color}
% \changes{v1.0f}{1994/05/11}
% {Use new \cs{color@setgroup} concept.}
% \changes{v1.0f}{1994/05/11}
@@ -1103,11 +1131,17 @@
% \changes{v1.0m}{1994/11/04}
% {Added \cs{protected@edef}. ASAJ.}
% \changes{v1.0n}{1994/11/05}
-% {Colour resetting for footnotes moved to endminipage: as for main
+% {Color resetting for footnotes moved to endminipage: as for main
% page.}
% \changes{v1.0o}{1994/11/05}
-% {Colour groups restored here.}
+% {Color groups restored here.}
+% \changes{v1.4b}{2021/02/10}
+% {Explicitly run \cs{par} in support for paragraph tagging}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@mpfootnotetext}{footnotetext tagging}%
\long\def\@mpfootnotetext#1{%
\global\setbox\@mpfootins\vbox{%
\unvbox\@mpfootins
@@ -1119,7 +1153,31 @@
\color@begingroup
\@makefntext{%
\rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+ \par
\color@endgroup}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@mpfootnotetext}{footnotetext tagging}%
+%<latexrelease>
+%<latexrelease>\long\def\@mpfootnotetext#1{%
+%<latexrelease> \global\setbox\@mpfootins\vbox{%
+%<latexrelease> \unvbox\@mpfootins
+%<latexrelease> \reset@font\footnotesize
+%<latexrelease> \hsize\columnwidth
+%<latexrelease> \@parboxrestore
+%<latexrelease> \protected@edef\@currentlabel
+%<latexrelease> {\csname p@mpfootnote\endcsname\@thefnmark}%
+%<latexrelease> \color@begingroup
+%<latexrelease> \@makefntext{%
+%<latexrelease> \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+%<latexrelease> \color@endgroup}}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
diff --git a/macros/latex/base/ltclass.dtx b/macros/latex/base/ltclass.dtx
index c62136c309..a0ab0fa354 100644
--- a/macros/latex/base/ltclass.dtx
+++ b/macros/latex/base/ltclass.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltclass.dtx}
- [2020/12/17 v1.3v LaTeX Kernel (Class & Package Interface)]
+ [2021/05/18 v1.4b LaTeX Kernel (Class & Package Interface)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltclass.dtx}
@@ -427,7 +427,7 @@
% \changes{v0.2h}{1993/11/28}
% {Primitive filenames now terminated by space not \cs{relax}.}
% \changes{v0.2h}{1993/11/28}
-% {Directory syntax checing moved to dircheck.dtx}
+% {Directory syntax checking moved to dircheck.dtx}
% \changes{v0.2h}{1993/11/28}
% {Assorted commands now in the kernel removed.}
% \changes{v0.2i}{1993/12/03}
@@ -486,7 +486,7 @@
% \begin{macro}{\@declaredoptions}
% This list is automatically built by |\DeclareOption|.
% It is the list of options (separated by commas) declared in
-% the class or package file and it defines the order in which the
+% the class or package file and it defines the order in which
% the corresponding |\ds@|\meta{option} commands are executed.
% All local \meta{option}s which are not declared will be processed
% in the order defined by the optional argument of |\documentclass|
@@ -505,6 +505,14 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@raw@classoptionslist}
+% List of options of the main class (unprocessed).
+% \changes{v1.4b}{2021/05/18}{Initialise to \cs{relax} to match \cs{@classoptionslist}}
+% \begin{macrocode}
+\let\@raw@classoptionslist\relax
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@unusedoptionlist}
% \changes{v1.0u}{1996/07/26}{made only preamble}
% List of options of the main class that haven't been declared or
@@ -640,14 +648,38 @@
%<latexrelease> \@expl@push@filename@aux@@}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>
+% \end{macrocode}
+%
+% When we roll back from a release that has \pkg{expl3} preloaded, the
+% definitions of \cs{@pushfilename} and \cs{@popfilename} can't be
+% completely rolled back otherwise \pkg{expl3}-based packages won't
+% have the automatic \cs{ExplSyntaxOff} at the end. Here and below for
+% \cs{@popfilename}, we don't roll back all the way through if coming
+% from \LaTeX${}>2020-02-02$.
+% \changes{v1.4a}{2021/03/27}
+% {Do not completely roll back if \pkg{expl3} is loaded.}
+% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}{\@pushfilename}%
%<latexrelease> {Add \@expl@push@filename@@ and \@expl@push@filename@aux@@}%
+%<latexrelease>\ifnum\sourceLaTeXdate<20200202\relax
+%<latexrelease> \GenericInfo{}{Defining 00-00-00\string\@pushfilename.}
%<latexrelease>\def\@pushfilename{%
%<latexrelease> \xdef\@currnamestack{%
%<latexrelease> {\@currname}%
%<latexrelease> {\@currext}%
%<latexrelease> {\the\catcode`\@}%
%<latexrelease> \@currnamestack}}
+%<latexrelease>\else
+%<latexrelease> \GenericInfo{}{Defining 2020-02-02\string\@pushfilename.}
+%<latexrelease>\def\@pushfilename{%
+%<latexrelease> \@expl@push@filename@@
+%<latexrelease> \xdef\@currnamestack{%
+%<latexrelease> {\@currname}%
+%<latexrelease> {\@currext}%
+%<latexrelease> {\the\catcode`\@}%
+%<latexrelease> \@currnamestack}%
+%<latexrelease> \@expl@push@filename@aux@@}
+%<latexrelease>\fi
%<latexrelease>\EndIncludeInRelease
\@onlypreamble\@pushfilename
% \end{macrocode}
@@ -676,9 +708,21 @@
%<latexrelease> \@expl@pop@filename@@}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>
+% \end{macrocode}
+%
+% \changes{v1.4a}{2021/03/27}
+% {Do not completely roll back if \pkg{expl3} is loaded.}
+% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}{\@popfilename}%
%<latexrelease> {Add \@expl@push@filename@@ and \@expl@push@filename@aux@@}%
+%<latexrelease>\ifnum\sourceLaTeXdate<20200202\relax
+%<latexrelease> \GenericInfo{}{Defining 00-00-00\string\@popfilename.}
%<latexrelease>\def\@popfilename{\expandafter\@p@pfilename\@currnamestack\@nil}
+%<latexrelease>\else
+%<latexrelease> \GenericInfo{}{Defining 2020-02-02\string\@popfilename.}
+%<latexrelease>\def\@popfilename{\expandafter\@p@pfilename\@currnamestack\@nil
+%<latexrelease> \@expl@pop@filename@@}
+%<latexrelease>\fi
%<latexrelease>\EndIncludeInRelease
\@onlypreamble\@popfilename
% \end{macrocode}
@@ -712,6 +756,7 @@
% Path to the current file if explicitly given. The auxiliary is
% needed here to insert a \cs{@empty} to prevent the loss of braces.
% \changes{v1.3u}{2020/11/20}{Macro added}
+% \changes{v1.3w}{2021/01/21}{Add empty entry for latexrelease}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
@@ -719,6 +764,7 @@
%<latexrelease>\IncludeInRelease{2020/10/01}{\@kernel@currpathstack}%
%<latexrelease> {Add \@kernel@currpathstack}%
\gdef\@kernel@currpathstack{}
+%<latexrelease>\g@addto@macro\@kernel@currpathstack{{}}
\def\@p@pfilepath#1{%
\gdef\@currpath{#1}\@p@pfilepath@aux\@empty}
\def\@p@pfilepath@aux#1\@nil{%
@@ -1026,12 +1072,12 @@
% be cautious when handling the identification string in case it
% contains UTF-8 characters.
% \changes{v1.3e}{2019/11/29}{Protect package info text (gh/52)}
-% \changes{v1.3r}{2020/10/01}{Allow for package subsitution}
+% \changes{v1.3r}{2020/10/01}{Allow for package substitution}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
-%<latexrelease> {\@pr@videpackage}{Allow for package subsitution}%
+%<latexrelease> {\@pr@videpackage}{Allow for package substitution}%
\def\@pr@videpackage[#1]{%
\expandafter\protected@xdef % <-- protected...
\csname ver@\@currname.\@currext\endcsname{#1}% Loaded package
@@ -1164,13 +1210,14 @@
%
% \begin{macro}{\PassOptionsToPackage}
% \begin{macro}{\PassOptionsToClass}
-% If the package has been loaded, we check that it was first loaded with
-% the options. Otherwise we add the option list to that of the package.
+% If the package has been loaded, we check that it was first loaded with
+% the options. Otherwise we add the option list to that of the package.
% \changes{v1.3t}{2020/10/18}{Drop path from \cs{input@path} (gh/414).}
+% \changes{v1.3x}{2021/02/18}{save raw option lists (gh/85)}
% \begin{macrocode}
%</2ekernel>
-%<latexrelease>\IncludeInRelease{2020/10/01}{\@pass@ptions}
-%<latexrelease> {Add file replacement in \@pass@ptions}%
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@pass@ptions}{Raw option lists}%
%<*2ekernel|latexrelease>
\def\@pass@ptions#1#2#3{%
\@expl@@@filehook@set@curr@file@@nNN
@@ -1187,12 +1234,41 @@
% \begin{macrocode}
\expandafter\let
\csname opt@#3.#1\expandafter\endcsname
- \csname opt@\reserved@a\endcsname}
+ \csname opt@\reserved@a\endcsname
+% \end{macrocode}
+% Extend raw option list
+% \begin{macrocode}
+ \@ifundefined{@raw@opt@#3.#1}%
+ {\expandafter\gdef\csname @raw@opt@#3.#1\endcsname{#2}}%
+ {\expandafter\g@addto@macro\csname @raw@opt@#3.#1\endcsname{,#2}}%
+}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@pass@ptions}
+%<latexrelease> {Add file replacement in \@pass@ptions}%
+%<latexrelease>
+%<latexrelease>\def\@pass@ptions#1#2#3{%
+%<latexrelease> \@expl@@@filehook@set@curr@file@@nNN
+%<latexrelease> {\@expl@@@filehook@resolve@file@subst@@w #3.#1\@nil}%
+%<latexrelease> \reserved@a\reserved@b
+%<latexrelease> \@expl@@@filehook@clear@replacement@flag@@
+%<latexrelease> \expandafter\xdef\csname opt@\reserved@a\endcsname{%
+%<latexrelease> \@ifundefined{opt@\reserved@a}\@empty
+%<latexrelease> {\csname opt@\reserved@a\endcsname,}%
+%<latexrelease> \zap@space#2 \@empty}%
+%<latexrelease> \expandafter\let
+%<latexrelease> \csname opt@#3.#1\expandafter\endcsname
+%<latexrelease> \csname opt@\reserved@a\endcsname}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}{\@pass@ptions}
%<latexrelease> {\@pass@ptions}%
+%<latexrelease>
%<latexrelease>\def\@pass@ptions#1#2#3{%
%<latexrelease> \expandafter\xdef\csname opt@#3.#1\endcsname{%
%<latexrelease> \@ifundefined{opt@#3.#1}\@empty
@@ -1200,6 +1276,9 @@
%<latexrelease> \zap@space#2 \@empty}}
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
\@onlypreamble\@pass@ptions
% \end{macrocode}
%
@@ -1241,18 +1320,49 @@
% \end{macro}
%
% \begin{macro}{\OptionNotUsed}
+% \changes{v1.3x}{2021/02/18}{filter out =value from unused option list (gh/85)}
+% \begin{macro}{\@remove@eq@value}
+% \changes{v1.3x}{2021/02/18}{macro added (gh/85)}
% If we are in a class file, add |\CurrentOption| to the list of
% unused options. Otherwise, in a package file do nothing.
% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\OptionNotUsed}{filter unused option list}%
+%<*2ekernel|latexrelease>
+\def\@remove@eq@value#1=#2\@nil{#1}
+% \end{macrocode}
+%
+% \begin{macrocode}
\def\OptionNotUsed{%
\ifx\@currext\@clsextension
\xdef\@unusedoptionlist{%
\ifx\@unusedoptionlist\@empty\else\@unusedoptionlist,\fi
- \CurrentOption}%
+ \expandafter\@remove@eq@value\CurrentOption=\@nil}%
\fi}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\OptionNotUsed}{filter unused option list}%
+%<latexrelease>\let\@remove@eq@value\@undefined
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\def\OptionNotUsed{%
+%<latexrelease> \ifx\@currext\@clsextension
+%<latexrelease> \xdef\@unusedoptionlist{%
+%<latexrelease> \ifx\@unusedoptionlist\@empty\else\@unusedoptionlist,\fi
+%<latexrelease> \CurrentOption}%
+%<latexrelease> \fi}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
\@onlypreamble\OptionNotUsed
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\default@ds}
% The default option code.
@@ -1279,7 +1389,7 @@
% \changes{v0.2a}{1993/11/14}
% {Stop adding the global option list inside class files.}
% \changes{v0.2a}{1993/11/14}
-% {Optimise `empty option' code.}
+% {Optimize `empty option' code.}
% \changes{v0.2b}{1993/11/15}
% {Star form added.}
% \changes{v0.2c}{1993/11/17}
@@ -1312,19 +1422,50 @@
%
% \changes{v0.2y}{1994/02/07}
% {Add extra ,s so `two' is not matched with `twocolumn'}
+% \changes{v1.3z}{2021/03/05}{modify so braces to not give errors (gh/513)}
% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@xprocess@ptions}{safer @xprocess@ptions}%
+%<*2ekernel|latexrelease>
\def\@xprocess@ptions{%
\ifx\@currext\@clsextension\else
+ \ifx\@classoptionslist\relax\else
\@for\CurrentOption:=\@classoptionslist\do{%
\ifx\CurrentOption\@empty\else
- \@expandtwoargs\in@{,\CurrentOption,}{,\@declaredoptions,}%
- \ifin@
+ \@ifundefined{ds@\CurrentOption}{}{%
\@use@ption
\expandafter\let\csname ds@\CurrentOption\endcsname\@empty
- \fi
+ }%
\fi}%
+ \fi
\fi
\@process@pti@ns}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@xprocess@ptions}{safer @xprocess@ptions}%
+%<latexrelease>\let\@remove@eq@value\@undefined
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\def\@xprocess@ptions{%
+%<latexrelease> \ifx\@currext\@clsextension\else
+%<latexrelease> \@for\CurrentOption:=\@classoptionslist\do{%
+%<latexrelease> \ifx\CurrentOption\@empty\else
+%<latexrelease> \@expandtwoargs\in@{,\CurrentOption,}{,\@declaredoptions,}%
+%<latexrelease> \ifin@
+%<latexrelease> \@use@ption
+%<latexrelease> \expandafter\let\csname ds@\CurrentOption\endcsname\@empty
+%<latexrelease> \fi
+%<latexrelease> \fi}%
+%<latexrelease> \fi
+%<latexrelease> \@process@pti@ns}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
\@onlypreamble\@xprocess@ptions
% \end{macrocode}
%
@@ -1403,11 +1544,30 @@
% {Name changed from \cs{@executeoption}}
% \changes{v1.0e}{1994/05/17}
% {Execute option after removing from list, not before}
+% \changes{v1.3x}{2021/02/18}{filter out =value from unused option list (gh/85)}
% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@use@ption}{filter unused option list}%
+%<*2ekernel|latexrelease>
\def\@use@ption{%
- \@expandtwoargs\@removeelement\CurrentOption
+ \@expandtwoargs\@removeelement
+ {\expandafter\@remove@eq@value\CurrentOption=\@nil}%
\@unusedoptionlist\@unusedoptionlist
\csname ds@\CurrentOption\endcsname}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@use@ption}{filter unused option list}%
+%<latexrelease>\def\@use@ption{%
+%<latexrelease> \@expandtwoargs\@removeelement\CurrentOption
+%<latexrelease> \@unusedoptionlist\@unusedoptionlist
+%<latexrelease> \csname ds@\CurrentOption\endcsname}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
\@onlypreamble\@use@ption
% \end{macrocode}
% \end{macro}
@@ -1460,7 +1620,7 @@
% the internal command, |\@fileswithoptions|.
% \begin{macro}{\documentclass}
% \changes{v1.0q}{1995/06/19}
-% {Dont redefine \cs{usepackage} in compat mode for /1634}
+% {Don't redefine \cs{usepackage} in compat mode for /1634}
% The main new-style class declaration.
% \begin{macrocode}
\def\documentclass{%
@@ -1721,15 +1881,23 @@
% {Prevent loss of brackets PR/3965}
% \changes{v2.1b}{2016/11/09}
% {Improve \cs{ifx} tests PR/4497}
+% \changes{v1.3x}{2021/02/18}{save raw class option list (gh/85)}
% \begin{macrocode}
%</2ekernel>
-%<latexrelease>\IncludeInRelease{2017/01/01}%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease> {\@fileswith@pti@ns}{ifx tests in \@fileswith@pti@ns}%
%<*2ekernel|latexrelease>
\def\@fileswith@pti@ns#1[#2]#3[#4]{%
\ifx#1\@clsextension
\ifx\@classoptionslist\relax
\xdef\@classoptionslist{\zap@space#2 \@empty}%
+% \end{macrocode}
+% Save raw class list.
+% \begin{macrocode}
+ \gdef\@raw@classoptionslist{#2}%
+% \end{macrocode}
+%
+% \begin{macrocode}
\def\reserved@a{%
\@onefilewithoptions#3[{#2}][{#4}]#1%
\@documentclasshook}%
@@ -1750,8 +1918,8 @@
% \begin{macrocode}
\ifx\@nnil##1\relax\else
% \end{macrocode}
-% If |\ifx\@nnil##1\n@nil| is true then |#1| is (presumably) empty
-% (Older code used |\relax| which is slighly easier to get into |#1|
+% If |\ifx\@nnil##1\@nnil| is true then |#1| is (presumably) empty
+% (Older code used |\relax| which is slightly easier to get into |#1|
% by mistake, which would spoil this test.)
% \begin{macrocode}
\ifx\@nnil##1\@nnil\else
@@ -1768,6 +1936,33 @@
\fi
\reserved@a}
%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2017/01/01}%
+%<latexrelease> {\@fileswith@pti@ns}{ifx tests in \@fileswith@pti@ns}%
+%<latexrelease>\def\@fileswith@pti@ns#1[#2]#3[#4]{%
+%<latexrelease> \ifx#1\@clsextension
+%<latexrelease> \ifx\@classoptionslist\relax
+%<latexrelease> \xdef\@classoptionslist{\zap@space#2 \@empty}%
+%<latexrelease> \def\reserved@a{%
+%<latexrelease> \@onefilewithoptions#3[{#2}][{#4}]#1%
+%<latexrelease> \@documentclasshook}%
+%<latexrelease> \else
+%<latexrelease> \def\reserved@a{%
+%<latexrelease> \@onefilewithoptions#3[{#2}][{#4}]#1}%
+%<latexrelease> \fi
+%<latexrelease> \else
+%<latexrelease> \def\reserved@b##1,{%
+%<latexrelease> \ifx\@nnil##1\relax\else
+%<latexrelease> \ifx\@nnil##1\@nnil\else
+%<latexrelease> \noexpand\@onefilewithoptions##1[{#2}][{#4}]%
+%<latexrelease> \noexpand\@pkgextension
+%<latexrelease> \fi
+%<latexrelease> \expandafter\reserved@b
+%<latexrelease> \fi}%
+%<latexrelease> \edef\reserved@a{\zap@space#3 \@empty}%
+%<latexrelease> \edef\reserved@a{\expandafter\reserved@b\reserved@a,\@nnil,}%
+%<latexrelease> \fi
+%<latexrelease> \reserved@a}
% \end{macrocode}
%
% \begin{macrocode}
@@ -1834,7 +2029,7 @@
% \usepackage{some/local/path/array}
% \usepackage{array}
% \end{verbatim}
-% won't load \file{array.sty} twice. It is remotely possible that
+% won't load |array.sty| twice. It is remotely possible that
% those are two different files, but as a matter of principles, we
% will consider that the base file name uniquely identifies a
% package, regardless of where it lives. This assumption already
@@ -2087,7 +2282,7 @@
% loaded.}
%
% This has changed in 2020. We now use a separate macro per package
-% to avoid interferences in case of nested packages. The whole
+% to avoid interference in case of nested packages. The whole
% code for handling this issue (GitHub 22) was provided by Hironobu
% Yamashita, thanks for that.
% \changes{v1.3k}{2020/04/07}{Use different method to ignore
@@ -2424,7 +2619,7 @@
% \changes{v0.2r}{1993/12/19}{Different message when ignoring a file}
% \changes{v0.3g}{1994/04/11}
% {Add star form,
-% dont write \cs{endinput} at the end of the file.}
+% don't write \cs{endinput} at the end of the file.}
% \changes{v1.0c}{1994/05/11}
% {Add checks for form feed and tab}
% \changes{v1.0m}{1995/04/21}
@@ -2549,15 +2744,15 @@
% this only works for input files ending in \texttt{.tex}. If a
% different extension is used there is no way to see that we are
% overwriting ourselves!
+% \changes{v1.3y}{2021/03/03}
+% {Fix overwrite check for files with UTF-8 (gh/415)}
% \begin{macrocode}
- \edef\reserved@a{#1}%
- \edef\reserved@a{\detokenize\expandafter{\reserved@a}}%
\edef\reserved@b{\detokenize\expandafter{\jobname}}%
- \ifx\reserved@a\reserved@b%
+ \ifx\@curr@file\reserved@b%
\@fileswtrue%
\else%
\edef\reserved@b{\reserved@b\detokenize{.tex}}%
- \ifx\reserved@a\reserved@b
+ \ifx\@curr@file\reserved@b
\@fileswtrue%
\fi%
\fi%
@@ -2640,7 +2835,8 @@
% Text before the |\end|, write it with a warning.
% \begin{macrocode}
\@latex@warning{Writing text `##1' before %
- \string\end{\@currenvir}\MessageBreak as last line of \@curr@file}%
+ \string\end{\@currenvir}\MessageBreak
+ as last line of \@curr@file}%
\immediate\write\reserved@c{##1}%
\fi%
\ifx\relax##2\relax%
@@ -2675,7 +2871,8 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}%
+%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}%
+%<latexrelease>
%<latexrelease>\def\filecontents{\@tempswatrue\@fileswtrue
%<latexrelease> \@ifnextchar[\filec@ntents@opt\filec@ntents
%<latexrelease>}
@@ -2805,7 +3002,7 @@
%<latexrelease>\endgroup%
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}%
+%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}%
%<latexrelease>
%<latexrelease>\let\filec@ntents@opt \@undefined
%<latexrelease>\let\filec@ntents@force \@undefined
@@ -2976,7 +3173,7 @@
% YYYYMMDD (if there was one, otherwise the value of
% |\requestedLaTeXdate|) and |\pkgcls@targetlabel| will be
% empty. If there was a request for a named version then
-% |\pkgcls@targetlabel| holds the verion name and
+% |\pkgcls@targetlabel| holds the version name and
% |\pkgcls@targetdate| is set to \texttt{1}.
%
% |\pkgcls@targetdate=0| is used to indicate that there was no
@@ -3063,7 +3260,7 @@
\pkgcls@parse@date@arg{#3}%
% \end{macrocode}
% When determining the correct release to load we keep track of
-% candiates in |\pkgcls@candidate| and initially we don't have any:
+% candidates in |\pkgcls@candidate| and initially we don't have any:
% \begin{macrocode}
\let\pkgcls@candidate\@empty
% \end{macrocode}
@@ -3103,7 +3300,7 @@
%
% But if it starts with an equal sign followed by a date string or
% followed by a version name then this means that we should roll
-% back to the state of the package at tht date or to the version
+% back to the state of the package at that date or to the version
% with the requested name.
%
% If there was no optional argument or the optional argument
@@ -3381,7 +3578,7 @@
%
% \begin{macro}{\pkgcls@show@selection}
% This command records what selection was made. As that is needed
-% in two places (and it is rather lengthly) it was placed in a
+% in two places (and it is rather lengthy) it was placed in a
% separate command. The first argument is the name of the external
% file that is being loaded and is only needed for debugging. The
% second argument is the date that corresponds to this file and it
@@ -3484,7 +3681,7 @@
\pkgcls@releasedate
\fi
% \end{macrocode}
-% Otherwise the curent file is the right release, so we record that
+% Otherwise the current file is the right release, so we record that
% in the transcript and then carry on.
% \begin{macrocode}
\else
diff --git a/macros/latex/base/ltcmd.dtx b/macros/latex/base/ltcmd.dtx
new file mode 100644
index 0000000000..806161d538
--- /dev/null
+++ b/macros/latex/base/ltcmd.dtx
@@ -0,0 +1,4034 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 1999 Frank Mittelbach, Chris Rowley, David Carlisle
+% Copyright (C) 2004-2008 Frank Mittelbach, The LaTeX3 Project
+% Copyright (C) 2009-2021
+% 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: ltcmd.dtx
+%
+% \begin{macrocode}
+\def\ltcmdversion{v1.0e}
+\def\ltcmddate{2021-05-24}
+% \end{macrocode}
+%
+%<*driver>
+% \fi
+\ProvidesFile{ltcmd.dtx}
+ [\ltcmddate\space \ltcmdversion\space
+ LaTeX Kernel (Document commands)]
+% \iffalse
+\documentclass{l3doc}
+\GetFileInfo{ltcmd.dtx}
+\title{\filename}
+\date{\filedate}
+\author{Frank Mittelbach, Chris Rowley, David Carlisle, \LaTeX{} Project Team}
+\begin{document}
+ \maketitle
+ \DocInput{ltcmd.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \section{Creating document commands}
+%
+% \changes{v1.0a}{2020/11/20}{Initial version derived from \texttt{xparse.dtx}}
+%
+% Document commands should be created using the tools provided by this module:
+% \cs{NewDocumentCommand}, etc.\@, in almost all cases. This allows clean
+% separation of document-level syntax from code-level interfaces. Users have
+% a need to create new document commands, and as such a significant amount of
+% documentation for \pkg{ltcmd} is provided as part of \texttt{usrguide3}. Here,
+% additional material aimed at programmers is provided
+%
+% \StopEventually{}
+%
+% \begin{macrocode}
+%<@@=cmd>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*2ekernel>
+\message{document commands,}
+%</2ekernel>
+% \end{macrocode}
+%
+% \changes{v1.0b}{2021/03/18}{Use \cs{NewModuleRelease}.}
+% \changes{v1.0e}{2021/05/24}{Use \cs{msg_...} instead of \cs{__kernel_msg...}}
+%
+%
+% \pkg{ltcmd} code contains an |^^@| character, which usually has
+% catcode~15, so \cs{IncludeInRelease} will break when this code is
+% being skipped, so we'll save the catcode of |^^@| to restore later:
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\edef\@latexrelease@catcode@null{\the\catcode`\^^@ }
+%<latexrelease>\catcode`\^^@=12
+\ExplSyntaxOn
+%<latexrelease>\NewModuleRelease{2020/10/01}{ltcmd}
+%<latexrelease> {Document~command~parser}%
+% \end{macrocode}
+%
+% \subsection{Variables and constants}
+%
+% \begin{variable}{\l_@@_arg_spec_tl}
+% Holds the argument specification after normalization of shorthands.
+% \begin{macrocode}
+\tl_new:N \l_@@_arg_spec_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_args_tl}
+% Token list variable for grabbed arguments.
+% \begin{macrocode}
+\tl_new:N \l_@@_args_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_args_i_tl, \l_@@_args_ii_tl}
+% Hold the modified arguments when dealing with default values or
+% processors.
+% \begin{macrocode}
+\tl_new:N \l_@@_args_i_tl
+\tl_new:N \l_@@_args_ii_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_current_arg_int}
+% The number of the current argument being set up: this is used to
+% make sure there are at most 9 arguments, then for creating the
+% expandable auxiliary functions and knowing how many arguments the
+% code function should take.
+% \begin{macrocode}
+\int_new:N \l_@@_current_arg_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_defaults_bool, \l_@@_defaults_tl}
+% The boolean indicates whether there are any argument with default
+% value other than |-NoValue-|; the token list holds the code to
+% determine these default values in terms of other arguments.
+% \begin{macrocode}
+\bool_new:N \l_@@_defaults_bool
+\tl_new:N \l_@@_defaults_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_environment_bool}
+% Generating environments uses the same mechanism as generating functions.
+% However, full processing of arguments is always needed for environments,
+% and so the function-generating code needs to know this.
+% This variable is also used at run time to give correct error messages.
+% \begin{macrocode}
+\bool_new:N \l_@@_environment_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_environment_str}
+% Name of the environment, used at definition time and at run time.
+% \begin{macrocode}
+\str_new:N \l_@@_environment_str
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_expandable_bool}
+% Used to indicate if an expandable command is begin generated, as this
+% affects both the acceptable argument types and how they are implemented.
+% \begin{macrocode}
+\bool_new:N \l_@@_expandable_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_expandable_aux_name_tl}
+% Used to create pretty-printing names for the auxiliaries: although the
+% immediate definition does not vary, the full expansion does and so it
+% does not count as a constant.
+% \begin{macrocode}
+\tl_new:N \l_@@_expandable_aux_name_tl
+\tl_set:Nn \l_@@_expandable_aux_name_tl
+ {
+ \l_@@_function_tl \c_space_tl
+ ( arg~ \int_use:N \l_@@_current_arg_int )
+ }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_grabber_int}
+% Used (in exceptional cases) to get unique names for grabbers used by
+% expandable commands.
+% \begin{macrocode}
+\int_new:N \g_@@_grabber_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_fn_tl}
+% For passing the pre-formed name of the auxiliary to be used as the
+% parsing function.
+% \begin{macrocode}
+\tl_new:N \l_@@_fn_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_fn_code_tl}
+% For passing the pre-formed name of the auxiliary that contains the
+% actual code.
+% \begin{macrocode}
+\tl_new:N \l_@@_fn_code_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_function_tl}
+% Holds the control sequence name of the function currently being
+% defined: used to avoid passing this as an argument and to avoid repeated
+% use of \cs{cs_to_str:N}.
+% \begin{macrocode}
+\tl_new:N \l_@@_function_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_grab_expandably_bool}
+% When defining a non-expandable command, indicates whether the
+% arguments can all safely be grabbed by expandable grabbers. This is
+% to support abuses of \pkg{xparse} that use protected functions
+% inside csname constructions.
+% \begin{macrocode}
+\bool_new:N \l_@@_grab_expandably_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_obey_spaces_bool}
+% For trailing optionals.
+% \begin{macrocode}
+\bool_new:N \l_@@_obey_spaces_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_last_delimiters_tl}
+% Holds the delimiters (first tokens) of all optional arguments since
+% the previous mandatory argument, to warn about cases where it would
+% be impossible to omit optional arguments completely because the
+% following mandatory argument has the same delimiter as one of the
+% optional arguments.
+% \begin{macrocode}
+\tl_new:N \l_@@_last_delimiters_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_long_bool}
+% Used to indicate that an argument is long, on a per-argument basis.
+% \begin{macrocode}
+\bool_new:N \l_@@_long_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_m_args_int}
+% The number of \texttt{m} arguments: if this is the same as the total
+% number of arguments, then a short-cut can be taken in the creation of
+% the grabber code.
+% \begin{macrocode}
+\int_new:N \l_@@_m_args_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_prefixed_bool}
+% When preparing the signature of non-expandable commands, indicates
+% that the current argument is affected by a processor or by |+|
+% (namely is long).
+% \begin{macrocode}
+\bool_new:N \l_@@_prefixed_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_process_all_tl, \l_@@_process_one_tl, \l_@@_process_some_bool}
+% When preparing the signature, the processors that will be applied to
+% a given argument are collected in \cs{l_@@_process_one_tl}, while
+% \cs{l_@@_process_all_tl} contains processors for all arguments. The
+% boolean indicates whether there are any processors (to bypass the
+% whole endeavour otherwise).
+% \begin{macrocode}
+\tl_new:N \l_@@_process_all_tl
+\tl_new:N \l_@@_process_one_tl
+\bool_new:N \l_@@_process_some_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_saved_args_tl}
+% Stores \cs{l_@@_args_tl} to deal with space-trimming of
+% \texttt{b}-type arguments.
+% \begin{macrocode}
+\tl_new:N \l_@@_saved_args_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_signature_tl}
+% Used when constructing the signature (code for argument grabbing) to
+% hold what will become the implementation of the main function.
+% When arguments are grabbed (at point of use of the command/environment),
+% it also stores the code for grabbing the remaining arguments.
+% \begin{macrocode}
+\tl_new:N \l_@@_signature_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {\l_@@_some_obey_spaces_bool, \l_@@_some_long_bool, \l_@@_some_short_bool}
+% These flags are set while normalizing the argument specification.
+% The \texttt{obey_spaces} one is used to detect when |!| is used on
+% an argument that is not a trailing optional argument.
+% The other two are used to check whether all short arguments appear
+% before long arguments: this is needed to grab arguments expandably.
+% As soon as the first long argument is seen (other than
+% \texttt{t}-type, whose long status is ignored) the
+% \texttt{some_long} flag is set. The \texttt{some_short} flag is
+% used for expandable commands, to know whether to define a short
+% auxiliary too.
+% \begin{macrocode}
+\bool_new:N \l_@@_some_obey_spaces_bool
+\bool_new:N \l_@@_some_long_bool
+\bool_new:N \l_@@_some_short_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_tmp_prop, \l_@@_tmpa_tl, \l_@@_tmpb_tl}
+% \begin{macro}{\@@_tmp:w}
+% Scratch space.
+% \begin{macrocode}
+\prop_new:N \l_@@_tmp_prop
+\tl_new:N \l_@@_tmpa_tl
+\tl_new:N \l_@@_tmpb_tl
+\cs_new_eq:NN \@@_tmp:w ?
+% \end{macrocode}
+% \end{macro}
+% \end{variable}
+%
+% With \pkg{xparse}, information about commands being (re)defined was
+% switched off by default, unless the |log-declarations| package
+% option was used, so here we'll switch that off as well.
+% \begin{macrocode}
+\msg_redirect_module:nnn { cmd } { info } { none }
+% \end{macrocode}
+%
+% Also add \pkg{cmd} to the \pkg{LaTeX} messages.
+% \begin{macrocode}
+\prop_gput:Nnn \g_msg_module_type_prop { cmd } { LaTeX }
+% \end{macrocode}
+%
+% \subsection{Declaring commands and environments}
+%
+% \begin{macro}{\@@_declare_cmd:Nnn, \@@_declare_expandable_cmd:Nnn}
+% \begin{macro}{\@@_declare_cmd_aux:Nnn}
+% \begin{macro}
+% {\@@_declare_cmd_internal:Nnnn, \@@_declare_cmd_internal:cnxn}
+% The main functions for creating commands set the appropriate flag then
+% use the same internal code to do the definition.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_cmd:Nnn
+ {
+ \bool_set_false:N \l_@@_expandable_bool
+ \@@_declare_cmd_aux:Nnn
+ }
+\cs_new_protected:Npn \@@_declare_expandable_cmd:Nnn
+ {
+ \bool_set_true:N \l_@@_expandable_bool
+ \@@_declare_cmd_aux:Nnn
+ }
+% \end{macrocode}
+% The first stage is to log information, both for the user in the log and
+% for programmatic use in a property list of all declared commands.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_cmd_aux:Nnn #1#2#3
+ {
+ \cs_if_exist:NTF #1
+ {
+ \msg_info:nnxx { cmd } { redefine-command }
+ { \token_to_str:N #1 } { \tl_to_str:n {#2} }
+ }
+ {
+ \bool_lazy_or:nnT
+ { \cs_if_exist_p:c { \cs_to_str:N #1 ~ code } }
+ { \cs_if_exist_p:c { \cs_to_str:N #1 ~ defaults } }
+ {
+ \msg_warning:nnx { cmd } { unsupported-let }
+ { \token_to_str:N #1 }
+ }
+ \msg_info:nnxx { cmd } { define-command }
+ { \token_to_str:N #1 } { \tl_to_str:n {#2} }
+ }
+ \bool_set_false:N \l_@@_environment_bool
+ \@@_declare_cmd_internal:Nnnn #1 {#2} {#3} { }
+ }
+% \end{macrocode}
+% At definition time, the variable \cs{l_@@_fn_tl} is only used for error messages.
+% The real business of defining a document command starts with setting up
+% the appropriate name, then normalizing the argument specification to get rid of
+% shorthands.
+% \begin{macrocode}
+\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}
+ #4
+ \@@_break_point:n {#2}
+ }
+\cs_generate_variant:Nn \@@_declare_cmd_internal:Nnnn { cnx }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_break_point:n}
+% A marker used to escape from creating a definition if necessary.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_break_point:n \use_none:n
+% \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.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_cmd_code:Nnn
+ {
+ \bool_if:NTF \l_@@_grab_expandably_bool
+ { \@@_declare_cmd_code_expandable:Nnn }
+ { \@@_declare_cmd_code_aux:Nnn }
+ }
+% \end{macrocode}
+% Standard functions call \cs{@@_start:nNNnnn}, which receives the
+% argument specification, an auxiliary used for
+% grabbing arguments, an auxiliary containing the code, and then the
+% signature, default arguments, and processors.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_cmd_code_aux:Nnn #1#2#3
+ {
+ \cs_generate_from_arg_count:cNnn
+ { \l_@@_function_tl \c_space_tl code }
+ \cs_set_protected:Npn \l_@@_current_arg_int {#3}
+ \cs_set_protected_nopar:Npx #1
+ {
+ \bool_if:NTF \l_@@_environment_bool
+ {
+ \@@_start_env:nnnnn { \exp_not:n {#2} }
+ { \l_@@_environment_str }
+ }
+ {
+ \@@_start:nNNnnn { \exp_not:n {#2} }
+ \exp_not:c { \l_@@_function_tl \c_space_tl }
+ \exp_not:c { \l_@@_function_tl \c_space_tl code }
+ }
+ { \exp_not:o \l_@@_signature_tl }
+ {
+ \bool_if:NT \l_@@_defaults_bool
+ { \exp_not:o \l_@@_defaults_tl }
+ }
+ {
+ \bool_if:NT \l_@@_process_some_bool
+ { \exp_not:o \l_@@_process_all_tl }
+ }
+ }
+ }
+% \end{macrocode}
+% Expandable functions and functions whose arguments can be grabbed
+% expandably call \cs{@@_start_expandable:nNNNNn}, which receives the
+% argument specification, four auxiliaries (two for grabbing arguments, one for
+% the code, and one for default arguments), and finally the signature.
+% Non-expandable functions that take this branch should nevertheless
+% be protected, as well as their \texttt{code} function. They will
+% only be expanded in contexts such as constructing a csname.
+% The two grabbers (named after the function with one or two spaces)
+% are needed when there are both short and long arguments; otherwise
+% the same grabber is included twice in the definition. If all
+% arguments are long or all are short the (only) grabber is defined
+% correspondingly to be long/short. Otherwise two grabbers are
+% defined, one long, one short.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_cmd_code_expandable:Nnn #1#2#3
+ {
+ \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 } :Npn }
+ \l_@@_current_arg_int {#3}
+ \bool_if:NT \l_@@_defaults_bool
+ {
+ \use:x
+ {
+ \cs_generate_from_arg_count:cNnn
+ { \l_@@_function_tl \c_space_tl defaults }
+ \cs_set:Npn \l_@@_current_arg_int
+ { \exp_not:o \l_@@_defaults_tl }
+ }
+ }
+ \bool_if:NTF \l_@@_expandable_bool
+ { \cs_set_nopar:Npx } { \cs_set_protected_nopar:Npx } #1
+ {
+ \exp_not:N \@@_start_expandable:nNNNNn
+ { \exp_not:n {#2} }
+ \exp_not:c { \l_@@_function_tl \c_space_tl }
+ \exp_not:c
+ {
+ \l_@@_function_tl \c_space_tl
+ \bool_if:NT \l_@@_some_short_bool
+ { \bool_if:NT \l_@@_some_long_bool { \c_space_tl } }
+ }
+ \exp_not:c { \l_@@_function_tl \c_space_tl code }
+ \bool_if:NTF \l_@@_defaults_bool
+ { \exp_not:c { \l_@@_function_tl \c_space_tl defaults } }
+ { ? }
+ { \exp_not:o \l_@@_signature_tl }
+ }
+ \bool_if:NTF \l_@@_some_long_bool
+ {
+ \bool_if:NT \l_@@_some_short_bool
+ {
+ \cs_set_nopar:cpx { \l_@@_function_tl \c_space_tl \c_space_tl }
+ ##1##2 { ##1 {##2} }
+ }
+ \cs_set:cpx
+ }
+ { \cs_set_nopar:cpx }
+ { \l_@@_function_tl \c_space_tl } ##1##2 { ##1 {##2} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_declare_env:nnnn}
+% \begin{macro}{\@@_declare_env_internal:nnnn}
+% The lead-off to creating an environment is much the same as that for
+% creating a command: issue the appropriate message, store the argument
+% specification then hand off to an internal function.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_env:nnnn #1#2
+ {
+ \str_set:Nx \l_@@_environment_str {#1}
+ \str_set:Nx \l_@@_environment_str
+ { \tl_trim_spaces:o { \l_@@_environment_str } }
+ \cs_if_exist:cTF { \l_@@_environment_str }
+ {
+ \msg_info:nnxx { cmd } { redefine-environment }
+ { \l_@@_environment_str } { \tl_to_str:n {#2} }
+ }
+ {
+ \msg_info:nnxx { cmd } { define-environment }
+ { \l_@@_environment_str } { \tl_to_str:n {#2} }
+ }
+ \bool_set_false:N \l_@@_expandable_bool
+ \bool_set_true:N \l_@@_environment_bool
+ \exp_args:NV \@@_declare_env_internal:nnnn
+ \l_@@_environment_str {#2}
+ }
+% \end{macrocode}
+% Creating a document environment requires a few more steps than creating
+% a single command. In order to pass the arguments of the command to the
+% end of the function, it is necessary to store the grabbed arguments.
+% To do that, the function used at the end of the environment has to be
+% redefined to contain the appropriate information. To minimize the amount
+% of expansion at point of use, the code here is expanded now as well as
+% when used.
+% The last argument of \cs{@@_declare_cmd_internal:Nnnn} is only run
+% if the definition succeeded. In package mode this ensures that the
+% original definition of the environment is not changed if the
+% definition fails for any reason. This also avoids an error when
+% defining the \verb*|end aux | function when the user asks for more
+% than $9$ arguments.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare_env_internal:nnnn #1#2#3#4
+ {
+ \@@_declare_cmd_internal:cnxn { environment~ #1 } {#2}
+ {
+ \cs_set_nopar:Npx \exp_not:c { environment~ #1 ~end~aux }
+ {
+ \exp_not:N \exp_not:N \exp_not:c { environment~ #1~end~aux~ }
+ \exp_not:n { \exp_not:o \l_@@_args_tl }
+ }
+ \exp_not:n {#3}
+ }
+ {
+ \cs_set_nopar:cpx { environment~ #1 ~end }
+ { \exp_not:c { environment~ #1 ~end~aux } }
+ \cs_generate_from_arg_count:cNnn
+ { environment~ #1 ~end~aux~ } \cs_set:Npn
+ \l_@@_current_arg_int {#4}
+ \cs_set_eq:cc {#1} { environment~ #1 }
+ \cs_set_eq:cc { end #1 } { environment~ #1 ~end }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Structure of \pkg{xparse} commands}
+%
+% \begin{macro}{\@@_start_env:nnnnn, \@@_start:nNNnnn}
+% For error messages that occur during run-time when getting arguments
+% of environments it is necessary to keep track of the environment
+% name. We begin non-expandable commands with a token equal to
+% \cs{scan_stop:}, whose name gives a reasonable error message if the
+% command is used inside a csname and protects against
+% \texttt{f}-expansion. This is useless for environments since
+% \cs{begin} is already not expandable. Both the command and
+% environment codes start with \cs{group_align_safe_begin:}, then
+% \cs{@@_run_code:} (used by both) does \cs{group_align_safe_end:}, so
+% that delimited arguments may be grabbed in alignments if they
+% contain and alignment tab token (see latex3/latex3/issues/839).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_start_env:nnnnn #1#2
+ {
+ \conditionally@traceoff
+ \group_align_safe_begin:
+ \str_set:Nn \l_@@_environment_str {#2}
+ \bool_set_true:N \l_@@_environment_bool
+ \@@_start_aux:ccnnnn
+ { environment~ \l_@@_environment_str \c_space_tl }
+ { environment~ \l_@@_environment_str \c_space_tl code }
+ {#1}
+ }
+\cs_new_protected:Npx \@@_start:nNNnnn #1#2#3
+ {
+ \exp_not:c { xparse~function~is~not~expandable }
+ \exp_not:N \conditionally@traceoff
+ \exp_not:N \group_align_safe_begin:
+ \exp_not:n { \bool_set_false:N \l_@@_environment_bool }
+ \exp_not:N \@@_start_aux:NNnnnn
+ #2 #3 {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_start_aux:NNnnnn, \@@_start_aux:ccnnnn}
+% This sets up a few variables to minimize the boilerplate code
+% included in all \pkg{xparse}-defined commands. It then runs the
+% grabbers~|#4|. Again, the argument specification |#1| is only for
+% diagnostics.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_start_aux:NNnnnn #1#2#3#4#5#6
+ {
+ \tl_clear:N \l_@@_args_tl
+ \tl_set:Nn \l_@@_fn_tl {#1}
+ \tl_set:Nn \l_@@_fn_code_tl {#2}
+ \tl_set:Nn \l_@@_defaults_tl {#5}
+ \tl_set:Nn \l_@@_process_all_tl {#6}
+ #4 \@@_run_code:
+ }
+\cs_generate_variant:Nn \@@_start_aux:NNnnnn { cc }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_run_code:}
+% After arguments are grabbed, this function is responsible for
+% inserting default values, running processors, and finally doing
+% \cs{group_align_safe_end:} as promised, and running the code.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_run_code:
+ {
+ \tl_if_empty:NF \l_@@_defaults_tl { \@@_defaults: }
+ \tl_if_empty:NF \l_@@_process_all_tl { \@@_args_process: }
+ \group_align_safe_end:
+ \conditionally@traceon
+ \exp_after:wN \l_@@_fn_code_tl \l_@@_args_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_defaults:}
+% \begin{macro}{\@@_defaults_def:, \@@_defaults_def:nn, \@@_defaults_def:nnn}
+% \begin{macro}{\@@_defaults_aux:, \@@_defaults_error:w}
+% First construct \cs{@@_tmp:w} (see below) that will receive
+% the arguments found so far and determine default values for any
+% missing argument. Then call it repeatedly until the set of
+% arguments stabilizes. Since that could lead to an infinite loop we
+% only call it up to nine times, the maximal number needed for
+% stabilization if there is a chain of arguments that depend on each
+% other. If that fails to stabilize raise an error.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_defaults:
+ {
+ \@@_defaults_def:
+ \tl_set_eq:NN \l_@@_args_i_tl \l_@@_args_tl
+ \@@_defaults_aux: \@@_defaults_aux: \@@_defaults_aux:
+ \@@_defaults_aux: \@@_defaults_aux: \@@_defaults_aux:
+ \@@_defaults_aux: \@@_defaults_aux: \@@_defaults_aux:
+ \@@_defaults_error:w
+ \q_recursion_stop
+ \tl_set_eq:NN \l_@@_args_tl \l_@@_args_i_tl
+ }
+\cs_new_protected:Npn \@@_defaults_aux:
+ {
+ \tl_set:Nx \l_@@_args_ii_tl
+ { \exp_after:wN \@@_tmp:w \l_@@_args_i_tl }
+ \tl_if_eq:NNT \l_@@_args_ii_tl \l_@@_args_i_tl
+ { \use_none_delimit_by_q_recursion_stop:w }
+ \tl_set_eq:NN \l_@@_args_i_tl \l_@@_args_ii_tl
+ }
+\cs_new_protected:Npn \@@_defaults_error:w \q_recursion_stop
+ {
+ \msg_error:nnx { cmd } { loop-in-defaults }
+ { \@@_environment_or_command: }
+ }
+% \end{macrocode}
+% To construct \cs{@@_tmp:w}, first go through the arguments
+% found and the corresponding defaults, building a token list with
+% |{#|\meta{arg number}|}| for arguments found in the input (whose
+% default will not be used) and otherwise
+% |{|\cs{exp_not:n}\Arg{default}|}| for arguments whose default will
+% be used.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_defaults_def:
+ {
+ \tl_clear:N \l_@@_tmpa_tl
+ \int_zero:N \l_@@_current_arg_int
+ \@@_tl_mapthread_function:NNN \l_@@_args_tl \l_@@_defaults_tl
+ \@@_defaults_def:nn
+ \cs_generate_from_arg_count:NNVo \@@_tmp:w \cs_set:Npn
+ \l_@@_current_arg_int \l_@@_tmpa_tl
+ }
+\cs_generate_variant:Nn \cs_generate_from_arg_count:NNnn { NNVo }
+\cs_new_protected:Npn \@@_defaults_def:nn
+ {
+ \int_incr:N \l_@@_current_arg_int
+ \exp_args:NV \@@_defaults_def:nnn \l_@@_current_arg_int
+ }
+\cs_new_protected:Npn \@@_defaults_def:nnn #1#2#3
+ {
+ \tl_put_right:Nx \l_@@_tmpa_tl
+ {
+ {
+ \exp_not:N \exp_not:n
+ {
+ \tl_if_novalue:nTF {#2}
+ { \exp_not:o {#3} }
+ { \exp_not:n { ## #1 } }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_args_process:}
+% \begin{macro}{\@@_args_process_loop:nn, \@@_args_process_aux:n}
+% Loop through arguments (stored in \cs{l_@@_args_tl}) and the
+% corresponding processors (in \cs{l_@@_process_all_tl})
+% simultaneously, apply all processors for each argument and store the
+% result back into \cs{l_@@_args_tl}. To allow processors to depend
+% on other arguments, for every processor define a temporary auxiliary
+% that receives all arguments \cs{l_@@_args_tl}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_args_process:
+ {
+ \tl_clear:N \l_@@_args_ii_tl
+ \@@_tl_mapthread_function:NNN
+ \l_@@_args_tl
+ \l_@@_process_all_tl
+ \@@_args_process_loop:nn
+ \tl_set_eq:NN \l_@@_args_tl \l_@@_args_ii_tl
+ }
+\cs_new_protected:Npn \@@_args_process_loop:nn #1#2
+ {
+ \tl_set:Nn \ProcessedArgument {#1}
+ \tl_if_novalue:nF {#1}
+ { \tl_map_function:nN {#2} \@@_args_process_aux:n }
+ \tl_put_right:No \l_@@_args_ii_tl
+ { \exp_after:wN { \ProcessedArgument } }
+ }
+\cs_new_protected:Npn \@@_args_process_aux:n #1
+ {
+ \cs_generate_from_arg_count:NNnn \@@_tmp:w \cs_set:Npn
+ { \tl_count:N \l_@@_args_tl } {#1}
+ \exp_args:NNNo \exp_after:wN \@@_tmp:w \l_@@_args_tl
+ { \ProcessedArgument }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_start_expandable:nNNNNn}
+% This is called for all expandable commands. |#6| is the signature,
+% responsible for grabbing arguments. |#5| is used to determine
+% default values (or is |?| if there are none). |#4| is the code to run.
+% |#2|~and~|#3| are functions (named after the command) that grab a single
+% argument in the input stream (|#3|~is~short). The argument specification |#1| is
+% only used by diagnostic functions. Same as for the non-expandable
+% version, this starts with \cs{group_align_safe_begin:}, which
+% expands to nothing, so may be safely used in an expandable context.
+% \begin{macrocode}
+\cs_new:Npn \@@_start_expandable:nNNNNn #1#2#3#4#5#6
+ {
+ \group_align_safe_begin:
+ #6 \@@_end_expandable:NNw #5 #4 \q_@@ #2#3
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_end_expandable:NNw}
+% \begin{macro}[EXP]{\@@_end_expandable_aux:w}
+% \begin{macro}[EXP]{\@@_end_expandable_aux:nNNNN}
+% \begin{macro}[EXP]{\@@_end_expandable_defaults:nnnNNn}
+% \begin{macro}[EXP]{\@@_end_expandable_defaults:nnw}
+% \begin{macro}[EXP]{\@@_end_expandable_defaults:nw}
+% Followed by a function |#1| to determine default values (or |?| if
+% there are no defaults), the code
+% |#2|, arguments that have been grabbed, then \cs{q_@@} and two generic
+% grabbers. The idea to find default values is similar to the
+% non-expandable case but we cannot define an auxiliary function, so
+% at every step in the loop we need to go through all arguments
+% searching for which ones started out as |-NoValue-| and replacing
+% these by the newly computed values. In fact we need to keep track
+% of three versions of all arguments: the original version, the
+% previous version with default values, and the currently built
+% version (first argument of \cs{@@_end_expandable_defaults:nnnNNn}).
+% \begin{macrocode}
+\cs_new:Npn \@@_end_expandable:NNw #1#2
+ { \@@_end_expandable_aux:w #1#2 \prg_do_nothing: }
+\cs_new:Npn \@@_end_expandable_aux:w #1#2#3 \q_@@
+ { \exp_args:No \@@_end_expandable_aux:nNNNN {#3} #1 #2 }
+\cs_new:Npn \@@_end_expandable_aux:nNNNN #1#2#3#4#5
+ {
+ \token_if_eq_charcode:NNT ? #2 { \exp_after:wN \use_iv:nnnn }
+ \@@_end_expandable_defaults:nnnNNn {#1} { } {#1} #2#3
+ { } { } { } { } { } { } { } { } { } { }
+ {
+ \msg_expandable_error:nnf { cmd } { loop-in-defaults }
+ { \exp_args:Nf \tl_trim_spaces:n { \token_to_str:N #4 } }
+ \use_iv:nnnn
+ }
+ \q_stop
+ }
+\cs_new:Npn \@@_end_expandable_defaults:nnnNNn #1#2#3#4#5#6
+ {
+ #6
+ \str_if_eq:nnTF {#1} {#2}
+ { \use_i_delimit_by_q_stop:nw { \group_align_safe_end: #5 #1 } }
+ {
+ \exp_args:No \@@_tl_mapthread_function:nnN
+ { #4 #1 } {#3}
+ \@@_end_expandable_defaults:nnw
+ \@@_end_expandable_defaults:nnnNNn { } {#1} {#3} #4 #5
+ }
+ }
+\cs_new:Npn \@@_end_expandable_defaults:nnw #1#2
+ {
+ \tl_if_novalue:nTF {#2}
+ { \exp_args:No \@@_end_expandable_defaults:nw {#1} }
+ { \@@_end_expandable_defaults:nw {#2} }
+ }
+\cs_new:Npn \@@_end_expandable_defaults:nw
+ #1#2 \@@_end_expandable_defaults:nnnNNn #3
+ { #2 \@@_end_expandable_defaults:nnnNNn { #3 {#1} } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Normalizing the argument specifications}
+%
+% The goal here is to expand aliases and check that the argument
+% specification is valid before the main parsing run. If it is not
+% valid the entire set up is abandoned to avoid any strange internal
+% errors. A function is provided for each argument type that will grab
+% any extra data items and call the loop function after performing the
+% following checks and tasks.
+% \begin{itemize}
+% \item Check that each argument has the correct number of data items
+% associated with it, and that where a single character is required,
+% one has actually been supplied.
+% \item Check that processors and the markers~|+| and~|!| are followed
+% by an argument for which they make sense, and are not redundant.
+% \item Check the absence of forbidden types for expandable commands,
+% namely \texttt{G}/\texttt{v} always, and \texttt{l}/\texttt{u}
+% after optional arguments (\pkg{xparse} may have inserted braces
+% due to a failed search for an optional argument).
+% \item Check that no optional argument is followed by a mandatory
+% argument with the same delimiter, as otherwise the optional
+% argument could never be omitted.
+% \item Keep track in \cs{l_@@_some_long_bool} and
+% \cs{l_@@_some_short_bool} of whether the command has some
+% long/short arguments.
+% \item Keep track in \cs{l_@@_grab_expandably_bool} of whether all
+% arguments are \texttt{m}/\texttt{l}/\texttt{u} type and short
+% arguments appear before long ones, in which case they can be
+% grabbed expandably just as safely as they could be grabbed
+% nonexpandably. Regardless of that, arguments of expandable
+% commands will be grabbed expandably and arguments of environments
+% will not (because the list of arguments built by non-expandable
+% grabbing is used to pass them to the end-environment code).
+% \end{itemize}
+% Further checks happen at the end of the loop:
+% \begin{itemize}
+% \item that there are at most $9$ arguments;
+% \item that an expandable command does not end with an optional
+% argument (this case is detected by using the fact that
+% \cs{l_@@_last_delimiters_tl} is cleared by every mandatory argument
+% and filled by every optional argument).
+% \end{itemize}
+%
+% \begin{macro}{\@@_normalize_arg_spec:n}
+% \begin{macro}{\@@_normalize_arg_spec_loop:n}
+% Loop through the argument specification, calling an auxiliary
+% specific to each argument type. If any argument is unknown stop the
+% definition.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_normalize_arg_spec:n #1
+ {
+ \int_zero:N \l_@@_current_arg_int
+ \tl_clear:N \l_@@_last_delimiters_tl
+ \tl_clear:N \l_@@_arg_spec_tl
+ \bool_set_true:N \l_@@_grab_expandably_bool
+ \bool_set_false:N \l_@@_obey_spaces_bool
+ \bool_set_false:N \l_@@_long_bool
+ \bool_set_false:N \l_@@_some_obey_spaces_bool
+ \bool_set_false:N \l_@@_some_long_bool
+ \bool_set_false:N \l_@@_some_short_bool
+ \@@_normalize_arg_spec_loop:n #1
+ \q_recursion_tail \q_recursion_tail \q_recursion_tail \q_recursion_stop
+ \int_compare:nNnT \l_@@_current_arg_int > 9
+ {
+ \msg_error:nnxx { cmd } { too-many-arguments }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+ \bool_if:NT \l_@@_expandable_bool
+ {
+ \tl_if_empty:NF \l_@@_last_delimiters_tl
+ {
+ \msg_error:nnxx { cmd } { expandable-ending-optional }
+ { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+ }
+ \bool_if:NT \l_@@_expandable_bool
+ { \bool_set_true:N \l_@@_grab_expandably_bool }
+ \bool_if:NT \l_@@_environment_bool
+ { \bool_set_false:N \l_@@_grab_expandably_bool }
+ }
+\cs_new_protected:Npn \@@_normalize_arg_spec_loop:n #1
+ {
+ \quark_if_recursion_tail_stop:n {#1}
+ \int_incr:N \l_@@_current_arg_int
+ \cs_if_exist_use:cF { @@_normalize_type_ \tl_to_str:n {#1} :w }
+ {
+ \bool_lazy_any:nTF
+ {
+ { \str_if_eq_p:nn {#1} { G } }
+ { \str_if_eq_p:nn {#1} { g } }
+ { \str_if_eq_p:nn {#1} { l } }
+ { \str_if_eq_p:nn {#1} { u } }
+ }
+ {
+ \msg_error:nnxx { cmd } { xparse-argument-type }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ }
+ {
+ \msg_error:nnxx { cmd } { unknown-argument-type }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ }
+ \@@_bad_def:wn
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_normalize_type_d:w,
+% \@@_normalize_type_e:w,
+% \@@_normalize_type_o:w,
+% \@@_normalize_type_O:w,
+% \@@_normalize_type_r:w,
+% \@@_normalize_type_s:w,
+% }
+% These argument types are aliases of more general ones, for example
+% with the default argument |-NoValue-|. To easily insert that marker
+% expanded in the definitions we call \cs{@@_tmp:w} with the argument
+% |-NoValue-|. For argument types that need additional data, check
+% that the data is present (not \cs{q_recursion_tail}) before
+% proceeding.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1
+ {
+ \cs_new_protected:Npn \@@_normalize_type_d:w ##1##2
+ {
+ \quark_if_recursion_tail_stop_do:nn {##2} { \@@_bad_arg_spec:wn }
+ \@@_normalize_type_D:w {##1} {##2} {#1}
+ }
+ \cs_new_protected:Npn \@@_normalize_type_e:w ##1
+ {
+ \quark_if_recursion_tail_stop_do:nn {##1} { \@@_bad_arg_spec:wn }
+ \@@_normalize_type_E:w {##1} { }
+ }
+ \cs_new_protected:Npn \@@_normalize_type_o:w
+ { \@@_normalize_type_D:w [ ] {#1} }
+ \cs_new_protected:Npn \@@_normalize_type_O:w
+ { \@@_normalize_type_D:w [ ] }
+ \cs_new_protected:Npn \@@_normalize_type_r:w ##1##2
+ {
+ \quark_if_recursion_tail_stop_do:nn {##2} { \@@_bad_arg_spec:wn }
+ \@@_normalize_type_R:w {##1} {##2} {#1}
+ }
+ \cs_new_protected:Npn \@@_normalize_type_s:w
+ { \@@_normalize_type_t:w * }
+ }
+\exp_args:No \@@_tmp:w { \c_novalue_tl }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_normalize_type_>:w,
+% \@@_normalize_type_+:w,
+% \@@_normalize_type_!:w,
+% }
+% Check that these prefixes have arguments, namely that the next token
+% is not \cs{q_recursion_tail}, and remember to leave it after the
+% looping macro. Processors are forbidden in expandable commands.
+% If all is good, store the prefix in the cleaned up
+% \cs{l_@@_arg_spec_tl}, and decrement the argument number as prefixes
+% do not correspond to arguments.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_normalize_type_>:w } #1#2
+ {
+ \quark_if_recursion_tail_stop_do:nn {#2} { \@@_bad_arg_spec:wn }
+ \bool_if:NT \l_@@_expandable_bool
+ {
+ \msg_error:nnxx { cmd } { processor-in-expandable }
+ { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+ \tl_put_right:Nx \l_@@_arg_spec_tl { > { \tl_trim_spaces:n {#1} } }
+ \int_decr:N \l_@@_current_arg_int
+ \bool_set_false:N \l_@@_grab_expandably_bool
+ \@@_normalize_arg_spec_loop:n {#2}
+ }
+\cs_new_protected:cpn { @@_normalize_type_+:w } #1
+ {
+ \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn }
+ \bool_if:NT \l_@@_long_bool
+ {
+ \msg_error:nnxx { cmd } { two-markers }
+ { \@@_environment_or_command: } { + }
+ \@@_bad_def:wn
+ }
+ \bool_set_true:N \l_@@_long_bool
+ \int_decr:N \l_@@_current_arg_int
+ \@@_normalize_arg_spec_loop:n {#1}
+ }
+\cs_new_protected:cpn { @@_normalize_type_!:w } #1
+ {
+ \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn }
+ \bool_if:NT \l_@@_obey_spaces_bool
+ {
+ \msg_error:nnxx { cmd } { two-markers }
+ { \@@_environment_or_command: } { ! }
+ \@@_bad_def:wn
+ }
+ \bool_set_true:N \l_@@_obey_spaces_bool
+ \bool_set_true:N \l_@@_some_obey_spaces_bool
+ \int_decr:N \l_@@_current_arg_int
+ \@@_normalize_arg_spec_loop:n {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_normalize_type_D:w,
+% \@@_normalize_type_E:w,
+% \@@_normalize_type_t:w,
+% }
+% \begin{macro}{\@@_normalize_E_unique_check:w}
+% Optional argument types. Check that all required data is present
+% (and consists of single characters if applicable) and check for
+% forbidden types for expandable commands. For \texttt{E}-type
+% require that there is at least one embellishment, that each one is a
+% single character, and that there aren't more optional arguments than
+% embellishments; also remember that each embellishment counts as one
+% argument for \cs{l_@@_current_arg_int}. Then in each case
+% store the data in \cs{l_@@_arg_spec_tl}, and
+% for later checks store in \cs{l_@@_last_delimiters_tl} the tokens
+% whose presence determines whether there is an optional argument (for
+% braces store |{}|, seen later as an empty delimiter).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_normalize_type_D:w #1#2#3
+ {
+ \quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn }
+ \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
+ \@@_single_token_check:n {#2}
+ \@@_add_arg_spec:n { D #1 #2 {#3} }
+ \tl_put_right:Nn \l_@@_last_delimiters_tl {#1}
+ \bool_set_false:N \l_@@_grab_expandably_bool
+ \@@_normalize_arg_spec_loop:n
+ }
+\cs_new_protected:Npn \@@_normalize_type_E:w #1#2
+ {
+ \quark_if_recursion_tail_stop_do:nn {#2} { \@@_bad_arg_spec:wn }
+ \tl_if_blank:nT {#1} { \@@_bad_arg_spec:wn }
+ \tl_map_function:nN {#1} \@@_single_token_check:n
+ \tl_map_function:nN {#1} \@@_allowed_token_check:N
+ \@@_normalize_E_unique_check:w #1 \q_nil \q_stop
+ \int_compare:nNnT { \tl_count:n {#2} } > { \tl_count:n {#1} }
+ { \@@_bad_arg_spec:wn }
+ \@@_add_arg_spec:n { E {#1} {#2} }
+ \tl_put_right:Nn \l_@@_last_delimiters_tl {#1}
+ \bool_set_false:N \l_@@_grab_expandably_bool
+ \int_add:Nn \l_@@_current_arg_int { \tl_count:n {#1} - 1 }
+ \@@_normalize_arg_spec_loop:n
+ }
+\cs_new_protected:Npn \@@_normalize_E_unique_check:w #1#2 \q_stop
+ {
+ \quark_if_nil:NF #1
+ {
+ \tl_if_in:nnT {#2} {#1} { \@@_bad_arg_spec:wn }
+ \@@_normalize_E_unique_check:w #2 \q_stop
+ }
+ }
+\cs_new_protected:Npn \@@_normalize_type_t:w #1
+ {
+ \quark_if_recursion_tail_stop_do:Nn #1 { \@@_bad_arg_spec:wn }
+ \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
+ \tl_put_right:Nx \l_@@_arg_spec_tl
+ {
+ \bool_if:NT \l_@@_obey_spaces_bool { ! }
+ t \exp_not:n {#1}
+ }
+ \tl_put_right:Nn \l_@@_last_delimiters_tl {#1}
+ \bool_set_false:N \l_@@_grab_expandably_bool
+ \bool_set_false:N \l_@@_obey_spaces_bool
+ \bool_set_false:N \l_@@_long_bool
+ \@@_normalize_arg_spec_loop:n
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_normalize_type_m:w,
+% \@@_normalize_type_R:w,
+% \@@_normalize_type_v:w
+% }
+% Mandatory arguments. First check the required data is present,
+% consists of single characters where applicable, and that the argument
+% type is allowed for expandable commands if applicable. For the
+% \texttt{m} and \texttt{R} argument types check that they do not
+% follow some optional argument with that delimiter as otherwise the
+% optional argument could not be omitted. Then save data in
+% \cs{l_@@_arg_spec_tl}, count the mandatory argument, and empty the
+% list of last delimiters.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_normalize_type_m:w
+ {
+ \@@_delimiter_check:nnn { } { m } { \iow_char:N \{ }
+ \@@_add_arg_spec_mandatory:n { m }
+ \@@_normalize_arg_spec_loop:n
+ }
+\cs_new_protected:Npn \@@_normalize_type_R:w #1#2#3
+ {
+ \quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn }
+ \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
+ \@@_single_token_check:n {#2}
+ \@@_delimiter_check:nnn {#1} { R/r } { \tl_to_str:n {#1} }
+ \bool_set_false:N \l_@@_grab_expandably_bool
+ \@@_add_arg_spec_mandatory:n { R #1 #2 {#3} }
+ \@@_normalize_arg_spec_loop:n
+ }
+\cs_new_protected:Npn \@@_normalize_type_v:w
+ {
+ \@@_normalize_check_gv:N v
+ \@@_add_arg_spec_mandatory:n { v }
+ \@@_normalize_arg_spec_loop:n
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_normalize_type_b:w}
+% This argument type is not allowed for commands. This is only
+% allowed at the end of the argument specification, hence we check
+% that |#1| is the end.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_normalize_type_b:w #1
+ {
+ \bool_if:NF \l_@@_environment_bool
+ {
+ \msg_error:nnxx { cmd } { invalid-command-arg }
+ { \@@_environment_or_command: } { b }
+ \@@_bad_def:wn
+ }
+ \tl_clear:N \l_@@_last_delimiters_tl
+ \@@_add_arg_spec:n { b }
+ \quark_if_recursion_tail_stop:n {#1}
+ \msg_error:nnxx { cmd } { arg-after-body }
+ { \@@_environment_or_command: }
+ { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_single_token_check:n}
+% Checks that the argument is a single (non-space) token (possibly
+% surrounded by spaces), and aborts the definition otherwise.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_single_token_check:n #1
+ {
+ \tl_trim_spaces_apply:nN {#1} \tl_if_single_token:nF
+ {
+ \msg_error:nnxx { cmd } { not-single-token }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_allowed_token_check:N}
+% Some tokens are now allowed as delimiters for some argument types,
+% notably implicit begin/end-group tokens (|\bgroup|/|\egroup|).
+% The major problem with these tokens is that for |\peek_...| functions,
+% a literal~|{|$_1$. is virtually indistinguishable from a |\bgroup| or
+% other token which was |\let| to a~|{|$_1$, and the same goes
+% for~|}|$_2$. All other tokens can be easily distingushed from their
+% implicit counterparts by grabbing them and looking at the string
+% length (see \cs{@@_token_if_cs:NTF}), but for begin/end group tokens
+% 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.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_allowed_token_check:N #1
+ {
+ \token_if_eq_meaning:NNTF #1 \c_group_begin_token
+ { \use:n }
+ {
+ \token_if_eq_meaning:NNTF #1 \c_group_end_token
+ { \use:n }
+ { \use_none:n }
+ }
+ {
+ \msg_error:nnxxx { cmd } { forbidden-implicit-group-token }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ {
+ \token_if_eq_meaning:NNTF #1 \c_group_begin_token
+ { begin } { end }
+ }
+ \@@_bad_def:wn
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_normalize_check_gv:N, \@@_normalize_check_lu:N}
+% Called for arguments that are always forbidden, or forbidden after
+% an optional argument, for expandable commands.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_normalize_check_gv:N #1
+ {
+ \bool_if:NT \l_@@_expandable_bool
+ {
+ \msg_error:nnxx { cmd } { invalid-expandable-argument-type }
+ { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+ \bool_set_false:N \l_@@_grab_expandably_bool
+ }
+\cs_new_protected:Npn \@@_normalize_check_lu:N #1
+ {
+ \bool_if:NT \l_@@_expandable_bool
+ {
+ \tl_if_empty:NF \l_@@_last_delimiters_tl
+ {
+ \msg_error:nnxx { cmd } { invalid-after-optional-expandably }
+ { \iow_char:N \\ \l_@@_function_tl } { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_delimiter_check:nnn}
+% Called for \texttt{m} and \texttt{R} arguments. Checks that the
+% leading token does not coincide with the token denoting the presence
+% of a previous optional argument. Instead of dealing with braces for
+% the \texttt{m}-type we use an empty delimiter to denote that case.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_delimiter_check:nnn #1#2#3
+ {
+ \tl_map_inline:Nn \l_@@_last_delimiters_tl
+ {
+ \tl_if_eq:nnT {##1} {#1}
+ {
+ \msg_warning:nnxx { cmd } { optional-mandatory }
+ {#2} {#3}
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_bad_arg_spec:wn, \@@_bad_def:wn}
+% If the argument specification is wrong, this provides an escape from
+% the entire definition process.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_bad_arg_spec:wn #1 \@@_break_point:n #2
+ {
+ \msg_error:nnxx { cmd } { bad-arg-spec }
+ { \@@_environment_or_command: } { \tl_to_str:n {#2} }
+ }
+\cs_new_protected:Npn \@@_bad_def:wn #1 \@@_break_point:n #2 { }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_arg_spec:n, \@@_add_arg_spec_mandatory:n}
+% 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.
+% Before that, test for a short argument following some long
+% arguments: this is forbidden for expandable commands and prevents
+% grabbing arguments expandably.
+%
+% For mandatory arguments do some more work, in particular complain if
+% they were preceeded by~|!|.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_arg_spec:n #1
+ {
+ \bool_lazy_and:nnT
+ { ! \l_@@_long_bool }
+ { \l_@@_some_long_bool }
+ {
+ \bool_if:NT \l_@@_expandable_bool
+ {
+ \msg_error:nnx { cmd } { inconsistent-long }
+ { \iow_char:N \\ \l_@@_function_tl }
+ \@@_bad_def:wn
+ }
+ \bool_set_false:N \l_@@_grab_expandably_bool
+ }
+ \bool_if:NTF \l_@@_long_bool
+ { \bool_set_true:N \l_@@_some_long_bool }
+ { \bool_set_true:N \l_@@_some_short_bool }
+ \tl_put_right:Nx \l_@@_arg_spec_tl
+ {
+ \bool_if:NT \l_@@_long_bool { + }
+ \bool_if:NT \l_@@_obey_spaces_bool { ! }
+ \exp_not:n {#1}
+ }
+ \bool_set_false:N \l_@@_long_bool
+ \bool_set_false:N \l_@@_obey_spaces_bool
+ }
+\cs_new_protected:Npn \@@_add_arg_spec_mandatory:n #1
+ {
+ \bool_if:NT \l_@@_some_obey_spaces_bool
+ {
+ \msg_error:nnxx { cmd } { non-trailing-obey-spaces }
+ { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+ \@@_bad_def:wn
+ }
+ \tl_clear:N \l_@@_last_delimiters_tl
+ \@@_add_arg_spec:n {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Preparing the signature: general mechanism}
+%
+% \begin{macro}{\@@_prepare_signature:n}
+% \begin{macro}{\@@_prepare_signature:N}
+% \begin{macro}{\@@_prepare_signature_bypass:N}
+% Actually creating the signature uses the same loop approach as
+% normalizing the signature. There are first a number of variables which need
+% to be set to track what is going on. Many of these variables are unused
+% when defining expandable commands.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_prepare_signature:n #1
+ {
+ \int_zero:N \l_@@_current_arg_int
+ \bool_set_false:N \l_@@_long_bool
+ \bool_set_false:N \l_@@_obey_spaces_bool
+ \int_zero:N \l_@@_m_args_int
+ \bool_set_false:N \l_@@_defaults_bool
+ \tl_clear:N \l_@@_defaults_tl
+ \tl_clear:N \l_@@_process_all_tl
+ \tl_clear:N \l_@@_process_one_tl
+ \bool_set_false:N \l_@@_process_some_bool
+ \tl_clear:N \l_@@_signature_tl
+ \@@_prepare_signature:N #1 \q_recursion_tail \q_recursion_stop
+ \bool_if:NF \l_@@_expandable_bool { \@@_flush_m_args: }
+ }
+% \end{macrocode}
+% The main looping function does not take an argument, but carries out the
+% reset on the processor boolean. This is split off from the rest of the
+% process so that when actually setting up processors the flag-reset can
+% be bypassed.
+%
+% For each known argument type there is an appropriate function to actually
+% do the addition to the signature. These are separate for expandable and
+% standard functions, as the approaches are different.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_prepare_signature:N
+ {
+ \bool_set_false:N \l_@@_prefixed_bool
+ \@@_prepare_signature_bypass:N
+ }
+\cs_new_protected:Npn \@@_prepare_signature_bypass:N #1
+ {
+ \quark_if_recursion_tail_stop:N #1
+ \use:c
+ {
+ @@_add
+ \bool_if:NT \l_@@_grab_expandably_bool { _expandable }
+ _type_ \token_to_str:N #1 :w
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Setting up a standard signature}
+%
+% Each argument-adding function appends to the signature a grabber (and
+% for some types, the delimiters or default value), except the one for
+% \texttt{m} arguments. These are collected and added to the signature
+% all at once by \cs{@@_flush_m_args:}, called for every other argument
+% type. All of the functions then call the loop function
+% \cs{@@_prepare_signature:N}. Default values of arguments are
+% collected by \cs{@@_add_default:n} rather than being stored with the
+% argument; this function and \cs{@@_add_default:} are also responsible
+% for keeping track of \cs{l_@@_current_arg_int}.
+%
+% \begin{macro}{\@@_add_type_+:w}
+% Making the next argument long means setting the flag. The \texttt{m}
+% arguments are recorded here as
+% this has to be done for every case where there is then a long argument.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_add_type_+:w }
+ {
+ \@@_flush_m_args:
+ \bool_set_true:N \l_@@_long_bool
+ \bool_set_true:N \l_@@_prefixed_bool
+ \@@_prepare_signature_bypass:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_!:w}
+% Much the same for controlling trailing optional arguments.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_add_type_!:w }
+ {
+ \@@_flush_m_args:
+ \bool_set_true:N \l_@@_obey_spaces_bool
+ \bool_set_true:N \l_@@_prefixed_bool
+ \@@_prepare_signature_bypass:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_>:w}
+% When a processor is found, the processor code is stored. It will be
+% used by \cs{@@_args_process:} once arguments are all found. Here too
+% the loop calls \cs{@@_prepare_signature_bypass:N} rather than
+% \cs{@@_prepare_signature:N} so that the flag is not reset.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_add_type_>:w } #1
+ {
+ \@@_flush_m_args:
+ \bool_set_true:N \l_@@_prefixed_bool
+ \bool_set_true:N \l_@@_process_some_bool
+ \tl_put_left:Nn \l_@@_process_one_tl { {#1} }
+ \@@_prepare_signature_bypass:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_b:w}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_b:w
+ {
+ \@@_flush_m_args:
+ \@@_add_default:
+ \@@_add_grabber:N b
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_D:w}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_D:w #1#2#3
+ {
+ \@@_flush_m_args:
+ \@@_add_default:n {#3}
+ \@@_add_grabber:N D
+ \tl_put_right:Nn \l_@@_signature_tl { #1 #2 }
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_E:w}
+% The \texttt{E}-type argument needs a special handling of default
+% values.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_E:w #1#2
+ {
+ \@@_flush_m_args:
+ \@@_add_default_E:nn {#1} {#2}
+ \@@_add_grabber:N E
+ \tl_put_right:Nn \l_@@_signature_tl { {#1} }
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_m:w}
+% The \texttt{m} type is special as short arguments which are not
+% post-processed are simply counted at this stage. Thus there is a check
+% to see if either of these cases apply. If so, a one-argument grabber
+% is added to the signature. On the other hand, if a standard short
+% argument is required it is simply counted at this stage, to be
+% added later using \cs{@@_flush_m_args:}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_m:w
+ {
+ \@@_add_default:
+ \bool_if:NTF \l_@@_prefixed_bool
+ { \@@_add_grabber:N m }
+ { \int_incr:N \l_@@_m_args_int }
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_R:w}
+% The \texttt{R}-type argument is very similar to the \texttt{D}-type.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_R:w #1#2#3
+ {
+ \@@_flush_m_args:
+ \@@_add_default:n {#3}
+ \@@_add_grabber:N R
+ \tl_put_right:Nn \l_@@_signature_tl { #1 #2 }
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_t:w}
+% Setting up a \texttt{t} argument means collecting one token for the test,
+% and adding it along with the grabber to the signature.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_t:w #1
+ {
+ \@@_flush_m_args:
+ \@@_add_default:
+ \@@_add_grabber:N t
+ \tl_put_right:Nn \l_@@_signature_tl {#1}
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_type_v:w}
+% At this stage, the \texttt{v} argument is identical to \texttt{l}
+% except that since the grabber may fail to read a verbatim argument
+% we need a default value.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_type_v:w
+ {
+ \@@_flush_m_args:
+ \exp_args:No \@@_add_default:n \c_novalue_tl
+ \@@_add_grabber:N v
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_flush_m_args:}
+% As \texttt{m} arguments are simply counted, there is a need to add
+% them to the token register in a block. As this function can only
+% be called if something other than \texttt{m} turns up, the flag can
+% be switched here.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_flush_m_args:
+ {
+ \int_compare:nNnT \l_@@_m_args_int > 0
+ {
+ \tl_put_right:Nx \l_@@_signature_tl
+ { \exp_not:c { @@_grab_m_ \int_use:N \l_@@_m_args_int :w } }
+ \tl_put_right:Nx \l_@@_process_all_tl
+ { \prg_replicate:nn { \l_@@_m_args_int } { { } } }
+ }
+ \int_zero:N \l_@@_m_args_int
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_grabber:N}
+% To keep the various checks needed in one place, adding the grabber
+% to the signature is done here. The only questions are whether the
+% grabber should be long or not, and whether to obey spaces. The
+% \cs{l_@@_obey_spaces_bool} boolean can only be \texttt{true} for
+% trailing optional arguments. In that case spaces will not be
+% ignored when looking for that optional argument.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_grabber:N #1
+ {
+ \tl_put_right:Nx \l_@@_signature_tl
+ {
+ \exp_not:c
+ {
+ @@_grab_ #1
+ \bool_if:NT \l_@@_long_bool { _long }
+ \bool_if:NT \l_@@_obey_spaces_bool { _obey_spaces }
+ :w
+ }
+ }
+ \bool_set_false:N \l_@@_long_bool
+ \bool_set_false:N \l_@@_obey_spaces_bool
+ \tl_put_right:Nx \l_@@_process_all_tl
+ { { \exp_not:o \l_@@_process_one_tl } }
+ \tl_clear:N \l_@@_process_one_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_default:n, \@@_add_default:, \@@_add_default_E:nn}
+% Store the default value of an argument, or rather code that gives
+% that default value (it may involve other arguments). This is
+% \cs{c_novalue_tl} for arguments with no actual default or with
+% default |-NoValue-|; and (in a brace group) \cs{prg_do_nothing:}
+% followed by a default value for others. For \texttt{E}-type
+% arguments, pad the defaults |#2| with some \cs{c_novalue_tl}
+% until there are as many as embellishments~|#1|. These functions are
+% also used when defining expandable commands.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_default:n #1
+ {
+ \tl_if_novalue:nTF {#1}
+ { \@@_add_default: }
+ {
+ \int_incr:N \l_@@_current_arg_int
+ \bool_set_true:N \l_@@_defaults_bool
+ \tl_put_right:Nn \l_@@_defaults_tl { { \prg_do_nothing: #1 } }
+ }
+ }
+\cs_new_protected:Npn \@@_add_default:
+ {
+ \int_incr:N \l_@@_current_arg_int
+ \tl_put_right:Nn \l_@@_defaults_tl { \c_novalue_tl }
+ }
+\cs_new_protected:Npn \@@_add_default_E:nn #1#2
+ {
+ \tl_map_function:nN {#2} \@@_add_default:n
+ \prg_replicate:nn
+ { \tl_count:n {#1} - \tl_count:n {#2} }
+ { \@@_add_default: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Setting up expandable types}
+%
+% The approach here is not dissimilar to that for standard types, but fewer types
+% are supported. There is
+% also a need to define the per-function auxiliaries: this is done here, while
+% the general grabbers are dealt with later.
+%
+% \begin{macro}{\@@_add_expandable_type_+:w}
+% We have already checked that short arguments are before long
+% arguments, so \cs{l_@@_long_bool} only changes from \texttt{false}
+% to \texttt{true} once (and there is no need to reset it after each
+% argument). Also knock back the argument count because |+| is not an
+% argument. Continue the loop.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_add_expandable_type_+:w }
+ {
+ \bool_set_true:N \l_@@_long_bool
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_D:w}
+% \begin{macro}{\@@_add_expandable_type_D_aux:NNNn}
+% \begin{macro}{\@@_add_expandable_type_D_aux:NNN}
+% \begin{macro}{\@@_add_expandable_type_D_aux:NN}
+% The set up for \texttt{D}-type arguments involves constructing a
+% rather complex auxiliary which is used
+% repeatedly when grabbing. There is an auxiliary here so that the
+% \texttt{R}-type can share code readily: |#1| is |D| or~|R|.
+% The |_aux:NN| auxiliary is needed if the two delimiting tokens are
+% identical: in contrast to the non-expandable route, the grabber here
+% has to act differently for this case.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_type_D:w
+ { \@@_add_expandable_type_D_aux:NNNn D }
+\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NNNn #1#2#3#4
+ {
+ \@@_add_default:n {#4}
+ \tl_if_eq:nnTF {#2} {#3}
+ { \@@_add_expandable_type_D_aux:NN #1 #2 }
+ { \@@_add_expandable_type_D_aux:NNN #1 #2 #3 }
+ \@@_prepare_signature:N
+ }
+\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NNN #1#2#3
+ {
+ \bool_if:NTF \l_@@_long_bool
+ { \cs_set:cpx }
+ { \cs_set_nopar:cpx }
+ { \l_@@_expandable_aux_name_tl } ##1 ##2 #2 ##3 \q_@@ ##4 #3
+ { ##1 {##2} {##3} {##4} }
+ \@@_add_expandable_grabber:nn {#1}
+ {
+ \exp_not:c { \l_@@_expandable_aux_name_tl }
+ \exp_not:n { #2 #3 }
+ }
+ }
+\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NN #1#2
+ {
+ \bool_if:NTF \l_@@_long_bool
+ { \cs_set:cpx }
+ { \cs_set_nopar:cpx }
+ { \l_@@_expandable_aux_name_tl } ##1 #2 ##2 #2
+ { ##1 {##2} }
+ \@@_add_expandable_grabber:nn { #1_alt }
+ {
+ \exp_not:c { \l_@@_expandable_aux_name_tl }
+ \exp_not:n {#2}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_E:w}
+% \begin{macro}{\@@_add_expandable_type_E_aux:n}
+% For each embellishment, use \cs{@@_get_grabber:NN} to obtain an
+% auxiliary delimited by that token and store a pair constituted of
+% the auxiliary and the token in \cs{l_@@_tmpb_tl}, before appending
+% the whole set of these pairs to the signature, and an equal number
+% of |-NoValue-| markers (regardless of the default values of
+% arguments). Set the current argument appropriately.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_type_E:w #1#2
+ {
+ \@@_add_default_E:nn {#1} {#2}
+ \tl_clear:N \l_@@_tmpb_tl
+ \tl_map_function:nN {#1} \@@_add_expandable_type_E_aux:n
+ \@@_add_expandable_grabber:nn
+ { E \bool_if:NT \l_@@_long_bool { _long } }
+ {
+ { \exp_not:o \l_@@_tmpb_tl }
+ {
+ \prg_replicate:nn { \tl_count:n {#1} }
+ { { \c_novalue_tl } }
+ }
+ }
+ \@@_prepare_signature:N
+ }
+\cs_new_protected:Npn \@@_add_expandable_type_E_aux:n #1
+ {
+ \@@_get_grabber:NN #1 \l_@@_tmpa_tl
+ \tl_put_right:Nx \l_@@_tmpb_tl
+ { \exp_not:o \l_@@_tmpa_tl \exp_not:N #1 }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_m:w}
+% Unlike the standard case, when working expandably each argument is always
+% grabbed separately.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_type_m:w
+ {
+ \@@_add_default:
+ \@@_add_expandable_grabber:nn
+ { m \bool_if:NT \l_@@_long_bool { _long } } { }
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_R:w}
+% The \texttt{R}-type is very similar to the \texttt{D}-type
+% argument, and so the same internals are used.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_type_R:w
+ { \@@_add_expandable_type_D_aux:NNNn R }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_type_t:w}
+% An auxiliary delimited by |#1| is built now. It will be used to
+% test for the presence of that token.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_type_t:w #1
+ {
+ \@@_add_default:
+ \@@_get_grabber:NN #1 \l_@@_tmpa_tl
+ \@@_add_expandable_grabber:nn { t }
+ {
+ \exp_not:o \l_@@_tmpa_tl
+ \exp_not:N #1
+ }
+ \@@_prepare_signature:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_expandable_grabber:nn}
+% This is called for all arguments to place the right grabber in the
+% signature.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_expandable_grabber:nn #1#2
+ {
+ \tl_put_right:Nx \l_@@_signature_tl
+ { \exp_not:c { @@_expandable_grab_ #1 :w } #2 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_get_grabber:NN}
+% \begin{macro}{\@@_get_grabber_auxi:NN}
+% \begin{macro}{\@@_get_grabber_auxii:NN}
+% Given a token |#1|, defines an expandable function delimited by that
+% token and stores it in the token list~|#2|. The function is named
+% after the token, unless that function name is already taken by some
+% other grabber (this can happen in the rare case where delimiters
+% with different category codes are used in the same document): in
+% that case use a global counter to get a unique name. Since the
+% grabbers are not named after \pkg{xparse} commands they should not
+% be used to get material from the input stream.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_get_grabber:NN #1#2
+ {
+ \cs_set:Npn \@@_tmp:w ##1 #1 {##1}
+ \exp_args:Nc \@@_get_grabber_auxi:NN
+ { @@_grabber_ \token_to_str:N #1 :w } #2
+ }
+\cs_new_protected:Npn \@@_get_grabber_auxi:NN #1#2
+ {
+ \cs_if_eq:NNTF \@@_tmp:w #1
+ { \tl_set:Nn #2 {#1} }
+ {
+ \cs_if_exist:NTF #1
+ {
+ \int_gincr:N \g_@@_grabber_int
+ \exp_args:Nc \@@_get_grabber_auxi:NN
+ {
+ @@_grabber_
+ - \int_use:N \g_@@_grabber_int :w
+ }
+ #2
+ }
+ { \@@_get_grabber_auxii:NN #1 #2 }
+ }
+ }
+\cs_new_protected:Npn \@@_get_grabber_auxii:NN #1#2
+ {
+ \cs_set_eq:NN #1 \@@_tmp:w
+ \tl_set:Nn #2 {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Grabbing arguments}
+%
+% All of the grabbers follow the same basic pattern. The initial
+% function stores in \cs{l_@@_signature_tl} the code to grab further
+% arguments, defines (the function in) \cs{l_@@_fn_tl} that will grab
+% the argument, and calls it.
+%
+% Defining \cs{l_@@_fn_tl} means determining whether to use
+% \cs{cs_set:Npn} or \cs{cs_set_nopar:Npn}, and for optional arguments
+% whether to skip spaces. Once the argument is found, \cs{l_@@_fn_tl}
+% calls \cs{@@_add_arg:n}, responsible for calling processors and
+% grabbing further arguments.
+%
+% \begin{macro}
+% {
+% \@@_grab_b:w,
+% \@@_grab_b_long:w,
+% \@@_grab_b_obey_spaces:w,
+% \@@_grab_b_long_obey_spaces:w,
+% \@@_grab_b_aux:NNw,
+% \@@_grab_b_end:Nw
+% }
+% This uses the well-tested code of \texttt{D}-type arguments,
+% skipping the peeking step because the \texttt{b}-type argument is
+% always present, and adding a cleanup stage at the end by hijacking
+% the signature. The clean-up consists of properly
+% dealing with \cs{l_@@_args_tl} and also putting back the \cs{end}
+% that served as an end-delimiter: this \cs{end} receives the
+% environment name as its argument and is run normally. The
+% \texttt{D}-type code stores the argument found (body of the
+% environment) as a brace group in \cs{l_@@_args_tl} and depending on
+% the presence of a prefix~|!| we trim spaces or not before adding
+% this braced argument into the saved \cs{l_@@_args_tl}.
+% The strange \verb*|\begin | control sequence is there for display
+% purposes only: it has to look like |\begin| in the terminal but
+% not to delimited arguments.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_b:w
+ { \@@_grab_b_aux:NNw \cs_set_protected_nopar:Npn \tl_trim_spaces:n }
+\cs_new_protected:Npn \@@_grab_b_long:w
+ { \@@_grab_b_aux:NNw \cs_set_protected:Npn \tl_trim_spaces:n }
+\cs_new_protected:Npn \@@_grab_b_obey_spaces:w
+ { \@@_grab_b_aux:NNw \cs_set_protected_nopar:Npn \exp_not:n }
+\cs_new_protected:Npn \@@_grab_b_long_obey_spaces:w
+ { \@@_grab_b_aux:NNw \cs_set_protected:Npn \exp_not:n }
+\cs_new_protected:Npn \@@_grab_b_aux:NNw #1#2#3 \@@_run_code:
+ {
+ \@@_grab_D_aux:NNnN \begin \end {#3} #1
+ \tl_put_left:Nn \l_@@_signature_tl { \@@_grab_b_end:Nw #2 }
+ \tl_set_eq:NN \l_@@_saved_args_tl \l_@@_args_tl
+ \tl_clear:N \l_@@_args_tl
+ \exp_args:Nc \l_@@_fn_tl { begin ~ }
+ }
+\cs_new_protected:Npn \@@_grab_b_end:Nw #1#2 \@@_run_code:
+ {
+ \tl_set:Nx \l_@@_args_tl
+ {
+ \exp_not:V \l_@@_saved_args_tl
+ { \exp_after:wN #1 \l_@@_args_tl }
+ }
+ #2
+ \@@_run_code:
+ \end
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_D:w}
+% \begin{macro}{\@@_grab_D_long:w}
+% \begin{macro}{\@@_grab_D_obey_spaces:w}
+% \begin{macro}{\@@_grab_D_long_obey_spaces:w}
+% The generic delimited argument grabber. The auxiliary function does
+% a peek test before calling \cs{@@_grab_D_call:Nw}, so that the
+% optional nature of the argument works as expected.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_D:w #1#2#3 \@@_run_code:
+ {
+ \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected_nopar:Npn
+ \@@_peek_nonspace_remove:NTF
+ }
+\cs_new_protected:Npn \@@_grab_D_long:w #1#2#3 \@@_run_code:
+ {
+ \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected:Npn
+ \@@_peek_nonspace_remove:NTF
+ }
+\cs_new_protected:Npn \@@_grab_D_obey_spaces:w #1#2#3 \@@_run_code:
+ {
+ \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected_nopar:Npn
+ \@@_peek_meaning_remove:NTF
+ }
+\cs_new_protected:Npn \@@_grab_D_long_obey_spaces:w #1#2#3 \@@_run_code:
+ {
+ \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected:Npn
+ \@@_peek_meaning_remove:NTF
+ }
+% \end{macrocode}
+% \begin{macro}{\@@_grab_D_aux:NNnNN}
+% \begin{macro}{\@@_grab_D_aux:NNnN}
+% This is a bit complicated. The idea is that, in order to check for
+% nested optional argument tokens (\texttt{[[...]]} and so on) the
+% argument needs to be grabbed without removing any braces at all. If
+% this is not done, then cases like |[{[}]| fail. So after testing for
+% an optional argument, it is collected piece-wise. Inserting a quark
+% prevents loss of braces, and there is then a test to see if there are
+% nested delimiters to handle.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_D_aux:NNnNN #1#2#3#4#5
+ {
+ \@@_grab_D_aux:NNnN #1#2 {#3} #4
+ #5 #1
+ { \@@_grab_D_call:Nw #1 }
+ { \@@_add_arg:o \c_novalue_tl }
+ }
+% \end{macrocode}
+% Inside the \enquote{standard} grabber, there is a test to see if the
+% grabbed argument is entirely enclosed by braces. There are a couple of
+% extra factors to allow for: the argument might be entirely empty, and
+% spaces at the start and end of the input must be retained around a brace
+% group. Also notice that a \emph{blank} argument might still contain
+% spaces.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_D_aux:NNnN #1#2#3#4
+ {
+ \tl_set:Nn \l_@@_signature_tl {#3}
+ \exp_after:wN #4 \l_@@_fn_tl ##1 #2
+ {
+ \tl_if_in:nnTF {##1} {#1}
+ { \@@_grab_D_nested:NNnN #1 #2 {##1} #4 }
+ {
+ \tl_if_blank:oTF { \use_none:n ##1 }
+ { \@@_add_arg:o { \use_none:n ##1 } }
+ {
+ \str_if_eq:eeTF
+ { \exp_not:o { \use_none:n ##1 } }
+ { { \exp_not:o { \use_ii:nnn ##1 \q_nil } } }
+ { \@@_add_arg:o { \use_ii:nn ##1 } }
+ { \@@_add_arg:o { \use_none:n ##1 } }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\@@_grab_D_nested:NNnN}
+% \begin{macro}{\@@_grab_D_nested:w}
+% \begin{macro}{\l_@@_nesting_a_tl}
+% \begin{macro}{\l_@@_nesting_b_tl}
+% \begin{macro}{\q_@@}
+% Catching nested optional arguments means more work. The aim here is
+% to collect up each pair of optional tokens without \TeX{} helping out,
+% and without counting anything. The code above will already have
+% removed the leading opening token and a closing token, but the
+% wrong one. The aim is then to work through the material grabbed
+% so far and divide it up on each opening token, grabbing a closing
+% token to match (thus working in pairs). Once there are no opening
+% tokens, then there is a second check to see if there are any
+% opening tokens in the second part of the argument (for things
+% like |[][]|). Once everything has been found, the entire collected
+% material is added to the output as a single argument. The only tricky part
+% here is ensuring that any grabbing function that might run away is named
+% after the function currently being parsed and not after \pkg{xparse}. That
+% leads to some rather complex nesting! There is also a need to prevent the
+% loss of any braces, hence the insertion and removal of quarks along the
+% way.
+% \begin{macrocode}
+\tl_new:N \l_@@_nesting_a_tl
+\tl_new:N \l_@@_nesting_b_tl
+\quark_new:N \q_@@
+\cs_new_protected:Npn \@@_grab_D_nested:NNnN #1#2#3#4
+ {
+ \tl_clear:N \l_@@_nesting_a_tl
+ \tl_clear:N \l_@@_nesting_b_tl
+ \exp_after:wN #4 \l_@@_fn_tl ##1 #1 ##2 \q_@@ ##3 #2
+ {
+ \tl_put_right:No \l_@@_nesting_a_tl { \use_none:n ##1 #1 }
+ \tl_put_right:No \l_@@_nesting_b_tl { \use_i:nn #2 ##3 }
+ \tl_if_in:nnTF {##2} {#1}
+ {
+ \l_@@_fn_tl
+ \q_nil ##2 \q_@@ \ERROR
+ }
+ {
+ \tl_put_right:Nx \l_@@_nesting_a_tl
+ { \@@_grab_D_nested:w \q_nil ##2 \q_stop }
+ \tl_if_in:NnTF \l_@@_nesting_b_tl {#1}
+ {
+ \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_nesting_b_tl
+ \tl_clear:N \l_@@_nesting_b_tl
+ \exp_after:wN \l_@@_fn_tl \exp_after:wN
+ \q_nil \l_@@_tmpa_tl \q_nil \q_@@ \ERROR
+ }
+ {
+ \tl_put_right:No \l_@@_nesting_a_tl
+ \l_@@_nesting_b_tl
+ \@@_add_arg:V \l_@@_nesting_a_tl
+ }
+ }
+ }
+ \l_@@_fn_tl #3 \q_nil \q_@@ \ERROR
+ }
+\cs_new:Npn \@@_grab_D_nested:w #1 \q_nil \q_stop
+ { \exp_not:o { \use_none:n #1 } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\@@_grab_D_call:Nw}
+% For \texttt{D} and \texttt{R}-type arguments, to avoid losing any
+% braces, a token needs to be inserted before the argument to be grabbed.
+% If the argument runs away because the closing token is missing then this
+% inserted token shows up in the terminal. Ideally, |#1| would therefore be
+% used directly, but that is no good as it will mess up the rest of the
+% grabber. Instead, a copy of |#1| with an altered category code is used,
+% as this will look right in the terminal but will not mess up the grabber.
+% The only issue then is that the category code of |#1| is unknown. So there
+% is a quick test to ensure that the inserted token can never be matched by
+% the grabber. (This assumes that the open and close delimiters are not the
+% same character with different category codes, but that really should not
+% happen in any sensible document-level syntax.)
+% An exception is when |#1| is a control sequence token, in which case the
+% character-token treatment is no good because if hit with \cs{token_to_str:N}
+% it would add sputios tokens to the argument. In this case a different
+% branch is taken. The token inserted is then the same \meta{csname} as |#1|,
+% but with a space appended, so that the grabber don't see it as another
+% of the same delimiter.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_grab_D_call:Nw #1
+ {
+ \token_if_eq_catcode:NNTF + #1
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \l_@@_fn_tl \char_generate:nn { `#1 } { 11 }
+ }
+ {
+ \@@_token_if_cs:NTF #1
+ {
+ \exp_after:wN \l_@@_fn_tl
+ \cs:w \cs_to_str:N #1 ~ \cs_end:
+ }
+ {
+ \exp_after:wN \l_@@_fn_tl
+ \token_to_str:N #1
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_grab_E:w, \@@_grab_E_long:w,
+% \@@_grab_E_obey_spaces:w, \@@_grab_E_long_obey_spaces:w
+% }
+% \begin{macro}{\@@_grab_E:nnNN}
+% \begin{macro}{\@@_grab_E_loop:NnN}
+% \begin{macro}{\@@_grab_E_finalise:}
+% Everything here needs to point to a loop.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_E:w #1#2 \@@_run_code:
+ {
+ \@@_grab_E:nnNN {#1} {#2}
+ \cs_set_protected_nopar:Npn
+ \@@_peek_nonspace_remove:NTF
+ }
+\cs_new_protected:Npn \@@_grab_E_long:w #1#2 \@@_run_code:
+ {
+ \@@_grab_E:nnNN {#1} {#2}
+ \cs_set_protected:Npn
+ \@@_peek_nonspace_remove:NTF
+ }
+\cs_new_protected:Npn \@@_grab_E_obey_spaces:w #1#2 \@@_run_code:
+ {
+ \@@_grab_E:nnNN {#1} {#2}
+ \cs_set_protected_nopar:Npn
+ \@@_peek_meaning_remove:NTF
+ }
+\cs_new_protected:Npn \@@_grab_E_long_obey_spaces:w #1#2 \@@_run_code:
+ {
+ \@@_grab_E:nnNN {#1} {#2}
+ \cs_set_protected:Npn
+ \@@_peek_meaning_remove:NTF
+ }
+% \end{macrocode}
+% A loop is needed here to allow a random ordering of keys. These are
+% searched for one at a time, with any not found needing to be tracked:
+% they can appear later. The grabbed values are held in a property list
+% which is then turned into an ordered list to be passed back to the user.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_E:nnNN #1#2#3#4
+ {
+ \exp_after:wN #3 \l_@@_fn_tl ##1##2##3
+ {
+ \prop_put:Nnn \l_@@_tmp_prop {##1} {##3}
+ \@@_grab_E_loop:NnN #4 { } ##2 \q_recursion_stop
+ }
+ \prop_clear:N \l_@@_tmp_prop
+ \tl_set:Nn \l_@@_signature_tl {#2}
+ \cs_set_protected:Npn \@@_grab_E_finalise:
+ {
+ \tl_map_inline:nn {#1}
+ {
+ \prop_get:NnNF \l_@@_tmp_prop {####1} \l_@@_tmpb_tl
+ { \tl_set_eq:NN \l_@@_tmpb_tl \c_novalue_tl }
+ \tl_put_right:Nx \l_@@_args_tl
+ { { \exp_not:V \l_@@_tmpb_tl } }
+ }
+ \l_@@_signature_tl \@@_run_code:
+ }
+ \@@_grab_E_loop:NnN #4 { } #1 \q_recursion_tail \q_recursion_stop
+ }
+\cs_new_protected:Npn \@@_grab_E_loop:NnN #1#2#3#4 \q_recursion_stop
+ {
+ \cs_if_eq:NNTF #3 \q_recursion_tail
+ { \@@_grab_E_finalise: }
+ {
+ #1 #3
+ { \l_@@_fn_tl #3 {#2#4} }
+ { \@@_grab_E_loop:NnN #1 {#2#3} #4 \q_recursion_stop }
+ }
+ }
+\cs_new_protected:Npn \@@_grab_E_finalise: { }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_grab_m:w}
+% \begin{macro}{\@@_grab_m_long:w}
+% Collecting a single mandatory argument is quite easy.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_m:w #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl ##1
+ { \@@_add_arg:n {##1} }
+ \l_@@_fn_tl
+ }
+\cs_new_protected:Npn \@@_grab_m_long:w #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_protected:Npn \l_@@_fn_tl ##1
+ { \@@_add_arg:n {##1} }
+ \l_@@_fn_tl
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_m_1:w}
+% \begin{macro}{\@@_grab_m_2:w}
+% \begin{macro}{\@@_grab_m_3:w}
+% \begin{macro}{\@@_grab_m_4:w}
+% \begin{macro}{\@@_grab_m_5:w}
+% \begin{macro}{\@@_grab_m_6:w}
+% \begin{macro}{\@@_grab_m_7:w}
+% \begin{macro}{\@@_grab_m_8:w}
+% \begin{macro}{\@@_grab_m_9:w}
+% \begin{macro}{\@@_grab_m_aux:Nnnnnnnnn}
+% Grabbing 1--8 mandatory arguments is done by giving 8--1 known
+% arguments to a 9-argument function that stores them in
+% \cs{l_@@_args_tl}. For simplicity, grabbing 9 mandatory arguments
+% is done by grabbing 5 then 4 arguments.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_grab_m_aux:Nnnnnnnnn #1#2#3#4#5#6#7#8#9
+ {
+ \tl_put_right:No \l_@@_args_tl
+ { #1 {#2} {#3} {#4} {#5} {#6} {#7} {#8} {#9} }
+ \l_@@_signature_tl \@@_run_code:
+ }
+\cs_new_protected:cpn { @@_grab_m_1:w } #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn
+ \l_@@_fn_tl \use_none:nnnnnnn { } { } { } { } { } { } { }
+ }
+\cs_new_protected:cpn { @@_grab_m_2:w } #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn
+ \l_@@_fn_tl \use_none:nnnnnn { } { } { } { } { } { }
+ }
+\cs_new_protected:cpn { @@_grab_m_3:w } #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn
+ \l_@@_fn_tl \use_none:nnnnn { } { } { } { } { }
+ }
+\cs_new_protected:cpn { @@_grab_m_4:w } #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn
+ \l_@@_fn_tl \use_none:nnnn { } { } { } { }
+ }
+\cs_new_protected:cpn { @@_grab_m_5:w } #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn
+ \l_@@_fn_tl \use_none:nnn { } { } { }
+ }
+\cs_new_protected:cpn { @@_grab_m_6:w } #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn
+ \l_@@_fn_tl \use_none:nn { } { }
+ }
+\cs_new_protected:cpn { @@_grab_m_7:w } #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn
+ \l_@@_fn_tl \use_none:n { }
+ }
+\cs_new_protected:cpn { @@_grab_m_8:w } #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \exp_after:wN \cs_set_eq:NN \l_@@_fn_tl \@@_grab_m_aux:Nnnnnnnnn
+ \l_@@_fn_tl \prg_do_nothing:
+ }
+\cs_new_protected:cpx { @@_grab_m_9:w }
+ {
+ \exp_not:c { @@_grab_m_5:w }
+ \exp_not:c { @@_grab_m_4:w }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_R:w, \@@_grab_R_long:w}
+% \begin{macro}{\@@_grab_R_aux:NNnN}
+% The grabber for \texttt{R}-type arguments is basically the same as
+% that for \texttt{D}-type ones, but always skips spaces (as it is mandatory)
+% and has a hard-coded error message.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_R:w #1#2#3 \@@_run_code:
+ { \@@_grab_R_aux:NNnN #1 #2 {#3} \cs_set_protected_nopar:Npn }
+\cs_new_protected:Npn \@@_grab_R_long:w #1#2#3 \@@_run_code:
+ { \@@_grab_R_aux:NNnN #1 #2 {#3} \cs_set_protected:Npn }
+\cs_new_protected:Npn \@@_grab_R_aux:NNnN #1#2#3#4
+ {
+ \@@_grab_D_aux:NNnN #1 #2 {#3} #4
+ \@@_peek_nonspace_remove:NTF #1
+ { \@@_grab_D_call:Nw #1 }
+ {
+ \msg_error:nnxx { cmd } { missing-required }
+ { \@@_environment_or_command: }
+ { \token_to_str:N #1 }
+ \@@_add_arg:o \c_novalue_tl
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_t:w}
+% \begin{macro}{\@@_grab_t_obey_spaces:w}
+% \begin{macro}{\@@_grab_t_aux:NNw}
+% Dealing with a token is quite easy. Check the match, remove the
+% token if needed and add a flag to the output.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_t:w
+ { \@@_grab_t_aux:NNw \@@_peek_nonspace_remove:NTF }
+\cs_new_protected:Npn \@@_grab_t_obey_spaces:w
+ { \@@_grab_t_aux:NNw \@@_peek_meaning_remove:NTF }
+\cs_new_protected:Npn \@@_grab_t_aux:NNw #1#2#3 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#3}
+ \exp_after:wN \cs_set_protected:Npn \l_@@_fn_tl
+ {
+ #1 #2
+ { \@@_add_arg:n { \BooleanTrue } }
+ { \@@_add_arg:n { \BooleanFalse } }
+ }
+ \l_@@_fn_tl
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_v_arg_tl}
+% \begin{macrocode}
+\tl_new:N \l_@@_v_arg_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_grab_v:w}
+% \begin{macro}{\@@_grab_v_long:w}
+% \begin{macro}{\@@_grab_v_aux:w}
+% \begin{macro}{\@@_grab_v_group_end:}
+% The opening delimiter is the first non-space token, and is never
+% read verbatim. This is required by consistency with the case where
+% the preceding argument was optional and absent: then \TeX{} has
+% already read and tokenized that token when looking for the optional
+% argument. The first thing is thus to check is that this delimiter
+% is a character, and to distinguish the case of a left brace (in that
+% case, \cs{group_align_safe_end:} is needed to compensate for the
+% begin-group character that was just seen). Then set verbatim
+% catcodes with \cs{@@_grab_v_aux_catcodes:}.
+%
+% The group keep catcode changes local, and
+% \cs{group_align_safe_begin/end:} allow to use a character
+% with category code~$4$ (normally |&|) as the delimiter (all commands
+% do \cs{group_align_safe_begin/end:}, so there's no need to do that
+% again here).
+% It is ended by \cs{@@_grab_v_group_end:}, which smuggles
+% the collected argument out of the group.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_v:w
+ {
+ \bool_set_false:N \l_@@_long_bool
+ \@@_grab_v_aux:w
+ }
+\cs_new_protected:Npn \@@_grab_v_long:w
+ {
+ \bool_set_true:N \l_@@_long_bool
+ \@@_grab_v_aux:w
+ }
+\cs_new_protected:Npn \@@_grab_v_aux:w #1 \@@_run_code:
+ {
+ \tl_set:Nn \l_@@_signature_tl {#1}
+ \group_begin:
+ \tex_escapechar:D = 92 \scan_stop:
+ \tl_clear:N \l_@@_v_arg_tl
+ \peek_remove_spaces:n
+ {
+ \peek_meaning_remove:NTF \c_group_begin_token
+ {
+ \group_align_safe_end:
+ \@@_grab_v_bgroup:
+ }
+ {
+ \peek_N_type:TF
+ { \@@_grab_v_aux_test:N }
+ { \@@_grab_v_aux_abort:n { } }
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_grab_v_group_end:
+ {
+ \exp_args:NNNo
+ \group_end:
+ \tl_set:Nn \l_@@_v_arg_tl { \l_@@_v_arg_tl }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_v_aux_test:N}
+% \begin{macro}
+% {
+% \@@_grab_v_aux_loop:N,
+% \@@_grab_v_aux_loop:NN,
+% \@@_grab_v_aux_loop_end:
+% }
+% Check that the opening delimiter is a character, setup category codes,
+% then start reading tokens one by one, keeping the delimiter as an argument.
+% If the verbatim was not nested, we will be grabbing one character
+% at each step. Unfortunately, it can happen that what follows the
+% verbatim argument is already tokenized. Thus, we check at each step
+% that the next token is indeed a \enquote{nice}
+% character, \emph{i.e.}, is not a character with
+% category code $1$ (begin-group), $2$ (end-group)
+% or $6$ (macro parameter), nor the space character,
+% with category code~$10$ and character code~$32$,
+% nor a control sequence.
+% The partially built argument is stored in \cs{l_@@_v_arg_tl}.
+% If we ever meet a token which we cannot grab (non-N-type),
+% or which is not a character according to
+% \cs{@@_grab_v_token_if_char:NTF}, then we bail out with
+% \cs{@@_grab_v_aux_abort:n}. Otherwise, we stop at the first
+% character matching the delimiter.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_v_aux_test:N #1
+ {
+ \@@_grab_v_token_if_char:NTF #1
+ {
+ \@@_grab_v_aux_put:N #1
+ \@@_grab_v_aux_catcodes:
+ \@@_grab_v_aux_loop:N #1
+ }
+ { \@@_grab_v_aux_abort:n {#1} #1 }
+ }
+\cs_new_protected:Npn \@@_grab_v_aux_loop:N #1
+ {
+ \peek_N_type:TF
+ { \@@_grab_v_aux_loop:NN #1 }
+ { \@@_grab_v_aux_abort:n { } }
+ }
+\cs_new_protected:Npn \@@_grab_v_aux_loop:NN #1#2
+ {
+ \@@_grab_v_token_if_char:NTF #2
+ {
+ \token_if_eq_charcode:NNTF #1 #2
+ { \@@_grab_v_aux_loop_end: }
+ {
+ \@@_grab_v_aux_put:N #2
+ \@@_grab_v_aux_loop:N #1
+ }
+ }
+ { \@@_grab_v_aux_abort:n {#2} #2 }
+ }
+\cs_new_protected:Npn \@@_grab_v_aux_loop_end:
+ {
+ \@@_grab_v_group_end:
+ \@@_add_arg:x { \tl_tail:N \l_@@_v_arg_tl }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_v_nesting_int}
+% \begin{macrocode}
+\int_new:N \l_@@_v_nesting_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_grab_v_bgroup:}
+% \begin{macro}{\@@_grab_v_bgroup_loop:}
+% \begin{macro}{\@@_grab_v_bgroup_loop:N}
+% If the opening delimiter is a left brace, we keep track of
+% how many left and right braces were encountered so far in
+% \cs{l_@@_v_nesting_int} (the methods used for optional
+% arguments cannot apply here), and stop as soon as it reaches~$0$.
+%
+% Some care was needed when removing the opening delimiter, which
+% has already been assigned category code~$1$: using
+% \cs{peek_meaning_remove:NTF} in the \cs{@@_grab_v_aux:w}
+% function would break within alignments. Instead, we first
+% convert that token to a string, and remove the result as a
+% normal undelimited argument.
+% \begin{macrocode}
+\cs_new_protected:Npx \@@_grab_v_bgroup:
+ {
+ \exp_not:N \@@_grab_v_aux_catcodes:
+ \exp_not:n { \int_set:Nn \l_@@_v_nesting_int { 1 } }
+ \exp_not:N \@@_grab_v_aux_put:N \iow_char:N \{
+ \exp_not:N \@@_grab_v_bgroup_loop:
+ }
+\cs_new_protected:Npn \@@_grab_v_bgroup_loop:
+ {
+ \peek_N_type:TF
+ { \@@_grab_v_bgroup_loop:N }
+ { \@@_grab_v_aux_abort:n { } }
+ }
+\cs_new_protected:Npn \@@_grab_v_bgroup_loop:N #1
+ {
+ \@@_grab_v_token_if_char:NTF #1
+ {
+ \token_if_eq_charcode:NNTF \c_group_end_token #1
+ {
+ \int_decr:N \l_@@_v_nesting_int
+ \int_compare:nNnTF \l_@@_v_nesting_int > 0
+ {
+ \@@_grab_v_aux_put:N #1
+ \@@_grab_v_bgroup_loop:
+ }
+ { \@@_grab_v_aux_loop_end: }
+ }
+ {
+ \token_if_eq_charcode:NNT \c_group_begin_token #1
+ { \int_incr:N \l_@@_v_nesting_int }
+ \@@_grab_v_aux_put:N #1
+ \@@_grab_v_bgroup_loop:
+ }
+ }
+ { \@@_grab_v_aux_abort:n {#1} #1 }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_v_aux_catcodes:}
+% \begin{macro}{\@@_grab_v_aux_abort:n}
+% The approach for short verbatim arguments is to make the end-line
+% character a macro parameter character: this is forbidden by the
+% rest of the code. Then the error branch can check what caused the
+% bail out and give the appropriate error message.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_v_aux_catcodes:
+ {
+ \cs_set_eq:NN \do \char_set_catcode_other:N
+ \dospecials
+ \tex_endlinechar:D = `\^^M \scan_stop:
+ \bool_if:NTF \l_@@_long_bool
+ { \char_set_catcode_other:n { \tex_endlinechar:D } }
+ { \char_set_catcode_parameter:n { \tex_endlinechar:D } }
+ }
+\cs_new_protected:Npn \@@_grab_v_aux_abort:n #1
+ {
+ \@@_grab_v_group_end:
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \peek_meaning_remove:NTF \char_generate:nn { \tex_endlinechar:D } { 6 }
+ {
+ \msg_error:nnxxx { cmd } { verbatim-newline }
+ { \@@_environment_or_command: }
+ { \tl_to_str:N \l_@@_v_arg_tl }
+ { \tl_to_str:n {#1} }
+ \@@_add_arg:o \c_novalue_tl
+ }
+ {
+ \msg_error:nnxxx { cmd } { verbatim-tokenized }
+ { \@@_environment_or_command: }
+ { \tl_to_str:N \l_@@_v_arg_tl }
+ { \tl_to_str:n {#1} }
+ \@@_add_arg:o \c_novalue_tl
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_v_aux_put:N}
+% 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}
+\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 }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_v_token_if_char:NTF}
+% This function assumes that the escape character is printable.
+% Then the string representation of control sequences is at least
+% two characters, and \cs{str_tail:n} only removes the escape
+% character. Macro parameter characters are doubled by
+% \cs{tl_to_str:n}, and will also yield a non-empty result,
+% hence are not considered as characters.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_v_token_if_char:NTF #1
+ { \str_if_eq:eeTF { } { \str_tail:n {#1} } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_arg:n, \@@_add_arg:V, \@@_add_arg:o, \@@_add_arg:x}
+% When an argument is found it is stored, then further arguments are
+% grabbed by calling \cs{l_@@_signature_tl}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_add_arg:n #1
+ {
+ \tl_put_right:Nn \l_@@_args_tl { {#1} }
+ \l_@@_signature_tl \@@_run_code:
+ }
+\cs_generate_variant:Nn \@@_add_arg:n { V , o , x }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Grabbing arguments expandably}
+%
+% \begin{macro}[EXP]{\@@_expandable_grab_D:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_D:NNNwNNn}
+% \begin{macro}[EXP]{\@@_expandable_grab_D:NNNwNNnnn}
+% \begin{macro}[EXP]{\@@_expandable_grab_D:Nw}
+% \begin{macro}[EXP]{\@@_expandable_grab_D:nnNNNwNN}
+% The first step is to grab the first token or group. The generic grabbers
+% \cs{\meta{function}}\verb*| | and \cs{\meta{function}}\verb*| | are just after \cs{q_@@}, we go and find
+% them (and use the long one).
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_D:w #1 \q_@@ #2#3
+ { #2 { \@@_expandable_grab_D:NNNwNNn #1 \q_@@ #2 #3 } }
+% \end{macrocode}
+% We then wish to test whether |#7|, which we just grabbed, is exactly |#2|.
+% A preliminary test is whether their string representations coincide, then
+% expand the only grabber function we have, |#1|, once: the two strings below
+% are equal if and only if |#7| matches |#2| exactly.\footnote{It is obvious
+% that if \texttt{\#7} matches \texttt{\#2} then the strings are equal. We
+% must check the converse. The right-hand-side of \cs{str_if_eq:onTF} does
+% not end with \texttt{\#3}, implying that the grabber function took
+% everything as its arguments. The first brace group can only be empty if
+% \texttt{\#7} starts with \texttt{\#2}, otherwise the brace group preceding
+% \texttt{\#7} would not vanish. The third brace group is empty, thus the
+% \cs{q_@@} that was used by our grabber \texttt{\#1} must be the one
+% that we inserted (not some token in \texttt{\#7}), hence the second brace
+% group contains the end of \texttt{\#7} followed by \texttt{\#2}. Since this
+% is \texttt{\#2} on the right-hand-side, and no brace can be lost there,
+% \texttt{\#7} must contain nothing else than its leading \texttt{\#2}.}
+% The preliminary test is needed as |#7| could validly contain
+% \tn{par} (because a later mandatory argument could be long) and our
+% grabber may be short. If
+% |#7| does not match |#2|, then the optional argument is missing, we use the
+% default |-NoValue-|, and put back the argument |#7| in the input stream.
+%
+% If it does match, then interesting things need to be done. We will grab the
+% argument piece by piece, with the following pattern:
+% \begin{quote}
+% \meta{grabber} \Arg{tokens} \\
+% ~~\cs{q_nil} \Arg{piece 1} \meta{piece 2} \cs{ERROR} \cs{q_@@}\\
+% ~~\cs{q_nil} \meta{input stream}
+% \end{quote}
+% The \meta{grabber} will find an opening delimiter in \meta{piece 2}, take
+% the \cs{q_@@} as a second delimiter, and find more material delimited
+% by the closing delimiter in the \meta{input stream}. We then move the part
+% before the opening delimiter from \meta{piece 2} to \meta{piece 1}, and the
+% material taken from the \meta{input stream} to the \meta{piece 2}. Thus,
+% the argument moves gradually from the \meta{input stream} to the
+% \meta{piece 2}, then to the \meta{piece 1} when we have made sure to find
+% all opening and closing delimiters. This two-step process ensures that
+% nesting works: the number of opening delimiters minus closing delimiters in
+% \meta{piece 1} is always equal to the number of closing delimiters in
+% \meta{piece 2}. We stop grabbing arguments once the \meta{piece 2} contains
+% no opening delimiter any more, hence the balance is reached, and the final
+% argument is \meta{piece 1} \meta{piece 2}.
+% The indirection via \cs{@@_tmp:w} allows to insert |-NoValue-| expanded.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1
+ {
+ \cs_new:Npn \@@_expandable_grab_D:NNNwNNn ##1##2##3##4 \q_@@ ##5##6##7
+ {
+ \str_if_eq:nnTF {##2} {##7}
+ {
+ \str_if_eq:onTF
+ { ##1 { } { } ##7 ##2 \q_@@ ##3 }
+ { { } {##2} { } }
+ }
+ { \use_ii:nn }
+ {
+ ##1
+ { \@@_expandable_grab_D:NNNwNNnnn ##1##2##3##4 \q_@@ ##5##6 }
+ \q_nil { } ##2 \ERROR \q_@@ \ERROR
+ }
+ { ##4 {#1} \q_@@ ##5 ##6 {##7} }
+ }
+ }
+\exp_args:No \@@_tmp:w { \c_novalue_tl }
+% \end{macrocode}
+% At this stage, |#7| is \cs{q_nil} \Arg{piece 1} \meta{more for piece 1},
+% and we want to concatenate all that, removing \cs{q_nil}, and keeping the
+% opening delimiter |#2|. Simply use \cs{use_ii:nn}. Also, |#8| is
+% \meta{remainder of piece 2} \cs{ERROR}, and |#9| is \cs{ERROR} \meta{more
+% for piece 2}. We concatenate those, replacing the two \cs{ERROR} by the
+% closing delimiter |#3|.
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_D:NNNwNNnnn #1#2#3#4 \q_@@ #5#6#7#8#9
+ {
+ \exp_args:Nof \@@_expandable_grab_D:nnNNNwNN
+ { \use_ii:nn #7 #2 }
+ { \@@_expandable_grab_D:Nw #3 \exp_stop_f: #8 #9 }
+ #1#2#3 #4 \q_@@ #5 #6
+ }
+\cs_new:Npn \@@_expandable_grab_D:Nw #1#2 \ERROR \ERROR { #2 #1 }
+% \end{macrocode}
+% Armed with our two new \meta{pieces}, we are ready to loop. However, we
+% must first see if \meta{piece 2} (here |#2|) contains any opening
+% delimiter |#4|. Again, we expand |#3|, this time removing its whole output
+% with \cs{use_none:nnn}. The test is similar to \cs{tl_if_in:nnTF}. The
+% token list is empty if and only if |#2| does not contain the opening
+% delimiter. In that case, we are done, and put the argument (from which we
+% remove a spurious pair of delimiters coming from how we started the loop).
+% Otherwise, we go back to looping with
+% \cs{@@_expandable_grab_D:NNNwNNnnn}. The code to deal with brace stripping
+% is much the same as for the non-expandable case.
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_D:nnNNNwNN #1#2#3#4#5#6 \q_@@ #7#8
+ {
+ \exp_args:No \tl_if_empty:oTF
+ { #3 { \use_none:nnn } #2 \q_@@ #5 #4 \q_@@ #5 }
+ {
+ \tl_if_blank:oTF { \use_none:nn #1#2 }
+ { \@@_put_arg_expandable:ow { \use_none:nn #1#2 } }
+ {
+ \str_if_eq:eeTF
+ { \exp_not:o { \use_none:nn #1#2 } }
+ { { \exp_not:o { \use_iii:nnnn #1#2 \q_nil } } }
+ { \@@_put_arg_expandable:ow { \use_iii:nnn #1#2 } }
+ { \@@_put_arg_expandable:ow { \use_none:nn #1#2 } }
+ }
+ #6 \q_@@ #7 #8
+ }
+ {
+ #3
+ { \@@_expandable_grab_D:NNNwNNnnn #3#4#5#6 \q_@@ #7 #8 }
+ \q_nil {#1} #2 \ERROR \q_@@ \ERROR
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:NNwNNn}
+% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:Nwn}
+% When the delimiters are identical, nesting is not possible and a simplified
+% approach is used. The test concept here is the same as for the case where
+% the delimiters are different but there cannot be any nesting.
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_D_alt:w #1 \q_@@ #2#3
+ { #2 { \@@_expandable_grab_D_alt:NNwNNn #1 \q_@@ #2 #3 } }
+\cs_set_protected:Npn \@@_tmp:w #1
+ {
+ \cs_new:Npn \@@_expandable_grab_D_alt:NNwNNn ##1##2##3 \q_@@ ##4##5##6
+ {
+ \str_if_eq:nnTF {##6} {##2}
+ {
+ \str_if_eq:onTF
+ { ##1 { } ##6 ##2 ##2 }
+ { { } ##2 }
+ }
+ { \use_ii:nn }
+ {
+ ##1
+ { \@@_expandable_grab_D_alt:NNwn ##4 ##5 ##3 \q_@@ }
+ ##6 \ERROR
+ }
+ { ##3 {#1} \q_@@ ##4 ##5 {##6} }
+ }
+ }
+\exp_args:No \@@_tmp:w { \c_novalue_tl }
+\cs_new:Npn \@@_expandable_grab_D_alt:NNwn #1#2#3 \q_@@ #4
+ {
+ \tl_if_blank:oTF { \use_none:n #4 }
+ { \@@_put_arg_expandable:ow { \use_none:n #4 } }
+ {
+ \str_if_eq:eeTF
+ { \exp_not:o { \use_none:n #4 } }
+ { { \exp_not:o { \use_ii:nnn #4 \q_nil } } }
+ { \@@_put_arg_expandable:ow { \use_ii:nn #4 } }
+ { \@@_put_arg_expandable:ow { \use_none:n #4 } }
+ }
+ #3 \q_@@ #1 #2
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_expandable_grab_E:w, \@@_expandable_grab_E_long:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_E_aux:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_E_test:nnw}
+% \begin{macro}[EXP]{\@@_expandable_grab_E_loop:nnnNNw}
+% \begin{macro}[EXP]{\@@_expandable_grab_E_find:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_E_find:nnw}
+% \begin{macro}[EXP]{\@@_expandable_grab_E_end:nnw}
+% We keep track of long/short by placing the appropriate grabber as
+% the third token after \cs{q_@@}; it is eventually removed by the
+% \texttt{end:nnw} auxiliary. The \texttt{aux:w} auxiliary will be
+% called repeatedly with two arguments: the set
+% of pairs \meta{parser} \meta{token}, and the set of arguments found
+% so far (initially all |{-NoValue-}|). At each step, grab what
+% follows in the input stream then call the \texttt{loop:nnnNNw}
+% auxiliary to compare it with each possible embellishment in turn.
+% This auxiliary's |#1| is what was found in the input, |#2| collects
+% \meta{parser} \meta{token} pairs that did not match, |#3| collects
+% the corresponding arguments found previously, |#4| and |#5| is the
+% current pair, |#6| is the remaining pairs, |#7| is empty or two
+% \cs{q_nil}, and |#8| is the current argument. If none of the pairs
+% matched (determined by \cs{quark_if_nil:NTF}) then call the
+% \texttt{end} auxiliary to stop looking for embellishments,
+% remembering to put what was grabbed in the input back where it
+% belongs, and storing the arguments found just before \cs{q_@@}. If
+% the current argument |#8| is not |-NoValue-| or if the input |#1|
+% does not match |#5| (see \texttt{t}-type arguments below for a
+% similar \cs{str_if_eq:onTF} test) then carry on the loop.
+% Otherwise, we found a new embellishment: grab the corresponding
+% argument in the input using the \texttt{find:w} auxiliary. To avoid
+% losing braces around that auxiliary's argument we include a
+% space, which will be eliminated in the next loop through
+% embellishments.
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_E:w #1 \q_@@ #2#3
+ { \@@_expandable_grab_E_aux:w #1 \q_@@ #2 #3 #3 }
+\cs_new:Npn \@@_expandable_grab_E_long:w #1 \q_@@ #2#3
+ { \@@_expandable_grab_E_aux:w #1 \q_@@ #2 #3 #2 }
+\cs_new:Npn \@@_expandable_grab_E_aux:w #1 \q_@@ #2#3#4
+ { #2 { \@@_expandable_grab_E_test:nnw #1 \q_@@ #2 #3 #4 } }
+\cs_new:Npn \@@_expandable_grab_E_test:nnw #1#2#3 \q_@@ #4#5#6#7
+ {
+ \@@_expandable_grab_E_loop:nnnNNw {#7} { } { }
+ #1 \q_nil \q_nil \q_nil \q_mark #2 \q_nil
+ #3 \q_@@ #4 #5 #6
+ }
+\cs_new:Npn \@@_expandable_grab_E_loop:nnnNNw
+ #1#2#3#4#5#6 \q_nil #7 \q_mark #8
+ {
+ \quark_if_nil:NTF #4
+ { \@@_expandable_grab_E_end:nnw {#1} {#3} }
+ {
+ \tl_if_novalue:nTF {#8}
+ { \str_if_eq:onTF { #4 { } #1 #5 } {#5} }
+ { \use_ii:nn }
+ { \@@_expandable_grab_E_find:w { #2 #4 #5 #6 } {#3} ~ }
+ {
+ \@@_expandable_grab_E_loop:nnnNNw
+ {#1} { #2 #4 #5 } { #3 {#8} }
+ #6 \q_nil #7 \q_mark
+ }
+ }
+ }
+\cs_new:Npn \@@_expandable_grab_E_find:w #1 \q_@@ #2#3#4
+ { #4 { \@@_expandable_grab_E_find:nnw #1 \q_@@ #2 #3 #4 } }
+\cs_new:Npn \@@_expandable_grab_E_find:nnw #1#2#3 \q_nil #4 \q_@@ #5#6#7#8
+ { \@@_expandable_grab_E_aux:w {#1} { #2 {#8} #3 } #4 \q_@@ #5 #6 #7 }
+\cs_new:Npn \@@_expandable_grab_E_end:nnw #1#2#3 \q_@@ #4#5#6
+ { #3 #2 \q_@@ #4 #5 {#1} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_expandable_grab_m:w, \@@_expandable_grab_m_long:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_m_aux:wNn}
+% The mandatory case is easy: find the auxiliary after the \cs{q_@@},
+% and use it directly to grab the argument, then correctly position
+% the argument before \cs{q_@@}.
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_m:w #1 \q_@@ #2#3
+ { #3 { \@@_expandable_grab_m_aux:wNn #1 \q_@@ #2 #3 } }
+\cs_new:Npn \@@_expandable_grab_m_long:w #1 \q_@@ #2#3
+ { #2 { \@@_expandable_grab_m_aux:wNn #1 \q_@@ #2 #3 } }
+\cs_new:Npn \@@_expandable_grab_m_aux:wNn #1 \q_@@ #2#3#4
+ { #1 {#4} \q_@@ #2 #3 }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_expandable_grab_R:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_R_aux:NNNwNNn}
+% Much the same as for the \texttt{D}-type argument, with only the lead-off
+% function varying.
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_R:w #1 \q_@@ #2#3
+ { #2 { \@@_expandable_grab_R_aux:NNNwNNn #1 \q_@@ #2#3 } }
+\cs_set_protected:Npn \@@_tmp:w #1
+ {
+ \cs_new:Npn \@@_expandable_grab_R_aux:NNNwNNn ##1##2##3##4 \q_@@ ##5##6##7
+ {
+ \str_if_eq:nnTF {##7} {##2}
+ {
+ \str_if_eq:onTF
+ { ##1 { } { } ##7 ##2 \q_@@ ##3 }
+ { { } {##2} { } }
+ }
+ { \use_ii:nn }
+ {
+ ##1
+ { \@@_expandable_grab_D:NNNwNNnnn ##1##2##3##4 \q_@@ ##5##6 }
+ \q_nil { } ##2 \ERROR \q_@@ \ERROR
+ }
+ {
+ \msg_expandable_error:nnff { cmd } { missing-required }
+ { \exp_args:Nf \tl_trim_spaces:n { \token_to_str:N ##5 } }
+ { \tl_to_str:n {##2} }
+ ##4 {#1} \q_@@ ##5 ##6 {##7}
+ }
+ }
+ }
+\exp_args:No \@@_tmp:w { \c_novalue_tl }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_expandable_grab_R_alt:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_R_alt_aux:NNwNNn}
+% When the delimiters are identical, nesting is not possible and a simplified
+% approach is used. The test concept here is the same as for the case where
+% the delimiters are different.
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_R_alt:w #1 \q_@@ #2#3
+ { #2 { \@@_expandable_grab_R_alt_aux:NNwNNn #1 \q_@@ #2#3 } }
+\cs_set_protected:Npn \@@_tmp:w #1
+ {
+ \cs_new:Npn \@@_expandable_grab_R_alt_aux:NNwNNn ##1##2##3 \q_@@ ##4##5##6
+ {
+ \str_if_eq:nnTF {##6} {##2}
+ {
+ \str_if_eq:onTF
+ { ##1 { } ##6 ##2 ##2 }
+ { { } ##2 }
+ }
+ { \use_ii:nn }
+ {
+ ##1
+ { \@@_expandable_grab_D_alt:NNwn ##4 ##5 ##3 \q_@@ }
+ ##6 \ERROR
+ }
+ {
+ \msg_expandable_error:nnff { cmd } { missing-required }
+ { \exp_args:Nf \tl_trim_spaces:n { \token_to_str:N ##4 } }
+ { \tl_to_str:n {##2} }
+ ##3 {#1} \q_@@ ##4 ##5 {##6}
+ }
+ }
+ }
+\exp_args:No \@@_tmp:w { \c_novalue_tl }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_expandable_grab_t:w}
+% \begin{macro}[EXP]{\@@_expandable_grab_t_aux:NNwn}
+% As for a \texttt{D}-type argument, here we compare the grabbed tokens using
+% the only parser we have in order to work out if |#2| is exactly equal to
+% the output of the grabber.
+% \begin{macrocode}
+\cs_new:Npn \@@_expandable_grab_t:w #1 \q_@@ #2#3
+ { #2 { \@@_expandable_grab_t_aux:NNwn #1 \q_@@ #2 #3 } }
+\cs_new:Npn \@@_expandable_grab_t_aux:NNwn #1#2#3 \q_@@ #4#5#6
+ {
+ \str_if_eq:onTF { #1 { } #6 #2 } {#2}
+ { #3 { \BooleanTrue } \q_@@ #4 #5 }
+ { #3 { \BooleanFalse } \q_@@ #4 #5 {#6} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+% {\@@_put_arg_expandable:nw, \@@_put_arg_expandable:ow}
+% A useful helper, to store arguments when they are ready.
+% \begin{macrocode}
+\cs_new:Npn \@@_put_arg_expandable:nw #1#2 \q_@@ { #2 {#1} \q_@@ }
+\cs_generate_variant:Nn \@@_put_arg_expandable:nw { o }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Argument processors}
+%
+% \begin{macro}{\@@_bool_reverse:N}
+% A simple reversal.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_bool_reverse:N #1
+ {
+ \bool_if:NTF #1
+ { \tl_set:Nn \ProcessedArgument { \c_false_bool } }
+ { \tl_set:Nn \ProcessedArgument { \c_true_bool } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_split_list_seq, \l_@@_split_list_tl}
+% \begin{macro}{\@@_split_list:nn}
+% \begin{macro}{\@@_split_list_multi:nn, \@@_split_list_multi:nV}
+% \begin{macro}{\@@_split_list_single:Nn}
+% Splitting can take place either at a single token or at a longer
+% identifier. To deal with single active tokens, a two-part procedure is
+% needed.
+% \begin{macrocode}
+\seq_new:N \l_@@_split_list_seq
+\tl_new:N \l_@@_split_list_tl
+\cs_new_protected:Npn \@@_split_list:nn #1#2
+ {
+ \tl_if_single:nTF {#1}
+ {
+ \token_if_cs:NTF #1
+ { \@@_split_list_multi:nn {#1} {#2} }
+ { \@@_split_list_single:Nn #1 {#2} }
+ }
+ { \@@_split_list_multi:nn {#1} {#2} }
+ }
+\cs_new_protected:Npn \@@_split_list_multi:nn #1#2
+ {
+ \seq_set_split:Nnn \l_@@_split_list_seq {#1} {#2}
+ \tl_clear:N \ProcessedArgument
+ \seq_map_inline:Nn \l_@@_split_list_seq
+ { \tl_put_right:Nn \ProcessedArgument { {##1} } }
+ }
+\cs_generate_variant:Nn \@@_split_list_multi:nn { nV }
+\group_begin:
+\char_set_catcode_active:N \^^@
+\cs_new_protected:Npn \@@_split_list_single:Nn #1#2
+ {
+ \tl_set:Nn \l_@@_split_list_tl {#2}
+ \group_begin:
+ \char_set_lccode:nn { `\^^@ } { `#1 }
+ \tex_lowercase:D
+ {
+ \group_end:
+ \tl_replace_all:Nnn \l_@@_split_list_tl { ^^@ }
+ } {#1}
+ \@@_split_list_multi:nV {#1} \l_@@_split_list_tl
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{variable}
+%
+% \begin{macro}{\@@_split_argument:nnn}
+% \begin{macro}{\@@_split_argument_aux:nnnn}
+% \begin{macro}[EXP]{\@@_split_argument_aux:n}
+% \begin{macro}[rEXP]{\@@_split_argument_aux:wn}
+% Splitting to a known number of items is a special version of splitting
+% a list, in which the limit is hard-coded and where there will always be
+% exactly the correct number of output items. An auxiliary function is
+% used to save on working out the token list length several times.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_split_argument:nnn #1#2#3
+ {
+ \@@_split_list:nn {#2} {#3}
+ \exp_args:Nf \@@_split_argument_aux:nnnn
+ { \tl_count:N \ProcessedArgument }
+ {#1} {#2} {#3}
+ }
+\cs_new_protected:Npn \@@_split_argument_aux:nnnn #1#2#3#4
+ {
+ \int_compare:nNnF {#1} = { #2 + 1 }
+ {
+ \int_compare:nNnTF {#1} > { #2 + 1 }
+ {
+ \tl_set:Nx \ProcessedArgument
+ {
+ \exp_last_unbraced:NnNo
+ \@@_split_argument_aux:n
+ { #2 + 1 }
+ \use_none_delimit_by_q_stop:w
+ \ProcessedArgument
+ \q_stop
+ }
+ \msg_error:nnxxx { cmd } { split-excess-tokens }
+ { \tl_to_str:n {#3} } { \int_eval:n { #2 + 1 } }
+ { \tl_to_str:n {#4} }
+ }
+ {
+ \tl_put_right:Nx \ProcessedArgument
+ {
+ \prg_replicate:nn { #2 + 1 - (#1) }
+ { { \exp_not:V \c_novalue_tl } }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% Auxiliaries to leave exactly the correct number of arguments in
+% \cs{ProcessedArgument}.
+% \begin{macrocode}
+\cs_new:Npn \@@_split_argument_aux:n #1
+ { \prg_replicate:nn {#1} { \@@_split_argument_aux:wn } }
+\cs_new:Npn \@@_split_argument_aux:wn #1 \use_none_delimit_by_q_stop:w #2
+ {
+ \exp_not:n { {#2} }
+ #1
+ \use_none_delimit_by_q_stop:w
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_trim_spaces:n}
+% This one is almost trivial.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_trim_spaces:n #1
+ { \tl_set:Nx \ProcessedArgument { \tl_trim_spaces:n {#1} } }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Access to the argument specification}
+%
+% \begin{macro}{\@@_get_arg_spec_error:N, \@@_get_arg_spec_error:n}
+% \begin{macro}{\@@_get_arg_spec_error_aux:n}
+% Provide an informative error when trying to get the argument
+% specification of a non-\pkg{xparse} command or environment.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_get_arg_spec_error:N #1
+ {
+ \bool_set_false:N \l_@@_environment_bool
+ \tl_set:Nn \l_@@_fn_tl {#1}
+ \@@_get_arg_spec_error_aux:n { \cs_if_exist:NTF #1 }
+ }
+\cs_new_protected:Npn \@@_get_arg_spec_error:n #1
+ {
+ \bool_set_true:N \l_@@_environment_bool
+ \str_set:Nx \l_@@_environment_str {#1}
+ \@@_get_arg_spec_error_aux:n
+ { \cs_if_exist:cTF { \l_@@_environment_str } }
+ }
+\cs_new_protected:Npn \@@_get_arg_spec_error_aux:n #1
+ {
+ #1
+ {
+ \msg_error:nnx { cmd } { non-xparse }
+ { \@@_environment_or_command: }
+ }
+ {
+ \msg_error:nnx { cmd } { unknown }
+ { \@@_environment_or_command: }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_get_arg_spec:NTF}
+% If the command is not an \pkg{xparse} command, complain. If it is,
+% its second \enquote{item} is the argument specification.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_get_arg_spec:NTF #1#2#3
+ {
+ \__kernel_cmd_if_xparse:NTF #1
+ {
+ \tl_set:Nx \ArgumentSpecification { \tl_item:Nn #1 { 2 } }
+ #2
+ }
+ {#3}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% Rolling forward from 2020-10-01 is tricky because the entire |ltcmd|
+% module is new, but the user-level commands have the same name, so only
+% these will clash. To work around that, in |latexrelease| mode we will
+% (temporarily) disable \cs{__kernel_chk_if_free_cs:N} for this final
+% part of the code, then restore at the end.
+% \begin{macrocode}
+%<latexrelease>\cs_new_eq:NN \@@_chk_if_free_cs:N \__kernel_chk_if_free_cs:N
+%<latexrelease>\cs_gset_eq:NN \__kernel_chk_if_free_cs:N \use_none:n
+% \end{macrocode}
+%
+% \begin{variable}{\ArgumentSpecification}
+% \begin{macrocode}
+\tl_new:N \ArgumentSpecification
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_get_arg_spec:N}
+% \begin{macro}{\@@_get_arg_spec:n}
+% Recovering the argument specification is now trivial.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_get_arg_spec:N #1
+ {
+ \@@_get_arg_spec:NTF #1 { }
+ { \@@_get_arg_spec_error:N #1 }
+ }
+\cs_new_protected:Npn \@@_get_arg_spec:n #1
+ {
+ \exp_args:Nc \@@_get_arg_spec:NTF
+ { environment~ \tl_to_str:n {#1} }
+ { }
+ { \@@_get_arg_spec_error:n {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_show_arg_spec:N}
+% \begin{macro}{\@@_show_arg_spec:n}
+% Showing the argument specification simply means finding it and then
+% calling the \cs{tl_show:N} function.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_show_arg_spec:N #1
+ {
+ \@@_get_arg_spec:NTF #1
+ { \tl_show:N \ArgumentSpecification }
+ { \@@_get_arg_spec_error:N #1 }
+ }
+\cs_new_protected:Npn \@@_show_arg_spec:n #1
+ {
+ \exp_args:Nc \@@_get_arg_spec:NTF
+ { environment~ \tl_to_str:n {#1} }
+ { \tl_show:N \ArgumentSpecification }
+ { \@@_get_arg_spec_error:n {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Utilities}
+%
+% \begin{macro}{\@@_check_definable:nNT, \@@_check_definable_aux:nN}
+% Check that a token list is appropriate as a first argument of
+% \cs{NewDocumentCommand} and similar functions and otherwise
+% produce an error. First trim whitespace to allow for spaces around
+% the actual command to be defined. If the result has multiple
+% tokens, it is not a valid argument. The single token is a control
+% sequence exactly if its string representation has more than one
+% character (using \cs{token_to_str:N} rather than \cs{tl_to_str:n}
+% to avoid problems with macro parameter characters, and setting
+% \cs{tex_escapechar:D} to prevent it from being non-printable).
+% Finally, check for an active character: this is done by lowercasing
+% the token to fix its character code (arbitrarily to that of~|?|)
+% and comparing the result to an active~|?|. Both control sequences
+% and active characters are valid arguments, and non-active character
+% tokens are not. In all cases, the group opened to keep assignments
+% local must be closed.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_check_definable:nNT #1
+ { \tl_trim_spaces_apply:nN {#1} \@@_check_definable_aux:nN }
+\group_begin:
+ \char_set_catcode_active:n { `? }
+ \cs_new_protected:Npn \@@_check_definable_aux:nN #1#2
+ {
+ \group_begin:
+ \tl_if_single_token:nTF {#1}
+ {
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \exp_args:Nx \tl_if_empty:nTF
+ { \exp_args:No \str_tail:n { \token_to_str:N #1 } }
+ {
+ \exp_args:Nx \char_set_lccode:nn
+ { ` \str_head:n {#1} } { `? }
+ \tex_lowercase:D { \tl_if_eq:nnTF {#1} } { ? }
+ { \group_end: \use_iii:nnn }
+ { \group_end: \use_i:nnn }
+ }
+ { \group_end: \use_iii:nnn }
+ }
+ { \group_end: \use_ii:nnn }
+ {
+ \msg_error:nnxx { cmd } { not-definable }
+ { \tl_to_str:n {#1} } { \token_to_str:N #2 }
+ }
+ {
+ \msg_error:nnxx { cmd } { not-one-token }
+ { \tl_to_str:n {#1} } { \token_to_str:N #2 }
+ }
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_token_if_cs:NTF}
+% Based on the definition of \cs{@@_check_definable_aux:nN} above, but
+% only checks for an actual control sequence (\emph{i.e.},
+% \cs[no-index]{\meta{anything}}). \cs{tex_escapechar:D} is
+% temporarily changed to a known value and then it checks if
+% |\string#1| contains more than one character: if it does, it's a
+% control sequence. This test differs from \cs{token_if_cs:NTF} for
+% example in \verb|\token_if_cs:NTF \c_group_begin_token {T}{F}|,
+% where \cs{token_if_cs:NTF} returns false.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_token_if_cs:NTF #1
+ {
+ \group_begin:
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \exp_args:Nx \tl_if_empty:nTF
+ { \exp_args:No \str_tail:n { \token_to_str:N #1 } }
+ { \group_end: \use_ii:nn }
+ { \group_end: \use_i:nn }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_tl_mapthread_function:NNN, \@@_tl_mapthread_function:nnN}
+% \begin{macro}{\@@_tl_mapthread_loop:w}
+% Analogue of \cs{seq_mapthread_function:NNN} for token lists.
+% \begin{macrocode}
+\cs_new:Npn \@@_tl_mapthread_function:NNN #1#2#3
+ {
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_tl_mapthread_loop:w
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN #3
+ \exp_after:wN #1
+ \exp_after:wN \q_recursion_tail
+ \exp_after:wN \q_mark
+ #2
+ \q_recursion_tail
+ \q_recursion_stop
+ }
+\cs_new:Npn \@@_tl_mapthread_function:nnN #1#2#3
+ {
+ \@@_tl_mapthread_loop:w #3
+ #1 \q_recursion_tail \q_mark
+ #2 \q_recursion_tail \q_recursion_stop
+ }
+\cs_new:Npn \@@_tl_mapthread_loop:w #1#2#3 \q_mark #4
+ {
+ \quark_if_recursion_tail_stop:n {#2}
+ \quark_if_recursion_tail_stop:n {#4}
+ #1 {#2} {#4}
+ \@@_tl_mapthread_loop:w #1#3 \q_mark
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\__kernel_cmd_if_xparse:NTF}
+% \changes{v1.0d}{2021/04/19}{Renamed \cs{__cmd_cmd_if_xparse:NTF} to
+% \cs{__kernel_cmd_if_xparse:NTF} for cross-module usage}
+% \begin{macro}{\@@_cmd_if_xparse_aux:N}
+%
+% To determine whether the command is an \pkg{xparse} command check
+% that its |arg_spec| is empty (this also excludes non-macros) and
+% that its |replacement_spec| starts with either
+% \cs{@@_start:nNNnnn} (non-expandable command) or
+% \cs{@@_start_expandable:nNNNNn} (expandable command) or
+% \cs{@@_start_env:nnnnn} (environment).
+%
+% This conditional is needed in several kernel modules and is
+% therefore has a kernel-internal name.
+% \begin{macrocode}
+\cs_new_protected:Npn \__kernel_cmd_if_xparse:NTF #1
+ {
+ \exp_args:Nf \str_case_e:nnTF
+ {
+ \exp_args:Nf \tl_if_empty:nT { \cs_argument_spec:N #1 }
+ {
+ \exp_last_unbraced:Nf \@@_cmd_if_xparse_aux:w
+ { \cs_replacement_spec:N #1 } ~ \q_stop
+ }
+ }
+ {
+ { \token_to_str:N \@@_start:nNNnnn } { }
+ { \token_to_str:N \@@_start_expandable:nNNNNn } { }
+ { \token_to_str:N \@@_start_env:nnnnn } { }
+ }
+ }
+\cs_new:Npn \@@_cmd_if_xparse_aux:w #1 ~ #2 \q_stop {#1}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_peek_nonspace:NTF, \@@_peek_nonspace_remove:NTF, \@@_peek_nonspace_aux:nNNTF}
+% Collect spaces in a loop, and put the collected spaces back in the
+% false branch of a call to \cs{peek_meaning:NTF} or
+% \cs{peek_meaning_remove:NTF}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_peek_nonspace:NTF
+ { \@@_peek_nonspace_aux:nNNTF { } \@@_peek_meaning:NTF }
+\cs_new_protected:Npn \@@_peek_nonspace_remove:NTF
+ { \@@_peek_nonspace_aux:nNNTF { } \@@_peek_meaning_remove:NTF }
+\cs_new_protected:Npn \@@_peek_nonspace_aux:nNNTF #1#2#3#4#5
+ {
+ \peek_meaning_remove:NTF \c_space_token
+ { \@@_peek_nonspace_aux:nNNTF { #1 ~ } #2 #3 {#4} {#5} }
+ { #2 #3 { #4 } { #5 #1 } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_peek_meaning:NTF, \@@_peek_meaning_remove:NTF}
+% \begin{macro}{\@@_peek_cs_check_equal:NNN, \@@_peek_meaning_aux:NNTF, \@@_peek_true_remove:NNw}
+% Peek ahead for a token with a given meaning. In case the search
+% token is a control sequence, also check that the \meta{csname} is
+% the same as the control sequence peeked at. This extra verification
+% is necessary when the command is delimited by control sequence tokens
+% (as opposed to character tokens), and we want the the exact same
+% control sequence to match.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_peek_meaning:NTF
+ { \@@_peek_meaning_aux:NNTF \c_false_bool }
+\cs_new_protected:Npn \@@_peek_meaning_remove:NTF
+ { \@@_peek_meaning_aux:NNTF \c_true_bool }
+\cs_new_protected:Npn \@@_peek_meaning_aux:NNTF #1#2#3#4
+ {
+ \tl_set:Nn \l_@@_tmpa_tl {#3}
+ \tl_set:Nn \l_@@_tmpb_tl {#4}
+ \peek_meaning:NTF #2
+ {
+ \token_if_eq_meaning:NNTF #2 \c_group_begin_token
+ { \@@_peek_true_remove:Nw #1 }
+ {
+ \@@_token_if_cs:NTF #2
+ { \@@_peek_cs_check_equal:NNN #1 #2 }
+ { \@@_peek_true_remove:Nw #1 }
+ }
+ }
+ { \l_@@_tmpb_tl }
+ }
+\cs_new_protected:Npn \@@_peek_cs_check_equal:NNN #1#2#3
+ {
+ \str_if_eq:nnTF {#2} {#3}
+ { \@@_peek_true_remove:Nw #1 }
+ { \l_@@_tmpb_tl }
+ #3
+ }
+\cs_new_protected:Npn \@@_peek_true_remove:Nw #1
+ {
+ \bool_if:NTF #1
+ {
+ \tex_afterassignment:D \l_@@_tmpa_tl
+ \cs_set_eq:NN \@@_tmp:w
+ }
+ { \l_@@_tmpa_tl }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+% \begin{variable}{\c_@@_ignore_def_tl}
+% \begin{macrocode}
+\tl_const:Nn \c_@@_ignore_def_tl
+ { \\ \\ LaTeX~will~ignore~this~entire~definition. }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_environment_or_command:}
+% Two texts used in several messages.
+% \begin{macrocode}
+\cs_new:Npn \@@_environment_or_command:
+ {
+ \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 }
+ '
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% Some messages intended as errors when defining commands/environments.
+% \begin{macrocode}
+\msg_new:nnnn { cmd } { arg-after-body }
+ { In~the~definition~of~#1,~b~(body)~argument~must~be~last. }
+ {
+ The~'body'~argument~type~is~followed~by~'#2'~in~the~argument~
+ specification~of~the~#1.~This~is~not~allowed.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { bad-arg-spec }
+ { Bad~argument~specification~'#2'~for~#1. }
+ {
+ The~argument~specification~provided~was~not~valid:~
+ one~or~more~mandatory~pieces~of~information~were~missing.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { command-already-defined }
+ { Command~'#1'~already~defined! }
+ {
+ You~have~used~#2~
+ with~a~command~that~already~has~a~definition. \\ \\
+ The~existing~definition~of~'#1'~will~not~be~altered.
+ }
+\msg_new:nnnn { cmd } { command-not-yet-defined }
+ { Command ~'#1'~not~yet~defined! }
+ {
+ You~have~used~#2~
+ with~a~command~that~was~never~defined.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { environment-already-defined }
+ { Environment~'#1'~already~defined! }
+ {
+ You~have~used~\NewDocumentEnvironment
+ with~an~environment~that~already~has~a~definition. \\ \\
+ The~existing~definition~of~'#1'~will~not~be~altered.
+ }
+\msg_new:nnnn { cmd } { environment-not-yet-defined }
+ { Environment~'#1'~not~yet~defined! }
+ {
+ You~have~used~\RenewDocumentEnvironment
+ with~an~environment~that~was~never~defined.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { expandable-ending-optional }
+ {
+ Argument~specification~'#2'~for~expandable~command~'#1'~
+ ends~with~optional~argument.
+ }
+ {
+ Expandable~commands~must~have~a~final~mandatory~argument~
+ (or~no~arguments~at~all).~You~cannot~have~a~terminal~optional~
+ argument~with~expandable~commands.
+ }
+\msg_new:nnnn { cmd } { inconsistent-long }
+ { Inconsistent~long~arguments~for~expandable~command~'#1'. }
+ {
+ The~arguments~for~an~expandable~command~must~not~involve~short~
+ arguments~after~long~arguments.~You~have~tried~to~mix~the~two~types.
+ }
+\msg_new:nnnn { cmd } { invalid-command-arg }
+ { Argument~type~'#2'~not~available~for~#1. }
+ {
+ The~letter~'#2'~can~only~be~used~in~environment~argument~
+ specifications,~not~for~commands.
+ \\ \\
+ LaTeX~will~ignore~this~entire~definition.
+ }
+\msg_new:nnnn { cmd } { invalid-expandable-argument-type }
+ { Argument~type~'#2'~not~available~for~expandable~command~'#1'. }
+ {
+ The~letter~'#2'~specifies~an~argument~type~which~cannot~be~used~
+ in~an~expandable~command.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { invalid-after-optional-expandably }
+ {
+ Argument~type~'#2'~not~available~after~optional~argument~
+ for~expandable~command~'#1'.
+ }
+ {
+ The~letter~'#2'~specifies~an~argument~type~which~cannot~be~used~
+ in~an~expandable~command~after~an~optional~argument.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { non-trailing-obey-spaces }
+ { Prefix~'!'~used~before~mandatory~argument~'#2'~of~#1. }
+ {
+ The~prefix~'!'~can~only~apply~to~trailing~optional~arguments.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { not-definable }
+ { First~argument~of~'#2'~must~be~a~command. }
+ {
+ The~first~argument~of~'#2'~should~be~the~document~command~that~will~
+ be~defined.~The~provided~argument~'#1'~is~a~character.~Perhaps~a~
+ backslash~is~missing?
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { not-one-token }
+ { First~argument~of~'#2'~must~be~a~command. }
+ {
+ The~first~argument~of~'#2'~should~be~the~document~command~that~will~
+ be~defined.~The~provided~argument~'#1'~contains~more~than~one~
+ token.~Perhaps~a~backslash~is~missing?
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { not-single-token }
+ {
+ Argument~delimiter~'#2'~for~the~#1~should~be~
+ a~single~non-space~token.
+ }
+ {
+ The~argument~specification~provided~was~not~valid:~in~a~place~
+ where~a~single~token~is~required,~LaTeX~found~'#2'.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { forbidden-implicit-group-token }
+ { Argument~delimiter~'#2'~for~the~#1~is~not~allowed. }
+ {
+ The~argument~specification~provided~was~not~valid:~the~implicit~
+ #3-group~token~'#2'~is~not~allowed~as~an~argument~delimiter.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { processor-in-expandable }
+ { Argument~processor~'>{#2}'~cannot~be~used~for~the~expandable~command~'#1'. }
+ {
+ The~argument~specification~for~#1~contains~a~processor~function:~
+ this~is~only~supported~for~standard~robust~commands.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { too-many-arguments }
+ { Too~many~arguments~in~argument~specification~'#2'~of~#1. }
+ {
+ The~argument~specification~provided~has~more~than~9~arguments.~
+ This~cannot~be~implemented.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { two-markers }
+ { Two~'#2'~apply~to~the~same~argument~in~argument~specification~of~#1. }
+ {
+ The~argument~specification~provided~has~two~markers~'#2'~applying~
+ to~the~same~argument;~these~are~redundant.
+ }
+\msg_new:nnnn { cmd } { unknown-argument-type }
+ { Unknown~argument~type~'#2'~for~the~#1. }
+ {
+ The~letter~'#2'~does~not~specify~a~known~argument~type.
+ \c_@@_ignore_def_tl
+ }
+\msg_new:nnnn { cmd } { xparse-argument-type }
+ { Deprecated~argument~type~'#2'~for~the~#1~requires~xparse. }
+ {
+ The~letter~'#2'~specifies~a~known~argument~type~that~requires~
+ the~xparse~package.
+ \c_@@_ignore_def_tl
+ }
+% \end{macrocode}
+%
+% Errors when using commands/environments. The \texttt{if-boolean}
+% message is always used in expandable errors. The
+% \texttt{loop-in-defaults} and \texttt{missing-required} messages can
+% be expandable or not expandable.
+% \begin{macrocode}
+\msg_new:nnn { cmd } { if-boolean }
+ { Invalid~use~\iow_char:N\\IfBooleanTF~{#1} }
+\msg_new:nnnn { cmd } { loop-in-defaults }
+ { Defaults~of~#1~have~circular~dependency. }
+ {
+ The~default~values~of~two~or~more~arguments~of~the~#1~
+ depend~on~each~other~in~a~way~that~cannot~be~resolved.
+ }
+\msg_new:nnnn { cmd } { missing-required }
+ { Missing~required~argument~for~#1. }
+ {
+ The~current~#1~expects~an~argument~starting~with~'#2'.~
+ LaTeX~did~not~find~it,~and~will~insert~a~default~value~to~be~processed.
+ }
+\msg_new:nnnn { cmd } { non-xparse }
+ { \str_uppercase:n #1~not~defined~using~xparse. }
+ {
+ You~have~asked~for~the~argument~specification~for~the~#1,~
+ but~this~was~not~defined~using~xparse.
+ }
+\msg_new:nnnn { cmd } { split-excess-tokens }
+ { Too~many~'#1'~tokens~when~trying~to~split~argument. }
+ {
+ LaTeX~was~asked~to~split~the~input~'#3'~
+ at~each~occurrence~of~the~token~'#1',~up~to~a~maximum~of~#2~parts.~
+ There~were~too~many~'#1'~tokens.
+ }
+\msg_new:nnnn { cmd } { unknown }
+ { Unknown~document~#1. }
+ {
+ You~have~asked~for~the~argument~specification~for~the~#1,~
+ but~it~is~not~defined.
+ }
+\msg_new:nnnn { cmd } { verbatim-newline }
+ { Verbatim~argument~of~#1~ended~by~end~of~line. }
+ {
+ The~verbatim~argument~of~the~#1~cannot~contain~more~than~one~line,~
+ but~the~end~
+ of~the~current~line~has~been~reached.~You~may~have~forgotten~the~
+ closing~delimiter.
+ \\ \\
+ LaTeX~will~ignore~'#2'.
+ }
+\msg_new:nnnn { cmd } { verbatim-tokenized }
+ { The~verbatim~#1~cannot~be~used~inside~an~argument. }
+ {
+ The~#1~takes~a~verbatim~argument.~
+ It~may~not~appear~within~the~argument~of~another~function.~
+ It~received~an~illegal~token \tl_if_empty:nF {#3} { ~'#3' } .
+ \\ \\
+ LaTeX~will~ignore~'#2'.
+ }
+% \end{macrocode}
+%
+% Intended more for information.
+% \begin{macrocode}
+\msg_new:nnn { cmd } { define-command }
+ {
+ Defining~command~#1~
+ with~sig.~'#2'~\msg_line_context:.
+ }
+\msg_new:nnn { cmd } { define-environment }
+ {
+ Defining~environment~'#1'~
+ with~sig.~'#2'~\msg_line_context:.
+ }
+\msg_new:nnn { cmd } { redefine-command }
+ {
+ Redefining~command~#1~
+ with~sig.~'#2'~\msg_line_context:.
+ }
+\msg_new:nnn { cmd } { redefine-environment }
+ {
+ Redefining~environment~'#1'~
+ with~sig.~'#2'~\msg_line_context:.
+ }
+\msg_new:nnn { cmd } { optional-mandatory }
+ {
+ Since~the~mandatory~argument~'#1'~has~the~same~delimiter~'#2'~
+ as~a~previous~optional~argument,~it~will~not~be~possible~to~
+ omit~all~optional~arguments~when~calling~this~command.
+ }
+\msg_new:nnn { cmd } { unsupported-let }
+ {
+ The~command~'#1'~was~undefined~but~not~the~associated~commands~
+ '#1~code'~and/or~'#1~defaults'.~Maybe~you~tried~using~
+ \iow_char:N\\let.~This~may~lead~to~an~infinite~loop.
+ }
+% \end{macrocode}
+%
+% \subsection{User functions}
+%
+% The user functions are more or less just the internal functions
+% renamed.
+%
+% \begin{macro}{\BooleanFalse}
+% \begin{macro}{\BooleanTrue}
+% Design-space names for the Boolean values.
+% \begin{macrocode}
+\cs_new_eq:NN \BooleanFalse \c_false_bool
+\cs_new_eq:NN \BooleanTrue \c_true_bool
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\NewDocumentCommand}
+% \begin{macro}{\RenewDocumentCommand}
+% \begin{macro}{\ProvideDocumentCommand}
+% \begin{macro}{\DeclareDocumentCommand}
+% The user macros are pretty simple wrappers around the internal ones.
+% There is however a check that the first argument is a single token,
+% possibly surrounded by spaces (hence the strange \cs{use:nnn}), and
+% is definable.
+% \begin{macrocode}
+\cs_new_protected:Npn \NewDocumentCommand #1#2#3
+ {
+ \@@_check_definable:nNT {#1} \NewDocumentCommand
+ {
+ \cs_if_exist:NTF #1
+ {
+ \msg_error:nnxx { cmd } { command-already-defined }
+ { \use:nnn \token_to_str:N #1 { } }
+ { \token_to_str:N \NewDocumentCommand }
+ }
+ { \@@_declare_cmd:Nnn #1 {#2} {#3} }
+ }
+ }
+\cs_new_protected:Npn \RenewDocumentCommand #1#2#3
+ {
+ \@@_check_definable:nNT {#1} \RenewDocumentCommand
+ {
+ \cs_if_exist:NTF #1
+ { \@@_declare_cmd:Nnn #1 {#2} {#3} }
+ {
+ \msg_error:nnxx { cmd } { command-not-yet-defined }
+ { \use:nnn \token_to_str:N #1 { } }
+ { \token_to_str:N \RenewDocumentCommand }
+ }
+ }
+ }
+\cs_new_protected:Npn \ProvideDocumentCommand #1#2#3
+ {
+ \@@_check_definable:nNT {#1} \ProvideDocumentCommand
+ { \cs_if_exist:NF #1 { \@@_declare_cmd:Nnn #1 {#2} {#3} } }
+ }
+\cs_new_protected:Npn \DeclareDocumentCommand #1#2#3
+ {
+ \@@_check_definable:nNT {#1} \DeclareDocumentCommand
+ { \@@_declare_cmd:Nnn #1 {#2} {#3} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\NewDocumentEnvironment}
+% \begin{macro}{\RenewDocumentEnvironment}
+% \begin{macro}{\ProvideDocumentEnvironment}
+% \begin{macro}{\DeclareDocumentEnvironment}
+% Very similar for environments.
+% \begin{macrocode}
+\cs_new_protected:Npn \NewDocumentEnvironment #1#2#3#4
+ {
+ \cs_if_exist:cTF {#1}
+ { \msg_error:nnx { cmd } { environment-already-defined } {#1} }
+ { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
+ }
+\cs_new_protected:Npn \RenewDocumentEnvironment #1#2#3#4
+ {
+ \cs_if_exist:cTF {#1}
+ { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
+ { \msg_error:nnx { cmd } { environment-not-yet-defined } {#1} }
+ }
+\cs_new_protected:Npn \ProvideDocumentEnvironment #1#2#3#4
+ { \cs_if_exist:cF {#1} { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} } }
+\cs_new_protected:Npn \DeclareDocumentEnvironment #1#2#3#4
+ { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\NewExpandableDocumentCommand}
+% \begin{macro}{\RenewExpandableDocumentCommand}
+% \begin{macro}{\ProvideExpandableDocumentCommand}
+% \begin{macro}{\DeclareExpandableDocumentCommand}
+% The expandable versions are essentially the same as the basic
+% functions. The strange \cs{use:nnn} is there in case |#1| is
+% surrounded with spaces, as can happen with usual document catcodes
+% in \cs{RenewExpandableDocumentCommand} |{| |\!| |}| \ldots{}
+% \begin{macrocode}
+\cs_new_protected:Npn \NewExpandableDocumentCommand #1#2#3
+ {
+ \@@_check_definable:nNT {#1} \NewExpandableDocumentCommand
+ {
+ \cs_if_exist:NTF #1
+ {
+ \msg_error:nnxx { cmd } { command-already-defined }
+ { \use:nnn \token_to_str:N #1 { } }
+ { \token_to_str:N \NewExpandableDocumentCommand }
+ }
+ { \@@_declare_expandable_cmd:Nnn #1 {#2} {#3} }
+ }
+ }
+\cs_new_protected:Npn \RenewExpandableDocumentCommand #1#2#3
+ {
+ \@@_check_definable:nNT {#1} \RenewExpandableDocumentCommand
+ {
+ \cs_if_exist:NTF #1
+ { \@@_declare_expandable_cmd:Nnn #1 {#2} {#3} }
+ {
+ \msg_error:nnxx { cmd } { command-not-yet-defined }
+ { \use:nnn \token_to_str:N #1 { } }
+ { \token_to_str:N \RenewExpandableDocumentCommand }
+ }
+ }
+ }
+\cs_new_protected:Npn \ProvideExpandableDocumentCommand #1#2#3
+ {
+ \@@_check_definable:nNT {#1} \ProvideExpandableDocumentCommand
+ {
+ \cs_if_exist:NF #1
+ { \@@_declare_expandable_cmd:Nnn #1 {#2} {#3} }
+ }
+ }
+\cs_new_protected:Npn \DeclareExpandableDocumentCommand #1#2#3
+ {
+ \@@_check_definable:nNT {#1} \DeclareExpandableDocumentCommand
+ { \@@_declare_expandable_cmd:Nnn #1 {#2} {#3} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\IfBooleanT, \IfBooleanF, \IfBooleanTF}
+% The logical \meta{true} and \meta{false} statements are just the
+% normal \cs{c_true_bool} and \cs{c_false_bool} so \cs{bool_if:NTF} is
+% almost enough. However, this code-level function blows up badly
+% when passed invalid input. We want \cs{IfBooleanTF} to accept a
+% single (non-space) token equal to \cs{c_true_bool} or
+% \cs{c_false_bool}, possibly surrounded by spaces. If the input is
+% blank or multiple items, jump to the error and pick the false
+% branch. If the input, ignoring spaces (we do this by omitting
+% braces in the \cs{tl_if_single_token:nF} test), is not a single
+% token then jump to the error as well. It is then safe to compare
+% the token to the two booleans, picking the appropriate branch. If
+% neither matches, we jump to the error as well.
+% \begin{macrocode}
+\cs_new:Npn \IfBooleanTF #1
+ {
+ \tl_if_single:nF {#1}
+ { \prg_break:n { \use:n } }
+ \tl_if_single_token:nF #1
+ { \prg_break:n { \use:n } }
+ \token_if_eq_meaning:NNT #1 \c_true_bool
+ { \prg_break:n { \use_ii:nnn } }
+ \token_if_eq_meaning:NNT #1 \c_false_bool
+ { \prg_break:n { \use_iii:nnn } }
+ \prg_break:n { \use:n }
+ \prg_break_point:
+ {
+ \msg_expandable_error:nnn { cmd } { if-boolean } {#1}
+ \use_ii:nn
+ }
+ }
+\cs_new:Npn \IfBooleanT #1#2 { \IfBooleanTF {#1} {#2} { } }
+\cs_new:Npn \IfBooleanF #1 { \IfBooleanTF {#1} { } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\IfNoValueT, \IfNoValueF, \IfNoValueTF}
+% Simple re-naming.
+% \begin{macrocode}
+\cs_new_eq:NN \IfNoValueF \tl_if_novalue:nF
+\cs_new_eq:NN \IfNoValueT \tl_if_novalue:nT
+\cs_new_eq:NN \IfNoValueTF \tl_if_novalue:nTF
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\IfValueT, \IfValueF, \IfValueTF}
+% Inverted logic.
+% \begin{macrocode}
+\cs_new:Npn \IfValueF { \tl_if_novalue:nT }
+\cs_new:Npn \IfValueT { \tl_if_novalue:nF }
+\cs_new:Npn \IfValueTF #1#2#3 { \tl_if_novalue:nTF {#1} {#3} {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ProcessedArgument}
+% Processed arguments are returned using this name, which is reserved
+% here although the definition will change.
+% \begin{macrocode}
+\tl_new:N \ProcessedArgument
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ReverseBoolean, \SplitArgument, \SplitList, \TrimSpaces}
+% Simple copies.
+% \begin{macrocode}
+\cs_new_eq:NN \ReverseBoolean \@@_bool_reverse:N
+\cs_new_eq:NN \SplitArgument \@@_split_argument:nnn
+\cs_new_eq:NN \SplitList \@@_split_list:nn
+\cs_new_eq:NN \TrimSpaces \@@_trim_spaces:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ProcessList}
+% To support \cs{SplitList}.
+% \begin{macrocode}
+\cs_new_eq:NN \ProcessList \tl_map_function:nN
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\GetDocumentCommandArgSpec}
+% \begin{macro}{\GetDocumentEnvironmentArgSpec}
+% \begin{macro}{\ShowDocumentCommandArgSpec}
+% \begin{macro}{\ShowDocumentEnvironmentArgSpec}
+% More simple mappings, with a check that the argument is a single
+% control sequence or active character.
+% \begin{macrocode}
+\cs_new_protected:Npn \GetDocumentCommandArgSpec #1
+ {
+ \@@_check_definable:nNT {#1} \GetDocumentCommandArgSpec
+ { \@@_get_arg_spec:N #1 }
+ }
+\cs_new_eq:NN \GetDocumentEnvironmentArgSpec \@@_get_arg_spec:n
+\cs_new_protected:Npn \ShowDocumentCommandArgSpec #1
+ {
+ \@@_check_definable:nNT {#1} \ShowDocumentCommandArgSpec
+ { \@@_show_arg_spec:N #1 }
+ }
+\cs_new_eq:NN \ShowDocumentEnvironmentArgSpec \@@_show_arg_spec:n
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% Finally as promised, restore \cs{__kernel_chk_if_free_cs:N}:
+% \begin{macrocode}
+%<latexrelease>\cs_gset_eq:NN \__kernel_chk_if_free_cs:N \@@_chk_if_free_cs:N
+%<latexrelease>\cs_undefine:N \@@_chk_if_free_cs:N
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{0000/00/00}{ltcmd}%
+%<latexrelease> {Document~command~parser}%
+%<latexrelease>
+%<latexrelease>\EndModuleRelease
+\ExplSyntaxOff
+%<latexrelease>\@ifundefined{ExplSyntaxOff}{}{\latexrelease@postexpl}
+%<latexrelease>\catcode`\^^@=\@latexrelease@catcode@null\relax
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% We need to stop DocStrip treating |@@| in a special way at this point.
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \Finale
diff --git a/macros/latex/base/ltcmdhooks-code.pdf b/macros/latex/base/ltcmdhooks-code.pdf
new file mode 100644
index 0000000000..e29001cf29
--- /dev/null
+++ b/macros/latex/base/ltcmdhooks-code.pdf
Binary files differ
diff --git a/macros/latex/base/ltcmdhooks-code.tex b/macros/latex/base/ltcmdhooks-code.tex
new file mode 100644
index 0000000000..e54dcf10d8
--- /dev/null
+++ b/macros/latex/base/ltcmdhooks-code.tex
@@ -0,0 +1,4 @@
+% this will typeset documentation + code
+
+\AtBeginDocument{\AlsoImplementation}
+\input{ltcmdhooks.dtx}
diff --git a/macros/latex/base/ltcmdhooks-doc.pdf b/macros/latex/base/ltcmdhooks-doc.pdf
new file mode 100644
index 0000000000..1dd0937d57
--- /dev/null
+++ b/macros/latex/base/ltcmdhooks-doc.pdf
Binary files differ
diff --git a/macros/latex/base/ltcmdhooks-doc.tex b/macros/latex/base/ltcmdhooks-doc.tex
new file mode 100644
index 0000000000..1efae5f229
--- /dev/null
+++ b/macros/latex/base/ltcmdhooks-doc.tex
@@ -0,0 +1,6 @@
+% this will typeset only documentation but not the code
+
+\AtBeginDocument{\OnlyDescription
+ \let\tableofcontents\relax
+ }
+\input{ltcmdhooks.dtx}
diff --git a/macros/latex/base/ltcmdhooks.dtx b/macros/latex/base/ltcmdhooks.dtx
new file mode 100644
index 0000000000..40cd55e52c
--- /dev/null
+++ b/macros/latex/base/ltcmdhooks.dtx
@@ -0,0 +1,1094 @@
+% \iffalse meta-comment
+%
+%% File: ltcmdhooks.dtx (C) Copyright 2020-2021
+%% Frank Mittelbach, Phelype Oleinik, LaTeX Team
+%
+% 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
+%
+%
+%%% From File: ltcmdhooks.dtx
+%
+\def\ltcmdhooksversion{v1.0b}
+\def\ltcmdhooksdate{2021/05/26}
+%
+%
+%
+%<*driver>
+\documentclass{l3doc}
+%\usepackage{ltcmdhooks}
+\makeatletter
+\providecommand\footref[1]{%
+ \begingroup
+ \unrestored@protected@xdef\@thefnmark{\ref{#1}}%
+ \endgroup
+ \@footnotemark}
+\makeatother
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{ltcmdhooks.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+%
+% \providecommand\hook[1]{\texttt{#1}}
+% \providecommand\fmi[1]{\marginpar{\footnotesize FMi: #1}}
+% \providecommand\pho[1]{\marginpar{\footnotesize PhO: #1}}
+% \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\
+% Project.}}
+% \author{Frank Mittelbach \and Phelype Oleinik}
+%
+% \maketitle
+%
+%
+% \tableofcontents
+%
+%
+% \section{Introduction}
+%
+% This file implements generic hooks for (arbitrary) commands.
+% In theory every command \tn[no-index]{\meta{name}} offers now two
+% associated hooks to which code can be added using \tn{AddToHook}
+% or \tn{AddToHookNext}.\footnote{In practice this is not supported
+% for all types of commands, see section~\ref{sec:look-ahead} for
+% the restrictions that apply and what happens if one tries to use
+% this with commands for which this is not supported.} These are
+% \begin{description}
+% \item[\hook{cmd/\meta{name}/before}]
+%
+% This hook is executed at the very start of the command
+% execution after its arguments (if any) are parsed. The hook
+% \meta{code} is wrapped in the command inside a call to
+% \cs{UseHook}|{cmd/|\meta{name}|/before}|, so the arguments
+% passed to the command are \emph{not} available in the hook
+% \meta{code}.
+%
+% \item[\hook{cmd/\meta{name}/after}]
+%
+% This hook is similar to \hook{cmd/\meta{name}/before}, but it is
+% executed at the very end of the command body. This hook is
+% implemented as a reversed hook.
+% \end{description}
+%
+% The hooks are not physically present before
+% \verb=\begin{document}= (i.e., using a command in the preamble
+% will never execute them) and if nobody has declared any code for
+% them, then they are not added to the command code ever. For
+% example, if we have the following definition
+%\begin{verbatim}
+% \newcommand\foo[2]{Code #1 for #2!}
+%\end{verbatim}
+% then executing \verb=\foo{A}{B}= will simply run
+% \verb*=Code A for B!=
+% as it was always the case. However, if somebody, somewhere (e.g.,
+% in a package) adds
+%\begin{verbatim}
+% \AddToHook{cmd/foo/before}{<before code>}
+%\end{verbatim}
+% then, after |\begin{document}| the definition of \cs[no-index]{foo} will be:
+%\begin{verbatim}
+% \renewcommand\foo[2]{\UseHook{cmd/foo/before}Code #1 for #2!}
+%\end{verbatim}
+% and similarly \verb=\AddToHook{cmd/foo/after}{<after code>}=
+% alters the definition to
+%\begin{verbatim}
+% \renewcommand\foo[2]{Code #1 for #2!\UseHook{cmd/foo/after}}
+%\end{verbatim}
+%
+% In other words, the mechanism is similar to what \pkg{etoolbox}
+% offers with \tn{pretocmd} and \tn{apptocmd} with the important
+% differences
+% \begin{itemize}
+% \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
+%
+% \item
+%
+% and that by using the hook management interface it is now
+% possible to define how the code chunks added in these places
+% are ordered, if different packages want to add code at these
+% points.
+%
+% \end{itemize}
+%
+%
+%
+%
+% \section{Restrictions and Operational details}
+% \label{sec:restrictions}
+%
+% Adding arbitrary material to commands is tricky because most of the
+% time we do not know what the macro expects as arguments when expanding
+% and \TeX{} doesn't have a reliable way to see that, so some guesswork
+% has to be employed.
+%
+% \subsection{Patching}
+%
+% The code here tries to find out if a command was defined with
+% \tn{newcommand} or \tn{DeclareRobustCommand} or
+% \tn{NewDocumentCommand}, and if so it \emph{assumes} that the argument
+% specification of the command is as expected (which is not fail-proof,
+% if someone redefines the internals of these commands in devious ways,
+% but is a reasonable assumption).
+%
+% If the command is one of the defined types, the code here does a
+% sandboxed expansion of the command such that it can be redefined again
+% exactly as before, but with the hook code added.
+%
+% If however the command is not a known type (it was defined with
+% \tn{def}, for example), then the code uses an approach similar to
+% \pkg{etoolbox}'s \tn{patchcmd} to retokenize the command with the hook
+% code in place. This procedure, however, is more likely to fail if the
+% catcode settings are not the same as the ones at the time of command's
+% definition, so not always adding a hook to a command will work.
+%
+% \subsubsection{Timing}
+%
+% When \cs{AddToHook} (or its \pkg{expl3} equivalent) is called with
+% a generic |cmd| hook, say, \hook{cmd/foo/before}, for the first time
+% (that is, no code was added to that same hook before), in the preamble
+% of a document, it will store a patch instruction for that command
+% until |\begin{document}|, and only then all the commands which had
+% hooks added will be patched in one go. That means that no command in
+% the preamble will have hooks patched into them.
+%
+% At |\begin{document}| all the delayed patches will be executed, and
+% if the command doesn't exist the code is still added to the hook,
+% but it will not be executed. After |\begin{document}|, when
+% \cs{AddToHook} is called with a generic |cmd| hook the first time,
+% the command will be immediately patched to include the hook, and if
+% it doesn't exist or if it can't be patched for any reason, an error
+% is thrown; if \cs{AddToHook} was already used in the preamble no new
+% patching is attempted.
+%
+% This has the consequence that a command defined or redefined after
+% |\begin{document}| only uses generic |cmd| hook code if
+% \cs{AddToHook} is called for the first time after the definition is
+% made, or if the command explicitly uses the generic hook in its
+% definition by declaring it with \cs{NewHookPair} adding \cs{UseHook} as
+% part of the code.\footnote{We might change this behavior in the main
+% document slightly after gaining some usage experience.}
+%
+%
+% \subsection{Commands that look ahead}
+% \label{sec:look-ahead}
+%
+% Some commands are defined in different ``steps'' and they look ahead
+% in the input stream to find more arguments. If you try to add some
+% code to the \hook{cmd/\meta{name}/after} hook of such command, it will
+% not work, and it is not possible to detect that programmatically, so
+% the user has to know (or find out) which commands can or cannot have
+% hooks attached to them.
+%
+% One good example is the \tn{section} command. You can add something
+% to the \hook{cmd/section/before} hook, but if you try to add something
+% to the \hook{cmd/section/after} hook, \tn{section} will no longer
+% work. That happens because the \tn{section} macro takes no argument,
+% but instead calls a few internal \LaTeX{} macros to look for the
+% optional and mandatory arguments. By adding code to the
+% \hook{cmd/section/after} hook, you get in the way of that scanning.
+%
+%
+%
+% \section{Package Author Interface}
+%
+% The \hook{cmd} hooks are, by default, available for all commands
+% that can be patched to add the hooks. For some commands, however,
+% the very beginning or the very end of the code is not the best place
+% to put the hooks, for example, if the command looks ahead for
+% arguments (see section~\ref{sec:look-ahead}).
+%
+% If you are a package author and you want to add the hooks to your
+% own commands in the proper position you can define the command and
+% manually add the \cs{UseHook} calls inside the command in the proper
+% positions, and manually define the hooks with \cs{NewHook} or
+% \cs{NewReversedHook}. When the hooks are explicitly defined,
+% patching is not attempted so you can make sure your command works
+% properly. For example, an (admittedly not really useful) command
+% that typesets its contents in a framed box with width optionally
+% given in parentheses:
+% \begin{verbatim}
+% \newcommand\fancybox{\@ifnextchar({\@fancybox}{\@fancybox(5cm)}}
+% \def\@fancybox(#1)#2{\fbox{\parbox{#1}{#2}}}
+% \end{verbatim}
+% If you try that definition, then add some code after it with
+% \begin{verbatim}
+% \AddToHook{cmd/fancybox/after}{<code>}
+% \end{verbatim}
+% and then use the \cs[no-index]{fancybox} command you will see that it
+% will be completely broken, because the hook will get executed in the
+% middle of parsing for optional \texttt{(...)} argument.
+%
+% If, on the other hand, you want to add hooks to your command you can
+% do something like:
+% \begin{verbatim}
+% \newcommand\fancybox{\@ifnextchar({\@fancybox}{\@fancybox(5cm)}}
+% \def\@fancybox(#1)#2{\fbox{%
+% \UseHook{cmd/fancybox/before}%
+% \parbox{#1}{#2}%
+% \UseHook{cmd/fancybox/after}}}
+% \NewHook{cmd/fancybox/before}
+% \NewReversedHook{cmd/fancybox/after}
+% \end{verbatim}
+% then the hooks will be executed where they should and no patching
+% will be attempted. It is important that the hooks are declared with
+% \cs{NewHook} or \cs{NewReversedHook}, otherwise the command hook
+% code will try to patch the command. Note also that the call to
+% |\UseHook{cmd/fancybox/before}| does not need to be in the
+% definition of \cs[no-index]{fancybox}, but anywhere it makes sense
+% to insert it (in this case in the internal
+% \cs[no-index]{@fancybox}).
+%
+% Alternatively, if for whatever reason your command does not support
+% the generic hooks provided here, you can disable a hook with
+% \cs{DisableHook}\footnote{Please use \cs{DisableHook} if at all, only
+% on hooks that you \enquote{own}, i.e., for commands that your
+% package or class defines and not second guess
+% whether or not hooks of other packages should get disabled!}, so
+% that when someone tries to add code to it they will get an error.
+% Or if you don't want the error, you can simply declare the hook with
+% \cs{NewHook} and never use it.
+%
+%
+% The above approach is useful for really complex commands where for
+% one or the other reason the hooks can't be placed at the very
+% beginning and end of the command body and some hand-crafting is
+% needed. However, in the example above the real (and in fact only)
+% issue is the cascading argument parsing in the style developed long
+% ago in \LaTeX~2.09. Thus, a much simpler solution for this case is
+% to replace it with the modern \cs{NewDocumentCommand} syntax and
+% define the command as follows:
+% \begin{verbatim}
+% \DeclareDocumentCommand\fancybox{D(){5cm}m}{\fbox{\parbox{#1}{#2}}}
+% \end{verbatim}
+% If you do that then both hooks automatically work and are patched
+% into the right places.
+%
+% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
+%
+%
+%
+% \section{The Implementation}
+%
+% \subsection{Execution plan}
+%
+% To add |before| and |after| hooks to a command we will need to peek
+% into the definition of a command, which is always a tricky thing to
+% do. Some cases are easy because we know how the command was defined,
+% so we can assume how its \meta{parameter text} looks like (for example
+% a command defined with \tn{newcommand} may have an optional argument
+% followed by a run of mandatory arguments), so we can just expand that
+% command and make it grab |#1|, |#2|, etc.\@ as arguments and
+% define it all back with the hooks added.
+%
+% Life's usually not that easy, so with some commands we can't do that
+% (a |#1| might as well be |#|$_{12}$|1|$_{12}$ instead of the expected
+% |#|$_{6}$|1|$_{12}$, for example) so we need to resort to ``patching''
+% the command: read its \tn{meaning}, and tokenize it again with
+% \tn{scantokens} and hope for the best.
+%
+% So the overall plan is:
+% \begin{enumerate}
+% \item
+% Check if a command is of a known type (that is, defined with
+% \tn{newcommand}\footnote{It's not always possible to reliably
+% detect this case because a command defined with no optional
+% argument is indistinguishable from a \tn{def}ed command.},
+% \cs[no-index]{DeclareRobustCommand}, or
+% \cs[no-index]{New(Expandable)DocumentCommand}), and if is, take
+% appropriate action.
+% \item
+% If the command is not a known type, we'll check if the command can
+% be patched. Two things will prevent a command from being
+% patched: if it was defined in a nonstandard catcode setting, or
+% if it is an internal expl3 command with |__|\meta{module} in its
+% name, in which case we refuse to patch.
+% \item
+% If the command was defined in nonstandard catcode settings, we
+% will try a few standard ones to try our best to carry out the
+% pathing. If this doesn't help either, the code will give up and
+% throw an error.
+% \end{enumerate}
+%
+%
+% \begin{macrocode}
+%<@@=hook>
+% \end{macrocode}
+%
+% \changes{v1.0b}{2021/05/24}{Use \cs{msg_...} instead of \cs{__kernel_msg...}}
+%
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+\ExplSyntaxOn
+%<latexrelease>\NewModuleRelease{2021/06/01}{ltcmdhooks}
+%<latexrelease> {The~hook~management~system~for~commands}
+% \end{macrocode}
+%
+% \subsection{Variables}
+%
+% \begin{macro}[int]{\g_hook_patch_action_list_tl}
+% Pairs of |\if<cmd>..\patch<cmd>| to be used with
+% \tn{robust@command@act} when looking for a known patching
+% rule. This token list is exposed because we see some future
+% applications (with very specialized packages, such as
+% \pkg{etoolbox} that may want to extend the pairs processed. It is
+% not meant for general use which is why it is not documented in
+% the interface documentation above.
+% \begin{macrocode}
+\tl_new:N \g_hook_patch_action_list_tl
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_patch_num_args_int}
+% The number of arguments in a macro being patched.
+% \begin{macrocode}
+\int_new:N \l_@@_patch_num_args_int
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_patch_prefixes_tl}
+% \begin{macro}{\l_@@_patch_param_text_tl}
+% \begin{macro}{\l_@@_patch_replacement_tl}
+% The prefixes and parameters of the definition for the macro being
+% patched.
+% \begin{macrocode}
+\tl_new:N \l_@@_patch_prefixes_tl
+\tl_new:N \l_@@_patch_param_text_tl
+\tl_new:N \l_@@_patch_replacement_tl
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_delayed_patches_prop}
+% A list containing the patches delayed to |\begin{document}|, so that
+% patching is not attempted twice.
+% \begin{macrocode}
+\prop_new:N \g_@@_delayed_patches_prop
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_patch_debug:x}
+% A helper for patching debug info.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_debug:x #1
+ { \@@_debug:n { \iow_term:x { [lthooks]~#1 } } }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Variants}
+%
+% \begin{macro}[int]{\tl_rescan:nV}
+% \pkg{expl3} function variants used throughout the code.
+% \begin{macrocode}
+\cs_generate_variant:Nn \tl_rescan:nn { nV }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Patching or delaying}
+%
+% \begin{macro}{\@@_try_put_cmd_hook:n,\@@_try_put_cmd_hook:w}
+% Before |\begin{document}| all patching is delayed.
+% This function is called from within \cs{AddToHook}, when code is
+% added to a generic |cmd| hook is newly declared. It checks whether
+% the patch position is valid, then proceeds to trying to patch or
+% delaying to |\begin{document}| if in the preamble.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_try_put_cmd_hook:n #1
+ { \@@_try_put_cmd_hook:w #1 / / / \s_@@_mark {#1} }
+\cs_new_protected:Npn \@@_try_put_cmd_hook:w
+ #1 / #2 / #3 / #4 \s_@@_mark #5
+ {
+ \@@_debug:n { \iow_term:n { ->~Adding~cmd~hook~to~'#2'~(#3): } }
+ \str_case:nnTF {#3}
+ { { before } { } { after } { } }
+ { \exp_args:Nc \@@_patch_cmd_or_delay:Nnn {#2} {#2} {#3} }
+ { \msg_error:nnnn { hooks } { wrong-cmd-hook } {#2} {#3} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_patch_cmd_or_delay:Nnn}
+% \begin{macro}{\@@_cmd_begindocument_code:}
+% In the preamble, \cs{@@_patch_cmd_or_delay:Nnn} just adds the patch
+% instruction to a property list to be executed later.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_cmd_or_delay:Nnn #1 #2 #3
+ {
+ \@@_debug:n { \iow_term:n { ->~Add~generic~cmd~hook~for~#2~(#3). } }
+ \@@_debug:n
+ { \iow_term:n { !~In~the~preamble:~delaying. } }
+ \prop_gput:Nnn \g_@@_delayed_patches_prop { #2 / #3 }
+ { \@@_cmd_try_patch:nn {#2} {#3} }
+ }
+% \end{macrocode}
+%
+% The delayed patches are added to a property list to prevent
+% duplication, and the code stored in the property list for each
+% key is executed. The function \cs{@@_patch_cmd_or_delay:Nnn} is
+% also redefined to be \cs{@@_patch_command:Nnn} so that no further
+% delaying is attempted.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_cmd_begindocument_code:
+ {
+ \cs_gset_eq:NN \@@_patch_cmd_or_delay:Nnn \@@_patch_command:Nnn
+ \prop_map_function:NN \g_@@_delayed_patches_prop { \use_ii:nn }
+ \prop_gclear:N \g_@@_delayed_patches_prop
+ \cs_undefine:N \@@_cmd_begindocument_code:
+ }
+\g@addto@macro \@kernel@after@begindocument
+ { \@@_cmd_begindocument_code: }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_cmd_try_patch:nn}
+% At |\begin{document}| tries patching the command if the hook
+% was not manually created in the meantime. If the document does not
+% exist, no error is raised here as it may hook into a package that
+% wasn't loaded. Hooks added to commands in the document body still
+% raise an error if the command is not defined.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_cmd_try_patch:nn #1 #2
+ {
+ \@@_debug:n
+ { \iow_term:x { ->~\string\begin{document}~try~cmd / #1 / #2. } }
+ \@@_if_declared:nTF { cmd / #1 / #2 }
+ {
+ \@@_debug:n
+ { \iow_term:n { .->~Giving~up:~hook~already~created. } }
+ }
+ {
+ \cs_if_exist:cT {#1}
+ { \exp_args:Nc \@@_patch_command:Nnn {#1} {#1} {#2} }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+% \subsection{Patching commands}
+%
+% \begin{macro}{\@@_patch_command:Nnn}
+% \begin{macro}{\@@_patch_check:NNnn}
+% \begin{macro}[TF]{\@@_if_public_command:N}
+% \begin{macro}{\@@_if_public_command:w}
+% \cs{@@_patch_command:Nnn} will do some sanity checks on the
+% argument to detect if it is possible to add hooks to the command,
+% and raises an error otherwise. If the command can contain hooks,
+% then it uses \tn{robust@command@act} to find out what type is the
+% command, and patch it accordingly.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_command:Nnn #1 #2 #3
+ {
+ \@@_patch_debug:x { analyzing~'\token_to_str:N #1' }
+ \@@_patch_debug:x { \token_to_str:N #1 = \token_to_meaning:N #1 }
+ \@@_patch_check:NNnn \cs_if_exist:NTF #1 { undef }
+ {
+ \@@_patch_debug:x { ++~control~sequence~is~defined }
+ \@@_patch_check:NNnn \token_if_macro:NTF #1 { macro }
+ {
+ \@@_patch_debug:x { ++~control~sequence~is~a~macro }
+ \@@_patch_check:NNnn \@@_if_public_command:NTF #1 { expl3 }
+ {
+ \@@_patch_debug:x { ++~macro~is~not~private }
+ \robust@command@act
+ \g_hook_patch_action_list_tl #1
+ \@@_retokenize_patch:Nnn { #1 {#2} {#3} }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% And here's the auxiliary used above:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_check:NNnn #1 #2 #3 #4
+ {
+ #1 #2 {#4}
+ {
+ \msg_error:nnxx { hooks } { cant-patch }
+ { \token_to_str:N #2 } {#3}
+ }
+ }
+% \end{macrocode}
+% and a conditional \cs{@@_if_public_command:N} 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.
+% \begin{macrocode}
+\use:x
+ {
+ \prg_new_protected_conditional:Npnn
+ \exp_not:N \@@_if_public_command:N ##1 { TF }
+ {
+ \exp_not:N \exp_last_unbraced:Nf
+ \exp_not:N \@@_if_public_command:w
+ { \exp_not:N \cs_to_str:N ##1 }
+ \tl_to_str:n { _ _ } \s_@@_mark
+ }
+ }
+\exp_last_unbraced:NNNNo
+\cs_new_protected:Npn \@@_if_public_command:w
+ #1 \tl_to_str:n { _ _ } #2 \s_@@_mark
+ {
+ \tl_if_empty:nTF {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+%
+%
+%
+% \subsubsection{Patching by expansion and redefinition}
+%
+% \begin{macro}[int]{\g_hook_patch_action_list_tl}
+% This is the list of known command types and the function that
+% patches the command hooks into them. The conditionals are taken
+% from \tn{ShowCommand}, \tn{NewCommandCopy} and
+% \cs{__kernel_cmd_if_xparse:NTF} defined in \texttt{ltcmd}.
+% \begin{macrocode}
+\tl_gset:Nn \g_hook_patch_action_list_tl
+ {
+ { \@if@DeclareRobustCommand \@@_patch_DeclareRobustCommand:Nnn }
+ { \@if@newcommand \@@_patch_newcommand:Nnn }
+ { \__kernel_cmd_if_xparse:NTF \@@_cmd_patch_xparse:Nnn }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\@@_patch_DeclareRobustCommand:Nnn}
+% At this point we know that the commands can be patched by expanding
+% then redefining. These are the cases of commands defined with
+% \tn{newcommand} with an optional argument or with
+% \tn{DeclareRobustCommand}.
+%
+% With \cs{@@_patch_DeclareRobustCommand:Nnn} we check if the command
+% has an optional argument (with a test counter-intuitively called
+% \tn{@if@newcommand}). If so, we forward the action to
+% \cs{@@_patch_newcommand:Nnn}, otherwise call the patching engine
+% \cs{@@_patch_expand_redefine:NNnn} with a \cs{c_false_bool} to
+% indicate that there is no optional argument.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_DeclareRobustCommand:Nnn #1
+ {
+ \exp_args:Nc \@if@newcommand { \cs_to_str:N #1 ~ }
+ { \exp_args:Nc \@@_patch_newcommand:Nnn }
+ { \exp_args:NNc \@@_patch_expand_redefine:NNnn \c_false_bool }
+ { \cs_to_str:N #1 ~ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_patch_newcommand:Nnn}
+% If the command was defined with \tn{newcommand} and an optional
+% argument, call the patching engine with a \cs{c_true_bool} to flag
+% the presence of an optional argument, and with
+% \cs[no-index]{\string\command} to patch the actual code for
+% \cs[no-index]{command}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_newcommand:Nnn #1
+ {
+ \exp_args:NNc \@@_patch_expand_redefine:NNnn \c_true_bool
+ { \c_backslash_str \cs_to_str:N #1 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_cmd_patch_xparse:Nnn}
+% And for commands defined by the \pkg{xparse} commands use this
+% for patching:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_cmd_patch_xparse:Nnn #1
+ {
+ \exp_args:NNc \@@_patch_expand_redefine:NNnn \c_false_bool
+ { \cs_to_str:N #1 ~ code }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\@@_patch_expand_redefine:NNnn}
+% \begin{macro}[EXP]{\@@_make_prefixes:w}
+% Now the real action begins. Here we have in |#1| a boolean
+% indicating if the command has a |[|\ldots|]|-delimited argument, in
+% |#2| the command control sequence, in |#3| the name of the command
+% (note that |#1|${}\ne{}$|\csname#2\endcsname| at this point!), and
+% in |#4| the hook position, either |before| or |after|.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_expand_redefine:NNnn #1 #2 #3 #4
+ {
+ \@@_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
+% 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
+ \bool_if:NT #1 { -1 }
+ }
+% \end{macrocode}
+% Now build two token lists:
+% \begin{description}
+% \item[\cs{l_@@_patch_param_text_tl}] will contain the
+% \meta{parameter text} to be used when redefining the macro. It
+% should be identical to the \meta{parameter text} used when
+% originally defining that macro.
+% \item[\cs{l_@@_patch_replacement_tl}] will contain braced pairs of
+% |#|$_{12}$\meta{num} to feed to the macro when expanded. This
+% token list as well as the previous will have the first item
+% surrounded by |[|\ldots|]| in the case of an optional argument.
+% \end{description}
+% \begin{macrocode}
+ \int_compare:nNnTF { \l_@@_patch_num_args_int } > { \c_zero_int }
+ {
+ \tl_set:Nx \l_@@_patch_param_text_tl
+ { \bool_if:NTF #1 { [####1] } { ####1 } }
+ \tl_set:Nx \l_@@_patch_replacement_tl
+ { \bool_if:NTF #1 { [####1] } { {####1} } }
+ \int_step_inline:nnn { 2 } { \l_@@_patch_num_args_int }
+ {
+ \tl_put_right:Nn \l_@@_patch_param_text_tl { ## ####1 }
+ \tl_put_right:Nn \l_@@_patch_replacement_tl { { ## ####1 } }
+ }
+ }
+ {
+ \tl_clear:N \l_@@_patch_param_text_tl
+ \tl_clear:N \l_@@_patch_replacement_tl
+ }
+% \end{macrocode}
+% Finally, before redefining, we need to also get the prefixes used
+% when defining the command. Here we ensure that the \tn{escapechar}
+% is printable, otherwise a macro defined with prefixes
+% |\protected \long| will have it \tn{meaning} printed as
+% |protectedlong|, making life unnecessarily complicated. Here the
+% \tn{escapechar} is changed to |/|, then we loop between pairs of
+% |/|\ldots|/| extracting the prefixes.
+% \begin{macrocode}
+ \group_begin:
+ \int_set:Nn \tex_escapechar:D { `\/ }
+ \use:x
+ {
+ \group_end:
+ \tl_set:Nx \exp_not:N \l_@@_patch_prefixes_tl
+ { \exp_not:N \@@_make_prefixes:w \cs_prefix_spec:N #2 / / }
+ }
+% \end{macrocode}
+% Now that all the needed tools are ready, without further ado we'll
+% redefine the command |#2|. The definition uses the prefixes
+% gathered in \cs{l_@@_patch_prefixes_tl}, a primitive \cs{tex_def:D}
+% to avoid adding extra prefixes, and the \meta{parameter text} from
+% \cs{l_@@_patch_param_text_tl}.
+%
+% Then finally, in the body of the definition, we insert
+% \hook{cmd/\#3/before} if |#4| is |before|, the code of the
+% command expanded once grabbing the parameters in
+% \cs{l_@@_patch_replacement_tl}, and \hook{cmd/\#3/after} if |#4| is
+% |after|.
+% \begin{macrocode}
+ \use:x
+ {
+ \l_@@_patch_prefixes_tl \tex_def:D
+ \exp_not:N #2 \exp_not:V \l_@@_patch_param_text_tl
+ {
+ \str_if_eq:nnT {#4} { before }
+ { \exp_not:N \UseHook { cmd / #3 / #4 } }
+ \exp_args:No \exp_not:o
+ { \exp_after:wN #2 \l_@@_patch_replacement_tl }
+ \str_if_eq:nnT {#4} { after }
+ { \exp_not:N \UseHook { cmd / #3 / #4 } }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% Here's the auxiliary that makes the prefix control sequences for the
+% redefinition. Each item has to be \cs{tl_trim_spaces:n}'d because
+% the last item (and not any other) has a trailing space.
+% \begin{macrocode}
+\cs_new:Npn \@@_make_prefixes:w / #1 /
+ {
+ \tl_if_empty:nF {#1}
+ {
+ \exp_not:c { tex_ \tl_trim_spaces:n {#1} :D }
+ \@@_make_prefixes:w /
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+%
+%
+% \subsubsection{Patching by retokenization}
+%
+% At this point we've drained the possibilities of patching a command by
+% expansion-and-redefinition, so we have to resort to patching by
+% retokenizing the command. Patching by retokenization is done by
+% getting the \tn{meaning} of the command, doing the necessary
+% manipulations on the generated string, and the retokenizing that again
+% by using \tn{scantokens}.
+%
+% Patching by retokenization is definitely a riskier business, because
+% it relies that the tokens printed by \tn{meaning} produce the exact
+% same tokens as the ones in the original definition. That is, the
+% catcode régime must be exactly(ish) the same, and there is no way of
+% telling except by trial and error.
+%
+% \begin{macro}{\@@_retokenize_patch:Nnn}
+% This is the macro that will control the whole process. First we'll
+% try out one final, rather trivial case, of a command with no
+% arguments; that is, a token list. This case can be patched with
+% the expand-and-redefine routine but it has to be the very last case
+% tested for, because most (all?) robust commands start with a
+% 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{@@_patch_expand_redefine:NNnn}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_retokenize_patch:Nnn #1 #2 #3
+ {
+ \@@_patch_debug:x { ..~command~can~only~be~patched~by~rescanning }
+ \str_if_eq:eeTF { \cs_argument_spec:N #1 } { }
+ { \@@_patch_expand_redefine:NNnn \c_false_bool #1 {#2} {#3} }
+ {
+% \end{macrocode}
+%
+% Otherwise, we start the actual patching by retokenization job. The
+% code calls \cs{@@_try_patch_with_catcodes:Nnnnw} with a different
+% catcode setting:
+% \begin{itemize}
+% \item The current catcode setting;
+% \item Switching the catcode of |@|;
+% \item Switching the \pkg{expl3} syntax on or off;
+% \item Both of the above.
+% \end{itemize}
+%
+% If patching succeeds, \cs{@@_try_patch_with_catcodes:Nnnnw} has the
+% side-effect of patching the macro |#1| (which may be an internal
+% from the command whose name is~|#2|).
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpa_tl
+ {
+ \int_compare:nNnTF { \char_value_catcode:n {`\@ } } = { 12 }
+ { \exp_not:N \makeatletter } { \exp_not:N \makeatother }
+ }
+ \tl_set:Nx \l_@@_tmpb_tl
+ {
+ \bool_if:NTF \l__kernel_expl_bool
+ { \ExplSyntaxOff } { \ExplSyntaxOn }
+ }
+ \use:x
+ {
+ \exp_not:N \@@_try_patch_with_catcodes:Nnnnw
+ \exp_not:n { #1 {#2} {#3} }
+ { \prg_do_nothing: }
+ { \exp_not:V \l_@@_tmpa_tl } % @
+ { \exp_not:V \l_@@_tmpb_tl } % _:
+ {
+ \exp_not:V \l_@@_tmpa_tl % @
+ \exp_not:V \l_@@_tmpb_tl % _:
+ }
+ }
+ \q_recursion_tail \q_recursion_stop
+% \end{macrocode}
+%
+% If no catcode setting succeeds, give up and raise an error. The
+% command isn't changed in any way in that case.
+% \begin{macrocode}
+ {
+ \msg_error:nnxx { hooks } { cant-patch }
+ { \c_backslash_str #2 } { retok }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_try_patch_with_catcodes:Nnnnw}
+% This function is a simple wrapper around
+% \cs{@@_cmd_if_scanable:NnTF} and \cs{@@_patch_retokenize:Nnnn} if
+% the former returns \meta{true}, plus some debug messages.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_try_patch_with_catcodes:Nnnnw #1 #2 #3 #4
+ {
+ \quark_if_recursion_tail_stop_do:nn {#4} { \use:n }
+ \@@_patch_debug:x { ++~trying~to~patch~by~retokenization }
+ \@@_cmd_if_scanable:NnTF {#1} {#4}
+ {
+ \@@_patch_debug:x { ++~macro~can~be~retokenized~cleanly }
+ \@@_patch_debug:x { ==~retokenizing~macro~now }
+ \@@_patch_retokenize:Nnnn #1 {#2} {#3} {#4}
+ \use_i_delimit_by_q_recursion_stop:nw \use_none:n
+ }
+ {
+ \@@_patch_debug:x { --~macro~cannot~be~retokenized~cleanly }
+ \@@_try_patch_with_catcodes:Nnnnw #1 {#2} {#3}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}[int]{\kerneltmpDoNotUse}
+% This is an oddity required to be safe (as safe as reasonably
+% possible) when patching the command. The entirety of
+% \begin{quote}
+% \meta{prefixes} \tn{def} \meta{cs} \meta{parameter text}
+% |{|\meta{replacement text}|}|
+% \end{quote}
+% will go through \tn{scantokens}. The \meta{parameter text} and
+% \meta{replacement text} are what we are trying to retokenize, so not
+% much worry there. The other items, however, should ``just work'',
+% so some care is needed to not use too fancy catcode settings.
+% Therefore we can't use an \pkg{expl3}-named macro for \meta{cs}, nor
+% the \pkg{expl3} versions of \tn{def} or the \meta{prefixes}.
+% That is why the definitions that will eventually go into
+% \tn{scantokens} will use the oddly (but hopefully clearly)-named
+% \cs{kerneltmpDoNotUse}:
+% \begin{macrocode}
+\cs_new_eq:NN \kerneltmpDoNotUse !
+% \end{macrocode}
+% \phoinline{Maybe this can be avoided by running the \meta{parameter text}
+% and the \meta{replacement text} separately through \tn{scantokens}
+% and then putting everything together at the end.}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_patch_required_catcodes:}
+% Here are the catcode settings that are \emph{mandatory} when
+% retokenizing commands. These are the minimum necessary settings to
+% perform the definitions: they identify control sequences, which
+% must be escaped with |\|$_0$, delimit the definition with |{|$_1$
+% and |}|$_2$, and mark parameters with |#|$_6$. Everything else may
+% be changed, but not these.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_required_catcodes:
+ {
+ \char_set_catcode_escape:N \\
+ \char_set_catcode_group_begin:N \{
+ \char_set_catcode_group_end:N \}
+ \char_set_catcode_parameter:N \#
+ % \int_set:Nn \tex_endlinechar:D { -1 }
+ % \int_set:Nn \tex_newlinechar:D { -1 }
+ }
+% \end{macrocode}
+% \phoinline{\pkg{etoolbox} sets the \tn{endlinechar} and \tn{newlinechar}
+% when patching, but as far as I tested these didn't make much of
+% a difference, so I left them out for now. Maybe
+% \tn{newlinechar}|=-1| avoids a space token being added after the
+% definition.}
+% \phoinline{If the patching is split by \meta{parameter text} and
+% \meta{replacement text}, then only \# will have to stay in that
+% list.}
+% \phoinline{Actually now that we patch
+% \texttt{\cs{UseHook}\{cmd/foo/before\}}, all the tokens there need
+% to have the right catcodes, so this list now includes all
+% lowercase letters, U and H, the slash, and whatever characters in
+% the command name\ldots sigh\ldots}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}[TF]{\@@_cmd_if_scanable:Nn}
+% Here we'll do a quick test if the command being patched can in fact
+% be retokenized with the specific catcode setting without changing
+% in meaning. The test is straightforward:
+% \begin{enumerate}
+% \item apply \tn{meaning} to the command;
+% \item split the \meta{prefixes}, \meta{parameter text} and
+% \meta{replacement text} and arrange them as
+% \begin{quote}
+% \meta{prefixes}\tn{def}\cs{kerneltmpDoNotUse}%^^A
+% \meta{parameter text}|{|\meta{replacement text}|}|
+% \end{quote}
+% \item rescan that with the given catcode settings, and do
+% the definition; then finally
+% \item compare \cs{kerneltmpDoNotUse} with the original command.
+% \end{enumerate}
+% If both are \tn{ifx}-equal, the command can be safely patched.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \@@_cmd_if_scanable:Nn #1 #2 { TF }
+ {
+ \cs_set_eq:NN \kerneltmpDoNotUse \scan_stop:
+ \cs_set_eq:NN \@@_tmp:w \scan_stop:
+ \use:x
+ {
+ \cs_set:Npn \@@_tmp:w
+ ####1 \tl_to_str:n { macro: } ####2 -> ####3 \s_@@_mark
+ { ####1 \def \kerneltmpDoNotUse ####2 {####3} }
+ \tl_set:Nx \exp_not:N \l_@@_tmpa_tl
+ { \exp_not:N \@@_tmp:w \token_to_meaning:N #1 \s_@@_mark }
+ }
+ \tl_rescan:nV { #2 \@@_patch_required_catcodes: } \l_@@_tmpa_tl
+ \token_if_eq_meaning:NNTF #1 \kerneltmpDoNotUse
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_patch_retokenize:Nnnn}
+% Then, if \cs{@@_cmd_if_scanable:NnTF} returned true, we can go on
+% and patch the command.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_retokenize:Nnnn #1 #2 #3 #4
+ {
+% \end{macrocode}
+% Start off by making some things \tn{relax} to avoid lots of
+% \tn{noexpand} below.
+% \begin{macrocode}
+ \cs_set_eq:NN \kerneltmpDoNotUse \scan_stop:
+ \cs_set_eq:NN \@@_tmp:w \scan_stop:
+ \use:x
+ {
+% \end{macrocode}
+% Now we'll define \cs{@@_tmp:w} such that it splits the \tn{meaning}
+% of the macro (|#1|) into its three parts:
+% \begin{enumerate}
+% \def\makelabel#1{\texttt{\#\#\#\##1}}
+% \item \meta{prefixes}
+% \item \meta{parameter text}
+% \item \meta{replacement text}
+% \end{enumerate}
+% and arrange that a complete definition, then place the |before|
+% or |after| hooks around the \meta{replacement text}:
+% accordingly.
+% \begin{macrocode}
+ \cs_set:Npn \@@_tmp:w
+ ####1 \tl_to_str:n { macro: } ####2 -> ####3 \s_@@_mark
+ {
+ ####1 \def \kerneltmpDoNotUse ####2
+ {
+ \str_if_eq:nnT {#3} { before }
+ { \token_to_str:N \UseHook { cmd / #2 / #3 } }
+ ####3
+ \str_if_eq:nnT {#3} { after }
+ { \token_to_str:N \UseHook { cmd / #2 / #3 } }
+ }
+ }
+% \end{macrocode}
+% Now we just have to get the \tn{meaning} of the command being
+% patched and pass it through the meat grinder above.
+% \begin{macrocode}
+ \tl_set:Nx \exp_not:N \l_@@_tmpa_tl
+ { \exp_not:N \@@_tmp:w \token_to_meaning:N #1 \s_@@_mark }
+ }
+% \end{macrocode}
+% Now rescan with the given catcode settings (overridden by the
+% \cs{@@_patch_required_catcodes:}), and implicitly (by using the
+% rescanned token list) carry out the definition from above.
+% \begin{macrocode}
+ \tl_rescan:nV { #4 \@@_patch_required_catcodes: } \l_@@_tmpa_tl
+% \end{macrocode}
+% And to close, copy the newly-defined command into the old name and
+% the patching is finally completed:
+% \begin{macrocode}
+ \cs_set_eq:NN #1 \kerneltmpDoNotUse
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+% \begin{macrocode}
+\msg_new:nnnn { hooks } { wrong-cmd-hook }
+ {
+ Generic~hook~`cmd/#1/#2'~is~invalid.
+% The~hook~should~be~`cmd/#1/before'~or~`cmd/#1/after'.
+ }
+ {
+ You~tried~to~add~a~generic~hook~to~command~\iow_char:N \\#1,~but~`#2'~
+ is~an~invalid~component.~Only~`before'~or~`after'~are~allowed.
+ }
+\msg_new:nnnn { hooks } { cant-patch }
+ {
+ Generic~hooks~cannot~be~added~to~'#1'.
+ }
+ {
+ You~tried~to~add~a~hook~to~'#1',~but~LaTeX~was~unable~to~
+ patch~the~command~because~it~\@@_unpatchable_cases:n {#2}.
+ }
+\cs_new:Npn \@@_unpatchable_cases:n #1
+ {
+ \str_case:nn {#1}
+ {
+ { undef } { doesn't~exist }
+ { macro } { is~not~a~macro }
+ { expl3 } { is~a~private~expl3~macro }
+ { retok } { can't~be~retokenized~cleanly }
+ }
+ }
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}{ltcmdhooks}%
+%<latexrelease> {The~hook~management~system~for~commands}
+%<latexrelease>
+% \end{macrocode}
+% The command \cs{@@_cmd_begindocument_code:} is used in an
+% internal hook, so we need to make sure it has a harmless
+% definition after rollback as that will not remove it from the
+% kernel hook.
+% \begin{macrocode}
+%<latexrelease>\cs_set_eq:NN \@@_cmd_begindocument_code: \prg_do_nothing:
+%<latexrelease>
+%<latexrelease>\EndModuleRelease
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \Finale
+%
diff --git a/macros/latex/base/ltcntrl.dtx b/macros/latex/base/ltcntrl.dtx
index b779d27fb6..d65b3aee94 100644
--- a/macros/latex/base/ltcntrl.dtx
+++ b/macros/latex/base/ltcntrl.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltcntrl.dtx}
- [2014/04/21 v1.0h LaTeX Kernel (program control)]
+ [2020/12/04 v1.0h LaTeX Kernel (program control)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltcntrl.dtx}
@@ -241,7 +241,7 @@
%
% \begin{macro}{\@for}
% \changes{v1.0d}{1995/04/24}
-% {Dont expand second argument with \cs{edef}: /1317 (DPC)}
+% {Don't expand second argument with \cs{edef}: /1317 (DPC)}
% \begin{macrocode}
\long\def\@for#1:=#2\do#3{%
\expandafter\def\expandafter\@fortmp\expandafter{#2}%
diff --git a/macros/latex/base/ltcounts.dtx b/macros/latex/base/ltcounts.dtx
index 5dc1c8866d..445cac2f2e 100644
--- a/macros/latex/base/ltcounts.dtx
+++ b/macros/latex/base/ltcounts.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltcounts.dtx}
- [2018/04/22 v1.1l LaTeX Kernel (Counters)]
+ [2020/12/04 v1.1l LaTeX Kernel (Counters)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltcounts.dtx}
@@ -630,7 +630,7 @@
% always selects the correct branch in an |\ifmmode| switch with
% the usual disadvantage of ruining kerning. For the application we
% use it for here that shouldn't matter. The alternative would be
-% to mimic |\IeC| from \textsf{inputenc} but then it wil have the
+% to mimic |\IeC| from \textsf{inputenc} but then it will have the
% disadvantage of choosing the wrong branch if appearing at the
% beginning of an alignment cell. However, users of e\TeX\ will be
% pleasantly surprised to get the best of both worlds and no bad
diff --git a/macros/latex/base/ltdefns.dtx b/macros/latex/base/ltdefns.dtx
index 920c1acde6..4f39d922cc 100644
--- a/macros/latex/base/ltdefns.dtx
+++ b/macros/latex/base/ltdefns.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltdefns.dtx}
- [2020/11/25 v1.5o LaTeX Kernel (definition commands)]
+ [2021/05/27 v1.5p LaTeX Kernel (definition commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltdefns.dtx}
@@ -103,7 +103,7 @@
% \end{macrocode}
%
%
-% \subsection{Initex initialisations}
+% \subsection{Initex initializations}
%
% \task{???}{This section needs extension}
%
@@ -858,7 +858,7 @@
% |\CheckCommand| takes the same arguments as |\newcommand|. If
% the command already exists, with the same definition, then
% nothing happens, otherwise a warning is issued. Useful for
-% checking the current state befor a macro package starts
+% checking the current state before a macro package starts
% redefining things. Currently two macros are considered to have
% the same definition if they are the same except for different
% default arguments. That is, if the old definition was:
@@ -1217,11 +1217,12 @@
% top-level definition to have the right kind of structure, but
% this is somewhat problematical as we then have to distinguish
% between \cs{long} macros and others and also take into account
-% that sometimes the top-level is deliberately dones manually (like
+% that sometimes the top-level is deliberately done manually (like
% with \cs{begin}).
%
% The macro firstly checks if the control sequence in question exists
% at all.
+% \changes{v1.5p}{2021/05/26}{Normalize error message in \cs{MakeRobust}}
% \begin{macrocode}
%</2ekernel>
%<latexrelease>\IncludeInRelease{2020/10/01}{\MakeRobust}{\MakeRobust}%
@@ -1230,7 +1231,7 @@
\count@=\escapechar
\escapechar=`\\
\@ifundefined{\expandafter\@gobble\string#1}{%
- \@latex@error{The control sequence `\string#1' is undefined!%
+ \@latex@error{Command `\string#1' is undefined!%
\MessageBreak There is nothing here to make robust}%
\@eha
}%
@@ -1259,7 +1260,7 @@
\noexpand\protect\expandafter\noexpand
\csname\expandafter\@gobble\string#1\space\endcsname}%
}%
- {\@latex@info{The control sequence `\string#1' is already robust}}%
+ {\@latex@info{Command `\string#1' is already robust}}%
}%
\escapechar=\count@
}%
@@ -1363,12 +1364,12 @@
% \end{macro}
%
% \begin{macro}{\kernel@make@fragile}
-% The opposite of |\MakeRobust| execpt that it doesn't do many
+% The opposite of |\MakeRobust| except that it doesn't do many
% checks as it is internal to the kernel. Why does one want such a
% thing?
% Only for compatibility reasons if \texttt{latexrelease} requests
% a rollback of the kernel. For this reason we pretend that this
-% command existed in all earler versions of \LaTeX{} i.e., we are
+% command existed in all earlier versions of \LaTeX{} i.e., we are
% not rolling it back since we need it precisely then. But we have
% to get it into the \texttt{latexrelease} file so that a roll
% forward is possible too.
@@ -1452,7 +1453,7 @@
% robust commands. This code will then be used to test if a command is
% robust, considered the different types of robustness, and then either copy
% that definition, if \cs{DeclareCommandCopy} (or similar) is used, or show
-% the definition of the command, if \cs{ShowCommmand} is used.
+% the definition of the command, if \cs{ShowCommand} is used.
%
% \begin{macro}{\robust@command@act}
% \changes{v1.5k}{2020/08/19}{Made \cs{robust@command@act}
@@ -1471,7 +1472,7 @@
% \ldots
% \end{quote}
% \cs{robust@command@act} will iterate over the \meta{action-list}, evaluating
-% each \meta{if-type-$n$}\meta{robust-cmd}|{|\meta{true}|}{|\meta{false}|}|.
+% each \meta{if-type-$n$} \meta{robust-cmd} |{|\meta{true}|}{|\meta{false}|}|.
% If the \meta{if-type-$n$} conditional returns \meta{true}, then
% \meta{act-type-$n$}\meta{act-arg} is executed, and the loop ends. If the
% conditional returns \meta{false}, then \meta{if-type-$n+1$} is executed in
@@ -1711,7 +1712,7 @@
% \begin{macro}{\@showcommandlisthook}
% The initial definition of \cs{@showcommandlisthook} contains the same tests
% as used for copying, but \cs{@show@...} commands instead of \cs{@copy@...}.
-% Same as before, it is initialised to cope with \cs{DeclareRobustCommand} and
+% Same as before, it is initialized to cope with \cs{DeclareRobustCommand} and
% \cs{newcommand} with optional arguments.
% \begin{macrocode}
\def\@showcommandlisthook{%
@@ -2283,7 +2284,7 @@
%
% The primitive |\-| command adds a discretionary hyphen using the
% current font's |\hyphenchar|. Monospace fonts are usually declared
-% with |\hyphenchar| set to $-1$ to suppress hyhenation.
+% with |\hyphenchar| set to $-1$ to suppress hyphenation.
%
% \LaTeX, from \LaTeX2.09 in 1986 defined |\-| by
% \begin{verbatim}
@@ -2419,7 +2420,8 @@
%
%
% \begin{macro}{\g@addto@macro}
-% Globally add to the end of a macro.
+% Globally add to the end of a macro.
+% This macro is used by the kernel to add to its internal hooks.
% \changes{v0.2a}{1993/11/14}{Made global}
% \changes{v0.2w}{1994/01/31}
% {Use toks register to avoid `hash' problems}
diff --git a/macros/latex/base/ltdirchk.dtx b/macros/latex/base/ltdirchk.dtx
index 3abd49aced..36a1ca616c 100644
--- a/macros/latex/base/ltdirchk.dtx
+++ b/macros/latex/base/ltdirchk.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -37,7 +37,7 @@
%<*driver>
% \fi
\ProvidesFile{ltdirchk.dtx}
- [2020/08/21 v1.3a LaTeX Kernel (System Dependent Parts)]
+ [2021/01/15 v1.3a LaTeX Kernel (System Dependent Parts)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltdirchk.dtx}
@@ -63,7 +63,7 @@
% {Add unstripped module,
% so that dircheck.dtx may be used with initex}
% \changes{v1.0a}{1994/03/08}
-% {Reorganise driver module into `new style'}
+% {Reorganize driver module into `new style'}
% \changes{v1.0b}{1994/03/12}
% {Change name from dircheck.dtx}
% \changes{v1.0b}{1994/03/12}
@@ -81,13 +81,13 @@
% \changes{v1.0w}{1998/08/17}{(RmS) Documentation improvements.}
%
%
-% \section{\LaTeX\ System Dependent Initialisations}
+% \section{\LaTeX\ System Dependent Initializations}
%
% \changes{v0.2g}{1994/01/21}
-% {Improve documentation, reorganise docstrip module}
+% {Improve documentation, reorganize docstrip module}
%
% This file implements the semi-automatic determination of various
-% system dependent parts of the initialisation. The actual definitions
+% system dependent parts of the initialization. The actual definitions
% may be placed in a file |texsys.cfg|. Thus for operating systems for
% which the tests here do not result in acceptable settings, a `hand
% written' |texsys.cfg| may be produced.
@@ -127,14 +127,16 @@
% |\input@path| should expand to a list of such directories, each in a
% |{}| group.
%
+% \begin{sloppypar}
% \DescribeMacro{\filename@parse}
% After a call of the form: |\filename@parse{|\meta{filename}|}|, the
-% three macros |\filename@area|,|\filename@base|,|\filename@ext| should
+% three macros |\filename@area|, |\filename@base| and |\filename@ext| should
% be defined to be the `area' (or directory), basename and
% extension respectively. If there was no extension specified in
% \meta{filename}, |\filename@ext| should be |\let| to |\relax| (so this
% case may be tested with |\@ifundefined{filename@ext}| and, perhaps a
% default extension substituted).
+% \end{sloppypar}
%
% Normally one would not need to define this macro in |texsys.cfg| as
% the automatic tests can supply parsers that work with UNIX and VMS and
@@ -153,7 +155,7 @@
%
% \DescribeMacro{\@TeXversion}
% \changes{v1.0f}{1994/05/23}{Document \cs{@TeXversion}}
-% |\@TeXversion| is now set automatically by the initialisation tests
+% |\@TeXversion| is now set automatically by the initialization tests
% in this file. You should not need to set it in |texsys.cfg|, however
% the following documentation is left for information. \LaTeX\ does
% not set this variable exactly, the automatic tests set it to:\\
@@ -206,7 +208,7 @@
%
% \StopEventually{}
%
-% \section{Initialisation}
+% \section{Initialization}
% As this file is read at a very early stage, some definitions that
% are normally considered to be part of the format must be made here.
%
@@ -470,18 +472,20 @@
% |{}| group.
%
%
+% \begin{sloppypar}
% \DescribeMacro{\filename@parse}
% After a call of the form: |\filename@parse{|\meta{filename}|}|, the
-% three macros |\filename@area|,|\filename@base|,|\filename@ext| should
+% three macros |\filename@area|, |\filename@base|, |\filename@ext| should
% be defined to be the `area' (or directory), basename and
% extension respectively. If there was no extension specified in
% \meta{filename}, |\filename@ext| should be |\let| to |\relax| (so this
% case may be tested with |\@ifundefined{filename@ext}| and, perhaps a
% default extension substituted).
+% \end{sloppypar}
%
% Normally one would not need to define this macro in |texsys.cfg| as
% the automatic tests can supply parsers that work with UNIX and VMS
-% syntax, as well as a basic parser that willcover many other cases.
+% syntax, as well as a basic parser that will cover many other cases.
% However some operating systems may need a `hand produced' parser
% in which case it should be defined in this file.
%
@@ -794,7 +798,7 @@
% to supply the correct information to the prompts. Now the interaction
% is omitted. After the format is made the installer can attempt to run
% the test document |ltxcheck.tex| through \LaTeXe. This will check,
-% amongst other things, whether |texsys.cfg| will need to be edited and
+% among other things, whether |texsys.cfg| will need to be edited and
% the format remade.
%
% \begin{macro}{\input@path}
diff --git a/macros/latex/base/lterror.dtx b/macros/latex/base/lterror.dtx
index 9a606ea8c1..7f480a0171 100644
--- a/macros/latex/base/lterror.dtx
+++ b/macros/latex/base/lterror.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltexpl.dtx b/macros/latex/base/ltexpl.dtx
index 7f9019ede3..6d7ec3ff60 100644
--- a/macros/latex/base/ltexpl.dtx
+++ b/macros/latex/base/ltexpl.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2019-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2019-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltexpl.dtx}
- [2020/12/18 v1.2h LaTeX Kernel (expl3-dependent code)]
+ [2021/04/20 v1.3c LaTeX Kernel (expl3-dependent code)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltexpl.dtx}
@@ -82,33 +82,60 @@
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
-%<latexrelease> {kernel@enddocument hooks}{Define kernel enddocument Hooks}%
-\let\@kernel@after@enddocument\@empty
-\let\@kernel@after@enddocument@afterlastpage\@empty
+%<latexrelease> {kernel@enddocument hooks}{Define several kernel hooks}
+% \end{macrocode}
+% We only initialize these kernel hooks if they are not already
+% existing. Otherwise they would be set to \cs{@empty} on rollback
+% which would be wrong because code that has been added to to them
+% may still have to be executed in the rollback situation . Instead
+% code that writes to them needs to handle the rollback as needed.
+% It is likely that we have to change that approach in the future,
+% but for now it should do.
+% (It is enough to test only for the existence of one hook, as all
+% got added at the same time.)
+% \changes{v1.3c}{2021/04/20}{Don't empty kernel hooks on rollback}
+% \begin{macrocode}
+\ifx\@kernel@after@enddocument\@undefined
+ \let \@kernel@after@enddocument \@empty
+ \let \@kernel@after@enddocument@afterlastpage \@empty
+% \end{macrocode}
+%
+% \begin{macro}{\@kernel@before@begindocument,\@kernel@after@begindocument}
+% For the similar reasons we also define those that are used in
+% \cs{document} because they too get material added to in early modules.
+% \begin{macrocode}
+ \let \@kernel@before@begindocument \@empty
+ \let \@kernel@after@begindocument \@empty
+\fi
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {kernel@enddocument hooks}{Define kernel enddocument Hooks}%
+%<latexrelease> {kernel@enddocument hooks}{Define several kernel hooks}
%<latexrelease>\let\@kernel@after@enddocument\@undefined
%<latexrelease>\let\@kernel@after@enddocument@afterlastpage\@undefined
-%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\let\@kernel@before@begindocument\@undefined
+%<latexrelease>\let\@kernel@after@begindocument\@undefined
%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% First define some blank commands, so that in case something goes wrong while
% loading \textsf{expl3}, we won't get strange \texttt{Undefined control
% sequence} errors.
+% \changes{v1.3a}{2021/01/24}{Define \pkg{expl3} hooks conditionally}
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease> {\@expl@sys@load@backend@@}{Roll forward support}%
-\def\@expl@sys@load@backend@@{}
-\def\@expl@push@filename@@{}
-\def\@expl@push@filename@aux@@{}
-\def\@expl@pop@filename@@{}
+\def\reserved@a#1{\ifdefined#1\else\def#1{}\fi}
+\reserved@a\@expl@sys@load@backend@@
+\reserved@a\@expl@push@filename@@
+\reserved@a\@expl@push@filename@aux@@
+\reserved@a\@expl@pop@filename@@
%<latexrelease>\EndIncludeInRelease
%</2ekernel|latexrelease>
% \end{macrocode}
@@ -188,7 +215,9 @@
% In \texttt{2ekernel} mode, an error is fatal and building the format
% is aborted. Use \verb=\batchmode \read -1 to \tokenlist=, which errors
% with
-% \verb=! Emergency stop. (cannot \read from terminal in nonstop modes)=
+%\begin{verbatim}
+% ! Emergency stop. (cannot \read from terminal in nonstop modes)
+%\end{verbatim}
% and aborts the \TeX{} run. In \texttt{latexrelease} mode, raise an
% error and do nothing. Both ways, the error message shows the minimum
% \textsf{expl3} engine requirements.
@@ -214,7 +243,7 @@
%</2ekernel>
% \end{macrocode}
% We do not support a roll forward across 2019. You need to start
-% with 2019 if you want to get to 2020 or beyond.
+% with 2019 if you want to get to 2020 or beyond.
% \changes{v1.2g}{2020/11/24}{Support for roll forward (gh/434)}
% \begin{macrocode}
%<*latexrelease>
@@ -225,21 +254,18 @@
--- I'm giving up!\MessageBreak\MessageBreak
Note that manually loading the expl3 package\MessageBreak
from your distribution is not enough}%
- \@@end % die
+ \batchmode \read -1 to \reserved@a
%</latexrelease>
}%
- {%
- \input expl3.ltx
- \ifdefined\NewDocumentCommand
- \else
- \IfFileExists{xparse.ltx}
- {\input xparse.ltx }
- {}%
- \fi
- }%
+ {\input expl3.ltx }%
}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>
+% \end{macrocode}
+% To support roll-forward for the case where \textsf{xparse} is fully
+% integrated into the kernel, we do not need to repeat the complex test
+% above as we can simply look for the marker command.
+% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {expl3}{Pre-load expl3}%
%<latexrelease>\IfFileExists{expl3.ltx}
@@ -262,39 +288,12 @@
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
-%
-% Starting with 2020-10 the kernel contains most of the
-% \texttt{xparse} interfaces loaded above. These interfaces are
-% later used to define various user command. However, if somebody
-% with an earlier installation tries to roll forward (using a
-% \texttt{latexrelease} package from a newer release) this will not
-% work as the earlier kernel doesn't contain commands such as
-% \cs{NewDocumentCommand}.
-%
-% We therefore add code into \texttt{latexrelease.sty} to load the
-% \texttt{xparse} package of the current installation instead. this
-% may not work if the installation is really old, but roll forward
-% can't do miracles.
-%
-% If the kernel is 2020-10 or later \cs{NewDocumentCommand} is
-% already known (whether or not you roll forward or back) so
-% nothing happens, but if you start from am earlier kernel the
-% \texttt{xparse} package gets loaded by \texttt{latexrelease}.
-% \changes{v1.2g}{2020/11/24}{Load xparse in latexrelease if needed (gh/434)}
-% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2020/10/01}%
-%<latexrelease> {\NewDocumentCommand}{Emergency loading xparse}%
-%<latexrelease>
-%<latexrelease>\ifdefined\NewDocumentCommand \else
-%<latexrelease> \RequirePackage{xparse}
-%<latexrelease>\fi
-%<latexrelease>
-%<latexrelease>\EndIncludeInRelease
-% \end{macrocode}
+% \changes{v1.3a}{2021/01/21}
+% {Move \pkg{xparse} rollback code to \texttt{ltcmd.dtx}}
%
% \subsection{Using expl3 code}
%
-% In order to ease the implemantation of some new features in
+% In order to ease the implementation of some new features in
% \LaTeXe\ we may (temporarily) use some coding based on the
% \pkg{expl3}-code.
% Such macros will eventually vanish and may be changed
diff --git a/macros/latex/base/ltfilehook-code.pdf b/macros/latex/base/ltfilehook-code.pdf
index b31a72bc78..2058ec38af 100644
--- a/macros/latex/base/ltfilehook-code.pdf
+++ b/macros/latex/base/ltfilehook-code.pdf
Binary files differ
diff --git a/macros/latex/base/ltfilehook-doc.pdf b/macros/latex/base/ltfilehook-doc.pdf
index 5fd86946d1..e9611649b2 100644
--- a/macros/latex/base/ltfilehook-doc.pdf
+++ b/macros/latex/base/ltfilehook-doc.pdf
Binary files differ
diff --git a/macros/latex/base/ltfilehook.dtx b/macros/latex/base/ltfilehook.dtx
index b4f716748a..5d0acc8fdf 100644
--- a/macros/latex/base/ltfilehook.dtx
+++ b/macros/latex/base/ltfilehook.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
-%%
-%% File: ltfilehook.dtx (C) Copyright 2020 Frank Mittelbach,
-%% Phelype Oleinik & LaTeX Team
+%
+% Copyright (C) 2020-2021
+% Frank Mittelbach, Phelype Oleinik & LaTeX Team
%
% This file is part of the LaTeX base system.
% -------------------------------------------
@@ -31,8 +31,8 @@
%%% From File: ltfilehook.dtx
%
% \begin{macrocode}
-\providecommand\ltfilehookversion{v1.0e}
-\providecommand\ltfilehookdate{2021/01/07}
+\providecommand\ltfilehookversion{v1.0k}
+\providecommand\ltfilehookdate{2021/05/25}
% \end{macrocode}
%
%<*driver>
@@ -55,6 +55,10 @@
}
\ExplSyntaxOff
+\providecommand\InternalDetectionOff{}
+\providecommand\InternalDetectionOn{}
+
+
\usepackage{structuredlog} % for demonstration
\EnableCrossrefs
@@ -75,7 +79,7 @@
% \ltfilehookversion\ dated \ltfilehookdate, \copyright\ \LaTeX\
% Project.}}
%
-% \author{Frank Mittelbach}
+% \author{Frank Mittelbach, Phelype Oleinik, \LaTeX{} Project Team}
%
% \maketitle
%
@@ -339,9 +343,12 @@
%
% \subsection{High-level interfaces for \LaTeX{}}
%
-% We do not provide any high-level \LaTeX{} commands (like
-% \pkg{filehook} or \pkg{scrlfile} do) but think that for package
-% writers the commands from for hook management are sufficient.
+% We do not provide any additional wrappers around the hooks (like
+% \pkg{filehook} or \pkg{scrlfile} do) because we believe that for
+% package writers the high-level commands from the hook management,
+% e.g., \cs{AddToHook}, etc.\
+% are sufficient and in fact easier to work with, given that the hooks
+% have consistent naming conventions.
%
%
%
@@ -371,7 +378,7 @@
% \em
% Please do not misuse this functionality and replace a file with
% another unless if really needed and only if the new version is
-% implementating the same functionality as the original one!
+% implementing the same functionality as the original one!
% \end{quote}
% \end{function}
%
@@ -447,6 +454,7 @@
%
%
% \section{The Implementation}
+%
% \begin{macrocode}
%<*2ekernel>
% \end{macrocode}
@@ -455,6 +463,8 @@
%<@@=filehook>
% \end{macrocode}
%
+% \changes{v1.0k}{2021/05/24}{Use \cs{msg_...} instead of \cs{__kernel_msg...}}
+%
%
% \subsection{Document and package-level commands}
%
@@ -517,7 +527,7 @@
% }
% A utility macro to trigger \pkg{expl3}'s file-parsing and lookup,
% and return a normalized representation of the file name. If the
-% queried file doesn't exist, no normalisation takes place.
+% queried file doesn't exist, no normalization takes place.
% The output of \cs{@@_file_parse_full_name:nN} is passed on to the
% |#2|---a 3-argument macro that takes the \meta{path}, \meta{base},
% and \meta{ext} parts of the file name.
@@ -578,9 +588,13 @@
% places don't use \cs{InputIfFileExists} directly (\cs{include}) or
% need \cs{CurrentFile} earlier (\cs{@onefilewithoptions}), so these
% are manually used elsewhere as well.
+% \changes{v1.0h}{2021/03/18}
+% {Define \cs{g_@@_input_file_seq} to avoid losing data when
+% rolling back.}
% \begin{macrocode}
\tl_new:N \l_@@_internal_tl
-\seq_new:N \g_@@_input_file_seq
+\seq_if_exist:NF \g_@@_input_file_seq
+ { \seq_new:N \g_@@_input_file_seq }
\cs_new_protected:Npn \@@_file_push:
{
\seq_gpush:Nx \g_@@_input_file_seq
@@ -594,7 +608,7 @@
\seq_gpop:NNTF \g_@@_input_file_seq \l_@@_internal_tl
{ \exp_after:wN \@@_file_pop_assign:nnnn \l_@@_internal_tl }
{
- \msg_error:nnn { hooks } { should-not-happen }
+ \msg_error:nnn { kernel } { should-not-happen }
{ Tried~to~pop~from~an~empty~file~name~stack. }
}
}
@@ -619,6 +633,7 @@
% When rolling forward the following expl3 functions may not be defined.
% If we roll back the code does nothing.
% \changes{v1.0d}{2020/11/24}{Support for roll forward (gh/434)}
+% \InternalDetectionOff
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease> {\file_parse_full_name_apply:nN}{Roll forward help}%
@@ -640,7 +655,8 @@
%<latexrelease> {
%<latexrelease> \tl_if_empty:nTF {#3}
%<latexrelease> { \__file_parse_full_name_base:nw { } #2 . \s__file_stop {#1} }
-%<latexrelease> { \__file_parse_full_name_area:nw { #1 / #2 } #3 \s__file_stop }
+%<latexrelease> { \__file_parse_full_name_area:nw { #1 / #2 }
+%<latexrelease> #3 \s__file_stop }
%<latexrelease> }
%<latexrelease>\cs_new:Npn \__file_parse_full_name_base:nw #1 #2 . #3 \s__file_stop
%<latexrelease> {
@@ -654,7 +670,8 @@
%<latexrelease> }
%<latexrelease> { \__file_parse_full_name_tidy:nnnN {#1} { .#2 } }
%<latexrelease> }
-%<latexrelease> { \__file_parse_full_name_base:nw { #1 . #2 } #3 \s__file_stop }
+%<latexrelease> { \__file_parse_full_name_base:nw { #1 . #2 }
+%<latexrelease> #3 \s__file_stop }
%<latexrelease> }
%<latexrelease>\cs_new:Npn \__file_parse_full_name_tidy:nnnN #1 #2 #3 #4
%<latexrelease> {
@@ -672,6 +689,7 @@
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
+% \InternalDetectionOn
%
% \begin{macrocode}
%<@@=>
@@ -844,6 +862,17 @@
%<latexrelease>\long\def \InputIfFileExists#1#2{%
%<latexrelease> \IfFileExists{#1}%
%<latexrelease> {#2\@addtofilelist{#1}\@@input \@filef@und}}
+% \end{macrocode}
+%
+% Also undo the internal command as some packages unfortunately test
+% for their existence instead of using \cs{IfFormatAtLeastTF}.
+% \changes{v1.0g}{2021/02/08}{Undo the internal for robust
+% \cs{InputIfFileExists} in rollback (gh/494)}
+% \begin{macrocode}
+%<latexrelease>\expandafter\let\csname InputIfFileExists \endcsname\@undefined
+% \end{macrocode}
+%
+% \begin{macrocode}
%<latexrelease>\let\@input@file@exists@with@hooks\@undefined
%<latexrelease>\let\unqu@tefilef@und\@undefined
%<latexrelease>\EndIncludeInRelease
@@ -894,7 +923,8 @@
@file-subst@
\@@_subst_file_normalize:Nn \use_ii_iii:nnn {#1}
}
- { \@@_subst_file_normalize:Nn \@@_file_name_compose:nnn {#2} }
+ { \@@_subst_file_normalize:Nn \@@_file_name_compose:nnn
+ {#2} }
\group_end:
}
\cs_new_protected:Npn \@@_subst_remove:n #1
@@ -957,12 +987,18 @@
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
%
+% We are not fully rolling back the file substitutions in case a
+% rollback encounters a package that contains them, but is itself
+% not setup for rollback. So we just bypass them and hope for the
+% best.
+% \changes{v1.0d}{2020/12/04}{Don't drop file substitution commands on
+% rollback}
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\declare@file@substitution}{File substitution}%
%<latexrelease>
-%<latexrelease>\let \declare@file@substitution \@undefined
-%<latexrelease>\let \undeclare@file@substitution \@undefined
+%<latexrelease>\let \declare@file@substitution \@gobbletwo
+%<latexrelease>\let \undeclare@file@substitution \@gobble
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
@@ -981,6 +1017,7 @@
% \subsection{Selecting a file (\cs{set@curr@file})}
%
% \begin{macro}{\set@curr@file,\@curr@file,\@curr@file@reqd}
+% \changes{v1.0f}{2021/01/31}{set \cs{protect} to \cs{string} gh/481}
% Now we hook into \cs{set@curr@file} to resolve a possible file
% substitution, and add \cs{@expl@@@filehook@set@curr@file@@nNN}
% at the end, after \cs{@curr@file} is set.
@@ -988,7 +1025,7 @@
% A file name is built using
% \cs{expandafter}\cs{string}\cs{csname}\meta{filename}\cs{endcsname}
% to avoid expanding utf8 active characters. The \cs{csname} expands
-% the normalisation machinery and the routine to resolve a file
+% the normalization machinery and the routine to resolve a file
% substitution, returning a control sequence with the same name as the
% file.
%
@@ -1001,14 +1038,18 @@
% false positives. Here we define \cs{csname\cs{endcsname}} to
% expand to itself to avoid it matching the definition of some other
% control sequence.
+% \changes{v1.0i}{2021/04/20}
+% {Make \string~ expand to a string (tracks change in l3kernel)}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease>\IncludeInRelease{2021/06/01}%
%<latexrelease> {\set@curr@file}{Setting current file name}%
\def\set@curr@file#1{%
\begingroup
\escapechar\m@ne
+ \let\protect\string
+ \edef~{\string~}%
\expandafter\def\csname\expandafter\endcsname
\expandafter{\csname\endcsname}%
% \end{macrocode}
@@ -1018,7 +1059,7 @@
% actual loaded file. \cs{@curr@file} is resolved first, to check if
% a substitution happens. If it doesn't,
% \cs{@expl@@@filehook@if@file@replaced@@TF} short-cuts and just copies
-% \cs{@curr@file}, otherwise the full normalisation procedure is
+% \cs{@curr@file}, otherwise the full normalization procedure is
% executed.
%
% At this stage the file name is parsed and normalized, but if the
@@ -1046,6 +1087,29 @@
% \end{macrocode}
%
% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\set@curr@file}{Setting current file name}%
+%<latexrelease>\def\set@curr@file#1{%
+%<latexrelease> \begingroup
+%<latexrelease> \escapechar\m@ne
+%<latexrelease> \expandafter\def\csname\expandafter\endcsname
+%<latexrelease> \expandafter{\csname\endcsname}%
+%<latexrelease> \@expl@@@filehook@if@no@extension@@nTF{#1}%
+%<latexrelease> {\@tempswatrue}{\@tempswafalse}%
+%<latexrelease> \@kernel@make@file@csname\@curr@file
+%<latexrelease> \@expl@@@filehook@resolve@file@subst@@w {#1}%
+%<latexrelease> \@expl@@@filehook@if@file@replaced@@TF
+%<latexrelease> {\@kernel@make@file@csname\@curr@file@reqd
+%<latexrelease> \@expl@@@filehook@normalize@file@name@@w{#1}%
+%<latexrelease> \if@tempswa \@expl@@@filehook@drop@extension@@N\@curr@file@reqd \fi}%
+%<latexrelease> {\if@tempswa \@expl@@@filehook@drop@extension@@N\@curr@file \fi
+%<latexrelease> \global\let\@curr@file@reqd\@curr@file}%
+%<latexrelease> \@expl@@@filehook@clear@replacement@flag@@
+%<latexrelease> \endgroup}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2019/10/01}%
%<latexrelease> {\set@curr@file}{Setting current file name}%
%<latexrelease>\def\set@curr@file#1{%
@@ -1097,7 +1161,8 @@
\expandafter\ifx\csname\endcsname#1%
.tex\else\string#1\fi}
% \end{macrocode}
-%
+%
+% \begin{sloppypar}
% Then we call \cs{@expl@@@filehook@set@curr@file@@nNN} once for
% \cs{@curr@file} to set \cs[no-index]{CurrentFile(Path)Used} and once for
% \cs{@curr@file@reqd} to set \cs[no-index]{CurrentFile(Path)}.
@@ -1107,6 +1172,7 @@
% \cs{@curr@file} and \cs{@curr@file@reqd} differ. This macro is
% issued separate from \cs{set@curr@file} because it changes
% \cs{CurrentFile}, and side-effects would quickly get out of control.
+% \end{sloppypar}
% \begin{macrocode}
\def\@filehook@set@CurrentFile{%
\@expl@@@filehook@set@curr@file@@nNN{\@curr@file}%
@@ -1170,13 +1236,13 @@
% \begin{macro}{\@@_resolve_file_subst:w}
% \begin{macro}{\@@_normalize_file_name:w}
% \begin{macro}{\@@_file_name_compose:nnn}
-% Start by sanitising the file with \cs{@@_file_parse_full_name:nN}
+% Start by sanitizing the file with \cs{@@_file_parse_full_name:nN}
% then do \cs{@@_file_subst_begin:nnn}\Arg{path}\Arg{name}\Arg{ext}.
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
-%<latexrelease> {\@@_resolve_file_subst:w}{Replace files detect loops}%
+%<latexrelease> {\@@_resolve_file_subst:w}{Replace files detect loops}%
\ExplSyntaxOn
\cs_new:Npn \@@_resolve_file_subst:w #1 \@nil
{ \@@_file_parse_full_name:nN {#1} \@@_file_subst_begin:nnn }
@@ -1195,7 +1261,7 @@
% a flag to remember if a substitution happened. We use this in
% \cs{set@curr@file} to short-circuit some of it in case no
% substitution happened (by far the most common case, so it's worth
-% optimising). The flag raised during the file substitution algorithm
+% optimizing). The flag raised during the file substitution algorithm
% must be explicitly cleared after the \cs{@@_if_file_replaced:TF}
% conditional is no longer needed, otherwise further uses of
% \cs{@@_if_file_replaced:TF} will wrongly return true.
@@ -1258,8 +1324,8 @@
% the macro below, \cs{@@_file_subst_loop:cc} is called with
% \cs[no-index]{@file-subst@\meta{file}} and
% \cs[no-index]{@file-subst@\cs[no-index]{@file-subst@\meta{file}}};
-% that is, the substitution of \meta{file} and the substution of that
-% substution: the Tortoise walks one step while the Hare walks two.
+% that is, the substitution of \meta{file} and the substitution of that
+% substitution: the Tortoise walks one step while the Hare walks two.
%
% Within \cs{@@_file_subst_loop:NN} the two substitutions are
% compared, and if they lead to the same file it means that there is
@@ -1275,7 +1341,7 @@
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
-%<latexrelease> {\@@_file_subst_tortoise_hare:nn}{Tortoise and Hare}%
+%<latexrelease> {\@@_file_subst_tortoise_hare:nn}{Tortoise and Hare}%
\ExplSyntaxOn
\cs_new:Npn \@@_file_subst_tortoise_hare:nn #1 #2 #3
{
@@ -1428,7 +1494,7 @@
% \begin{macrocode}
%<@@=>
% \end{macrocode}
-%
+% \InternalDetectionOff
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
@@ -1474,7 +1540,7 @@
%
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@filehook@file@push@@
- \__filehook_file_push:
+ \__filehook_file_push:
% \end{macrocode}
%
% \begin{macrocode}
@@ -1486,6 +1552,7 @@
\cs_new_eq:NN \@expl@@@filehook@file@pop@assign@@nnnn
\__filehook_file_pop_assign:nnnn
% \end{macrocode}
+% \InternalDetectionOn
%
%
% \begin{macrocode}
@@ -1545,7 +1612,7 @@
% \end{macro}
%
% \begin{macro}{\@@_log_file_record:n}
-% This macro is responsible for increasing and decresing the file
+% This macro is responsible for increasing and decreasing the file
% nesting level, as well as printing to the log. The argument is
% either |STOPTART| or |STOP| and the action it takes on the nesting
% integer depends on that.
@@ -1664,8 +1731,8 @@
% \Finale
%
%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\endinput
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/macros/latex/base/ltfiles.dtx b/macros/latex/base/ltfiles.dtx
index 99be77c844..bcaac58220 100644
--- a/macros/latex/base/ltfiles.dtx
+++ b/macros/latex/base/ltfiles.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfiles.dtx}
- [2020/10/04 v1.2j LaTeX Kernel (File Handling)]
+ [2021/04/17 v1.2m LaTeX Kernel (File Handling)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfiles.dtx}
@@ -49,6 +49,9 @@
\providecommand\pkg[1]{\texttt{#1}}
+\providecommand\InternalDetectionOff{}
+\providecommand\InternalDetectionOn{}
+
\begin{document}
\MaintainedByLaTeXTeam{latex}
\maketitle
@@ -192,19 +195,6 @@
% \end{oldcomments}
%
%
-% \task{???}{Do we use @unused or mainaux?}
-% \begin{macro}{\@inputcheck}
-% \begin{macro}{\@unused}
-% Allocate read stream for testing and output stream.
-% \changes{v1.0l}{1994/11/07}
-% {move here from ltdefns, remove duplicate \cs{@mainaux}}
-% \begin{macrocode}
-\newread\@inputcheck
-\newwrite\@unused
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
% \begin{macro}{\@mainaux}
% \begin{macro}{\@partaux}
% \begin{macrocode}
@@ -334,7 +324,7 @@
% locally in the output routine. In particular it allows hyphenation
% in the page head even if the page break happens in verbatim.
% If this has already been set by a package, set to the value of |\language|
-% at this spoint.
+% at this point.
% \changes{v1.1n}{2017/03/10}{Save language default}
% \begin{macrocode}
\ifx\document@default@language\m@ne
@@ -456,18 +446,25 @@
% harmless), however, in more complicated scenarios where several
% full documents are combined to a single document it might get
% applied several times with harmful effects. We therefore
-% explicitly drop it at this point. the coing is somewhat obscure
+% explicitly drop it at this point. the coding is somewhat obscure
% due to the name of the macro which requires constructing.
+% \InternalDetectionOff
% \begin{macrocode}
\edef \@kernel@after@begindocument@before {%
\let\expandafter\noexpand\csname
__hook env/document/begin\endcsname
\noexpand\@empty}
% \end{macrocode}
+% \InternalDetectionOn
%
+% These internal hooks are already declared earlier (in
+% \texttt{ltexpl}) so that other modules could write to them.
+% \changes{v1.2m}{2021/04/17}{Move \cs{@kernel@before@begindocument} and
+% \cs{@kernel@after@begindocument} init earlier so that other modules can
+% write to the hooks}
% \begin{macrocode}
-\let \@kernel@before@begindocument \@empty
-\let \@kernel@after@begindocument \@empty
+%\let \@kernel@before@begindocument \@empty
+%\let \@kernel@after@begindocument \@empty
% \end{macrocode}
%
% \end{macro}
@@ -710,15 +707,15 @@
\@latex@error{\string\include\space cannot be nested}\@eha
\else
% \end{macrocode}
-% Here the normalisation will add |.tex| for all files, (it uses the
-% the same normalisation as the hooks), so we need to remove that
+% Here the normalization will add |.tex| for all files, (it uses
+% the same normalization as the hooks), so we need to remove that
% manually. \cs{@strip@tex@ext} does that.
% \begin{macrocode}
\set@curr@file{#1}%
\edef\@curr@file{\@strip@tex@ext\@curr@file}%
% \end{macrocode}
% For historical reasons \cs{@include} expects an argument
-% delimited by a space. This is kept (though uncessary now) to avoid
+% delimited by a space. This is kept (though unnecessary now) to avoid
% errors in other packages that use \cs{@include} directly.
% \begin{macrocode}
\expandafter\@include\expandafter{\@curr@file} % deliberate space
@@ -726,13 +723,13 @@
% \end{macrocode}
%
% Here in \cs{includeonly} we also need to strip |.tex| after
-% normalisation:
+% normalization:
% \begin{macrocode}
\def\includeonly#1{%
\@partswtrue
% \end{macrocode}
% Because the argument to |\includeonly| is a comma-separated list
-% of filenames where there may be comma's precedeing some of the
+% of filenames where there may be comma's preceding some of the
% filenames or trailing them. Therefore we need to take the list
% apart, remove the unwanted spaces while leaving the spaces
% \emph{in} the filenames intact.
@@ -996,10 +993,11 @@
% A side effect of the new code is that we will see quotes around
% file name displays where there haven't been any before.
%
-% For compatibilty with existing code using |{abc}.tex| or |{one.two}.png|
-% an initial brace group is discarded before expansion and |\string| is applied
-% The content of the brace group is discarded. This means that a leading space
-% will be lost unless protected (by |{ }| or |" "| or |\space|) but filenames
+% For compatibility with existing code using |{abc}.tex| or
+% |{one.two}.png|, an initial brace group is discarded before
+% expansion and |\string| is applied. The content of the brace
+% group is discarded. This means that a leading space will be lost
+% unless protected (by |{ }| or |" "| or |\space|) but filenames
% with a space are hopefully rare.
%
% \changes{v1.2a}{2019/07/01}{Support UTF-8}
@@ -1058,7 +1056,7 @@
%
% \changes{v1.2a}{2019/07/01}{Support UTF-8}
% \changes{v1.2b}{2019/08/27}{Make command robust}
-% \changes{v1.2d}{2019/10/26}{dont quote name}
+% \changes{v1.2d}{2019/10/26}{don't quote name}
% \begin{macrocode}
\DeclareRobustCommand\IfFileExists[1]{%
\set@curr@file{#1}%
@@ -1066,30 +1064,114 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\quote@name}{Quote file names}%
+%<latexrelease>
+%<latexrelease>\let\quote@name\@undefined
+%<latexrelease>\let\quote@@name\@undefined
+%<latexrelease>\let\unquote@name\@undefined
+%<latexrelease>
+%<latexrelease>\long\def \IfFileExists#1#2#3{%
+%<latexrelease> \openin\@inputcheck#1 %
+%<latexrelease> \ifeof\@inputcheck
+%<latexrelease> \ifx\input@path\@undefined
+%<latexrelease> \def\reserved@a{#3}%
+%<latexrelease> \else
+%<latexrelease> \def\reserved@a{\@iffileonpath{#1}{#2}{#3}}%
+%<latexrelease> \fi
+%<latexrelease> \else
+%<latexrelease> \closein\@inputcheck
+%<latexrelease> \edef\@filef@und{#1 }%
+%<latexrelease> \def\reserved@a{#2}%
+%<latexrelease> \fi
+%<latexrelease> \reserved@a}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+%
+%
% \begin{macro}{\IfFileExists@}
% \changes{v0.9b}{1993/12/04}{Macro added}
% \changes{v0.9p}{1994/01/18}{New Definition}
% \changes{v1.0t}{1995/05/25}{(CAR) added \cs{long}}
-% \changes{v1.2d}{2019/10/26}{quote on openin}%
+% \changes{v1.2d}{2019/10/26}{quote on openin}
+% \changes{v1.2k}{2021/03/12}{Allow unbalanced conditionals (gh/530)}
% Argument |#1| is |\@curr@file| so catcode 12 string with no quotes.
+%
+% The original definition picked up arguments |#2| and |#3| in a
+% way that they couldn't contain unbalanced conditionals. A better
+% implementation would have been not to pick up the arguments at
+% all but instead use the usual \cs{@firstoftwo} and
+% \cs{secondoftwo}. However, that changes how |#| is interpreted
+% and so we can't do that nowaways without invalidating a lot of
+% code. Therefore the somewhat curious construction near the end.
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\IfFileExists@}{manage unbalanced conditionals}
\long\def \IfFileExists@#1#2#3{%
\openin\@inputcheck"#1" %
\ifeof\@inputcheck
\ifx\input@path\@undefined
- \def\reserved@a{#3}%
+ \let\reserved@a\@secondoftwo
\else
- \def\reserved@a{\@iffileonpath{#1}{#2}{#3}}%
+ \def\reserved@a{\@iffileonpath{#1}}%
\fi
\else
\closein\@inputcheck
\edef\@filef@und{"#1" }%
- \def\reserved@a{#2}%
+ \let\reserved@a\@firstoftwo
\fi
- \reserved@a}
+% \end{macrocode}
+% This is just there so that any |#| inside |#2| or |#3| needs
+% doubling (as that was the case in the past).
+% \begin{macrocode}
+ \expandafter\def\expandafter\reserved@a
+ \expandafter{\reserved@a{#2}{#3}}%
+\reserved@a}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\IfFileExists@}{manage unbalanced conditionals}
+%<latexrelease>
+%<latexrelease>\long\def \IfFileExists@#1#2#3{%
+%<latexrelease> \openin\@inputcheck"#1" %
+%<latexrelease> \ifeof\@inputcheck
+%<latexrelease> \ifx\input@path\@undefined
+%<latexrelease> \def\reserved@a{#3}%
+%<latexrelease> \else
+%<latexrelease> \def\reserved@a{\@iffileonpath{#1}{#2}{#3}}%
+%<latexrelease> \fi
+%<latexrelease> \else
+%<latexrelease> \closein\@inputcheck
+%<latexrelease> \edef\@filef@und{"#1" }%
+%<latexrelease> \def\reserved@a{#2}%
+%<latexrelease> \fi
+%<latexrelease> \reserved@a}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\IfFileExists@}{manage unbalanced conditionals}
+%<latexrelease>
+%<latexrelease>\let\IfFileExists@\@undefined
+%<latexrelease>
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
+%
+%
+%
% \begin{macro}{\@iffileonpath}
% If the file is not found by |\openin|, and |\input@path| is defined,
% look in all the directories specified in |\input@path|.
@@ -1103,6 +1185,10 @@
% \changes{v1.2d}{2019/10/26}{quote on openin}%
% \changes{v1.2f}{2019/11/11}{make \cs{@filef@und} match quoting used on \cs{openin}}%
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\@iffileonpath}{Quote file names}
\long\def\@iffileonpath#1{%
\let\reserved@a\@secondoftwo
\expandafter\@tfor\expandafter\reserved@b\expandafter
@@ -1122,28 +1208,7 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\quote@name}{Quote file names}%
-%<latexrelease>
-%<latexrelease>\let\quote@name\@undefined
-%<latexrelease>\let\quote@@name\@undefined
-%<latexrelease>\let\unquote@name\@undefined
-%<latexrelease>
-%<latexrelease>\let\IfFileExists@\@undefined
-%<latexrelease>
-%<latexrelease>\long\def \IfFileExists#1#2#3{%
-%<latexrelease> \openin\@inputcheck#1 %
-%<latexrelease> \ifeof\@inputcheck
-%<latexrelease> \ifx\input@path\@undefined
-%<latexrelease> \def\reserved@a{#3}%
-%<latexrelease> \else
-%<latexrelease> \def\reserved@a{\@iffileonpath{#1}{#2}{#3}}%
-%<latexrelease> \fi
-%<latexrelease> \else
-%<latexrelease> \closein\@inputcheck
-%<latexrelease> \edef\@filef@und{#1 }%
-%<latexrelease> \def\reserved@a{#2}%
-%<latexrelease> \fi
-%<latexrelease> \reserved@a}
+%<latexrelease> {\quote@name}{Quote file names}
%<latexrelease>
%<latexrelease>\long\def\@iffileonpath#1{%
%<latexrelease> \let\reserved@a\@secondoftwo
diff --git a/macros/latex/base/ltfinal.dtx b/macros/latex/base/ltfinal.dtx
index aa4219723a..19f82934aa 100644
--- a/macros/latex/base/ltfinal.dtx
+++ b/macros/latex/base/ltfinal.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfinal.dtx}
- [2020-09-26 v2.2j LaTeX Kernel (Final Settings)]
+ [2021/04/18 v2.2o LaTeX Kernel (Final Settings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfinal.dtx}
@@ -57,7 +57,7 @@
%
%
% \section{Final settings}
-% This section contains the final settings for \LaTeX. It initialises
+% This section contains the final settings for \LaTeX. It initializes
% some debugging and typesetting parameters, sets the default
% |\catcode|s and uc/lc codes, and inputs the hyphenation file.
%
@@ -90,6 +90,9 @@
% \changes{v2.0s}{2016/10/15}{Tidy up status of char 127}
% \changes{v2.2i}{2020/08/21}{Integration of new hook management interface}
%
+%
+%
+%
% \subsection{Debugging}
%
% By default, \LaTeX{} shows statistics:
@@ -150,7 +153,7 @@
%\begin{macro}{\newXeTeXintercharclass}
% \changes{v2.0a}{2014/12/30}{macro added}
% \changes{v2.0b}{2015/01/23}{use reserved count 257}
-% \changes{v2.0f}{2015/04/28}{define \cs{xe@alloc@intercharclass} for compatibility with older xelatex initilisation}
+% \changes{v2.0f}{2015/04/28}{define \cs{xe@alloc@intercharclass} for compatibility with older xelatex initialization}
%\begin{macro}{\xe@alloc@intercharclass}
%\begin{macro}{\e@alloc@intercharclass@top}
% \changes{v2.0j}{2016/01/04}{Start allocation at one not three}
@@ -239,7 +242,73 @@
% \end{macro}
% \end{macro}
%
-%
+% \begin{macro}{trace_stack_levels}
+% Now define the Lua function to emulate \cs{tracingstacklevels} and
+% install it in the \texttt{input_level_string} callback.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+% In \texttt{latexrelease} mode we always remove the function from
+% the callback, then add the correct version later.
+% \begin{macrocode}
+%<latexrelease>\ifx\directlua\@undefined
+%<latexrelease>\else
+%<latexrelease> \directlua{%
+%<latexrelease> if luatexbase.callbacktypes['input_level_string'] and %
+%<latexrelease> luatexbase.in_callback('input_level_string','tracingstacklevels') then
+%<latexrelease> luatexbase.remove_from_callback('input_level_string','tracingstacklevels')
+%<latexrelease> end}%
+%<latexrelease>\fi
+%<latexrelease>\IncludeInRelease{2021/06/01}{trace_stack_levels}%
+%<latexrelease> {Lua trace_stack_levels function}%
+\ifx\directlua\@undefined
+\else
+%<*2ekernel>
+ \expanded{%
+ \everyjob{\the\everyjob
+ \noexpand%\directlua
+%</2ekernel>
+ \directlua{%
+ local function trace_stack_levels (input_ptr)
+ local tracingstacklevels = tex.count.tracingstacklevels
+ if tex.tracingmacros > 0 or input_ptr < tracingstacklevels then
+ if tracingstacklevels > 0 then
+ if input_ptr < tracingstacklevels then
+ return "\string\n\string~" .. string.rep(".",input_ptr)
+ else
+ return "\string~\string~"
+ end
+ else
+ return "\string\n"
+ end
+ else
+ return ""
+ end
+ end
+%<latexrelease> if luatexbase.callbacktypes['input_level_string'] then
+ luatexbase.add_to_callback('input_level_string',
+ trace_stack_levels,'tracingstacklevels')
+%<latexrelease> end
+ }%
+%<*2ekernel>
+ }}%
+%</2ekernel>
+\fi
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+% \end{macrocode}
+% Then for the full rollback, just do nothing, since the function
+% was already taken out of the rollback above.
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}{trace_stack_levels}%
+%<latexrelease> {Lua trace_stack_levels function}%
+%<latexrelease>% Nothing here
+%<latexrelease>\EndIncludeInRelease
+%</2ekernel|latexrelease>
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
%
% The default values of the picture and |\fbox| parameters:
% \begin{macrocode}
@@ -522,12 +591,13 @@
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2017/04/15}%
-%<latexrelease> {\document@default@language}{Save language for hyphenation}%
+%<latexrelease> {\document@default@language}{Save language for hyphenation}%
\let\document@default@language\m@ne
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\document@default@language}{Save language for hyphenation}%
+%<latexrelease> {\document@default@language}{Save language for hyphenation}%
+%
%<latexrelease>\let\document@default@language\@undefined
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
@@ -562,6 +632,52 @@
\fi
% \end{macrocode}
%
+% For pdf\TeX\ preload and enable automatic glyph to Unicode mapping
+% for more reliable copy and paste support.
+% \changes{v2.2l}{2021/01/21}{Load glyphtounicode.tex for pdf\TeX}
+% \changes{v2.2m}{2021/02/25}{Improve speed of ToUnicode everyjob loading code}
+%
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\pdfgentounicode}{Preload glyphtounicode}%
+\ifx \pdfgentounicode \@undefined \else
+%<*2ekernel>
+ \ifnum 0=0%
+ \ifdefined\pdftexversion
+% \pdftexversion<140 does not have \pdfgentounicode, so we only check higher values
+ \ifnum \pdftexversion=140 \ifnum\pdftexrevision<22 1\fi\fi
+ \fi
+ \relax
+%</2ekernel>
+ \input glyphtounicode
+%<*2ekernel>
+ \else
+ \begingroup
+ \everyeof{\noexpand}\endlinechar-1
+ \edef\x{\endgroup
+ \everyjob{\the\everyjob\@@input glyphtounicode }%
+ }\x
+ \fi
+%</2ekernel>
+ \pdfgentounicode=1
+\fi
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+% When rolling back we can't unload the glyphtounicode mappings, but we
+% can reset |\pdfgentounicode| to ensure that they aren't used.
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\pdfgentounicode}{Preload glyphtounicode}%
+%<latexrelease>\ifx \pdfgentounicode \@undefined \else
+%<latexrelease> \pdfgentounicode=0
+%<latexrelease>\fi
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
% \subsection{Input encoding}
%
% \changes{v2.1a}{2018/03/25}{default to UTF-8}
@@ -632,7 +748,7 @@
%
% \begin{macro}{\UseRawInputEncoding}
% \changes{v2.1a}{2018/03/25}{Macro added}
-% Reset 8 bit characters to catcode 12 so the input endcoing matches the ``Raw''
+% Reset 8 bit characters to catcode 12 so the input encoding matches the ``Raw''
% font encoding.
% Useful for special behaviours, or for compatibility with older \LaTeX\ formats.
% \changes{v2.1b}{2018/04/06}{Undo changes to \cs{DeclareFontEncoding@} and
@@ -939,7 +1055,7 @@
\expandafter\reserved@a\@uclclist\reserved@b{\reserved@b\@gobble}%
% \end{macrocode}
% Tell UTF-8 processing to process chars even though we are in an \cs{protected@edef}.
-% \changes{v2.1h}{2019/09/14}{Expand UTF8 chrs when case changing (github/177)}
+% \changes{v2.1h}{2019/09/14}{Expand UTF8 chars when case changing (github/177)}
% \begin{macrocode}
\let\UTF@two@octets@noexpand\@empty
\let\UTF@three@octets@noexpand\@empty
diff --git a/macros/latex/base/ltfloat.dtx b/macros/latex/base/ltfloat.dtx
index dee9a10197..ed25db3ed1 100644
--- a/macros/latex/base/ltfloat.dtx
+++ b/macros/latex/base/ltfloat.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -31,7 +31,7 @@
%
%<*driver>
% \fi
-\ProvidesFile{ltfloat.dtx}[2020/04/09 v1.2d LaTeX Kernel (Floats)]
+\ProvidesFile{ltfloat.dtx}[2021/03/03 v1.2f LaTeX Kernel (Floats)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfloat.dtx}
@@ -356,7 +356,7 @@
% \changes{v1.1f}{1994/11/21}
% {Missing percents reinserted after 4, 8: these are not numbers.}
% \changes{v1.1g}{1994/12/10}{Old version reinstated temporarily}
-% \changes{v1.1g}{1994/12/10}{Sanitisation added temporarily}
+% \changes{v1.1g}{1994/12/10}{Sanitization added temporarily}
% The first part of this sets the count register that stores all
% the information about the type and fps of the float.
%
@@ -574,7 +574,7 @@
%
% \begin{macro}{\@setnobreak}
% \changes{v1.1f}{1994/11/21}{Macro added}
-% \changes{v1.1n}{1996/07/26}{remove unecessary \cs{global} before
+% \changes{v1.1n}{1996/07/26}{remove unnecessary \cs{global} before
% \cs{@nobreak...}}
% \begin{macrocode}
\def \@setnobreak{%
@@ -588,7 +588,7 @@
%
% \begin{macro}{\@setminipage}
% \changes{v1.1f}{1994/11/21}{Macro added}
-% \changes{v1.1n}{1996/07/26}{remove unecessary \cs{global} before
+% \changes{v1.1n}{1996/07/26}{remove unnecessary \cs{global} before
% \cs{@minipage...}}
% \begin{macrocode}
\def \@setminipage{%
@@ -734,7 +734,7 @@
% {Use new \cs{color@hbox} concept.}
% \changes{v1.1f}{1994/11/21}{Corrected position of \cs{outer@nobreak}}
% \changes{v1.1f}{1994/11/21}{Added reset of minipage flag}
-% \changes{v1.1n}{1996/07/26}{remove unecessary \cs{global} before
+% \changes{v1.1n}{1996/07/26}{remove unnecessary \cs{global} before
% \cs{@minipage...}}
% \begin{macrocode}
\@minipagefalse
@@ -1002,9 +1002,14 @@
% \changes{v1.1f}{1994/11/21}{Added \cs{@setminipage} etc}
% \changes{v1.1f}{1994/11/21}{Added resetting of size and font}
% \changes{v1.1m}{1995/05/25}{(CAR) Resettings moved to hook}
-% \changes{v1.1n}{1996/07/26}{remove unecessary \cs{global} before
+% \changes{v1.1n}{1996/07/26}{remove unnecessary \cs{global} before
% \cs{@minipage...}}
+% \changes{v1.2e}{2021/02/03}{Explicitly end with \cs{par} (gh/489)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@savemarbox}{Explicit par for marginpar}%
\long\def \@savemarbox #1#2{%
\global\setbox #1%
\color@vbox
@@ -1012,12 +1017,35 @@
\hsize\marginparwidth
\@parboxrestore
\@marginparreset
- #2%
+ #2\par
\@minipagefalse
\outer@nobreak
}%
\color@endbox
}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@savemarbox}{Explicit par for marginpar}%
+%<latexrelease>
+%<latexrelease>\long\def \@savemarbox #1#2{%
+%<latexrelease> \global\setbox #1%
+%<latexrelease> \color@vbox
+%<latexrelease> \vtop{%
+%<latexrelease> \hsize\marginparwidth
+%<latexrelease> \@parboxrestore
+%<latexrelease> \@marginparreset
+%<latexrelease> #2%
+%<latexrelease> \@minipagefalse
+%<latexrelease> \outer@nobreak
+%<latexrelease> }%
+%<latexrelease> \color@endbox
+%<latexrelease>}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -1026,7 +1054,7 @@
%
% The rational for allowing these normally global flags to be set
% locally here, via |\@parboxrestore| was stated originally by
-% Donald Arsenau and extended by Chris Rowley.
+% Donald Arseneau and extended by Chris Rowley.
% It is because these flags are only set globally to
% true by section commands, and these should never appear within
% marginals or floats or, indeed, in any group; and they are only ever
@@ -1480,7 +1508,13 @@
% {Removed \cs{normalcolor} (again)}
% \changes{v1.1t}{1997/11/19}
% {Missing percent, again}
+% \changes{v1.2e}{2021/02/10}{Explicitly run \cs{par} at the end of footnote text
+% in preparation for paragraph hooks}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@footnotetext}{footnotetext tagging}%
\long\def\@footnotetext#1{\insert\footins{%
\reset@font\footnotesize
\interlinepenalty\interfootnotelinepenalty
@@ -1493,7 +1527,32 @@
\color@begingroup
\@makefntext{%
\rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+ \par
\color@endgroup}}%
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@footnotetext}{footnotetext tagging}%
+%<latexrelease>
+%<latexrelease>\long\def\@footnotetext#1{\insert\footins{%
+%<latexrelease> \reset@font\footnotesize
+%<latexrelease> \interlinepenalty\interfootnotelinepenalty
+%<latexrelease> \splittopskip\footnotesep
+%<latexrelease> \splitmaxdepth \dp\strutbox \floatingpenalty \@MM
+%<latexrelease> \hsize\columnwidth \@parboxrestore
+%<latexrelease> \protected@edef\@currentlabel{%
+%<latexrelease> \csname p@footnote\endcsname\@thefnmark
+%<latexrelease> }%
+%<latexrelease> \color@begingroup
+%<latexrelease> \@makefntext{%
+%<latexrelease> \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+%<latexrelease> \color@endgroup}}%
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -1558,10 +1617,51 @@
% \begin{macrocode}
\def\@mpfn{footnote}
\def\thempfn{\thefootnote}
-%</2ekernel>
% \end{macrocode}
+%
% \end{macro}
% \end{macro}
%
+%
+%
+%
+% \begin{macro}{\footref}
+% This command generates a footnote mark. The value is produced by
+% referencing a \cs{label} placed into a \cs{footnote} elsewhere
+% (can be one in the main galley or in a minipage).
+% \changes{v1.2f}{2021/02/16}{\cs{footref} added}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\footref}{Add footref}%
+\def\footref#1{%
+ \begingroup
+ \unrestored@protected@xdef\@thefnmark{\ref{#1}}%
+ \endgroup
+ \@footnotemark
+}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+% We don't remove it when rolling back so that packages offered it
+% in the past do not need to alter their behavior in a rollback
+% situation.
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\footref}{Add footref}%
+%<latexrelease>
+%<latexrelease> % \let\footref\@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+%</2ekernel>
+% \end{macrocode}
+%
% \Finale
%
diff --git a/macros/latex/base/ltfntcmd.dtx b/macros/latex/base/ltfntcmd.dtx
index 0a44d5acf1..5f70053a68 100644
--- a/macros/latex/base/ltfntcmd.dtx
+++ b/macros/latex/base/ltfntcmd.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfntcmd.dtx}
- [2019/12/17 v3.4c LaTeX Kernel (Font commands)]
+ [2020/12/05 v3.4c LaTeX Kernel (Font commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfntcmd.dtx}
@@ -303,7 +303,7 @@
% character in an unsloped font; we believe (in early 2003) that
% this is perhaps inefficient but not dangerous.
%
-% It also now checks for empty contents of the text command and optimises
+% It also now checks for empty contents of the text command and optimizes
% this case. Some care is also taken to check that doing dangerous
% things in vertical mode is avoided.
%
@@ -539,7 +539,7 @@
%
% \begin{macro}{\ifmaybe@ic}
% \changes{v3.4a}{2009/12/14}{Macro added}
-% Switch used soley within |\maybe@ic| not interfering with other
+% Switch used solely within |\maybe@ic| not interfering with other
% switches.
% \begin{macrocode}
\newif\ifmaybe@ic
@@ -585,7 +585,7 @@
% \begin{macrocode}
\do \t@st@ic
% \end{macrocode}
-% Frank thinks that the next bit it is inefficient if done after
+% Frank thinks that the next bit is inefficient if done after
% the second change. Chris thinks that most all of this is
% inefficient for the commonest cases: but that is the price of a
% cleverer algorithm. It is certainly needed to deal with the use
diff --git a/macros/latex/base/ltfssaxes.dtx b/macros/latex/base/ltfssaxes.dtx
index a66a26cd39..86c84b111f 100644
--- a/macros/latex/base/ltfssaxes.dtx
+++ b/macros/latex/base/ltfssaxes.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2019-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2019-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -35,7 +35,7 @@
%
%
\ProvidesFile{ltfssaxes.dtx}
- [2020/08/21 v1.0g LaTeX Kernel (NFSS Axes handing)]
+ [2021/03/18 v1.0i LaTeX Kernel (NFSS Axes handing)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -68,11 +68,11 @@
%
% \StopEventually{}
%
-% Everything in the this file got introduced 2020/02/02, so we do a
-% single rollback (for now).
+% \changes{v1.0h}{2020/12/04}{Reorganized the rollback data}
+%
+% Everything in the this file got introduced 2020/02/02, so we use large rollback
+% chunks, only interrupted if necessary.
% \begin{macrocode}
-%<*2ekernel>
-%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\DeclareFontSeriesChangeRule}{Series change rules}%
@@ -168,13 +168,13 @@
% request (i.e., second argument).
%
% In particular this is also true for cases involving \texttt{m},
-% e.g., \texttt{bm} (bold medium width) which automatially gets
+% e.g., \texttt{bm} (bold medium width) which automatically gets
% reduced result in \texttt{b} or \texttt{mc} (medium weight
% condensed) which becomes \texttt{c} as a result.
%
% \item
%
-% Only a few entries have ``alterative'' values and perhaps most of
+% Only a few entries have ``alternative'' values and perhaps most of
% them should get dropped. Or maybe not \ldots{} needs some thought
% perhaps.
%
@@ -183,7 +183,7 @@
% to stay with \texttt{b} when a change to \texttt{c} is requested
% and \texttt{bc} doesn't exist, than to go to first change the
% shape to \texttt{n} and then find that \texttt{bc/n} doesn't
-% exist either and thus ending up wth \texttt{m/n}.
+% exist either and thus ending up with \texttt{m/n}.
%
% \item
%
@@ -678,21 +678,59 @@
% \end{macrocode}
%
%
-
-
+% Supporting rollback \ldots
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\DeclareFontSeriesChangeRule}{Series change rules}%
+%<latexrelease>
+%<latexrelease>\let\DeclareFontSeriesChangeRule\@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+%
+%
+%
+%
% \subsection{Changing to a new series}
%
%
-
-% \begin{macro}{\if@forced@series}
-% If the series gets forced we need to know that fact later on.
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\fontseries}{delay fontseries update}%
+% \end{macrocode}
+%
+%
+% \begin{macro}{\fontseries}
+% The \cs{fontseries} command takes one argument which is the requested new
+% font series. In the orginal implementation it simply saved the
+% expanded value in \cs{f@series}. Now we do a bit more processing
+% and look up the final value in the font series data base. This is
+% done by \cs{merge@font@series}. But the lookup should be done
+% within the target family and call to \cs{fontseries} might be
+% followed by a \cs{fontfamily} call. So we delay the processing to
+% \cs{selectfont} and only record the necessary action in
+% \cs{delayed@f@adjustment}.
% \changes{v1.0c}{2020/02/10}{Switch \cs{if@forced@series} added}
+% \changes{v1.0h}{2020/12/04}{Distangle series and shape update (gh/444)}
% \begin{macrocode}
-\newif\if@forced@series
+\DeclareRobustCommand\fontseries[1]{\@forced@seriesfalse
+ \expandafter\def\expandafter\delayed@f@adjustment\expandafter
+ {\delayed@f@adjustment\delayed@merge@font@series{#1}}}
% \end{macrocode}
% \end{macro}
%
%
+% \begin{macro}{\delayed@f@adjustment}
+% The macro holding the delayed action(s) for use in \cs{selectfont}.
+% \begin{macrocode}
+\let\delayed@f@adjustment\@empty
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\fontseriesforce}
% To change unconditionally to a new series you can use
% \cs{fontseriesforce}. Of course, if the series doesn't exist for
@@ -700,24 +738,69 @@
% dependency on the current series.
% \changes{v1.0c}{2020/02/10}{Switch \cs{if@forced@series} added}
% \begin{macrocode}
-\DeclareRobustCommand\fontseriesforce[1]{\@forced@seriestrue\edef\f@series{#1}}
+\DeclareRobustCommand\fontseriesforce[1]{\@forced@seriestrue
+ \expandafter\def\expandafter\delayed@f@adjustment\expandafter
+ {\delayed@f@adjustment\edef\f@series{#1}}}
% \end{macrocode}
% \end{macro}
%
%
-% \begin{macro}{\fontseries}
-% The \cs{fontseries} command takes one argument which is the requested new
-% font series. In the orginal implementation it simply saved the
-% expanded value in \cs{f@series}. Now we do a bit more processing
-% and look up the final value in the font series data base. This is
-% done by \cs{merge@font@series}.
+%
+% \begin{macro}{\if@forced@series}
+% If the series gets forced we need to know that fact later on.
% \changes{v1.0c}{2020/02/10}{Switch \cs{if@forced@series} added}
% \begin{macrocode}
-\DeclareRobustCommand\fontseries[1]{\@forced@seriesfalse\merge@font@series{#1}}
+\newif\if@forced@series
% \end{macrocode}
% \end{macro}
-
-
+%
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\fontseries}{delay fontseries update}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\fontseries[1]{\@forced@seriesfalse
+%<latexrelease> \merge@font@series{#1}}
+%<latexrelease>\DeclareRobustCommand\fontseriesforce[1]{\@forced@seriestrue
+%<latexrelease> \edef\f@series{#1}}
+%<latexrelease>\let\delayed@f@adjustment\@undefined
+%<latexrelease>
+% \end{macrocode}
+% For a roll forward we may have to define \cs{if@forced@series}
+% but this needs doing in a way that \TeX{} doesn't see it when
+% skipping over conditionals.
+% \changes{v1.0i}{2021/03/18}
+% {Fix rollforward definition.}
+% \begin{macrocode}
+%<latexrelease>\expandafter\newif\csname if@forced@series\endcsname
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\fontseries}{delay fontseries update}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\fontseries[1]{\edef\f@series{#1}}
+%<latexrelease>\let\fontseriesforce\@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+%
+%
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\merge@font@series}{Merge series values}%
+% \end{macrocode}
+%
+%
% \begin{macro}{\merge@font@series}
% We look up the data base value by expanding the right command
% twice. If no such value exist then the result will be \cs{relax}
@@ -734,9 +817,9 @@
}
% \end{macrocode}
% \end{macro}
-
-
-
+%
+%
+%
% \begin{macro}{\merge@font@series@}
% This now defines the new \cs{f@series}:
% \begin{macrocode}
@@ -758,11 +841,9 @@
% \end{macrocode}
% Otherwise we check if the desired result for the series
% (\texttt{\#1}) exists for the font family and the current shape.
-% As the \texttt{.fd} is perhaps not loaded yet, we first
-% have to do that, otherwise the test would fail even if the face
-% is actually available.
+% All this happens inside \cs{selectfont} which has already taken care to load
+% the \texttt{.fd}, file if necessary.
% \begin{macrocode}
- \maybe@load@fontshape
\edef\reserved@a{\f@encoding /\f@family /#1/\f@shape}%
\ifcsname \reserved@a \endcsname
% \end{macrocode}
@@ -798,9 +879,10 @@
% \end{macrocode}
% It is possible that the previous font and the new one are
% actually identical (and the font was not found because it still
-% needs loading) in which case a warning would look rather odd. So
-% we make a quick check for that (which is the reason why we defined
-% \cs{@reserveda} above.
+% needs loading) in which case a warning would look rather odd. So
+% we make a quick check for that (which is the reason why we
+% defined \cs{@reserveda} above instead of doing inline testing
+% inside \cs{ifcsname}).
% \begin{macrocode}
\def\@font@shape@subst@warning{%
\edef\reserved@b{\curr@fontshape}%
@@ -814,13 +896,71 @@
%
%
%
+% \begin{macro}{\merge@font@series@without@substitution,
+% \merge@font@series@without@substitution@,
+% \delayed@merge@font@series}
+%
+% \changes{v1.0h}{2020/12/22}{Distangle series and shape update (gh/444)}
+%
+% \cs{merge@font@series@without@substitution} works like
+% \cs{merge@font@series}, i.e., it looks up the combination in the
+% rule base and if there exists an entry it uses it and if not it
+% uses the new series value. However, it doesn't check if there is
+% actually a font face with the new series value as
+% \cs{merge@font@series} does. This simplified command is used in
+% \cs{selectfont} at a point where other font attributes are not
+% yet updated so that checking the font face might result incorrect
+% in substitutions.
+%
+% \begin{macrocode}
+\def\merge@font@series@without@substitution#1{%
+ \expandafter\expandafter\expandafter
+ \merge@font@series@without@substitution@
+ \csname series@\f@series @#1\endcsname
+ {#1}%
+ \@nil
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\merge@font@series@without@substitution@#1#2#3\@nil{%
+ \def\reserved@a{#3}%
+ \ifx\reserved@a\@empty
+ \set@target@series{#2}%
+ \else
+ \set@target@series{#1}%
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\delayed@merge@font@series}
+%
+% When we delay the merge action in \cs{fontseries} we first
+% attempt to use merging without substitution. If that results in a
+% non-existing font face the merge is redone in \cs{selectfont}
+% using a version with substitution. See \cs{selectfont} for details.
+%
+% \changes{v1.0h}{2020/12/22}{Distangle series and shape update
+% (gh/444)}
+% \begin{macrocode}
+\let\delayed@merge@font@series\merge@font@series@without@substitution
+% \end{macrocode}
+% \end{macro}
%
% \begin{macro}{\maybe@load@fontshape}
% A small helper that we use a couple of times: try loading a
% fontshape (in a group because \cs{try@load@fontshape} normalizes
-% catcodes).
+% catcodes and we also want to change \cs{typeout} so that it
+% doesn't report missing \texttt{.fd} files on the terminal).
% \begin{macrocode}
-\def\maybe@load@fontshape{\begingroup\try@load@fontshape\endgroup}
+\def\maybe@load@fontshape{%
+ \begingroup
+ \let \typeout \@font@info
+ \try@load@fontshape
+ \endgroup}
% \end{macrocode}
% \end{macro}
%
@@ -845,7 +985,7 @@
% \end{macrocode}
% We need to \cs{edef} the argument first in case it starts with a
% conditional. Then we check (and perhaps drop) an ``m'' from the
-% value andassign the result to \cs{f@series}.
+% value and assign the result to \cs{f@series}.
% \changes{v1.0d}{2020/02/27}{Drop ``m'' only in a specific set of values (gh/293)}
% \begin{macrocode}
\edef\f@series{#1}%
@@ -916,6 +1056,30 @@
}
% \end{macrocode}
% \end{macro}
+%
+%
+%
+% Supporting rollback \ldots
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\merge@font@series}{Merge series values}%
+%<latexrelease>
+%<latexrelease>\let\merge@font@series\@undefined
+%<latexrelease>\let\merge@font@series@\@undefined
+%<latexrelease>\let\@font@shape@subst@warning\@undefined
+%<latexrelease>\let\merge@font@series@without@substitution\@undefined
+%<latexrelease>\let\merge@font@series@without@substitution@\@undefined
+%<latexrelease>\let\delayed@merge@font@series\@undefined
+%<latexrelease>\let\maybe@load@fontshape\@undefined
+%<latexrelease>\let\set@target@series\@undefined
+%<latexrelease>\let\series@maybe@drop@one@m\@undefined
+%<latexrelease>\let\series@drop@one@m\@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+
@@ -925,6 +1089,12 @@
% that is desirable), essentially building in an ``sc''
% axis).
%
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\DeclareFontShapeChangeRule}{Font shape change rules}%
+% \end{macrocode}
+%
%
%
% \begin{macro}{\DeclareFontShapeChangeRule}
@@ -948,8 +1118,9 @@
% 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 is normally the same as
-% calling both \cs{ulcshape} and \cs{upshape}, only more efficient.
+% 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.
%
%
% \begin{macro}{\ulcshape}
@@ -1080,7 +1251,7 @@
% \texttt{n}. This is the way \texttt{fontspec} implemented its
% version on this interface, so this rule means we are also
% compatible with the way \texttt{fontspec} behaved. Still it
-% remains an odditywhic I would rather liked to have avoided.
+% remains an oddity which I would rather liked to have avoided.
% \begin{macrocode}
%\DeclareFontShapeChangeRule {sc}{up} {sc} {}
\DeclareFontShapeChangeRule {sc}{up} {n} {}
@@ -1100,7 +1271,7 @@
% \texttt{ulc} in \cs{f@series} which most certainly doesn't
% exist. So when a font is later selected that would result in a
% substitution (so no harm done really). Alternatively, we could in
-% this case use \texttt{n} as aternative, which may be a bit
+% this case use \texttt{n} as alternative, which may be a bit
% faster, but such a setup would be so weird in the first place
% that this isn't worth the effort.
%
@@ -1134,26 +1305,97 @@
\DeclareFontShapeChangeRule {sw}{up} {n} {}
% \end{macrocode}
%
+% Supporting rollback \ldots
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\DeclareFontShapeChangeRule}{Font shape change rules}%
+%<latexrelease>
+%<latexrelease>\let\DeclareFontShapeChangeRule\@undefined
+%<latexrelease>\let\ulcshape\@undefined
+%<latexrelease>\let\ulcdefault\@undefined
+%<latexrelease>\let\swshape\@undefined
+%<latexrelease>\let\swdefault\@undefined
+%<latexrelease>\let\sscshape\@undefined
+%<latexrelease>\let\sscdefault\@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
%
% \subsection{Changing to a new shape}
%
+%
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\fontshape}{Font shape change}%
+% \end{macrocode}
+%
+%
+%
% \begin{macro}{\fontshape}
% Again the \cs{fontshape} now has to do a lookup to get to its new
% value in \cs{f@shape}. The method is exactly the same as in
% \cs{fontseries}.
+% \changes{v1.0h}{2020/12/04}{Distangle series and shape update (gh/444)}
% \begin{macrocode}
-\DeclareRobustCommand\fontshape[1]{\merge@font@shape{#1}}
+\DeclareRobustCommand\fontshape[1]
+ {\expandafter\def\expandafter\delayed@f@adjustment\expandafter
+ {\delayed@f@adjustment\delayed@merge@font@shape{#1}}}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\fontshapeforce}
% The unconditional version:
+%
+% \changes{v1.0h}{2020/12/04}{Distangle series and shape update (gh/444)}
% \begin{macrocode}
-\DeclareRobustCommand\fontshapeforce[1]{\edef\f@shape{#1}}
+\DeclareRobustCommand\fontshapeforce[1]
+ {\expandafter\def\expandafter\delayed@f@adjustment\expandafter
+ {\delayed@f@adjustment\edef\f@shape{#1}}}
% \end{macrocode}
% \end{macro}
%
+%
+% Supporting rollback \ldots
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\fontshape}{Font shape change}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\fontshape[1]{\merge@font@shape{#1}}
+%<latexrelease>\DeclareRobustCommand\fontshapeforce[1]{\edef\f@shape{#1}}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\fontshape}{Font shape change}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\fontshape [1]{\edef\f@shape{#1}}
+%<latexrelease>\let\fontshapeforce\@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+
+
+
+
+
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\merge@font@shape}{Font shape change rules}%
+% \end{macrocode}
+%
+%
+%
% \begin{macro}{\merge@font@shape}
% Look up the database entry (if existing) and act accordingly.
% \begin{macrocode}
@@ -1178,9 +1420,12 @@
\ifx\reserved@a\@empty
\edef\f@shape{#2}%
\else
- \maybe@load@fontshape
+% \end{macrocode}
+% \cs{reserved@a} is used in \cs{@font@shape@subst@warning} so we
+% have to define it in addition to do the \cs{ifcsname} test
+% \begin{macrocode}
\edef\reserved@a{\f@encoding /\f@family /\f@series/#1}%
- \ifcsname \reserved@a\endcsname
+ \ifcsname \reserved@a\endcsname
\edef\f@shape{#1}%
\else
\ifcsname \f@encoding /\f@family /\f@series/#2\endcsname
@@ -1197,6 +1442,38 @@
% \end{macro}
%
%
+% \begin{macro}{\merge@font@shape@without@substitution,
+% \merge@font@shape@without@substitution@,
+% \delayed@merge@font@shape}
+% See definition of \cs{selectfont} for how these macros are used.
+% \changes{v1.0h}{2020/12/22}{Distangle series and shape update (gh/444)}
+% \begin{macrocode}
+\def\merge@font@shape@without@substitution#1{%
+ \expandafter\expandafter\expandafter
+ \merge@font@shape@without@substitution@
+ \csname shape@\f@shape @#1\endcsname
+ {#1}%
+ \@nil
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\merge@font@shape@without@substitution@#1#2#3\@nil{%
+ \def\reserved@a{#3}%
+ \ifx\reserved@a\@empty
+ \edef\f@shape{#2}%
+ \else
+ \edef\f@shape{#1}%
+ \fi
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\let\delayed@merge@font@shape\merge@font@shape@without@substitution
+% \end{macrocode}
+% \end{macro}
+%
+%
%
% \begin{macro}{\normalshape}
%
@@ -1255,52 +1532,41 @@
% \end{macrocode}
% \end{macro}
%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Supporting rollback \ldots
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\DeclareFontSeriesChangeRule}{Series change rules}%
+%<latexrelease> {\merge@font@shape}{Font shape change rules}%
%<latexrelease>
-%<latexrelease>\DeclareRobustCommand\fontseries[1]{\edef\f@series{#1}}
%<latexrelease>\DeclareRobustCommand\fontshape [1]{\edef\f@shape{#1}}
-%<latexrelease>\let\fontseriesforce\@undefined
%<latexrelease>\let\fontshapeforce\@undefined
%<latexrelease>
-%<latexrelease>\let\DeclareFontSeriesChangeRule\@undefined
-%<latexrelease>\let\merge@font@series\@undefined
-%<latexrelease>\let\merge@font@series@\@undefined
-%<latexrelease>\let\@font@shape@subst@warning\@undefined
-%<latexrelease>\let\maybe@load@fontshape\@undefined
-%<latexrelease>\let\set@target@series\@undefined
-%<latexrelease>\let\series@maybe@drop@one@m\@undefined
-%<latexrelease>\let\series@drop@one@m\@undefined
-%<latexrelease>\let\DeclareFontShapeChangeRule\@undefined
%<latexrelease>\let\merge@font@shape\@undefined
%<latexrelease>\let\merge@font@shape@\@undefined
+%<latexrelease>
+%<latexrelease>\let\merge@font@shape@without@substitution\@undefined
+%<latexrelease>\let\merge@font@shape@without@substitution@\@undefined
+%<latexrelease>\let\delayed@merge@font@shape\@undefined
+%<latexrelease>
%<latexrelease>\let\normalshape\@undefined
-%<latexrelease>\let\ulcshape\@undefined
-%<latexrelease>\let\ulcdefault\@undefined
-%<latexrelease>\let\swshape\@undefined
-%<latexrelease>\let\swdefault\@undefined
-%<latexrelease>\let\sscshape\@undefined
-%<latexrelease>\let\sscdefault\@undefined
-%<latexrelease>\let\normalshape\@undefined
+%<latexrelease>
% \end{macrocode}
% This is always called in \cs{document} so don't make it undefined.
% \begin{macrocode}
%<latexrelease>
%<latexrelease>\let\reinstall@nfss@defs\relax
%<latexrelease>\EndIncludeInRelease
-%<*2ekernel>
% \end{macrocode}
%
+%
+%
% This initializes the 2020/02/02 extensions to NFSS after any changes
% in the preamble.
% \changes{v1.0g}{2020/08/21}{Integration of new hook management interface}
% \begin{macrocode}
-%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}%
diff --git a/macros/latex/base/ltfssbas.dtx b/macros/latex/base/ltfssbas.dtx
index 30f500b6e4..df265d0b0f 100644
--- a/macros/latex/base/ltfssbas.dtx
+++ b/macros/latex/base/ltfssbas.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -35,7 +35,7 @@
%
%
\ProvidesFile{ltfssbas.dtx}
- [2020/12/10 v3.2h LaTeX Kernel (NFSS Basic Macros)]
+ [2021/04/26 v3.2i LaTeX Kernel (NFSS Basic Macros)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -896,15 +896,35 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/02/02}%
-%<latexrelease> {\usefont}{Drop m in usefont}%
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\usefont}{Force font face}%
\DeclareRobustCommand\usefont[4]{\fontencoding{#1}%
\edef\f@family{#2}%
\set@target@series{#3}%
- \edef\f@shape{#4}\selectfont
+ \edef\f@shape{#4}%
+% \end{macrocode}
+% Any earlier \cs{fontseries}, etc.\ should be canceled and we
+% should switch unconditionally to the requested font face so we
+% drop any code that may have been stored in
+% \cs{delayed@f@adjustment}.
+% \changes{v3.2i}{2021/04/26}{Unconditionally switch to the requested
+% font face (gh/444)}
+% \begin{macrocode}
+ \let\delayed@f@adjustment\@empty
+ \selectfont
\ignorespaces}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\usefont}{Drop m in usefont}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\usefont[4]{\fontencoding{#1}%
+%<latexrelease> \edef\f@family{#2}%
+%<latexrelease> \set@target@series{#3}%
+%<latexrelease> \edef\f@shape{#4}\selectfont
+%<latexrelease> \ignorespaces}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\usefont}{Drop m in usefont}%
%<latexrelease>
@@ -1403,7 +1423,7 @@
% The idea for this macro is stolen from the \texttt{substitutefont}
% package by Günter Milde, with some modifications and a new name.
%
-% Its purpose is to provide characters in a special encoding tht
+% Its purpose is to provide characters in a special encoding that
% are not available in the current font family to be taken from a
% different family that is visually compatible (or not if you
% choose badly). For example, you can match the GFS Didot Greek
@@ -1422,7 +1442,7 @@
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/02/02}%
-%<latexrelease> {\DeclareFontFamilySubstitution}{Provide family substituation}%
+%<latexrelease> {\DeclareFontFamilySubstitution}{Provide family substitution}%
\begingroup
\nfss@catcodes
\gdef\DeclareFontFamilySubstitution#1#2#3{%
@@ -1432,7 +1452,7 @@
% is better to handle that differently.
%
% Of course the families may still need loading at
-% this point and so we arange for this. Otherwise we might run into
+% this point and so we arrange for this. Otherwise we might run into
% trouble because the necessary \cs{DeclareFontFamily} has not been
% seen.
% \begin{macrocode}
@@ -1476,7 +1496,7 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\DeclareFontFamilySubstitution}{Provide family substituation}%
+%<latexrelease> {\DeclareFontFamilySubstitution}{Provide family substitution}%
%<latexrelease>
%<latexrelease>\let\DeclareFontFamilySubstitution\@undefined
%<latexrelease>\EndIncludeInRelease
@@ -1503,11 +1523,11 @@
\noexpand\@nil}%
% \end{macrocode}
% Initialize all those internal variables which may or may not have
-% values in the first seconds of NFSS' bootstraping process. Later
+% values in the first seconds of NFSS' bootstrapping process. Later
% on such values will be updated when an encoding is selected, etc.
%
% We definitely don't want to set |\f@encoding|; we can set all the
-% others since if they are left ``blank'' any selection would grap
+% others since if they are left ``blank'' any selection would grab
% ``error default values'' as well. However, this probably should
% go also---and now it did.
% \changes{v2.1n}{1994/05/14}{Don't set \cs{f@encoding}}
@@ -1559,7 +1579,7 @@
% \begin{macrocode}
%</2ekernel>
%<latexrelease>\IncludeInRelease{2015/01/01}{\wrong@fontshape}%
-%<latexrelease> {Font substituation in preamble}%
+%<latexrelease> {Font substitution in preamble}%
%<*2ekernel|latexrelease>
\def\wrong@fontshape{%
\csname D@\f@encoding\endcsname % install defaults if in math
@@ -1600,9 +1620,9 @@
% corresponding \texttt{.fd} file may not been loaded
% yet. Therefore we try this now. Otherwise equating the requested
% font shape with the finally selected fontshape below will fail
-% and can result in ``NFSS tables corruped''. After begin document
+% and can result in ``NFSS tables corrupted''. After begin document
% that will not happen as all \texttt{.fd} files involved in
-% substituation are loaded at |\begin{document}|.
+% substitution are loaded at |\begin{document}|.
% \begin{macrocode}
\begingroup
\try@load@fontshape
@@ -1681,7 +1701,7 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}{\wrong@fontshape}%
-%<latexrelease> {Font substituation in preamble}%
+%<latexrelease> {Font substitution in preamble}%
%<latexrelease>\def\wrong@fontshape{%
%<latexrelease> \csname D@\f@encoding\endcsname
%<latexrelease> \edef\reserved@a{\csname\curr@fontshape\endcsname}%
@@ -1856,7 +1876,7 @@
% it modifies the corresponding macro |\mv@|\meta{version}
% so that it calls |\getanddefine@fonts| directly in future as well.
% We use the macro |\extract@alph@from@version| to do this.
-% It takes the math alphabet identifer |#1| and the math version
+% It takes the math alphabet identifier |#1| and the math version
% macro as arguments.
% \changes{v1.9a}{1992/07/26}{}
% \begin{macrocode}
@@ -1944,7 +1964,7 @@
\use@mathgroup##1{#2}}}%
% \end{macrocode}
% \changes{v2.1t}{1994/10/15}{Warn if math alpha is used outside math}
-% In addtion it defines the alphabet the way it should be used from
+% In addition it defines the alphabet the way it should be used from
% now on.
% \begin{macrocode}
\gdef#3{\relax\ifmmode \else \non@alpherr#3\fi
diff --git a/macros/latex/base/ltfsscmp.dtx b/macros/latex/base/ltfsscmp.dtx
index 8583fb1a9b..03be855127 100644
--- a/macros/latex/base/ltfsscmp.dtx
+++ b/macros/latex/base/ltfsscmp.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -36,7 +36,7 @@
%
%
\ProvidesFile{ltfsscmp.dtx}
- [2015/06/23 v3.0f LaTeX Kernel (NFSS1 Compatibility)]
+ [2020/12/05 v3.0f LaTeX Kernel (NFSS1 Compatibility)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -181,7 +181,7 @@
\in@{pt}{#3}% not a proof but a good chance
\ifin@
% \end{macrocode}
-% We grap also everything after pt and discard it if people have
+% We grab also everything after pt and discard it if people have
% forgotten to place a percent sign there.
% \changes{v2.1d}{1994/02/10}{scan away stuff after pt}
% \begin{macrocode}
diff --git a/macros/latex/base/ltfssdcl.dtx b/macros/latex/base/ltfssdcl.dtx
index 291cd1368f..9710d54382 100644
--- a/macros/latex/base/ltfssdcl.dtx
+++ b/macros/latex/base/ltfssdcl.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -36,7 +36,7 @@
%
%
\ProvidesFile{ltfssdcl.dtx}
- [2020/03/19 v3.0v LaTeX Kernel (NFSS Declarative Interface)]
+ [2021/02/15 v3.0w LaTeX Kernel (NFSS Declarative Interface)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -490,7 +490,11 @@
in version \math@version}%
\@eha
\fi
- \else \expandafter\non@alpherr\fi
+% \end{macrocode}
+% extra \cs{expandafter} to remove the \cs{expandafter} added below
+% \changes{v3.0w}{2021/02/115}{fix for (gh/501)}
+% \begin{macrocode}
+ \else \expandafter\expandafter\expandafter\non@alpherr\fi
% \end{macrocode}
% If the legacy interface is used, e.g., \verb=$\sf -1$= the math
% alphabet \verb=#1= does not take an argument so we better do not
@@ -747,7 +751,7 @@
\@font@info{Redeclaring symbol font `#1'}%
% \end{macrocode}
% \changes{v3.0f}{1997/11/13}
-% {(DPC) Really update \cs{group@list} dont
+% {(DPC) Really update \cs{group@list} don't
% leave new version in \cs{toks@}. latex/2661}
% Update the group list.
% \begin{macrocode}
@@ -1526,7 +1530,7 @@
\def\set@mathdelimiter#1#2#3#4#5#6{%
% \end{macrocode}
% We use \cs{protected} not \cs{MakeRobust} so that
-% \verb=\bigl\lfoor= etc.\ works inside \cs{protected@edef}.
+% \verb=\bigl\lfoor= etc.\ works inside the argument of \cs{protected@edef}.
% \changes{v3.0s}{2019/08/27}{Make math delimiters robust}
% \changes{v3.0t}{2020/01/20}{fix for gh/251}
% \begin{macrocode}
@@ -1733,7 +1737,7 @@
\relax
% \end{macrocode}
% If it is undefined, fine otherwise check if it is a math alphabet
-% defined via |\DeclareSymbolFontAlphabet|:
+% defined via \\ |\DeclareSymbolFontAlphabet|:
% \begin{macrocode}
\else
\edef\reserved@a{%
diff --git a/macros/latex/base/ltfssini.dtx b/macros/latex/base/ltfssini.dtx
index fbea725c1d..b06fc161b0 100644
--- a/macros/latex/base/ltfssini.dtx
+++ b/macros/latex/base/ltfssini.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -36,7 +36,7 @@
%
%
\ProvidesFile{ltfssini.dtx}
- [2020/10/08 v3.2e LaTeX Kernel (NFSS Initialisation)]
+ [2021/04/26 v3.2h LaTeX Kernel (NFSS Initialisation)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -56,7 +56,7 @@
%
% \GetFileInfo{ltfssini.dtx}
% \title{A new font selection scheme for \TeX{} macro packages\\
-% (Initialisation)\thanks
+% (Initialization)\thanks
% {This file has version number
% \fileversion\ dated \filedate}}
%
@@ -83,7 +83,7 @@
% \changes{v3.1d}{2019/08/27}{Make various commands robust}
%
%
-% \section{NFSS Initialisation}
+% \section{NFSS Initialization}
%
% \iffalse
%<+checkmem>\CHECKMEM
@@ -301,7 +301,7 @@
\else
% \end{macrocode}
%
-% \changes{v3.1g}{2020/02/05}{Clarrified error text}
+% \changes{v3.1g}{2020/02/05}{Clarified error text}
% \begin{macrocode}
\@latex@error{Wrong syntax for \string\DeclareFontSeriesDefault}%
{Mandatory first argument must be 'md' or 'bf'.}
@@ -431,7 +431,7 @@
%<+debug> \series@change@debug{No series preparation (forced \f@series)\on@line}%
\fontfamily#2%
\else
-%<+debug> \series@change@debug{Prepearing for switching to #1 (#2)\on@line}%
+%<+debug> \series@change@debug{Preparing for switching to #1 (#2)\on@line}%
\expand@font@defaults
% \end{macrocode}
% We prepare for changing the current series. We have to find it
@@ -448,7 +448,7 @@
% \item \cs{bfseries} is called for a family using \texttt{bx}
% (e.g., CMR)
% \item Switch to a font family that is none of the meta
-% families, e.g., via \verb=\fontfamily{ptm}\selectfont=
+% families, e.g., via \verb=\fontfamily{ptm}\allowbreak\verb=\selectfont=
% \item Then none of the real meta families, match but the final
% \verb=\@elt{??}= will.
% \item Therefore if the current series is \cs{mddefault} or
@@ -493,7 +493,7 @@
% \end{macrocode}
% The \cs{target@series@value} may contain something like
% \texttt{cm} (coming from a default) and so we can't directly
-% asign it to \cs{f@series} be have to drop any surplus \texttt{m}
+% assign it to \cs{f@series} be have to drop any surplus \texttt{m}
% first.
% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from
% \cs{target@series@value} (gh/291)}
@@ -513,7 +513,7 @@
% In this macro used in the look you basically find the nested
% \cs{ifx}s from the outline above. The only difference is that is
% it is parameterized instead of being written out and only for one
-% block of tests because the code is called reatedly when looping
+% block of tests because the code is called repeatedly when looping
% over the meta family list. From the list we get each meta family
% name in turn.
% \begin{macrocode}
@@ -665,7 +665,7 @@
% the now current series value (in \cs{f@series}).
%
% But what should happen if \cs{seriesdefault} got explicitly
-% changed? In that case the explicit change should surive and we
+% changed? In that case the explicit change should survive and we
% should not alter \cs{seriesdefault}. This is solved by comparing
% the current value of \cs{seriesdefault} with a kernel version
% saved in the format and if they differ we do not call
@@ -915,9 +915,9 @@
%\end{verbatim}
% We have to do the testing while the current family is still
% unchanged but we have to do the adjustment of the series after it
-% got changed (because the new family might has different sets
-% ofshapes available and we certainly don't want to see
-% substituation going on. So we use \cs{target@series@value} to
+% got changed (because the new family might have different sets
+% of shapes available and we certainly don't want to see
+% substitution going on. So we use \cs{target@series@value} to
% hold the target series (if any).
%\begin{verbatim}
% \let\target@series@value\@empty
@@ -1088,6 +1088,8 @@
% \end{macro}
%
%
+% \changes{v3.2g}{2021/03/18}
+% {Add legacy hook definitions for rollback.}
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
@@ -1140,6 +1142,9 @@
%<latexrelease> \prepare@family@series@update{tt}\ttdefault
%<latexrelease> \@ttfamilyhook
%<latexrelease> \selectfont}
+%<latexrelease>\let\@rmfamilyhook\@empty
+%<latexrelease>\let\@sffamilyhook\@empty
+%<latexrelease>\let\@ttfamilyhook\@empty
%<latexrelease>
% \end{macrocode}
%
@@ -1183,7 +1188,7 @@
% to different NFSS axis values it becomes important to have the
% ability to determine the current context as we can no longer look
% at \cs{f@series} to answer a question such as ``am I currently
-% typsetting in a bold typeface?''
+% typesetting in a bold typeface?''
%
% This is provided by the test \cs{IfFontSeriesContextTF}. It takes
% three arguments:
@@ -1221,7 +1226,7 @@
\DeclareRobustCommand\IfFontSeriesContextTF[1]{%
\expand@font@defaults
% \end{macrocode}
-% In the beginning we haven't found the context we are loking for.
+% In the beginning we haven't found the context we are looking for.
% \begin{macrocode}
\@font@series@contextfalse
% \end{macrocode}
@@ -1238,7 +1243,7 @@
\expandafter\edef\csname ??def@ult\endcsname{\f@family}%
% \end{macrocode}
% Then we run through the meta family list (currently containing
-% just the three values) followed by the artifical meta family
+% just the three values) followed by the artificial meta family
% \texttt{??} and test each of them in turn using
% \cs{test@font@series@context} as the testing command.
% \begin{macrocode}
@@ -1264,7 +1269,7 @@
% \begin{macro}{\test@font@series@context}
% This tests the context (stored in \cs{requested@test@context})
-% and updates the bookean if the right context is found.
+% and updates the boolean if the right context is found.
% \begin{macrocode}
\def\test@font@series@context#1{%
% \end{macrocode}
@@ -1307,8 +1312,9 @@
}
% \end{macrocode}
% \end{macro}
-
-
+%
+%
+%
% \begin{macro}{\if@font@series@context}
% The boolean to signal if we found the requested font series context.
% \begin{macrocode}
@@ -1334,19 +1340,21 @@
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
-
-
-
+%
+%
+%
+%
+%
%
% \section{Supporting nested emphasis}
%
% By default \LaTeXe{} supports two levels of nested emphasis: if
% the current font has an upright shape then it switches to
% \cs{itshape} otherwise to \cs{eminnershape} (which defaults to
-% \cs{upshape}). This means nested emphasis will ocssilate between
+% \cs{upshape}). This means nested emphasis will oscillate between
% italic and upright shapes.
%
-% Sometimes it would be nice to allow for a more lengthly sequence,
+% Sometimes it would be nice to allow for a more lengthy sequence,
% but instead of providing a fixed one \LaTeX{} now offers a
% general mechanism that allows to define arbitrary sequences.
%
@@ -1377,7 +1385,7 @@
% \begin{macro}{\DeclareEmphSequence}
%
% \cs{DeclareEmphSequence} expects a clist of declaration. Spaces in the
-% argument are dropped to avoid surious spaces in the output. The
+% argument are dropped to avoid spurious spaces in the output. The
% declarations are additive. At the very end the shape is reset
% using |\emreset| and |\emforce| so that this case is never
% skipped.\footnote{Maybe we should not add \cs{emforce} but allow
@@ -1401,9 +1409,9 @@
\let\emfontdeclare@clist\@empty
% \end{macrocode}
% \end{macro}
-
-
-
+%
+%
+%
% \begin{macro}{\emrest}
% Reset the font to upright and upper/lower case. With the default rules
% using \cs{shapedefault} does that for us but to be on the safe side we
@@ -1412,12 +1420,13 @@
\DeclareRobustCommand\emreset{\upshape\ulcshape}
% \end{macrocode}
% \end{macro}
-
-
-
+%
+%
+%
% \begin{macro}{\em}
-% The new definition for \cs{em} (and implicitly \cs{emph} is like
-% it was before if \cs{emfontdeclare@clist} is empty.
+%
+% The new definition for \cs{em} (and implicitly \cs{emph}) is the
+% same as before as long as \cs{emfontdeclare@clist} is empty.
% \begin{macrocode}
\DeclareRobustCommand\em{%
\@nomath\em
@@ -1479,7 +1488,7 @@
% \begin{macrocode}
\expandafter\ifx\csname \curr@fontshape/\f@size\em@force
% \end{macrocode}
-% For the comparison with \cs{ifx} we have to exand
+% For the comparison with \cs{ifx} we have to expand
% \cs{em@currfont} once as the relevant info is inside.
% \begin{macrocode}
\expandafter\endcsname
@@ -1761,7 +1770,7 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease>\IncludeInRelease{2021/06/01}%
%<latexrelease> {\normalfont}{Add hook to \normalfont}%
\DeclareRobustCommand\normalfont{%
% \end{macrocode}
@@ -1774,6 +1783,15 @@
\edef\f@series{\seriesdefault}%
\edef\f@shape{\shapedefault}%
% \end{macrocode}
+% Any earlier \cs{fontseries}, etc.\ should be canceled and we
+% should switch unconditionally to the requested font face so we
+% drop any code that may have been stored in
+% \cs{delayed@f@adjustment}.
+% \changes{v3.2h}{2021/04/26}{Unconditionally switch to the requested
+% font face (gh/444)}
+% \begin{macrocode}
+ \let\delayed@f@adjustment\@empty
+% \end{macrocode}
%
% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
% \begin{macrocode}
@@ -1785,18 +1803,54 @@
\@defaultfamilyhook % hookname from 2020/02 will vanish
\selectfont}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\let\reset@font\normalfont
% \end{macrocode}
% \end{macro}
% \end{macro}
-%
+%
%
%
% \begin{macrocode}
+% \changes{v3.2g}{2021/03/18}
+% {Add missing 2020/02/02 latexrelease entry.}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\normalfont}{Add hook to \normalfont}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\normalfont{%
+%<latexrelease> \fontencoding\encodingdefault
+%<latexrelease> \edef\f@family{\familydefault}%
+%<latexrelease> \edef\f@series{\seriesdefault}%
+%<latexrelease> \edef\f@shape{\shapedefault}%
+%<latexrelease> \UseHook{normalfont}%
+%<latexrelease> \@defaultfamilyhook % hookname from 2020/02 will vanish
+%<latexrelease> \selectfont}
+%<latexrelease>
+%<latexrelease>\let\reset@font\normalfont
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\normalfont}{Add hook to \normalfont}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\normalfont{%
+%<latexrelease> \fontencoding\encodingdefault
+%<latexrelease> \edef\f@family{\familydefault}%
+%<latexrelease> \edef\f@series{\seriesdefault}%
+%<latexrelease> \edef\f@shape{\shapedefault}%
+%<latexrelease> \@defaultfamilyhook
+%<latexrelease> \selectfont}
+%<latexrelease>
+%<latexrelease>\let\reset@font\normalfont
+%<latexrelease>
+%<latexrelease>\let\@defaultfamilyhook\@empty
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\normalfont}{Add hook to \normalfont}%
%<latexrelease>
@@ -1863,8 +1917,20 @@
% \changes{v3.1c}{2019/07/09}{Explicitly set some defaults}
% \begin{macrocode}
\fontfamily{cmr}
-\fontseries{m}
-\fontshape{n}
+% \end{macrocode}
+%
+% \changes{v3.2f}{2020/12/04}{Adjust start values for series and shape (gh/444)}
+% Previously the default values for series and shape were set by
+% calling \cs{fontseries} and \cs{fontshape}, but their action is
+% now delayed until \cs{selectfont} which isn't called inside the
+% format (to avoid unnecessarily loading a font that may never get used).
+% We therefore have to set \cs{f@series} and \cs{f@shape} directly instead.
+% \begin{macrocode}
+\def\f@series{m} % \fontseries{m}
+\def\f@shape{n} % \fontshape{n}
+% \end{macrocode}
+%
+% \begin{macrocode}
\fontsize{10}{10}
% \end{macrocode}
%
diff --git a/macros/latex/base/ltfsstrc.dtx b/macros/latex/base/ltfsstrc.dtx
index 055f408ceb..c6aec105ba 100644
--- a/macros/latex/base/ltfsstrc.dtx
+++ b/macros/latex/base/ltfsstrc.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -30,14 +30,14 @@
% \iffalse
%%% From File: ltfsstrc.dtx
%% Copyright (C) 1989-97 by Frank Mittelbach and Rainer Sch\"opf.
-%% Copyright (C) 1994-97 by LaTeX3 project. All rights reserved.
+%% Copyright (C) 1994-97 by LaTeX Project. All rights reserved.
%
-%<package>\NeedsTeXFormat{LaTeX2e}[1995/05/16]
+%<package>\NeedsTeXFormat{LaTeX2e}[2021/06/01]
%<package>\ProvidesPackage{tracefnt}
-%<package> [2019/10/11 v3.0l Standard LaTeX package (font tracing)]
+%<package> [2020/12/22 v3.0n Standard LaTeX package (font tracing)]
% \fi
% \ProvidesFile{ltfsstrc.dtx}
-% [2020/02/03 v3.0l LaTeX Kernel (NFSS tracing)]
+% [2021/04/26 v3.0o LaTeX Kernel (NFSS tracing)]
%
% \iffalse
%<+checkmem>\CHECKMEM
@@ -190,7 +190,7 @@
% special package file named \texttt{trace.sty}.\footnote{This package
% is not in distribution at the moment (and probably doesn't any
% longer work). Think of this part of the code as being historical
-% artefacts.}
+% artifacts.}
% \begin{macrocode}
%<+debug> \input trace.sty
% \end{macrocode}
@@ -420,19 +420,25 @@
% \end{macrocode}
% \end{macro}
%
+
+% \begin{macrocode}
+%<*2ekernel|latexrelease|package>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\selectfont}{Add hook to \selectfont}%
+% \end{macrocode}
+%
%
-% \changes{v1.0j}{1990/02/18}
-% {Redefine unprotected version \cs{p@selectfont}
-% instead of \cs{selectfont}.}
%
%
% \begin{macro}{\selectfont}
+% \changes{v1.0j}{1990/02/18}
+% {Redefine unprotected version \cs{p@selectfont}
+% instead of \cs{selectfont}.}
% \changes{v1.1a}{1989/12/16}{Changed order of calls.}
% \changes{v2.3f}{1994/05/12}{Use \cs{DeclareRobustCommand}}
% The macro |\selectfont| is called whenever a font change must
% take place.
% \begin{macrocode}
-%<*2ekernel|package>
\DeclareRobustCommand\selectfont
{%
% \end{macrocode}
@@ -456,6 +462,77 @@
\ifx\f@linespread\baselinestretch \else
\set@fontsize\baselinestretch\f@size\f@baselineskip \fi
% \end{macrocode}
+%
+% The series and shape updates are only prepared by
+% \cs{fontseries} and \cs{fontshape} but not executed until after
+% we are ready to change the font face. This way they happen after
+% a possibly new family is set which is important because they
+% look at the available font faces in that family and alter the
+% selection based on availibility. Several calls to \cs{fontseries}
+% or \cs{fontshape} are delayed in the order in which they appear,
+% so that by switching them one can work around missing
+% intermediate font faces and avoid substitutions.
+%
+% We first attempt to do the merge without any substitution. As we
+% might end up with a non-existing font face we may have to restart
+% and therefore save the current values of \cs{f@series} and
+% \cs{f@shape} before the merge.
+%
+% But first we make a quick test to see if there are any delayed
+% actions, because if not it is pointless to make all the
+% assignments and try loading a missing fontshape.
+%
+% \changes{v3.0n}{2020/12/22}{Execute delayed series and shape updates (gh/444)}
+% \begin{macrocode}
+ \ifx\delayed@f@adjustment\@empty
+ \else
+ \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
+% \begin{macrocode}
+ \delayed@f@adjustment
+% \end{macrocode}
+% We then check if the resulting cominbation is valid but for this
+% we have to make sure the the appropiate \texttt{.fd} is loaded if
+% that hasn't happened so far.
+% \begin{macrocode}
+ \maybe@load@fontshape
+ \ifcsname \f@encoding/\f@family/\f@series/\f@shape \endcsname
+% \end{macrocode}
+% If this macro is defined then we are good and no further action
+% is necessary.
+%
+% Otherwise the combination is not valid, so we redo the merge but
+% this time with substitutions.
+% \begin{macrocode}
+ \else
+ \let\f@shape\f@shape@saved
+ \let\f@series\f@series@saved
+ \let\delayed@merge@font@shape\merge@font@shape
+ \let\delayed@merge@font@series\merge@font@series
+ \delayed@f@adjustment
+ \let\delayed@merge@font@shape\merge@font@shape@without@substitution
+ \let\delayed@merge@font@series\merge@font@series@without@substitution
+ \fi
+% \end{macrocode}
+% Now the series and shape values are updated and we clear
+% \cs{delayed@f@adjustment}. This is important because on the next
+% execution of \cs{selectfont} we should not mistakenly redo the
+% delayed actions if there wasn't any series or shape change.
+% \begin{macrocode}
+ \let\delayed@f@adjustment\@empty
+ \fi
+% \end{macrocode}
+% If the series was forced we should now cancel that in case the
+% next series change is done with some low-level setting to
+% \cs{f@series}.
+% \changes{v3.0o}{2021/04/26}{Unset the forced series boolean when reaching
+% \cs{selectfont} (gh/444)}
+% \begin{macrocode}
+ \@forced@seriesfalse
+% \end{macrocode}
% Then we generate the internal name of the font
% by concatenating {\em family}, {\em series},
% {\em shape}, and current {\em size},
@@ -478,18 +555,13 @@
% \begin{macrocode}
\font@name
% \end{macrocode}
-% If |\tracingfonts| is
-% greater than 2 we also show the font switch.
-% We do this before |\glb@settings| is called since this
-% macro might redefine |\font@name|.
-% \changes{v1.0k}{1990/03/14}{Added code for TeX3.}
-% \changes{v1.0i}{1990/02/16}{Changed \cs{f@size} to \cs{lcl@currsize}
-% (see fam file).}
+%
+% After switching fonts we run a hook, so that packages can make
+% last minute alterations based on the new font (originally provided
+% in \pkg{everysel} but using a different interface).
+% \changes{v3.0m}{2020/12/03}{Install a hook in \cs{selectfont} (gh/444)}
% \begin{macrocode}
-%<*trace>
- \ifnum \tracingfonts>\tw@
- \@font@info{Switching to \font@name}\fi
-%</trace>
+ \UseHook{selectfont}%
% \end{macrocode}
% Finally we call |\size@update|. This macro is normally empty but
% will contain actions (like setting the |\baselineskip|) that have
@@ -514,11 +586,69 @@
% \end{macro}
%
%
+% \begin{macro}{selectfont}
+% Declare the hook used in selecfont in the kernel, but not
+% inside the \pkg{tracefnt} package.
+% \begin{macrocode}
+%<-trace>\NewHook{selectfont}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% If |\tracingfonts| is
+% greater than 2 we also show the font switch inside \cs{selectfont}.
+% We do this by adding this code to the hook in the \pkg{tracefnt} package:
+% macro might redefine |\font@name|.
+% \begin{macrocode}
+%<*trace>
+\AddToHook{selectfont}
+ {\ifnum \tracingfonts>\tw@
+ \@font@info{Switching to \font@name}\fi}
+%</trace>
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease|package>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% With \cs{selectfont} having different definitions in different
+% kernels we also have to provide them in the \texttt{tracefnt}
+% package to support rollback. In packages that works a bit
+% differently and therefore we have to provide an empty block there.
+% \begin{macrocode}
+%<package>\IncludeInRelease{2021/06/01}%
+%<package> {\selectfont}{Add hook to \selectfont}%
+%<package>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease|package>\IncludeInRelease{0000/00/00}%
+%<latexrelease|package> {\selectfont}{Add hook to \selectfont}%
+%<latexrelease|package>
+%<latexrelease|package>\DeclareRobustCommand\selectfont
+%<latexrelease|package> {%
+%<latexrelease|package> \ifx\f@linespread\baselinestretch \else
+%<latexrelease|package> \set@fontsize\baselinestretch\f@size\f@baselineskip \fi
+%<latexrelease|package> \xdef\font@name{%
+%<latexrelease|package> \csname\curr@fontshape/\f@size\endcsname}%
+%<latexrelease|package> \pickup@font
+%<latexrelease|package> \font@name
+%<latexrelease|package> \size@update
+%<latexrelease|package> \enc@update
+%<latexrelease|package> }
+%<latexrelease|package>
+%<latexrelease|package>\EndIncludeInRelease
+% \end{macrocode}
+%
+%
%
% \begin{macro}{\set@fontsize}
% The macro |\set@fontsize| does the actual work. First it assigns
% new values to |\f@size|, |\f@baselineskip| and |\f@linespread|.
% \begin{macrocode}
+%<*2ekernel|package>
\def\set@fontsize#1#2#3{%
\@defaultunits\@tempdimb#2pt\relax\@nnil
\edef\f@size{\strip@pt\@tempdimb}%
@@ -1245,7 +1375,7 @@
% Now, we are through with the case of a simple size, except for
% calling the size function. This will be handled later, as it is
% the same mechanism for all types of size specification. We will
-% now proceed to macors for extraction of size range specification.
+% now proceed to macros for extraction of size range specification.
%
%
%
diff --git a/macros/latex/base/lthooks-code.pdf b/macros/latex/base/lthooks-code.pdf
index b209ada543..27e926f575 100644
--- a/macros/latex/base/lthooks-code.pdf
+++ b/macros/latex/base/lthooks-code.pdf
Binary files differ
diff --git a/macros/latex/base/lthooks-doc.pdf b/macros/latex/base/lthooks-doc.pdf
index b72a3e2b2f..01a03ff1af 100644
--- a/macros/latex/base/lthooks-doc.pdf
+++ b/macros/latex/base/lthooks-doc.pdf
Binary files differ
diff --git a/macros/latex/base/lthooks.dtx b/macros/latex/base/lthooks.dtx
index 0a04c38efb..20e172a57f 100644
--- a/macros/latex/base/lthooks.dtx
+++ b/macros/latex/base/lthooks.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
-%%
-%% File: lthooks.dtx (C) Copyright 2020 Frank Mittelbach,
-%% Phelype Oleinik & LaTeX Team
+%
+% Copyright (C) 2020-2021
+% Frank Mittelbach, Phelype Oleinik & LaTeX Team
%
% This file is part of the LaTeX base system.
% -------------------------------------------
@@ -31,8 +31,8 @@
%%% From File: lthooks.dtx
%
% \begin{macrocode}
-\def\lthooksversion{v1.0h}
-\def\lthooksdate{2021/01/07}
+\def\lthooksversion{v1.0n}
+\def\lthooksdate{2021/05/26}
% \end{macrocode}
%
%<*driver>
@@ -54,6 +54,9 @@
}
\ExplSyntaxOff
+\providecommand\InternalDetectionOff{}
+\providecommand\InternalDetectionOn{}
+
\EnableCrossrefs
\CodelineIndex
\begin{document}
@@ -64,10 +67,13 @@
% \fi
%
%
-% \long\def\fmi#1{\begin{quote}\itshape FMi: #1\end{quote}}
-% \long\def\pho#1{\begin{quote}\itshape PhO: #1\end{quote}}
+% \providecommand\hook[1]{\texttt{#1}}
+%
+% \providecommand\fmi[1]{\marginpar{\footnotesize FMi: #1}}
+% \providecommand\fmiinline[1]{\begin{quote}\itshape\footnotesize FMi: #1\end{quote}}
+% \providecommand\pho[1]{\marginpar{\footnotesize PhO: #1}}
+% \providecommand\phoinline[1]{\begin{quote}\itshape\footnotesize PhO: #1\end{quote}}
%
-% \newcommand\hook[1]{\texttt{#1}}
%
%
% \title{The \texttt{lthooks} package\thanks{This package has version
@@ -119,14 +125,15 @@
%
% \subsection{\LaTeXe\ interfaces}
%
-% \subsubsection{Declaring hooks and using them in code}
+% \subsubsection{Declaring hooks}
%
-% With two exceptions, hooks have to be declared before they can be
-% used. The exceptions are hooks in environments (i.e., executed at
-% \cs{begin} and \cs{end}) and hooks run when loading files,
-% e.g. before and after a package is loaded, etc. Their hook names
-% depend on the environment or the file name and so declaring them
-% beforehand is difficult.
+% With a few exceptions, hooks have to be declared before they can
+% be used. The exceptions are the generic hooks for commands,
+% environments (i.e., executed at \cs{begin} and \cs{end}) and
+% hooks run when loading files, e.g. before and after a package is
+% loaded, etc. Their hook names depend on the command,
+% environment or the
+% file name and so declaring them beforehand is not practical.
%
%
% \begin{function}{\NewHook}
@@ -173,6 +180,62 @@
% \end{function}
%
%
+% \subsubsection{Special declarations for hooks}
+%
+% The declarations here should normally not be used. They are available
+% to provide support for special use cases mainly involving
+% generic command hooks.
+%
+% \begin{function}{\DisableHook}
+% \begin{syntax}
+% \cs{DisableHook} \Arg{hook}
+% \end{syntax}
+% After this declaration the \meta{hook} is no longer usable: Any
+% attempt to add further code to it will result in an error and any
+% use, e.g., via \cs{UseHook}, will simply do nothing.
+%
+% This is intended to be used with generic command hooks (see
+% \texttt{ltcmdhooks-doc}) as depending on the definition of the
+% command such generic hooks may be unusable. If that is known, a
+% package developer can disable such hooks up front.
+%
+% 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}{\ProvideHook}
+% \begin{syntax}
+% \cs{ProvideHook} \Arg{hook}
+% \end{syntax}
+% Like \cs{NewHook} but does nothing if the hook was previously
+% declared with \cs{NewHook}. This declaration should only be used
+% in special situations, e.g., when command of another package
+% need to be altered and it is is not clear if for that command a
+% generic hook was already explicitly declared before.
+%
+% Normally \cs{NewHook} should be used instead.
+% \end{function}
+%
+% \begin{function}{\ProvideReversedHook}
+% \begin{syntax}
+% \cs{ProvideReversedHook} \Arg{hook}
+% \end{syntax}
+% Like \cs{NewReversedHook} but does nothing if the hook was
+% previously declared as a reversed hook.
+% \end{function}
+%
+% \begin{function}{\ProvideMirroredHookPair}
+% \begin{syntax}
+% \cs{ProvideMirroredHookPair} \Arg{hook-1} \Arg{hook-2}
+% \end{syntax}
+% A shorthand for
+% \cs{ProvideHook}\Arg{hook-1}\cs{ProvideReversedHook}\Arg{hook-2}.
+% \end{function}
+%
+%
+%
+% \subsubsection{Using hooks in code}
%
%
% \begin{function}{\UseHook}
@@ -198,7 +261,7 @@
% Some hooks are only used (and can be only used) in one place, for
% example, those in \verb=\begin{document}= or
% \verb=\end{document}=. Once we have passed that point adding to
-% the hook through a defined \cs{\meta{addto-cmd}} command (e.g.,
+% the hook through a defined \cs[no-index]{\meta{addto-cmd}} command (e.g.,
% \cs{AddToHook} or \cs{AtBeginDocument}, etc.\@) would have no
% effect (as would the use of such a command inside the hook code
% itself). It is therefore customary to redefine
@@ -209,10 +272,12 @@
% consumed and any further attempt to add to it will result in
% executing the code to be added immediately.
%
-% \fmi{Maybe add an error version as well?}
+% \fmiinline{Maybe add an error version as well?}
%
% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
-% A leading |.| is treated literally.
+% A leading |.| is treated literally. See
+% section~\ref{sec:default-label} for details.
+
% \end{function}
%
%
@@ -261,9 +326,10 @@
% that label, the removal order takes action and the code is not
% added.
%
-% If the optional argument is \texttt{*}, then all code chunks are
+% If the optional \meta{label} argument is \texttt{*}, then all code chunks are
% removed. This is rather dangerous as it drops code from other
-% packages one may not know about!
+% packages one may not know about and should therefore not by used
+% by packages but only in document preambles!
%
% The \meta{hook} and \meta{label} can be specified using the
% dot-syntax to denote the current package name.
@@ -296,7 +362,7 @@
%\end{verbatim}
% because that only \enquote{adds} a further empty chunk of code to
% the hook. Adding \cs{normalsize} would work but that means the hook
-% then contained \cs{small}\cs{normalsize} which means to font size
+% then contained \cs{small}\cs{normalsize} which means two font size
% changes for no good reason.
%
% The above is only needed if one wants to typeset several quotes in a
@@ -356,10 +422,9 @@
% \meta{label} throughout the sub-packages in order to avoid
% that the labels change if you internally reorganize your code.
%
-% Except for \cs{UseHook}, \cs{UseOneTimeHook}, \cs{IfHookEmptyTF}, and
-% \cs{IfHookExistsTF} (and their \pkg{expl3} interfaces \cs{hook_use:n},
-% \cs{hook_use_once:n}, \cs{hook_if_empty:nTF}, and
-% \cs{hook_if_exist:nTF}), all \meta{hook}
+% Except for \cs{UseHook}, \cs{UseOneTimeHook} and \cs{IfHookEmptyTF}
+% (and their \pkg{expl3} interfaces \cs{hook_use:n},
+% \cs{hook_use_once:n} and \cs{hook_if_empty:nTF}, all \meta{hook}
% and \meta{label} arguments are processed in the same way: first,
% spaces are trimmed around the argument, then it is fully expanded
% until only character tokens remain. If the full expansion of the
@@ -367,8 +432,8 @@
% token, a low-level \TeX{} error is raised (namely, the \meta{hook} is
% expanded using \TeX's \cs{csname}\ldots\cs{endcsname}, as such,
% Unicode characters are allowed in \meta{hook} and \meta{label}
-% arguments). The arguments of \cs{UseHook}, \cs{UseOneTimeHook},
-% \cs{IfHookEmptyTF}, and \cs{IfHookExistsTF} are
+% arguments). The arguments of \cs{UseHook}, \cs{UseOneTimeHook}, and
+% \cs{IfHookEmptyTF} are
% processed much in the same way except that spaces are not trimmed
% around the argument, for better performance.
%
@@ -422,8 +487,7 @@
% this syntax is not available in \cs{UseHook} (and \cs{hook_use:n})
% because the hook is most of the time used outside of the package file
% in which it was defined. This syntax is also not available in the hook
-% conditionals \cs{IfHookEmptyTF} (and \cs{hook_if_empty:nTF}) and
-% \cs{IfHookExistsTF} (and \cs{hook_if_exist:nTF}) because these
+% conditionals \cs{IfHookEmptyTF} (and \cs{hook_if_empty:nTF}), because these
% conditionals are used in some performance-critical parts of the hook
% management code, and because they are usually used to refer to other
% package's hooks, so the dot-syntax doesn't make much sense.
@@ -432,7 +496,7 @@
% it in logical parts, but still use the main package name as
% \meta{label}, then the \meta{default label} can be set using
% \cs{SetDefaultHookLabel} or
-% \cs{PushDefaultHookLabel}..\cs{PopDefaultHookLabel}.
+% \cs{PushDefaultHookLabel}\verb={..}=\,\ldots\cs{PopDefaultHookLabel}.
%
% \begin{function}{\PushDefaultHookLabel,\PopDefaultHookLabel}
% \begin{syntax}
@@ -595,7 +659,7 @@
% There can only be a single relation between two labels for a
% given hook,
% i.e., a later \cs{DeclareHookrule} overwrites any previous
-% delcaration.
+% declaration.
%
% The \meta{hook} and \meta{label} can be specified using the
% dot-syntax to denote the current package name.
@@ -648,9 +712,10 @@
% \item exist and be non-empty; and
% \item not exist (in which case emptiness doesn't apply);
% \end{itemize}
-% Hooks are a bit more complicated: they have four possible states.
-% A hook may exist or not, and either way it may or may not be empty.
-% This means that even a hook that doesn't exist may be non-empty.
+% Hooks are a bit more complicated:
+% a hook may exist or not, and either way it may or may not be empty.
+% This means that even a hook that doesn't exist may be non-empty and
+% it can also be disabled.
%
% This seemingly strange state may happen when, for example, package~$A$
% defines hook \hook{A/foo}, and package $B$ adds some code to that
@@ -661,11 +726,17 @@
% querying the existence of a hook doesn't imply its emptiness, neither
% does the other way around.
%
+% Given that code or rules can be added to a hook even if it doesn't
+% physically exist yet, means that a querying its existence has no
+% real use case (in contrast to other variables that can only be
+% update if they have already been declared). For that reason only the
+% test for emptiness has a public interface.
+%
% A hook is said to be empty when no code was added to it, either to
% its permanent code pool, or to its ``next'' token list. The hook
% doesn't need to be declared to have code added to its code pool.
% A hook is said to exist when it was declared with \cs{NewHook} or
-% some variant thereof. Generic \hook{file} and \hook{env} hooks are
+% some variant thereof. Generic hooks such as \hook{file} and \hook{env} hooks are
% automatically declared when code is added to them.
%
% \begin{function}[EXP]{\IfHookEmptyTF}
@@ -673,7 +744,8 @@
% \cs{IfHookEmptyTF} \Arg{hook} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the \meta{hook} is empty (\emph{i.e.}, no code was added to
-% it using either \cs{AddToHook} or \cs{AddToHookNext}), and
+% it using either \cs{AddToHook} or \cs{AddToHookNext}) or such code
+% was removed again (via \cs{RemoveFromHook}), and
% branches to either \meta{true code} or \meta{false code} depending
% on the result.
%
@@ -681,30 +753,7 @@
% A leading |.| is treated literally.
% \end{function}
%
-% \begin{function}[EXP]{\IfHookExistsTF}
-% \begin{syntax}
-% \cs{IfHookExistsTF} \Arg{hook} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests if the \meta{hook} exists (if it was created with either
-% \cs{NewHook}, \cs{NewReversedHook}, or \cs{NewMirroredHookPair}), and
-% branches to either \meta{true code} or \meta{false code} depending
-% on the result.
-%
-% The existence of a hook usually doesn't mean much from the viewpoint
-% of code that tries to add/remove code from that hook, since package
-% loading order may vary, thus the creation of hooks is asynchronous
-% to adding and removing code from it, so this test should be used
-% sparingly.
-%
-% Generic hooks are declared at the time code is added to them, so the
-% result of \cs{hook_if_exist:n} will change once code is added to
-% said hook (unless the hook was previously declared).
-%
-% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
-% A leading |.| is treated literally.
-% \end{function}
%
-% \fmi{Would be helpful if we provide some use cases}
%
% \subsubsection{Displaying hook code}
%
@@ -807,7 +856,7 @@
% \meta{label-2}, in that order, as detailed in \cs{DeclareHookRule}.
% If the relation is \texttt{default} it means that that rule applies
% to \meta{label-1} and \meta{label-2} in \emph{all} hooks, (unless
-% overrided by a non-default relation).
+% overridden by a non-default relation).
%
% Finally, line~14 lists the labels in the hook after sorting;
% that is, in the order they will be executed when the hook is used.
@@ -819,7 +868,7 @@
% \begin{syntax}
% \cs{DebugHooksOn}
% \end{syntax}
-% Turn the debugging of hook code on or off. This displays changes
+% 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
% not really intended for normal use.
% \end{function}
@@ -856,6 +905,53 @@
%
%
%
+% \begin{function}{\hook_disable:n}
+% \begin{syntax}
+% \cs{hook_disable:n} \Arg{hook}
+% \end{syntax}
+% Marks \Arg{hook} as disabled. Any further attempt to add code to
+% it or declare it, will result in an error and any call to
+% \cs{hook_use:n} will simply do nothing.
+%
+% This declaration is intended for use with generic hooks that are
+% known not to work (see \texttt{ltcmdhooks-doc}) if they receive
+% code.
+%
+% 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_provide:n}
+% \begin{syntax}
+% \cs{hook_provide:n} \Arg{hook}
+% \end{syntax}
+% Like \cs{hook_new:n} but does nothing if the hook was previously
+% declared with \cs{hook_new:n}. This declaration should only be used
+% in special situations, e.g., when a command of another package
+% needs to be altered and it is is not clear if for that command a
+% generic \hook{cmd} hook was already explicitly declared before.
+%
+% Normally \cs{hook_new:n} should be used instead.
+% \end{function}
+%
+% \begin{function}{\hook_provide_reversed:n}
+% \begin{syntax}
+% \cs{hook_provide_reversed:n} \Arg{hook}
+% \end{syntax}
+% Like \cs{hook_new_reversed:n} but does nothing if the hook was
+% previously declared as a reversed hook.
+% \end{function}
+%
+% \begin{function}{\hook_provide_pair:nn}
+% \begin{syntax}
+% \cs{hook_provide_pair:nn} \Arg{hook-1} \Arg{hook-2}
+% \end{syntax}
+% A shorthand for
+% \cs{hook_provide:n}\Arg{hook-1}\cs{hook_provide_reversed:n}\Arg{hook-2}.
+% \end{function}
+%
+%
+%
% \begin{function}{\hook_use:n}
% \begin{syntax}
% \cs{hook_use:n} \Arg{hook}
@@ -968,28 +1064,6 @@
% A leading |.| is treated literally.
% \end{function}
%
-% \begin{function}[pTF]{\hook_if_exist:n}
-% \begin{syntax}
-% \cs{hook_if_exist:nTF} \Arg{hook} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests if the \meta{hook} exists (if it was created with either
-% \cs{NewHook}, \cs{NewReversedHook}, or \cs{NewMirroredHookPair}), and
-% branches to either \meta{true code} or \meta{false code} depending
-% on the result.
-%
-% The existence of a hook usually doesn't mean much from the viewpoint
-% of code that tries to add/remove code from that hook, since package
-% loading order may vary, thus the creation of hooks is asynchronous
-% to adding and removing code from it, so this test should be used
-% sparingly.
-%
-% Generic hooks are declared at the time code is added to them, so the
-% result of \cs{hook_if_exist:n} will change once code is added to
-% said hook (unless the hook was previously declared).
-%
-% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
-% A leading |.| is treated literally.
-% \end{function}
%
% \begin{function}{\hook_show:n,\hook_log:n}
% \begin{syntax}
@@ -1259,8 +1333,8 @@
% For that reason such code is not using the hook management, but
% instead private kernel commands directly before or after a public
% hook with the following naming
-% convention: \cs{@kernel@before@\meta{hookname}} or
-% \cs{@kernel@after@\meta{hookname}}. For example, in
+% convention: \cs{@kernel@before@\meta{hook}} or
+% \cs{@kernel@after@\meta{hook}}. For example, in
% \cs{enddocument} you find
%\begin{verbatim}
% \UseHook{enddocument}%
@@ -1336,20 +1410,14 @@
% Like \cs{AtBeginDocument} but for the \hook{enddocument} hook.
% \end{function}
%
-%
-%
-% \begin{function}{\AtBeginDvi}
-% \begin{syntax}
-% \cs{AtBeginDvi} \oarg{label} \Arg{code}
-% \end{syntax}
-% This hook is discussed in conjunction with the shipout hooks.
-% \end{function}
+% There is also \cs{AtBeginDvi} which is discussed in conjunction
+% with the shipout hooks.
%
% \bigskip
%
% The few hooks that existed previously in \LaTeXe{} used internally
% commands such as \cs{@begindocumenthook} and packages sometimes
-% augemented them directly rather than working through
+% augmented them directly rather than working through
% \cs{AtBeginDocument}. For that reason there is currently support
% for this, that is, if the system detects that such an internal
% legacy hook command contains code it adds it to the new hook
@@ -1415,7 +1483,7 @@
%
% The hooks are only executed if \cs{begin}\Arg{env} and
% \cs{end}\Arg{env} is used. If the environment code is executed
-% via low-level calls to \cs{\meta{env}} and \cs{end\meta{env}}
+% via low-level calls to \cs[no-index]{\meta{env}} and \cs[no-index]{end\meta{env}}
% (e.g., to avoid the environment grouping) they are not
% available. If you want them available in code using this method,
% you would need to add them yourself, i.e., write something like
@@ -1458,6 +1526,38 @@
% \end{function}
%
%
+% \subsubsection{Generic hooks for commands}
+%
+% Similar to environments there are now (at least in theory) two
+% generic hooks available for any \LaTeX{} command. These are
+% \begin{description}
+% \item[\hook{cmd/\meta{name}/before}]
+%
+% This hook is executed at the very start of the command
+% execution.
+%
+% \item[\hook{cmd/\meta{name}/after}]
+% This hook is executed at the very end of the command body. It is
+% implemented as a reversed hook.
+% \end{description}
+% In practice there are restrictions and especially the
+% \hook{after} hook works only with a subset of commands. Details
+% about these restrictions are documented in
+% \texttt{ltcmdhooks-doc.pdf} or with code in
+% \texttt{ltcmdhooks-code.pdf}.
+%
+%
+%
+%
+% \subsubsection{Generic hooks provided by file loading operations}
+%
+% There are several hooks added to \LaTeX{}'s process of loading
+% file via its high-level interfaces such as \cs{input},
+% \cs{include}, \cs{usepackage}, \cs{RequirePackage}, etc. These
+% are documented in \texttt{ltfilehook-doc.pdf} or with code in
+% \texttt{ltfilehook-code.pdf}.
+%
+%
%
% \subsubsection{Hooks provided by \cs{begin}\texttt{\{document\}}}
% \label{sec:begindocument-hooks}
@@ -1557,7 +1657,9 @@
% generates material for further pages. It is the right place to
% do some final housekeeping and possibly write out some
% information to the \texttt{.aux} file (which is still open at
-% this point to receive data). It is also the correct place to
+% this point to receive data, but since there will be no more pages you
+% need to write to it using \cs{immediate}\cs{write}). It is also the
+% correct place to
% set up any testing code to be run when the \texttt{.aux} file
% is re-read in the next step.
%
@@ -1615,7 +1717,7 @@
%
%
% It is in also possible to use the generic \hook{env/document/end}
-% hook which is execuded by \cs{end}, i.e., just in front of the
+% hook which is executed by \cs{end}, i.e., just in front of the
% first hook above. Note however that the other generic \cs{end}
% environment hook, i.e., \hook{env/document/after} will never get
% executed, because by that time \LaTeX{} has finished the document
@@ -1624,7 +1726,7 @@
%
%
%
-% \subsubsection{Hooks provided \cs{shipout} operations}
+% \subsubsection{Hooks provided by \cs{shipout} operations}
% \label{sec:shipout}
%
% There are several hooks and mechanisms added to \LaTeX{}'s
@@ -1633,14 +1735,6 @@
% \texttt{ltshipout-code.pdf}.
%
%
-% \subsubsection{Hooks provided by file loading operations}
-%
-% There are several hooks added to \LaTeX{}'s
-% process of loading file via its high-level interfaces such as
-% \cs{input}, \cs{include}, \cs{usepackage}, etc. These are documented in
-% \texttt{ltfilehook-doc.pdf} or with code in
-% \texttt{ltfilehook-code.pdf}.
-%
%
% \subsubsection{Hooks provided in NFSS commands}
%
@@ -1709,27 +1803,20 @@
% \section{The Implementation}
%
%
-% \subsection{Loading further extensions}
-%
% \begin{macrocode}
%<@@=hook>
% \end{macrocode}
%
+% \changes{v1.0i}{2021/03/18}{Use \cs{NewModuleRelease}.}
+% \changes{v1.0n}{2021/05/24}{Use \cs{msg_...} instead of \cs{__kernel_msg...}}
%
-% At the moment the whole module rolls back in one go, but if we
-% make any modifications in later releases this will then need
-% splitting.
% \begin{macrocode}
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/10/01}%
-%<latexrelease> {\NewHook}{The hook management}%
-% \end{macrocode}
-%
-% \begin{macrocode}
\ExplSyntaxOn
+%<latexrelease>\NewModuleRelease{2020/10/01}{lthooks}
+%<latexrelease> {The~hook~management~system}
% \end{macrocode}
%
-%
% \subsection{Debugging}
%
% \begin{macro}{\g_@@_debug_bool}
@@ -1772,9 +1859,11 @@
%
% \begin{macro}[EXP]{\@@_str_compare:nn}
% Private copy of \cs{__str_if_eq:nn}
+% \InternalDetectionOff
% \begin{macrocode}
\cs_new_eq:NN \@@_str_compare:nn \__str_if_eq:nn
% \end{macrocode}
+% \InternalDetectionOn
% \end{macro}
%
% \subsection{Declarations}
@@ -1857,8 +1946,9 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\tl_gremove_once:Nx,\tl_show:x,\tl_log:x}
-% Some variants of \pkg{expl3} functions. \fmi{should be moved to expl3}
+% \begin{macro}[int]{\tl_gremove_once:Nx,\tl_show:x,\tl_log:x}
+% Some variants of \pkg{expl3} functions.
+% \fmiinline{should probably be moved to expl3}
% \begin{macrocode}
\cs_generate_variant:Nn \tl_gremove_once:Nn { Nx }
\cs_generate_variant:Nn \tl_show:n { x }
@@ -1950,25 +2040,30 @@
% \end{macro}
%
%
+%
% \subsection{Providing new hooks}
%
-% \begin{macro}{\g_@@_..._code_prop,\@@~...,\@@_next~...}
+% \subsubsection{The data structures of a hook}
%
-% Hooks have a \meta{name} and for each hook we have to provide a number of
-% data structures. These are
+% \DescribeMacro{\g_@@_\meta{hook}_code_prop}
+% \DescribeMacro{\@@\textvisiblespace\meta{hook}}
+% \DescribeMacro{\@@_next\textvisiblespace\meta{hook}}
+% Hooks have a name (called \meta{hook} in the description below)
+% and for each hook we have to
+% provide a number of data structures. These are
% \begin{description}
-% \item[\cs{g_@@_\meta{name}_code_prop}] A property list holding the code
+% \item[\cs{g_@@_\meta{hook}_code_prop}] A property list holding the code
% for the hook in separate chunks. The keys are by default the
% package names that add code to the hook, but it is possible
% for packages to define other keys.
%
-% \item[{\cs[no-index]{g_@@_\meta{name}_rule_\meta{label1}\string|\meta{label2}_tl}}]
+% \item[{\cs[no-index]{g_@@_\meta{hook}_rule_\meta{label1}\string|\meta{label2}_tl}}]
% A token list holding the relation between \meta{label1} and
-% \meta{label2} in the \meta{name}. The \meta{labels} are lexically
+% \meta{label2} in the \meta{hook}. The \meta{labels} are lexically
% (reverse) sorted to ensure that two labels always point to the same
-% token list. For global rules, the \meta{name} is |??|.
+% token list. For global rules, the \meta{hook} name is |??|.
%
-% \item[\cs{@@~\meta{name}}] The code that is actually executed
+% \item[\cs{@@\textvisiblespace\meta{hook}}] The code that is actually executed
% when the hook is called in the document is stored in this token
% list. It is constructed from the code chunks applying the
% information.
@@ -1977,54 +2072,194 @@
% and to make it simpler to normalize hook names in
% \cs{@@_make_name:n}.
%
-% \item[\cs{g_@@_\meta{name}_reversed_tl}] Some hooks are
+% \item[\cs{g_@@_\meta{hook}_reversed_tl}] Some hooks are
% \enquote{reversed}. This token list stores a |-| for such hook
% so that it can be identified. The |-| character is used because
% $\meta{reversed}1$ is $+1$ for normal hooks and $-1$ for reversed
% ones.
+
+% \item[{\cs[no-index]{g_@@_\meta{hook}_declared_tl}}] This token
+% list serves as marker for the hook being officially declared. Its
+% existence is tested to raise an error in case another declaration
+% is attempted.
%
-% \item[\cs{@@_toplevel~\meta{name}}] This token list stores the code
+% \item[\cs{@@_toplevel\textvisiblespace\meta{hook}}] This token list stores the code
% inserted in the hook from the user's document, in the |top-level|
% label. This label is special, and doesn't participate in sorting.
% Instead, all code is appended to it and executed after (or before,
% if the hook is reversed) the normal
% hook code, but before the |next| code chunk.
%
-% \item[\cs{@@_next~\meta{name}}] Finally there is extra code
-% (normally empty) that is used on the next invocation of the hook
-% (and then deleted). This can be used to define some special
-% behavior for a single occasion from within the document. This token
-% list follows the same naming scheme than the main \cs{@@~\meta{name}}
-% token list. It is called \cs{@@_next~\meta{name}} rather than
-% \cs{@@~next_\meta{name}} because otherwise a hook whose name is
-% |next_|\meta{name} would clash with the next code-token list of the
-% hook called \meta{name}.
+% \item[\cs{@@_next\textvisiblespace\meta{hook}}] Finally there is
+% extra code (normally empty) that is used on the next invocation
+% of the hook (and then deleted). This can be used to define some
+% special behavior for a single occasion from within the document.
+% This token list follows the same naming scheme than the main
+% \cs{@@\textvisiblespace\meta{hook}} token list. It is called
+% \cs{@@_next\textvisiblespace\meta{hook}} rather than
+% \cs[no-index]{@@\textvisiblespace next_\meta{hook}} because
+% otherwise a hook whose name is |next_|\meta{hook} would clash
+% with the next code-token list of the hook called \meta{hook}.
%
% \end{description}
-% \end{macro}
%
%
+% \subsubsection{On the existence of hooks}
+% \label{sec:existence}
+%
+% A hook may be in different states of existence. Here we give an
+% overview of internal commands to set up hooks and explain how the
+% different states are distinguished. The actual implementation
+% then follows in the next sections.
%
+% One problem we have to solve is, that we need to be able to add
+% code to hooks (e.g., with \cs{AddToHook}) even if that code has
+% not been declared yet. For example, one package needs to write
+% into a hook of another package, but that package ay not get
+% loaded or only loaded later. Another problem most hooks require
+% declaration but this is not the case for the generic hooks.
%
-% \begin{macro}{\hook_new:n}
-% The \cs{hook_new:n} declaration declare a new hook and expects
+% We therefore distinguish the following states for a hook and they
+% are managed with four different tests: structure existence
+% (\cs{@@_if_structure_exist:nTF}), creation
+% (\cs{@@_if_usable:nTF}), declaration (\cs{@@_if_declared:nTF})
+% and disabled or not (\cs{@@_if_disabled:nTF})
+% \begin{description}
+% \setlist[itemize]{leftmargin=5cm,format=\cs}
+% \item[not existing]
+%
+% Nothing is known about the hook so far. This state can be
+% detected with \cs{@@_if_structure_exist:nTF}
+% (which uses the false branch).
+%
+% In this state the hook can be declared, disabled, rules can be
+% defined or code could be added to it, but it is not possible
+% to use the hook (with \cs{UseHook}).
+
+% \item[basic data structure set up]
+%
+% A hook is this state when its basic data structure has been
+% set up (using \cs{@@_init_structure:n}). The data structure setup happens
+% automatically when commands such as \cs{AddToHook} are used
+% and the hook is at that point in state \enquote{not existing}.
+%
+% In this state the four tests give the following results:
+% \begin{itemize}
+% \item [@@_if_structure_exist:nTF] returns |true|.
+% \item [@@_if_usable:nTF] returns |false|.
+% \item [@@_if_declared:nTF] returns |false|.
+% \item [@@_if_disabled:nTF] returns |false|.
+% \end{itemize}
+%
+% The allowed acctions are the same as in the \enquote{not
+% existing} state.
+%
+% \item[declared]
+%
+% A hook is in this state it is not disabled and was explicity declared (e.g.,
+% with \cs{NewHook}). In this case the four tests give the
+% following results:
+% \begin{itemize}
+% \item [@@_if_structure_exist:nTF] returns |true|.
+% \item [@@_if_usable:nTF] returns |true|.
+% \item [@@_if_declared:nTF] returns |true|.
+% \item [@@_if_disabled:nTF] returns |false|.
+% \end{itemize}
+%
+% \item[usable]
+%
+% A hook is in this state if it is not disabled, was not
+% explicitly declared but nevertheless is allowed to be used
+% (with \cs{UseHook} or \cs{hook_use:n}). This state is only
+% possible for generic hooks as they do not need to be
+% declared. Therefore such hooks move directly from state
+% \enquote{not existing} to \enquote{usable} the moment a
+% declaration such as \cs{AddToHook} wants to add to the hook
+% data structure. In this state the tests give the following
+% results:
+% \begin{itemize}
+% \item [@@_if_structure_exist:nTF] returns |true|.
+% \item [@@_if_usable:nTF] returns |true|.
+% \item [@@_if_declared:nTF] returns |false|.
+% \item [@@_if_disabled:nTF] returns |false|.
+% \end{itemize}
+%
+%
+% \item[disabled]
+%
+% A hook in any state is moved to this state when
+% \cs{DisableHook} is used. This changes the tests to give the
+% following results:
+% \begin{itemize}
+% \item [@@_if_structure_exist:nTF] \emph{unchanged}.
+% \item [@@_if_usable:nTF] returns |false|.
+% \item [@@_if_declared:nTF] returns |true|.
+% \item [@@_if_disabled:nTF] returns |true|.
+% \end{itemize}
+% The structure test is unchanged (if the hook was unknown before it is
+% false, otherwise true). The usable test returns false so that
+% any \cs{UseHook} will bypass the hook from now on. The
+% declared test returns true so that any further \cs{NewHook}
+% generates an error and the disabled test returns true so that
+% \cs{AddToHook} can return an error.
+% \fmiinline{maybe it should do this only after begin document?}
+%
+% \end{description}
+%
+%
+%
+%
+% \subsubsection{Setting hooks up}
+%
+%
+% \begin{macro}{\hook_new:n,\@@_new:n}
+% The \cs{hook_new:n} declaration declares a new hook and expects
% the hook \meta{name} as its argument, e.g.,
% \hook{begindocument}.
% \begin{macrocode}
\cs_new_protected:Npn \hook_new:n #1
{ \@@_normalize_hook_args:Nn \@@_new:n {#1} }
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_new:n #1
{
% \end{macrocode}
-% We check for one of the internal data structures and if it
-% already exists we complain.
+% We check if the hook was already \emph{explicitly} declared with
+% \cs{hook_new:n}, and if it already exists we complain, otherwise set
+% the \enquote{created} flag for the hook so that it errors next time
+% \cs{hook_new:n} is used.
% \begin{macrocode}
- \hook_if_exist:nTF {#1}
+ \@@_if_declared:nTF {#1}
{ \msg_error:nnn { hooks } { exists } {#1} }
+ {
+ \tl_new:c { g_@@_#1_declared_tl }
+ \@@_make_usable:n {#1}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_make_usable:n}
+%
+% This initializes all hook data structures for the hook but if
+% used on its own doesn't mark the hook as declared (as
+% \cs{hook_new:n} does, so a later \cs{hook_new:n} on that hook will
+% not result in an error. This command is internally used by
+% \cs{hook_gput_code:n} when adding code to a generic hook.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_usable:n #1
+ {
% \end{macrocode}
-% Otherwise we add the hook name to the list of all hooks and
-% allocate the necessary data structures for the new hook.
+% Now we check if the hook's data structure can be safely created
+% without \pkg{expl3} raising errors, then
+% we add the hook name to the list of all hooks and
+% allocate the necessary data structures for the new hook,
+% otherwise just do nothing.
% \begin{macrocode}
+ \tl_if_exist:cF { @@~#1 }
{
\seq_gput_right:Nn \g_@@_all_seq {#1}
% \end{macrocode}
@@ -2035,12 +2270,12 @@
% \end{macrocode}
% Now ensure that the base data structure for the hook exists:
% \begin{macrocode}
- \@@_declare:n {#1}
+ \@@_init_structure:n {#1}
% \end{macrocode}
% The \cs{g_@@_\meta{hook}_labels_clist} holds the sorted list of
% labels (once it got sorted). This is used only for debugging.
% \begin{macrocode}
- \clist_new:c {g_@@_#1_labels_clist}
+ \clist_new:c { g_@@_#1_labels_clist }
% \end{macrocode}
% Some hooks should reverse the default order of code chunks. To
% signal this we have a token list which is empty for normal hooks
@@ -2062,23 +2297,30 @@
%
% \begin{macrocode}
\@@_include_legacy_code_chunk:n {#1}
- }
+ }
}
% \end{macrocode}
% \end{macro}
%
%
%
-% \begin{macro}{\@@_declare:n}
-% This function declares the basic data structures for a hook without
-% actually declaring the hook itself. This is needed to allow adding
-% to undeclared hooks. Here it is unnecessary to check whether all
-% variables exist, since all three are declared at the same time
-% (either all of them exist, or none).
+% \begin{macro}{\@@_init_structure:n}
+% This function declares the basic data structures for a hook
+% without explicit declaring the hook itself. This is needed to
+% allow adding to undeclared hooks. Here it is unnecessary to
+% check whether all variables exist, since all three are declared
+% at the same time (either all of them exist, or none).
+%
+% It creates the hook code pool
+% (\cs[no-index]{g_@@_\meta{hook}_code_prop}) and the |top-level|
+% and |next| token lists. A hook is initialized with
+% \cs{@@_init_structure:n} the first time anything is added to it.
+% Inizializing a hook just with \cs{@@_init_structure:n} will not
+% make it usable with \cs{hook_use:n}.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_declare:n #1
+\cs_new_protected:Npn \@@_init_structure:n #1
{
- \@@_if_exist:nF {#1}
+ \@@_if_structure_exist:nF {#1}
{
\prop_new:c { g_@@_#1_code_prop }
\tl_new:c { @@_toplevel~#1 }
@@ -2110,6 +2352,9 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
% \begin{macro}{\hook_new_pair:nn}
% A shorthand for declaring a normal and a (matching) reversed hook in one go.
% \begin{macrocode}
@@ -2160,6 +2405,140 @@
%
%
%
+% \subsubsection{Disabling and providing hooks}
+%
+% \begin{macro}{\hook_disable:n}
+% \begin{macro}{\@@_disable:n}
+% \begin{macro}[pTF]{\@@_if_disabled:n}
+%
+% Disables a hook by creating its
+% \cs[no-index]{g_@@_\meta{hook}_declared_tl} so that the hook
+% errors when used with \cs{hook_new:n}, then it undefines
+% \cs{@@\textvisiblespace\meta{hook}} so that it may not be executed.
+%
+% This does not clear any code that may be already stored in the
+% hook's structure, but doesn't allow adding more code.
+% \cs{@@_if_disabled:nTF} uses that specific combination to check
+% if the hook is disabled.
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\hook_disable:n}{Disable~hooks}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_disable:n #1
+ { \@@_normalize_hook_args:Nn \@@_disable:n {#1} }
+\cs_new_protected:Npn \@@_disable:n #1
+ {
+ \tl_gclear_new:c { g_@@_#1_declared_tl }
+ \cs_undefine:c { @@~#1 }
+ }
+\prg_new_conditional:Npnn \@@_if_disabled:n #1 { p, T, F, TF }
+ {
+ \bool_lazy_and:nnTF
+ { \tl_if_exist_p:c { g_@@_#1_declared_tl } }
+ { ! \tl_if_exist_p:c { @@~#1 } }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}
+%<latexrelease> {\hook_disable:n}{Disable~hooks}
+%<latexrelease>
+%<latexrelease>\cs_new_protected:Npn \hook_disable:n #1 {}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hook_provide:n}
+% \begin{macro}{\hook_provide_reversed:n}
+% \begin{macro}{\@@_provide:n}
+% The \cs{hook_provide:n} declaration declares a new hook if it
+% wasn't declared already, in which case it only checks that the
+% already existing hook is not a reversed hook.
+% The \cs{hook_provide_reversed:n} does the same for reversed hooks.
+% \hook{begindocument}.
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\hook_provide:n}{Providing~hooks}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_provide:n #1
+ { \@@_normalize_hook_args:Nn \@@_provide:nn {#1} { } }
+\cs_new_protected:Npn \hook_provide_reversed:n #1
+ { \@@_normalize_hook_args:Nn \@@_provide:nn {#1} { - } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_provide:nn #1 #2
+ {
+% \end{macrocode}
+% If the hook to be provided was disabled we warn (for now --- this
+% may change).
+% \begin{macrocode}
+ \@@_if_disabled:nTF {#1}
+ { \msg_warning:nnn { hooks } { provide-disabled } {#1} }
+% \end{macrocode}
+% Otherwise we check if it was already declared.
+% \begin{macrocode}
+ {
+ \@@_if_declared:nTF {#1}
+ {
+% \end{macrocode}
+% Issue an error if we try to provide a a hook that is reversed and
+% the already existing one is not (or vice versa).
+% \begin{macrocode}
+ \str_if_eq:eeF { \tl_use:c { g_@@_#1_reversed_tl } } {#2}
+ { \msg_error:nnn { hooks } { provide-error } {#1} }
+ }
+% \end{macrocode}
+% If it wasn't declared, we declared as a normal or reversed hook
+% as appropriate.
+% \begin{macrocode}
+ {
+ \tl_new:c { g_@@_#1_declared_tl }
+ \@@_make_usable:n {#1}
+ \tl_gset:cn { g_@@_#1_reversed_tl } {#2}
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hook_provide_pair:nn}
+% A shorthand for providing a normal and a (matching) reversed hook in one go.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_provide_pair:nn #1#2
+ { \hook_provide:n {#1} \hook_provide_reversed:n {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}
+%<latexrelease> {\hook_provide:n}{Providing~hooks}
+%<latexrelease>
+%<latexrelease>\cs_new_protected:Npn \hook_provide_reversed:n #1 {}
+%<latexrelease>\cs_new_protected:Npn \hook_provide:n #1 {}
+%<latexrelease>\cs_new_protected:Npn \hook_provide_pair:nn #1#2 {}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+%
% \subsection{Parsing a label}
%
% \begin{macro}[EXP]{\@@_parse_label_default:n}
@@ -2231,7 +2610,7 @@
{
\tl_if_empty:NTF \@currname
{
- \msg_expandable_error:nnn { hooks } { should-not-happen }
+ \msg_expandable_error:nnn { kernel } { should-not-happen }
{ Empty~default~label. }
\@@_make_name:n { label-missing }
}
@@ -2243,15 +2622,15 @@
% \end{macro}
%
% \begin{macro}[EXP]{\@@_make_name:n,\@@_make_name:w}
-% Provides a standard sanitisation of a hook's name.
+% Provides a standard sanitization of a hook's name.
% It uses \cs{cs:w} to build a control sequence out of the hook name,
% then uses \cs{cs_to_str:N} to get the string representation of that,
% without the escape character. \cs{cs:w}-based expansion is used
% instead of |e|-based because Unicode characters don't behave well
-% inside \cs{expanded}. The macro adds the \cs{@@~} prefix to the
+% inside \cs{expanded}. The macro adds the \cs[no-index]{@@\textvisiblespace} prefix to the
% hook name to reuse the hook's code token list to build the csname
% and avoid leaving \enquote{public} control sequences defined
-% (as~\cs{relax}) in TeX's memory.
+% (as~\cs[no-index]{relax}) in TeX's memory.
% \begin{macrocode}
\cs_new:Npn \@@_make_name:n #1
{
@@ -2311,6 +2690,9 @@
% \end{macro}
%
%
+%
+% \subsection{Adding or removing hook code}
+%
% \begin{macro}{\hook_gput_code:nnn}
% \begin{macro}{\@@_gput_code:nnn,\@@_gput_code:nxv,\@@_hook_gput_code_do:nnn}
%
@@ -2320,6 +2702,9 @@
% \begin{macrocode}
\cs_new_protected:Npn \hook_gput_code:nnn #1 #2
{ \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} }
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_gput_code:nnn #1 #2 #3
{
% \end{macrocode}
@@ -2343,7 +2728,7 @@
% If no removal is queued, we are free to add. Start by checking if
% the hook exists.
% \begin{macrocode}
- \hook_if_exist:nTF {#1}
+ \@@_if_usable:nTF {#1}
% \end{macrocode}
% If so we simply add (or append) the new code to the property list
% holding different chunks for the hook. At \verb=\begin{document}=
@@ -2364,10 +2749,17 @@
% declare it as a generic hook, if its name matches one of the valid
% patterns.
% \begin{macrocode}
- { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} }
+ {
+ \@@_if_disabled:nTF {#1}
+ { \msg_error:nnn { hooks } { hook-disabled } {#1} }
+ { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} }
+ }
}
}
}
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_generate_variant:Nn \@@_gput_code:nnn { nxv }
% \end{macrocode}
%
@@ -2379,7 +2771,7 @@
% However, first some debugging info if debugging is enabled:
% \begin{macrocode}
\@@_debug:n{\iow_term:x{****~ Add~ to~
- \hook_if_exist:nF {#1} { undeclared~ }
+ \@@_if_usable:nF {#1} { undeclared~ }
hook~ #1~ (#2)
\on@line\space <-~ \tl_to_str:n{#3}} }
% \end{macrocode}
@@ -2387,9 +2779,9 @@
% If there's code already there, then append \verb=#3= to that,
% otherwise just put \verb=#3=. If the current label is |top-level|,
% the code is added to a dedicated token list
-% \cs[no-index]{@@_toplevel~\meta{hook}} that goes at the end of the
+% \cs{@@_toplevel\textvisiblespace\meta{hook}} that goes at the end of the
% hook (or at the beginning, for a reversed hook), just before
-% \cs[no-index]{@@_next~\meta{hook}}.
+% \cs[no-index]{@@_next\textvisiblespace\meta{hook}}.
% \begin{macrocode}
\str_if_eq:nnTF {#2} { top-level }
{
@@ -2397,9 +2789,9 @@
{
% \end{macrocode}
% If the hook's basic structure does not exist, we need to declare it
-% with \cs{@@_declare:n}.
+% with \cs{@@_init_structure:n}.
% \begin{macrocode}
- \@@_declare:n {#1}
+ \@@_init_structure:n {#1}
\@@_tl_gput_right:cn { @@_toplevel~#1 } {#3}
}
{ \msg_error:nnn { hooks } { misused-top-level } {#1} }
@@ -2424,14 +2816,15 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_gput_undeclared_hook:nnn #1 #2 #3
{
- \@@_declare:n {#1}
+ \@@_init_structure:n {#1}
\@@_hook_gput_code_do:nnn {#1} {#2} {#3}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\@@_try_declaring_generic_hook:nnn}
-% \begin{macro}{\@@_try_declaring_generic_next_hook:nn}
+% \begin{macro}{\@@_try_declaring_generic_hook:nnn,
+% \@@_try_declaring_generic_next_hook:nn}
+%
% These entry-level macros just pass the arguments along to the
% common \cs{@@_try_declaring_generic_hook:nNNnn} with the right
% functions to execute when some action is to be taken.
@@ -2458,13 +2851,14 @@
\hook_gput_next_code:nn \@@_gput_next_do:nn
}
% \end{macrocode}
+% \end{macro}
%
-% \begin{macro}{
-% \@@_try_declaring_generic_hook:nNNnn,
-% \@@_try_declaring_generic_hook_split:nNNnn
-% }
-% \begin{macro}[TF]{\@@_try_declaring_generic_hook:wn}
-% \cs{@@_try_declaring_generic_hook:nNNnn} now splits the hook name
+%
+% \begin{macro}{\@@_try_declaring_generic_hook:nNNnn,
+% \@@_try_declaring_generic_hook_split:nNNnn}
+%
+% \cs{@@_try_declaring_generic_hook:nNNnn}
+% now splits the hook name
% at the first \texttt{/} (if any) and first checks if it is a
% file-specific hook (they require some normalization) using
% \cs{@@_if_file_hook:wTF}. If not then check it is one of a
@@ -2482,12 +2876,24 @@
}
{ \@@_try_declaring_generic_hook_split:nNNnn {#1} }
}
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_try_declaring_generic_hook_split:nNNnn #1 #2 #3
{
\@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
{ #2 }
{ #3 } {#1}
}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[TF]{\@@_try_declaring_generic_hook:wn}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@@_try_declaring_generic_hook:wn}{Support~cmd~hooks}
\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
#1 / #2 / #3 / #4 \scan_stop: #5 { TF }
{
@@ -2496,31 +2902,70 @@
{
\prop_if_in:NnTF \c_@@_generics_prop {#1}
{
- \hook_if_exist:nF {#5} { \hook_new:n {#5} }
+ \@@_if_usable:nF {#5}
+ {
% \end{macrocode}
-% After having declared the hook we check the second component (for
-% file hooks) or the third component for environment hooks) and
-% if it is on the list of components for which we should have declared
-% a reversed hook we alter the hook data structure accordingly.
+% If the hook doesn't exist yet we check if it is a \texttt{cmd}
+% hook and if so we attempt patching the command in addition to
+% declaring the hook.
+%
+% For some commands this will not be possible, in which case
+% \cs{@@_patch_cmd_or_delay:Nnn} (defined in \texttt{ltcmdhooks})
+% will generate an appropriate error message.
+% \begin{macrocode}
+ \str_if_eq:nnT {#1} { cmd }
+ { \@@_try_put_cmd_hook:n {#5} }
+% \end{macrocode}
+%
+% Declare the hook always even if it can't really be used (error
+% message generated elsewhere).
+%
+% Here we use \cs{@@_make_usable:n}, so that a \cs{hook_new:n} is still
+% possible later.
% \begin{macrocode}
+ \@@_make_usable:n {#5}
+ }
\prop_if_in:NnTF \c_@@_generics_reversed_ii_prop {#2}
{ \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
{
\prop_if_in:NnT \c_@@_generics_reversed_iii_prop {#3}
{ \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
}
-% \end{macrocode}
-% Now that we know that the hook is declared we can add the code to it.
-% \begin{macrocode}
\prg_return_true:
}
{ \prg_return_false: }
}
}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@@_try_declaring_generic_hook:wn}{Support~cmd~hooks}
+%<latexrelease>
+%<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
+%<latexrelease> #1 / #2 / #3 / #4 \scan_stop: #5 { TF }
+%<latexrelease> {
+%<latexrelease> \tl_if_empty:nTF {#2}
+%<latexrelease> { \prg_return_false: }
+%<latexrelease> {
+%<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> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
+%<latexrelease> {
+%<latexrelease> \prop_if_in:NnT \c_@@_generics_reversed_iii_prop {#3}
+%<latexrelease> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
+%<latexrelease> }
+%<latexrelease> \prg_return_true:
+%<latexrelease> }
+%<latexrelease> { \prg_return_false: }
+%<latexrelease> }
+%<latexrelease> }
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
% \end{macro}
%
% \begin{macro}[pTF]{\@@_if_file_hook:w}
@@ -2529,7 +2974,7 @@
% |file/before/foo.tex|). If it is a file-specific hook, then it
% executes the \meta{true} branch, otherwise \meta{false}.
%
-% A file-specific hook is \texttt{file/\meta{position}/\meta{name}}.
+% A file-specific hook is \hook{file/\meta{position}/\meta{name}}.
% If any of these parts don't exist, it is a general file hook or not
% a file hook at all, so the conditional evaluates to \meta{false}.
% Otherwise, it checks that the first part is |file| and that the
@@ -2595,14 +3040,16 @@
% Property list holding the generic names. We don't provide any user
% interface to this as this is meant to be static.
% \begin{description}
+% \item[\texttt{cmd}]
+% The generic hooks used for commands.
% \item[\texttt{env}]
% The generic hooks used in \cs{begin} and \cs{end}.
-% \item[\texttt{file}]
+% \item[\texttt{file}, \texttt{package}, \texttt{class}, \texttt{include}]
% The generic hooks used when loading a file
% \end{description}
% \begin{macrocode}
\prop_const_from_keyval:Nn \c_@@_generics_prop
- {env=,file=,package=,class=,include=}
+ {cmd=,env=,file=,package=,class=,include=}
% \end{macrocode}
% \end{macro}
%
@@ -2629,11 +3076,11 @@
\cs_new_protected:Npn \@@_gremove_code:nn #1 #2
{
% \end{macrocode}
-% First check that the hook code pool exists. \cs{hook_if_exist:nTF}
+% First check that the hook code pool exists. \cs{@@_if_usable:nTF}
% isn't used here because it should be possible to remove code from a
% hook before its defined (see section~\ref{sec:querying}).
% \begin{macrocode}
- \@@_if_exist:nTF {#1}
+ \@@_if_structure_exist:nTF {#1}
{
% \end{macrocode}
% Then remove the chunk and run \cs{@@_update_hook_code:n} so
@@ -2641,9 +3088,9 @@
% \verb=\begin{document}=.
%
% If all code is to be removed, clear the code pool
-% \cs[no-index]{g_@@_\meta{hook}_code_prop}, the top-level code
-% \cs[no-index]{@@_toplevel~\meta{hook}}, and the next-execution code
-% \cs[no-index]{@@_next~\meta{hook}}.
+% \cs{g_@@_\meta{hook}_code_prop}, the top-level code
+% \cs{@@_toplevel\textvisiblespace\meta{hook}}, and the next-execution code
+% \cs{@@_next\textvisiblespace\meta{hook}}.
% \begin{macrocode}
\str_if_eq:nnTF {#2} {*}
{
@@ -2656,7 +3103,7 @@
% If the label is |top-level| then clear the token list, as all code
% there is under the same label. Marked removal is not implemented
% for |top-level| because it is hard to reliably know that no code
-% was added to \cs[no-index]{@@_toplevel~\meta{hook}} (granted that
+% was added to \cs{@@_toplevel\textvisiblespace\meta{hook}} (granted that
% an empty code could be interpreted as that, but then it differs in
% behaviour from other labels, in which an empty chunk is still valid
% for removal). Besides, it doesn't make much (if any) sense for
@@ -2680,7 +3127,7 @@
% \end{macrocode}
% Finally update the code, if the hook exists.
% \begin{macrocode}
- \hook_if_exist:nT {#1}
+ \@@_if_usable:nT {#1}
{ \@@_update_hook_code:n {#1} }
}
% \end{macrocode}
@@ -2775,10 +3222,10 @@
% disadvantage of that being not really distinguishable from a real
% hook name. I now have settled for \texttt{??} which needs some
% gymnastics to get it into the csname, but since this is used a
-% lot things should be fast, so this is not done with \texttt{c}
+% lot, the code should be fast, so this is not done with \texttt{c}
% expansion in the code later on.
%
-% \cs{@@~??} isn't used, but it has to be defined to trick
+% \cs{@@\textvisiblespace??} isn't used, but it has to be defined to trick
% the code into thinking that \verb=??= is actually a hook.
% \begin{macrocode}
\prop_new:c {g_@@_??_code_prop}
@@ -2799,14 +3246,12 @@
%
% \begin{macro}{\hook_gset_rule:nnnn}
% \begin{macro}{\@@_gset_rule:nnnn}
-%
-% \fmi{needs docu correction given new implementation}
-%
% With
% \cs{hook_gset_rule:nnnn}\Arg{hook}\Arg{label1}\Arg{relation}\Arg{label2}
% a relation is defined between the two code labels for the given
% \meta{hook}. The special hook \texttt{??} stands for \emph{any}
-% hook describing a default rule.
+% hook, which sets a default rule (to be used if no other relation
+% between the two hooks exist).
% \begin{macrocode}
\cs_new_protected:Npn \hook_gset_rule:nnnn #1#2#3#4
{
@@ -2814,14 +3259,14 @@
{#1} {#2} {#3} {#4}
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\cs_new_protected:Npn \@@_gset_rule:nnnn #1#2#3#4
{
% \end{macrocode}
% First we ensure the basic data structure of the hook exists:
% \begin{macrocode}
- \@@_declare:n {#1}
+ \@@_init_structure:n {#1}
% \end{macrocode}
% Then we clear any previous relationship between both labels.
% \begin{macrocode}
@@ -2898,9 +3343,11 @@
% 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}
%
@@ -2937,7 +3384,7 @@
{
\if_int_compare:w \@@_str_compare:nn {#1} {#2} > 0 \exp_stop_f:
\prg_return_true:
- \else
+ \else:
\prg_return_false:
\fi:
}
@@ -3037,13 +3484,13 @@
% If there aren't any code
% chunks for the current hook, there is no point in even starting
% the sorting routine so we make a quick test for that and in that
-% case just update \cs{@@~\meta{hook}} to hold the |top-level| and
+% case just update \cs{@@\textvisiblespace\meta{hook}} to hold the |top-level| and
% |next| code chunks. If there are code chunks we call
% \cs{@@_initialize_single:NNn} and pass to it ready made csnames
% as they are needed several times inside. This way we save a bit
% on processing time if we do that up front.
% \begin{macrocode}
- \hook_if_exist:nT {#1}
+ \@@_if_usable:nT {#1}
{
\prop_if_empty:cTF {g_@@_#1_code_prop}
{
@@ -3096,7 +3543,7 @@
% \begin{macro}[EXP]{\@@_tl_csname:n,\@@_seq_csname:n}
% It is faster to pass a single token and expand it when necessary
% than to pass a bunch of character tokens around.
-% \fmi{note to myself: verify}
+% \fmiinline{note to myself: verify}
% \begin{macrocode}
\cs_new:Npn \@@_tl_csname:n #1 { l_@@_label_#1_tl }
\cs_new:Npn \@@_seq_csname:n #1 { l_@@_label_#1_seq }
@@ -3160,7 +3607,7 @@
% a way that one can omit a lot of tests and I have mimicked that as
% far as possible. The result is a restriction I do not test for at
% the moment: a label can't be equal to the number 0! \fmi{Needs
-% checking for, just in case}
+% checking for, just in case ... maybe}
%
% ^^A #1 <- \@@~#1
% ^^A #2 <- \g_@@_#1_labels_clist
@@ -3301,7 +3748,7 @@
% \end{macrocode}
%
% This is not really the information one needs in the error case
-% but will do for now \ldots \fmi{fix}
+% but will do for now \ldots \fmi{improve output on a rainy day}
% \begin{macrocode}
\@@_debug_label_data:N \l_@@_work_prop
\iow_term:x{====================}
@@ -3572,15 +4019,20 @@
{ \@@_log_cmd:x { >~#1 } }
\cs_new_protected:Npn \@@_log_line_indent:x #1
{ \@@_log_cmd:x { >~\@spaces #1 } }
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_log:nN #1 #2
{
\@@_preamble_hook:n {#1}
\@@_log_cmd:x { ^^J ->~The~hook~'#1': }
% \end{macrocode}
-%
+%
% \begin{macrocode}
- \hook_if_exist:nF {#1}
- { \@@_log_line:x { is~not~declared! } }
+ \@@_if_usable:nF {#1}
+ { \@@_log_line:x { The~hook~is~not~declared. } }
+ \@@_if_disabled:nT {#1}
+ { \@@_log_line:x { The~hook~is~disabled. } }
\hook_if_empty:nTF {#1}
{ #2 { The~hook~is~empty } }
{
@@ -3598,7 +4050,7 @@
\@@_log_line:x
{
Document-level~(top-level)~code
- \hook_if_exist:nT {#1}
+ \@@_if_usable:nT {#1}
{ ~(executed~\@@_if_reversed:nTF {#1} {first} {last} ) } :
}
\@@_log_line_indent:x
@@ -3649,7 +4101,7 @@
% to that hook) and not empty
% \begin{macrocode}
\bool_lazy_and:nnTF
- { \hook_if_exist_p:n {#1} }
+ { \@@_if_usable_p:n {#1} }
{ ! \hook_if_empty_p:n {#1} }
{
\@@_log_line:x
@@ -3671,10 +4123,12 @@
}
}
{
+ \@@_log_line:x { Execution~order: }
#2
{
- Hook~ \hook_if_exist:nTF {#1}
- {code~pool~empty} {not~declared}
+ \@spaces Not~set~because~the~hook~ \@@_if_usable:nTF {#1}
+ { code~pool~is~empty }
+ { is~\@@_if_disabled:nTF {#1} {disabled} {undeclared} }
}
}
}
@@ -3766,25 +4220,37 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
% \subsection{Specifying code for next invocation}
%
% \begin{macro}{\hook_gput_next_code:nn}
-% \begin{macro}{%
-% \@@_gput_next_code:nn,
-% \@@_gput_next_do:nn,
-% \@@_gput_next_do:Nnn,
-% \@@_clear_next:n
-% }
% \begin{macrocode}
\cs_new_protected:Npn \hook_gput_next_code:nn #1
{ \@@_normalize_hook_args:Nn \@@_gput_next_code:nn {#1} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_gput_next_code:nn,
+% \@@_gput_next_do:nn,
+% \@@_gput_next_do:Nnn,
+% \@@_clear_next:n}
+% \begin{macrocode}
\cs_new_protected:Npn \@@_gput_next_code:nn #1 #2
{
- \@@_declare:n {#1}
- \hook_if_exist:nTF {#1}
- { \@@_gput_next_do:nn {#1} {#2} }
- { \@@_try_declaring_generic_next_hook:nn {#1} {#2} }
+ \@@_if_disabled:nTF {#1}
+ { \msg_error:nnn { hooks } { hook-disabled } {#1} }
+ {
+ \@@_init_structure:n {#1}
+ \@@_if_usable:nTF {#1}
+ { \@@_gput_next_do:nn {#1} {#2} }
+ { \@@_try_declaring_generic_next_hook:nn {#1} {#2} }
+ }
}
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_gput_next_do:nn #1
{
\exp_args:Nc \@@_gput_next_do:Nnn
@@ -3813,7 +4279,11 @@
{ \cs_gset_eq:cN { @@_next~#1 } \c_empty_tl }
% \end{macrocode}
% \end{macro}
-% \end{macro}
+%
+%
+%
+%
+%
%
% \subsection{Using the hook}
%
@@ -3840,7 +4310,7 @@
% them causes an update, so \cs{hook_use:n} can be made expandable.
% This one is better not protected so that it can expand into nothing
% if containing no code. Also important in case of generic hooks that
-% we do not generate a \cs{relax} as a side effect of checking for a
+% we do not generate a \cs[no-index]{relax} as a side effect of checking for a
% csname. In contrast to the \TeX{} low-level
% \verb=\csname ...\endcsname= construct \cs{tl_if_exist:c} is
% careful to avoid this.
@@ -3877,7 +4347,7 @@
% \end{macro}
%
% \begin{macro}[EXP]{\@@_use:wn}
-% \begin{macro}{\@@_try_file_hook:n,\@@_if_exist_use:n}
+% \begin{macro}{\@@_try_file_hook:n,\@@_if_usable_use:n}
% \cs{@@_use:wn} does a quick check to test if the current hook is a
% file hook: those need a special treatment. If it is not, the hook
% does not exist. If it is, then \cs{@@_try_file_hook:n} is called,
@@ -3887,7 +4357,7 @@
%
% If it is a file-specific hook, it passes through the same
% normalization as during declaration, and then it is used if defined.
-% \cs{@@_if_exist_use:n} checks if the hook exist, and calls
+% \cs{@@_if_usable_use:n} checks if the hook exist, and calls
% \cs{@@_preamble_hook:n} if so, then uses the hook.
% \begin{macrocode}
\cs_new:Npn \@@_use:wn #1 / #2 \s_@@_mark #3
@@ -3896,16 +4366,22 @@
{ \@@_try_file_hook:n {#3} }
{ } % Hook doesn't exist
}
+% \end{macrocode}
+%
+% \begin{macrocode}
\cs_new_protected:Npn \@@_try_file_hook:n #1
{
\@@_if_file_hook:wTF #1 / / \s_@@_mark
{
- \exp_args:Ne \@@_if_exist_use:n
+ \exp_args:Ne \@@_if_usable_use:n
{ \exp_args:Ne \@@_file_hook_normalize:n {#1} }
}
- { \@@_if_exist_use:n {#1} } % file/ generic hook (e.g. file/before)
+ { \@@_if_usable_use:n {#1} } % file/ generic hook (e.g. file/before)
}
-\cs_new_protected:Npn \@@_if_exist_use:n #1
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_if_usable_use:n #1
{
\tl_if_exist:cT { @@~#1 }
{
@@ -3928,7 +4404,6 @@
% hook name, since \cs{hook_use:n} and \cs{hook_use_once:n} are
% documented to not trim spaces.
%
-% \pho{Should this raise an error if the hook doesn't exist?}
% \begin{macrocode}
\cs_new_protected:Npn \hook_use_once:n #1
{
@@ -3952,9 +4427,10 @@
% exist, in which case emptiness doesn't apply (though
% \cs{tl_if_empty:N} returns false in this case).
%
-% Hooks are a bit more complicated: they have four possible states.
+% Hooks are a bit more complicated: they have several other states as
+% discussed in \ref{sec:existence}.
% A hook may exist or not, and either way it may or may not be empty
-% (even a hook that doesn't exist may be non-empty).
+% (even a hook that doesn't exist may be non-empty) or may be disabled.
%
% A hook is said to be empty when no code was added to it, either to
% its permanent code pool, or to its ``next'' token list. The hook
@@ -3964,19 +4440,19 @@
% In this case it is important that the code added by package $B$ is
% remembered until package $A$ is loaded).
%
-% A hook is said to exist when it was declared with \cs{hook_new:n} or
-% some variant thereof.
-%
+% All other states can only be queried with internal tests as the
+% different states are irrelevant for package code.
+
% \begin{macro}[pTF]{\hook_if_empty:n}
% Test if a hook is empty (that is, no code was added to that hook).
% A \meta{hook} being empty means that all three of its
-% \cs[no-index]{g_@@_\meta{hook}_code_prop}, its
-% \cs[no-index]{@@_toplevel~\meta{hook}} and its
-% \cs[no-index]{@@_next~\meta{hook}} are empty.
+% \cs{g_@@_\meta{hook}_code_prop}, its
+% \cs{@@_toplevel\textvisiblespace\meta{hook}} and its
+% \cs{@@_next\textvisiblespace\meta{hook}} are empty.
% \begin{macrocode}
\prg_new_conditional:Npnn \hook_if_empty:n #1 { p , T , F , TF }
{
- \@@_if_exist:nTF {#1}
+ \@@_if_structure_exist:nTF {#1}
{
\bool_lazy_and:nnTF
{ \prop_if_empty_p:c { g_@@_#1_code_prop } }
@@ -3993,8 +4469,9 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[pTF]{\hook_if_exist:n}
-% A canonical way to test if a hook exists. A hook exists if the
+%
+% \begin{macro}[pTF]{\@@_if_usable:n}
+% A hook is usable if the
% token list that stores the sorted code for that hook,
% \cs[no-index]{@@~\meta{hook}}, exists. The property list
% \cs[no-index]{g_@@_\meta{hook}_code_prop} cannot be used here
@@ -4002,7 +4479,7 @@
% if such hook was already declared, or even if it will ever be
% (for example, in case the package that defines it isn't loaded).
% \begin{macrocode}
-\prg_new_conditional:Npnn \hook_if_exist:n #1 { p , T , F , TF }
+\prg_new_conditional:Npnn \@@_if_usable:n #1 { p , T , F , TF }
{
\tl_if_exist:cTF { @@~#1 }
{ \prg_return_true: }
@@ -4011,13 +4488,15 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[pTF]{\@@_if_exist:n}
-% An internal check if the hook has already been declared with
-% \cs{@@_declare:n}. This means that the hook was already used somehow
+% \begin{macro}[pTF]{\@@_if_structure_exist:n}
+%
+% An internal check if the hook has already its basic internal
+% structure set up with
+% \cs{@@_init_structure:n}. This means that the hook was already used somehow
% (a code chunk or rule was added to it), but it still wasn't declared
% with \cs{hook_new:n}.
% \begin{macrocode}
-\prg_new_conditional:Npnn \@@_if_exist:n #1 { p , T , F , TF }
+\prg_new_conditional:Npnn \@@_if_structure_exist:n #1 { p , T , F , TF }
{
\prop_if_exist:cTF { g_@@_#1_code_prop }
{ \prg_return_true: }
@@ -4025,6 +4504,22 @@
}
% \end{macrocode}
% \end{macro}
+%
+%
+%
+% \begin{macro}[pTF]{\@@_if_declared:n}
+%
+% Internal test to check if the hook was officially declared with
+% \cs{hook_new:n} or a variant.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_declared:n #1 { p, T, F, TF }
+ {
+ \tl_if_exist:cTF { g_@@_#1_declared_tl }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
%
% \begin{macro}[pTF]{\@@_if_reversed:n}
% An internal conditional that checks if a hook is reversed.
@@ -4043,11 +4538,21 @@
%
% \subsection{Messages}
%
+% Hook errors are LaTeX kernel errors:
+% \begin{macrocode}
+\prop_gput:Nnn \g_msg_module_type_prop { hooks } { LaTeX }
+% \end{macrocode}
+% And so are kernel errors (this should move elsewhere eventually).
+% \begin{macrocode}
+\prop_gput:Nnn \g_msg_module_type_prop { kernel } { LaTeX }
+%\prop_gput:Nnn \g_msg_module_name_prop { kernel } { } % <-- currently not working
+% \end{macrocode}
+%
% \begin{macrocode}
\msg_new:nnnn { hooks } { labels-incompatible }
{
- Labels~`#1'~and~`#2'~are~incompatible
- \str_if_eq:nnF {#3} {??} { ~in~hook~`#3' } .~
+ Labels~'#1'~and~'#2'~are~incompatible
+ \str_if_eq:nnF {#3} {??} { ~in~hook~'#3' } .~
\int_compare:nNnTF {#4} = { 1 }
{ The~ code~ for~ both~ labels~ will~ be~ dropped. }
{ You~ may~ see~ errors~ later. }
@@ -4058,17 +4563,28 @@
%
% \begin{macrocode}
\msg_new:nnnn { hooks } { exists }
- { Hook~`#1'~ has~ already~ been~ declared. }
+ { Hook~'#1'~ has~ already~ been~ declared. }
{ There~ already~ exists~ a~ hook~ declaration~ with~ this~
name.\\
Please~ use~ a~ different~ name~ for~ your~ hook.}
% \end{macrocode}
%
+%
+% \begin{macrocode}
+\msg_new:nnnn { hooks } { hook-disabled }
+ { 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:n~or~\iow_char:N\\DisableHook,~so~
+ it~cannot~have~code~added~to~it.
+ }
+% \end{macrocode}
+%
% \begin{macrocode}
\msg_new:nnn { hooks } { empty-label }
{
Empty~code~label~\msg_line_context:.~
- Using~`\@@_currname_or_default:'~instead.
+ Using~'\@@_currname_or_default:'~instead.
}
% \end{macrocode}
%
@@ -4082,26 +4598,26 @@
%
% \begin{macrocode}
\msg_new:nnnn { hooks } { unknown-rule }
- { Unknown~ relationship~ `#3'~
- between~ labels~ `#2'~ and~ `#4'~
- \str_if_eq:nnF {#1} {??} { ~in~hook~`#1' }. ~
+ { Unknown~ relationship~ '#3'~
+ between~ labels~ '#2'~ and~ '#4'~
+ \str_if_eq:nnF {#1} {??} { ~in~hook~'#1' }. ~
Perhaps~ a~ missspelling?
}
{
The~ relation~ used~ not~ known~ to~ the~ system.~ Allowed~ values~ are~
- `before'~ or~ `<',~
- `after'~ or~ `>',~
- `incompatible-warning',~
- `incompatible-error',~
- `voids'~ or~
- `unrelated'.
+ 'before'~ or~ '<',~
+ 'after'~ or~ '>',~
+ 'incompatible-warning',~
+ 'incompatible-error',~
+ 'voids'~ or~
+ 'unrelated'.
}
% \end{macrocode}
%
% \begin{macrocode}
\msg_new:nnnn { hooks } { misused-top-level }
{
- Illegal~\iow_char:N \\AddToHook{#1}[top-level]{...}.\\
+ Illegal~use~of~\iow_char:N \\AddToHook{#1}[top-level]{...}.\\
'top-level'~is~reserved~for~the~user's~document.
}
{
@@ -4115,22 +4631,13 @@
% \begin{macrocode}
\msg_new:nnn { hooks } { set-top-level }
{
- You~cannot~change~the~default~label~#1~`top-level'.~Illegal \\
+ You~cannot~change~the~default~label~#1~'top-level'.~Illegal \\
\use:nn { ~ } { ~ } \iow_char:N \\#2{#3} \\
\msg_line_context:.
}
% \end{macrocode}
%
% \begin{macrocode}
-\msg_new:nnn { hooks } { ddhl-deprecated }
- {
- \iow_char:N \\DeclareDefaultHookLabel~is~deprecated.\\
- Use~\iow_char:N \\SetDefaultHookLabel~instead.\\ \\
- The~deprecated~name~will~be~removed~in~the~next~release.
- }
-% \end{macrocode}
-%
-% \begin{macrocode}
\msg_new:nnn { hooks } { extra-pop-label }
{
Extra~\iow_char:N \\PopDefaultHookLabel. \\
@@ -4139,18 +4646,47 @@
\msg_new:nnn { hooks } { missing-pop-label }
{
Missing~\iow_char:N \\PopDefaultHookLabel. \\
- The~label~`#1'~was~pushed~but~never~popped.~Something~is~wrong.
+ The~label~'#1'~was~pushed~but~never~popped.~Something~is~wrong.
}
% \end{macrocode}
%
% \begin{macrocode}
-\msg_new:nnn { hooks } { should-not-happen }
+\msg_new:nnn { kernel } { should-not-happen }
{
- ERROR!~This~should~not~happen.~#1 \\
+ This~should~not~happen.~#1 \\
Please~report~at~https://github.com/latex3/latex2e.
}
% \end{macrocode}
%
+%
+%
+% \begin{macrocode}
+\msg_new:nnn { hooks } { provide-disabled }
+ {
+ Cannot~ provide~ hook~ '#1'~ because~ it~ is~ disabled!
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnnn { hooks } { provide-error }
+ {
+ Hook~'#1'~ already~ declared~ as~ a~
+ \@@_if_reversed:nTF {#1} { reversed } { normal }~ hook!
+ }
+ {
+ You~ attempted~ to~ provide~ the~ hook~'#1'~ as~ a~
+ \@@_if_reversed:nTF {#1} { normal } { reversed }~ hook,~ but~ it~
+ was~ already~ previously~ declared~ as~ a~
+ \@@_if_reversed:nTF {#1} { reversed } { normal }~ hook.~
+ A~ redeclaration~ is~ not~ possible.
+ }
+% \end{macrocode}
+%
+%
+%
+%
+%
+%
% \subsection{\LaTeXe{} package interface commands}
%
%
@@ -4164,6 +4700,44 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\hook_provide:n}{Providing~hooks}
+% \end{macrocode}
+%
+% \begin{macro}{\ProvideHook,\ProvideReversedHook,\ProvideMirroredHookPair}
+% Providing new hooks \ldots
+% \changes{v1.0m}{2021/04/29}{Add \cs{ProvideHook} etc.}
+% \begin{macrocode}
+\NewDocumentCommand \ProvideHook { m }{ \hook_provide:n {#1} }
+\NewDocumentCommand \ProvideReversedHook { m }{ \hook_provide_reversed:n {#1} }
+\NewDocumentCommand \ProvideMirroredHookPair { mm }{ \hook_provide_pair:nn {#1}{#2} }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\DisableHook}
+% Disabling a (generic) hook.
+% \begin{macrocode}
+\NewDocumentCommand \DisableHook { m }{ \hook_disable:n {#1} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/10/01}
+%<latexrelease> {\hook_provide:n}{Providing~hooks}
+%<latexrelease>
+%<latexrelease>\def \ProvideHook#1{}
+%<latexrelease>\def \ProvideReversedHook#1{}
+%<latexrelease>\def \ProvideMirroredHookPair#1#2{}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+%
% \begin{macro}{\AddToHook}
%
% \begin{macrocode}
@@ -4192,7 +4766,10 @@
% \begin{macro}{\SetDefaultHookLabel}
% \begin{macro}{\PushDefaultHookLabel}
% \begin{macro}{\PopDefaultHookLabel}
-% \begin{macro}{\DeclareDefaultHookLabel}
+%
+% \fmiinline{Docu task: At some point this code for this should be moved to the
+% label section earlier and here we should keep only the interface commands.}
+%
% \begin{macro}{\@@_curr_name_push:n,\@@_curr_name_push_aux:n}
% \begin{macro}{\@@_curr_name_pop:}
% \begin{macro}{\@@_end_document_label_check:}
@@ -4216,8 +4793,11 @@
% the stack to support roll forward. But in some rare cases,
% \pkg{latexrelease} may be loaded inside another package (notably
% \pkg{platexrelease}), so we'll first push the |top-level| entry:
+% \changes{v1.0i}{2021/03/18}
+% {Only add \texttt{top-level} if not already there.}
% \begin{macrocode}
-%<latexrelease>\seq_gput_right:Nn \g_@@_name_stack_seq { top-level }
+%<latexrelease>\seq_if_empty:NT \g_@@_name_stack_seq
+%<latexrelease> { \seq_gput_right:Nn \g_@@_name_stack_seq { top-level } }
% \end{macrocode}
% then we dissect the \cs{@currnamestack}, adding \cs{@currname} to
% the stack:
@@ -4233,9 +4813,12 @@
%<latexrelease> \q_recursion_tail \q_recursion_tail
%<latexrelease> \q_recursion_tail \q_recursion_stop
% \end{macrocode}
-% and finalle set the default label to be the \cs{@currname}:
+% and finally set the default label to be the \cs{@currname}:
+% \changes{v1.0i}{2021/03/18}
+% {Remove the (empty) \enquote{top-level} from \cs{@currnamestack}.}
% \begin{macrocode}
%<latexrelease>\tl_gset:Nx \g_@@_hook_curr_name_tl { \@currname }
+%<latexrelease>\seq_gpop_right:NN \g_@@_name_stack_seq \l_@@_tmpa_tl
% \end{macrocode}
%
% Two commands keep track of the stack: when a file is input,
@@ -4274,7 +4857,7 @@
% \end{macrocode}
%
% At the end of the document we want to check if there was no
-% \cs{@@_curr_name_push:} without a matching \cs{@@_curr_name_pop:}
+% \cs{@@_curr_name_push:n} without a matching \cs{@@_curr_name_pop:}
% (not a critical error, but it might indicate that something else is
% not quite right):
% \begin{macrocode}
@@ -4316,11 +4899,6 @@
}
{ \tl_gset:Nn \g_@@_hook_curr_name_tl {#1} }
}
-\NewDocumentCommand \DeclareDefaultHookLabel { m }
- {
- \msg_error:nn { hooks } { ddhl-deprecated }
- \SetDefaultHookLabel {#1}
- }
% \end{macrocode}
%
% The label is only automatically updated with \cs{@onefilewithoptions}
@@ -4360,7 +4938,6 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
%
%
%
@@ -4413,7 +4990,7 @@
% \begin{macro}{\ClearHookRule}
% A special setup rule that removes an existing relation.
% Basically {@@_rule_gclear:nnn} plus fixing the property list for debugging.
-% \fmi{Need an L3 interface, or maybe it should get dropped?}
+% \fmiinline{Needs perhaps an L3 interface, or maybe it should get dropped?}
% \begin{macrocode}
\NewDocumentCommand \ClearHookRule { m m m }
{ \hook_gset_rule:nnnn {#1}{#2}{unrelated}{#3} }
@@ -4421,19 +4998,33 @@
% \end{macro}
%
%
-% \begin{macro}[EXP]{\IfHookExistsTF,\IfHookEmptyTF}
+% \begin{macro}[EXP]{\IfHookEmptyTF}
% Here we avoid the overhead of \pkg{xparse}, since \cs{IfHookEmptyTF}
% is used in \cs{end} (that is, every \LaTeX{} environment). As a
% further optimisation, use \cs{let} rather than \cs{def} to avoid one
% expansion step.
% \begin{macrocode}
-\cs_new_eq:NN \IfHookExistsTF \hook_if_exist:nTF
\cs_new_eq:NN \IfHookEmptyTF \hook_if_empty:nTF
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[EXP]{\IfHookExistsTF}
+% Marked for removal and no longer documented in the doc section!
+% \phoinline{\cs{IfHookExistsTF} is used in \texttt{jlreq.cls},
+% \texttt{pxatbegshi.sty}, \texttt{pxeverysel.sty},
+% \texttt{pxeveryshi.sty}, so the public name may be an alias of the
+% internal conditional for a while. Regardless, those packages' use for
+% \cs{IfHookExistsTF} is not really correct and can be changed.}
+% \begin{macrocode}
+\cs_new_eq:NN \IfHookExistsTF \@@_if_usable:nTF
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
%
% \subsection{Internal commands needed elsewhere}
%
@@ -4449,6 +5040,7 @@
% \begin{macro}{\@expl@@@initialize@all@@,
% \@expl@@@hook@curr@name@pop@@}
%
+% \InternalDetectionOff
% \begin{macrocode}
\cs_new_eq:NN \@expl@@@initialize@all@@
\__hook_initialize_all:
@@ -4458,29 +5050,25 @@
\cs_new_eq:NN \@expl@@@hook@curr@name@pop@@
\__hook_curr_name_pop:
% \end{macrocode}
+% \InternalDetectionOn
% \end{macro}
%
-%
-% \begin{macrocode}
-\ExplSyntaxOff
-% \end{macrocode}
-%
-%
% Rolling back here doesn't undefine the interface commands as they
% may be used in packages without rollback functionality. So we
% just make them do nothing which may or may not work depending on
% the code usage.
% \changes{v1.0d}{2020/10/04}{Definition \cs{AddToHookNext} was supposed
-% to be for \cs{AddToHook} vize versa (gh/401)}
+% to be for \cs{AddToHook} vice versa (gh/401)}
% \begin{macrocode}
-%</2ekernel|latexrelease>
-%<latexrelease>\EndIncludeInRelease
+%
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\NewHook}{The hook management}%
+%<latexrelease> {lthooks}{The~hook~management}%
+%<latexrelease>
+%<latexrelease>\def \NewHook#1{}
+%<latexrelease>\def \NewReversedHook#1{}
+%<latexrelease>\def \NewMirroredHookPair#1#2{}
%<latexrelease>
-%<latexrelease>\def\NewHook#1{}
-%<latexrelease>\def\NewReversedHook#1{}
-%<latexrelease>\def\NewMirroredHookPair#1#2{}
+%<latexrelease>\def \DisableHook #1{}
%<latexrelease>
%<latexrelease>\long\def\AddToHookNext#1#2{}
%<latexrelease>
@@ -4508,7 +5096,9 @@
%<latexrelease>\long\def \IfHookExistsTF #1#2#3{#3}
%<latexrelease>\long\def \IfHookEmptyTF #1#2#3{#2}
%<latexrelease>
-%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\EndModuleRelease
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
% \end{macrocode}
%
%
diff --git a/macros/latex/base/lthyphen.dtx b/macros/latex/base/lthyphen.dtx
index 71ab081c66..9244db0642 100644
--- a/macros/latex/base/lthyphen.dtx
+++ b/macros/latex/base/lthyphen.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -40,7 +40,7 @@
%\iffalse This is a META comment
%
% File `lthyphen.dtx'.
-% Copyright (C) 1994-94 LaTeX3 project, Frank Mittelbach and
+% Copyright (C) 1994-94 LaTeX Project, Frank Mittelbach and
% Rainer Sch\"opf, all rights reserved.
%
%\fi
diff --git a/macros/latex/base/ltidxglo.dtx b/macros/latex/base/ltidxglo.dtx
index dcb88e83e9..75a80cd439 100644
--- a/macros/latex/base/ltidxglo.dtx
+++ b/macros/latex/base/ltidxglo.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltlength.dtx b/macros/latex/base/ltlength.dtx
index f5b63ed35e..1be147547e 100644
--- a/macros/latex/base/ltlength.dtx
+++ b/macros/latex/base/ltlength.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltlength.dtx}
- [2019/08/27 v1.1d LaTeX Kernel (Lengths)]
+ [2020/12/05 v1.1d LaTeX Kernel (Lengths)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltlength.dtx}
@@ -154,7 +154,7 @@
% This macro takes the contents of the skip register that is
% supplied as its argument and removes the fractional part to make
% it a whole number of points. This can be used in class files to
-% avoid values like |345.4666666pt| when calulating a dimension.
+% avoid values like |345.4666666pt| when calculating a dimension.
% \changes{LaTeX2e}{1993/11/22}{Macro added}
% \begin{macrocode}
\def\@settopoint#1{\divide#1\p@\multiply#1\p@}
diff --git a/macros/latex/base/ltlists.dtx b/macros/latex/base/ltlists.dtx
index 653e4e2edd..fecb312588 100644
--- a/macros/latex/base/ltlists.dtx
+++ b/macros/latex/base/ltlists.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -31,7 +31,7 @@
%<*driver>
% \fi
\ProvidesFile{ltlists.dtx}
- [2020/04/24 v1.0t LaTeX Kernel (List Environments)]
+ [2020/12/05 v1.0t LaTeX Kernel (List Environments)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltlists.dtx}
@@ -112,7 +112,7 @@
% the entire environment is a single item. It is defined by
% letting |\quotation| == |\list{}{...}\item\relax|. (Note the
% |\relax|, there in case the first character in the environment is a
-% '['.) The spacing parameters provide a great deal of flexability in
+% '['.) The spacing parameters provide a great deal of flexibility in
% designing the format, including the ability to let the indentation of
% the first paragraph be different from that of the subsequent ones.
%
@@ -589,7 +589,7 @@
% when not inlabel flag is false}
% Because |\par| is sometimes made a no-op it is possible for a missing
% |\item| to produce a loop that does not fill memory and so never gets
-% trapped by \TeX. We thus need to trap this here by seting |\par| to
+% trapped by \TeX. We thus need to trap this here by setting |\par| to
% count the number of times a paragraph ii is called with no progress
% being made started.
% \begin{macrocode}
@@ -729,7 +729,7 @@
% If a section heading changes |\clubpenalty| to keep lines
% after it together then this modification is restored via the
% |\everypar| mechanism at the start of the next paragraph. As we
-% destroy the contents of this token here we explicity set
+% destroy the contents of this token here we explicitly set
% |\clubpenalty| back to its default.
% \changes{v1.0t}{2015/05/10}{Explicitly reset \cs{clubpenalty} before
% clearing \cs{everypar}; see also pr/0462 and pr/4065}
@@ -807,7 +807,7 @@
% \end{macro}
%
% \begin{macro}{\@item}
-% \changes{v1.0l}{1996/07/26}{Remove unecessary \cs{global} before
+% \changes{v1.0l}{1996/07/26}{Remove unnecessary \cs{global} before
% \cs{@minipage...}}
% \begin{macrocode}
\def\@item[#1]{%
@@ -889,7 +889,7 @@
\everypar{}%
\fi}%
% \end{macrocode}
-% \changes{v1.0l}{1996/07/26}{Remove unecessary \cs{global} before
+% \changes{v1.0l}{1996/07/26}{Remove unnecessary \cs{global} before
% \cs{@nobreak...}}
% \changes{v1.0m}{1996/10/23}{\cs{@nobreak...} moved into the
% \cs{everypar} and not executed unconditionally, see above}
diff --git a/macros/latex/base/ltlogos.dtx b/macros/latex/base/ltlogos.dtx
index 6784cb41c0..132eaf636f 100644
--- a/macros/latex/base/ltlogos.dtx
+++ b/macros/latex/base/ltlogos.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltluatex.dtx b/macros/latex/base/ltluatex.dtx
index 8573b3e6ca..3b9a337731 100644
--- a/macros/latex/base/ltluatex.dtx
+++ b/macros/latex/base/ltluatex.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2015-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2015-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -28,7 +28,7 @@
\ProvidesFile{ltluatex.dtx}
%</driver>
%<*tex>
-[2020/09/25 v1.1s
+[2021/04/18 v1.1t
%</tex>
%<plain> LuaTeX support for plain TeX (core)
%<*tex>
@@ -38,6 +38,10 @@
%</tex>
%<*driver>
\documentclass{ltxdoc}
+
+\providecommand\InternalDetectionOff{}
+\providecommand\InternalDetectionOn{}
+
\GetFileInfo{ltluatex.dtx}
\begin{document}
\title{\filename\\(Lua\TeX{}-specific support)}
@@ -129,7 +133,7 @@
% \DescribeMacro{\newluachunkname}
% |newluachunkname{|\meta{chunkname}|}|\\
% Allocates a number for Lua chunk register, indexed from~$1$.
-% Also enters the name of the regiser (without backslash) into the
+% Also enters the name of the register (without backslash) into the
% \verb|lua.name| table to be used in stack traces.
%
% \noindent
@@ -204,6 +208,7 @@
% The number is returned and also \meta{name} argument is added to the
% |lua.name| array at that index.
%
+% \begin{sloppypar}
% \noindent
% \DescribeMacro{new_luafunction}
% |luatexbase.new_luafunction(|\meta{functionname}|)|\\
@@ -211,6 +216,7 @@
% with |\luafunction|, |\lateluafunction|, and |\luadef|,
% indexed from~$1$. The optional \meta{functionname} argument
% is just used for logging.
+% \end{sloppypar}
%
% These functions all require access to a named \TeX{} count register
% to manage their allocations. The standard names are those defined
@@ -582,7 +588,7 @@
% \changes{v1.0a}{2015/09/24}{Macro added}
% Category code tables are allocated with a limit half of that used by Lua\TeX{}
% for everything else. At the end of allocation there needs to be an
-% initialisation step. Table~$0$ is already taken (it's the global one for
+% initialization step. Table~$0$ is already taken (it's the global one for
% current use) so the allocation starts at~$1$.
% \begin{macrocode}
\ifx\e@alloc@ccodetable@count\@undefined
@@ -779,8 +785,8 @@
% \subsection{Lua loader}
% \changes{v1.1r}{2020/08/10}{Load ltluatex Lua module during format building}
%
-% Lua code loaded in the format often has to to be loaded again at the
-% beginning of every job, so we define a helper whch allows us to avoid
+% Lua code loaded in the format often has to be loaded again at the
+% beginning of every job, so we define a helper which allows us to avoid
% duplicated code:
%
% \begin{macrocode}
@@ -1113,9 +1119,10 @@ luatexbase.registernumber = registernumber
%
% \begin{macro}{new_attribute}
% \changes{v1.0a}{2015/09/24}{Function added}
-% \changes{v1.1c}{2017/02/18}{Parameterise count used in tracking}
+% \changes{v1.1c}{2017/02/18}{Parameterize count used in tracking}
% As attributes are used for Lua manipulations its useful to be able
% to assign from this end.
+% \InternalDetectionOff
% \begin{macrocode}
local attributes=setmetatable(
{},
@@ -1143,12 +1150,13 @@ local function new_attribute(name)
end
luatexbase.new_attribute = new_attribute
% \end{macrocode}
+% \InternalDetectionOn
% \end{macro}
%
% \subsection{Custom whatsit allocation}
%
% \begin{macro}{new_whatsit}
-% \changes{v1.1c}{2017/02/18}{Parameterise count used in tracking}
+% \changes{v1.1c}{2017/02/18}{Parameterize count used in tracking}
% Much the same as for attribute allocation in Lua.
% \begin{macrocode}
local whatsit_count_name = whatsit_count_name or "e@alloc@whatsit@count"
@@ -1169,7 +1177,7 @@ luatexbase.new_whatsit = new_whatsit
% \subsection{Bytecode register allocation}
%
% \begin{macro}{new_bytecode}
-% \changes{v1.1c}{2017/02/18}{Parameterise count used in tracking}
+% \changes{v1.1c}{2017/02/18}{Parameterize count used in tracking}
% Much the same as for attribute allocation in Lua.
% The optional \meta{name} argument is used in the log if given.
% \begin{macrocode}
@@ -1192,7 +1200,7 @@ luatexbase.new_bytecode = new_bytecode
% \subsection{Lua chunk name allocation}
%
% \begin{macro}{new_chunkname}
-% \changes{v1.1c}{2017/02/18}{Parameterise count used in tracking}
+% \changes{v1.1c}{2017/02/18}{Parameterize count used in tracking}
% As for bytecode registers but also store the name in the
% |lua.name| table.
% \begin{macrocode}
@@ -1404,6 +1412,7 @@ local callbacktypes = callbacktypes or {
% \changes{v1.1j}{2019/06/18}{make\_extensible added}
% \changes{v1.1j}{2019/06/18}{font\_descriptor\_objnum\_provider added}
% \changes{v1.1l}{2020/02/02}{glyph\_info added}
+% \changes{v1.1t}{2021/04/18}{input\_level\_string added}
% \begin{macrocode}
define_font = exclusive,
glyph_info = exclusive,
@@ -1411,6 +1420,7 @@ local callbacktypes = callbacktypes or {
glyph_stream_provider = exclusive,
make_extensible = exclusive,
font_descriptor_objnum_provider = exclusive,
+ input_level_string = exclusive,
% \end{macrocode}
% \changes{v1.0m}{2016/02/11}{pdf\_stream\_filter\_callback removed}
% \begin{macrocode}
@@ -1469,7 +1479,7 @@ end
% functions in inverse order.
% \item[exclusive] is for functions with more complex signatures; functions in
% this type of callback are \emph{not} combined: An error is raised if
-% a second callback is registered..
+% a second callback is registered.
% \end{description}
%
% Handler for |data| callbacks.
@@ -1735,7 +1745,7 @@ luatexbase.add_to_callback = add_to_callback
%
% \begin{macro}{remove_from_callback}
% \changes{v1.0a}{2015/09/24}{Function added}
-% \changes{v1.0k}{2015/12/02}{adjust initialisation of cb local (PHG)}
+% \changes{v1.0k}{2015/12/02}{adjust initialization of cb local (PHG)}
% \changes{v1.0k}{2015/12/02}{Give more specific error messages (PHG)}
% \changes{v1.1m}{2020/03/07}{Do not call callback.register for user-defined callbacks}
% Remove a function from a callback. First check arguments.
diff --git a/macros/latex/base/ltluatex.pdf b/macros/latex/base/ltluatex.pdf
index 2cc8ddad3f..93315b577e 100644
--- a/macros/latex/base/ltluatex.pdf
+++ b/macros/latex/base/ltluatex.pdf
Binary files differ
diff --git a/macros/latex/base/ltmath.dtx b/macros/latex/base/ltmath.dtx
index 770367c8a3..aadb96fb02 100644
--- a/macros/latex/base/ltmath.dtx
+++ b/macros/latex/base/ltmath.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -38,7 +38,7 @@
%<*driver>
% \fi
\ProvidesFile{ltmath.dtx}
- [2020/11/09 v1.2h LaTeX Kernel (Math Setup)]
+ [2021/04/20 v1.2i LaTeX Kernel (Math Setup)]
% \iffalse
%</driver>
%
@@ -529,7 +529,7 @@
%
% Originally \LaTeX{} only provided a small set of spacing commands
% for use in text and math, some of the commands like \cs{;} were
-% only supported in manth mode. \texttt{amsmath} normalized and
+% only supported in math mode. \texttt{amsmath} normalized and
% provided all of them in text and math. This code has now been
% moved to the kernel so that it is generally available.
%
@@ -961,11 +961,12 @@
% \end{macro}
%
% \begin{macro}{\@eqncr}
+% \changes{v1.2i}{2021/04/20}{Use \cs{protected} for \cs{\bslash} variant (gh/548)}
% \begin{macro}{\@xeqncr}
% \begin{macro}{\@yeqncr}
% \changes{v1.0y}{1995/10/16}{(DPC) Use \cs{@testopt} /1911}
% \begin{macrocode}
-\def\@eqncr{%
+\protected\def\@eqncr{%
{\ifnum0=`}\fi
\@ifstar{%
\global\@eqpen\@M\@yeqncr
@@ -1033,8 +1034,9 @@
\let\@seqncr=\@eqncr
% \end{macrocode}
%
+% \changes{v1.2i}{2021/04/20}{Use \cs{protected} for \cs{\bslash} variant (gh/548)}
% \begin{macrocode}
-\@namedef{eqnarray*}{\def\@eqncr{\nonumber\@seqncr}\eqnarray}
+\@namedef{eqnarray*}{\protected\def\@eqncr{\nonumber\@seqncr}\eqnarray}
% \end{macrocode}
%
% \begin{macrocode}
@@ -1101,7 +1103,7 @@
% To put the equation number on the left side of an equation we
% have to use a little trick. The number is shifted |\displaywidth|
% to the left inside a box of (approximately) zero width. This
-% fails when the quation is too wide, the equation number than may
+% fails when the equation is too wide, the equation number than may
% overprint the equation itself.
% \changes{v1.2y classes}{1995/01/12}{Added \cs{normalcolor}}
% \changes{v1.3c classes}{1995/05/25}
diff --git a/macros/latex/base/ltmiscen.dtx b/macros/latex/base/ltmiscen.dtx
index cf7f3c836b..8bae3f9bfa 100644
--- a/macros/latex/base/ltmiscen.dtx
+++ b/macros/latex/base/ltmiscen.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltmiscen.dtx}
- [2020/12/18 v1.1x LaTeX Kernel (Misc. Environments)]
+ [2021/02/08 v1.1y LaTeX Kernel (Misc. Environments)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltmiscen.dtx}
@@ -214,6 +214,7 @@
% \changes{v1.1i}{2000/05/19}
% {Reset \cs{AtEndDocument} for latex/3060}
% \begin{macrocode}
+ \@kernel@before@enddocument
\UseOneTimeHook{enddocument}%
\@kernel@after@enddocument
% \end{macrocode}
@@ -390,6 +391,35 @@
%<*2ekernel>
% \end{macrocode}
%
+% \begin{macro}{\@kernel@before@enddocument}
+% The \cs{@kernel@before@enddocument} hook is slightly different
+% because we initialize it with \cs{par} so that \cs{enddocument} always
+% returns to vertical mode as its first action.
+% \changes{v1.1x}{2020/10/26}{\cs{enddocument} should always start out in
+% vmode (gh/385)}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}%
+%<latexrelease> {\@kernel@before@enddocument}{kernel before hook}%
+\def\@kernel@before@enddocument{\par}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% The rollback code renders it harmless.
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@kernel@before@enddocument}{kernel before hook}%
+%<latexrelease>
+%<latexrelease>\let\@kernel@before@enddocument\@empty
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
%
%
% \begin{macro}{\@testdef}
@@ -838,6 +868,15 @@
%<latexrelease> \expandafter\endgroup\if@endpe\@doendpe\fi
%<latexrelease> \if@ignore\@ignorefalse\ignorespaces\fi}
%<latexrelease>
+% \end{macrocode}
+% Also undo the internal commands as some packages unfortunately test
+% for their existence instead of using \cs{IfFormatAtLeastTF}.
+% \changes{v1.1y}{2021/02/08}{Undo the internals for robust \cs{begin}
+% and \cs{end} in rollback (gh/494)}
+% \begin{macrocode}
+%<latexrelease>\expandafter\let\csname begin \endcsname\@undefined
+%<latexrelease>\expandafter\let\csname end \endcsname\@undefined
+%<latexrelease>
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
diff --git a/macros/latex/base/ltnews.cls b/macros/latex/base/ltnews.cls
index 632f068117..9271b56f1c 100644
--- a/macros/latex/base/ltnews.cls
+++ b/macros/latex/base/ltnews.cls
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -35,7 +35,7 @@
% with LaTeX. The changes log is at the end of the file.
% Copyright 1994-2004
-% Alan Jeffrey and the LaTeX3 project.
+% Alan Jeffrey and the LaTeX Project.
% This is a LaTeX2e document class.
@@ -437,7 +437,7 @@
\newcommand{\indicia}{\renewcommand{\@indicia}}
\newcommand{\@indicia}{%
\LaTeXNews, and the \LaTeX{} software,
- are brought to you by the \LaTeX3 Project Team;
+ are brought to you by the \LaTeX\ Project Team;
Copyright \@year, all rights reserved.
}
diff --git a/macros/latex/base/ltnews.pdf b/macros/latex/base/ltnews.pdf
index 19f3de087e..c3a22e4f81 100644
--- a/macros/latex/base/ltnews.pdf
+++ b/macros/latex/base/ltnews.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews.tex b/macros/latex/base/ltnews.tex
index ffc34da26c..fa44de670c 100644
--- a/macros/latex/base/ltnews.tex
+++ b/macros/latex/base/ltnews.tex
@@ -1,7 +1,9 @@
% \iffalse meta-comment
%
-% Copyright 2006, 2009, 2011, 2014 Heiko Oberdiek
-% Copyright (C) 2014-2020 The LaTeX3 Project
+% Copyright (C) 2006, 2009, 2011, 2014 Heiko Oberdiek
+% Copyright (C) 2014-2021
+% The LaTeX Project and any individual authors listed elsewhere
+% in this file.
%
% This file is part of the LaTeX base system.
% -------------------------------------------
@@ -36,9 +38,9 @@
\NeedsTeXFormat{LaTeX2e}
\ProvidesFile{ltnews.tex}%
- [2020/04/13 v1.4d Master file for ltnews*.tex (LaTeX Project)]
+ [2020/10/25 v1.4d Master file for ltnews*.tex (LaTeX Project)]
-\providecommand*{\lastissue}{32}
+\providecommand*{\lastissue}{33}
\InputIfFileExists{ltnews-lastissue.cfg}{}{}
@@ -175,6 +177,11 @@
\egroup
}
+\ExplSyntaxOn
+\newcommand \acro [1]
+ { \textsc { \text_lowercase:n {#1} } }
+\ExplSyntaxOff
+
\makeatother
diff --git a/macros/latex/base/ltnews01.pdf b/macros/latex/base/ltnews01.pdf
index a595669dd5..855b37cb67 100644
--- a/macros/latex/base/ltnews01.pdf
+++ b/macros/latex/base/ltnews01.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews01.tex b/macros/latex/base/ltnews01.tex
index c5d66f003e..3703f23f61 100644
--- a/macros/latex/base/ltnews01.tex
+++ b/macros/latex/base/ltnews01.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -52,8 +52,8 @@ fixes, newly available packages, or any other \LaTeX{} news.
The most important news is the release of \LaTeXe, the new version of
the \LaTeX{} software. This version has better support for fonts,
-graphics and colour, and will be actively maintained by the \LaTeX3
-project team. Upgrades will be issued every six months, in June and
+graphics and colour, and will be actively maintained by the \LaTeX\
+Project team. Upgrades will be issued every six months, in June and
December.
\section{Why a new \LaTeX?}
@@ -110,7 +110,7 @@ from the distributor who brought you \LaTeXe:
\item[graphics] for including images.
\item[mfnfss] for using bitmap fonts.
\item[psnfss] for using Type~1 fonts.
-\item[tools] other packages by the \LaTeX3 team.
+\item[tools] other packages by the \LaTeX\ Project team.
\end{citations}
The packages come with full documentation, and are also described in
\emph{\LaTeX: A Document Processing System} or
diff --git a/macros/latex/base/ltnews02.pdf b/macros/latex/base/ltnews02.pdf
index ce3cca5271..ceb30b352e 100644
--- a/macros/latex/base/ltnews02.pdf
+++ b/macros/latex/base/ltnews02.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews02.tex b/macros/latex/base/ltnews02.tex
index b0e3d15be8..e1fa2909dc 100644
--- a/macros/latex/base/ltnews02.tex
+++ b/macros/latex/base/ltnews02.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews03.pdf b/macros/latex/base/ltnews03.pdf
index 9f4b7fb62b..cc114b3c2c 100644
--- a/macros/latex/base/ltnews03.pdf
+++ b/macros/latex/base/ltnews03.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews03.tex b/macros/latex/base/ltnews03.tex
index 0496843f0d..f000d66e4d 100644
--- a/macros/latex/base/ltnews03.tex
+++ b/macros/latex/base/ltnews03.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews04.pdf b/macros/latex/base/ltnews04.pdf
index 0491401886..2fa4552b7f 100644
--- a/macros/latex/base/ltnews04.pdf
+++ b/macros/latex/base/ltnews04.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews04.tex b/macros/latex/base/ltnews04.tex
index d64d4cb748..cbcf151f12 100644
--- a/macros/latex/base/ltnews04.tex
+++ b/macros/latex/base/ltnews04.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews05.pdf b/macros/latex/base/ltnews05.pdf
index 4006b29016..2320f76c61 100644
--- a/macros/latex/base/ltnews05.pdf
+++ b/macros/latex/base/ltnews05.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews05.tex b/macros/latex/base/ltnews05.tex
index 07b95287ef..f8d611808b 100644
--- a/macros/latex/base/ltnews05.tex
+++ b/macros/latex/base/ltnews05.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews06.pdf b/macros/latex/base/ltnews06.pdf
index 86bb0d89c1..9dccfbb5dd 100644
--- a/macros/latex/base/ltnews06.pdf
+++ b/macros/latex/base/ltnews06.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews06.tex b/macros/latex/base/ltnews06.tex
index c296040047..d0c5943b5e 100644
--- a/macros/latex/base/ltnews06.tex
+++ b/macros/latex/base/ltnews06.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews07.pdf b/macros/latex/base/ltnews07.pdf
index a6c31f8701..ed48011dc9 100644
--- a/macros/latex/base/ltnews07.pdf
+++ b/macros/latex/base/ltnews07.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews07.tex b/macros/latex/base/ltnews07.tex
index 020e8bd8a6..53b8b778f4 100644
--- a/macros/latex/base/ltnews07.tex
+++ b/macros/latex/base/ltnews07.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews08.pdf b/macros/latex/base/ltnews08.pdf
index 0645d3dc33..7f06cefc47 100644
--- a/macros/latex/base/ltnews08.pdf
+++ b/macros/latex/base/ltnews08.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews08.tex b/macros/latex/base/ltnews08.tex
index ab9d26d48b..5ea811267d 100644
--- a/macros/latex/base/ltnews08.tex
+++ b/macros/latex/base/ltnews08.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews09.pdf b/macros/latex/base/ltnews09.pdf
index 1d17dca6e7..e085006df9 100644
--- a/macros/latex/base/ltnews09.pdf
+++ b/macros/latex/base/ltnews09.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews09.tex b/macros/latex/base/ltnews09.tex
index f0b396586f..0d959d9f92 100644
--- a/macros/latex/base/ltnews09.tex
+++ b/macros/latex/base/ltnews09.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -47,7 +47,7 @@
\section{New math font encodings}
-A joint working group of the \TeX{} Users Group and the \LaTeX3
+A joint working group of the \TeX{} Users Group and the \LaTeX\
Project is developing a new 8-bit math font encoding for \TeX{}.
It is designed to overcome several limitations and implementation
problems of the old math font encodings and to simplify switching
diff --git a/macros/latex/base/ltnews10.pdf b/macros/latex/base/ltnews10.pdf
index cccbbd2ff3..e5022eedcc 100644
--- a/macros/latex/base/ltnews10.pdf
+++ b/macros/latex/base/ltnews10.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews10.tex b/macros/latex/base/ltnews10.tex
index 02ba863a38..bad9fda6ce 100644
--- a/macros/latex/base/ltnews10.tex
+++ b/macros/latex/base/ltnews10.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews11.pdf b/macros/latex/base/ltnews11.pdf
index 3073a3a2d3..d6d87f102a 100644
--- a/macros/latex/base/ltnews11.pdf
+++ b/macros/latex/base/ltnews11.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews11.tex b/macros/latex/base/ltnews11.tex
index 40c1c120af..6d27fee067 100644
--- a/macros/latex/base/ltnews11.tex
+++ b/macros/latex/base/ltnews11.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -110,7 +110,7 @@ package.
\section{New math font encodings}
As we announced in \LaTeX{} News~9, a joint working group of the
-\TeX{} Users Group and the \LaTeX3 Project has developed a new
+\TeX{} Users Group and the \LaTeX\ Project has developed a new
\mbox{8-bit} math font encoding for \TeX{}.
The reason why this work is not yet released is because of other
exciting developments in the world of math fonts and math characters.
diff --git a/macros/latex/base/ltnews12.pdf b/macros/latex/base/ltnews12.pdf
index f33b9fa2b2..c7f1944e4a 100644
--- a/macros/latex/base/ltnews12.pdf
+++ b/macros/latex/base/ltnews12.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews12.tex b/macros/latex/base/ltnews12.tex
index 5bf095b4aa..7e3a73f508 100644
--- a/macros/latex/base/ltnews12.tex
+++ b/macros/latex/base/ltnews12.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -40,8 +40,7 @@
\publicationyear{1999}
\publicationissue{12}
-% Should go to .cls:
-\newcommand{\acro}[1]{\textsc{\MakeLowercase{#1}}}
+\providecommand{\acro}[1]{\textsc{\MakeLowercase{#1}}}
\begin{document}
diff --git a/macros/latex/base/ltnews13.pdf b/macros/latex/base/ltnews13.pdf
index 0b8da8f1a3..2eb3e5252d 100644
--- a/macros/latex/base/ltnews13.pdf
+++ b/macros/latex/base/ltnews13.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews13.tex b/macros/latex/base/ltnews13.tex
index f9241ead81..185a080e2b 100644
--- a/macros/latex/base/ltnews13.tex
+++ b/macros/latex/base/ltnews13.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews14.pdf b/macros/latex/base/ltnews14.pdf
index 0efc5c9b02..901ed0d704 100644
--- a/macros/latex/base/ltnews14.pdf
+++ b/macros/latex/base/ltnews14.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews14.tex b/macros/latex/base/ltnews14.tex
index 22df643f75..836591019e 100644
--- a/macros/latex/base/ltnews14.tex
+++ b/macros/latex/base/ltnews14.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews15.pdf b/macros/latex/base/ltnews15.pdf
index fce7d7f09f..b2e8b569c5 100644
--- a/macros/latex/base/ltnews15.pdf
+++ b/macros/latex/base/ltnews15.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews15.tex b/macros/latex/base/ltnews15.tex
index cbf8f8840b..4532111d98 100644
--- a/macros/latex/base/ltnews15.tex
+++ b/macros/latex/base/ltnews15.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews16.pdf b/macros/latex/base/ltnews16.pdf
index 9010892932..893063bfad 100644
--- a/macros/latex/base/ltnews16.pdf
+++ b/macros/latex/base/ltnews16.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews16.tex b/macros/latex/base/ltnews16.tex
index 75ee38c815..8f96ed197f 100644
--- a/macros/latex/base/ltnews16.tex
+++ b/macros/latex/base/ltnews16.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -49,7 +49,7 @@
\section{Anniversary news}
This anniversary \textit{Issue~16} takes a brief look into the future work of
-the \LaTeX3 Project Team, both short and longer range. Please let
+the \LaTeX\ Project Team, both short and longer range. Please let
us know if you want %\newline
to get involved with us in any of this work (see below).
diff --git a/macros/latex/base/ltnews17.pdf b/macros/latex/base/ltnews17.pdf
index 463a597b99..cf3983ba37 100644
--- a/macros/latex/base/ltnews17.pdf
+++ b/macros/latex/base/ltnews17.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews17.tex b/macros/latex/base/ltnews17.tex
index 9abe4053e7..f850f8d64c 100644
--- a/macros/latex/base/ltnews17.tex
+++ b/macros/latex/base/ltnews17.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews18.pdf b/macros/latex/base/ltnews18.pdf
index 59ed450aef..83e8a09910 100644
--- a/macros/latex/base/ltnews18.pdf
+++ b/macros/latex/base/ltnews18.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews18.tex b/macros/latex/base/ltnews18.tex
index 3a99f8501b..518aeda067 100644
--- a/macros/latex/base/ltnews18.tex
+++ b/macros/latex/base/ltnews18.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews19.pdf b/macros/latex/base/ltnews19.pdf
index 40360ea17c..734b324d0e 100644
--- a/macros/latex/base/ltnews19.pdf
+++ b/macros/latex/base/ltnews19.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews19.tex b/macros/latex/base/ltnews19.tex
index a6f1fa9512..4d50b98c82 100644
--- a/macros/latex/base/ltnews19.tex
+++ b/macros/latex/base/ltnews19.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews20.pdf b/macros/latex/base/ltnews20.pdf
index d9b48b8a9e..6b226bdffb 100644
--- a/macros/latex/base/ltnews20.pdf
+++ b/macros/latex/base/ltnews20.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews20.tex b/macros/latex/base/ltnews20.tex
index a43aa37b7c..44acd1ec3e 100644
--- a/macros/latex/base/ltnews20.tex
+++ b/macros/latex/base/ltnews20.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 1993--2019
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews21.pdf b/macros/latex/base/ltnews21.pdf
index 8212b9a06b..0d13bc374b 100644
--- a/macros/latex/base/ltnews21.pdf
+++ b/macros/latex/base/ltnews21.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews21.tex b/macros/latex/base/ltnews21.tex
index d94df28b48..14de47c648 100644
--- a/macros/latex/base/ltnews21.tex
+++ b/macros/latex/base/ltnews21.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 2019
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews22.pdf b/macros/latex/base/ltnews22.pdf
index 4192e08538..64be8e37ce 100644
--- a/macros/latex/base/ltnews22.pdf
+++ b/macros/latex/base/ltnews22.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews22.tex b/macros/latex/base/ltnews22.tex
index c6cfec6c45..e73fb4b7c4 100644
--- a/macros/latex/base/ltnews22.tex
+++ b/macros/latex/base/ltnews22.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2015-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2015-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews23.pdf b/macros/latex/base/ltnews23.pdf
index 399e25e457..9b856dfed5 100644
--- a/macros/latex/base/ltnews23.pdf
+++ b/macros/latex/base/ltnews23.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews23.tex b/macros/latex/base/ltnews23.tex
index e14a0697b0..36f8948e7d 100644
--- a/macros/latex/base/ltnews23.tex
+++ b/macros/latex/base/ltnews23.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2015-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2015-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews24.pdf b/macros/latex/base/ltnews24.pdf
index 18b2406db7..bb25bb9195 100644
--- a/macros/latex/base/ltnews24.pdf
+++ b/macros/latex/base/ltnews24.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews24.tex b/macros/latex/base/ltnews24.tex
index 6371ffa0a3..5dee993186 100644
--- a/macros/latex/base/ltnews24.tex
+++ b/macros/latex/base/ltnews24.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2015-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2015-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews25.pdf b/macros/latex/base/ltnews25.pdf
index 1b9c0bec61..61064c6c9e 100644
--- a/macros/latex/base/ltnews25.pdf
+++ b/macros/latex/base/ltnews25.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews25.tex b/macros/latex/base/ltnews25.tex
index 1500da5c07..e1881018ba 100644
--- a/macros/latex/base/ltnews25.tex
+++ b/macros/latex/base/ltnews25.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2016-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2016-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews26.pdf b/macros/latex/base/ltnews26.pdf
index 4be6545a43..26a3d6b5aa 100644
--- a/macros/latex/base/ltnews26.pdf
+++ b/macros/latex/base/ltnews26.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews26.tex b/macros/latex/base/ltnews26.tex
index 134859ad63..e1ae85dda8 100644
--- a/macros/latex/base/ltnews26.tex
+++ b/macros/latex/base/ltnews26.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2017-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2017-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews27.pdf b/macros/latex/base/ltnews27.pdf
index eaa272fd12..906f101f3c 100644
--- a/macros/latex/base/ltnews27.pdf
+++ b/macros/latex/base/ltnews27.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews27.tex b/macros/latex/base/ltnews27.tex
index 6b550bf0cd..3572b5e0b1 100644
--- a/macros/latex/base/ltnews27.tex
+++ b/macros/latex/base/ltnews27.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2017-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2017-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews28.pdf b/macros/latex/base/ltnews28.pdf
index f326e75b15..758cac6345 100644
--- a/macros/latex/base/ltnews28.pdf
+++ b/macros/latex/base/ltnews28.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews28.tex b/macros/latex/base/ltnews28.tex
index 6a683c83af..59b01ed4fc 100644
--- a/macros/latex/base/ltnews28.tex
+++ b/macros/latex/base/ltnews28.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2017-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2017-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -353,7 +353,7 @@ between 2016 and 2018.
In: TUGboat, 38\#2, 2017.
\url{https://www.latex-project.org/publications/}
-\bibitem{amsldoc} American Mathematical Society and The \LaTeX3 Project:
+\bibitem{amsldoc} American Mathematical Society and The \LaTeX\ Project:
\emph{User's Guide for the \texttt{amsmath} package} (Version 2.1).
April 2018.
Available from
diff --git a/macros/latex/base/ltnews29.pdf b/macros/latex/base/ltnews29.pdf
index bfae9f4a80..10f239284e 100644
--- a/macros/latex/base/ltnews29.pdf
+++ b/macros/latex/base/ltnews29.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews29.tex b/macros/latex/base/ltnews29.tex
index c707c65342..a5732eada9 100644
--- a/macros/latex/base/ltnews29.tex
+++ b/macros/latex/base/ltnews29.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2018-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2018-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -513,7 +513,7 @@ source code (with index etc.\@) and a number of other goodies.
\emph{\LaTeX{} Project publications on the \LaTeX{} Project Website}.\\
\url{https://latex-project.org/publications/}
-\bibitem{29:amsldoc} American Mathematical Society and The \LaTeX3 Project:
+\bibitem{29:amsldoc} American Mathematical Society and The \LaTeX\ Project:
\emph{User's Guide for the \texttt{amsmath} Package} (Version 2.1).
April 2018.
Available from
diff --git a/macros/latex/base/ltnews30.pdf b/macros/latex/base/ltnews30.pdf
index 433d868639..d15360dd4d 100644
--- a/macros/latex/base/ltnews30.pdf
+++ b/macros/latex/base/ltnews30.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews30.tex b/macros/latex/base/ltnews30.tex
index d09e1fe2b0..cfb67b0c68 100644
--- a/macros/latex/base/ltnews30.tex
+++ b/macros/latex/base/ltnews30.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 2019
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews31.pdf b/macros/latex/base/ltnews31.pdf
index 7ef233d67f..6378f3e9ff 100644
--- a/macros/latex/base/ltnews31.pdf
+++ b/macros/latex/base/ltnews31.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews31.tex b/macros/latex/base/ltnews31.tex
index 1b775a532e..61e8b00683 100644
--- a/macros/latex/base/ltnews31.tex
+++ b/macros/latex/base/ltnews31.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 2019-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltnews32.pdf b/macros/latex/base/ltnews32.pdf
index 22b3c72894..6e7b951c9d 100644
--- a/macros/latex/base/ltnews32.pdf
+++ b/macros/latex/base/ltnews32.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews32.tex b/macros/latex/base/ltnews32.tex
index 85283a86a9..c56537a203 100644
--- a/macros/latex/base/ltnews32.tex
+++ b/macros/latex/base/ltnews32.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 2019-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -278,7 +278,7 @@ expressions (as used by the \cs{glueexpr} primitive although all uses
in \texttt{picture} mode are non-stretchy).
So, valid uses include \verb|\put(2,2)| as previously,
- but now also uses such as\tubcommand\\\verb|\put(\textwidth-5cm,0.4\textheight)|.
+ but now also uses such as\tubcommand\\ \verb|\put(\textwidth-5cm,0.4\textheight)|.
Note that you can only use expressions with lengths; \verb|\put(1+2,0)| is not
supported.
diff --git a/macros/latex/base/ltnews33.pdf b/macros/latex/base/ltnews33.pdf
new file mode 100644
index 0000000000..f087a6ffcd
--- /dev/null
+++ b/macros/latex/base/ltnews33.pdf
Binary files differ
diff --git a/macros/latex/base/ltnews33.tex b/macros/latex/base/ltnews33.tex
new file mode 100644
index 0000000000..899650c693
--- /dev/null
+++ b/macros/latex/base/ltnews33.tex
@@ -0,0 +1,942 @@
+% \iffalse meta-comment
+%
+% Copyright 2019-2021
+% 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
+% Filename: ltnews33.tex
+%
+% This is issue 33 of LaTeX News.
+
+\NeedsTeXFormat{LaTeX2e}[2020-02-02]
+
+\documentclass{ltnews}
+
+%%CCC Temporary definitions:
+\providecommand\Dash {\unskip ---}
+
+
+
+%% NOTE: Chris' preferred hyphens!
+%%\showhyphens{parameters}
+\hyphenation{because para-me-ters}
+
+\usepackage[T1]{fontenc}
+
+\usepackage{lmodern,url,hologo}
+
+\usepackage{csquotes}
+\usepackage{multicol}
+
+\providecommand\hook[1]{\texttt{#1}}
+
+\providecommand\meta[1]{$\langle$\textrm{\itshape#1}$\rangle$}
+\providecommand\option[1]{\texttt{#1}}
+\providecommand\env[1]{\texttt{#1}}
+\providecommand\Arg[1]{\texttt\{\meta{#1}\texttt\}}
+
+
+\providecommand\eTeX{\hologo{eTeX}}
+\providecommand\XeTeX{\hologo{XeTeX}}
+\providecommand\LuaTeX{\hologo{LuaTeX}}
+\providecommand\pdfTeX{\hologo{pdfTeX}}
+\providecommand\MiKTeX{\hologo{MiKTeX}}
+\providecommand\CTAN{\textsc{ctan}}
+\providecommand\TL{\TeX\,Live}
+\providecommand\githubissue[2][]{\ifhmode\unskip\fi
+ \quad\penalty500\strut\nobreak\hfill
+ \mbox{\small\slshape(%
+ \href{https://github.com/latex3/latex2e/issues/\getfirstgithubissue#2 \relax}%
+ {github issue#1 #2}%
+ )}%
+ \par\smallskip}
+
+% simple solution right now (just link to the first issue if there are more)
+\def\getfirstgithubissue#1 #2\relax{#1}
+
+\providecommand\sxissue[1]{\ifhmode\unskip\fi
+ \quad\penalty500\strut\nobreak\hfill
+ \mbox{\small\slshape(\url{https://tex.stackexchange.com/#1})}\par}
+
+\providecommand\gnatsissue[2]{\ifhmode\unskip\fi
+ \quad\penalty500\strut\nobreak\hfill
+ \mbox{\small\slshape(%
+ \href{https://www.latex-project.org/cgi-bin/ltxbugs2html?pr=#1\%2F\getfirstgithubissue#2 \relax}%
+ {gnats issue #1/#2}%
+ )}%
+ \par}
+
+\let\cls\pkg
+\providecommand\env[1]{\texttt{#1}}
+\providecommand\acro[1]{\textsc{#1}}
+
+\vbadness=1400 % accept slightly empty columns
+
+
+\makeatletter
+% maybe not the greatest design but normally we wouldn't have subsubsections
+\renewcommand{\subsubsection}{%
+ \@startsection {subsubsection}{2}{0pt}{1.5ex \@plus 1ex \@minus .2ex}%
+ {-1em}{\@subheadingfont\colonize}%
+}
+\newcommand\colonize[1]{#1:}
+\makeatother
+
+\let\finalvspace\vspace % for document layout fixes
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\providecommand\tubcommand[1]{}
+\tubcommand{\input{tubltmac}}
+
+\publicationmonth{June}
+\publicationyear{2021} %% --- Draft Version 3p
+
+\publicationissue{33}
+
+\begin{document}
+
+\tubcommand{\addtolength\textheight{4.2pc}} % only for TUB
+
+\maketitle
+{\hyphenpenalty=10000 \spaceskip=3.33pt \hbadness=10000 \tableofcontents}
+
+\setlength\rightskip{0pt plus 3em}
+
+
+\medskip
+
+
+\section{Introduction}
+
+The focus of the June 2021 release is to provide further important
+building blocks for the future production of
+reliable tagged PDF output
+(see \cite{33:blueprint}); these enhancements
+are discussed in the next two
+sections.
+
+Subsequent sections describe quite a number of recent smaller
+enhancements and fixes. As usual, more detail on individual changes
+can be found in the \texttt{changes.txt} files in the distribution
+and, of course, in the documented sources~\cite{33:source2e}.
+
+
+
+\section{Extending the hook concept to paragraphs}
+
+Largely triggered by the need for better control of paragraph text
+processing, in particular when producing tagged PDF output, we have
+changed \LaTeX{} so that the kernel gains control both at the start
+and at the end of each paragraph. This is done in a manner that is (or
+should be) transparent to both packages and documents.
+
+Besides the addition of internal control points for the exclusive use
+of the \LaTeX{} kernel, we also implemented four public hooks that can
+be used in packages or documents (via the normal hook management
+declarations) to achieve special effects, etc. Until now, such
+enhancements required redefinitions of \cs{everypar} or \cs{par},
+which led to the usual issues since such changes can easily conflict
+with changes made by other packages.
+
+The documentation of these new \enquote{paragraph hooks}, together
+with a few examples, is in \file{ltpara-doc.pdf} and, for those who
+want to study it, the (quite interesting) code can be found in
+\file{ltpara-code.pdf}. Additionally, both of these files are included
+as part of the full kernel documentation in \file{source2e.pdf}.
+
+
+
+\section{Extending the hook concept to commands}
+
+Up to now, hook management covered hooks for only a few core areas,
+such as the hooks for the \cs{shipout} process or those in the
+\env{document} environment, as well as some \enquote {generic} hooks,
+both for file loading (helpful for patching such files) and for
+arbitrary environments (the hooks executed within \cs{begin} and
+\cs{end}). This concept of \enquote{generic hooks} has now been
+extended to provide \hook{/before} and \hook{/after} hooks for any
+(document-level) command\Dash in theory at least.
+
+
+In practice, these new generic \hook{cmd} hooks, especially the
+\hook{cmd/.../after}, hooks may fail with commands that are too
+complex to be automatically patched, breaking if the hook contains any
+code. These restrictions are documented in
+\texttt{ltcmdhooks-doc.pdf}.
+%
+However, given that these hooks are mainly meant for developers who
+wish to provide better interoperability between different packages,
+and between packages and the \LaTeX{} kernel, these restrictions are,
+we hope, of minor importance. Indeed, for commands where this
+mechanism can't be applied, one is in the same situation as before;
+and for all others there will be a noticeable improvement.
+
+These hooks will be especially important for our current project to
+provide accessible and tagged PDF output~\cite{33:blueprint} because
+we will eventually have to patch many third-party packages, and this
+must be done in controlled and standardized ways.
+
+
+
+
+\section{Other hook business}
+
+
+\subsection{Shipping out a page while bypassing hooks}
+
+In the 2020 October release, several hooks were added to control the
+process of constructing and shipping out a page box: these support,
+for example, the addition of background or foreground material
+to some or all pages.
+
+
+We have now added a command, called \cs{RawShipout}, which does not do
+any rebuilding of the page box and so does not run most of these
+hooks. When using this new command, essential internal book-keeping
+is still carried out, such as updating the \texttt{totalpages} counter
+and adding \texttt{shipout/firstpage} or \texttt{shipout/lastpage}
+material when appropriate.
+
+
+\subsection{A new Lua callback in \pkg{ltshipout},
+for custom attributes}
+
+For use just before shipping out a page, there is now a \LuaTeX{}
+callback \texttt{pre\_shipout\_filter} to contain final adjustments to
+the box being shipped out. This is particularly useful for
+Lua\TeX\ packages which flag (using, for example, attributes or
+properties) elements on a page in order to apply effects (such as the
+insertion of \enquote{color commands}) to these elements at shipout.
+
+
+
+\section{Improved handling of file names}
+
+\subsection[File names with spaces, multiple dots or\\
+ \acro{utf-8} characters]
+ {File names with spaces, multiple dots or \acro{utf-8} characters}
+
+In one of the recent \LaTeX{} releases we improved the interface
+for specifying file names so that they can now safely contain spaces
+(as is common these days),
+more than one dot character, and also \acro{utf-8} characters
+outside the \acro{ascii} range.
+In the past this was only possible by applying a special syntax
+in the case of spaces,
+while file names with several dots often failed,
+as did most \acro{utf-8} characters.
+
+
+\subsubsection{Consequences for file names in \cs{include}}
+
+\TeX{} has a built-in rule saying that you can normally leave out the
+extension if it is \texttt{.tex}. Thus \verb=\input{file}= and
+\verb=\input{file.tex}= both load \file{file.tex} (if it exists).
+While this is convenient most of the time, it is a little awkward in
+some scenarios (for example, when both \file{file} and \file{file.tex}
+exist) and also when you manually try to implement the rule.
+
+\LaTeX{} therefore had one special syntax for \cs{include} and
+\cs{includeonly}: they always expected that
+their arguments contain a
+file name\footnote{In the case of \cs{includeonly}, a comma-separated list of such names.}
+with no extension given,
+ so that it had to be \texttt{.tex}. Thus,
+ when you mistakenly wrote
+\verb=\include{mychap.tex}= (for example,
+because you changed from \cs{input}
+to \cs{include}),
+\LaTeX{} went ahead and looked for the
+file \file{mychap.tex.tex} for inclusion and tried to
+use the file \file{mychap.tex.aux} for internal (auxiliary) information. The reason was that
+\cs{include} had to construct both
+of these file names from the given
+argument and it didn't bother to do
+anything special
+with the supplied
+extension \texttt{.tex}.
+
+With the new implementation this has
+changed:
+the extension \texttt{.tex}
+now gets removed/ignored if it was
+supplied.
+Thus \verb=\include{mychap.tex}= now
+no longer looks for \file{mychap.tex.tex}
+but loads
+\file{mychap.tex}
+and uses \file{mychap.aux}.
+%
+\githubissue{486}
+
+
+
+\subsection{Normalization of robust commands in file names}
+
+The handling of file names has been modified so that \verb|\string| is
+applied to normalize robust commands within the file name.
+Previously, for example, \verb|\input{\sqrt{2}}| would cause
+\LaTeX\ to loop indefinitely whereas with
+the new normalization
+it looks for the file named \verb|sqrt {2}.tex|
+(and therefore very likely reports ``file not found'').
+%
+\githubissue{481}
+
+
+
+
+\subsection{Fix for \env{filecontents} with \acro{utf-8}
+ chars in the file name}
+
+Since a few releases back, the \env{filecontents} environment has
+allowed \acro{utf-8} characters in the file name. There was, however,
+a bug that would not allow \emph{over}writing a file with \acro{utf-8}
+characters in its name. This has been fixed and now
+\env{filecontents} allows any characters in the file name.
+%
+\githubissue{415}
+
+
+
+\section{Updates to the font selection scheme}
+
+
+\subsection{A new hook in \cs{selectfont}}
+
+After \cs{selectfont} has changed the font, we now run a hook (\hook{selectfont})
+so that packages can make final \mbox{adjustments}. This functionality was
+originally provided by the \pkg{everysel} package but our
+implementation is slightly different and uses the standard hook
+management.
+%
+\githubissue{444}
+
+
+\subsection{Change of font series/shape delayed until \cs{selectfont}}
+
+With the NFSS extensions introduced in 2020, the font series and shape
+settings can be influenced by changes to the font family. The
+settings of these two are now therefore delayed until \cs{selectfont}
+is executed; this avoids unnecessary or incorrect substitutions that
+may otherwise happen due to the order of declarations.
+%
+\githubissue{444}
+
+
+
+\section{Glyphs, characters \& encodings}
+
+\subsection{Improved copy\,\&\,paste for \pdfTeX{} documents}
+
+When compiling with \pdfTeX{}, additional information
+(from the file \texttt{glyphtounicode.tex}) is now added automatically
+to the PDF file in order to improve copying from, and searching in,
+text.
+
+In particular, this allows the most common ligatures to be copied as
+intended from all generated PDF files without the need to explicitly
+load the package \pkg{cmap}.
+%
+\githubissue{465}
+
+
+
+
+
+\subsection{Support for more Unicode characters}
+
+
+\LaTeX\ is quite capable of typesetting characters such as
+\enquote{\d{m}}, but until now it could not access some Unicode
+characters from the Latin Extended Additional block. This meant that,
+for example, there were no Unicode mappings for some characters that
+are used to write Sanskrit words in Latin transliteration (as seen in
+books about yoga, Buddhist philosophy, etc.).
+%
+These characters have now been added so that they can be entered
+directly instead of using \verb=\d{m}=, etc.
+%
+\githubissue{484}
+
+
+
+
+
+\subsection{More ``dashes'' in encodings \texttt{OT1},
+ \texttt{T1} and \texttt{TU}}
+
+When pasting in text from external sources, one can encounter these
+three Unicode characters
+%
+\texttt{"2011} (non-breaking hyphen),
+\texttt{"2012} (figure dash) and
+\texttt{"2015} (horizontal bar),
+%
+in addition to the more common
+%
+\texttt{"2013} (en-dash) and \texttt{"2014} (em-dash).
+%
+In the past, these first three produced an error message when used
+with \pdfTeX{} (since they are not available in \texttt{OT1} or
+\texttt{T1} encoded fonts). They now typeset an approximation to the
+glyph: e.g., the ``figure dash'' is approximated by an en-dash.
+
+With Unicode engines they either work (when the glyph is contained in
+the selected Unicode font) or they typeset nothing, producing a
+``Missing character'' warning in the log file.
+
+With all engines these characters can also now be accessed using the
+command names \cs{textnonbreakinghyphen}, \cs{textfiguredash} and
+\cs{texthorizontalbar}, respectively.
+%
+\githubissue{404}
+
+
+\subsection{Poor man's \cs{textasteriskcentered}}
+
+The \cs{textasteriskcentered} symbol, used as part of the set of
+footnote symbols in \LaTeX{}, is assumed to be implemented by every
+font with the \texttt{TS1} encoding (when \pdfTeX{} is used) or with
+the \texttt{TU} encoding for the Unicode engines. That assumption is
+unfortunately not correct for all fonts since, for example, the
+\texttt{stix2} fonts don't provide this glyph. A result is that one
+gets missing glyph messages when using \cs{thanks}, etc.
+
+Therefore \cs{textasteriskcentered} now checks whether there is such a
+glyph and, if not, uses a normal \enquote{*}, but slightly enlarged
+and lowered. This may not be perfect in all cases, but it is
+certainly better than no glyph showing up.
+%
+\githubissue{502}
+
+\subsection {The characters from \pkg{textcomp} are in the kernel}
+
+A couple of releases back, the functionality of the \pkg{textcomp}
+package was integrated into the \LaTeX{} kernel. Thus it is no longer
+necessary to load this package in order to access glyphs such as
+\cs{textcopyright}, \cs{texteuro} or \cs{textyen}.
+
+
+At this time the opportunity was also taken to bring some order to the
+chaos surrounding the question: \enquote{which glyphs from the
+ \texttt{TS1} encoding are available in a given font?}. This was
+done using an approach based on font families and collections, with
+the differing glyph coverage of the \enquote*{text symbols} being
+indicated by assigning to a font family or collection a ``sub-encoding
+number'' that indicates which glyphs from the \texttt{TS1} encoding are
+guaranteed to be available when using a font from that family or
+collection. This assignment ensures that \LaTeX{} always errs on the
+side of caution, possibly claiming that a glyph is not available even
+when it in fact is.
+
+\iffalse %%FMi but drop that
+
+The documented code for this can be found now in the file
+\file{lttextcomp.dtx} but we hope to publish a full explanation of
+the approach very soon now.
+
+\fi %% FMi potential drop
+
+
+
+\subsubsection
+ [A note on the history of ``text symbols'']
+ {A note on the history of ``text symbols'' and
+ the \texttt{TS1} encoding}
+
+
+The \enquote{text symbol encoding} (\texttt{TS1}) was originally
+designed at the Cork Conference as a companion to the \texttt{T1}
+encoding. In it various symbols that are not subject to hyphenation
+got assembled and the \pkg{textcomp} package was developed to make
+them accessible. Unfortunately the \TeX{} community was a bit too
+enthusiastic and included several symbols only available in a few
+\TeX{} fonts and some, such as the capital accents, not available at
+all but developed as part of the reference font implementation.
+
+In hindsight that was a very bad idea because it meant that other
+existing fonts (at the time) and later new fonts that got developed
+were unable to provide the full set of glyphs that made up the
+\texttt{TS1} encoding. For existing free PostScript fonts people
+took the extra effort and produced virtual fonts that faked (some) of
+the missing glyphs. But this was and is a time-consuming effort so it
+was done for only a few basic fonts. But even then, only some fonts
+included all glyphs from \texttt{TS1} so the \pkg{textcomp} already
+back then contained a long list, dividing fonts into 5 categories
+according to which glyphs were implemented and which were missing.
+
+
+When we recently integrated the functionality of the \pkg{textcomp}
+into the \LaTeX{} kernel
+many new free fonts had appeared and
+unfortunately the chaos around the question \enquote{which glyphs of
+ the \texttt{TS1} encoding are implemented by which font} had
+increased with it. Not only did one find many new holes, it was next to
+impossible to order the set of fonts into a reasonable set of
+sub-encodings that are contained in each other in a single sequence.
+
+In the end we decided on nine or ten sub-encodings with a reasonable
+number of fonts in each so that all fonts implemented all glyphs of the
+sub-encoding they got mapped to. Thus when typesetting with a font one
+could be sure that a command like \cs{textcopyleft} would either
+typeset the requested character (if the glyph was part of the
+sub-encoding the font belonged to) or it would raise an error, saying
+that the glyph is unavailable in that font. The mapping would ensure
+that \LaTeX{} always errs on the side of caution, because it might
+claim a glyph is unavailable even though in fact it is.\looseness-1
+
+For example, the old \texttt{pcr} (PostScript Courier) font (as well
+as most other older PS fonts) is mapped to sub-encoding 5 and
+therefore claims that \cs{textasciigrave} is unavailable even though
+in fact for Courier this is not true. If one uses such a font and this
+becomes an issue then there are a couple (suboptimal) possibilities.
+For one, one can alter the mapping of Courier and pretend that belongs
+to a fuller sub-encoding, e.g.
+\begin{verbatim}
+ \DeclareEncodingSubset{TS1}{pcr}{2}
+\end{verbatim}
+The downside is, that \LaTeX{} then believes other glyphs that are in fact
+unavailable are also there, so that it is important to check that the
+final document doesn't have some missing glyphs.
+
+An alternative is to pretend that \cs{textasciigrave} can always be
+taken from the \texttt{TS1} encoding (no questions asked):
+\begin{verbatim}
+ \DeclareTextSymbolDefault{\textasciigrave}{TS1}
+\end{verbatim}
+Again there is a danger that this is not true when it is used with a
+different font and would then generate a missing glyph.
+
+Finally, and possibly the best solution, if not impossible for other
+reasons, is to simply use a different font, for example, to use the
+\TeX{} Gyre Cursor font (a reimplementation of Courier with a
+much more complete glyph set).
+
+
+
+
+\section{New or improved commands}
+
+\subsection{Adjusting \env{itemize} labels with \cs{labelitemfont}}
+
+The command \cs{labelitemfont} was introduced already with the
+\LaTeX\ release 2020-02-02, but back then we forgot to describe it, so
+we do this now. Its purpose is to resolve some bad formatting issues
+with the \env{itemize} environment and also to make it easier to
+adjust the layout when necessary. What could happen in the past was
+that the \env{itemize} labels (e.g., the \textbullet{}) would
+sometimes react to surrounding font changes and could then suddenly
+change shape, for example to \textit{\textbullet}.
+
+This new command \cs{labelitemfont}, which defaults to \cs{normalfont},
+can be used to provide additional control in the typesetting of
+each label. Thus by choosing
+different settings other effects can be achieved. Here are two
+examples:
+\begin{verbatim}
+ \renewcommand\labelitemfont
+ {\normalfont\fontfamily{lmss}\selectfont}
+ \renewcommand\labelitemfont
+ {\rmfamily\normalshape}
+\end{verbatim}
+The first definition will take the symbols from the font Latin Modern
+Sans, so that you get
+%
+\def\myfont#1{{\let\labelitemfont\empty\fontfamily{lmss}\selectfont#1}}%
+%
+\myfont\labelitemi, \myfont\labelitemii, \myfont\labelitemiii\ and
+\!\!\myfont\labelitemiv\,; while the second variant freezes the font family
+and shape, but leaves the series as a variable quantity, so that an
+\env{itemize} in a bold context would show bolder symbols. Making
+\cs{labelitemfont} empty would give you back the buggy old behavior.
+%
+\githubissue{497}
+
+
+\subsection{Producing several marks for one footnote}
+
+It is sometimes necessary to reference the same footnote several
+times: i.e., to produce several footnote marks using the same number
+or symbol. This is now easily possible by placing a \cs{label} within
+the referenced \cs{footnote} and referencing this label by using the
+new command \cs{footref}. This means that footnote marks can be
+generated to refer to arbitrary footnotes (including those in
+\texttt{minipage}s).
+
+This \cs{footref} command has previously been available, but only when
+using certain classes or the \pkg{footmisc} package.
+%
+\githubissue{482}
+
+
+\subsection{Allow \cs{nocite} in the preamble}
+
+A natural place for \verb=\nocite{*}= would be the preamble of the
+document, but for historical reasons \LaTeX{} issued an error message
+if it was placed there. This command is now allowed in the preamble.
+%
+\githubissue{424}
+
+
+\subsection{Made \cs{\textbackslash} generally robust}
+
+In 2018 most \LaTeX{} user-level commands were made robust, including
+the \cs{\textbackslash} command. However, \cs{\textbackslash} gets
+redefined in various environments and not all these cases were caught:
+such as, in particular, its use as the row delimiter in \env{tabular}
+structures. This has been corrected so that \cs{\textbackslash}
+should now be robust in all circumstances.
+
+
+This change also fixed one anomaly present in the past:
+in a tabular preamble of the form
+\finalvspace*{-.3\baselineskip}
+\begin{quote}
+ \hspace*{-.15em}\verb={l=\texttt{\string>}\verb={raggedright}p{10cm}r}= % stupid class
+\end{quote}
+\finalvspace*{-.3\baselineskip}
+a \cs{\textbackslash} in the second column would have the definition
+used within \cs{raggedright} and so it would not indicate the
+(premature) end of the \env{tabular}. Thus, for example,%
+\finalvspace*{-.3\baselineskip}
+\begin{quote}
+ \verb=a & b1 \\ b2 & c \\=
+\end{quote}
+\finalvspace*{-.3\baselineskip}
+was interpreted as a single row of the \env{tabular} (as intended),
+whereas
+\finalvspace*{-.3\baselineskip}
+\begin{quote}
+ \verb=a & \\ b2 & c \\=
+\end{quote}
+\finalvspace*{-.3\baselineskip}
+resulted in two rows! This happened because the \cs{\textbackslash}
+directly following the \verb=&= got interpreted while it still had the
+\enquote{end the row} meaning and not yet the \enquote{start a new
+ line within the second column} meaning.
+
+With \cs{\textbackslash} now being robust, the special scanning mode
+initiated by the \verb=&= ends immediately when this command is seen:
+the second column is therefore then started, which results in the
+\cs{\textbackslash} being interpreted as being within that column and
+hence as having its expected, within-column, meaning.
+
+We have restored consistency here: now both of the above lines
+produce a single \env{tabular} row.
+%
+As before, you can
+put \cs{raggedright}\cs{arraybackslash} in the \env{tabular}'s
+preamble for a column to ensure that \cs{\textbackslash} is always
+interpreted as a tabular row separator when used in that column. And
+you can use \cs{tabularnewline} to explicitly ask for a new table row,
+even when \cs{\textbackslash} has a different meaning within the
+current column.
+%
+\githubissue{548}
+
+
+
+
+\subsection{Allow extra space between name and address in \pkg{letter} class}
+
+The \cs{opening} command in the \pkg{letter} class expects the name
+and address to be separated by \verb=\\=, but it didn't allow the use
+of an optional argument to add some extra space after the name. The
+code has now been slightly altered to allow this.
+%
+\githubissue{427}
+
+
+
+\subsection{Additions to \cs{tracingall}}
+
+In July 2020 David Jones suggested an extension to \TeX{} engines,
+that added the possibility to set \cs{tracinglostchars}\texttt{=3} in
+order to generate an error message in case some character is missing
+from a font. In previous years, a warning about a missing character
+was silently printed to the \texttt{.log} file\linebreak
+(if $\cs{tracinglostchars}>0$) and to the terminal\linebreak
+ (if ${}>1$). This extension was added for \TL{} and \MiKTeX{}
+(except in Knuth's \TeX, of course),
+so that with $\cs{tracinglostchars}>2$ you now also get an
+error message for each missing glyph.
+
+Later, in January 2021, Petr Olšák suggested yet another extension:
+a new primitive
+\mbox{parameter}
+%
+\cs{tracingstacklevels} that, when both it and \cs{tracingmacros} are
+positive, will add to the \mbox{tracing} information for each
+macro a visual indication (using dots) of
+its nesting level in the macro expansion stack.
+
+These changes have both now been added to \LaTeX's debugging macros
+\cs{tracingall} and \cs{tracingnone}, so that these two new extensions
+are activated/deactivated as appropriate, so long as the \TeX{} engine
+supports them. An example document demonstrating these parameters is
+in the linked GitHub issue.
+%
+\githubissue{524}
+
+
+
+
+\section{Code improvements}
+
+\subsection{Execute \cs{par} at the end of \cs{marginpar}}
+
+Previously, \LaTeX{} ended a \cs{marginpar} without ever explicitly
+calling \cs{par}. This command is now explicitly added because it is
+essential to the correct working of the paragraph hooks.
+
+Another case where this issue caused problems was the \pkg{lineno}
+package, where the last line was not numbered if the \cs{marginpar}
+ended without an explicit \cs{par}.
+%
+\githubissue{489}
+
+
+
+\subsection{Execute \cs{AtEndDocument} hook in vertical mode}
+
+Until now \verb=\end{document}= executed the code from the
+\cs{AtEndDocument} hook as its first action. This meant that this
+hook was executed in horizontal mode if the user left no empty line
+after the last paragraph. As a result, one could get a spurious space
+added when, for example, that code contained a \cs{write}
+statement. This was fixed and now \cs{enddocument} first issues a
+\cs{par} to ensure that it always goes into vertical mode.
+%
+\githubissue{385}
+
+
+\subsection{Color groups made permanent}
+
+The use of color in certain \LaTeX{} constructs, especially boxes,
+needs an extra layer of grouping to ensure that the color setting does
+not \emph{escape} and continue outside the box when it shouldn't.
+%
+To support this, the \LaTeX{} kernel defines a number of commands,
+e.g., \cs{color@begingroup} to be used in such places.
+
+
+Until now, these commands were initially set as no-ops and only the
+color packages redefined them to become real groups; this methodology
+complicates the coding as one has to account for a group being present
+or not (\mbox{depending} on what is loaded in the document).
+%
+The kernel therefore now permanently adds these \enquote{color groups}.
+%
+\githubissue{488}
+
+
+\subsection{Provide the raw option list to key/value option handlers}
+
+Before any further processing of the option list, the original
+(un-normalized, \enquote{raw} and unchanged) list of package or class
+options is now saved, as \cs{@raw@opt@...}; this list is not used by
+the standard option processing code but it is now available for use by
+extended class/package processing systems. Note that, for
+compatibility reasons, the standard option processing code has not
+been changed.
+
+
+
+One
+aspect of this
+change does affect the standard \mbox{processing}: any tokens to the
+right of an \texttt{=}
+sign are \mbox{removed}
+from consideration
+when constructing
+the \enquote{\mbox{unused} option list}.
+For example, in
+this release \texttt{clip=true} and
+\texttt{clip=false} both contribute \texttt{clip} to the list of
+options that have been used.
+%
+\githubissue{85}
+
+
+\subsection{New for \pkg{latexrelease}\,: \cs{NewModuleRelease}}
+
+To explain the need for this new feature, we shall consider the
+following example: in the 2020-10-01 release, \LaTeX's new hook
+management system was added to the kernel (see \cite{33:ltnews32})
+and, as with all changes to the kernel, it was added to
+\pkg{latexrelease}; this made it possible to roll back to a date where
+this module didn't yet exist, or to roll forward from an older
+\LaTeX{} release to get the hook management system (by loading the
+\pkg{latexrelease} package).
+%
+However, this method of rolling back from a later release to the
+2020-10-01 release didn't quite work because it would try to define
+all the commands from \pkg{lthooks} again; and this would of course
+result in the expected errors from commands defined with
+\cs{newcommand} or (as in \pkg{lthooks}) \cs{cs\_new:Npn}.
+
+To solve such issues, we now provide \cs{NewModuleRelease} so that
+completely new modules can be defined using the facilities of
+\pkg{latexrelease} in such a way that, when rolling back or forward,
+the system will know whether the code of the new module has to be read
+or completely ignored. More details on this can be found in the
+\pkg{latexrelease} documentation (get this with
+\verb|texdoc latexrelease|).
+%
+\githubissue{479}
+
+
+\subsection{Small fix for rolling back prior to 2020-02-02}
+
+Whereas the \pkg{latexrelease} package can usually emulate an older
+\LaTeX{} kernel without much problem, rolling back to before the
+2020-02-02 release didn't work properly: this is because the
+management of the \cs{ExplSyntaxOn/Off} status for packages (after an
+\pkg{expl3}-based package is loaded) cannot be removed by the rollback
+without messing up the catcodes. This has been fixed so that rollback
+is now more careful not to leave \cs{ExplSyntaxOn} after a package
+ends.
+%
+\githubissue{504}
+
+
+
+\section{Changes to packages in the \pkg{graphics} category}
+
+
+\subsection{Removed warning when loading graphics files}
+
+A previous release sometimes mistakenly caused a (false) warning
+message to appear when \mbox{using} a generic graphics rule to find
+and load a graphics file with an unknown \mbox{extension}.
+%%CCC removing hyphenation here makes this one line longer.
+This warning would incorrectly say that the file was not found,
+whereas the file would in fact be correctly loaded. The warning now
+doesn't show up in that case.
+%
+\githubissue{516}
+
+
+\subsection{Fixed loading of \texttt{gzip}ped
+ PostScript files}
+
+A previous release mistakenly changed the file searching mechanism so
+that compressed PostScript graphics files would raise an error when
+being loaded with \cs{includegraphics}. This has been fixed so that
+\texttt{gzip}ped graphics files now load correctly.
+%
+\githubissue{519}
+
+
+
+
+\section{Changes to packages in the \pkg{tools} category}
+
+\subsection{\pkg{layout}: Added language options}
+
+This package now recognizes \texttt{japanese} and \texttt{romanian} as
+language options.
+%
+\githubissue[s]{353 and 529}
+
+
+\subsection{\pkg{array} and \pkg{longtable}: Make \cs{\textbackslash} generally robust}
+
+The fix for this issue was also applied to these packages; see above.
+%
+\githubissue{548}
+
+
+\subsection{\pkg{longtable}: General bug fix update}
+
+This is a minor update to the \pkg{longtable} package that fixes several
+reported bugs: notably the possibility of incorrect page breaks when
+floats appear on the page where a \env{longtable} starts. As this may
+affect page breaking in existing documents, a rollback to
+\pkg{longtable 4.13} (\file{longtable-2020-01-07.sty}) is supported.
+%
+\gnatsissue{tools}{2914 3396 3512}
+\githubissue{133 137 183 464 561}
+
+
+\subsection{\pkg{trace}: Additions to \cs{traceon}}
+
+The \cs{tracingstacklevels} and \cs{tracinglostchars} extensions to
+\cs{tracingall} (see above) were also added to \cs{traceon} in the
+\pkg{trace} package, so its users can also benefit from these new
+debugging possibilities.
+%
+\githubissue{524}
+
+
+\subsection{\pkg{bm}: Better support for commands with optional arguments}
+
+Some uses of optional arguments in \cs{bm} stopped being supported (in
+2004) when \cs{kernel@ifnextchar} was used internally by the format
+instead of \cs{@ifnextchar}. This update handles both versions of this
+command and restores the original \mbox{behavior}.
+
+In addition, package options for guiding the use of \enquote{poor
+ man's bold} in fallback situations were added.
+%
+\githubissue{554}
+
+
+
+\section{Changes to packages in the \pkg{amsmath} category}
+
+The fix for issue 548 was also applied in \pkg{amsmath}; see above.
+%
+\githubissue{548}
+
+
+
+
+\medskip
+
+\begin{thebibliography}{9}
+
+\fontsize{9.3}{11.3}\selectfont
+
+\bibitem{33:blueprint} Frank Mittelbach and Chris Rowley:
+ \emph{\LaTeX{} Tagged PDF \Dash A blueprint for a large project}.\\
+ \url{https://latex-project.org/publications/indexbyyear/2020/}
+
+\bibitem{33:source2e}
+ \emph{\LaTeX{} documentation on the \LaTeX{} Project Website}.\\
+ \url{https://latex-project.org/help/documentation/}
+
+\bibitem{33:ltnews32} \LaTeX{} Project Team:
+ \emph{\LaTeXe{} news 32}.\\
+ \url{https://latex-project.org/news/latex2e-news/ltnews32.pdf}
+
+\end{thebibliography}
+
+
+
+\end{document}
diff --git a/macros/latex/base/ltoutenc.dtx b/macros/latex/base/ltoutenc.dtx
index c6bfc149b7..eb2ecd1e53 100644
--- a/macros/latex/base/ltoutenc.dtx
+++ b/macros/latex/base/ltoutenc.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -37,14 +37,14 @@
%<TS1>\ProvidesFile{ts1enc.def}[2001/06/05 v3.0e (jk/car/fm)
%<TU>\ProvidesFile{tuenc.def}
%<package>\ProvidesPackage{fontenc}
-%<OT1|T1|OMS|OML|OT4|TU|package> [2020/08/10 v2.0s
+%<OT1|T1|OMS|OML|OT4|TU|package> [2021/04/29 v2.0v
%<OT1|T1|OMS|OML|OT4|TS1|TU> Standard LaTeX file]
%<package> Standard LaTeX package]
%
%<*driver>
% \fi
\ProvidesFile{ltoutenc.dtx}
- [2020/08/10 v2.0s LaTeX Kernel (font encodings)]
+ [2021/04/29 v2.0v LaTeX Kernel (font encodings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltoutenc.dtx}
@@ -421,7 +421,7 @@
% for |\textdollar| in \texttt{OT1} is a hack since \$ and \pounds{}
% actually share the same slot in this encoding. Thus if such a glyph
% becomes available in a different encoding (e.g., \texttt{TS1}) one
-% would like to get rid of the flacky one and make the default
+% would like to get rid of the flaky one and make the default
% definition point to the new encoding. In such a case defining
%\begin{verbatim}
% \DeclareTextSymbol{\textdollar}{TS1}{36}
@@ -841,7 +841,7 @@
% 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
-% disable that part of the code temporaily.
+% 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.
% \changes{v2.0m}{2019/12/18}{Avoid code that breaks \cs{accent}}
@@ -1717,6 +1717,17 @@
\DeclareTextSymbol{\textemdash}{OT1}{124}
\DeclareTextSymbol{\textendash}{OT1}{123}
% \end{macrocode}
+%
+% The \verb=\nobreak\hskip\z@= is there to prevent a break after
+% the hyphen but allow later breaks in the remainder of the word.
+% \changes{v2.0u}{2021/02/19}{Add \cs{textnonbreakinghyphen}, \cs{textfiguredash}
+% and \cs{texthorizontalbar} (gh/404)}
+% \begin{macrocode}
+\DeclareTextCommand{\textnonbreakinghyphen}{OT1}{\mbox{-}\nobreak\hskip\z@}
+\DeclareTextCommand{\textfiguredash} {OT1}{\textendash}
+\DeclareTextCommand{\texthorizontalbar} {OT1}{\textemdash}
+% \end{macrocode}
+%
% Using the ligatures helps with OT1 fonts that have
% |\textexclamdown| and |\textquestiondown| in unusual positions.
% \changes{v1.95}{2002/06/17}{Definition of \cs{textexclamdown} changed (pr/3368)}
@@ -2045,6 +2056,19 @@
\DeclareTextSymbol{\textdollar}{T1}{`\$}
\DeclareTextSymbol{\textemdash}{T1}{22}
\DeclareTextSymbol{\textendash}{T1}{21}
+% \end{macrocode}
+%
+% The \verb=\nobreak\hskip\z@= is there to prevent a break after
+% the hyphen but allow later breaks in the remainder of the word.
+% \changes{v2.0u}{2021/02/19}{Add \cs{textnonbreakinghyphen}, \cs{textfiguredash}
+% and \cs{texthorizontalbar} (gh/404)}
+% \begin{macrocode}
+\DeclareTextCommand{\textnonbreakinghyphen}{T1}{\mbox{-}\nobreak\hskip\z@}
+\DeclareTextCommand{\textfiguredash} {T1}{\textendash}
+\DeclareTextCommand{\texthorizontalbar} {T1}{\textemdash}
+% \end{macrocode}
+%
+% \begin{macrocode}
\DeclareTextSymbol{\textexclamdown}{T1}{189}
\DeclareTextSymbol{\textgreater}{T1}{`\>}
%\DeclareTextSymbol{\texthyphenchar}{T1}{127}
@@ -2538,7 +2562,7 @@
%
% The tie accent was borrowed from the |cmmi| font. The tc fonts
% now provide four tie accents, the first two are done in the
-% classical way with assymetric glyphs hanging out of their boxes;
+% classical way with asymmetric glyphs hanging out of their boxes;
% the new ties are centered in their boxes like all other accents.
% They need a name: please tell us if you know what to call them.
%
@@ -2550,7 +2574,7 @@
\DeclareTextAccent{\capitalnewtie}{TS1}{29}
% \end{macrocode}
%
-% Compund word marks.
+% Compound word marks.
%
% The text companion fonts contain two compound word marks of
% different heights, one has |cap_height|, the other |asc_height|.
@@ -2583,8 +2607,31 @@
\DeclareTextSymbol{\textquotesingle}{TS1}{39}
% \end{macrocode}
% "28 = 40
-% \begin{macrocode}
-\DeclareTextSymbol{\textasteriskcentered}{TS1}{42}
+%
+% The symbol \cs{textasteriskcentered} ``\textasteriskcentered'' is
+% supposed to be always available in \texttt{TS1} and that is
+% important as it is used in footnote symbols. However, in a few
+% fonts it is missing even though they are otherwise fairly
+% complete. We therefore use a rather elaborate method and check if
+% the slot has a glyph and if not produce a poor man's version by
+% using a normal ``*'' slightly enlarged and somewhat lowered.
+% The main application for this symbol is in footnote symbols and
+% there it should produce a comparable size and show a similar placement.
+% \changes{v2.0t}{2021/02/17}{Special definition for
+% \cs{textasteriskcentered} when missing in TS1 (gh/502)}
+% \begin{macrocode}
+%\DeclareTextSymbol{\textasteriskcentered}{TS1}{42} % that's wanted
+\DeclareTextCommand \textasteriskcentered{TS1}{% % and that's needed
+ \iffontchar\font 42 \char42 \else
+ \begingroup\fontencoding{T1}%
+ \fontsize
+ {\the\dimexpr1.3\dimexpr\f@size pt\relax}%
+ {\f@baselineskip}%
+ \selectfont
+ \raisebox{-0.7ex}[\dimexpr\height-0.7ex][0pt]{*}%
+ \endgroup
+ \fi
+}
% \end{macrocode}
% Note that '054 is a comma and '056 is a full stop: these make
% numbers using oldstyle digits easier to input.
@@ -2837,7 +2884,7 @@
%<*TU>
% \end{macrocode}
% In the base interface the Unicode encoding is always known as TU
-% But we parameterise the encoding name to allow for modelling
+% But we parameterize the encoding name to allow for modelling
% differences in Unicode support by different fonts.
% \begin{macrocode}
\providecommand\UnicodeEncodingName{TU}
@@ -3106,8 +3153,34 @@
\DeclareTextSymbol{\textbaht} \UnicodeEncodingName{"0E3F}
\DeclareTextSymbol{\SS} \UnicodeEncodingName{"1E9E}
\DeclareTextSymbol{\textcompwordmark} \UnicodeEncodingName{"200C}
+% \end{macrocode}
+%
+% \changes{v2.0u}{2021/02/19}{Add \cs{textnonbreakinghyphen}, \cs{textfiguredash}
+% and \cs{texthorizontalbar} (gh/404)}
+% \begin{macrocode}
+%\DeclareTextSymbol{\textnonbreakinghyphen} \UnicodeEncodingName{"2011}
+%\DeclareTextSymbol{\textfiguredash} \UnicodeEncodingName{"2012}
\DeclareTextSymbol{\textendash} \UnicodeEncodingName{"2013}
\DeclareTextSymbol{\textemdash} \UnicodeEncodingName{"2014}
+%\DeclareTextSymbol{\texthorizontalbar} \UnicodeEncodingName{"2015}
+% \end{macrocode}
+% Unfortunately some fonts do not implement \texttt{"2011}, \texttt{"2012} and/or
+% \texttt{"2015} (including the \LaTeX{} default fonts for Unicode
+% engines) so we provide some approximations if the glyph is
+% missing, like we do for \texttt{OT1} and \texttt{T1}.
+%
+% The \verb=\nobreak\hskip\z@= is there to prevent a break after
+% the hyphen but allow later breaks in the remainder of the word.
+% \begin{macrocode}
+\DeclareTextCommand{\textnonbreakinghyphen} \UnicodeEncodingName
+ {\iffontchar\font "2011 \char "2011 \else \mbox{-}\nobreak\hskip\z@ \fi}
+\DeclareTextCommand{\textfiguredash} \UnicodeEncodingName
+ {\iffontchar\font "2012 \char "2012 \else \char "2013 \fi}
+\DeclareTextCommand{\texthorizontalbar} \UnicodeEncodingName
+ {\iffontchar\font "2015 \char "2015 \else \char "2014 \fi}
+% \end{macrocode}
+%
+% \begin{macrocode}
\DeclareTextSymbol{\textbardbl} \UnicodeEncodingName{"2016}
\DeclareTextSymbol{\textquoteleft} \UnicodeEncodingName{"2018}
\DeclareTextSymbol{\textquoteright} \UnicodeEncodingName{"2019}
@@ -3159,15 +3232,17 @@
% \end{macrocode}
%
% Not all fonts have U+2217 but using U+002A requires some adjustment.
+% \changes{v2.0t}{2021/02/17}{Adjust values for
+% \cs{textasteriskcentered} To match TS1 definition (gh/502)}
% \begin{macrocode}
\DeclareTextCommand{\textasteriskcentered}\UnicodeEncodingName{%
\iffontchar\font"2217 \char"2217 \else
\begingroup
\fontsize
- {\the\dimexpr1.2\dimexpr\f@size pt\relax}%
+ {\the\dimexpr1.3\dimexpr\f@size pt\relax}%
{\f@baselineskip}%
\selectfont
- \raisebox{-0.6ex}[\dimexpr\height-0.6ex][0pt]{*}%
+ \raisebox{-0.7ex}[\dimexpr\height-0.7ex][0pt]{*}%
\endgroup
\fi
}
@@ -3393,8 +3468,19 @@
\DeclareUnicodeComposite{\v} {o}{"01D2}
\DeclareUnicodeComposite{\v} {U}{"01D3}
\DeclareUnicodeComposite{\v} {u}{"01D4}
+% \end{macrocode}
+%
+% \changes{v2.0v}{2021/04/29}{Add composites for
+% \texttt{\protect\string\ae/\protect\string\AE/\ae/\AE} (gh/552)}
+% \begin{macrocode}
+\DeclareUnicodeComposite{\'} \AE{"01FC}
+\DeclareUnicodeComposite{\'} {Æ}{"01FC}
+\DeclareUnicodeComposite{\'} \ae{"01FD}
+\DeclareUnicodeComposite{\'} {æ}{"01FD}
\DeclareUnicodeComposite{\=} \AE{"01E2}
+\DeclareUnicodeComposite{\=} {Æ}{"01E2}
\DeclareUnicodeComposite{\=} \ae{"01E3}
+\DeclareUnicodeComposite{\=} {æ}{"01E3}
\DeclareUnicodeComposite{\v} {G}{"01E6}
\DeclareUnicodeComposite{\v} {g}{"01E7}
\DeclareUnicodeComposite{\v} {K}{"01E8}
diff --git a/macros/latex/base/ltoutenc.ins b/macros/latex/base/ltoutenc.ins
index 17d62e11e8..1330b5c44e 100644
--- a/macros/latex/base/ltoutenc.ins
+++ b/macros/latex/base/ltoutenc.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/ltoutput.dtx b/macros/latex/base/ltoutput.dtx
index 35d049b959..b1b3a24096 100644
--- a/macros/latex/base/ltoutput.dtx
+++ b/macros/latex/base/ltoutput.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -37,7 +37,7 @@
%<*driver>
% \fi
\ProvidesFile{ltoutput.dtx}
- [2020/08/21 v1.4f LaTeX Kernel (Output Routine)]
+ [2021/05/05 v1.4g LaTeX Kernel (Output Routine)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltoutput.dtx}
@@ -57,7 +57,7 @@
% \iffalse
% LATEX VERSION 2e
% Copyright (C) 1992 by Leslie Lamport
-% Copyright (C) 1994-2000 by Leslie Lamport, LaTeX3 project
+% Copyright (C) 1994-2000 by Leslie Lamport, LaTeX Project
%
% LaTeX 2e kernel file for the output routine.
%
@@ -1134,7 +1134,7 @@
\global \advance \@colht \@tempdima
\ifx \@dbltoplist \@empty
\else
- \@latexerr{Float(s) lost}\@ehb
+ \@latex@error{Float(s) lost}\@ehb
\let \@dbltoplist \@empty
\fi
\@cons \@dbltoplist \@currbox
@@ -1525,7 +1525,7 @@
\global \@colroom \@colht
\ifx \@currlist\@empty
\else
- \@latexerr{Float(s) lost}\@ehb
+ \@latex@error{Float(s) lost}\@ehb
\global \let \@currlist \@empty
\fi
\@makefcolumn\@deferlist
@@ -1676,7 +1676,7 @@
% \begin{macro}{\@makecol}
% \changes{v0.1c}{1993/11/23}{Command changed}
% \changes{v1.0b}{1993/11/29}{\cs{@makespecialcolbox} added}
-% We must rewrite this macro to alllow for variations in page-makeup
+% We must rewrite this macro to allow for variations in page-makeup
% required by changes in page-length.
%
% This uses a different macro if a special-length column is being
@@ -1860,7 +1860,7 @@
% force the shortest possible column with the possibility of an
% overfull box.
%
-% This should work for bothe flush- and ragged-bottom setting since
+% This should work for both flush- and ragged-bottom setting since
% it makes the contents no smaller than the size (|\@colht|) of the
% box into which they are put.
%
@@ -2074,7 +2074,7 @@
% \end{macrocode}
%
% The |\catcode`\ = 10| was removed as it was considered useless
-% (presumably because nothing gets tokenised during shipout).
+% (presumably because nothing gets tokenized during shipout).
%
% This was put in as some error produced active spaces in a mark, I
% think.
@@ -2156,7 +2156,7 @@
%
% The rest was always inside the box.
%
-% RmS 91/08/15: aded this line:
+% RmS 91/08/15: added this line:
% \begin{macrocode}
\reset@font
% \end{macrocode}
@@ -3864,7 +3864,7 @@
% be printed in as small a space as possible, ie it uses any
% shrinkability in the column. If the column was not explicitly broken
% (\eg with |\pagebreak|) this may result in an overfull box message but
-% execpt for this it will come out as expected (if you know what to
+% except for this it will come out as expected (if you know what to
% expect).
%
% The star form of this command is dedicated to Leslie Lamport, the
@@ -3920,9 +3920,9 @@
%</trace>
\@tempskipa#2\relax
\ifdim \@tempskipa>.5\maxdimen
- \@latexerr{Suggested\space extra\space height\space
- (\the\@tempskipa)\space dangerously\space
- large}\@eha
+ \@latex@error{Suggested\space extra\space height\space
+ (\the\@tempskipa)\space dangerously\space
+ large}\@eha
\else
\ifdim \vsize<.5\maxdimen
%<*trace>
@@ -3940,8 +3940,8 @@
\fi
%</trace>
\else
- \@latexerr{Page\space height\space already\space
- too\space large}\@eha
+ \@latex@error{Page\space height\space already\space
+ too\space large}\@eha
\fi
\fi
}
@@ -3973,7 +3973,7 @@
% It also enables the use of an extra specifier, {\tt !}, in the
% location optional argument of a float. If this is present then,
% just for this particular float, whenever it is processed by the float
-% mechanism the followinhg are ignored:
+% mechanism the following are ignored:
%
% \begin{itemize}
% \item all restrictions on the number of floats which can appear;
@@ -4556,7 +4556,7 @@
% Yet another is to move the column count register from the multicol
% package into the kernel. This has been done.
% \item Where should the reinserts be put to maximise the
-% probability that footmotes come out on the correct page?
+% probability that footnotes come out on the correct page?
% Or should we go for as much compatibility as possible (but see
% next item)?
% \item Should we continue to support (as much as possible)
@@ -4980,7 +4980,7 @@
%
% At the top of the page |\@fptop| is inserted;
% typically this supplies some stretchable whitespace.
-% At the bottom of the page |\@fpbot| ais inserted.
+% At the bottom of the page |\@fpbot| is inserted.
% Between adjacent floats |\@fpsep| is inserted.
%
% These parameters are used for all floating objects on a
diff --git a/macros/latex/base/ltpage.dtx b/macros/latex/base/ltpage.dtx
index 8c7aac0a7b..4504033f54 100644
--- a/macros/latex/base/ltpage.dtx
+++ b/macros/latex/base/ltpage.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltpage.dtx}
- [2020/07/27 v1.0m LaTeX Kernel (page style setup)]
+ [2020/12/05 v1.0m LaTeX Kernel (page style setup)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltpage.dtx}
@@ -260,7 +260,7 @@
% the problem is solved.}
% \changes{v1.0j}{2000/05/26}{Use \cs{@empty} instead of brace group
% (pr/3203).}
-% \task{???}{mark initialisation solved?}
+% \task{???}{mark initialization solved?}
% \begin{macrocode}
\def\@markright#1#2#3{\@temptokena {#1}%
\unrestored@protected@xdef\@themark{{\the\@temptokena}{#3}}}
diff --git a/macros/latex/base/ltpageno.dtx b/macros/latex/base/ltpageno.dtx
index 6374f58b89..03d36a53d9 100644
--- a/macros/latex/base/ltpageno.dtx
+++ b/macros/latex/base/ltpageno.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltpageno.dtx}
- [1994/05/19 v1.1a LaTeX Kernel (Page Numbering)]
+ [2020/12/05 v1.1a LaTeX Kernel (Page Numbering)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltpageno.dtx}
@@ -71,7 +71,7 @@
% assigned by |\newcount|.
%
% \DescribeMacro{\pagenumbering}
-% The user sets the pagenumber style with the |\pagenumbering|\marg{foo}
+% The user sets the page number style with the |\pagenumbering|\marg{foo}
% command, which sets the page counter to 1 and defines |\thepage| to be
% |\foo|. For example, |\pagenumbering{roman}| causes pages to be
% numbered i, ii, etc.
diff --git a/macros/latex/base/ltpar.dtx b/macros/latex/base/ltpar.dtx
index ed1b439e9d..969954be0a 100644
--- a/macros/latex/base/ltpar.dtx
+++ b/macros/latex/base/ltpar.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltpar.dtx}
- [1995/04/29 v1.1c LaTeX Kernel (paragraphs)]
+ [2021/04/13 v1.1c LaTeX Kernel (paragraphs)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltpar.dtx}
@@ -67,9 +67,11 @@
% |\par| and |\everypar| when ever their function needs to be
% changed for a long time.
%
-% \StopEventually{}
-%
-% \subsection{Implementation}
+% This file here describes the interfaces that have been in the kernel
+% forever, used to implement the scenarios described below. They
+% remain valid but are now augmented in the next file
+% (\texttt{ltpara.dtx}) to add hooks to paragraphs. At some point we
+% will consolidate the two files further.
%
%
% There are two situations in which |\par| may be changed:
@@ -93,6 +95,12 @@
% \end{itemize}
% \end{itemize}
%
+%
+% \StopEventually{}
+%
+% \subsection{Implementation}
+%
+%
% \DescribeMacro{\@setpar}
% To permit the proper interaction of these two situations, long-term
% changes are made by the |\@setpar{|\meta{VAL}|}| command.
diff --git a/macros/latex/base/ltpara-code.pdf b/macros/latex/base/ltpara-code.pdf
new file mode 100644
index 0000000000..5e12893ec3
--- /dev/null
+++ b/macros/latex/base/ltpara-code.pdf
Binary files differ
diff --git a/macros/latex/base/ltpara-code.tex b/macros/latex/base/ltpara-code.tex
new file mode 100644
index 0000000000..2e5beda31c
--- /dev/null
+++ b/macros/latex/base/ltpara-code.tex
@@ -0,0 +1,4 @@
+% this will typeset documentation + code
+
+\AtBeginDocument{\AlsoImplementation}
+\input{ltpara.dtx}
diff --git a/macros/latex/base/ltpara-doc.pdf b/macros/latex/base/ltpara-doc.pdf
new file mode 100644
index 0000000000..75dae10c7d
--- /dev/null
+++ b/macros/latex/base/ltpara-doc.pdf
Binary files differ
diff --git a/macros/latex/base/ltpara-doc.tex b/macros/latex/base/ltpara-doc.tex
new file mode 100644
index 0000000000..c3892b8180
--- /dev/null
+++ b/macros/latex/base/ltpara-doc.tex
@@ -0,0 +1,6 @@
+% this will typeset only documentation but not the code
+
+\AtBeginDocument{\OnlyDescription
+ \let\tableofcontents\relax
+ }
+\input{ltpara.dtx}
diff --git a/macros/latex/base/ltpara.dtx b/macros/latex/base/ltpara.dtx
new file mode 100644
index 0000000000..5ab52a5e9b
--- /dev/null
+++ b/macros/latex/base/ltpara.dtx
@@ -0,0 +1,1223 @@
+% \iffalse meta-comment
+%
+%% File: ltpara.dtx (C) Copyright 2020-2021
+% Frank Mittelbach, LaTeX Team
+%
+% 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
+%
+%
+%%% From File: ltpara.dtx
+%
+% \begin{macrocode}
+\def\ltparaversion{v1.0g}
+\def\ltparadate{2021/05/27}
+% \end{macrocode}
+%<*driver>
+\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}}}
+
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{ltpara.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+% \providecommand\hook[1]{\texttt{#1}}
+% \providecommand\env[1]{\texttt{#1}}
+%
+%
+%
+% \title{The \texttt{ltpara.dtx} code\thanks{This file has version
+% \ltparaversion\ dated \ltparadate, \copyright\ \LaTeX\
+% Project.}}
+% \author{Frank Mittelbach}
+%
+% \maketitle
+%
+%
+% \begin{abstract}
+% This code defines four special kernel hooks to support paragraph
+% tagging as well as four public hooks which can be occasionally
+% useful.
+% \end{abstract}
+%
+% \tableofcontents
+%
+%
+% \section{Introduction}
+%
+%
+% The building of paragraphs in the \TeX{} engine(s) has a number
+% of peculiarities that makes it on one hand fairly flexible but on
+% the other hand somewhat awkward to control or reliably to extend.
+% Thus to better understand the code below we start with a brief introduction
+% of the mechanism; for more details refer to the
+% \TeX{}book~\cite[chap.~14]{texbook} (for the full truth you may
+% even have to study the program code).
+%
+% \subsection{The default processing done by the engine}
+%
+% \TeX{} automatically starts building a paragraph when it is
+% currently in vertical mode and encounters anything that can only
+% live in horizontal mode. Most often this is a character, but
+% there are also many commands that can be used only in horizontal mode.
+% If any of them is encountered, \TeX{} will immediately back up
+% (i.e., the character or command is read later again), adds a
+% \cs{parskip} glue to the current vertical list unless the list is
+% empty, switches to
+% horizontal mode, starts its special \enquote{start of paragraph
+% processing} and only then rereads the character or command that
+% caused the mode change.\footnote{Already not quite true: the
+% command \cs{noindent} starts the paragraph but influences the
+% special processing by suppressing the paragraph indentation box
+% normally inserted by it.}
+%
+% This \enquote{start of paragraph
+% processing} first adds an empty box at the start of the
+% horizontal list of width \cs{parindent} (which represents the
+% paragraph indentation) unless the paragraph was started with
+% \cs{noindent} in which case no such box is
+% added\footnote{That's a bit different from placing a zero-sized
+% box!}. It then reads and processes all tokens stored in the
+% special engine token register \cs{everypar}. After that it reads
+% and processes whatever has caused the paragraph to start.
+%
+% Thus out of the box, \TeX{} offers the possibility to put some
+% special code into \cs{everypar} to gain control at (more or less)
+% the start of the paragraph. For example, in LaTeX{} and a number
+% of packages, special code like the following is sometimes used:
+%\begin{verbatim}
+% \everypar{{\setbox\z@\lastbox}\everypar{} ...}
+%\end{verbatim}
+% This removes the paragraph indentation box again (that was already
+% placed by \TeX), then resets \cs{everypar} so that it doesn't do
+% anything on the next paragraph start and then does whatever it
+% wants to do, e.g., in an \cs{item} of a list it will typeset the label in
+% front of the paragraph text.
+% However, there is only one such \cs{everypar} token register and
+% if different packages and/or the kernel all attempt to add their
+% own code here, coordination is very difficult if not impossible.
+%
+% The process when the paragraph ends has different mechanisms and interfaces.
+% A paragraph ends when the engine primitive \cs{par} is called
+% while \TeX{} is in unrestricted horizontal mode, i.e., is
+% building a paragraph. At other times this primitive does nothing
+% or generates as an error depending on the mode \TeX{} is in,
+% e.g., the \cs{par} in
+% \verb=\hbox{a\par b}= is ignored, but \verb=$a\par b$= would complain.
+%
+% If this primitive ends the paragraph it does some special
+% \enquote{end of horizontal list} processing, then calls \TeX{} paragraph
+% builder that breaks the horizontal list into lines then these
+% lines are added as boxes to the enclosing vertical list and
+% \TeX{} returns to vertical mode.
+%
+% This \cs{par} command can be given explicitly, but there are also
+% situations in which \TeX{} is generating it on the fly. Most
+% often this happens when \TeX\ encounters a blank line which is
+% automatically changed to a \cs{par} command which is then
+% executed. The other possibility is that \TeX{} encounters a
+% command which is incompatible with horizontal processing, e.g.,
+% \cs{vskip} (a request for adding vertical space). In such case it
+% silently backs up, and inserts a \cs{par} in the hope that this
+% gets it out of horizontal mode and makes the offending command
+% acceptable.
+
+% The important point to note here is that \TeX{} really inserts
+% the command \cs{par} which can be redefined. Thus, it may not have
+% its original \enquote{primitive} meaning and therefore may not end the
+% horizontal list and call the paragraph builder. This approach
+% offers some flexibility but also allows you to easily produce a
+% \TeX{} document that loops forever, for example, the simple line
+%\begin{verbatim}
+% A \let\par\relax \vskip
+%\end{verbatim}
+% will start a horizontal list at \texttt{A}, redefines \cs{par},
+% then sees \cs{vskip} and inserts \cs{par} to end the
+% paragraph. But this now only runs \cs{relax} so nothing changes
+% and \cs{vskip} is read again, issues a \cs{par} which \ldots. In
+% short, it takes a plain \TeX{} document with five tokens to run
+% forever (as not even memory is consumed and therefore eventually
+% exhausted).
+%
+% There are no other ways than changing \cs{par} to gain control at
+% the end of a paragraph, i.e., there is no token list like
+% \cs{everypar} that is inserted, i.e., the only way to change the
+% default behavior is to modify the action that \cs{par} executes
+% with similar issues as outlined before: different processes need
+% to ensure that they do not overwrite their modifications or
+% worse, think that the \cs{par} in front of them is the engine
+% primitive while in fact it has already been changed by other
+% code.
+%
+%
+% To make matters slightly worse there are a few places where
+% \TeX{} handles the situation differently (most likely for speed
+% reasons back when computers were much slower). If \TeX{} finds
+% itself in unrestricted horizontal mode at the end of building a
+% vertical box (or an \cs{insert}, \cs{vadjust} or at the end of
+% executing the output routine code), it will finish the horizontal
+% list not by issuing a \cs{par} command (which would be consistent
+% with all other places, but by simply executing the primitive version
+% of \cs{par} regardless of the definition that \cs{par} has at the
+% time.
+%
+% Thus, if you have carefully crafted a redefined \cs{par} to execute
+% some special actions at the end of a paragraph and you write
+% something like
+%\begin{verbatim}
+% \vbox{Some paragraph ... text.}
+%\end{verbatim}
+% you will find that your code has never run for the last paragraph
+% in that box. \LaTeX{} avoids this problem, by making sure that
+% all its boxes (such as \cs{parbox} or the \env{minipage}
+% environment, etc.) all internally add an explicit \cs{par} at the
+% end so that such code is run and \TeX{} finds itself in vertical
+% mode already without the need to start up the paragraph builder
+% internally. But, of course, this only works for boxes under direct
+% control of the \LaTeX{} kernel, if some package uses low-level
+% \cs{vbox}es without adding this precaution the \TeX{}
+% optimization kicks in and no special \cs{par} code is executed.
+%
+% And there is another optimization that is painful: if a paragraph
+% is interrupted by a mathematical display, e.g., \verb=\[...\]= in
+% \LaTeX{} or \verb=$$...$$= in plain \TeX{}, then \TeX{} will
+% resume horizontal mode afterward, i.e., build a new horizontal
+% list (without inserting an indentation box or \cs{everypar} at
+% that point). However, if that list immediately ends with an
+% explicit or implicit \cs{par} then \TeX{} will simply throw away
+% this \enquote{null} paragraph and not do its usual \enquote{end
+% of horizontal list} processing, so this special case need to be
+% accounted for when introducing some extended processing.
+%
+%
+%
+% \section{The new mechanism implemented for \LaTeX{}}
+%
+% To improve the situation (and also to support automatic tagging
+% of PDF documents) we now offer public as well as private hooks at
+% the start and end of the paragraph processing. The public hooks
+% can be used by packages (or by the user in the preamble or
+% within the document) and using the hook mechanisms it is possible
+% to reorder or arrange code from different packages in a way that
+% it can safely coexist.
+%
+% To make that happen we have to make use of the basic
+% functionality that is offered by \TeX{}, e.g., we install
+% special code inside \cs{everypar} to provide hooks at the
+% beginning and we redefine \cs{par} to do some special processing
+% when appropriate to install hooks at the end of the paragraph.
+%
+% In order to make this work, we have to ensure that package use of
+% \cs{everypar} is not overwriting our code. This is done through a
+% trick: we basically hide the real \cs{everypar} from the packages
+% and offer them a new token register (with the same name). So if
+% they install their own code it doesn't overwrite ours. Our code
+% then inserts the new \cs{everypar} at the right place inside the
+% process so that it looks as if it was the primitive
+% \cs{everypar}.\footnote{Ideally, \cs{everypar} wouldn't be used
+% at all by packages and instead they would simply write their code
+% into the hooks now offered by the kernel. However, while this is
+% the longterm goal and clearly an improvement (because then the
+% packages do no longer need to worry about getting their code
+% overwritten or needing to account for already existing code in
+% \cs{everypar}), this will not happen overnight. For that reason
+% support for this legacy method is retained.}
+%
+% At the end of the paragraph it would be great if we could use a
+% similar trick. However, due to the fact that \TeX{} inserts the
+% token \cs{par} (that doesn't have a defined meaning) we can't hide
+% \enquote{the real thing\textsuperscript{TM}} and offer the
+% package an indistinguishable alternate.
+%
+% Fortunately, \LaTeX{} has already redefined \cs{par} for its own
+% purposes. As a result there aren't many packages that attempt to
+% change \cs{par}, because without a lot of extra care that would
+% fail miserably. But bottom line, if you load a package that
+% alters \cs{par} then the end of paragraph hooks are most likely
+% not executing while that redefinition is
+% active.\footnote{Similarly to the \cs{everypar} situation, the
+% remedy is that such packages stop doing this and instead add
+% their alterations into the paragraph hooks now provided.}
+%
+%
+%
+% \subsection{The provided hooks}
+%
+%
+% \begin{variable}{para/before,
+% para/begin,
+% para/end,
+% para/after
+% }
+% The following four public hooks are defined and executed for
+% each paragraph:
+% \begin{description}
+%
+% \item[\hook{para/before}]
+%
+% This hook is executed after the kernel hook
+% \cs{@kernel@before@para@before} (discussed below) in vertical
+% mode immediately after \TeX{} has contributed \cs{parskip} to
+% the vertical list and before the actual paragraph processing in
+% horizontal mode starts.
+%
+% This hook should either not produce any typeset material or add
+% only vertical material. If it starts a paragraph an error is
+% generated. The reason is that we are in the starting process of
+% processing a paragraph and so this would lead to endless
+% recursion.\footnote{One could allow it but only if the newly
+% started paragraph is processed without any hooks. Furthermore
+% correct spacing would be a bit of a nightmare so for now this
+% is forbidden.}
+%
+% \end{description}
+% \end{variable}
+%
+% \vspace{-\bigskipamount}
+%
+% \begin{description}
+%
+% \item[\hook{para/begin}]
+%
+% This hook is executed after the kernel hook
+% \cs{@kernel@before@para@begin} (discussed below) in horizontal
+% mode immediately before the indentation box is placed (if there
+% is any, i.e., if the paragraph hasn't been started with
+% \cs{noindent}).
+%
+% The indentation box to be typeset is available to the hook as
+% \cs{IndentBox} and its automatic placement (after the hook is
+% executed) can be prevented through \cs{OmitIndent}.
+% More precisely \cs{OmitIndent} voids the box.
+%
+% The indentation box is then typeset directly
+% after the hook execution by something equivalent to
+% \cs{box}\cs{IndentBox} followed by the current content of
+% the token register \cs{everypar} that it is available to the
+% kernel or to packages (that run some legacy code).
+%
+% One has to be careful not to add any code to the hook that
+% starts its own paragraph (e.g., by adding a \cs{parbox} or a
+% \cs{marginpar} inside) because that would call the hook inside
+% again (as a new paragraph is started there) and thus lead to an
+% endless recursion ending only after exhausting the available
+% memory. This can only be done by making sure that is not
+% executed for the inner paragraphs (or at least not recursively
+% forever).
+%
+%
+% \item[\hook{para/end}]
+%
+% This hook is executed at the end of a paragraph when \TeX{} is
+% ready to return to vertical mode and after it has removed the
+% last horizontal glue (but not kern) placed on the horizontal
+% list. The code is still executed in horizontal mode so it is
+% possible to add further horizontal material at this point, but
+% it should not alter the mode (even a temporary exit from
+% horizontal mode would create chaos---any attempt will cause an
+% error message)! After the hook has ended the kernel hook
+% \cs{@kernel@after@para@end} is executed and then \TeX{} returns to
+% vertical mode.
+%
+% The hook is offered as public hook, but because of the
+% requirement to stay within horizontal mode one needs to be
+% careful in what is placed into the hook.\footnote{Maybe we
+% should guard against that, but it would be rather tricky to
+% implement as mode changes can happen across group boundaries so
+% one would need to keep a private stack just for that. Well,
+% something to ponder.}
+%
+% This hook is implemented as a reversed hook.
+%
+% \item[\hook{para/after}]
+%
+% This hook is executed directly after \TeX{} has returned to
+% vertical mode and after any material that migrated out of the
+% horizontal list (e.g., from a \cs{vadjust}) has processed.
+%
+% This hook should either not produce any typeset material or add
+% only vertical material.
+% However, for this hook starting a new paragraph is not a
+% disaster so that it isn't prevented.
+%
+% This hook is implemented as a reversed hook.
+%
+% Once that hook code has been processed the kernel hook
+% \cs{@kernel@after@para@after} is executed as the final action
+% of the paragraph processing.
+%
+% \end{description}
+%
+% \begin{variable}{\@kernel@before@para@before,
+% \@kernel@after@para@after,
+% \@kernel@before@para@begin,
+% \@kernel@after@para@end,
+% }
+% As already mentioned above there are also four kernel hooks that
+% are executed at the start and end of the processing.
+% \begin{description}
+%
+% \item[\cs{@kernel@before@para@before}]
+% For future extensions, not currently used by the kernel.
+%
+%
+% \item[\cs{@kernel@after@para@after}]
+% For future extensions, not currently used by the kernel.
+%
+%
+% \item[\cs{@kernel@before@para@begin}]
+%
+% Used by the kernel to implement tagging. This hook is executed
+% at the very beginning of a paragraph after \TeX{} has switched to
+% horizontal mode but before any indentation box got added or any
+% \cs{everypar} was run.
+%
+% It should not generate typeset material that could alter the
+% position. Note that it should never leave hmode, otherwise you
+% will end with a loop! We could guard against this, but since it
+% is an internal kernel hook that shouldn't be touched this isn't
+% checked.
+% \end{description}
+% \end{variable}
+%
+% \vspace{-\bigskipamount}
+%
+% \begin{description}
+%
+% \item[\cs{@kernel@after@para@end}]
+%
+% Used by the kernel to implement tagging. It is executed
+% directly after the public \hook{para/end} hook. After it there
+% is a quick check that we are still in horizontal mode, i.e.,
+% that the public hook has not mistakenly ended horizontal mode
+% prematurely (this is an incomplete check just testing the mode
+% and could perhaps be improved (at the cost of speed)).
+%
+% \end{description}
+%
+%
+% \subsection{Altered and newly provided commands}
+%
+% \begin{function}{\par,\endgraf,\para_end:}
+% An explicit request for ending a paragraph is known in plain
+% \TeX{} under the name \cs{endgraf} where it simply calls the
+% paragraph primitive (regardless of what \cs{par} may have as its
+% current definition). In \LaTeX{} \cs{endgraf} with that behavior
+% was also made available.
+%
+% With the new paragraph handling in \LaTeX{}, ending a paragraph
+% means a bit more than just calling the engine's paragraph
+% builder: the process also has to add any hook code for the end of
+% a paragraph. Thus
+% \cs{endgraf} was changed to provide this additional functionality
+% (and so by extension \cs{par} subject to its current meaning).
+%
+% The \pkg{expl3} name for the functionality is \cs{para_end:}.
+% \end{function}
+%
+% \begin{quote}
+% \textbf{Note:} \em The next two commands are still under
+% discussion and may slightly change their semantics (as described
+% in the document) and/or their names between now and the 2021
+% Spring release!
+% \end{quote}
+%
+% \begin{function}{\OmitIndent,\para_omit_indent:}
+% Inside the \hook{para/begin} hook one can use this command to
+% suppress the indentation box at the start of the
+% paragraph. (Technically it is possible to use this command
+% outside the hook as well, but this should not be relied upon.)
+% The box itself remains available for use.
+%
+% The \pkg{expl3} name for the function is \cs{para_omit_indent:}.
+% \end{function}
+%
+% \begin{variable}{\IndentBox,\g_para_indent_box}
+% The box register holding the indentation box for the paragraph is
+% available for inspection (or changes) inside hooks. It remains
+% available even if the \cs{OmitIndent} command was
+% used; in that case it will just not be automatically placed.
+%
+% The \pkg{expl3} name for the box register is \cs{g_para_indent_box}.
+% \end{variable}
+%
+%
+% \begin{function}{\RawIndent,\para_raw_indent:,
+% \RawNoindent,\para_raw_noindent:,
+% \RawParEnd,\para_raw_end:}
+% \begin{syntax}
+% \cs{RawIndent} \textit{hmode material} \cs{RawParEnd}
+% \cs{RawNoindent} \textit{hmode material} \cs{RawParEnd}
+% \end{syntax}
+%
+% The commands \cs{RawIndent} and \cs{RawNoindent} are not meant
+% for normal paragraph building (where the result is a textual
+% paragraph in the the traditional meaning of the word), but for
+% special cases where \TeX{}'s low-level algorithm is used to
+% achieve special effects, but where the result is not a
+% \enquote{paragraph}.
+%
+% They are called \enquote{raw}, because they bypass \LaTeX{}'s
+% hook mechanism for paragraphs and simply invoke the low-level
+% \TeX{} algorithm. I.e., they are like the original \TeX{}
+% primitives \cs{indent} and \cs{noindent} (that is they execute no
+% hooks other than \cs{everypar}) except that they can only be used
+% in vertical mode and generate an error if found elsewhere.
+%
+% To avoid issues a paragraph started by them should always be
+% ended by \cs{RawParEnd}\footnote{Technical note for those who
+% know their \textit{\TeX book\/}: the \cs{RawParEnd} comand
+% invokes the original \TeX{} engine definition of \cs{par} that
+% (soley) triggers the paragraph builder in \TeX{} when found
+% inside unrestricted horizontal mode and does nothing in other
+% processing modes.}
+% and not by \cs{par} (or a blank line), because the latter will execute
+% hooks which then have no counterpart at the beginning of the
+% paragraph. It is the responsibility of the programmer to make
+% sure that they are properly paired. This also means that one
+% should not put arbitrary user content between these commands if
+% that content could contain stray \cs{par}s.
+%
+% The \pkg{expl3} names for the functions are
+% \cs{para_raw_indent:}, \cs{para_raw_indent:} and
+% \cs{para_raw_end:}.
+% \end{function}
+%
+%
+%
+% \subsection{Examples}
+%
+% None of the examples in this section are meant for real use as
+% they are far too simpleminded but they should give some ideas of
+% what could be possible if a bit more care is applied.
+%
+% \subsubsection{Testing the mechanism}
+%
+% The idea is to output for each paragraph encountered some
+% information: a paragraph sequence number, a level number in roman
+% numerals, the environment in which this paragraph appears, and
+% the line number where the start or end of the paragraph is, e.g.,
+% something like
+%\begin{verbatim}
+% PARA: 1-i start (document env. on input line 38)
+% PARA: 1-i end (document env. on input line 38)
+% PARA: 2-i start (document env. on input line 40)
+% PARA: 3-ii start (minipage env. on input line 40)
+% PARA: 3-ii end (minipage env. on input line 40)
+% PARA: 2-i end (document env. on input line 41)
+%\end{verbatim}
+% As you can see paragraph 2 starts on line 40 and ends on 41 and
+% inside a minipage started paragraph 3 (start and end on line 40).
+% If you run this on some document you will find that \LaTeX{}
+% considers more things \enquote{a paragraph} than you have
+% probably thought.
+%
+% This was generated by the following hook code:
+%\begin{verbatim}
+% \newcounter{paracnt} % sequence counter
+% \newcounter{paralevel} % level counter
+%\end{verbatim}
+%
+% To support paragraph nesting we need to maintain a stack of the
+% sequence numbers. This is most easily done using \pkg{expl3}
+% functions, so we switch over. This is not a very general
+% implementation, just enough for what we need and a bit of
+% \LaTeXe{} thrown in as well. When popping the result gets stored
+% in \cs{paracntvalue} and the \cs{ERROR} should never happen
+% because it means we have tried to pop from an empty stack.
+%\begin{verbatim}
+% \ExplSyntaxOn
+% \seq_new:N \g_para_seq
+% \cs_new:Npn \ParaPush
+% {\seq_gpush:No \g_para_seq {\the\value{paracnt}}}
+% \cs_new:Npn \ParaPop {\seq_gpop:NNF \g_para_seq \paracntvalue \ERROR }
+% \ExplSyntaxOff
+%\end{verbatim}
+% At the start of the paragraph increment both sequence counter and
+% level and also save the then current sequence number on our stack.
+%\begin{verbatim}
+% \AddToHook{para/begin}{%
+% \stepcounter{paracnt}\stepcounter{paralevel}%
+% \ParaPush
+%\end{verbatim}
+% To display the sequence number we \cs{typeout} the current
+% sequence and level number. The command \cs{@currenvir} gives us
+% the current environment and \cs{on@line} produces a space and
+% the current input line number.
+%\begin{verbatim}
+% \typeout{PARA: \arabic{paracnt}-\roman{paralevel} start
+% (\@currenvir\space env.\on@line)}%
+%\end{verbatim}
+% We also typeset the sequence number as a tiny red number in a box
+% that takes up no horizontal space. This helps us seeing where
+% \LaTeX{} sees the start and end of the paragraphs in the
+% document.
+%\begin{verbatim}
+% \llap{\color{red}\tiny\arabic{paracnt}\ }%
+% }
+%\end{verbatim}
+%
+% At the end of the paragraph we display sequence number and
+% level again. The level counter has the correct value but we need
+% to retrieve the right sequence value by popping it off the stack
+% after which it is available in \cs{paracntvalue} the way we have
+% set this up above.
+%\begin{verbatim}
+% \AddToHook{para/end}{%
+% \ParaPop
+% \typeout{PARA: \paracntvalue-\roman{paralevel} end \space\space
+% (\@currenvir\space env.\on@line)}%
+%\end{verbatim}
+% We also typeset again a tiny red number with that value, this
+% time sticking out to the right.\footnote{Note that this can alter
+% the document pagination, because a paragraph ending in a display
+% (e.g., an equation) will get an extra line---in that case our tiny number
+% has an effect even though it doesn't take up any space, because
+% it paragraph is no longer empty and thus isn't dropped!}
+% We also decrement the level counter since our level has finished.
+%\begin{verbatim}
+% \rlap{\color{red}\tiny\ \paracntvalue}%
+% \addtocounter{paralevel}{-1}%
+% }
+% \makeatother
+%\end{verbatim}
+%
+%
+%
+% \subsubsection{Mark the first paragraph of each \env{itemize}}
+%
+% The code for this is rather simple. We apply hook code that is
+% executed only once inside a hook that is executed at the begin of
+% each \env{itemize}. We explicitly change the color back and
+% forth so that we don't introduce grouping around the paragraph.
+%\begin{verbatim}
+% \AddToHook{env/itemize/begin}{%
+% \AddToHookNext{para/begin}{\color{blue}}%
+% \AddToHookNext{para/end}{\color{black}}%
+% }
+%\end{verbatim}
+% As a result the first paragraph of each \env{itemize} will appear
+% in blue.
+%
+%
+%
+% \subsection{Some technical notes}
+%
+% The code tries hard to be transparent for package code, but of
+% course any change means that there is a potential for breaking
+% other code. So in section we collect a few cases that may be of
+% importance if low-level code is dealing with paragraphs that are
+% now behaving slightly differently. The notes are from issues we
+% observed and will probably grow over time.
+%
+% \subsubsection{Glue items between paragraphs (found with \pkg{fancypar})}
+%
+% In the past \LaTeX{} placed two glue items between two
+% consecutive paragraph, e.g.,
+%\begin{verbatim}
+% text1 \par text2 \par
+%\end{verbatim}
+% would show something like
+%\begin{verbatim}
+% \glue(\parskip) 0.0 plus 1.0
+% \glue(\baselineskip) 5.16669
+%\end{verbatim}
+% but now there is anothe \cs{parskip} glue (that is always 0pt):
+%\begin{verbatim}
+% \glue(\parskip) 0.0 plus 1.0
+% \glue(\parskip) 0.0
+% \glue(\baselineskip) 5.16669
+%\end{verbatim}
+% The reason is that we generate a \enquote{fake}'' paragraph to
+% gain control and safely add the early hooks, but this generates
+% an additional glue item. That item doesn't contribute anything
+% vertically but ifsomebody writes code the unravels a constructed
+% list using \cs{lastbox}, \cs{unskip} and \cs{unpenalty} then the
+% code has to remove one additional glue item or else will fail.
+
+%
+% ^^A \subsubsection{}
+%
+%
+%
+% ^^A \subsubsection{}
+%
+%
+%
+%
+%
+%
+% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
+%
+%
+% \section{The Implementation}
+%
+% \begin{macrocode}
+%<@@=para>
+% \end{macrocode}
+%
+% \changes{v1.0g}{2021/05/24}{Use \cs{msg_...} instead of \cs{__kernel_msg...}}
+%
+%
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+\ExplSyntaxOn
+%<latexrelease>\NewModuleRelease{2021/06/01}{ltpara}
+%<latexrelease> {Paragraph~handling~and~hooks}
+% \end{macrocode}
+%
+%
+%
+% \subsection{Providing hooks for paragraphs}
+%
+%
+% \begin{macro}{para/before,para/after,para/begin,para/end}
+% The public hooks. They are implemented as a paired set of hooks.
+% \begin{macrocode}
+\hook_new_pair:nn{para/before}{para/after}
+\hook_new_pair:nn{para/begin}{para/end}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@kernel@before@para@before,
+% \@kernel@after@para@after,
+% \@kernel@before@para@begin,
+% \@kernel@after@para@end}
+% The corresponding kernel hooks (for tagging and future extensions).
+% \begin{macrocode}
+\let \@kernel@before@para@before \@empty
+\let \@kernel@before@para@begin \@empty
+\let \@kernel@after@para@end \@empty
+\let \@kernel@after@para@after \@empty
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+% \begin{macro}{\g_@@_standard_everypar_tl}
+% Whenever \TeX{} starts a paragraph it inserts first an
+% indentation box and then executes the tokens stored in
+% \cs{tex_everypar:D} (known to \LaTeX{} as \cs{everypar}). We
+% alter this behavior slightly here, so that hooks are added
+% into the right place. Otherwise the process change remains
+% transparent to any legacy code for this space.
+%
+% We keep the standard code to be used by \cs{tex_everypar:D} in a
+% separate token list because we have to switch back and forth
+% for error recovery and so altering \cs{tex_everypar:D} all the
+% time should be a tiny bit faster.
+% \begin{macrocode}
+\tl_new:N \g_@@_standard_everypar_tl
+% \end{macrocode}
+% Here is now its definition:
+% \begin{macrocode}
+\tl_gset:Nn \g_@@_standard_everypar_tl {
+% \end{macrocode}
+% First we remove the indentation box and store it in
+% \cs{g_para_indent_box}. If there was none because the paragraph
+% was started by \cs{noindent} the box register will be void.
+% \begin{macrocode}
+ \box_gset_to_last:N \g_para_indent_box
+% \end{macrocode}
+%
+% This will make the newly started horizontal list empty, so if we
+% stop it now and return to vertical mode it will be dropped by
+% \TeX{}. We do that but inside a group so that any \cs{parshape}
+% settings will not get lost as we need them for later.
+% \begin{macrocode}
+ \group_begin:
+ \tex_par:D
+ \group_end:
+% \end{macrocode}
+% We then change \cs{tex_everypar:D} to generate an error so that
+% we can detect and report if the \hook{para/before} hook illegally
+% changed out of vmode.
+% \begin{macrocode}
+ \tex_everypar:D { \msg_error:nnnn { hooks }{ para-mode }{before}{vertical} }
+ \@kernel@before@para@before
+ \hook_use:n {para/before}
+% \end{macrocode}
+% Assuming the hooks have been well behaved it is time to return to
+% horizontal mode and start the paragraph in earnest. We already
+% have the indentation box saved away so we now have to restart the
+% paragraph with an empty \cs{tex_everypar:D} and with
+% \cs{tex_noindent:D}. And we need to make sure not to get another
+% \cs{parskip} or rather (since we can't prevent that) that it is
+% of zero size.
+% \begin{macrocode}
+ \group_begin:
+ \tex_everypar:D {}
+ \skip_zero:N \tex_parskip:D
+ \tex_noindent:D
+ \group_end:
+% \end{macrocode}
+% That brings us back to the start of the horizontal list but we
+% need to change \cs{tex_everypar:D} back to its normal content in
+% case there are nested paragraphs coming up.
+% \begin{macrocode}
+ \tex_everypar:D{\g_@@_standard_everypar_tl}
+% \end{macrocode}
+%
+% This is followed by executing the kernel and the public hook. The
+% kernel hook is there to enable tagging.
+% \begin{macrocode}
+ \@kernel@before@para@begin
+ \hook_use:n {para/begin}
+% \end{macrocode}
+% If we aren't in horizontal mode any longer the hooks above misbehaved.
+% \begin{macrocode}
+ \if_mode_horizontal: \else:
+ \msg_error:nnnn { hooks }{ para-mode }{begin}{vertical} \fi:
+% \end{macrocode}
+% Finally we reinsert the indentation box (unless suppressed) and
+% then call \cs{everypar} the way legacy \LaTeX\ code expects it.
+%
+% However, adding the public \cs{everypar} is a bit tricky (see below) so
+% we add that later, and indirectly.
+% \begin{macrocode}
+ \@@_handle_indent:
+% \the \everypar % <--- done differently below
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\tex_everypar:D}
+% \cs{tex_everypar:D} then only has to execute
+% \cs{g_@@_standard_everypar_tl} by default.
+% \begin{macrocode}
+\tex_everypar:D{\g_@@_standard_everypar_tl}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}[int]{\everypar}
+%
+% Tokens inserted at the beginning of the paragraph are placed into
+% \cs{everypar} inside legacy \LaTeX{} code, e.g., by the list
+% environments or by headings to handle \cs{clubpenalty}, etc. Now
+% this isn't any longer the primitive but simply a toks register
+% used in the code above but to legacy \LaTeX{} code that is
+% transparent.
+%
+% There is, however, a problem: a handful packages use exactly the
+% same trick and replace the primitive with a token register and
+% call the token register inside the renamed primitive. That is
+% they assume that \cs{everypar} is the primitive and that it will
+% still be called at the start of the paragraph even if renamed.
+%
+% But if we have already replaced it by a token register then all
+% they do is to give that token register a new name. Thus our code
+% in \cs{tex_everypar:D} would call \cs{everypar} (which is their
+% now token register) and the code that they added ends up in our
+% token register which is then never used at all. A bit mind
+% boggling I guess.
+%
+% So what we have to do is not to call the token register
+% \cs{everypar} by its name inside \cs{tex_everypar:D} but by using
+% its actual register number.
+% \begin{macrocode}
+\newtoks \everypar
+% \end{macrocode}
+%
+% After we have allocated a new toks register with the name
+% \cs{everypar} the actual register number is available (briefly)
+% inside \cs{allocationnumber}. So instead of \cs{the}\cs{everypar}
+% we have to put \cs{the}\cs{toks}\meta{allocated number} at the end of
+% \cs{tex_everypar:D}.
+%
+% So what remains doing is to append a few tokens to the token list
+% \cs{g_@@_standard_everypar_tl} which we do now. We use \texttt{x}
+% expansion here to get the value of \cs{allocationnumber} in, all
+% the other tokens should not be expanded at this point.
+
+% One important point here is to terminate the register allocation
+% number with a real space. This space will get swallowed up when
+% the number is read. Anything else, such as \cs{scan_stop:} would
+% remain in the input and that would mean that it would interfere
+% with \cs{everypar} code that attempts to scan ahead to see how
+% the paragraph text starts.
+% \begin{macrocode}
+\tl_gput_right:Nx \g_@@_standard_everypar_tl {
+ \exp_not:N \the
+ \exp_not:N \toks
+ \the \allocationnumber
+ \c_space_tl
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\g_para_indent_box}
+% For managing the indentation we need to provide a public
+% accessible box register
+% \begin{macrocode}
+\box_new:N \g_para_indent_box
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\@@_handle_indent:}
+% Adding (typesetting) the indent box is straight forward.
+% If it was emptied before it does nothing.
+% \begin{macrocode}
+\cs_new:Npn \@@_handle_indent: {
+ \box_use_drop:N \g_para_indent_box
+}
+% \end{macrocode}
+% The declaration \cs{para_omit_indent:} (or
+% \cs{OmitIndent}) changes that to do nothing.
+% \begin{macrocode}
+\cs_new:Npn \para_omit_indent: {
+ \box_gclear:N \g_para_indent_box
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\IndentBox,\OmitIndent}
+% The \LaTeXe{} names for the indentation box and for suppressing it
+% for use in the \hook{para/begin} hook.
+% \begin{macrocode}
+\cs_set_eq:NN \IndentBox \g_para_indent_box
+\cs_set_eq:NN \OmitIndent \para_omit_indent:
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+%
+% \begin{macro}{\para_end:}
+% Adding hooks to the end of a paragraph is similar but here we
+% need to alter the command that is used by \TeX{} to end horizontal
+% mode and return to vertical mode, i.e., \cs{par}.
+%
+% This is a bit more complicated as this command can appear anywhere
+% either explicitly or implicitly added by \TeX{} in certain
+% situations:
+% \begin{itemize}
+% \item
+% when using \cs{par} in the code or the document
+% \item
+% when using a blank line (which is converted to \cs{par})
+% \item
+% when \TeX{} finds any commands incompatible with horizontal
+% mode it issues a \cs{par} and then rereads the command.
+% \end{itemize}
+%
+% Unfortunately, \TeX{} has some (these days) unnecessary
+% optimization: if a \cs{vbox} ends and \TeX{} is still in
+% horizontal mode it simply exercises the paragraph builder instead
+% of issuing a \cs{par}. It is therefore necessary for \LaTeX{} to
+% ensure that this case doesn't happen and all boxes internally
+% have a \cs{par} command at their end.
+%
+% This \cs{par} may or may not run the ``par primitive'' (which is
+% always available as \cs{tex_par:D} in \pkg{expl3}); it is
+% permissible to have a changed meaning and it is in fact changed
+% by \LaTeX{} in various ways at various points inside
+% \texttt{latex.ltx}. For this \LaTeXe{} code has the following
+% conventions: \cs{@@@@par} and \cs{endgraf} both refer to the
+% default meaning (in the past this was the initex primitive) while
+% \cs{par} is the current meaning which may does something else.
+%
+%
+% We are now going to change this default meaning to run
+% \cs{para_end:} instead, which ultimately executes the initex
+% primitive but additionally adds our hooks when appropriate.
+% This way the change is again transparent to the legacy \LaTeXe{}
+% code.
+%
+% In most cases \cs{para_end:} should behave exactly like the
+% primitive and we achieve this by simply expanding it to the
+% primitive which is available to us as \cs{tex_par:D}. This way we
+% don't have to care about whether \TeX{} just does nothing (e.g.,
+% if in vertical mode already) or generate an error, etc.
+% \begin{macrocode}
+\cs_new_protected:Npn \para_end: {
+% \end{macrocode}
+%
+% The only case we care about is when we are in horizontal mode
+% (i.e., doing typesetting) and not also in inner mode (i.e.,
+% making paragraphs and not building an \cs{hbox}.
+% \begin{macrocode}
+% \bool_lazy_and:nnT
+% { \mode_if_horizontal_p: }
+% { \bool_not_p:n { \mode_if_inner_p: } }
+% { ...
+% \end{macrocode}
+% Since this is executed for each and every paragraph in a document
+% we try to stay a fast as possible, So we are aren't using the
+% above construct but two conditionals instead. Using low-level
+% \cs{if_mode...} conditions would be even faster but has the
+% danger to conflict with conditionals in the user hooks.
+% \begin{macrocode}
+ \mode_if_horizontal:TF {
+ \mode_if_inner:F {
+% \end{macrocode}
+% In that case the action of the primitive would be to remove the
+% last glue (not kern) from the horizontal list constructed to form
+% a paragraph then append the a penalty of 10000 and the
+% \cs{parfillskip} at the end and pass the whole list to the
+% paragraph builder which breaks it into lines and \TeX{} then
+% returns to vertical mode.
+%
+% What we want to do instead is to add our hook code at the end of
+% the horizontal list before that happens and the code is passed to
+% the paragraph builder. If there was a glue item at the end then
+% it should get removed before the hook code gets added so we have
+% to arrange for its removal ourselves.
+%
+% There is not much point in checking if there was really a glue
+% item at the end of the horizontal list, instead we simply try to
+% remove one using \cs{tex_unskip:D}, if there wasn't one this will
+% do nothing.
+% \begin{macrocode}
+ \tex_unskip:D
+% \end{macrocode}
+% The we execute the public hook (which may add final typesetting
+% material) followed by the kernel hook we need for adding tagging
+% support. None of this is supposed to change the mode---at the
+% moment we make only a very simple test for this, more devious
+% changes go unnoticed, but too bad, that will then probably
+% badly backfire.
+% \begin{macrocode}
+ \hook_use:n{para/end}
+ \@kernel@after@para@end
+ \mode_if_horizontal:TF {
+% \end{macrocode}
+% The final action (before getting to the point where
+% \cs{tex_par:D} is called) is to add a kern item so that the
+% primitive is prevented from removing glue (if there was some). If
+% we don't do this and the
+% horizontal list ended in several glue items we would end up with
+% removing two instead of just the last one, which would be wrong.
+% We use a kern as that is minimally faster.
+%
+% There is however one other \TeX{} optimization that hurts: in a
+% sequence like this \verb=$$ ... $$ \par= \TeX{} will be in
+% horizontal mode after the display, ready to receive further
+% paragraph text, but since the \cs{par} follows immediately there
+% is a ``null'' paragraph at the end and \TeX{} simply throws that
+% away. The space between \verb=$$= and \cs{par} got already
+% dropped during the display processing so the \cs{par} is not
+% removing any space and appending \cs{parfillskip}, instead it
+% simply goes silently to vmode. Now if we would had added something (to
+% prevent glue removal) that would look to \TeX{} like material
+% after the display and so we would end up with an empty paragraph
+% just containing \cs{parfillskip}.
+%
+% We therefore check if the current hlist is empty
+% (\cs{tex_lastnodetype:D} has the value \texttt{-1} and
+% only if not we add our kern.
+% \begin{macrocode}
+ \if_int_compare:w 0 < \tex_lastnodetype:D
+ \tex_kern:D \c_zero_dim
+ \fi:
+% \end{macrocode}
+% To run the \hook{para/after} hook we first end the
+% paragraph. This means that the \cs{tex_par:D} at the very end is
+% unnecessary but executing it there unnecessarily is better than
+% having code that test for all the different mode possibilities.
+% \begin{macrocode}
+ \tex_par:D
+ \hook_use:n{para/after}
+ \@kernel@after@para@after
+ }
+% \end{macrocode}
+% If we haven't been in horizontal mode then the earlier hook
+% \hook{para/end} is at fault and we report that.
+% \begin{macrocode}
+ { \msg_error:nnnn { hooks }{ para-mode }{end}{horizontal} }
+% \end{macrocode}
+% Finally close out the nested conditionals.
+% \begin{macrocode}
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \tex_par:D
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\para_raw_indent:,
+% \para_raw_noindent:,
+% \para_raw_end:}
+%
+% The commands \cs{para_raw_indent:} and \cs{para_raw_noindent:}
+% are like the primitives \cs{indent} and \cs{noindent} except that
+% they can only be used in vertical mode.
+%
+% To avoid issues a paragraph started by them should always be
+% ended by \cs{para_raw_end:} and not by \cs{para_end:} or
+% \cs{par} as the latter will execute hooks which then have no
+% counterpart at the beginning of the paragraph. It is the
+% responsibility of the programmer to make sure that they are
+% properly paired.
+% \begin{macrocode}
+\cs_new:Npn \para_raw_indent: {
+ \mode_if_vertical:TF
+ {
+ \tex_everypar:D {
+ \box_gset_to_last:N \g_para_indent_box
+ \tex_everypar:D { \g_@@_standard_everypar_tl }
+ \@@_handle_indent:
+ \the\everypar }
+ }
+ { \msg_error:nn { kernel }{ raw-para } }
+ \tex_indent:D
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Npn \para_raw_noindent: {
+ \mode_if_vertical:TF
+ {
+ \tex_everypar:D {
+ \tex_everypar:D { \g_@@_standard_everypar_tl }
+ \the\everypar }
+ }
+ { \msg_error:nn { kernel }{ raw-para } }
+ \tex_noindent:D
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \para_raw_end: \tex_par:D
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\RawIndent,\RawNoIndent,\RawParEnd}
+% The \LaTeXe{} names for starting and ending a paragraph without adding any hooks.
+% \begin{macrocode}
+\cs_set_eq:NN \RawIndent \para_raw_indent:
+\cs_set_eq:NN \RawNoindent \para_raw_noindent:
+\cs_set_eq:NN \RawParEnd \para_raw_end:
+% \end{macrocode}
+% \end{macro}
+%
+%
+% This ends the \texttt{para} module code.
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \begin{macro}{\par,\endgraf}
+% \begin{macro}[int]{\@@par}
+%
+% Having the new default definition for \cs{par} we also have to
+% set it up so that it gets used. This is needed in three places
+% \cs{par}, \cs{@@par} (to which \LaTeX{} resets \cs{par}
+% occasionally) and \cs{endgraf} which is another name for the
+% ``default'' action of \cs{par}.
+% \begin{macrocode}
+\cs_set_eq:NN \par \para_end:
+\cs_set_eq:NN \@@par \para_end:
+\cs_set_eq:NN \endgraf \para_end:
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% While this is not integrated properly into the format we have to
+% 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
+% \end{macrocode}
+%
+%
+% \subsection{The error messages}
+%
+% This one is used when we detect that some hook code has changed
+% the mode where it shouldn't, e.g., by starting or ending a
+% paragraph.
+% The first argument is the hook name second the mode
+% it should have stayed in but didn't.
+%
+% \begin{macrocode}
+\msg_new:nnnn { hooks } { para-mode }
+ {
+ Illegal~mode~ change~ in~ hook~ 'para/#1'.\\
+ Hook~ code~ did~ not~ remain~ in~ #2~ mode.
+ }
+ {
+ Paragraph~ hooks~ cannot~ change~ the~ TeX~ mode~ without~ causing~
+ endless~ recursion.~ The~ hook~ code~ in~ 'para/#1'~ needs~ to~ stay~
+ in~ #2~ mode,~ but~ it~ didn't.~ Examine~ the~ hook~
+ code~ with~ \iow_char:N \\ShowHook~ to~ find~ the~ issue.
+ }
+% \end{macrocode}
+%
+% And here is one used in the \enquote{raw} commands when they are
+% used outside of vertical mode.
+% \begin{macrocode}
+\msg_new:nnnn { kernel } { raw-para }
+ {
+ Not~ in~ vertical~ mode.
+ }
+ {
+ Starting~ a~ paragraph~ with~ \iow_char:N \\RawIndent~ or~
+ \iow_char:N \\RawNoindent \\
+ (or~ \iow_char:N \\para_raw_indent:~ or~
+ \iow_char:N \\para_raw_noindent:)~ is~ only~ allowed \\
+ if~ LaTeX~ is~ in~ vertical~ mode.
+ }
+% \end{macrocode}
+
+
+% \begin{macrocode}
+%
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {ltpara}{Undo~hooks~for~paragraphs}
+%<latexrelease>
+%<latexrelease>\let \OmitIndent \@undefined
+%<latexrelease>\let \IndentBox \@undefined
+%<latexrelease>\let \RawIndent \@undefined
+%<latexrelease>\let \RawNoindent \@undefined
+%<latexrelease>\let \RawParEnd \@undefined
+%<latexrelease>
+%<latexrelease>\cs_set_eq:NN \par \tex_par:D
+%<latexrelease>\cs_set_eq:NN \@@par \tex_par:D
+%<latexrelease>\cs_set_eq:NN \endgraf \tex_par:D
+%<latexrelease>
+%<latexrelease>\EndModuleRelease
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+%
+%
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\endinput
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+
diff --git a/macros/latex/base/ltpictur.dtx b/macros/latex/base/ltpictur.dtx
index 5bef40375c..ae8b58995d 100644
--- a/macros/latex/base/ltpictur.dtx
+++ b/macros/latex/base/ltpictur.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltpictur.dtx}
- [2020/08/14 v1.2a LaTeX Kernel (Picture Mode)]
+ [2021/04/20 v1.2b LaTeX Kernel (Picture Mode)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltpictur.dtx}
@@ -454,9 +454,10 @@
% \end{macro}
%
% \begin{macro}{\@stackcr}
+% \changes{v1.2b}{2021/04/20}{Use \cs{protected} for \cs{\bslash} variant (gh/548)}
% \begin{macro}{\@ixstackcr}
% \begin{macrocode}
-\def\@stackcr{\@ifstar\@ixstackcr\@ixstackcr}
+\protected\def\@stackcr{\@ifstar\@ixstackcr\@ixstackcr}
\def\@ixstackcr{\@ifnextchar[\@istackcr{\cr\ignorespaces}}
% \end{macrocode}
% \end{macro}
@@ -1773,7 +1774,7 @@
%
% Initialization: ``|\thinlines|''
% \changes{v1.1f}{1995/10/27}
-% {Move initialisation to kernel from autoload file}
+% {Move initialization to kernel from autoload file}
% \begin{macrocode}
\let\@linefnt\tenln
\let\@circlefnt\tencirc
diff --git a/macros/latex/base/ltplain.dtx b/macros/latex/base/ltplain.dtx
index 7949b836d4..e0fbcecf1b 100644
--- a/macros/latex/base/ltplain.dtx
+++ b/macros/latex/base/ltplain.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltplain.dtx}
- [2020/08/20 v2.3d LaTeX Kernel (Plain TeX)]
+ [2021/04/18 v2.3f LaTeX Kernel (Plain TeX)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltplain.dtx}
@@ -695,7 +695,7 @@
% {Define \cs{alloc@} in terms of \cs{e@alloc}}
% Since |\e@alloc| was added in 2015, |\@alloc| has not been used,
% but was left as some legacy code calls it. However the original
-% defnition gives spurious errors once the ``classic'' registers
+% definition gives spurious errors once the ``classic'' registers
% run out, so it is now defined to call |\e@alloc| internally.
% \begin{macrocode}
%</2ekernel>
@@ -754,8 +754,8 @@
\chardef\e@insert@top\e@alloc@top
\fi
% \end{macrocode}
-% If the classic registers are exausted, take an insert from the free float list
-% and use |\extrafloats| to add a new float to that list.
+% If the classic registers are exhausted, take an insert from the free
+% float list and use |\extrafloats| to add a new float to that list.
% \changes{v2.2c}{2016/07/29}{fix for tlb-newinsert-001}
% \begin{macrocode}
\def\newinsert#1{%
@@ -823,6 +823,28 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+% \begin{macro}{\@inputcheck}
+% \begin{macro}{\@unused}
+% Allocate read stream for testing and output stream that is never open an
+% thus writes to the terminal.
+% \changes{v1.0l}{1994/11/07}
+% {move here from ltdefns, remove duplicate \cs{@mainaux}}
+% \changes{v2.3e}{2021/03/26}{Allocate \cs{@inputcheck} and
+% \cs{@unused} early so that they are before expl3 allocates
+% more streams (gh/538)}
+% \begin{macrocode}
+\newread\@inputcheck
+\newwrite\@unused
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+%
% \begin{macro}{\maxdimen}
% \begin{macro}{\hideskip}
% Here are some examples of allocation.
@@ -898,6 +920,37 @@
% \end{macrocode}
% \tracingcommands=0
% \tracingrestores=0
+% \end{macrocode}
+%
+% \begin{macro}{\tracingstacklevels}
+% For Lua\TeX, the \cs{tracingstacklevels} functionality was
+% implemented as a callback, so here we just define the count register
+% to hold the value of the parameter.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2021/06/01}{\tracingstacklevels}%
+%<latexrelease> {tracingstacklevels}%
+\ifx\directlua\@undefined
+ % \tracingstacklevels=0 % added in 2021
+\else
+ \newcount\tracingstacklevels
+ % Code for \tracingstacklevels defined in ltfinal.dtx
+\fi
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{0000/00/00}{\tracingstacklevels}%
+%<latexrelease> {tracingstacklevels}%
+%<latexrelease>\ifx\directlua\@undefined
+%<latexrelease>\else
+%<latexrelease> \let\tracingstacklevels\@undefined
+%<latexrelease>\fi
+%<latexrelease>\EndIncludeInRelease
+%</2ekernel|latexrelease>
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
% \language=0
% \begin{macrocode}
\uchyph=1
@@ -1481,43 +1534,69 @@
% \changes{v1.1x}{2002/02/24}{Macro added}
% \changes{v2.0b}{2012/01/20}{etex tracing if available}
% \changes{v2.0d}{2015/02/20}{Spell commands correctly :-)}
-% \changes{v2.0g}{2015/03/10}{Reorganise to be less noisy}
+% \changes{v2.0g}{2015/03/10}{Reorganize to be less noisy}
+% \changes{v2.3f}{2021/04/18}{Drop pre-$\varepsilon$-\TeX{} support}
+% \changes{v2.3f}{2021/04/18}
+% {Add \cs{tracingstacklevels} and \cs{tracinglostchars}=3}
% \begin{macrocode}
-%<latexrelease>\IncludeInRelease{2015/01/01}{\loggingall}{etex tracing}%
+%<latexrelease>\IncludeInRelease{2021/06/01}{\loggingall}
+%<latexrelease> {\tracingstacklevels and \tracinglostchars=3}%
%<*2ekernel|latexrelease>
-\ifx\tracingscantokens\@undefined
-\gdef\loggingall{%
+\edef\loggingall{%
\tracingstats\tw@
\tracingpages\@ne
- \tracinglostchars\@ne
- \tracingparagraphs\@ne
- \errorcontextlines\maxdimen
- \loggingoutput
- \tracingmacros\tw@
- \tracingcommands\tw@
- \tracingrestores\@ne
- }%
-\else
-\gdef\loggingall{%
- \tracingstats\tw@
- \tracingpages\@ne
- \tracinglostchars\tw@
+ \tracinglostchars\thr@@
\tracingparagraphs\@ne
\tracinggroups\@ne
\tracingifs\@ne
\tracingscantokens\@ne
\tracingnesting\@ne
\errorcontextlines\maxdimen
- \loggingoutput
+ \ifdefined\tracingstacklevels \tracingstacklevels\maxdimen \fi
+ \noexpand \loggingoutput
\tracingmacros\tw@
\tracingcommands\thr@@
\tracingrestores\@ne
\tracingassigns\@ne
}%
-\fi
-\gdef\tracingall{\showoverfull\loggingall}
+\def\tracingall{\showoverfull\loggingall}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{2015/01/01}{\loggingall}{etex tracing}%
+%<latexrelease>\ifx\tracingscantokens\@undefined
+%<latexrelease>\gdef\loggingall{%
+%<latexrelease> \tracingstats\tw@
+%<latexrelease> \tracingpages\@ne
+%<latexrelease> \tracinglostchars\@ne
+%<latexrelease> \tracingparagraphs\@ne
+%<latexrelease> \errorcontextlines\maxdimen
+%<latexrelease> \loggingoutput
+%<latexrelease> \tracingmacros\tw@
+%<latexrelease> \tracingcommands\tw@
+%<latexrelease> \tracingrestores\@ne
+%<latexrelease> }%
+%<latexrelease>\else
+%<latexrelease>\gdef\loggingall{%
+%<latexrelease> \tracingstats\tw@
+%<latexrelease> \tracingpages\@ne
+%<latexrelease> \tracinglostchars\tw@
+%<latexrelease> \tracingparagraphs\@ne
+%<latexrelease> \tracinggroups\@ne
+%<latexrelease> \tracingifs\@ne
+%<latexrelease> \tracingscantokens\@ne
+%<latexrelease> \tracingnesting\@ne
+%<latexrelease> \errorcontextlines\maxdimen
+%<latexrelease> \loggingoutput
+%<latexrelease> \tracingmacros\tw@
+%<latexrelease> \tracingcommands\thr@@
+%<latexrelease> \tracingrestores\@ne
+%<latexrelease> \tracingassigns\@ne
+%<latexrelease>}%
+%<latexrelease>\fi
+%<latexrelease>\gdef\tracingall{\showoverfull\loggingall}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
%<latexrelease>\IncludeInRelease{0000/00/00}{\loggingall}{etex tracing}%
%<latexrelease>\gdef\loggingall{\tracingcommands\tw@\tracingstats\tw@
%<latexrelease> \tracingpages\@ne\tracinglostchars\@ne
@@ -1532,29 +1611,14 @@
%
% \begin{macro}{\tracingnone}
% \changes{v2.0g}{2015/03/10}{macro added}
-% \begin{macro}{\hideoutput}
-% \changes{v2.0g}{2015/03/10}{macro added}
+% \changes{v2.3f}{2021/04/18}{Drop pre-$\varepsilon$-\TeX{} support}
+% \changes{v2.3f}{2021/04/18}
+% {Add \cs{tracingstacklevels} and \cs{tracinglostchars}=3}
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{2015/01/01}{\tracingnone}%
%<latexrelease> {turn off etex tracing}%
%<*2ekernel|latexrelease>
-\ifx\tracingscantokens\@undefined
-\def\tracingnone{%
- \tracingonline\z@
- \tracingcommands\z@
- \showboxdepth\m@ne
- \showboxbreadth\m@ne
- \tracingoutput\z@
- \errorcontextlines\m@ne
- \tracingrestores\z@
- \tracingparagraphs\z@
- \tracingmacros\z@
- \tracinglostchars\@ne
- \tracingpages\z@
- \tracingstats\z@
-}%
-\else
-\def\tracingnone{%
+\edef\tracingnone{%
\tracingassigns\z@
\tracingrestores\z@
\tracingonline\z@
@@ -1563,6 +1627,7 @@
\showboxbreadth\m@ne
\tracingoutput\z@
\errorcontextlines\m@ne
+ \ifdefined\tracingstacklevels \tracingstacklevels\z@ \fi
\tracingnesting\z@
\tracingscantokens\z@
\tracingifs\z@
@@ -1573,30 +1638,77 @@
\tracingpages\z@
\tracingstats\z@
}%
-\fi
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{2015/01/01}{\tracingnone}%
+%<latexrelease> {turn off etex tracing}%
+%<latexrelease>\ifx\tracingscantokens\@undefined
+%<latexrelease>\def\tracingnone{%
+%<latexrelease> \tracingonline\z@
+%<latexrelease> \tracingcommands\z@
+%<latexrelease> \showboxdepth\m@ne
+%<latexrelease> \showboxbreadth\m@ne
+%<latexrelease> \tracingoutput\z@
+%<latexrelease> \errorcontextlines\m@ne
+%<latexrelease> \tracingrestores\z@
+%<latexrelease> \tracingparagraphs\z@
+%<latexrelease> \tracingmacros\z@
+%<latexrelease> \tracinglostchars\@ne
+%<latexrelease> \tracingpages\z@
+%<latexrelease> \tracingstats\z@
+%<latexrelease>}%
+%<latexrelease>\else
+%<latexrelease>\def\tracingnone{%
+%<latexrelease> \tracingassigns\z@
+%<latexrelease> \tracingrestores\z@
+%<latexrelease> \tracingonline\z@
+%<latexrelease> \tracingcommands\z@
+%<latexrelease> \showboxdepth\m@ne
+%<latexrelease> \showboxbreadth\m@ne
+%<latexrelease> \tracingoutput\z@
+%<latexrelease> \errorcontextlines\m@ne
+%<latexrelease> \tracingnesting\z@
+%<latexrelease> \tracingscantokens\z@
+%<latexrelease> \tracingifs\z@
+%<latexrelease> \tracinggroups\z@
+%<latexrelease> \tracingparagraphs\z@
+%<latexrelease> \tracingmacros\z@
+%<latexrelease> \tracinglostchars\@ne
+%<latexrelease> \tracingpages\z@
+%<latexrelease> \tracingstats\z@
+%<latexrelease>}%
+%<latexrelease>\fi
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{0000/00/00}{\tracingnone}%
+%<latexrelease> {turn off etex tracing}%
+%<latexrelease>\let\tracingnone\@undefined
+%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
+% \end{macro}
%
+% \begin{macro}{\hideoutput}
+% \changes{v2.0g}{2015/03/10}{macro added}
% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2015/01/01}{\hideoutput}%
+%<latexrelease> {hide output from tracing}%
\def\hideoutput{%
\tracingoutput\z@
\showboxbreadth\m@ne
\showboxdepth\m@ne
\tracingonline\m@ne
}%
-% \end{macrocode}
-%
-% \begin{macrocode}
-%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
-%<latexrelease>\IncludeInRelease{0000/00/00}{\tracingnone}%
-%<latexrelease> {turn off etex tracing}%
-%<latexrelease>\let\tracingnone\@undefined
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{0000/00/00}{\hideoutput}%
+%<latexrelease> {hide output from tracing}%
%<latexrelease>\let\hideoutput\@undefined
%<latexrelease>\EndIncludeInRelease
+%</2ekernel|latexrelease>
% \end{macrocode}
% \end{macro}
-% \end{macro}
-%
%
% \LaTeX\ change: |\showhyphens| Defined later.
%
diff --git a/macros/latex/base/ltsect.dtx b/macros/latex/base/ltsect.dtx
index 359b445f45..29ea142ba6 100644
--- a/macros/latex/base/ltsect.dtx
+++ b/macros/latex/base/ltsect.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -31,7 +31,7 @@
%%% From File: ltsect.dtx
%<*driver>
% \fi
-\ProvidesFile{ltsect.dtx}[2020/07/27 v1.1e LaTeX Kernel (Sectioning)]
+\ProvidesFile{ltsect.dtx}[2020/12/05 v1.1e LaTeX Kernel (Sectioning)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltsect.dtx}
@@ -779,7 +779,7 @@
% \changes{v1.1c}{2018/09/26}{Sometimes mask the endline char when
% writing to files (github/73)}
% \changes{v1.1e}{2020/10/01}{add a fourth argument for better
-% hyperref compability}
+% hyperref compatibility}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
diff --git a/macros/latex/base/ltshipout-code.pdf b/macros/latex/base/ltshipout-code.pdf
index fe2cee9f3d..c2ee874b52 100644
--- a/macros/latex/base/ltshipout-code.pdf
+++ b/macros/latex/base/ltshipout-code.pdf
Binary files differ
diff --git a/macros/latex/base/ltshipout-doc.pdf b/macros/latex/base/ltshipout-doc.pdf
index d762ede0a7..30bb7daef5 100644
--- a/macros/latex/base/ltshipout-doc.pdf
+++ b/macros/latex/base/ltshipout-doc.pdf
Binary files differ
diff --git a/macros/latex/base/ltshipout.dtx b/macros/latex/base/ltshipout.dtx
index e226f753f3..f773cd23da 100644
--- a/macros/latex/base/ltshipout.dtx
+++ b/macros/latex/base/ltshipout.dtx
@@ -1,6 +1,7 @@
% \iffalse meta-comment
%%
-%% File: ltshipout.dtx (C) Copyright 2020 Frank Mittelbach, LaTeX Team
+%% Copyright (C) 2020-2021
+%% Frank Mittelbach, LaTeX Team
%%
%
% This file is part of the LaTeX base system.
@@ -31,8 +32,8 @@
%%% From File: ltshipout.dtx
%
% \begin{macrocode}
-\providecommand\ltshipoutversion{v1.0d}
-\providecommand\ltshipoutdate{2020/11/24}
+\providecommand\ltshipoutversion{v1.0i}
+\providecommand\ltshipoutdate{2021/03/17}
% \end{macrocode}
%
%<*driver>
@@ -55,6 +56,9 @@
}
\ExplSyntaxOff
+\providecommand\InternalDetectionOff{}
+\providecommand\InternalDetectionOn{}
+
\EnableCrossrefs
\CodelineIndex
\begin{document}
@@ -75,7 +79,7 @@
% \ltshipoutversion\ dated \ltshipoutdate, \copyright\ \LaTeX\
% Project.}}
%
-% \author{Frank Mittelbach}
+% \author{Frank Mittelbach, \LaTeX{} Project Team}
%
% \maketitle
%
@@ -108,11 +112,56 @@
% It then stores it in a named box register. This box can then be
% manipulated through a set of hooks after which it is shipped out
% for real.
+%
+% Each shipout that actually happens (i.e., where the material is
+% not discarded for one or the other reason) is recorded and the
+% total number is available in a readonly variable and in a
+% \LaTeX{} counter.
+% \end{function}
+%
+%
+% \begin{function}{\RawShipout}
+% This command implements a simplified shipout that bypasses the
+% foreground and background
+% hooks, e.g., only \hook{shipout/firstpage} and
+% \hook{shipout/lastpage} are executed and the total shipout
+% counters are incremented.
+%
+% The command doesn't use \cs{ShipoutBox} but its own private box
+% register so that it can be used inside of shipout hooks to do
+% some additional shipouts while already in the output routine with
+% the current page being stored in \cs{ShipoutBox}. It does have
+% access to \cs{ShipoutBox} if it is used in \hook{shipout/before}
+% (or \hook{shipout/after}) and can use its content.
+%
+% It is safe to use it in \hook{shipout/before} or
+% \hook{shipout/after} but not necessarily in the other
+% \hook{shipout/...} hooks as they are intended for special
+% processing.
% \end{function}
%
% \begin{variable}{\ShipoutBox,\l_shipout_box}
-% This box register is called \cs{ShipoutBox} (alternatively available via the
-% L3 name \cs{l_shipout_box}).
+% This box register is called \cs{ShipoutBox} (alternatively
+% available via the L3 name \cs{l_shipout_box}).
+%
+% This box is a ``local'' box and assignments to it should be done
+% only locally. Global assignments (as done by some packages with
+% older code where this is box is known as 255) may work but they are
+% conceptually wrong and may result in errors under certain
+% circumstances.
+%
+% During the execution of \hook{shipout/before} this box contains
+% the accumulated material for the page, but not yet any material
+% added by other shipout hooks.
+% During execution of \hook{shipout/after}, i.e., after the shipout
+% has happened, the box also contains any background or foreground
+% material.
+%
+% Material from the hooks \hook{shipout/firstpage} or
+% \hook{shipout/lastpage} is not included (but only used during the
+% actual shipout) to facilitate reuse of the box data (e.g.,
+% \hook{shipout/firstpage} material should never be added to a
+% later page of the output).
% \end{variable}
%
%
@@ -133,11 +182,11 @@
%
% \subsection{Provided hooks}
%
-% \begin{variable}{shipout/before,
+% \begin{variable}{shipout/before,shipout/after,
% shipout/foreground,shipout/background,
% shipout/firstpage,
% shipout/lastpage}
-% The code offers a number of hooks into which packages (or the
+% The code for \cs{shipout} offers a number of hooks into which packages (or the
% user) can add code to support different use cases.
% These are:
% \begin{description}
@@ -148,6 +197,20 @@
% It can be used to alter that box content or to discard it
% completely (see \cs{DiscardShipoutBox} below).
%
+% You can use \cs{RawShipout} inside this hook for special use
+% cases. It can make use of \cs{ShipoutBox} (which doesn't yet
+% include the background and foreground material).
+%
+% \textbf{Note:} It is not possible (or say advisable) to try
+% and use this hook to typeset material with the intention to
+% return it to main vertical list, it will go wrong and give
+% unexpected results in many cases---for starters it will appear
+% after the current page not before or it will vanish or the
+% vertical spacing will be wrong!
+% \end{description}
+% \end{variable}
+%
+% \begin{description}
% \item[\hook{shipout/background}]
%
% This hook adds a picture environment into the background of
@@ -186,15 +249,22 @@
% not discarded at the last minute). It should only contain
% \cs{special} or similar commands needed to direct post processors
% handling the \texttt{.dvi} or \texttt{.pdf} output.\footnotemark
+% \footnotetext{In
+% \LaTeXe{} that was already existing, but implemented using a box
+% register with the name \cs{@begindvibox}.}
%
% ^^A \fmi{not sure it has to be that restrictive.}
%
+% This hook is added to the very first page regardless of how it
+% is shipped out (i.e., with \cs{shipout} or \cs{RawShipout}).
%
% \item[\hook{shipout/lastpage}]
%
% The corresponding hook to add \cs{special}s at the very end of
-% the output file. It is only executed on the very last page ---
+% the output file. It is only executed on the very last page of
+% the output file ---
% or rather on the page that \LaTeX{} believes is the last one.
+% Again it is executed regardless of the shipout method.
%
% It may not be possible for \LaTeX{} to correctly determine
% which page is the last one without several reruns. If this
@@ -202,17 +272,32 @@
% extra page to place the material and also request a rerun to
% get the correct placement sorted out.
%
+% \item[\hook{shipout/after}]
+%
+% This hook is executed after a shipout has happened. If the
+% shipout box is discarded this hook is not looked at.
+%
+% You can use \cs{RawShipout} inside this hook for special use
+% cases and the main \cs{ShipoutBox} is still available at this
+% point (but in contrast to \hook{shipout/before} it now
+% includes the background and foreground material).
+%
+% \textbf{Note:} Just like \hook{shipout/before} this hook is
+% not meant to be used for adding adding typeset material back
+% to the main vertical list---it might vanish or the
+% vertical spacing will be wrong!
+%
+%
% \end{description}
-% \end{variable}\footnotetext{In
-% \LaTeXe{} that was already existing, but implemented using a box
-% register with the name \cs{@begindvibox}.}
%
% As mentioned above the hook \hook{shipout/before} is executed
% first and can manipulate the prepared shipout box stored in
% \cs{ShipoutBox} or set things up for use in \cs{write} during the
-% actual shipout. The other hooks are added inside hboxes to the
-% box being shipped out in the following
-% order:
+% actual shipout. It is even run if there was a
+% \cs{DiscardShipoutBox} request in the document.
+%
+% The other hooks (except \hook{shipout/after}) are added inside
+% hboxes to the box being shipped out in the following order:
% \begin{center}
% \begin{tabular}{ll}
% \hook{shipout/firstpage} & only on the first page \\
@@ -225,32 +310,50 @@
% If any of the hooks has no code then that particular no box is
% added at that point.
%
+% Once the (page) box has been shipped out the \hook{shipout/after}
+% hook is called (while you are still inside the output routine). It
+% is not called if the shipout box was discarded.
+%
% In a document that doesn't produce pages, e.g., only makes
-% \cs{typeout}s, none of the hooks are executed (as there is no
+% \cs{typeout}s, none of the hooks are ever executed (as there is no
% \cs{shipout}) not even the \hook{shipout/lastpage} hook.
%
+% If \cs{RawShipout} is used instead of \cs{shipout} then only the
+% hooks \hook{shipout/firstpage} and \hook{shipout/lastpage} are
+% executed (on the first or last page), all others are bypassed.
+%
+%
+%
+% \subsection{Legacy \LaTeX{} commands}
+%
% \begin{function}{\AtBeginDvi,\AtEndDvi}
% \cs{AtBeginDvi} is the existing \LaTeXe{} interface to fill the
% \hook{shipout/firstpage} hook. This is not really a good name
% as it is not just supporting \texttt{.dvi} but also \texttt{.pdf}
-% output or \texttt{.dvx}.
+% output or \texttt{.xdv}.
%
% \cs{AtEndDvi} is the counterpart that was not available in the
% kernel but only through the package \pkg{atenddvi}. It fills the
% \hook{shipout/lastpage} hook.
+% \end{function}
%
-% \fmi{better names? Any suggestions?}
+% As these two wrappers have been available for a long time we
+% continue offering them. However, for new code we suggest using
+% the high-level hook management commands directly instead of
+% ``randomly-named'' wrappers. This will lead to code that is
+% easier to understand and to maintain. For this reason we do not
+% provide any other wrapper commands for the above hooks in the
+% kernel.
%
-% \end{function}
%
% \subsection{Special commands for use inside the hooks}
%
-% \begin{function}{\DiscardShipoutBox,\shipout_discard_box:}
+% \begin{function}{\DiscardShipoutBox,\shipout_discard:}
% \begin{syntax}
% \cs{AddToHookNext} \texttt{\{shipout/before\} \{...\cs{DiscardShipoutBox}...\}}
% \end{syntax}
% The \cs{DiscardShipoutBox} declaration (L3 name
-% \cs{shipout_discard_box:})
+% \cs{shipout_discard:})
% requests that on the next
% shipout the page box is thrown away instead of being shipped to
% the \texttt{.dvi} or \texttt{.pdf} file.
@@ -261,6 +364,8 @@
% Note that if this declaration is used directly in the document it
% may depend on the placement to which page it applies, given that
% \LaTeX{} output routine is called in an asynchronous manner!
+% Thus normally one would use this only as part of the
+% \hook{shipout/before} code.
%
% \fmi{Once we have a new mark mechanism available we can improve
% on that and make sure that the declaration applies to the page
@@ -279,12 +384,28 @@
% names as given below.
%
%
+%
+% \subsection{Provided Lua\TeX\ callbacks}
+%
+% \begin{variable}{pre_shipout_filter}
+% Under Lua\TeX{} the \texttt{pre\_shipout\_filter} Lua callback is
+% provided which gets called immediately before the shipout primitive gets invoked.
+% The signature is
+% \begin{verbatim}
+% function(<node> head)
+% return true
+% end
+% \end{verbatim}
+% The \texttt{head} is the list node corresponding to the box to be shipped out.
+% The return value should always be \texttt{true}.
+% \end{variable}
+%
% \subsection{Information counters}
%
%
% \begin{variable}{\ReadonlyShipoutCounter,\g_shipout_readonly_int}
% \begin{syntax}
-% \cs{ifnum}\cs{ReadOnlyShipoutCounter}\texttt{=...}
+% \cs{ifnum}\cs{ReadonlyShipoutCounter}\texttt{=...}
% \cs{int_use:N} \cs{g_shipout_readonly_int} \texttt{\% expl3 usage}
% \end{syntax}
% This integer holds the number of pages shipped out up to now
@@ -292,6 +413,7 @@
% routine). More precisely, it is incremented only after it is
% clear that a page will be shipped out, i.e., after the
% \hook{shipout/before} hook (because that might discard the page)!
+% In contrast \hook{shipout/after} sees the incremented value.
%
% Just like with the \texttt{page} counter its value is
% only accurate within the output routine. In the body of the
@@ -299,10 +421,11 @@
% asynchronously!
%
% Also important: it \emph{must not} be set, only read. There are
-% no provisions to prevent that but if you do, chaos will be the
-% result. To emphasize this fact it is not provided as a \LaTeX{}
-% counter but as a \TeX{} counter (i.e., a command), so
-% \cs{Alph}\Arg{\cs{ReadonlyShipoutCounter}} etc, would not work.
+% no provisions to prevent that restriction, but if you manipulate
+% it, chaos will be the result. To emphasize this fact it is not
+% provided as a \LaTeX{} counter but as a \TeX{} counter (i.e., a
+% command), so \cs{Alph}\verb={=\cs{ReadonlyShipoutCounter}\verb=}=
+% etc, would not work.
% \end{variable}
%
% \begin{variable}{totalpages,\g_shipout_totalpages_int}
@@ -314,7 +437,8 @@
% \texttt{totalpages} counter is a \LaTeX{} counter and incremented
% for each shipout attempt including those pages that are discarded
% for one or the other reason. Again \hook{shipout/before} sees
-% the counter before it is incremented).
+% the counter before it is incremented. In contrast
+% \hook{shipout/after} sees the incremented value.
%
% Furthermore, while it is incremented for each page, its value is
% never used by \LaTeX. It can therefore be freely reset or changed by user
@@ -331,9 +455,9 @@
% \cs{thetotalpages}/\cs{PreviousTotalPages}
% \end{syntax}
% Command that expands to the number of total pages from the
-% previous run. If there was no previous run or if usedin the
+% previous run. If there was no previous run or if used in the
% preamble it expands to
-% \texttt{0}. Note that this is a command to a counter, so in order
+% \texttt{0}. Note that this is a command and not a counter, so in order
% to display the number in, say, Roman numerals you have to assign
% its value to a counter and then use \cs{Roman} on that counter.
% \end{variable}
@@ -356,9 +480,15 @@
%
% \section{Emulating commands from other packages}
%
-% The packages in this section are no longer necessary but as they
-% are used in other packages they are emulated when they are loaded
-% via \cs{usepackage} or \cs{RequirePackage}.
+% The packages in this section are no longer necessary, but as they
+% are used by other packages, they are emulated when they are
+% explicitly loaded with \cs{usepackage} or \cs{RequirePackage}.
+%
+% Please note that the emulation only happens if the package is
+% explicitly requested, i.e., the commands documented below are not
+% automatically available in the \LaTeX{} kernel! If you write a
+% new package we suggest to use the appropriate kernel hooks
+% directly instead of loading the emulation.
%
%
% \subsection{Emulating \pkg{atbegshi}}
@@ -410,6 +540,21 @@
% This is the name of the shipout box as \pkg{atbegshi} knows it.
% \end{function}
%
+%
+% \begin{function}{\AtBeginShipoutOriginalShipout}
+% This is the name of the \cs{shipout} primitive as \pkg{atbegshi}
+% knows it. This bypasses all the mechanisms set up by the \LaTeX{}
+% kernel and there are various scenarios in which it can therefore
+% fail. It should only be used to run existing legacy
+% \pkg{atbegshi} code but not in newly developed applications.
+%
+% The kernel alternative is \cs{RawShipout} which is integrated
+% with the \LaTeX{} mechanisms and updates, for example, the
+% \cs{ReadonlyShipoutCounter} counter. Please use \cs{RawShipout}
+% for new code if you want to bypass the before, foreground and
+% background hooks.
+% \end{function}
+%
% \begin{function}{\AtBeginShipoutInit}
% By default \pkg{atbegshi} delayed its action until
% \verb=\begin{document}=. This command was forcing it in an earlier
@@ -434,6 +579,13 @@
%
% \subsection{Emulating \pkg{everyshi}}
%
+% The \pkg{everyshi} package is providing commands to run arbitrary
+% code just before the shipout starts.
+% One point of difference: in the new shipout hooks the page is
+% available as \cs{ShipoutBox} for inspection of change, one should
+% not manipulate box 255 directly inside \hook{shipout/before}, so
+% old code doing this would change to use \cs{ShipoutBox} instead
+% of \texttt{255} or \cs{@cclv}.
%
% \begin{function}{\EveryShipout}
% \begin{syntax}
@@ -447,22 +599,49 @@
% \end{syntax}
% \end{function}
%
+% However, most use cases for \pkg{everyshi} are attempts to put
+% some picture or text into the background or foreground of the page
+% and that can be done today simply by using the
+% \hook{shipout/background} and
+% \hook{shipout/foreground} hooks without any need to coding.
%
%
% \subsection{Emulating \pkg{atenddvi}}
%
-% The \pkg{atenddvi} package implemented only a single command:
-% \cs{AtEndDvi} and that is now available out of the box.
+% The \pkg{atenddvi} package implemented only a single command:
+% \cs{AtEndDvi} and that is now available out of the box so the
+% emulation makes the package a no-op.
%
%
%
% \subsection{Emulating \pkg{everypage}}
%
-% This page takes over the original \cs{@begindvi} hook and replaces
-% it. It should be all covered by the hooks offered here (details
-% need checking) and thus could simply use the provided hooks
-% rather than defining its own.
+% This package patched the original \cs{@begindvi} hook and replaced
+% it with its own version.
+% Its functionality is now covered by the hooks offered by the
+% kernel so that there is no need for such patching any longer.
+%
+% \begin{function}{\AddEverypageHook}
+% \begin{syntax}
+% \cs{AddEverypageHook}\Arg{code} $\equiv$
+% \qquad\cs{AddToHook}\texttt{\{shipout/background\}\{\cs{put}(1in,-1in)\Arg{code}\}}
+% \end{syntax}
+% \cs{AddEverypageHook} is adding something into the
+% background of every page at a position of 1in to the right and
+% 1in down from the top left corner of the page.
+% By using the kernel hook directly you can put your material
+% directly to the right place, i.e., use other coordinates in the
+% \cs{put} statement above.
+% \end{function}
%
+% \begin{function}{\AddThispageHook}
+% \begin{syntax}
+% \cs{AddThispageHook}\Arg{code} $\equiv$
+% \qquad\cs{AddToHookNext}\texttt{\{shipout/background\}\{\cs{put}(1in,-1in)\Arg{code}\}}
+% \end{syntax}
+% The \cs{AddThispageHook} wrapper is similar but uses
+% \cs{AddToHookNext}.
+% \end{function}
%
%
% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
@@ -479,7 +658,7 @@
% \begin{macrocode}
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
-%<latexrelease> {\shipout}{Hook mangement (shipout)}%
+%<latexrelease> {\shipout}{Hook management (shipout)}%
% \end{macrocode}
%
%
@@ -540,6 +719,41 @@
% \end{macro}
%
%
+% \begin{macro}{\l_@@_raw_box}
+% The \cs{RawShipout} gets its own box but it is internal as there
+% is no hook manipulation for it.
+% \begin{macrocode}
+\box_new:N \l_@@_raw_box
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_finalize_box:}
+% For Lua\TeX{} invoke the \texttt{pre\_shipout\_filter} callback.
+% \changes{v1.0i}{2021/01/22}{Add \texttt{pre\_shipout\_filter} Lua callback}
+% \begin{macrocode}
+\sys_if_engine_luatex:TF
+ {
+ \newluafunction \@@_finalize_box:
+ \exp_args:Nx \everyjob {
+ \exp_not:V \everyjob
+ \exp_not:N \lua_now:n {
+ luatexbase.create_callback('pre_shipout_filter', 'list')
+ local~call, getbox, setbox = luatexbase.call_callback, tex.getbox, tex.setbox~
+ lua.get_functions_table()[\the \@@_finalize_box:] = function()
+ local~result = call('pre_shipout_filter', getbox(\the \l_shipout_box))
+ if~not (result == true) then~
+ setbox(\the \l_shipout_box, result~or~nil)
+ end~
+ end
+ }
+ }
+ \protected \luadef \@@_finalize_box: \the \@@_finalize_box:
+ } {
+ \cs_set_eq:NN \@@_finalize_box: \scan_stop:
+ }
+% \end{macrocode}
+% \end{macro}
%
%
% \begin{macro}{\@@_execute:}
@@ -567,7 +781,8 @@
%
% \begin{macro}{\l_@@_group_level_tl}
% Helper token list to record the group level at which
-% \cs{@@_execute:} is encountered. \begin{macrocode}
+% \cs{@@_execute:} is encountered.
+% \begin{macrocode}
\tl_new:N \l_@@_group_level_tl
% \end{macrocode}
% \end{macro}
@@ -581,28 +796,78 @@
\cs_new:Npn \@@_execute_test_level: {
\int_compare:nNnT
\l_@@_group_level_tl < \tex_currentgrouplevel:D
- \tex_aftergroup:D
- \@@_execute_cont:
+ \tex_aftergroup:D \@@_execute_cont:
}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_execute_cont:}
+% This does the actual shipout running several hooks as part of it.
+% The code for them is passed as argument \verb=#2= to \verb=#4=
+% to \cs{@@_execute_main_cont:Nnnn}; the first argument is the box
+% to be shipped out.
+% \begin{macrocode}
+\cs_new:Npn \@@_execute_cont: {
+ \@@_execute_main_cont:Nnnn
+ \l_shipout_box
+ { \hook_use:n {shipout/before} }
+ { \hook_if_empty:nF {shipout/foreground}
+ { \@@_add_foreground_picture:n
+ { \hook_use:n {shipout/foreground} } }
+% \end{macrocode}
+% If the user hook for the background (\hook{shipout/background}) has
+% no code, there might still code in the kernel hook so we need to
+% test for this too.
+% We only test for the \cs{@kernel@before@shipout@background}
+% though. If the \cs{@kernel@after@shipout@background} needs
+% executing even if the user hook is empty then we can add another
+% test (or the kernel could put something into the before hook).
+%
+% \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}}
+% \begin{macrocode}
+ \bool_lazy_and:nnF
+ { \hook_if_empty_p:n {shipout/background} }
+ { \tl_if_empty_p:N \@kernel@before@shipout@background }
+ { \@@_add_background_picture:n
+ { \@kernel@before@shipout@background
+ \hook_use:n {shipout/background}
+ \@kernel@after@shipout@background }
+ }
+ }
+ { \hook_use:n {shipout/after} }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_execute_main_cont:Nnnn}
% When we have reached this point the shipout box has been
% processed and is available in \cs{l_shipout_box} and ready for
-% real ship out (perhaps)..
+% real ship out (unless it gets discarded during the process).
+%
+% The three arguments hold hook code that is executed just before the
+% actual shipout (\verb=#1=), within the shipout adding
+% background and foreground material (\verb=#2=) and after the
+% shipout has happened (\verb=#3=).
+% These are passed as arguments because the same code without those
+% hooks is also used when doing a ``raw'' shipout implemented by
+% \cs{RawShipout}.
+% The only hook that is always executed is that for the very last
+% page, i.e., \hook{shipout/lastpage}.
%
% First we quickly check if it is void (can't happen in the
% standard \LaTeX{} output routine but \cs{shipout} might be called
% from a package that has some special processing logic). If it is
% void we aren't shipping anything out and processing ends.\footnote{In that
-% case we don't reset the deadcyles, that would be up to the OR
+% case we don't reset the deadcycles, that would be up to the OR
% processing logic to do.}
% \begin{macrocode}
-\cs_new:Npn \@@_execute_cont: {
- \box_if_empty:NTF \l_shipout_box
- { \PackageWarning{ltshipout}{Ignoring~ void~ shipout~ box} }
+\cs_new:Npn \@@_execute_main_cont:Nnnn #1#2#3#4 {
+ \box_if_empty:NTF #1
+ { \@latex@warning{Ignoring~ void~ shipout~ box} }
{
% \end{macrocode}
% Otherwise we assume that we will ship something and prepare for
@@ -610,7 +875,8 @@
% \cs{protect} while we are running the hook code).
% We also save the current \cs{protect} state to restore it later.
% \begin{macrocode}
- \bool_gset_false:N \g_@@_discard_bool
+% \bool_gset_false:N \g_@@_discard_bool % setting this would disable
+ % \DiscardShipoutBox on doc-level
\cs_set_eq:NN \@@_saved_protect: \protect
\set@typeset@protect
% \end{macrocode}
@@ -619,11 +885,12 @@
% necessary as the code could access them via \cs{box_ht:N}, etc.,
% but it is perhaps convenient.}
% \begin{macrocode}
- \@@_get_box_size:N \l_shipout_box
+ \@@_get_box_size:N #1
% \end{macrocode}
-% Then we execute the \hook{shipout/before} hook.
+% Then we execute the \hook{shipout/before} hook (or nothing in
+% case of \cs{RawShipout}).
% \begin{macrocode}
- \hook_use:n {shipout/before}
+ #2
% \end{macrocode}
% In \cs{g_shipout_totalpages_int} we count all shipout attempts so
% we increment that counter already here (the other one is
@@ -631,7 +898,8 @@
% \cs{shipout}.
%
% We increment it after running the above hook so that the values
-% for \cs{g_shipout_totalpages_int} and \cs{} are in sync while the
+% for \cs{g_shipout_totalpages_int} and \cs{g_shipout_readonly_int}
+% are in sync while the
% hook is executed (in the case that totalpages isn't manually
% altered or through discarding pages that is).
% \begin{macrocode}
@@ -641,7 +909,7 @@
% we now test for it.
% \begin{macrocode}
\bool_if:NTF \g_@@_discard_bool
- { \PackageInfo{ltshipout}{Completed~ page~ discarded}
+ { \@latex@info@no@line{Completed~ page~ discarded}
\bool_gset_false:N \g_@@_discard_bool
% \end{macrocode}
% As we are discarding the page box and not shipping anything out,
@@ -655,7 +923,7 @@
% needed? Or the resetting of \cs{protect} to its kernel value?}
% \begin{macrocode}
% \group_begin:
-% \box_set_eq_drop:NN \l_shipout_box \l_shipout_box
+% \box_set_eq_drop:NN #1 #1
% \group_end:
% \cs_set_eq:NN \protect \exp_not:N
}
@@ -666,8 +934,8 @@
% once more but this time make it a warning, because the best
% practice way is to use the request mechanism.
% \begin{macrocode}
- { \box_if_empty:NTF \l_shipout_box
- { \PackageWarning{ltshipout}{
+ { \box_if_empty:NTF #1
+ { \@latex@warning{
Shipout~ box~ was~ voided~ by~ hook,\MessageBreak
ignoring~ shipout~ box }
}
@@ -691,39 +959,54 @@
% changed) and then look at the hooks \hook{shipout/foreground}
% and \hook{shipout/background}. If either or both are non-empty
% we add a \texttt{picture} environment to the box (in the
-% foreground and or in the background) and execute the hook code
+% foreground and/or in the background) and execute the hook code
% inside that environment.
%
% \begin{macrocode}
- \@@_get_box_size:N \l_shipout_box
- \hook_if_empty:nF {shipout/foreground}
- { \@@_add_foreground_picture:n
- { \hook_use:n {shipout/foreground} } }
- \hook_if_empty:nF {shipout/background}
- { \@@_add_background_picture:n
- { \@kernel@before@shipout@background
- \hook_use:n {shipout/background} } }
+ \@@_get_box_size:N #1
+% \end{macrocode}
+% The first hook we run is the \hook{shipout/firstpage} hook. This
+% is only done once, then the \cs{@@_run_firstpage_hook:}
+% command redefines itself to do nothing. If the hook contains
+% \cs{special}s for integration at the top of the page they will be
+% temporarily stored in a safe place and added later with
+% \cs{@@_add_firstpage_specials:}.
+% \begin{macrocode}
+ \@@_run_firstpage_hook:
+% \end{macrocode}
+% Run the hooks for background and foreground or, if this
+% is called by \cs{RawShipout}, copy the box \cs{l_@@_raw_box} to
+% \cs{l_shipout_box} so that firstpage and lastpage material gets
+% added if necessary (that is always done to \cs{l_shipout_box}.
+% \begin{macrocode}
+ #3
% \end{macrocode}
-% We then run \cs{@@_execute_firstpage_hook:} that adds
+% We then run \cs{@@_add_firstpage_specials:} that adds
% the content of the hook \hook{shipout/firstpage} to the
% start of the first page (if non-empty). It is then redefined to
% do nothing on later pages.
% \begin{macrocode}
- \@@_execute_firstpage_hook:
+ \@@_add_firstpage_specials:
% \end{macrocode}
-% The we check if we have to add the \hook{shipout/lastpage} hook
+% Then we check if we have to add the \hook{shipout/lastpage} hook
+% or the corresponding kernel hook
% because we have reached the last page. This test will be false for
% all but one (and hopefully the correct) page.
+% \changes{v1.0d}{2020/11/23}{Check for both kernel and user hook (gh/431)}
% \begin{macrocode}
\int_compare:nNnT \@abspage@last = \g_shipout_readonly_int
- { \hook_if_empty:nF {shipout/lastpage}
+ { \bool_lazy_and:nnF
+ { \hook_if_empty_p:n {shipout/lastpage} }
+ { \tl_if_empty_p:N \@kernel@after@shipout@lastpage }
{ \@@_debug:n { \typeout{Executing~ lastpage~ hook~
- on~ page~ \int_use:N \g_shipout_readonly_int } }
- \_@@_add_foreground_box:n { \UseHook{shipout/lastpage}
- \@kernel@after@shipout@lastpage }
+ on~ page~ \int_use:N \g_shipout_readonly_int } }
+ \_@@_add_foreground_box:n
+ { \UseHook{shipout/lastpage}
+ \@kernel@after@shipout@lastpage }
}
\bool_gset_true:N \g_@@_lastpage_handled_bool
}
+ \@@_finalize_box:
% \end{macrocode}
% Finally we run the actual \TeX{} primitive for shipout. As that will
% expand delayed \cs{write} statements inside the page in which
@@ -732,6 +1015,21 @@
% \begin{macrocode}
\cs_set_eq:NN \protect \exp_not:N
\tex_shipout:D \box_use:N \l_shipout_box
+% \end{macrocode}
+% The \cs{l_shipout_box} may contain the firstpage material if this
+% was the very first shipout. That makes it unsuitable for reuse in
+% another shipout, so as a safety measure the next command resets
+% \cs{l_shipout_box} to its earlier state if that is necessary. On
+% later pages this is then a no-op.
+% \begin{macrocode}
+ \@@_drop_firstpage_specials:
+% \end{macrocode}
+% The \hook{shipout/after} hook (if in \verb=#4=) needs to run with
+% \cs{protect}ed commands again being executed, because that hook
+% will ``typeset'' material added at the top of the next page.
+% \begin{macrocode}
+ \set@typeset@protect
+ #4
}
}
% \end{macrocode}
@@ -746,20 +1044,69 @@
% \end{macro}
%
%
+%
+%
+% \begin{macro}{\@@_execute_raw:,
+% \@@_execute_test_level_raw:}
+%
+% This implements the ``raw'' shipout which bypasses the before,
+% foreground, background and after hooks. It follows the same pattern than
+% \cs{_@@_execute_raw:} except that it finally calls
+% \cs{_@@_execute_main_cont:Nnnn} with three empty arguments.
+% instead of the hook code.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_execute_raw: {
+ \tl_set:Nx \l_@@_group_level_tl
+ { \int_value:w \tex_currentgrouplevel:D }
+ \tex_afterassignment:D \@@_execute_test_level_raw:
+ \tex_setbox:D \l_@@_raw_box
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_execute_test_level_raw: {
+ \int_compare:nNnT
+ \l_@@_group_level_tl < \tex_currentgrouplevel:D
+ \tex_aftergroup:D \@@_execute_nohooks_cont:
+}
+% \end{macrocode}
+% Well, not totally empty arguments, we add some debugging if we
+% are actually doing a shipout.
+% \begin{macrocode}
+\cs_new:Npn \@@_execute_nohooks_cont: {
+ \@@_execute_main_cont:Nnnn \l_@@_raw_box
+ {} { \@@_debug:n{ \typeout{Doing~ raw~ shipout~ ...} }
+ \box_set_eq:NN \l_shipout_box \l_@@_raw_box } {}
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\RawShipout}
+% The interface name for raw shipout.
+% \changes{v1.0g}{2021/01/10}{Macro added}
+% \begin{macrocode}
+\cs_gset_eq:NN \RawShipout \@@_execute_raw:
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
% \begin{macro}{\@@_saved_protect:}
-% Remeber the current \cs{protect} state.
+% Remember the current \cs{protect} state.
% \begin{macrocode}
\cs_new_eq:NN \@@_saved_protect: \protect
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{shipout/before,
+% \begin{macro}{shipout/before,shipout/after,
% shipout/foreground,shipout/background,
% shipout/firstpage,
% shipout/lastpage}
% Declaring all hooks for the shipout code.
% \begin{macrocode}
\hook_new:n{shipout/before}
+\hook_new:n{shipout/after}
\hook_new:n{shipout/foreground}
\hook_new:n{shipout/background}
\hook_new:n{shipout/firstpage}
@@ -770,36 +1117,71 @@
%
%
% \begin{macro}{\@kernel@after@shipout@lastpage,
-% \@kernel@before@shipout@background}
+% \@kernel@before@shipout@background,
+% \@kernel@after@shipout@background}
% And here are the internal kernel hooks going before or after the
% public ones where needed.
+% \changes{v1.0g}{2021/01/10}{Internal hook
+% \cs{@kernel@after@shipout@background} added}
% \begin{macrocode}
\let\@kernel@after@shipout@lastpage\@empty
\let\@kernel@before@shipout@background\@empty
+\let\@kernel@after@shipout@background\@empty
% \end{macrocode}
% \end{macro}
%
%
-% \begin{macro}{\@@_execute_firstpage_hook: }
-% This command adds any specials into a box and adds that to the
-% very beginning of the first box shipped out. After that we
-% redefine it to do nothing on later pages.
+% \begin{macro}{\@@_run_firstpage_hook:}
+%
+% \changes{v1.0h}{2021/01/19}{Handling of firstpage hook altered}
+%
+% There are three commands to handle the \hook{shipout/firstpage}
+% hook:
+% \cs{@@_run_firstpage_hook:}, \cs{@@_add_firstpage_specials:} and
+% \cs{@@_drop_firstpage_specials:}.
+%
+% That hook is supposed to contain \cs{special}s and similar
+% material to be placed at the very beginning of the output page
+% and so it needs careful placing to avoid that anything else gets
+% in front of it. And this means we have to wait with this until
+% other hooks such as \hook{shipout/background} have added their
+% bits. It is also important that such \cs{special}s show up only
+% on the very first page, so if this page gets saved before
+% \cs{shipout} for later reuse, we have to make sure that they
+% aren't in the saved version.
+%
+% In addition the hook may also contain code to be executed ``first'', e.g.,
+% visible from code in \hook{shipout/background} and this conflicts
+% with adding the \cs{special}s late.
+%
+% Therefore the processing is split into different parts:
+% \cs{@@_run_firstpage_hook:} is done early and checks if there is
+% any material in the hook.
% \begin{macrocode}
-\cs_new:Npn \@@_execute_firstpage_hook: {
+\cs_new:Npn \@@_run_firstpage_hook: {
+ \hook_if_empty:nTF {shipout/firstpage}
% \end{macrocode}
-% Adding something to the beginning means adding it to the
-% background as that layer is done first in the output. Of course
-% that is only needed if the hook actually contains anything.
+% If not then we define the other two commands to do nothing.
% \begin{macrocode}
- \hook_if_empty:nF {shipout/firstpage}
- { \@@_add_background_box:n { \UseHook{shipout/firstpage} } }
+ {
+ \cs_gset_eq:NN \@@_add_firstpage_specials: \prg_do_nothing:
+ \cs_gset_eq:NN \@@_drop_firstpage_specials: \prg_do_nothing:
+ }
+% \end{macrocode}
+% If there is material we execute inside a box, which means any
+% \cs{special} will end up in that box and any other code is
+% executed and can have side effects (as long as they are global).
+% \begin{macrocode}
+ {
+ \hbox_set:Nn \l_@@_firstpage_box { \UseHook{shipout/firstpage} }
+ }
% \end{macrocode}
% Once we are here we change the definition to do nothing next time
% and we also change the command used to implement \cs{AtBeginDvi}
-% to become a warning and not add further material to a hook that
+% to become a warning and not add further material to a hook that
% is never used again.
% \begin{macrocode}
- \cs_gset_eq:NN \@@_execute_firstpage_hook: \prg_do_nothing:
+ \cs_gset_eq:NN \@@_run_firstpage_hook: \prg_do_nothing:
\cs_gset:Npn \@@_add_firstpage_material:Nn ##1 ##2 {
\@latex@warning{
First~ page~ is~ already~ shipped~ out,~ ignoring\MessageBreak
@@ -807,8 +1189,67 @@
}
}
% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_add_firstpage_specials:,\@@_drop_firstpage_specials:}
+% The \cs{@@_add_firstpage_specials:} then adds the \cs{special}s
+% stored in \cs{l_@@_firstpage_box} to the page to be shipped out
+% when the time is ready. Note that if there was no material in the
+% \hook{shipout/firstpage} hook then this command gets redefined to
+% do nothing. But for most documents there is something, e.g., some
+% PostScript header, or some meta data declaration, etc.\ so by
+% default we assume there is something to do.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_firstpage_specials: {
+% \end{macrocode}
+% First we make a copy of the \cs{l_shipout_box} that we can
+% restore it later on.
+% \begin{macrocode}
+ \box_set_eq:NN \l_@@_raw_box \l_shipout_box
+% \end{macrocode}
+% Adding something to the beginning means adding it to the
+% background as that layer is done first in the output.
+% \begin{macrocode}
+ \@@_add_background_box:n { \hbox_unpack_drop:N \l_@@_firstpage_box }
+% \end{macrocode}
+% After the actual shipout \cs{@@_drop_firstpage_specials:} is
+% run to
+% restore the earlier content of \cs{l_shipout_box} and then
+% redefines itself again to do nothing.
+%
+% As a final act we change the definition to do nothing next time.
+% \begin{macrocode}
+ \cs_gset_eq:NN \@@_add_firstpage_specials: \prg_do_nothing:
+}
+% \end{macrocode}
+%
+% The \cs{@@_drop_firstpage_specials:} is run after the shipout has
+% occurred but before the \hook{shipout/afterpage} hook is executed.
+% That is the point where we have to restore the \cs{ShipoutBox} to
+% its state without the \hook{shipout/firstpage} material.
+% \begin{macrocode}
+\cs_new:Npn \@@_drop_firstpage_specials: {
+ \box_set_eq:NN \l_shipout_box \l_@@_raw_box
+% \end{macrocode}
+% If there was no such material then \cs{@@_run_firstpage_hook:}
+% will have changed the definition to a no-op already. Otherwise
+% this is what we do here.
+% \begin{macrocode}
+ \cs_gset_eq:NN \@@_drop_firstpage_specials: \prg_do_nothing:
+ }
+% \end{macrocode}
% \end{macro}
%
+
+% \begin{macro}{\l_@@_firstpage_box}
+% The box to hold any firstpage \cs{special}s.
+% \begin{macrocode}
+\box_new:N \l_@@_firstpage_box
+% \end{macrocode}
+% \end{macro}
+
%
% \begin{macro}{\g_@@_lastpage_handled_bool}
% A boolean to signal if we have already handled the
@@ -849,8 +1290,8 @@
\dim_set:Nn \l_shipout_box_ht_dim { \box_ht:N #1 }
\dim_set:Nn \l_shipout_box_dp_dim { \box_dp:N #1 }
\dim_set:Nn \l_shipout_box_wd_dim { \box_wd:N #1 }
- \dim_set:Nn \l_shipout_box_ht_plus_dp_dim { \l_shipout_box_ht_dim +
- \l_shipout_box_dp_dim }
+ \dim_set:Nn \l_shipout_box_ht_plus_dp_dim
+ { \l_shipout_box_ht_dim + \l_shipout_box_dp_dim }
}
% \end{macrocode}
% \end{macro}
@@ -883,7 +1324,7 @@
% \begin{macro}{\l_@@_tmp_box,\l_@@_saved_badness_tl}
% We need a box for the background and foreground material and a
% token register to remember badness settings as we disable them
-% during te buildup below.
+% during the buildup below.
% \begin{macrocode}
\box_new:N \l_@@_tmp_box
\tl_new:N \l_@@_saved_badness_tl
@@ -1088,7 +1529,7 @@
% \begin{macrocode}
\cs_new:Npn \@@_picture_overlay:n #1 {
% \end{macrocode}
-% The very first time this is executed we have to initializes (and
+% The very first time this is executed we have to initialize (and
% freeze) the origins.
% \begin{macrocode}
\@@_init_page_origins:
@@ -1183,7 +1624,7 @@
%
% \begin{macro}{\g_shipout_totalpages_int,\c@totalpages}
% We count every shipout attempt (even those that are discarded) in
-% tis counter. It is not used in the code but may get used in user
+% this counter. It is not used in the code but may get used in user
% code.
% \begin{macrocode}
\int_new:N \g_shipout_totalpages_int
@@ -1207,7 +1648,7 @@
% or the statement is missing from it we initialize it with the
% largest possible number in \TeX{}. We use this as the default
% because then we are inserting the \hook{shipout/lastpage} on
-% the last page (or after the last page but not on page 1 for a
+% the last page (or after the last page) but not on page 1 for a
% multipage document.
% \begin{macrocode}
\xdef\@abspage@last{\number\maxdimen}
@@ -1219,11 +1660,11 @@
%
% Instead of using the hooks \hook{enddocument} and
% \hook{enddocument/afterlastpage} we add this code to private
-% kernel hooks to be 100\% when it is executed and to avoid
+% kernel hooks to be 100\% sure when it is executed and to avoid
% cluttering the hooks with data that is always there.
%
% Inside \cs{enddocument} there is a \cs{clearpage}. Just before
-% that we execute this code here. There is a good change that we
+% that we execute this code here. There is a good chance that we
% are on the last page. Therefore, if we don't know the value from
% the last run, we assume that the current page is the right
% one. So we set \cs{@abspage@last} and as a result the next
@@ -1307,7 +1748,7 @@
% At this point we also signal to \LaTeX{}'s endgame that a rerun is
% necessary so that an appropriate message can be shown on the
% terminal. We do this by simply defining a command used as a flag and
-% tested \cs{enddocument}.
+% tested in \cs{enddocument}.
% \begin{macrocode}
\cs_gset_eq:NN \@extra@page@added \relax
}
@@ -1380,7 +1821,8 @@
% defined so we better not use \cs{cs_new_protected:Npn} here.
% \changes{v1.0d}{2020/11/24}{Support for roll forward (gh/434)}
% \begin{macrocode}
-\cs_set_protected:Npn \AtBeginDvi {\@@_add_firstpage_material:Nn \AtBeginDvi}
+\cs_set_protected:Npn \AtBeginDvi
+ {\@@_add_firstpage_material:Nn \AtBeginDvi}
% \end{macrocode}
% \end{macro}
%
@@ -1409,6 +1851,7 @@
% \@expl@@@shipout@add@foreground@picture@@n}
% Some internals needed elsewhere.
%
+% \InternalDetectionOff
% \begin{macrocode}
\cs_set_eq:NN \@expl@@@shipout@add@firstpage@material@@Nn
\__shipout_add_firstpage_material:Nn
@@ -1433,6 +1876,7 @@
\cs_set_eq:NN \@expl@@@shipout@add@foreground@picture@@n
\__shipout_add_foreground_picture:n
% \end{macrocode}
+% \InternalDetectionOn
% \end{macro}
%
% \begin{macrocode}
@@ -1449,7 +1893,7 @@
%
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\shipout}{The hook management (shipout)}%
+%<latexrelease> {\shipout}{Hook management (shipout)}%
%<latexrelease>
% \end{macrocode}
% If we roll forward then \cs{tex\_shipout:D} may not be defined in
@@ -1462,6 +1906,7 @@
%<latexrelease> \csname tex_shipout:D\endcsname
%<latexrelease>\fi
%<latexrelease>
+%<latexrelease>\let \RawShipout\@undefined
%<latexrelease>\let \ShipoutBox\@undefined
%<latexrelease>\let \ReadonlyShipoutCounter \@undefined
%<latexrelease>\let \c@totalpages \@undefined
@@ -1485,23 +1930,13 @@
%<latexrelease>\let \ShipoutBoxDepth \@undefined
%<latexrelease>\let \ShipoutBoxWidth \@undefined
%<latexrelease>
-%<latexrelease>\let \AtBeginShipoutDiscard \@undefined
-%<latexrelease>
-%<latexrelease>\let \AtBeginShipoutAddToBox \@undefined
-%<latexrelease>\let \AtBeginShipoutAddToBoxForeground \@undefined
-%<latexrelease>\let \AtBeginShipoutUpperLeft \@undefined
-%<latexrelease>\let \AtBeginShipoutUpperLeftForeground \@undefined
-%<latexrelease>
% \end{macrocode}
% We do not undo a substitution when rolling back. As the file
% support gets undone the underlying data is no longer used (and
-% sufficiently obscure that should not interfer with existing
+% sufficiently obscure that it should not interfere with existing
% commands) and properly removing it would mean we need to make the
-% \cs{unclare@...} and its support macros available in all earlier
+% \cs{undeclare@...} and its support macros available in all earlier
% kernel releases which is pointless (and actually worse).
-% \begin{macrocode}
-%\undeclare@file@substitution{everyshi.sty}
-% \end{macrocode}
%
% \begin{macrocode}
%<latexrelease>
@@ -1509,7 +1944,7 @@
% \end{macrocode}
% We do not reenable a disabled package load when rolling back. As the file
% support gets undone the underlying data is no longer checked (and
-% sufficiently obscure that it should not interfer with existing
+% sufficiently obscure that it should not interfere with existing
% commands) and properly removing it would mean we need to make the
% \cs{reenable@package@load} command available in all earlier
% kernel releases which is pointless (and actually worse).
@@ -1585,8 +2020,8 @@
% \begin{macrocode}
%<*atbegshi-ltx>
\ProvidesPackage{atbegshi-ltx}
- [2020/08/17 v1.0a
- Emulation of the original atbegshi package^^Jwith kernel methods]
+ [2021/01/10 v1.0c
+ Emulation of the original atbegshi^^Jpackage with kernel methods]
% \end{macrocode}
%
%
@@ -1597,6 +2032,7 @@
% \end{macro}
%
%
+%
% \begin{macro}{\AtBeginShipoutInit}
% Compatibility only, we aren't delaying \ldots
% \begin{macrocode}
@@ -1650,15 +2086,27 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\AtBeginShipoutOriginalShipout}
+% This offers the raw \cs{shipout} primitive of the engine. A page
+% shipped out with this is not counted by
+% \cs{ReadonlyShipoutCounter} counter and thus the mechanism to
+% place \cs{special}s at the very end of the output might fail,
+% etc. It should therefore not be used in new applications but is
+% only provided to allow running legacy code. For new code use the
+% commands provided by the kernel instead.
+% \begin{macrocode}
+\ExplSyntaxOn
+\cs_new_eq:NN \AtBeginShipoutOriginalShipout \tex_shipout:D
+% \end{macrocode}
+% \end{macro}
%
%
-% \begin{macro}{\ShipoutBoxHeight,\ShipoutBoxWidth,\ShipoutoBoxDepth}
+% \begin{macro}{\ShipoutBoxHeight,\ShipoutBoxWidth,\ShipoutBoxDepth}
% This is somewhat different from the original in \pkg{atbegshi}
% where \cs{ShipoutBoxHeight} etc.\ only holds the
% \verb=\the\ht<box>= value. This may has some implications in some
% use cases and if that is a problem then it might need changing.
% \begin{macrocode}
-\ExplSyntaxOn
\cs_new:Npn \ShipoutBoxHeight { \dim_use:N \l_shipout_box_ht_dim }
\cs_new:Npn \ShipoutBoxDepth { \dim_use:N \l_shipout_box_dp_dim }
\cs_new:Npn \ShipoutBoxWidth { \dim_use:N \l_shipout_box_wd_dim }
@@ -1685,56 +2133,8 @@
%
% \subsection{Package \pkg{everyshi} emulation}
%
-% \begin{macrocode}
-%<*everyshi-ltx>
-% \end{macrocode}
-%
-% \begin{macrocode}
-\ProvidesPackage{everyshi-ltx}
- [2020/08/17 v1.0a
- Emulation of the original everyshi package^^Jwith kernel methods]
-% \end{macrocode}
-%
-% \begin{macro}{\EveryShipout,\AtNextShipout}
-% This package has only two public commands so simulating it is easy:
-% \begin{macrocode}
-\protected \def \EveryShipout {\AddToHook{shipout/before}}
-\protected \def \AtNextShipout {\AddToHookNext{shipout/before}}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macrocode}
-% This is one difference between \pkg{everyshi} and the kernel
-% implementation, the latter does not directly use box 255.
-%
-% For usage by ordinary users this makes no difference but of a
-% package use complicated code together with \pkg{everyshi} and
-% directly manipulates box 255 then this package needs updating.
-% In most cases the updates are simple because the kernel offers
-% hooks that makes such complicated code unnecessary.
-%
-% We therefore add a little file into the adjusted package
-% \begin{macrocode}
-%%
-%% In normal circumstances the above emulation is sufficient and in
-%% all known packages (we know of) that use everyshi it either works or
-%% the packages have been adjusted.
-%%
-%% Code that directly manipulates box 255, however, might fail.
-%% If that is the case look at the shipout hooks offered now as
-%% they are normally sufficienct to avoid such minpulations (or
-%% replace box 255 with \ShipoutBox in the code.
-%%
-%</everyshi-ltx>
-% \end{macrocode}
-%
-%
-% If the package is requested we substitute the one above:
-% \begin{macrocode}
-%<*2ekernel>
-\declare@file@substitution{everyshi.sty}{everyshi-ltx.sty}
-%</2ekernel>
-% \end{macrocode}
+% This is now directly handled in that package so emulation is not
+% necessary any more.
%
%
% Rather important :-)
diff --git a/macros/latex/base/ltspace.dtx b/macros/latex/base/ltspace.dtx
index 1a672c6455..17fb0d6518 100644
--- a/macros/latex/base/ltspace.dtx
+++ b/macros/latex/base/ltspace.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/lttab.dtx b/macros/latex/base/lttab.dtx
index dedd9e5d37..48627f40a3 100644
--- a/macros/latex/base/lttab.dtx
+++ b/macros/latex/base/lttab.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -31,7 +31,7 @@
%%% From File: lttab.dtx
%<*driver>
% \fi
-\ProvidesFile{lttab.dtx}[2020/04/24 v1.1r LaTeX Kernel (Columns)]
+\ProvidesFile{lttab.dtx}[2021/04/20 v1.1s LaTeX Kernel (Columns)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{lttab.dtx}
@@ -464,7 +464,7 @@
%
% \begin{macro}{\@tabcr}
% \begin{macrocode}
-\def\@tabcr{\@stopline \@ifstar{\penalty \@M \@xtabcr}\@xtabcr}
+\protected\def\@tabcr{\@stopline \@ifstar{\penalty \@M \@xtabcr}\@xtabcr}
% \end{macrocode}
% \end{macro}
%
@@ -964,8 +964,9 @@
%
% \begin{macro}{\@arraycr}
% Array version of |\\|.
+% \changes{v1.1s}{2021/04/20}{Use \cs{protected} for \cs{\bslash} variant (gh/548)}
% \begin{macrocode}
-\def\@arraycr{%
+\protected\def\@arraycr{%
${\ifnum0=`}\fi\@ifstar\@xarraycr\@xarraycr}
% \end{macrocode}
% \end{macro}
@@ -994,8 +995,9 @@
% \end{macro}
%
% \begin{macro}{\@tabularcr}
+% \changes{v1.1s}{2021/04/20}{Use \cs{protected} for \cs{\bslash} variant (gh/548)}
% \begin{macrocode}
-\def\@tabularcr{%
+\protected\def\@tabularcr{%
{\ifnum0=`}\fi\@ifstar\@xtabularcr\@xtabularcr}
% \end{macrocode}
% \end{macro}
diff --git a/macros/latex/base/lttextcomp.dtx b/macros/latex/base/lttextcomp.dtx
index 3b6231dafd..1efc36d563 100644
--- a/macros/latex/base/lttextcomp.dtx
+++ b/macros/latex/base/lttextcomp.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2019-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2019-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -26,6 +26,9 @@
% extension .ins) which are part of the distribution.
%
% \fi
+%
+%%% From File: lttextcomp.dtx
+%
% \iffalse
%
%<*driver>
@@ -33,7 +36,7 @@
%
%
\ProvidesFile{lttextcomp.dtx}
- [2020/04/29 v1.0d LaTeX Kernel (text companion symbols)]
+ [2021/04/16 v1.0f LaTeX Kernel (text companion symbols)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -46,7 +49,7 @@
%
%
% \GetFileInfo{lttextcomp.dtx}
-% \title{Providing addtional text symbols\\
+% \title{Providing additional text symbols\\
% (previously available through the \texttt{textcomp} package)\thanks
% {This file has version number
% \fileversion\ dated \filedate}}
@@ -67,20 +70,23 @@
%
% \StopEventually{}
%
+% \changes{v1.0e}{2021/03/19}
+% {Use \cs{NewModuleRelease}}
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\NewModuleRelease{2020/02/02}{lttextcomp}
+%<latexrelease> {Text Companion symbols}
+% \end{macrocode}
%
% \begin{macro}{\oldstylenums}
% \begin{macro}{\legacyoldstylenums}
%
-%
% Preserve the old definition of \cs{oldstylenums} under a different name.
%
% This macro implements old style numerals but only works if we
% assume that the standard math fonts are used. Thus it needs
% changing in case other math encodings are used.
% \begin{macrocode}
-%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/02/02}%
-%<latexrelease> {\oldstylenums}{Old style numerals}%
\DeclareRobustCommand\legacyoldstylenums[1]{%
\begingroup
% \end{macrocode}
@@ -112,7 +118,7 @@
\mathgroup\symletters #1%
\else
% \end{macrocode}
-% The \cs{CheckEncodingSubset} is discused below.
+% The \cs{CheckEncodingSubset} is discussed below.
% \begin{macrocode}
\CheckEncodingSubset\@use@text@encoding{TS1}\tc@oldstylesubst2{{#1}}%
\fi
@@ -154,44 +160,6 @@
% \end{macrocode}
% \end{macro}
%
-%
-% \begin{macrocode}
-%</2ekernel|latexrelease>
-%<latexrelease>\EndIncludeInRelease
-%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\oldstylenums}{Old style numerals}%
-%<latexrelease>
-%<latexrelease>\DeclareRobustCommand\oldstylenums[1]{%
-%<latexrelease> \begingroup
-%<latexrelease> \spaceskip\fontdimen\tw@\font
-%<latexrelease> \usefont{OML}{\rmdefault}{\f@series}{it}%
-%<latexrelease> \mathgroup\symletters #1%
-%<latexrelease> \endgroup
-%<latexrelease>}
-%<latexrelease>\let\legacyoldstylenums\@undefined
-%<latexrelease>\def\textcompsubstdefault{cmr}
-%<latexrelease>
-%<latexrelease>\EndIncludeInRelease
-% \end{macrocode}
-%
-%
-
-
-
-
-
-% Everything else in the this file got introduced 2020/02/02, so we do a
-% single rollback (for now).
-% \begin{macrocode}
-%<*2ekernel>
-%</2ekernel>
-%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/02/02}%
-%<latexrelease> {\DeclareEncodingSubset}{Text companion symbols}%
-% \end{macrocode}
-%
-%
-%
% \begin{macro}{\DeclareEncodingSubset}
%
% The declaration takes 3 mandatory arguments: an \emph{encoding}
@@ -200,7 +168,7 @@
% 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.
%
-% For \texttt{TS1} the numbers have been choosen in a way that most
+% For \texttt{TS1} the numbers have been chosen in a way that most
% fonts can be fairly correctly categorized, but the default
% settings are always conservative, that is they may claim that
% less glyphs are supported than there actually are.
@@ -362,13 +330,14 @@
}
% \end{macrocode}
% \end{macro}
-
-
-
-
+%
+%
+%
+%
+%
% \begin{macro}{\tc@fake@euro}
% |\tc@fake@euro| is an example of a ``fake'' definition to use in arg |#3| of
-% |\CheckEncodingSubset| when a symbol is not available in a
+% the command |\CheckEncodingSubset| when a symbol is not available in a
% certain font family. Here we produce a poor man's Euro symbol by combining
% a ``C'' with a ``=''.
% \begin{macrocode}
@@ -386,10 +355,10 @@
}
% \end{macrocode}
% \end{macro}
-
-
-
-
+%
+%
+%
+%
% \begin{macro}{\tc@check@symbol}
% \begin{macro}{\tc@check@accent}
% These are two abbreviations that we use below to check symbols
@@ -401,21 +370,22 @@
% to ensure that |\textcurrency| is only typeset if the current
% font has a \texttt{TS1} subset id of less than 3. Otherwise
% |\tc@error| is called telling the user that for this font family
-% |\textcurreny| is not available.
+% |\textcurrency| is not available.
% \begin{macrocode}
\def\tc@check@symbol{\CheckEncodingSubset\UseTextSymbol{TS1}\tc@subst}
% \end{macrocode}
%
-% Accents and been mad an error in the \texttt{textcomp} package when
+% Accents have been made an error in the \texttt{textcomp} package when
% not available. Now that we provide the functionality in the
-% kernel we avoid the eror by swapping in a \texttt{T1} accent if
+% kernel we avoid the error by swapping in a \texttt{T1} accent if
% the \texttt{TS1} accent is not available.
% \begin{macrocode}
%\def\tc@check@accent{\CheckEncodingSubset\UseTextAccent{TS1}\tc@error}
% \end{macrocode}
%
% \begin{macrocode}
-\def\tc@check@accent#1{\CheckEncodingSubset\UseTextAccent{TS1}{\tc@swap@accent#1}}
+\def\tc@check@accent#1{\CheckEncodingSubset\UseTextAccent
+ {TS1}{\tc@swap@accent#1}}
\def\tc@swap@accent#1#2{\UseTextAccent{T1}#1}
% \end{macrocode}
% \end{macro}
@@ -430,17 +400,17 @@
%
% \begin{macrocode}
\DeclareTextSymbolDefault{\textdollar}{TS1}
-\UndeclareTextCommand{\textdollar} {OT1} % don't use the OT1 def any longer
+\UndeclareTextCommand{\textdollar}{OT1} % don't use the OT1 def any longer
% \end{macrocode}
%
% \begin{macrocode}
\DeclareTextSymbolDefault{\textsterling}{TS1}
-\UndeclareTextCommand{\textsterling}{OT1} % don't use the OT1 def any longer
+\UndeclareTextCommand{\textsterling}{OT1}% don't use the OT1 def any longer
% \end{macrocode}
%
% \begin{macrocode}
\DeclareTextSymbolDefault{\textperthousand}{TS1}
-\UndeclareTextCommand{\textperthousand}{T1} % don't use the T1 def
+\UndeclareTextCommand{\textperthousand}{T1} % don't use the T1 def
% \end{macrocode}
% Using \cs{UndeclareTextCommand} above is enough only if the
% encoding definition files are not reloaded afterwards. In the
@@ -462,9 +432,9 @@
% \end{macrocode}
%
% And here are the other \texttt{TS1} glyphs that are implemented
-% by every font (or nearly everyone---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 one or two fonts.
+% because they aren't around in some fonts.
% \begin{macrocode}
%%\DeclareTextSymbolDefault{\textbardbl}{TS1} % subst in sub-enc 9 above
\DeclareTextSymbolDefault{\textbrokenbar}{TS1}
@@ -541,31 +511,49 @@
%
% \begin{macrocode}
\ifx\Umathcode\@undefined
- \DeclareTextCommandDefault{\capitalacute} {\tc@check@accent{\'}2\capitalacute}
- \DeclareTextCommandDefault{\capitalbreve} {\tc@check@accent{\u}2\capitalbreve}
- \DeclareTextCommandDefault{\capitalcaron} {\tc@check@accent{\v}2\capitalcaron}
- \DeclareTextCommandDefault{\capitalcedilla} {\tc@check@accent{\c}2\capitalcedilla}
- \DeclareTextCommandDefault{\capitalcircumflex} {\tc@check@accent{\^}2\capitalcircumflex}
- \DeclareTextCommandDefault{\capitaldieresis} {\tc@check@accent{\"}2\capitaldieresis}
- \DeclareTextCommandDefault{\capitaldotaccent} {\tc@check@accent{\.}2\capitaldotaccent}
- \DeclareTextCommandDefault{\capitalgrave} {\tc@check@accent{\`}2\capitalgrave}
- \DeclareTextCommandDefault{\capitalhungarumlaut}{\tc@check@accent{\H}2\capitalhungarumlaut}
- \DeclareTextCommandDefault{\capitalmacron} {\tc@check@accent{\=}2\capitalmacron}
- \DeclareTextCommandDefault{\capitalogonek} {\tc@check@accent{\k}2\capitalogonek}
- \DeclareTextCommandDefault{\capitalring} {\tc@check@accent{\r}2\capitalring}
- \DeclareTextCommandDefault{\capitaltie} {\tc@check@accent{\t}2\capitaltie}
- \DeclareTextCommandDefault{\capitaltilde} {\tc@check@accent{\~}2\capitaltilde}
+ \DeclareTextCommandDefault{\capitalacute}
+ {\tc@check@accent{\'}2\capitalacute}
+ \DeclareTextCommandDefault{\capitalbreve}
+ {\tc@check@accent{\u}2\capitalbreve}
+ \DeclareTextCommandDefault{\capitalcaron}
+ {\tc@check@accent{\v}2\capitalcaron}
+ \DeclareTextCommandDefault{\capitalcedilla}
+ {\tc@check@accent{\c}2\capitalcedilla}
+ \DeclareTextCommandDefault{\capitalcircumflex}
+ {\tc@check@accent{\^}2\capitalcircumflex}
+ \DeclareTextCommandDefault{\capitaldieresis}
+ {\tc@check@accent{\"}2\capitaldieresis}
+ \DeclareTextCommandDefault{\capitaldotaccent}
+ {\tc@check@accent{\.}2\capitaldotaccent}
+ \DeclareTextCommandDefault{\capitalgrave}
+ {\tc@check@accent{\`}2\capitalgrave}
+ \DeclareTextCommandDefault{\capitalhungarumlaut}
+ {\tc@check@accent{\H}2\capitalhungarumlaut}
+ \DeclareTextCommandDefault{\capitalmacron}
+ {\tc@check@accent{\=}2\capitalmacron}
+ \DeclareTextCommandDefault{\capitalogonek}
+ {\tc@check@accent{\k}2\capitalogonek}
+ \DeclareTextCommandDefault{\capitalring}
+ {\tc@check@accent{\r}2\capitalring}
+ \DeclareTextCommandDefault{\capitaltie}
+ {\tc@check@accent{\t}2\capitaltie}
+ \DeclareTextCommandDefault{\capitaltilde}
+ {\tc@check@accent{\~}2\capitaltilde}
% \end{macrocode}
% For \cs{newtie} and \cs{capitalnewtie} this is actually wrong, they should pick up
% the accent from the substitution font (not done yet).
% \begin{macrocode}
- \DeclareTextCommandDefault{\newtie} {\tc@check@accent{\t}2\newtie}
- \DeclareTextCommandDefault{\capitalnewtie} {\tc@check@accent{\t}2\capitalnewtie}
+ \DeclareTextCommandDefault{\newtie}
+ {\tc@check@accent{\t}2\newtie}
+ \DeclareTextCommandDefault{\capitalnewtie}
+ {\tc@check@accent{\t}2\capitalnewtie}
% \end{macrocode}
%
% In Unicode engines we just execute the simple accents:
-% \changes{v1.0c}{2020/02/10}{Use \cs{@tabacckludge} for tabbing where necessary (gh/271)}
-% \changes{v1.0d}{2020/04/29}{Make all captial accents text commands for hyperref (gh/332)}
+% \changes{v1.0c}{2020/02/10}{Use \cs{@tabacckludge} for
+% tabbing where necessary (gh/271)}
+% \changes{v1.0d}{2020/04/29}{Make all capital accents text
+% commands for hyperref (gh/332)}
% \begin{macrocode}
\else
\DeclareTextCommandDefault\capitalacute{\@tabacckludge'}
@@ -593,8 +581,10 @@
% The next two symbols exist in some fonts (faked?), but we ignore
% that to keep the subsets reasonable compact and most important linear.
% \begin{macrocode}
-\DeclareTextCommandDefault{\textlbrackdbl} {\tc@check@symbol2\textlbrackdbl}
-\DeclareTextCommandDefault{\textrbrackdbl} {\tc@check@symbol2\textrbrackdbl}
+\DeclareTextCommandDefault{\textlbrackdbl}
+ {\tc@check@symbol2\textlbrackdbl}
+\DeclareTextCommandDefault{\textrbrackdbl}
+ {\tc@check@symbol2\textrbrackdbl}
% \end{macrocode}
%
%
@@ -603,72 +593,118 @@
% claim they aren't in sub-encoding 2 as that's true for most
% fonts.
% \begin{macrocode}
-\DeclareTextCommandDefault{\texteightoldstyle} {\tc@check@symbol2\texteightoldstyle}
-\DeclareTextCommandDefault{\textfiveoldstyle} {\tc@check@symbol2\textfiveoldstyle}
-\DeclareTextCommandDefault{\textfouroldstyle} {\tc@check@symbol2\textfouroldstyle}
-\DeclareTextCommandDefault{\textnineoldstyle} {\tc@check@symbol2\textnineoldstyle}
-\DeclareTextCommandDefault{\textoneoldstyle} {\tc@check@symbol2\textoneoldstyle}
-\DeclareTextCommandDefault{\textsevenoldstyle} {\tc@check@symbol2\textsevenoldstyle}
-\DeclareTextCommandDefault{\textsixoldstyle} {\tc@check@symbol2\textsixoldstyle}
-\DeclareTextCommandDefault{\textthreeoldstyle} {\tc@check@symbol2\textthreeoldstyle}
-\DeclareTextCommandDefault{\texttwooldstyle} {\tc@check@symbol2\texttwooldstyle}
-\DeclareTextCommandDefault{\textzerooldstyle} {\tc@check@symbol2\textzerooldstyle}
-% \end{macrocode}
-%
-%
-%
-% The next set of glyphs is special to TeX fonts (and available
-% with a few older PS fonts supported in the virtual fonts), but
+\DeclareTextCommandDefault{\texteightoldstyle}
+ {\tc@check@symbol2\texteightoldstyle}
+\DeclareTextCommandDefault{\textfiveoldstyle}
+ {\tc@check@symbol2\textfiveoldstyle}
+\DeclareTextCommandDefault{\textfouroldstyle}
+ {\tc@check@symbol2\textfouroldstyle}
+\DeclareTextCommandDefault{\textnineoldstyle}
+ {\tc@check@symbol2\textnineoldstyle}
+\DeclareTextCommandDefault{\textoneoldstyle}
+ {\tc@check@symbol2\textoneoldstyle}
+\DeclareTextCommandDefault{\textsevenoldstyle}
+ {\tc@check@symbol2\textsevenoldstyle}
+\DeclareTextCommandDefault{\textsixoldstyle}
+ {\tc@check@symbol2\textsixoldstyle}
+\DeclareTextCommandDefault{\textthreeoldstyle}
+ {\tc@check@symbol2\textthreeoldstyle}
+\DeclareTextCommandDefault{\texttwooldstyle}
+ {\tc@check@symbol2\texttwooldstyle}
+\DeclareTextCommandDefault{\textzerooldstyle}
+ {\tc@check@symbol2\textzerooldstyle}
+% \end{macrocode}
+%
+%
+%
+% The next set of glyphs is special to \TeX{} fonts (and available
+% with a few older PS fonts supported through virtual fonts), but
% not any longer in the majority of fonts provided through
% autoinst, so we pretend there aren't available in sub-encoding 2
% and below.
% \begin{macrocode}
-\DeclareTextCommandDefault{\textacutedbl} {\tc@check@symbol2\textacutedbl}
-\DeclareTextCommandDefault{\textasciiacute} {\tc@check@symbol2\textasciiacute}
-\DeclareTextCommandDefault{\textasciibreve} {\tc@check@symbol2\textasciibreve}
-\DeclareTextCommandDefault{\textasciicaron} {\tc@check@symbol2\textasciicaron}
-\DeclareTextCommandDefault{\textasciidieresis} {\tc@check@symbol2\textasciidieresis}
-\DeclareTextCommandDefault{\textasciigrave} {\tc@check@symbol2\textasciigrave}
-\DeclareTextCommandDefault{\textasciimacron} {\tc@check@symbol2\textasciimacron}
-\DeclareTextCommandDefault{\textgravedbl} {\tc@check@symbol2\textgravedbl}
-\DeclareTextCommandDefault{\texttildelow} {\tc@check@symbol2\texttildelow}
+\DeclareTextCommandDefault{\textacutedbl}
+ {\tc@check@symbol2\textacutedbl}
+\DeclareTextCommandDefault{\textasciiacute}
+ {\tc@check@symbol2\textasciiacute}
+\DeclareTextCommandDefault{\textasciibreve}
+ {\tc@check@symbol2\textasciibreve}
+\DeclareTextCommandDefault{\textasciicaron}
+ {\tc@check@symbol2\textasciicaron}
+\DeclareTextCommandDefault{\textasciidieresis}
+ {\tc@check@symbol2\textasciidieresis}
+\DeclareTextCommandDefault{\textasciigrave}
+ {\tc@check@symbol2\textasciigrave}
+\DeclareTextCommandDefault{\textasciimacron}
+ {\tc@check@symbol2\textasciimacron}
+\DeclareTextCommandDefault{\textgravedbl}
+ {\tc@check@symbol2\textgravedbl}
+\DeclareTextCommandDefault{\texttildelow}
+ {\tc@check@symbol2\texttildelow}
% \end{macrocode}
%
%
% Finally those below are only available in CM-based fonts but in
% no font that has its origin outside of the \TeX{} world.
% \begin{macrocode}
-\DeclareTextCommandDefault{\textbaht} {\tc@check@symbol2\textbaht}
-\DeclareTextCommandDefault{\textbigcircle} {\tc@check@symbol2\textbigcircle}
-\DeclareTextCommandDefault{\textborn} {\tc@check@symbol2\textborn}
-\DeclareTextCommandDefault{\textcentoldstyle} {\tc@check@symbol2\textcentoldstyle}
-\DeclareTextCommandDefault{\textcircledP} {\tc@check@symbol2\textcircledP}
-\DeclareTextCommandDefault{\textcopyleft} {\tc@check@symbol2\textcopyleft}
-\DeclareTextCommandDefault{\textdblhyphenchar} {\tc@check@symbol2\textdblhyphenchar}
-\DeclareTextCommandDefault{\textdblhyphen} {\tc@check@symbol2\textdblhyphen}
-\DeclareTextCommandDefault{\textdied} {\tc@check@symbol2\textdied}
-\DeclareTextCommandDefault{\textdiscount} {\tc@check@symbol2\textdiscount}
-\DeclareTextCommandDefault{\textdivorced} {\tc@check@symbol2\textdivorced}
-\DeclareTextCommandDefault{\textdollaroldstyle} {\tc@check@symbol2\textdollaroldstyle}
-\DeclareTextCommandDefault{\textguarani} {\tc@check@symbol2\textguarani}
-\DeclareTextCommandDefault{\textleaf} {\tc@check@symbol2\textleaf}
-\DeclareTextCommandDefault{\textlquill} {\tc@check@symbol2\textlquill}
-\DeclareTextCommandDefault{\textmarried} {\tc@check@symbol2\textmarried}
-\DeclareTextCommandDefault{\textmho} {\tc@check@symbol2\textmho}
-\DeclareTextCommandDefault{\textmusicalnote} {\tc@check@symbol2\textmusicalnote}
-\DeclareTextCommandDefault{\textnaira} {\tc@check@symbol2\textnaira}
-\DeclareTextCommandDefault{\textopenbullet} {\tc@check@symbol2\textopenbullet}
-\DeclareTextCommandDefault{\textpeso} {\tc@check@symbol2\textpeso}
-\DeclareTextCommandDefault{\textpilcrow} {\tc@check@symbol2\textpilcrow}
-\DeclareTextCommandDefault{\textrecipe} {\tc@check@symbol2\textrecipe}
-\DeclareTextCommandDefault{\textreferencemark} {\tc@check@symbol2\textreferencemark}
-\DeclareTextCommandDefault{\textrquill} {\tc@check@symbol2\textrquill}
-\DeclareTextCommandDefault{\textservicemark} {\tc@check@symbol2\textservicemark}
-\DeclareTextCommandDefault{\textsurd} {\tc@check@symbol2\textsurd}
+\DeclareTextCommandDefault{\textbaht}
+ {\tc@check@symbol2\textbaht}
+\DeclareTextCommandDefault{\textbigcircle}
+ {\tc@check@symbol2\textbigcircle}
+\DeclareTextCommandDefault{\textborn}
+ {\tc@check@symbol2\textborn}
+\DeclareTextCommandDefault{\textcentoldstyle}
+ {\tc@check@symbol2\textcentoldstyle}
+\DeclareTextCommandDefault{\textcircledP}
+ {\tc@check@symbol2\textcircledP}
+\DeclareTextCommandDefault{\textcopyleft}
+ {\tc@check@symbol2\textcopyleft}
+\DeclareTextCommandDefault{\textdblhyphenchar}
+ {\tc@check@symbol2\textdblhyphenchar}
+\DeclareTextCommandDefault{\textdblhyphen}
+ {\tc@check@symbol2\textdblhyphen}
+\DeclareTextCommandDefault{\textdied}
+ {\tc@check@symbol2\textdied}
+\DeclareTextCommandDefault{\textdiscount}
+ {\tc@check@symbol2\textdiscount}
+\DeclareTextCommandDefault{\textdivorced}
+ {\tc@check@symbol2\textdivorced}
+\DeclareTextCommandDefault{\textdollaroldstyle}
+ {\tc@check@symbol2\textdollaroldstyle}
+\DeclareTextCommandDefault{\textguarani}
+ {\tc@check@symbol2\textguarani}
+\DeclareTextCommandDefault{\textleaf}
+ {\tc@check@symbol2\textleaf}
+\DeclareTextCommandDefault{\textlquill}
+ {\tc@check@symbol2\textlquill}
+\DeclareTextCommandDefault{\textmarried}
+ {\tc@check@symbol2\textmarried}
+\DeclareTextCommandDefault{\textmho}
+ {\tc@check@symbol2\textmho}
+\DeclareTextCommandDefault{\textmusicalnote}
+ {\tc@check@symbol2\textmusicalnote}
+\DeclareTextCommandDefault{\textnaira}
+ {\tc@check@symbol2\textnaira}
+\DeclareTextCommandDefault{\textopenbullet}
+ {\tc@check@symbol2\textopenbullet}
+\DeclareTextCommandDefault{\textpeso}
+ {\tc@check@symbol2\textpeso}
+\DeclareTextCommandDefault{\textpilcrow}
+ {\tc@check@symbol2\textpilcrow}
+\DeclareTextCommandDefault{\textrecipe}
+ {\tc@check@symbol2\textrecipe}
+\DeclareTextCommandDefault{\textreferencemark}
+ {\tc@check@symbol2\textreferencemark}
+\DeclareTextCommandDefault{\textrquill}
+ {\tc@check@symbol2\textrquill}
+\DeclareTextCommandDefault{\textservicemark}
+ {\tc@check@symbol2\textservicemark}
+\DeclareTextCommandDefault{\textsurd}
+ {\tc@check@symbol2\textsurd}
% \end{macrocode}
%
% The \cs{textpertenthousand} also belongs in this group but here
-% we have a choice: in T1 there is definition for
+% we have a choice: in T1 there is a definition for
% \cs{textpertenthousand} making the symbol up from \% and
% \verb=\char 24= (twice) but in many fonts that char doesn't exist
% and the slot is reused for random ligatures. So better not use it
@@ -679,7 +715,8 @@
% Alternatively we could just state that the symbol is unavailable in
% those fonts. For now I substitute.
% \begin{macrocode}
-\DeclareTextCommandDefault{\textpertenthousand} {\tc@check@symbol2\textpertenthousand}
+\DeclareTextCommandDefault{\textpertenthousand}
+ {\tc@check@symbol2\textpertenthousand}
\UndeclareTextCommand{\textpertenthousand}{T1}
% \end{macrocode}
%
@@ -691,8 +728,10 @@
% symbols. In the higher-numbered sub-encodings we see only a few
% dropped additionally.
% \begin{macrocode}
-\DeclareTextCommandDefault{\textlangle} {\tc@check@symbol3\textlangle}
-\DeclareTextCommandDefault{\textrangle} {\tc@check@symbol3\textrangle}
+\DeclareTextCommandDefault{\textlangle}
+ {\tc@check@symbol3\textlangle}
+\DeclareTextCommandDefault{\textrangle}
+ {\tc@check@symbol3\textrangle}
% \end{macrocode}
%
%
@@ -702,14 +741,22 @@
% \subsection{Sub-encoding \texttt{4}}
%
% \begin{macrocode}
-\DeclareTextCommandDefault{\textcolonmonetary} {\tc@check@symbol4\textcolonmonetary}
-\DeclareTextCommandDefault{\textdong} {\tc@check@symbol4\textdong}
-\DeclareTextCommandDefault{\textdownarrow} {\tc@check@symbol4\textdownarrow}
-\DeclareTextCommandDefault{\textleftarrow} {\tc@check@symbol4\textleftarrow}
-\DeclareTextCommandDefault{\textlira} {\tc@check@symbol4\textlira}
-\DeclareTextCommandDefault{\textrightarrow} {\tc@check@symbol4\textrightarrow}
-\DeclareTextCommandDefault{\textuparrow} {\tc@check@symbol4\textuparrow}
-\DeclareTextCommandDefault{\textwon} {\tc@check@symbol4\textwon}
+\DeclareTextCommandDefault{\textcolonmonetary}
+ {\tc@check@symbol4\textcolonmonetary}
+\DeclareTextCommandDefault{\textdong}
+ {\tc@check@symbol4\textdong}
+\DeclareTextCommandDefault{\textdownarrow}
+ {\tc@check@symbol4\textdownarrow}
+\DeclareTextCommandDefault{\textleftarrow}
+ {\tc@check@symbol4\textleftarrow}
+\DeclareTextCommandDefault{\textlira}
+ {\tc@check@symbol4\textlira}
+\DeclareTextCommandDefault{\textrightarrow}
+ {\tc@check@symbol4\textrightarrow}
+\DeclareTextCommandDefault{\textuparrow}
+ {\tc@check@symbol4\textuparrow}
+\DeclareTextCommandDefault{\textwon}
+ {\tc@check@symbol4\textwon}
% \end{macrocode}
%
%
@@ -720,22 +767,24 @@
%
% Most older PS fonts (supported in \TeX{} since the early nineties
% when virtual fonts became available) are sorted under this
-% sub-encoding. But in reality, many of them don't have all glpyhs
+% sub-encoding. But in reality, many of them don't have all glyphs
% that should be available in sub-encoding \texttt{5}. Instead they
% show little squares, i.e., they produce ``tofu'' if you are
% unlucky.
%
% But the coverage is so random that it is impossible to sort them
% properly and if we tried to ensure that they only typeset those
-% glyphs that are really always available wouput put them all into
-% sub-encoding \texttt{9} so that's a compromise really.
+% glyphs that are really always available, we would have to put them all into
+% sub-encoding \texttt{9}; so putting them into 5 is really a compromise.
%
-% Modern fonts that don't typeset a tofu character if a glyph is
-% missing are only cataloged as sub-encoding \texttt{5} if they
-% really support of its glyph set.
+% Modern fonts usually don't typeset a tofu character if a glyph is
+% missing. They are therefore only classified as sub-encoding \texttt{5} if they
+% really support its glyph set completely.
% \begin{macrocode}
-\DeclareTextCommandDefault{\textestimated} {\tc@check@symbol5\textestimated}
-\DeclareTextCommandDefault{\textnumero} {\tc@check@symbol5\textnumero}
+\DeclareTextCommandDefault{\textestimated}
+ {\tc@check@symbol5\textestimated}
+\DeclareTextCommandDefault{\textnumero}
+ {\tc@check@symbol5\textnumero}
% \end{macrocode}
%
%
@@ -744,8 +793,10 @@
% \subsection{Sub-encoding \texttt{6}}
%
% \begin{macrocode}
-\DeclareTextCommandDefault{\textflorin} {\tc@check@symbol6\textflorin}
-\DeclareTextCommandDefault{\textcurrency} {\tc@check@symbol6\textcurrency}
+\DeclareTextCommandDefault{\textflorin}
+ {\tc@check@symbol6\textflorin}
+\DeclareTextCommandDefault{\textcurrency}
+ {\tc@check@symbol6\textcurrency}
% \end{macrocode}
%
%
@@ -753,10 +804,14 @@
% \subsection{Sub-encoding \texttt{7}}
%
% \begin{macrocode}
-\DeclareTextCommandDefault{\textfractionsolidus}{\tc@check@symbol7\textfractionsolidus}
-\DeclareTextCommandDefault{\textohm} {\tc@check@symbol7\textohm}
-\DeclareTextCommandDefault{\textmu} {\tc@check@symbol7\textmu}
-\DeclareTextCommandDefault{\textminus} {\tc@check@symbol7\textminus}
+\DeclareTextCommandDefault{\textfractionsolidus}
+ {\tc@check@symbol7\textfractionsolidus}
+\DeclareTextCommandDefault{\textohm}
+ {\tc@check@symbol7\textohm}
+\DeclareTextCommandDefault{\textmu}
+ {\tc@check@symbol7\textmu}
+\DeclareTextCommandDefault{\textminus}
+ {\tc@check@symbol7\textminus}
% \end{macrocode}
%
%
@@ -764,16 +819,19 @@
% \subsection{Sub-encoding \texttt{8}}
%
% \begin{macrocode}
-\DeclareTextCommandDefault{\textblank} {\tc@check@symbol{8}\textblank}
-\DeclareTextCommandDefault{\textinterrobangdown}{\tc@check@symbol{8}\textinterrobangdown}
-\DeclareTextCommandDefault{\textinterrobang} {\tc@check@symbol{8}\textinterrobang}
+\DeclareTextCommandDefault{\textblank}
+ {\tc@check@symbol{8}\textblank}
+\DeclareTextCommandDefault{\textinterrobangdown}
+ {\tc@check@symbol{8}\textinterrobangdown}
+\DeclareTextCommandDefault{\textinterrobang}
+ {\tc@check@symbol{8}\textinterrobang}
% \end{macrocode}
%
% Fonts with this sub-encoding don't have a Euro symbol, but
% instead of substituting we fake it.
% \begin{macrocode}
\DeclareTextCommandDefault{\texteuro}
- {\CheckEncodingSubset\UseTextSymbol{TS1}\tc@fake@euro{8}\texteuro}
+ {\CheckEncodingSubset\UseTextSymbol{TS1}\tc@fake@euro{8}\texteuro}
% \end{macrocode}
%
%
@@ -782,13 +840,20 @@
% \subsection{Sub-encoding \texttt{9} (most missing)}
%
% \begin{macrocode}
-\DeclareTextCommandDefault{\textcelsius}{\tc@check@symbol{9}\textcelsius}
-\DeclareTextCommandDefault{\textonesuperior}{\tc@check@symbol{9}\textonesuperior}
-\DeclareTextCommandDefault{\textthreequartersemdash}{\tc@check@symbol{9}\textthreequartersemdash}
-\DeclareTextCommandDefault{\textthreesuperior}{\tc@check@symbol{9}\textthreesuperior}
-\DeclareTextCommandDefault{\texttwelveudash}{\tc@check@symbol{9}\texttwelveudash}
-\DeclareTextCommandDefault{\texttwosuperior}{\tc@check@symbol{9}\texttwosuperior}
-\DeclareTextCommandDefault{\textbardbl}{\tc@check@symbol{9}\textbardbl}
+\DeclareTextCommandDefault{\textcelsius}
+ {\tc@check@symbol{9}\textcelsius}
+\DeclareTextCommandDefault{\textonesuperior}
+ {\tc@check@symbol{9}\textonesuperior}
+\DeclareTextCommandDefault{\textthreequartersemdash}
+ {\tc@check@symbol{9}\textthreequartersemdash}
+\DeclareTextCommandDefault{\textthreesuperior}
+ {\tc@check@symbol{9}\textthreesuperior}
+\DeclareTextCommandDefault{\texttwelveudash}
+ {\tc@check@symbol{9}\texttwelveudash}
+\DeclareTextCommandDefault{\texttwosuperior}
+ {\tc@check@symbol{9}\texttwosuperior}
+\DeclareTextCommandDefault{\textbardbl}
+ {\tc@check@symbol{9}\textbardbl}
% \end{macrocode}
%
%
@@ -830,20 +895,20 @@
\DeclareTextCommand{\texteightoldstyle}\UnicodeEncodingName{\oldstylenums{8}}
\DeclareTextCommand{\textnineoldstyle} \UnicodeEncodingName{\oldstylenums{9}}
% \end{macrocode}
-% These have Unicode slots so this should be integrated into TU explictly
+% These have Unicode slots so this should be integrated into TU explicitly
% \begin{macrocode}
-\DeclareTextSymbol{\textpilcrow} \UnicodeEncodingName{"00B6}
-\DeclareTextSymbol{\textborn} \UnicodeEncodingName{"002A}
-\DeclareTextSymbol{\textdied} \UnicodeEncodingName{"2020}
-\DeclareTextSymbol{\textlbrackdbl} \UnicodeEncodingName{"27E6}
-\DeclareTextSymbol{\textrbrackdbl} \UnicodeEncodingName{"27E7}
-\DeclareTextSymbol{\textguarani} \UnicodeEncodingName{"20B2}
+\DeclareTextSymbol{\textpilcrow} \UnicodeEncodingName{"00B6}
+\DeclareTextSymbol{\textborn} \UnicodeEncodingName{"002A}
+\DeclareTextSymbol{\textdied} \UnicodeEncodingName{"2020}
+\DeclareTextSymbol{\textlbrackdbl} \UnicodeEncodingName{"27E6}
+\DeclareTextSymbol{\textrbrackdbl} \UnicodeEncodingName{"27E7}
+\DeclareTextSymbol{\textguarani} \UnicodeEncodingName{"20B2}
% \end{macrocode}
% We could make \cs{textcentoldstyle} and \cs{textdollaroldstyle}
% point to dollar and cent in the Unicode encoding
% \begin{macrocode}
-%\DeclareTextSymbol{\textcentoldstyle} \UnicodeEncodingName{"00A2}
-%\DeclareTextSymbol{\textdollaroldstyle} \UnicodeEncodingName{"0024}
+%\DeclareTextSymbol{\textcentoldstyle} \UnicodeEncodingName{"00A2}
+%\DeclareTextSymbol{\textdollaroldstyle}\UnicodeEncodingName{"0024}
% \end{macrocode}
% but I think it is better to pick them up from TS1 even if that
% usually means LMR fonts
@@ -908,7 +973,8 @@
\DeclareEncodingSubset{TS1}{lmss} {1}
\DeclareEncodingSubset{TS1}{lmssq} {1}
\DeclareEncodingSubset{TS1}{lmvtt} {1}
-\DeclareEncodingSubset{TS1}{lmtt} {1} % missing TM, SM, pertenthousand for some reason
+\DeclareEncodingSubset{TS1}{lmtt} {1} % missing TM, SM and
+ % pertenthousand for some reason
% \end{macrocode}
%
% \begin{macrocode}
@@ -918,33 +984,33 @@
% \end{macrocode}
%
% \begin{macrocode}
-\DeclareEncodingSubset{TS1}{bch} {5} % tofu for blank, ohm
-\DeclareEncodingSubset{TS1}{futj} {5} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{futs} {5} % tofu for blank, ohm
-\DeclareEncodingSubset{TS1}{futx} {5} % probably (currently broken distrib)
-\DeclareEncodingSubset{TS1}{pag} {5} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{pbk} {5} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{pcr} {5} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{phv} {5} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{pnc} {5} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{pplj} {5} % tofu for blank
-\DeclareEncodingSubset{TS1}{pplx} {5} % tofu for blank
-\DeclareEncodingSubset{TS1}{ppl} {5} % tofu for blank interrobang/down
-\DeclareEncodingSubset{TS1}{ptm} {5} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{pzc} {5} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{ul9} {5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{bch} {5} % tofu for blank, ohm
+\DeclareEncodingSubset{TS1}{futj}{5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{futs}{5} % tofu for blank, ohm
+\DeclareEncodingSubset{TS1}{futx}{5} % probably (currently broken distrib)
+\DeclareEncodingSubset{TS1}{pag} {5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{pbk} {5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{pcr} {5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{phv} {5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{pnc} {5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{pplj}{5} % tofu for blank
+\DeclareEncodingSubset{TS1}{pplx}{5} % tofu for blank
+\DeclareEncodingSubset{TS1}{ppl} {5} % tofu for blank interrobang/down
+\DeclareEncodingSubset{TS1}{ptm} {5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{pzc} {5} % tofu for blank, interrobang/down, ohm
+\DeclareEncodingSubset{TS1}{ul9} {5} % tofu for blank, interrobang/down, ohm
% \end{macrocode}
%
% \begin{macrocode}
-\DeclareEncodingSubset{TS1}{dayroms} {6} % tofu for blank, interrobang/down, ohm
-\DeclareEncodingSubset{TS1}{dayrom} {6} % tofu for blank, interrobang/down, ohm
+\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)
-\DeclareEncodingSubset{TS1}{ugq} {8}
+\DeclareEncodingSubset{TS1}{augie}{8} % really only missing euro
+\DeclareEncodingSubset{TS1}{put} {8}
+\DeclareEncodingSubset{TS1}{uag} {8} % probably (currently broken distrib)
+\DeclareEncodingSubset{TS1}{ugq} {8}
% \end{macrocode}
%
% \begin{macrocode}
@@ -976,14 +1042,14 @@
% substituted.
%
% \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}{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
% \end{macrocode}
%
% \begin{macrocode}
-\DeclareEncodingSubset{TS1}{tli} {1} % with lots of tofu inside
+\DeclareEncodingSubset{TS1}{tli} {1} % with lots of tofu inside
% \end{macrocode}
%
% \begin{macrocode}
@@ -1109,7 +1175,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}{Forum-LF} {7} % the superiors are missing
% \end{macrocode}
%
% \begin{macrocode}
@@ -1156,7 +1222,7 @@
% \begin{macro}{\textlegacysection}
%
% Here are new names for the legacy symbols that \LaTeX{} used to
-% pick up from the \texttt{OMS} encoded fonts (and used dor itemize
+% pick up from the \texttt{OMS} encoded fonts (and used for itemize
% lists or footnote symbols.
%
% We go the roundabout way via separate OMS declarations so that
@@ -1199,9 +1265,19 @@
% Supporting rollback \ldots
% \begin{macrocode}
%</2ekernel|latexrelease>
-%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\DeclareEncodingSubset}{Text companion symbols}%
+%<latexrelease> {lttextcomp}{Undefine text companion symbols}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\oldstylenums[1]{%
+%<latexrelease> \begingroup
+%<latexrelease> \spaceskip\fontdimen\tw@\font
+%<latexrelease> \usefont{OML}{\rmdefault}{\f@series}{it}%
+%<latexrelease> \mathgroup\symletters #1%
+%<latexrelease> \endgroup
+%<latexrelease>}
+%<latexrelease>\let\legacyoldstylenums\@undefined
+%<latexrelease>\def\textcompsubstdefault{cmr}
%<latexrelease>
%<latexrelease>\let\DeclareEncodingSubset\@undefined
%<latexrelease>\let\CheckEncodingSubset\@undefined
@@ -1237,26 +1313,32 @@
%<latexrelease>\let\textbrokenbar\@undefined
%<latexrelease>\let\textcelsius\@undefined
%<latexrelease>\let\textcent\@undefined
-%<latexrelease>\DeclareTextCommandDefault{\textcopyright}{\textcircled{c}}
+%<latexrelease>\DeclareTextCommandDefault{\textcopyright}
+%<latexrelease> {\textcircled{c}}
%<latexrelease>\let\textdegree\@undefined
%<latexrelease>\let\textdiv\@undefined
%<latexrelease>\let\textlnot\@undefined
%<latexrelease>\let\textonehalf\@undefined
%<latexrelease>\let\textonequarter\@undefined
%<latexrelease>\let\textonesuperior\@undefined
-%<latexrelease>\DeclareTextCommandDefault{\textordfeminine}{\textsuperscript{a}}
-%<latexrelease>\DeclareTextCommandDefault{\textordmasculine}{\textsuperscript{o}}
+%<latexrelease>\DeclareTextCommandDefault{\textordfeminine}
+%<latexrelease> {\textsuperscript{a}}
+%<latexrelease>\DeclareTextCommandDefault{\textordmasculine}
+%<latexrelease> {\textsuperscript{o}}
%<latexrelease>\let\textpm\@undefined
%<latexrelease>\let\textquotesingle\@undefined
%<latexrelease>\let\textquotestraightbase\@undefined
%<latexrelease>\let\textquotestraightdblbase\@undefined
-%<latexrelease>\DeclareTextCommandDefault{\textregistered}{\textcircled{%
-%<latexrelease> \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}}
+%<latexrelease>\DeclareTextCommandDefault{\textregistered}
+%<latexrelease> {\textcircled{%
+%<latexrelease> \check@mathfonts\fontsize\sf@size\z@
+%<latexrelease> \math@fontsfalse\selectfont R}}
%<latexrelease>\let\textthreequartersemdash\@undefined
%<latexrelease>\let\textthreequarters\@undefined
%<latexrelease>\let\textthreesuperior\@undefined
%<latexrelease>\let\texttimes\@undefined
-%<latexrelease>\DeclareTextCommandDefault{\texttrademark}{\textsuperscript{TM}}
+%<latexrelease>\DeclareTextCommandDefault{\texttrademark}
+%<latexrelease> {\textsuperscript{TM}}
%<latexrelease>\let\texttwelveudash\@undefined
%<latexrelease>\let\texttwosuperior\@undefined
%<latexrelease>\let\textyen\@undefined
@@ -1386,9 +1468,7 @@
%<latexrelease>\let\textlegacyperiodcentered\@undefined
%<latexrelease>\let\textlegacysection\@undefined
%<latexrelease>
-%<latexrelease>\EndIncludeInRelease
-%<*2ekernel>
-%</2ekernel>
+%<latexrelease>\EndModuleRelease
% \end{macrocode}
%
%
@@ -1433,9 +1513,12 @@
% kernel is info only). Using the package options you can change this behavior.
% \changes{v2.0n}{2020/02/05}{Changed the package default to info (gh/262)}
% \begin{macrocode}
-\DeclareOption{error}{\gdef\tc@errorwarn{\PackageError{textcomp}}}
-\DeclareOption{warn}{\gdef\tc@errorwarn#1#2{\PackageWarning{textcomp}{#1}}}
-\DeclareOption{info}{\gdef\tc@errorwarn#1#2{\PackageInfo{textcomp}{#1}}}
+\DeclareOption{error}
+ {\gdef\tc@errorwarn{\PackageError{textcomp}}}
+\DeclareOption{warn}
+ {\gdef\tc@errorwarn#1#2{\PackageWarning{textcomp}{#1}}}
+\DeclareOption{info}
+ {\gdef\tc@errorwarn#1#2{\PackageInfo{textcomp}{#1}}}
\DeclareOption{quiet}{\gdef\tc@errorwarn#1#2{}}
% \end{macrocode}
%
@@ -1443,7 +1526,7 @@
% of the default (which, unless changes, is 9 these days), i.e., it
% no longer depends on the font in use. This is mainly there
% because it might have been used in older documents, but not
-% somehting that is recommended.
+% something that is recommended.
% \begin{macrocode}
\DeclareOption{force}{%
\def\CheckEncodingSubset#1#2#3#4#5{%
@@ -1483,7 +1566,7 @@
% This section contains the old code for the textcomp package and
% its documentation. It is only used if we roll back prior to 2020.
% Thus all the rest is mainly for historians. Note that the old
-% code categorised in the sub-encodings only into 6 classes not 10.
+% code categorized in the sub-encodings only into 6 classes not 10.
%
% \begin{macrocode}
%<*TS1oldsty>
@@ -1773,7 +1856,7 @@
% to ensure that |\textcurrency| is only typeset if the current
% font has a \texttt{TS1} subset id of less than 3. Otherwise
% |\tc@error| is called telling the user that for this font family
-% |\textcurreny| is not available.
+% |\textcurrency| is not available.
% \begin{macrocode}
\def\tc@check@symbol{\CheckEncodingSubset\UseTextSymbol{TS1}\tc@subst}
\def\tc@check@accent{\CheckEncodingSubset\UseTextAccent{TS1}\tc@error}
@@ -2008,7 +2091,7 @@
%
% Finally input the encoding-specific definitions for
% \texttt{TS1} thus making the top-level definitions
-% optimised for this encoding (and not for the default
+% optimized for this encoding (and not for the default
% encoding).
% \changes{v1.9o}{1998/03/20}{Load decls after defaults for speed.}
% \begin{macrocode}
diff --git a/macros/latex/base/ltthm.dtx b/macros/latex/base/ltthm.dtx
index 4e3c51ab77..00fe97c77a 100644
--- a/macros/latex/base/ltthm.dtx
+++ b/macros/latex/base/ltthm.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltvers.dtx b/macros/latex/base/ltvers.dtx
index c42a126a31..af0688b887 100644
--- a/macros/latex/base/ltvers.dtx
+++ b/macros/latex/base/ltvers.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltvers.dtx}
- [2020/03/02 v1.1e LaTeX Kernel (Version Info)]
+ [2021/04/16 v1.1g LaTeX Kernel (Version Info)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltvers.dtx}
@@ -112,10 +112,10 @@
%</2ekernel>
%<latexrelease>\edef\latexreleaseversion
%<*2ekernel|latexrelease>
- {2020-10-01}
+ {2021-06-01}
%</2ekernel|latexrelease>
%<*2ekernel>
-\def\patch@level{4}
+\def\patch@level{0}
% \end{macrocode}
%
% \begin{macro}{\development@branch@name}
@@ -125,7 +125,7 @@
% intended to help us internally when we locally install a
% format out of some development branch.
% \begin{macrocode}
-\edef\development@branch@name{}
+\edef\development@branch@name{develop \the\year-\the\month-\the\day}
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -181,28 +181,30 @@
% \begin{macrocode}
\ifnum0\ifnum\patch@level=0 \ifx\development@branch@name\@empty 1\fi\fi>0 %
\everyjob\expandafter{\the\everyjob
- \typeout{\fmtname \space<\fmtversion>}}
+ \typeout{\fmtname\space <\fmtversion>}}
\immediate
\write16{\fmtname \space<\fmtversion>}
\else\ifnum\patch@level>0
\everyjob\expandafter{\the\everyjob
- \typeout{\fmtname \space<\fmtversion> patch level \patch@level}}
+ \typeout{\fmtname\space <\fmtversion> patch level \patch@level}}
\immediate
- \write16{\fmtname \space<\fmtversion> patch level \patch@level}
+ \write16{\fmtname\space <\fmtversion> patch level \patch@level}
\else
\everyjob\expandafter{\the\everyjob
- \typeout{\fmtname \space<\fmtversion> pre-release-\number-\patch@level\space
- \ifx\development@branch@name\@undefined \else
- \ifx\development@branch@name\@empty \else
- \space (\development@branch@name\space branch)%
+ \typeout{\fmtname\space <\fmtversion>
+ pre-release-\number-\patch@level\space
+ \ifx\development@branch@name\@undefined \else
+ \ifx\development@branch@name\@empty \else
+ \space (\development@branch@name\space branch)%
\fi
\fi
}}
\immediate
- \write16{\fmtname \space<\fmtversion> pre-release-\number-\patch@level\space
- \ifx\development@branch@name\@undefined \else
- \ifx\development@branch@name\@empty \else
- \space (\development@branch@name\space branch)%
+ \write16{\fmtname\space <\fmtversion>
+ pre-release-\number-\patch@level\space
+ \ifx\development@branch@name\@undefined \else
+ \ifx\development@branch@name\@empty \else
+ \space (\development@branch@name\space branch)%
\fi
\fi
}
@@ -212,6 +214,11 @@
% \end{macrocode}
%
% \begin{macro}{\IncludeInRelease}
+% \begin{macro}{\EndIncludeInRelease}
+% \begin{macro}{\@IncludeInRelease}
+% \begin{macro}{\@IncludeInRele@se}
+% \begin{macro}{\@gobble@IncludeInRelease}
+% \begin{macro}{\@check@IncludeInRelease}
% \changes{v1.0w}{2015/02/21}
% {set \cs{@currname} empty here (in case \cs{IncludeInRelease} input early)}
% \begin{macrocode}
@@ -222,6 +229,7 @@
% \changes{v1.0m}{2015/01/17}{modified with \cs{@currname}}
% \changes{v1.0o}{2015/01/19}{Optional argument}
% \changes{v1.0q}{2015/02/19}{Swap argument order}
+% \changes{v1.1f}{2021/03/18}{Add support for usage in \cs{NewModuleRelease}}
%
% \begin{macrocode}
%<*2ekernel|latexrelease>
@@ -235,9 +243,29 @@
{There is an \string\EndIncludeRelease\space missing}%
\@includeinreleasefalse
\fi
- \kernel@ifnextchar[%
- {\@IncludeInRelease{#1}}
- {\@IncludeInRelease{#1}[#1]}}
+ \ifnum0%
+ \ifx\new@moduledate\@empty\else 1\fi
+ \ifnum \expandafter\@parse@version#1//00\@nil=0 1\fi
+ =11
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ {\finish@module@release{#1}}%
+ {\kernel@ifnextchar[%
+ {\@IncludeInRelease{#1}}
+ {\@IncludeInRelease{#1}[#1]}}}
+\def\finish@module@release#1#2#3{%
+ \toks@{[#1] #3}%
+ \ifnum\expandafter\@parse@version\new@moduledate//00\@nil
+ >\expandafter\@parse@version\fmtversion//00\@nil
+ \GenericInfo{}{Applying: \the\toks@}%
+ \else
+ \GenericInfo{}{Skipping: \the\toks@}%
+ \expandafter\gobble@finish@module@release
+ \fi}
+\long\def\gobble@finish@module@release#1\EndModuleRelease{%
+ \EndModuleRelease}
% \end{macrocode}
%
% If a specific date has not been specified in |latexrelease|
@@ -255,13 +283,13 @@
% that is actually reapplying what is already in the format, i.e.,
% it is useless and possibly allocating new registers. However, it
% makes the logic simpler so this is the way it is for now. In
-% theory we could always jump overthe first patch because that is
+% theory we could always jump over the first patch because that is
% only really needed for rolling forward. So maybe one day \dots
% \begin{macrocode}
\ifnum\expandafter\@parse@version#1//00\@nil
- >\expandafter\@parse@version\fmtversion//00\@nil
+ >\expandafter\@parse@version\fmtversion//00\@nil
\GenericInfo{}{Skipping: \the\toks@}%
- \expandafter\expandafter\expandafter\@gobble@IncludeInRelease
+ \expandafter\expandafter\expandafter\@gobble@IncludeInRelease
\else
\GenericInfo{}{Applying: \the\toks@}%
\@includeinreleasetrue
@@ -280,6 +308,9 @@
\@includeinreleasefalse
\else
\PackageError{latexrelease}{mis-matched EndIncludeInRelease}{}%
+\fi
+\if@skipping@module
+ \expandafter\new@module@skip
\fi}
% \end{macrocode}
%
@@ -294,13 +325,87 @@
#2#3\@end@check@IncludeInRelease{%
\ifx\@check@IncludeInRelease#2\else
\PackageError{latexrelease}{skipped IncludeInRelease for tag \string#2}{}%
+ \fi
+ \if@skipping@module
+ \expandafter\new@module@skip
\fi}
% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
%
+% \subsection{Declaring an all-new module}
+%
+% \begin{macro}{\if@skipping@module}
+% \begin{macro}{\NewModuleRelease}
+% \begin{macro}{\EndModuleRelease}
+% \begin{macro}{\new@module@skip}
+% \begin{macro}{\new@modulename}
+% \begin{macro}{\new@moduledate}
+%
+% When we have a whole new module, we can't roll back to a date where
+% such module exists, otherwise hundreds of \enquote{command already
+% defined} errors will pop up. But we can't skip it altogether
+% either, because the module might have changes we still want applied,
+% so a more detailed cherry-picking of code chunks have to be done.
+%
+% \changes{v1.1f}{2021/03/18}{Added \cs{NewModuleRelease}.}
+% \changes{v1.1g}{2021/04/16}
+% {\cs{NewModuleRelease} with the same arguments as \cs{IncludeInRelease}.}
% \begin{macrocode}
-%</2ekernel|latexrelease>
+\let\if@skipping@module\iffalse
+\def\@skipping@moduletrue{\let\if@skipping@module\iftrue}
+\def\@skipping@modulefalse{\let\if@skipping@module\iffalse}
+\let\new@modulename\@empty
+\let\new@moduledate\@empty
+\def\NewModuleRelease#1#2#3{%
+ \ifx\new@modulename\@empty \else
+ \@latex@error{Nested \noexpand\NewModuleRelease forbidden.}\@ehd \fi
+ \edef\new@moduledate{#1}%
+ \edef\new@modulename{#2}%
+ \GenericInfo{}{BEGIN module: \new@modulename\space (\new@moduledate)}%
+ \GenericInfo{}{ \@spaces\@spaces\@spaces\space#3\@gobble}%
+ \ifnum\sourceLaTeXdate<%
+ \expandafter\@parse@version\new@moduledate//00\@nil\relax
+ \ifnum\expandafter\@parse@version\fmtversion//00\@nil<%
+ \expandafter\@parse@version\new@moduledate//00\@nil\relax
+ \GenericInfo{}{Skipping module \new@modulename}%
+ \expandafter\expandafter
+ \expandafter\gobble@finish@module@release
+ \else
+ \GenericInfo{}{Applying module \new@modulename}
+ \@skipping@modulefalse
+ \fi
+ \else
+ \GenericInfo{}{Skipping module \new@modulename}
+ \@skipping@moduletrue
+ \expandafter\new@module@skip
+ \fi}
+\long\def\new@module@skip#1\IncludeInRelease{\IncludeInRelease}
+\def\EndModuleRelease{%
+ \ifx\new@modulename\@empty
+ \@latex@error{Extra \string\EndModuleRelease.}\@eha
+ \else
+ \GenericInfo{}{END module: \new@modulename\space (\new@moduledate)}%
+ \let\new@modulename\@empty
+ \let\new@moduledate\@empty
+ \@skipping@modulefalse
+ \fi}
% \end{macrocode}
% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
% \Finale
%
\endinput
diff --git a/macros/latex/base/ltx3info.pdf b/macros/latex/base/ltx3info.pdf
index 383b3ab3d4..8a85835a8d 100644
--- a/macros/latex/base/ltx3info.pdf
+++ b/macros/latex/base/ltx3info.pdf
Binary files differ
diff --git a/macros/latex/base/ltx3info.tex b/macros/latex/base/ltx3info.tex
index ccb4e0ed99..2a376f6431 100644
--- a/macros/latex/base/ltx3info.tex
+++ b/macros/latex/base/ltx3info.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/ltxcheck.tex b/macros/latex/base/ltxcheck.tex
index b96c884f3c..9e013bc2af 100644
--- a/macros/latex/base/ltxcheck.tex
+++ b/macros/latex/base/ltxcheck.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -29,7 +29,7 @@
%
% \iffalse
%% File `ltxcheck.tex'.
-%% Copyright (C) 1994-1997 LaTeX3 project, David Carlisle
+%% Copyright (C) 1994-1997 LaTeX Project, David Carlisle
%%
% LaTeX Test File.
% ================
diff --git a/macros/latex/base/ltxdoc.dtx b/macros/latex/base/ltxdoc.dtx
index 0c7130c371..7a21f7d871 100644
--- a/macros/latex/base/ltxdoc.dtx
+++ b/macros/latex/base/ltxdoc.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -30,7 +30,7 @@
%
%<class>\NeedsTeXFormat{LaTeX2e}
%<class>\ProvidesClass{ltxdoc}
-%<class> [2020/10/04 v2.1b Standard LaTeX documentation class]
+%<class> [2020/12/05 v2.1b Standard LaTeX documentation class]
%
%<*driver>
\documentclass{ltxdoc}
@@ -484,7 +484,7 @@
% \end{macrocode}
% Set \cs{protect} to a suitable value in the index entries (we
% can't use |\set@display@protect| as that would result in different
-% numer of spaces after a command depending on the number of
+% number of spaces after a command depending on the number of
% expansion happening prior to writing the index).
% \begin{macrocode}
\begingroup
diff --git a/macros/latex/base/ltxdoc.pdf b/macros/latex/base/ltxdoc.pdf
index 9af62b008f..9308d90656 100644
--- a/macros/latex/base/ltxdoc.pdf
+++ b/macros/latex/base/ltxdoc.pdf
Binary files differ
diff --git a/macros/latex/base/ltxguide.cls b/macros/latex/base/ltxguide.cls
index f70c91dcd9..b743fd9cda 100644
--- a/macros/latex/base/ltxguide.cls
+++ b/macros/latex/base/ltxguide.cls
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 1993-2019
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -34,7 +34,7 @@
% and `LaTeX2e for class and package writers'. The changes log is at
% the end of the file.
-% Copyright 1994 1999 Alan Jeffrey and the LaTeX3 project.
+% Copyright 1994-1999 Alan Jeffrey and the LaTeX Project.
% This is a LaTeX2e document class.
diff --git a/macros/latex/base/ltxref.dtx b/macros/latex/base/ltxref.dtx
index 56ae09c165..dd482299b2 100644
--- a/macros/latex/base/ltxref.dtx
+++ b/macros/latex/base/ltxref.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltxref.dtx}
- [2020/08/23 v1.1o LaTeX Kernel (Cross Referencing)]
+ [2020/12/05 v1.1o LaTeX Kernel (Cross Referencing)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltxref.dtx}
@@ -68,10 +68,10 @@
% The user writes |\label|\marg{foo} to define the following
% cross-references:
%
-% |\ref|\marg{foo}: value of most recently incremented referencable
+% |\ref|\marg{foo}: value of most recently incremented referenceable
% counter. in the current environment. (Chapter, section,
% theorem and enumeration counters are
-% referencable, footnote counters are not.)
+% referenceable, footnote counters are not.)
%
% |\pageref|\marg{foo}: page number at which |\label{foo}| command
% appeared. where foo can be any string of characters not
@@ -98,7 +98,7 @@
\message{x-ref,}
% \end{macrocode}
%
-% This is implemented as follows. A referencable counter CNT is
+% This is implemented as follows. A referenceable counter CNT is
% incremented by the command \refstepcounter{CNT} , which sets
% \@currentlabel == {CNT}{eval(\p@cnt\theCNT)}. The command
% \label{FOO} then writes the following on file \@auxout :
diff --git a/macros/latex/base/makeindx.dtx b/macros/latex/base/makeindx.dtx
index a149bcf86c..e8e48e60b0 100644
--- a/macros/latex/base/makeindx.dtx
+++ b/macros/latex/base/makeindx.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -28,7 +28,7 @@
% \fi
%\iffalse
% Copyright (C) 1985 by Leslie Lamport
-% Copyright (C) 1994-98 by \LaTeX3 Project and Johannes Braams
+% Copyright (C) 1994-98 by LaTeX Project and Johannes Braams
%\fi
%
% \changes{1.0b}{1994/01/21}{added a missing \cs{end\{macro\}}, a
diff --git a/macros/latex/base/makeindx.ins b/macros/latex/base/makeindx.ins
index 5e86d50579..427d4c7967 100644
--- a/macros/latex/base/makeindx.ins
+++ b/macros/latex/base/makeindx.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/makeindx.pdf b/macros/latex/base/makeindx.pdf
index c439845e4b..130d740e12 100644
--- a/macros/latex/base/makeindx.pdf
+++ b/macros/latex/base/makeindx.pdf
Binary files differ
diff --git a/macros/latex/base/manifest.txt b/macros/latex/base/manifest.txt
index 0cf27343c1..65e6f80389 100644
--- a/macros/latex/base/manifest.txt
+++ b/macros/latex/base/manifest.txt
@@ -135,6 +135,7 @@
% -----------------
%
% ltexpl.dtx -- Basic support
+% ltcmd.dtx -- Document command definition
% lthooks.dtx -- Hook management
% ltfilehook.dtx -- Hook management for file loading
% ltshipout.dtx -- Hook management for \shipout
@@ -185,6 +186,7 @@
% doc.dtx -- Package for self documenting code.
% docstrip.dtx -- Module for removing comments.
% ltxdoc.dtx -- Class file for printing documentation.
+% doc-v3beta.sty -- New version of doc, current for internal use only.
%
%
% Installation scripts for the various parts:
diff --git a/macros/latex/base/manual.pdf b/macros/latex/base/manual.pdf
index 5c746a312a..6450d27796 100644
--- a/macros/latex/base/manual.pdf
+++ b/macros/latex/base/manual.pdf
Binary files differ
diff --git a/macros/latex/base/minimal.cls b/macros/latex/base/minimal.cls
index b38e4be093..9024a23bca 100644
--- a/macros/latex/base/minimal.cls
+++ b/macros/latex/base/minimal.cls
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 1993-2019
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/modguide.pdf b/macros/latex/base/modguide.pdf
index 59433901a4..30424c7e7a 100644
--- a/macros/latex/base/modguide.pdf
+++ b/macros/latex/base/modguide.pdf
Binary files differ
diff --git a/macros/latex/base/modguide.tex b/macros/latex/base/modguide.tex
index 33af973d29..15aad3358f 100644
--- a/macros/latex/base/modguide.tex
+++ b/macros/latex/base/modguide.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -40,7 +40,7 @@
\title{Modifying \LaTeX}
-\author{\copyright~Copyright 1995, \LaTeX3 Project Team.\\
+\author{\copyright~Copyright 1995, \LaTeX\ Project Team.\\
All rights reserved.}
\date{12 December 1995}
diff --git a/macros/latex/base/newdc.ins b/macros/latex/base/newdc.ins
index 962510313c..e2ce183f05 100644
--- a/macros/latex/base/newdc.ins
+++ b/macros/latex/base/newdc.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/newlfont.dtx b/macros/latex/base/newlfont.dtx
index 91a19196a7..3b6e001075 100644
--- a/macros/latex/base/newlfont.dtx
+++ b/macros/latex/base/newlfont.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/nfssfont.dtx b/macros/latex/base/nfssfont.dtx
index ce47cb8554..554c7ae8f0 100644
--- a/macros/latex/base/nfssfont.dtx
+++ b/macros/latex/base/nfssfont.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -27,7 +27,7 @@
%
% \fi
\def\nfssfontfileversion{v2.2e}
-\def\nfssfontfiledate{2019/10/12}
+\def\nfssfontfiledate{2020/11/26}
%
% \iffalse
@@ -55,7 +55,7 @@
%
% Within the \NFSS{} distribution there is a \LaTeX{} file
% \texttt{nfssfont.tex} which can be used to test new fonts, produce
-% font tables showing all characters, etc. This is an addaption of a
+% font tables showing all characters, etc. This is an adaption of a
% program originally written by Don Knuth.
% When you run this file through \LaTeX{} you will be asked to enter
@@ -79,7 +79,7 @@
% |\help|.
%
% This is at
-% the moment only a crude addaption of the test program for the
+% the moment only a crude adaption of the test program for the
% Computer Modern fonts by Donald Knuth.
%
% \StopEventually{}
diff --git a/macros/latex/base/nfssfont.ins b/macros/latex/base/nfssfont.ins
index d6760bcfde..7d1b9cc41a 100644
--- a/macros/latex/base/nfssfont.ins
+++ b/macros/latex/base/nfssfont.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/nfssfont.pdf b/macros/latex/base/nfssfont.pdf
index 17492f3e6f..93087ad9d6 100644
--- a/macros/latex/base/nfssfont.pdf
+++ b/macros/latex/base/nfssfont.pdf
Binary files differ
diff --git a/macros/latex/base/olddc.ins b/macros/latex/base/olddc.ins
index 85cb077b59..d878507d8e 100644
--- a/macros/latex/base/olddc.ins
+++ b/macros/latex/base/olddc.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/oldlfont.dtx b/macros/latex/base/oldlfont.dtx
index c0c14f2aa2..d04ddb6323 100644
--- a/macros/latex/base/oldlfont.dtx
+++ b/macros/latex/base/oldlfont.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/preload.dtx b/macros/latex/base/preload.dtx
index fd9e03ac44..b2ca24bce5 100644
--- a/macros/latex/base/preload.dtx
+++ b/macros/latex/base/preload.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/proc.dtx b/macros/latex/base/proc.dtx
index 8db8fef7f1..7a1329fb82 100644
--- a/macros/latex/base/proc.dtx
+++ b/macros/latex/base/proc.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -28,8 +28,8 @@
% \fi
%
% \iffalse
-% Copyright (C) 1991,1992 by Leslie Lamport \and
-% Copyright (C) 1994,1995 by the \LaTeX3 project \and Johannes Braams
+% Copyright (C) 1991,1992 by Leslie Lamport and
+% Copyright (C) 1994-2020 by the LaTeX Project and Johannes Braams
%
% \changes{v1.1}{1994/01/25}{Made `proc' a document class and provide
% a .sty file for compatibility mode}
@@ -73,7 +73,7 @@
%</driver>
%<+class>\ProvidesClass{proc}
%<+style>\ProvidesFile{proc.sty}
- [2014/09/29 v1.3l
+ [2020/11/23 v1.3l
%<+class> Standard LaTeX document class]
%<+style> LaTeX 2.09 compatibility style option `proc']
% \end{macrocode}
@@ -147,7 +147,7 @@
%
% \section{Implementation}
%
-% In this case a check is needed to see wether \LaTeXe\ runs in
+% In this case a check is needed to see whether \LaTeXe\ runs in
% compatibility mode.
% \changes{v1.3i}{1994/05/27}{Added missing docstrip guard}
% \begin{macrocode}
diff --git a/macros/latex/base/proc.ins b/macros/latex/base/proc.ins
index 2c419c92b9..cfed5bd6a3 100644
--- a/macros/latex/base/proc.ins
+++ b/macros/latex/base/proc.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/proc.pdf b/macros/latex/base/proc.pdf
index 3b22d4c207..3c363516dd 100644
--- a/macros/latex/base/proc.pdf
+++ b/macros/latex/base/proc.pdf
Binary files differ
diff --git a/macros/latex/base/slides.dtx b/macros/latex/base/slides.dtx
index 8b7276f492..883e7d34f0 100644
--- a/macros/latex/base/slides.dtx
+++ b/macros/latex/base/slides.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -28,7 +28,7 @@
% \fi
%
% \iffalse
-% Copyright (C) 1994-97 LaTeX3 project, Frank Mittelbach
+% Copyright (C) 1994-97 LaTeX Project, Frank Mittelbach
% and Rainer Sch\"opf, all rights reserved.
%
% \begin{macrocode}
@@ -53,7 +53,7 @@
%<*driver>
\ProvidesFile{slides.drv}
%</driver>
- [2020/02/20 v2.4b
+ [2020/11/23 v2.4b
%<+class> Standard LaTeX document class]
%<+cmd> SLiTeX definitions]
% \end{macrocode}
@@ -220,7 +220,7 @@
% \end{quote}
%
% The code is divided into two parts, we first implement the class
-% related functions and declarations and then define lowlevel stuff
+% related functions and declarations and then define low level stuff
% that is necessary within every class. By placing such commands into
% a separate file it will be possible to share it with other slide
% classes.
@@ -288,7 +288,7 @@
% \end{macrocode}
%
% The option \Lopt{landscape} switches the values of |\paperheight|
-% and |\paperwidth|, assuming the dimensions wer given for portrait
+% and |\paperwidth|, assuming the dimensions were given for portrait
% paper.
% \begin{macrocode}
\DeclareOption{landscape}
@@ -705,7 +705,7 @@
%
% \begin{macro}{\clubpenalty}
% \begin{macro}{\widowpenalty}
-% These penalties are use to discourrage club and widow lines.
+% These penalties are use to discourage club and widow lines.
% Because we use their default values we only show them here,
% commented out.
% \begin{macrocode}
@@ -718,7 +718,7 @@
% \begin{macro}{\displaywidowpenalty}
% \begin{macro}{\predisplaypenalty}
% \begin{macro}{\postdisplaypenalty}
-% Discourrage (but not so much) widows in front of a math display
+% Discourage (but not so much) widows in front of a math display
% and forbid breaking directly in front of a display. Allow break
% after a display without a penalty. Again the default values are
% used, therefore we only show them here.
@@ -1721,7 +1721,7 @@
\if@titlepage \break \fi}
% \end{macrocode}
-% \section{Initialisation}
+% \section{Initialization}
%
% \subsection{Date}
%
@@ -2348,8 +2348,8 @@ COLOR LAYER\\[.75in]%
% any output when the |@visible| switch is false.
%
% \changes{v2.2j}{1994/03/11}{Corrected \cs{@oval}, like previous
-% \changes{v2.4a}{2016/03/29}{initialise in \cs{@oval}tests added for latex/4452}
-% change to \file{latex.dtx}.}
+% \changes{v2.4a}{2016/03/29}{Initialize in \cs{@oval}tests added for
+% latex/4452} change to \file{latex.dtx}.}
% \begin{macrocode}
\def\line(#1,#2)#3{\if@visible\@xarg #1\relax \@yarg #2\relax
\@linelen #3\unitlength
diff --git a/macros/latex/base/slides.ins b/macros/latex/base/slides.ins
index 0eaa1eb1d7..43ec2bebdf 100644
--- a/macros/latex/base/slides.ins
+++ b/macros/latex/base/slides.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
@@ -96,8 +96,8 @@ extension .ins) which are part of the distribution.
This is a generated file.
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
@@ -138,8 +138,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/slides.pdf b/macros/latex/base/slides.pdf
index d2a5303726..d26b076adb 100644
--- a/macros/latex/base/slides.pdf
+++ b/macros/latex/base/slides.pdf
Binary files differ
diff --git a/macros/latex/base/slifonts.fdd b/macros/latex/base/slifonts.fdd
index d3951cfa57..ec8b802596 100644
--- a/macros/latex/base/slifonts.fdd
+++ b/macros/latex/base/slifonts.fdd
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 1993-2019
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -30,7 +30,7 @@
%\iffalse This is a META comment
%
% File `slifonts.fdd'.
-% Copyright (C) 1989-1998 LaTeX3 project, Frank Mittelbach and
+% Copyright (C) 1989-1998 LaTeX Project, Frank Mittelbach and
% Rainer Sch\"opf, all rights reserved.
%
%<lcmss&!ec>\ProvidesFile{ot1lcmss.fd}
diff --git a/macros/latex/base/slifonts.pdf b/macros/latex/base/slifonts.pdf
index f1120069c5..f14e61508f 100644
--- a/macros/latex/base/slifonts.pdf
+++ b/macros/latex/base/slifonts.pdf
Binary files differ
diff --git a/macros/latex/base/source2e.pdf b/macros/latex/base/source2e.pdf
index 2905a8efef..73e7c309e2 100644
--- a/macros/latex/base/source2e.pdf
+++ b/macros/latex/base/source2e.pdf
Binary files differ
diff --git a/macros/latex/base/source2e.tex b/macros/latex/base/source2e.tex
index e74c424d72..abe8c1aac2 100644
--- a/macros/latex/base/source2e.tex
+++ b/macros/latex/base/source2e.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -248,8 +248,12 @@ page_precedence "rnaA"
\DocInclude{ltdefns} % Initial definitions.
+ \DocInclude{ltcmd} % Document command creation (was xparse)
+
\DocInclude{lthooks} % Hook management (L3 module)
+ \DocInclude{ltcmdhooks}% Hook management for commands (L3 module)
+
\DocInclude{ltalloc} % Allocation of counters and others.
\DocInclude{ltcntrl} % Program control macros.
@@ -258,6 +262,8 @@ page_precedence "rnaA"
\DocInclude{ltpar} % Paragraphs.
+ \DocInclude{ltpara} % Paragraph hooks (L3 module)
+
\DocInclude{ltspace} % Spacing, line and page breaking.
\DocInclude{ltlogos} % Logos.
diff --git a/macros/latex/base/source2edoc.cls b/macros/latex/base/source2edoc.cls
index e06108230d..ba6acf9f80 100644
--- a/macros/latex/base/source2edoc.cls
+++ b/macros/latex/base/source2edoc.cls
@@ -2,7 +2,7 @@
% This class is buggy and needs fixing
\ProvidesClass{source2edoc}
- [2020/12/02 v0.2 Quick hack to typeset source2.tex
+ [2021/01/14 v0.2b Quick hack to typeset source2.tex
(not usable for anything else and buggy -- will vanish again)!]
\LoadClass{l3doc}
@@ -106,6 +106,31 @@
\fi
\cs_set_eq:NN \@auxout \@mainaux
}
+
+
+% change the setup here: we have a lot of long names so better run raggeded
+
+\cs_set_protected:Npn \__codedoc_macro_end_style:n #1
+ {
+ \nobreak \noindent
+ { \raggedright\hangindent1pc \footnotesize ( \emph{#1} ) \par }
+ }
+
+
+% next two declarations should move to l3doc.cls in the l3kernel eventually
+% they should be ``new'' not ``set'' but to avoid getting in timing issues
+% when they will be officially defined we use ``set'' here
+
+\cs_set_eq:NN \__codedoc_saved_detect_internals:N \__codedoc_detect_internals:N
+
+% maybe this change should be local so that it automatically reverts on \verb=\end{macro}=
+% without the need to explicitly turn it on again.
+
+\cs_new_protected:Npn \InternalDetectionOff
+ { \cs_gset_eq:NN \__codedoc_detect_internals:N \use_none:n }
+\cs_new_protected:Npn \InternalDetectionOn
+ { \cs_gset_eq:NN \__codedoc_detect_internals:N \__codedoc_saved_detect_internals:N }
+
\ExplSyntaxOff
\def\partname{File}
@@ -257,7 +282,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
{}
-%\errorstopmode
+\errorstopmode
\batchmode
-
+
\endinput
diff --git a/macros/latex/base/syntonly.dtx b/macros/latex/base/syntonly.dtx
index 1f7c5b651d..b214c49ae4 100644
--- a/macros/latex/base/syntonly.dtx
+++ b/macros/latex/base/syntonly.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/syntonly.ins b/macros/latex/base/syntonly.ins
index c4a69c4101..6b4113ed11 100644
--- a/macros/latex/base/syntonly.ins
+++ b/macros/latex/base/syntonly.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 1993-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 1993-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/syntonly.pdf b/macros/latex/base/syntonly.pdf
index 48bab0767e..44a42ca95c 100644
--- a/macros/latex/base/syntonly.pdf
+++ b/macros/latex/base/syntonly.pdf
Binary files differ
diff --git a/macros/latex/base/testpage.tex b/macros/latex/base/testpage.tex
index b89ef81bbc..ff17984ee1 100644
--- a/macros/latex/base/testpage.tex
+++ b/macros/latex/base/testpage.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/texpert.txt b/macros/latex/base/texpert.txt
index 8215f952a7..0eb1dd7784 100644
--- a/macros/latex/base/texpert.txt
+++ b/macros/latex/base/texpert.txt
@@ -207,4 +207,4 @@ the distributed files with names <*>guide.tex. You will need
to install the new version before you can typeset these files.
---- Copyright 1995-2019 the LaTeX3 project. All rights reserved ---
+--- Copyright (C) 1995-2019 the LaTeX Project. All rights reserved ---
diff --git a/macros/latex/base/tlc2.err b/macros/latex/base/tlc2.err
index 7f4e2817c8..a361d1673a 100644
--- a/macros/latex/base/tlc2.err
+++ b/macros/latex/base/tlc2.err
@@ -35,9 +35,10 @@
% Changes:
%
% v1.0a - changed name from errata.cls to ttcterrata.cls
+% v1.0b - added \arraybackslash
\ProvidesClass{ttcterrata}
- [2007/11/10 v1.0a Mini class for errata files; subject to change (FMi)]
+ [2021/04/22 v1.0b Mini class for errata files; subject to change (FMi)]
\LoadClass{article}
@@ -164,7 +165,7 @@
\multicolumn{4}{l}{\framebox[10cm][l]{\textbf{\normalsize\strut#1}}} \\}
\newenvironment{erratalist}
- {\begin{longtable}{r>{\raggedright}p{2cm}l>{\raggedright}p{10cm}l}}
+ {\begin{longtable}{r>{\raggedright\arraybackslash}p{2cm}l>{\raggedright\arraybackslash}p{10cm}l}}
{\endgobble\end{longtable}}
\newcommand\erratatitle[2]
diff --git a/macros/latex/base/tlc2.pdf b/macros/latex/base/tlc2.pdf
index 4e56aaa3fc..7f340888f1 100644
--- a/macros/latex/base/tlc2.pdf
+++ b/macros/latex/base/tlc2.pdf
Binary files differ
diff --git a/macros/latex/base/tulm.fdd b/macros/latex/base/tulm.fdd
index 9308d801ff..5c1566a5ba 100644
--- a/macros/latex/base/tulm.fdd
+++ b/macros/latex/base/tulm.fdd
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
% Copyright 2016-2019
-% The LaTeX3 Project and any individual authors listed elsewhere
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -30,7 +30,7 @@
%\iffalse This is a META comment
%
% File `cmfonts.fdd'.
-% Copyright (C) 2016-2019 LaTeX3 Project
+% Copyright (C) 2016-2019 LaTeX Project
%
%
%<TUlmr>\ProvidesFile{tulmr.fd}
@@ -51,7 +51,7 @@
\title{The file \texttt{tulm.fdd} for use with
\LaTeXe.\thanks{This file has version
number \fileversion, dated \filedate.}}
-\date{\filedate}\author{LaTeX3 Project}
+\date{\filedate}\author{\LaTeX\ Project}
\addtolength\textwidth{30pt}
\begin{document}
\MaintainedByLaTeXTeam{latex}
diff --git a/macros/latex/base/tulm.ins b/macros/latex/base/tulm.ins
index 9e32e39a63..98962f2b20 100644
--- a/macros/latex/base/tulm.ins
+++ b/macros/latex/base/tulm.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 2016-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 2016-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
@@ -48,8 +48,8 @@ reports for it can be opened at https://latex-project.org/bugs.html
(but please observe conditions on bug reports sent to that address!)
-Copyright (C) 2016-2020
-The LaTeX3 Project and any individual authors listed elsewhere
+Copyright (C) 2016-2021
+The LaTeX Project and any individual authors listed elsewhere
in this file.
This file was generated from file(s) of the LaTeX base system.
diff --git a/macros/latex/base/tulm.pdf b/macros/latex/base/tulm.pdf
index b871d94918..c91b48d517 100644
--- a/macros/latex/base/tulm.pdf
+++ b/macros/latex/base/tulm.pdf
Binary files differ
diff --git a/macros/latex/base/unpack.ins b/macros/latex/base/unpack.ins
index 3264a401d9..6332fcb5c0 100644
--- a/macros/latex/base/unpack.ins
+++ b/macros/latex/base/unpack.ins
@@ -3,8 +3,8 @@
%% driver files from the doc files in this package when run through
%% LaTeX or TeX.
%%
-%% Copyright (C) 1993-2020
-%% The LaTeX3 Project and any individual authors listed elsewhere
+%% Copyright (C) 1993-2021
+%% The LaTeX Project and any individual authors listed elsewhere
%% in this file.
%%
%% This file is part of the LaTeX base system.
diff --git a/macros/latex/base/usrguide.pdf b/macros/latex/base/usrguide.pdf
index 02e37ae675..bec8542099 100644
--- a/macros/latex/base/usrguide.pdf
+++ b/macros/latex/base/usrguide.pdf
Binary files differ
diff --git a/macros/latex/base/usrguide.tex b/macros/latex/base/usrguide.tex
index 4c2ddf24af..a94d8a6a70 100644
--- a/macros/latex/base/usrguide.tex
+++ b/macros/latex/base/usrguide.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -34,7 +34,7 @@
\title{\LaTeXe~for authors}
-\author{\copyright~Copyright 1995--2020, \LaTeX3 Project Team.\\
+\author{\copyright~Copyright 1995--2020, \LaTeX\ Project Team.\\
All rights reserved.}
\date{25 May 2020}
@@ -103,10 +103,10 @@ A brief description of the project can be found in the document
|ltx3info.tex|.
If you would like to support the project then you are welcome to send
-donations to the \LaTeX3 Project Fund; this has been set up to help
+donations to the \LaTeX\ Project Fund; this has been set up to help
the research team by financing various expenses associated with this
voluntary work of maintaining the current \LaTeX{} and developing
-\LaTeX3.
+\LaTeX\ further.
The fund is administered by The \TeX{} Users Group and by various
local user groups. Information about making donations and joining
diff --git a/macros/latex/base/usrguide3.pdf b/macros/latex/base/usrguide3.pdf
index b7063c2603..1dc77ecccc 100644
--- a/macros/latex/base/usrguide3.pdf
+++ b/macros/latex/base/usrguide3.pdf
Binary files differ
diff --git a/macros/latex/base/usrguide3.tex b/macros/latex/base/usrguide3.tex
index 4c3bde94f6..c378ac8592 100644
--- a/macros/latex/base/usrguide3.tex
+++ b/macros/latex/base/usrguide3.tex
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 2020-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -32,11 +32,11 @@
\usepackage[T1]{fontenc} % needed for \textbackslash in tt
-\title{\LaTeX3 methods for authors}
-\author{\copyright~Copyright 2020, \LaTeX\ Project Team.\\
+\title{New \LaTeX\ methods for authors (starting 2020)}
+\author{\copyright~Copyright 2020-2021, \LaTeX\ Project Team.\\
All rights reserved.}
-\date{Released 2020-12-02}
+\date{2021-04-12}
\NewDocumentCommand\cs{m}{\texttt{\textbackslash\detokenize{#1}}}
\NewDocumentCommand\marg{m}{\arg{#1}}
@@ -340,11 +340,11 @@ the nature of the argument received.
\begin{decl}
|\IfNoValueTF| \arg{arg} \arg{true code} \arg{false code} \\
- |\IfNoValueT| \arg{arg} \arg{true code} \arg{false code} \\
- |\IfNoValueF| \arg{arg} \arg{true code} \arg{false code}
+ |\IfNoValueT| \arg{arg} \arg{true code} \\
+ |\IfNoValueF| \arg{arg} \arg{false code}
\end{decl}
The \cs{IfNoValue(TF)} tests are used to check if \meta{argument} (|#1|,
-|#2|, \emph{etc.}) is the special |-NoValue-| marker For example
+|#2|, \emph{etc.}) is the special |-NoValue-| marker. For example
\begin{verbatim}
\NewDocumentCommand\foo{o m}
{%
@@ -381,8 +381,8 @@ analogue \cs{ifblank}.
\begin{decl}
|\IfValueTF| \arg{arg} \arg{true code} \arg{false code} \\
- |\IfValueT| \arg{arg} \arg{true code} \arg{false code} \\
- |\IfValueF| \arg{arg} \arg{true code} \arg{false code}
+ |\IfValueT| \arg{arg} \arg{true code} \\
+ |\IfValueF| \arg{arg} \arg{false code}
\end{decl}
The reverse form of the \cs{IfNoValue(TF)} tests are also available
as \cs{IfValue(TF)}. The context will determine which logical
@@ -398,8 +398,8 @@ names which are accessible outside of code blocks.
\begin{decl}
|\IfBooleanTF| \arg{arg} \arg{true code} \arg{false code} \\
- |\IfBooleanT| \arg{arg} \arg{true code} \arg{false code} \\
- |\IfBooleanF| \arg{arg} \arg{true code} \arg{false code}
+ |\IfBooleanT| \arg{arg} \arg{true code} \\
+ |\IfBooleanF| \arg{arg} \arg{false code}
\end{decl}
Used to test if \meta{argument} (|#1|, |#2|, \emph{etc.}) is
\cs{BooleanTrue} or \cs{BooleanFalse}. For example
diff --git a/macros/latex/base/utf8ienc.dtx b/macros/latex/base/utf8ienc.dtx
index 8d454d1c71..79c725915c 100644
--- a/macros/latex/base/utf8ienc.dtx
+++ b/macros/latex/base/utf8ienc.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
-% Copyright (C) 1993-2020
-% The LaTeX3 Project and any individual authors listed elsewhere
+% Copyright (C) 1993-2021
+% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the LaTeX base system.
@@ -216,7 +216,7 @@
%<+ts1> \ProvidesFile{ts1enc.dfu}
%<+x2> \ProvidesFile{x2enc.dfu}
%<+all> \ProvidesFile{utf8enc.dfu}
-%<-utf8-2018> [2019/11/14 v1.2k UTF-8 support for inputenc]
+%<-utf8-2018> [2021/01/27 v1.2l UTF-8 support for inputenc]
% \end{macrocode}
%
% \begin{macrocode}
@@ -318,7 +318,7 @@
% However, if we are not doing typesetting, then we execute the
% command \cs{UTFviii@two@octets@noexpand} which works like
% \cs{UTF@two@octets@string} but uses \cs{noexpand} instead of
-% \cs{string}. This way the sequence is temporay rendered harmless,
+% \cs{string}. This way the sequence is temporary rendered harmless,
% e.g., would display as is or stays put inside a
% \cs{protected@edef}. But if the result is later reused the
% starting octet is still active and so will be able to construct
@@ -363,7 +363,7 @@
% \begin{macro}{\UTFviii@two@octets@noexpand}
% \begin{macro}{\UTFviii@three@octets@noexpand}
% \begin{macro}{\UTFviii@four@octets@noexpand}
-% These tempoarily prevent the active chars from expanding.
+% These temporarily prevent the active chars from expanding.
% \begin{macrocode}
\long\def\UTF@two@octets@noexpand#1#2{\noexpand#2\noexpand}
\long\def\UTF@three@octets@noexpand#1#2#3{\noexpand#2\noexpand#3\noexpand}
@@ -530,10 +530,11 @@
%
%
% \begin{macro}{\UTFviii@loop}
-% This bit of code derived from \texttt{xmltex} defines the active character
-% correspnding to starting octets to call |\UTFviii@two@octets| etc as appropriate.
-% The starting octet itself is passed directly as the first argument, the others
-% are picked up later en route.
+% This bit of code derived from \texttt{xmltex} defines the active
+% character corresponding to starting octets to call |\UTFviii@two@octets|
+% etc as appropriate.
+% The starting octet itself is passed directly as the first
+% argument, the others are picked up later en route.
%
% The |\UTFviii@loop| loops through the numbers starting at
% |\count@| and ending at |\@tempcnta|${} - 1$, each time executing
@@ -691,7 +692,7 @@
% \end{macrocode}
%
% Here is an example of what is happening, for the pair \texttt{"C2 "A3}
-% (which is the utf8 represenation for the character \textsterling{}).
+% (which is the utf8 representation for the character \textsterling{}).
% After |\parse@XML@charref| we have, stored in |\UTFviii@tmp|, a
% single command with two character tokens as arguments:
% \begin{quote}
@@ -849,7 +850,7 @@
%
% \begin{macro}{\decode@UTFviii}
% \changes{v1.1o}{2015/08/28}{Macro added}
-% In the reverse direction, take a sequence of octects(bytes)
+% In the reverse direction, take a sequence of octets(bytes)
% representing a character in UTF-8 and construct the Unicode number.
% The sequence is terminated by |\relax|.
%
@@ -1134,9 +1135,9 @@
%
% \changes{v1.1o}{2015/08/28}{Add U+00A0 and U+00AD}
% \changes{v1.1q}{2015/12/02}{Add remaining latin uses of accents in T1}
-% \changes{v1.1r}{2015/12/03}{Add some more ogoneck cases}
+% \changes{v1.1r}{2015/12/03}{Add some more ogonek cases}
% \changes{v1.1s}{2016/01/11}{Add some more caron and acute}
-% \changes{v1.1t}{2017/01/28}{Add caron cominations for GgYy}
+% \changes{v1.1t}{2017/01/28}{Add caron combinations for GgYy}
% \begin{macrocode}
%<all,t1,ot1,ly1>\DeclareUnicodeCharacter{00A0}{\nobreakspace}
%<all,t1,ot1,ly1>\DeclareUnicodeCharacter{00A1}{\textexclamdown}
@@ -1537,7 +1538,7 @@
% two mappings are wrong or rather the names in OT2 should change for
% consistency.
%
-% On the other hand the names |\CYROTLD| are somewhat questionabled as the
+% On the other hand the names |\CYROTLD| are somewhat questionable as the
% Unicode standard only describes ``Cyrillic barred O'' while |TLD| refers
% to a tilde (which is more less what the ``Cyrillic FITA looks according
% to the Unicode book).
@@ -1700,6 +1701,18 @@
%<all,ts1>\DeclareUnicodeCharacter{0E3F}{\textbaht}
%<all,t1>\DeclareUnicodeCharacter{1E02}{\.B}
%<all,t1>\DeclareUnicodeCharacter{1E03}{\.b}
+% \end{macrocode}
+% \changes{v1.2k}{2021/01/27}{Added various additional dot accents (gh/484)}
+% \begin{macrocode}
+%<all,t1>\DeclareUnicodeCharacter{1E0D}{\d d}
+%<all,t1>\DeclareUnicodeCharacter{1E25}{\d h}
+%<all,t1>\DeclareUnicodeCharacter{1E37}{\d l}
+%<all,t1>\DeclareUnicodeCharacter{1E43}{\d m}
+%<all,t1>\DeclareUnicodeCharacter{1E45}{\.n}
+%<all,t1>\DeclareUnicodeCharacter{1E47}{\d n}
+%<all,t1>\DeclareUnicodeCharacter{1E5B}{\d r}
+%<all,t1>\DeclareUnicodeCharacter{1E63}{\d s}
+%<all,t1>\DeclareUnicodeCharacter{1E6D}{\d t}
%<all,t1>\DeclareUnicodeCharacter{1E9E}{\SS}
%<all,x2,t2c,t2b,t2a,t1,utf8>\DeclareUnicodeCharacter{200C}{\textcompwordmark}
% \end{macrocode}
diff --git a/macros/latex/base/utf8ienc.pdf b/macros/latex/base/utf8ienc.pdf
index 6ff7254be8..36ad4770ff 100644
--- a/macros/latex/base/utf8ienc.pdf
+++ b/macros/latex/base/utf8ienc.pdf
Binary files differ
diff --git a/macros/latex/base/webcomp.err b/macros/latex/base/webcomp.err
index 269636f9fb..6a62e258c5 100644
--- a/macros/latex/base/webcomp.err
+++ b/macros/latex/base/webcomp.err
@@ -12,7 +12,7 @@
\begin{filecontents}{ttcterrata.cls}
%%
-%% Copyright (C) 1997,2004,2005,2007 Frank Mittelbach
+%% Copyright (C) 1997-2021 Frank Mittelbach
%% This class file is licenced under LPPL latest version;
%% see https://www.latex-project.org/lppl
%
@@ -28,9 +28,10 @@
% Changes:
%
% v1.0a - changed name from errata.cls to ttcterrata.cls
+% v1.0b - added \arraybackslash
\ProvidesClass{ttcterrata}
- [2007/11/10 v1.0a Mini class for errata files; subject to change (FMi)]
+ [2021/04/22 v1.0b Mini class for errata files; subject to change (FMi)]
\LoadClass{article}
@@ -157,7 +158,7 @@
\multicolumn{4}{l}{\framebox[10cm][l]{\textbf{\normalsize\strut#1}}} \\}
\newenvironment{erratalist}
- {\begin{longtable}{r>{\raggedright}p{2cm}l>{\raggedright}p{10cm}l}}
+ {\begin{longtable}{r>{\raggedright\arraybackslash}p{2cm}l>{\raggedright\arraybackslash}p{10cm}l}}
{\endgobble\end{longtable}}
\newcommand\erratatitle[2]
diff --git a/macros/latex/base/webcomp.pdf b/macros/latex/base/webcomp.pdf
index 1a1cca038f..488cfb93ec 100644
--- a/macros/latex/base/webcomp.pdf
+++ b/macros/latex/base/webcomp.pdf
Binary files differ