diff options
Diffstat (limited to 'Master/texmf-dist/source')
53 files changed, 13022 insertions, 1202 deletions
diff --git a/Master/texmf-dist/source/latex/amsmath/amsmath.dtx b/Master/texmf-dist/source/latex/amsmath/amsmath.dtx index 42f3088867d..7f324700f67 100644 --- a/Master/texmf-dist/source/latex/amsmath/amsmath.dtx +++ b/Master/texmf-dist/source/latex/amsmath/amsmath.dtx @@ -86,7 +86,7 @@ Bug reports can be opened (category \texttt{#1}) at\\% % \end{macrocode} % % \begin{macrocode} -\ProvidesPackage{amsmath}[2020/01/20 v2.17e AMS math features] +\ProvidesPackage{amsmath}[2020/09/23 v2.17i AMS math features] % \end{macrocode} % % \section{Catcode defenses} @@ -466,24 +466,41 @@ For additional information on amsmath, use the \lq ?\rq\space option.% % \cs{DeclareRobustCommand}. % \changes{v2.17b}{2018/12/01}{Start LR-mode for \cs{thinspace} and % friends if necessary (github/49)} +% +% We start by undefining a number of commands (which in a current +% \LaTeX{} kernel will be defined, so that the +% \cs{DeclareRobustCommand} declarations below do not add a +% ``Command redefined'' info into the log. +% \begin{macrocode} +\let\tmspace\@undefined +\let\,\@undefined +\let\!\@undefined +\let\:\@undefined +\let\negmedspace\@undefined +\let\negthickspace\@undefined +% \end{macrocode} +% +% +% \changes{v2.17g}{2020/03/07}{Math/text spacing commands are now in +% the \LaTeX{} kernel and are made robust (gh/303)} % \begin{macrocode} \ifx\leavevmode@ifvmode\@undefined -\DeclareRobustCommand{\tmspace}[3]{% +\DeclareRobustCommand\tmspace[3]{% \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} \else -\DeclareRobustCommand{\tmspace}[3]{% +\DeclareRobustCommand\tmspace[3]{% \ifmmode\mskip#1#2\else\leavevmode@ifvmode\kern#1#3\fi\relax} \fi -\renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} +\DeclareRobustCommand\,{\tmspace+\thinmuskip{.1667em}} \let\thinspace\, -\renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} +\DeclareRobustCommand\!{\tmspace-\thinmuskip{.1667em}} \let\negthinspace\! -\renewcommand{\:}{\tmspace+\medmuskip{.2222em}} +\DeclareRobustCommand\:{\tmspace+\medmuskip{.2222em}} \let\medspace\: -\newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} -\renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} +\DeclareRobustCommand\negmedspace{\tmspace-\medmuskip{.2222em}} +\renewcommand\;{\tmspace+\thickmuskip{.2777em}} \let\thickspace\; -\newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} +\DeclareRobustCommand\negthickspace{\tmspace-\thickmuskip{.2777em}} % \end{macrocode} % \end{macro} % \end{macro} @@ -598,8 +615,14 @@ Foreign command \@backslashchar#1;\MessageBreak % abbreviations for some commonly needed mathstyle overrides. To % conserve csnames we avoid making \cn{dfrac} and \cn{tfrac} robust % (\cn{genfrac} is itself robust). +% \changes{v2.17i}{2020/09/23}{added \cs{Ustack} for luatex (moved patch from lualatex-math)} % \begin{macrocode} +% +\ifx\directlua\@undefined \DeclareRobustCommand{\frac}[2]{{\begingroup#1\endgroup\@@over#2}} +\else +\DeclareRobustCommand{\frac}[2]{{\Ustack{\begingroup#1\endgroup\@@over#2}}} +\fi \newcommand{\dfrac}{\genfrac{}{}{}0} \newcommand{\tfrac}{\genfrac{}{}{}1} % \end{macrocode} @@ -732,12 +755,12 @@ Foreign command \@backslashchar#1;\MessageBreak \fi } % \end{macrocode} -% +% \changes{v2.17i}{2020/09/23}{added \cs{Ustack} (moved patch from lualatex-math)} % \begin{macrocode} \DeclareRobustCommand{\genfrac}[6]{{% \@mathstyle{#4}% \genfrac@choice o{#1}% -{\begingroup#5\endgroup\ifx @#3@\@@over\else\@@above\fi#3\relax#6}% +{\Ustack {\begingroup#5\endgroup\ifx @#3@\@@over\else\@@above\fi#3\relax#6}}% \genfrac@choice c{#2}% }} % \end{macrocode} @@ -1633,13 +1656,15 @@ Foreign command \@backslashchar#1;\MessageBreak % \begin{macro}{\dddot} % \begin{macro}{\ddddot} % Triple and quadruple dot accents. +% \changes{v2.17f}{2020/02/20}{Add a kern so that a single char is not +% vertically shifted and move the dots slightly to the right (gh/126)} % \begin{macrocode} \ams@newcommand{\dddot}[1]{% - {\mathop{#1}\limits^{\vbox to-1.4\ex@{\kern-\tw@\ex@ - \hbox{\normalfont ...}\vss}}}} + {\mathop{\kern\z@#1}\limits^{\vbox to-1.4\ex@{\kern-\tw@\ex@ + \hbox{\,\normalfont...}\vss}}}} \ams@newcommand{\ddddot}[1]{% - {\mathop{#1}\limits^{\vbox to-1.4\ex@{\kern-\tw@\ex@ - \hbox{\normalfont....}\vss}}}} + {\mathop{\kern\z@#1}\limits^{\vbox to-1.4\ex@{\kern-\tw@\ex@ + \hbox{\,\normalfont....}\vss}}}} % \end{macrocode} % \end{macro} % \end{macro} @@ -2184,17 +2209,33 @@ Foreign command \@backslashchar#1;\MessageBreak % The minus sign used in constructing these arrow fills is smashed so % that superscripts above the arrows won't be too high. This % primarily affects the \cn{xleftarrow} and \cn{xrightarrow} arrows. -% +% \changes{v2.17h}{2020/08/24}{detect unicode engines and use their commands} % \begin{macrocode} -\mathchardef\std@minus\mathcode`\-\relax -\mathchardef\std@equal\mathcode`\=\relax +\@ifundefined{Umathcode} + {% + \mathchardef\std@minus\mathcode`\-\relax + \mathchardef\std@equal\mathcode`\=\relax + } + {% + \Umathcharnumdef\std@minus\Umathcodenum`\-\relax + \Umathcharnumdef\std@equal\Umathcodenum`\=\relax + } % \end{macrocode} % In case some alternative math fonts are loaded later: % \begin{macrocode} -\AtBeginDocument{% - \mathchardef\std@minus\mathcode`\-\relax - \mathchardef\std@equal\mathcode`\=\relax -} +\@ifundefined{Umathcode} + {% + \AtBeginDocument{% + \mathchardef\std@minus\mathcode`\-\relax + \mathchardef\std@equal\mathcode`\=\relax + }% + } + {% + \AtBeginDocument{% + \Umathcharnumdef\std@minus\Umathcodenum`\-\relax + \Umathcharnumdef\std@equal\Umathcodenum`\=\relax + }% + } % \end{macrocode} % % \begin{macro}{\relbar} @@ -2301,7 +2342,9 @@ Foreign command \@backslashchar#1;\MessageBreak % for use in a subscript or superscript. At the moment the supported % arguments are not the full possibilities of \env{array} but only % |c| or |l| for centered or left-aligned. And only one column. +% \changes{v2.17i}{2020/09/23}{moved to version from lualatex-math for luatex} % \begin{macrocode} +\ifx\directlua\@undefined \newenvironment{subarray}[1]{% % \end{macrocode} % Note: The predecessors of \env{subarray} (\env{Sb} and \env{Sp}, @@ -2340,6 +2383,23 @@ Foreign command \@backslashchar#1;\MessageBreak }{% \crcr\egroup\egroup } +\else +\newenvironment{subarray}[1]{% + \vcenter\bgroup + \Let@ \restore@math@cr \default@tag + \baselineskip \Umathstacknumup \scriptstyle + \advance\baselineskip \Umathstackdenomdown \scriptstyle + \lineskip \Umathstackvgap \scriptstyle + \lineskiplimit \lineskip + \ialign\bgroup\ifx c#1\hfil\fi + \Ustartmath + \m@th\scriptstyle## + \Ustopmath + \hfil\crcr +}{% + \crcr\egroup\egroup +} +\fi % \end{macrocode} % \end{environment} % @@ -3438,7 +3498,8 @@ and fix things up.} % \end{macro} % % \begin{macro}{\black@} -% \changes{v2.17a}{2017/09/02}{add fixed width box so overfull warning generated in centred environments in lists} +% \changes{v2.17a}{2017/09/02}{Add fixed width box so overfull warning +% generated in centred environments in lists} % This macro is made to produce an overfull box message and % possibly (depending on the value of \cs{overfullrule}) % a rule in the margin if the total width of an alignment @@ -3654,6 +3715,77 @@ and fix things up.} % \end{macrocode} % \end{macro} % +% +% +% \begin{macro}{\ams@start@box} +% This macro tests the optional positioning argument (in +% \texttt{gathered} or \texttt{aligned}. It explicitly tests for the +% value \texttt{b}, \texttt{c} and \texttt{t} and if the value is +% different, then we assume that it is a bracket group that belongs +% to the formula instead of being an misspelled optional argument. +% (In earlier versions of the code anything other than \texttt{b} +% or \texttt{t} was interpreted as \texttt{c} and the data was +% otherwise dropped.) +% \changes{v2.17g}{2020/03/10}{Explicity test for b/t/c and return +% optional argument is different (gh/5)} +% \begin{macrocode} +\def\ams@start@box#1{% +% \end{macrocode} +% As we may pick up an arbitrary part of the formula by mistake, we +% need to be very careful with the testing to avoid low-level +% errors. This is why we use \cs{detokenize}. But we also need to +% expand the argument (if possible) in case the position value is +% hidden inside a macro. We therefore apply the \cs{romannumeral} +% trick (known as f-expansion in \texttt{expl3}) in its old form. +% The code assumes that +% the default is correctly set up (which in this case is \texttt{c}). +% \begin{macrocode} + \edef\reserved@a{\csname ams@pos@\expandafter\detokenize + \expandafter{\romannumeral-`\0#1}\endcsname}% + \expandafter\ifx\reserved@a\relax +% \end{macrocode} +% If the argument is neither \texttt{b}, \texttt{c} or \texttt{t} +% we save it in \cs{ams@return@opt@arg}, so it can later be +% returned as part of the environment body. We could at this point +% also issue a warning that bracket group was found at the start of +% the formula and that it is safer to add a \cs{relax} before it. +% \begin{macrocode} + \PackageWarning{amsmath}{% + Bracket group \detokenize{[#1]} at formula start!\MessageBreak + It could be a misspelled positional argument.\MessageBreak + If it belongs to the formula add a \relax in\MessageBreak + front to hide it}% + \def\ams@return@opt@arg{[#1]}\vcenter +% \end{macrocode} +% If the argument was identified then we clear +% \cs{ams@return@opt@arg} (just in case somebod ever nests these +% environment. +% \begin{macrocode} + \else + \let\ams@return@opt@arg\@empty\reserved@a + \fi +} +% \end{macrocode} +% +% \begin{macro}{\ams@pos@t} +% \begin{macro}{\ams@pos@b} +% \begin{macro}{\ams@pos@c} +% +% \begin{macrocode} +\def\ams@pos@t{\vtop} +\def\ams@pos@b{\vbox} +\def\ams@pos@c{\vcenter} +% \end{macrocode} +% And we accept an empty argument as a way to get the default (as +% that was the case before as well, albeit by mistake in some sense). +% \begin{macrocode} +\let\ams@pos@\ams@pos@c +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro}{\start@aligned} % The \env{aligned} and \env{alignedat} environments are identical % except that the latter takes a mandatory argument to specify the @@ -3678,7 +3810,10 @@ and fix things up.} % to the margin. % \begin{macrocode} \alignedspace@left - \if #1t\vtop \else \if#1b \vbox \else \vcenter \fi \fi \bgroup +% \end{macrocode} +% Select the right kind of box based on the optional argument \verb=#1=. +% \begin{macrocode} + \ams@start@box{#1}\bgroup \maxfields@#2\relax \ifnum\maxfields@>\m@ne \multiply\maxfields@\tw@ @@ -3721,6 +3856,13 @@ and fix things up.} \hfil \tabskip\alignsep@ \crcr +% \end{macrocode} +% If we picked up a bracket group by mistake here is the place to +% return it for processing. +% \changes{v2.17g}{2020/03/10}{Explicity test for b/t/c and return +% optional argument is different (gh/5)} +% \begin{macrocode} + \ams@return@opt@arg } % \end{macrocode} % \end{macro} @@ -3805,12 +3947,21 @@ and fix things up.} \nonmatherr@{\begin{gathered}}% \fi \alignedspace@left - \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi \bgroup +% \end{macrocode} +% Select the right kind of box based on the optional argument \verb=#1=. +% \begin{macrocode} + \ams@start@box{#1}\bgroup \Let@ \chardef\dspbrk@context\@ne \restore@math@cr \spread@equation \ialign\bgroup \hfil\strut@$\m@th\displaystyle##$\hfil \crcr +% \end{macrocode} +% And put a mistaking picked up bracket group back: +% \changes{v2.17g}{2020/03/10}{Explicity test for b/t/c and return +% optional argument is different (gh/5)} +% \begin{macrocode} + \ams@return@opt@arg }{% \endaligned } diff --git a/Master/texmf-dist/source/latex/amsmath/amstext.dtx b/Master/texmf-dist/source/latex/amsmath/amstext.dtx index a5e8491dc2b..5e7e6ca6720 100644 --- a/Master/texmf-dist/source/latex/amsmath/amstext.dtx +++ b/Master/texmf-dist/source/latex/amsmath/amstext.dtx @@ -139,7 +139,7 @@ Bug reports can be opened (category \texttt{#1}) at\\% % The macros \cs{f@size}, \cs{sf@size} and \cs{ssf@size} hold the % sizes which should be used when we are loading a new font for use % in \cs{textfont}, \cs{scriptfont} and \cs{scriptscriptfont}. There -% is some question whether we should use use \cs{tf@size} or +% is some question whether we should use \cs{tf@size} or % \cs{f@size} for the main size, but since the primary purpose of the % \cn{text} macro is to switch back to text within a display, it % seems that \cs{f@size} is the better choice. (Indeed it could be diff --git a/Master/texmf-dist/source/latex/base/classes.dtx b/Master/texmf-dist/source/latex/base/classes.dtx index ea3b014c897..d6f2bb64e6a 100644 --- a/Master/texmf-dist/source/latex/base/classes.dtx +++ b/Master/texmf-dist/source/latex/base/classes.dtx @@ -53,7 +53,7 @@ %<*driver> \ProvidesFile{classes.drv} %</driver> - [2019/12/20 v1.4l + [2020/04/10 v1.4m %<article|report|book> Standard LaTeX document class] %<10pt|11pt|12pt> Standard LaTeX file (size option)] % \end{macrocode} @@ -214,6 +214,7 @@ % options that are new in \LaTeXe.} % \changes{v1.3v}{1997/06/16}{Documentation fixes.} % \changes{v1.4j}{2019/08/27}{Various commands made robust} +% \changes{v1.4m}{2020/04/10}{(JLB) prettyprinting the code} % % % \title{Standard Document Classes for \LaTeX{} version 2e\thanks{This @@ -221,7 +222,7 @@ % % \author{% % Copyright (C) 1992 by Leslie Lamport \and -% Copyright (C) 1994-2019 by Frank Mittelbach \and Johannes Braams \and +% Copyright (C) 1994-2020 by Frank Mittelbach \and Johannes Braams \and % \LaTeX3 Project Team % } % \date{\filedate} @@ -322,34 +323,34 @@ % \changes{v1.0g}{1993/12/09}{Removed typo, A4 is not 279 mm high} % \begin{macrocode} \if@compatibility\else -\DeclareOption{a4paper} - {\setlength\paperheight {297mm}% - \setlength\paperwidth {210mm}} -\DeclareOption{a5paper} - {\setlength\paperheight {210mm}% - \setlength\paperwidth {148mm}} -\DeclareOption{b5paper} - {\setlength\paperheight {250mm}% - \setlength\paperwidth {176mm}} -\DeclareOption{letterpaper} - {\setlength\paperheight {11in}% - \setlength\paperwidth {8.5in}} -\DeclareOption{legalpaper} - {\setlength\paperheight {14in}% - \setlength\paperwidth {8.5in}} -\DeclareOption{executivepaper} - {\setlength\paperheight {10.5in}% - \setlength\paperwidth {7.25in}} + \DeclareOption{a4paper} + {\setlength\paperheight {297mm}% + \setlength\paperwidth {210mm}} + \DeclareOption{a5paper} + {\setlength\paperheight {210mm}% + \setlength\paperwidth {148mm}} + \DeclareOption{b5paper} + {\setlength\paperheight {250mm}% + \setlength\paperwidth {176mm}} + \DeclareOption{letterpaper} + {\setlength\paperheight {11in}% + \setlength\paperwidth {8.5in}} + \DeclareOption{legalpaper} + {\setlength\paperheight {14in}% + \setlength\paperwidth {8.5in}} + \DeclareOption{executivepaper} + {\setlength\paperheight {10.5in}% + \setlength\paperwidth {7.25in}} % \end{macrocode} % % The option \Lopt{landscape} switches the values of |\paperheight| % and |\paperwidth|, assuming the dimensions were given for portrait % paper. % \begin{macrocode} -\DeclareOption{landscape} - {\setlength\@tempdima {\paperheight}% - \setlength\paperheight {\paperwidth}% - \setlength\paperwidth {\@tempdima}} + \DeclareOption{landscape} + {\setlength\@tempdima {\paperheight}% + \setlength\paperheight {\paperwidth}% + \setlength\paperwidth {\@tempdima}} \fi % \end{macrocode} % @@ -368,7 +369,7 @@ \if@compatibility \renewcommand\@ptsize{0} \else -\DeclareOption{10pt}{\renewcommand\@ptsize{0}} + \DeclareOption{10pt}{\renewcommand\@ptsize{0}} \fi \DeclareOption{11pt}{\renewcommand\@ptsize{1}} \DeclareOption{12pt}{\renewcommand\@ptsize{2}} @@ -382,7 +383,7 @@ % paragraphs into the outside margin. % \begin{macrocode} \if@compatibility\else -\DeclareOption{oneside}{\@twosidefalse \@mparswitchfalse} + \DeclareOption{oneside}{\@twosidefalse \@mparswitchfalse} \fi \DeclareOption{twoside}{\@twosidetrue \@mparswitchtrue} % \end{macrocode} @@ -395,7 +396,7 @@ % \begin{macrocode} \DeclareOption{draft}{\setlength\overfullrule{5pt}} \if@compatibility\else -\DeclareOption{final}{\setlength\overfullrule{0pt}} + \DeclareOption{final}{\setlength\overfullrule{0pt}} \fi % \end{macrocode} % @@ -405,7 +406,7 @@ % \begin{macrocode} \DeclareOption{titlepage}{\@titlepagetrue} \if@compatibility\else -\DeclareOption{notitlepage}{\@titlepagefalse} + \DeclareOption{notitlepage}{\@titlepagefalse} \fi % \end{macrocode} % @@ -427,7 +428,7 @@ % Two-column and one-column printing is again realized via a switch. % \begin{macrocode} \if@compatibility\else -\DeclareOption{onecolumn}{\@twocolumnfalse} + \DeclareOption{onecolumn}{\@twocolumnfalse} \fi \DeclareOption{twocolumn}{\@twocolumntrue} % \end{macrocode} @@ -468,7 +469,7 @@ % First some hook into the bibliography environment is filled. % \begin{macrocode} \AtEndOfPackage{% - \renewcommand\@openbib@code{% + \renewcommand\@openbib@code{% \advance\leftmargin\bibindent \itemindent -\bibindent \listparindent \itemindent @@ -477,7 +478,7 @@ % \end{macrocode} % In addition the definition of |\newblock| is overwritten. % \begin{macrocode} - \renewcommand\newblock{\par}}% + \renewcommand\newblock{\par}}% } % \end{macrocode} % @@ -950,7 +951,7 @@ % |\topskip|. % \begin{macrocode} \if@compatibility \setlength\maxdepth{4\p@} \else -\setlength\maxdepth{.5\topskip} \fi + \setlength\maxdepth{.5\topskip} \fi % \end{macrocode} % \end{macro} % @@ -1106,7 +1107,7 @@ % between two marginal notes is controlled by |\marginparpush|. % \begin{macrocode} \if@twocolumn - \setlength\marginparsep {10\p@} + \setlength\marginparsep {10\p@} \else %<10pt&!bk> \setlength\marginparsep{11\p@} %<11pt&!bk> \setlength\marginparsep{10\p@} @@ -1801,7 +1802,7 @@ % \changes{v1.3o}{1995/11/02}{(CAR) Make \cs{footnote} always work in % title, etc} % \begin{macrocode} - \if@titlepage +\if@titlepage \newcommand\maketitle{\begin{titlepage}% \let\footnotesize\small \let\footnoterule\relax @@ -1867,7 +1868,7 @@ \global\let\author\relax \global\let\date\relax \global\let\and\relax -} + } % \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 @@ -1884,12 +1885,12 @@ % \cs{@makefntext} to a) work and b) without using math} % \begin{macrocode} \else -\newcommand\maketitle{\par - \begingroup - \renewcommand\thefootnote{\@fnsymbol\c@footnote}% - \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}% - \long\def\@makefntext##1{\parindent 1em\noindent - \hb@xt@1.8em{% + \newcommand\maketitle{\par + \begingroup + \renewcommand\thefootnote{\@fnsymbol\c@footnote}% + \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}% + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% % \end{macrocode} % If this is a twocolumn document we start a new page in twocolumn @@ -1899,27 +1900,27 @@ % \changes{v1.2k}{1994/05/06}{Added check on number of columns in use % locally} % \begin{macrocode} - \if@twocolumn - \ifnum \col@number=\@ne - \@maketitle + \if@twocolumn + \ifnum \col@number=\@ne + \@maketitle + \else + \twocolumn[\@maketitle]% + \fi \else - \twocolumn[\@maketitle]% - \fi - \else % \end{macrocode} % When this is not a twocolumn 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} \newpage - \global\@topnum\z@ % Prevents figures from going at top of page. - \@maketitle - \fi + \global\@topnum\z@ % Prevents figures from going at top of page. + \@maketitle + \fi % \end{macrocode} % This page gets a \pstyle{plain} layout. We call |\@thanks| to % produce the footnotes. % \begin{macrocode} - \thispagestyle{plain}\@thanks + \thispagestyle{plain}\@thanks % \end{macrocode} % Now we can close the group, reset the \Lcount{footnote} counter, % disable |\thanks|, |\maketitle| and |\@maketitle| and save some @@ -1928,20 +1929,20 @@ % \changes{v1.3k}{1995/08/27}{Disable \cs{title} and similar decls} % \changes{v1.3n}{1995/10/29}{Empty \cs{@date} as well} % \begin{macrocode} - \endgroup - \setcounter{footnote}{0}% - \global\let\thanks\relax - \global\let\maketitle\relax - \global\let\@maketitle\relax - \global\let\@thanks\@empty - \global\let\@author\@empty - \global\let\@date\@empty - \global\let\@title\@empty - \global\let\title\relax - \global\let\author\relax - \global\let\date\relax - \global\let\and\relax -} + \endgroup + \setcounter{footnote}{0}% + \global\let\thanks\relax + \global\let\maketitle\relax + \global\let\@maketitle\relax + \global\let\@thanks\@empty + \global\let\@author\@empty + \global\let\@date\@empty + \global\let\@title\@empty + \global\let\title\relax + \global\let\author\relax + \global\let\date\relax + \global\let\and\relax + } % \end{macrocode} % \end{macro} % @@ -3144,7 +3145,7 @@ % First we do give the definition for compatibility mode. % \begin{macrocode} \if@compatibility -\newenvironment{titlepage} + \newenvironment{titlepage} {% %<book> \cleardoublepage \if@twocolumn @@ -3162,7 +3163,7 @@ % And here is the one for native \LaTeXe{}. % \begin{macrocode} \else -\newenvironment{titlepage} + \newenvironment{titlepage} {% %<book> \cleardoublepage \if@twocolumn diff --git a/Master/texmf-dist/source/latex/base/doc.dtx b/Master/texmf-dist/source/latex/base/doc.dtx index 1341f56b8b2..7e7817153c8 100644 --- a/Master/texmf-dist/source/latex/base/doc.dtx +++ b/Master/texmf-dist/source/latex/base/doc.dtx @@ -35,7 +35,7 @@ %<+package|shortvrb>\NeedsTeXFormat{LaTeX2e}[1994/12/01] %<+package> \ProvidesPackage{doc} %<+shortvrb>\ProvidesPackage{shortvrb} -%<+package|shortvrb> [2019/12/16 v2.1l +%<+package|shortvrb> [2020/06/15 v2.1m %<+package|shortvrb> Standard LaTeX documentation package (FMi)] %\catcode`\<=12 % @@ -132,14 +132,14 @@ % \setcounter{StandardModuleDepth}{1} % % {\catcode`\p=12 \catcode`\t=12 ^^A hack used later on to print -% \gdef\dimenvalue#1pt{$#1$pt}} ^^A a register value with a - sign +% \gdef\dimenvalue#1pt{$#1$pt}} ^^A register values with a - sign % % \newcommand{\DOC}{\texttt{doc}} % % \changes{v1.9t}{1995/05/11}{Use \cs{GetFileInfo}} % \GetFileInfo{doc.sty} % -% \CheckSum{2208} ^^A % keep the checksum in this file +% \CheckSum{2213} ^^A % keep the checksum in this file % % \title{The \DOC{} and \texttt{shortvrb} Packages\thanks % {This file has version number \fileversion{} dated \filedate{}.}} @@ -1324,6 +1324,16 @@ \if@inlabel\leavevmode\fi \trivlist \parskip \z@ \item[]% % \end{macrocode} +% The \cs{item} command sets the \cs{@labels} box but that box is +% never typeset (as \cs{everypar} that normally does this gets +% redefined later). That is normally not an issue, but produces a +% problem when typesetting in mixed directions, (e.g., in +% Japanese), so we explicitly clear it for that use case. +% \changes{v2.1m}{2020/06/15}{Void \cs{@labels} for vertical +% typesetting (gh/344)} +% \begin{macrocode} + \global\setbox\@labels\box\voidb@x +% \end{macrocode} % Additionally, everything should be set in \texttt{typewriter} font. % Some people might prefer it somewhat differently; because of this % the font choice is @@ -1448,7 +1458,8 @@ % bothered since doc-sources should be up-to-date but since the % request came from someone called David Carlisle \ldots :-) % \changes{v1.9y}{1996/01/26}{Support compat mode} -% \changes{v2.1l}{2019/12/16}{Use \cs{shapedefault} not \cs{updefault} for extended NFSS} +% \changes{v2.1l}{2019/12/16}{Use \cs{shapedefault} not +% \cs{updefault} for extended NFSS} % \begin{macrocode} \def\MacroFont{\small \usefont\encodingdefault diff --git a/Master/texmf-dist/source/latex/base/docstrip.dtx b/Master/texmf-dist/source/latex/base/docstrip.dtx index 9cc7945d602..a0a06311edb 100644 --- a/Master/texmf-dist/source/latex/base/docstrip.dtx +++ b/Master/texmf-dist/source/latex/base/docstrip.dtx @@ -29,9 +29,9 @@ \catcode`\{=1 \catcode`\}=2 \def\filename{docstrip.dtx} -\def\fileversion{2.5g} -\def\filedate{2018/05/03} -\def\docdate {2018/05/03} +\def\fileversion{v2.6a} +\def\filedate{2020-07-07} +\def\docdate {2020-07-11} %% % %\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-2003 LaTeX3 project and the above authors +%% Copyright (C) 1998-2020 LaTeX3 project and the above authors %% All rights are reserved. %% % @@ -82,6 +82,8 @@ % \changes{2.3e}{1996/10/02}{Introduced ``open lists''} % \changes{2.4a}{1996/06/06}{Add stream limits (MDW)} % \changes{2.4c}{1996/06/11}{Add initex support (DPC)} +% \changes{v2.6a}{2020-07-07}{Added the handling of @@-modules from +% \texttt{l3docstrip.dtx} (gh/337)} % % \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ } % \DoNotIndex{\@ne} @@ -785,6 +787,57 @@ % When a block of code is {\em not\/} included, any guards that occur % within that block are {\em not\/} evaluated. % +% \section{Internal functions and variables} +% +% An important consideration for \LaTeX3 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 +% system, this requires a convention for indicating which functions +% in a code-level module are public and which are private. +% +% Using \ds\ allows internal functions to be indicated +% using a `two part' system. Within the \texttt{.dtx} file, +% internal functions may be indicated using |@@| in place of the +% module name, for example +% \begin{verbatim} +% \cs_new_protected:Npn \@@_some_function:nn #1#2 +% { +% % Some code here +% } +% \tl_new:N \l_@@_internal_tl +% \end{verbatim} +% +% To extract the code using \ds, the original `guard' +% mecahnism 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} +% %<*package> +% %<@@=foo> +% \cs_new_protected:Npn \@@_some_function:nn #1#2 +% { +% % Some code here +% } +% \tl_new:N \l_@@_internal_tl +% %</package> +% \end{verbatim} +% is extracted as +% \begin{verbatim} +% \cs_new_protected:Npn \__foo_some_function:nn #1#2 +% { +% % Some code here +% } +% \tl_new:N \l__foo_internal_tl +% \end{verbatim} +% where the |__| indicates that the functions and variables are +% internal to the \texttt{foo} module. +% +% Use |@@@@| to obtain |@@| in the output (|@@@@@| to get |@@@|). +% For longer pieces of code the replacement can be completely +% suppressed by giving an empty module name, namely using the +% syntax \texttt{\%<@@=>}. +% % \section{Those other languages} % Since \TeX\ is an open system some of \TeX\ packages include % non-\TeX\ files. Some authors use \ds\ to generate PostScript @@ -853,7 +906,7 @@ % % \subsection{Verbatim mode} % If your programming language uses some construct that can -% interferes badly with \ds\ (e.g., percent in column one) you may +% interfere badly with \ds\ (e.g., percent in column one) you may % need a way for preventing it from being stripped off. For that % purpose \ds\ features `verbatim mode'. % @@ -1635,6 +1688,16 @@ Z \x % \end{macrocode} % +% \begin{macro}{\quote@name} +% \changes{v2.5h}{2020/04/18}{Macro added gfh/221)} +% A macro copied from \texttt{ltfiles.dtx} in order to be able to +% allow spaces in filenames. +% \begin{macrocode} +\def\quote@name#1{"\quote@@name#1\@gobble""} +\def\quote@@name#1"{#1\quote@@name} +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\StreamOpen}\begin{macro}{\StreamPut} % \begin{macro}{\StreamClose} % Here is stream opening operator. Its parameter should be a macro @@ -1642,6 +1705,10 @@ Z % write to file |foo.tex| use |\StreamOpen\foo|, then % |\StreamPut\foo| and |\StreamClose\foo|. % +% \changes{v2.5h}{2020/04/18}{Allow spaces in filenames by enclosing +% them in quotes (gh/221)} +% \changes{v2.5h}{2020/04/18}{Added two times two \cs{expandafters} to +% make the case with a filename in quotes work as well} % \begin{macrocode} \chardef\stream@closed=16 \def\StreamOpen#1{% @@ -1649,7 +1716,10 @@ Z \def\s@do##1{\ifnum##1=0 \chardef#1=\expandafter\@stripstr\string##1 % \global\chardef##1=1 % - \immediate\openout#1=\csname pth@\@stripstring#1\endcsname % + \edef\q@curr@file{% + \expandafter\expandafter\expandafter\quote@name + \expandafter\expandafter\expandafter{\csname pth@\@stripstring#1\endcsname}} + \immediate\openout#1=\q@curr@file\relax \@streamfound \fi} \@outputstreams @@ -2228,9 +2298,14 @@ Z % \subsection{Processing the input lines} % % \begin{macro}{\normalLine} +% \changes{v2.6a}{2020-07-07}{The search-and-replace macro +% \cs{replaceModuleInLine} added from \textsf{l3docstrip.dtx} +% (gh/337)} % The macro |\normalLine| writes its argument (which has to be % delimited with |\endLine|) on all active output files i.e. -% those with off-counters equal to zero. +% 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. % If statistics are included, the counter % |\codeLinesPassed| is incremented by $1$. % \begin{macrocode} @@ -2240,6 +2315,7 @@ Z %</stats> \maybeMsg{.}% \def\inLine{#1}% + \replaceModuleInLine \let\do\putline@do \activefiles } @@ -2400,14 +2476,17 @@ Z % \changes{2.3a}{1995/08/18}{Adapted to concurrent version} % \changes{2.3a}{1995/08/20}{Trying to avoid assignments} % \changes{2.3e}{1996/09/16}{Verbatim mode} +% \changes{v2.6a}{2020-07-07}{Add the @-sign option from +% \textsf{l3docstrip.dtx} (gh/337)} +% % When the macros that process a line have found that the line % starts with `\texttt{\%<}', a guard line has been encountered. % The first character of a guard can be an asterisk (\texttt{*}), a % slash (\texttt{/}) a plus (\texttt{+}), a minus (\texttt{-}), a -% less-than sign (\texttt{<}) starting verbatim mode or -% any other character that can be found in an option name. This -% means that we have to peek at the next token and -% decide what kind of guard we have. +% less-than sign (\texttt{<}) starting verbatim mode, a commercial +% at (\texttt{@}) or any other character that can be found in an +% option name. This means that we have to peek at the next token +% and decide what kind of guard we have. % % We reinsert |#1| as it may be needed by |\doOption|. % \begin{macrocode} @@ -2415,12 +2494,13 @@ Z \ifcase \ifx*#10\else \ifx/#11\else \ifx+#12\else \ifx-#13\else - \ifx<#14\else 5\fi\fi\fi\fi\fi\relax + \ifx<#14\else \ifx @#15\else 6\fi\fi\fi\fi\fi\fi\relax \expandafter\starOption\or \expandafter\slashOption\or \expandafter\plusOption\or \expandafter\minusOption\or \expandafter\verbOption\or + \expandafter\moduleOption\or \expandafter\doOption\fi #1} % \end{macrocode} @@ -2435,12 +2515,17 @@ Z % result of the test |\if1\Expr{|\meta{options}|}|, the current % line is either copied to the output stream or removed. Then % the test is computed for all active output files. +% \changes{v2.6a}{2020-07-07}{Now use \cs{InLine} and call +% \cs{replaceModuleInline} (gh/337)} % \begin{macrocode} \def\doOption#1>#2\endLine{% \maybeMsg{<#1 . >}% \Evaluate{#1}% \def\do##1##2##3{% - \if1\Expr{##2}\StreamPut##1{#2}\fi + \if1\Expr{##2}% + \def\inLine{#2}% + \replaceModuleInLine + \StreamPut##1{\inLine}\fi }% \activefiles } @@ -2664,6 +2749,94 @@ Z % \end{macrocode} % \end{macro} % +% \begin{macro}{\moduleOption} +% \changes{v2.6a}{2020-07-07}{Macro added from +% \textsf{l3docstrip.dtx} (gh/337)} +% +% In the case where the line starts |%<@|: the defined syntax requires that +% this continues to |%<@@=|. At the moment, we assume that the syntax is +% correct and |#1| here is the module name for substitution into any +% internal functions in the extracted material. +% \begin{macrocode} +\def\moduleOption @@=#1>#2\endLine{% + \maybeMsg{<@@=#1>}% + \prepareActiveModule{#1}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\prepareActiveModule} +% \changes{v2.6a}{2020-07-07}{Macro added from +% \textsf{l3docstrip.dtx} (gh/337)} +% \begin{macro}{\replaceModuleInLine} +% \changes{v2.6a}{2020-07-07}{Macro added from +% \textsf{l3docstrip.dtx} (gh/337)} +% Here, we set up to do the search-and-replace when doing the +% extraction. The argument (|#1|) is the replacement text to use, +% or if empty an indicator that no replacement should be done. The +% search material is one of |__@@|, |_@@| or |@@|, done in order +% such that all three end up the same in the output. The string +% |@@@@| is hidden from these replacements by temporarily turning +% it into a pair of letters with different category codes, not +% produced by \ds; this allows to get |@@| in the +% output. The replacement function is initialised as a do-nothing +% for the case where |%<@@=| is never seen. +% \begin{macrocode} +\begingroup + \catcode`\_ = 12 % + \long\gdef\prepareActiveModule#1{% + \ifx\relax#1\relax + \let\replaceModuleInLine\empty + \else + \edef\replaceModuleInLine{% + \noexpand\replaceAllIn\noexpand\inLine{@@@@}{\string aa}% + \noexpand\replaceAllIn\noexpand\inLine{__@@}{__#1}% + \noexpand\replaceAllIn\noexpand\inLine{_@@}{__#1}% + \noexpand\replaceAllIn\noexpand\inLine{@@}{__#1}% + \noexpand\replaceAllIn\noexpand\inLine{\string aa}{@@}% + }% + \fi + } +\endgroup +\let\replaceModuleInLine\empty +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\replaceAllIn} +% \changes{v2.6a}{2020-07-07}{Macro added from +% \textsf{l3docstrip.dtx} (gh/337)} +% \begin{macro}{\replaceAllInAuxI} +% \changes{v2.6a}{2020-07-07}{Macro added from +% \textsf{l3docstrip.dtx} (gh/337)} +% \begin{macro}{\replaceAllInAuxII} +% \changes{v2.6a}{2020-07-07}{Macro added from +% \textsf{l3docstrip.dtx} (gh/337)} +% \begin{macro}{\replaceAllInAuxIII} +% \changes{v2.6a}{2020-07-07}{Macro added from +% \textsf{l3docstrip.dtx} (gh/337)} +% The code here is a simple search-and-replace routine for a macro +% |#1|, replacing |#2| by |#3|. As set up here, there is an +% assumption that nothing is going to be expandable, which is +% reasonable as \ds\ deals with `string' material. +% \begin{macrocode} +\long\def\replaceAllIn#1#2#3{% + \long\def\tempa##1##2#2{% + ##2\qMark\replaceAllInAuxIII#3##1% + }% + \edef#1{\expandafter\replaceAllInAuxI#1\qMark#2\qStop}% +} +\def\replaceAllInAuxI{% + \expandafter\replaceAllInAuxII\tempa\replaceAllInAuxI\empty +} +\long\def\replaceAllInAuxII#1\qMark#2{#1} +\long\def\replaceAllInAuxIII#1\qStop{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \subsection{Batchfile commands} % \changes{2.3e}{1996/10/02}{Added doc} % \ds{} keeps information needed to control inclusion of sources in diff --git a/Master/texmf-dist/source/latex/base/fontdef.dtx b/Master/texmf-dist/source/latex/base/fontdef.dtx index c5623c5566e..632f1c9be56 100644 --- a/Master/texmf-dist/source/latex/base/fontdef.dtx +++ b/Master/texmf-dist/source/latex/base/fontdef.dtx @@ -39,7 +39,7 @@ %<driver, >\ProvidesFile{fontdef.drv} % \fi % \ProvidesFile{fontdef.dtx} -%<-latexrelease> [2020/02/11 v3.0g LaTeX Kernel +%<-latexrelease> [2020/08/01 v3.0i LaTeX Kernel % \iftrue (\else %<text, >(Text %<math, >(Math @@ -269,7 +269,7 @@ % % \changes{v3.0a}{2016/12/03}{(DPC) Default to TU encoding for Unicode TeX engines} % \begin{macrocode} -\ifx\Umathchar\@undefined +\ifx\Umathcode\@undefined % \end{macrocode} % % We then set the default text font encoding. This will @@ -436,7 +436,7 @@ % The following three definitions set up the meaning for % |\rmfamily|, |\sffamily|, and |\ttfamily|. % \begin{macrocode} -\ifx\Umathchar\@undefined +\ifx\Umathcode\@undefined \newcommand\encodingdefault{OT1} \newcommand\rmdefault{cmr} \newcommand\sfdefault{cmss} @@ -451,7 +451,7 @@ %</text> %<latexrelease>\IncludeInRelease{2017/01/01}% %<latexrelease> {\encodingdefault}{TU encoding default}% -%<latexrelease>\ifx\Umathchar\@undefined +%<latexrelease>\ifx\Umathcode\@undefined %<latexrelease>\renewcommand\encodingdefault{OT1} %<latexrelease>\fontencoding{\encodingdefault} %<latexrelease>\renewcommand\rmdefault{cmr} @@ -489,8 +489,8 @@ % Series changing commands are influenced by the following hooks. % \changes{v3.0e}{2019/12/17}{Set \cs{bfdefault} to ``b''} % \begin{macrocode} -\newcommand\bfdefault{b} % overwritten below -\newcommand\mddefault{m} +\newcommand\bfdefault{b} % overwritten below (for rollback) +\newcommand\mddefault{m} % overwritten below (for rollback) % \end{macrocode} % \end{macro} % \end{macro} @@ -506,7 +506,7 @@ \newcommand\itdefault{it} \newcommand\sldefault{sl} \newcommand\scdefault{sc} -\newcommand\updefault{up} % overwritten below +\newcommand\updefault{up} % overwritten below (for rollback) % \end{macrocode} % \end{macro} % \end{macro} @@ -519,8 +519,21 @@ %<*text|latexrelease> %<latexrelease>\IncludeInRelease{2020/02/02}% %<latexrelease> {\updefault}{font defaults change}% +% \begin{macrocode} \renewcommand\updefault{up} -\renewcommand\bfdefault{b} +% \end{macrocode} +% We append \cs{@empty} to the series value so that we can detect +% if it got changed via \cs{def} or \cs{renewcommand} later. +% \changes{v3.0h}{2020/03/19}{Support legacy use of \cs{bfdefault} +% and \cs{mddefault} (gh/306)} +% \begin{macrocode} +\renewcommand\bfdefault{b\@empty} +\renewcommand\mddefault{m\@empty} +% \end{macrocode} +% +% \begin{macrocode} +\let\bfdefault@previous\bfdefault +\let\mddefault@previous\mddefault %</text|latexrelease> %<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% @@ -528,6 +541,9 @@ %<latexrelease> %<latexrelease>\renewcommand\updefault{n} %<latexrelease>\renewcommand\bfdefault{bx} +%<latexrelease> +%<latexrelease>\let\bfdefault@previous\undefined +%<latexrelease>\let\mddefault@previous\undefined %<latexrelease>\EndIncludeInRelease %<*text> % \end{macrocode} @@ -549,8 +565,8 @@ % which resolved to \texttt{n}, but these days that is no longer % the case (and \texttt{up} is wrong when you want to do a % reset. So we now use \texttt{n} explicitly. -% \begin{macrocode} % \changes{v3.0e}{2019/12/17}{Set \cs{shapedefault} explicitly to ``n''} +% \begin{macrocode} \newcommand\shapedefault{n} % \end{macrocode} % \end{macro} diff --git a/Master/texmf-dist/source/latex/base/format.ins b/Master/texmf-dist/source/latex/base/format.ins index 940161edd5b..8796d16d3e2 100644 --- a/Master/texmf-dist/source/latex/base/format.ins +++ b/Master/texmf-dist/source/latex/base/format.ins @@ -161,7 +161,12 @@ the system are in the document `cfgguide.tex'. \from{ltdirchk.dtx}{initex,2ekernel,dircheck} \from{ltplain.dtx}{2ekernel} \from{ltvers.dtx}{2ekernel} + \from{ltluatex.dtx}{2ekernel} +% This is done as soon as possible here before \texttt{ltdefns.dtx} so that +% we have the extensions as soon as possible. + \from{ltexpl.dtx}{2ekernel} % expl3-based extensions \from{ltdefns.dtx}{2ekernel} + \from{lthooks.dtx}{2ekernel} % L3 layer module \from{ltalloc.dtx}{2ekernel} \from{ltcntrl.dtx}{2ekernel} \from{lterror.dtx}{2ekernel} @@ -194,9 +199,10 @@ the system are in the document `cfgguide.tex'. \from{ltidxglo.dtx}{2ekernel} \from{ltbibl.dtx}{2ekernel} \from{ltpage.dtx}{2ekernel} + \from{ltclass.dtx}{2ekernel,tracerollback} + \from{ltfilehook.dtx}{2ekernel} % L3 layer module + \from{ltshipout.dtx}{2ekernel} % L3 layer module \from{ltoutput.dtx}{2ekernel} - \from{ltclass.dtx}{2ekernel,tracerollback} - \from{ltluatex.dtx}{2ekernel} \from{ltfinal.dtx}{2ekernel}} \file{tracefnt.sty}{% \from{ltfsstrc.dtx}{package,trace}} @@ -225,8 +231,16 @@ the system are in the document `cfgguide.tex'. } -% expl3-based extensions -\generate{\file{ltexpl.ltx}{\from{ltexpl.dtx}{2ekernel}}} +% 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) diff --git a/Master/texmf-dist/source/latex/base/inputenc.dtx b/Master/texmf-dist/source/latex/base/inputenc.dtx index 641125cc75d..c1d08b4830f 100644 --- a/Master/texmf-dist/source/latex/base/inputenc.dtx +++ b/Master/texmf-dist/source/latex/base/inputenc.dtx @@ -261,18 +261,18 @@ % turn should ``hopefully'' set up the corresponding UTF-8 mapping). % % This works well enough for the main Western languages for which \LaTeX{} -% has proper font encoding support, but currently already falls short on -% languages like Greek (which has some semi-official font support, but for -% which corresponding UTF-8 mappings still need to be defined). +% has proper font encoding support, but can fall short on other +% languages. % -% For some languages (such as Greek mentioned above) all that remains doing is +% For some of these languages all that remains doing is % to provide the necessary mappings and stick them into |utf8ienc.dtx|, so % volunteers are welcome. For other languages that do not fit well into % \LaTeX{} font selection scheme, e.g., Asian languages the outlined inputenc % approach will not work. If that is the case one can try using Dominique % Unruh's option |utf8x| for inputenc which has a somewhat different approach % and encodes many more UTF-8 characters than the standard |utf8| option. -% However, we recommend to do so only if you really need such alphabets as +% However, we recommend to do so only if you really need such alphabets and can not +% switch to one of the unicode engines xelatex or lualatex as % there are problems with this extended approach which were precisely the % reason that we decided to limit the support to what is properly supported % within the boundaries of \LaTeX's font selection. @@ -410,7 +410,7 @@ %<cp1252&!ansinew> \ProvidesFile{cp1252.def} %<cp1250> \ProvidesFile{cp1250.def} %<cp1257> \ProvidesFile{cp1257.def} - [2018/08/11 v1.3c Input encoding file] + [2020/08/01 v1.3d Input encoding file] %<cp850>%% %<cp850>%% If you need a Euro symbol, try cp858 instead. %<cp850>%% @@ -545,7 +545,7 @@ % produces a warning message if no suitable definitions get read. % % \begin{macrocode} -\ifx\Umathchar\@undefined +\ifx\Umathcode\@undefined % \end{macrocode} % % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/base/latex209.dtx b/Master/texmf-dist/source/latex/base/latex209.dtx index 6523e65286f..d08a8001b56 100644 --- a/Master/texmf-dist/source/latex/base/latex209.dtx +++ b/Master/texmf-dist/source/latex/base/latex209.dtx @@ -200,7 +200,7 @@ % \end{macrocode} % Describe the file. % \begin{macrocode} -\ProvidesFile{latex209.def}[2018/08/11 v0.54 Standard LaTeX file] +\ProvidesFile{latex209.def}[2020/08/21 v0.55 Standard LaTeX file] % \end{macrocode} % \changes{v0.24}{1994/05/14}{Removed date.} % \changes{v0.40}{1995/03/21} @@ -469,6 +469,12 @@ \saved@missingfileerror{#1}{#2}% \fi } +\@ifundefined{@missing@onefilewithoptions}{}{% + \def\@missing@onefilewithoptions#1{% + \@pass@ptions\@currext{#1}{\@currname}% + \@missingfileerror\@currname\@currext + \let\@currname\@empty}% +} % \end{macrocode} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/base/latexrelease.ins b/Master/texmf-dist/source/latex/base/latexrelease.ins index ff55e7d8c0e..99af17e8fb6 100644 --- a/Master/texmf-dist/source/latex/base/latexrelease.ins +++ b/Master/texmf-dist/source/latex/base/latexrelease.ins @@ -86,7 +86,9 @@ extension .ins) which are part of the distribution. \from{ltvers.dtx} {latexrelease}% \from{latexrelease.dtx}{latexrelease}% \from{ltdirchk.dtx} {latexrelease}% + \from{ltexpl.dtx} {latexrelease}% empty \from{ltdefns.dtx} {latexrelease}% + \from{lthooks.dtx} {latexrelease}% empty % L3 layer module \from{ltalloc.dtx} {latexrelease}% empty \from{ltcntrl.dtx} {latexrelease}% empty \from{lterror.dtx} {latexrelease}% empty @@ -106,6 +108,8 @@ extension .ins) which are part of the distribution. \from{ltidxglo.dtx} {latexrelease}% empty \from{ltbibl.dtx} {latexrelease}% empty \from{ltpage.dtx} {latexrelease}% empty + \from{ltfilehook.dtx} {latexrelease}% empty % L3 layer module + \from{ltshipout.dtx} {latexrelease}% empty % L3 layer module \from{ltoutput.dtx} {latexrelease}% \from{ltclass.dtx} {latexrelease,tracerollback}% \from{ltspace.dtx} {latexrelease}% diff --git a/Master/texmf-dist/source/latex/base/letter.dtx b/Master/texmf-dist/source/latex/base/letter.dtx index ee9a87cf849..7b31dfbbc96 100644 --- a/Master/texmf-dist/source/latex/base/letter.dtx +++ b/Master/texmf-dist/source/latex/base/letter.dtx @@ -45,7 +45,7 @@ %<*driver> \ProvidesFile{letter.drv} %</driver> - [2014/09/29 v1.2z + [2020/03/11 v1.3b %<+letter> Standard LaTeX document class] % \end{macrocode} % @@ -115,10 +115,10 @@ % \end{macrocode} % Some commonly used abbreviations % \begin{macrocode} -\newcommand*{\Lopt}[1]{\textsf {#1}} -\newcommand*{\file}[1]{\texttt {#1}} -\newcommand*{\Lcount}[1]{\textsl {\small#1}} -\newcommand*{\pstyle}[1]{\textsl {#1}} +\newcommand*\Lopt[1]{\textsf {#1}} +\newcommand*\file[1]{\texttt {#1}} +\newcommand*\Lcount[1]{\textsl {\small#1}} +\newcommand*\pstyle[1]{\textsl {#1}} % \end{macrocode} % We also want the full details. % \begin{macrocode} @@ -162,6 +162,7 @@ % \changes{v1.2q}{1995/05/17}{cleaned up \cs{changes entries}} % \changes{v1.2q}{1995/05/18}{replaced \cs{hbox to} by \cs{hb@xt@}} % \changes{v1.2r}{1995/05/23}{removed a superfluous brace} +% \changes{v1.3a}{2020/03/07}{merged changes to classes.dtx into letter.dtx} % % \iffalse % Copyright (C) 1994 LaTeX3 project, Frank Mittelbach @@ -751,29 +752,29 @@ % \item |\name{Dr. L. User}| : to be used for the return address on % the envelope. % \begin{macrocode} -\newcommand*{\name}[1]{\def\fromname{#1}} +\newcommand*\name[1]{\def\fromname{#1}} % \end{macrocode} % \item |\signature{Larry User}| : goes after the closing. % \begin{macrocode} -\newcommand*{\signature}[1]{\def\fromsig{#1}} +\newcommand*\signature[1]{\def\fromsig{#1}} % \end{macrocode} % \item |\address{3245 Foo St.\\Gnu York}| : used as the return % address in the % letter and on the envelope. If not declared, then an % institutional standard address is used. % \begin{macrocode} -\newcommand*{\address}[1]{\def\fromaddress{#1}} +\newcommand*\address[1]{\def\fromaddress{#1}} % \end{macrocode} % \item |\location{Room 374}| : Acts as modifier to the standard % institutional address. % \begin{macrocode} -\newcommand*{\location}[1]{\def\fromlocation{#1}} +\newcommand*\location[1]{\def\fromlocation{#1}} % \end{macrocode} % \item |\telephone{(415)123-4567}| : Just in case some style puts it % on the letter. % \changes{v1.2m}{1994/06/23}{Removed typo (\#[] instead of [1])} % \begin{macrocode} -\newcommand*{\telephone}[1]{\def\telephonenum{#1}} +\newcommand*\telephone[1]{\def\telephonenum{#1}} % \end{macrocode} % \end{itemize} % \end{macro} @@ -805,7 +806,7 @@ % \begin{macro}{\makelabels} % The |\makelabels| declaration causes mailing labels to be made. % \begin{macrocode} -\newcommand*{\makelabels}{% +\newcommand*\makelabels{% % \end{macrocode} % At the beginning of the document, we need to activate the % |\@mlabel| and |\@startlabels| commands, as well as write @@ -914,7 +915,7 @@ % When the command |\stopbreaks| is issued no page breaks should % occur until |\startbreaks| is called. % \begin{macrocode} -\newcommand*{\stopbreaks}{% +\newcommand*\stopbreaks{% \interlinepenalty\@M \def\par{\@@par\nobreak}% \let\\\@nobreakcr @@ -953,7 +954,7 @@ % \begin{macro}{\startbreaks} % This cancels the effect of |\stopbreaks|. % \begin{macrocode} -\newcommand*{\startbreaks}{% +\newcommand*\startbreaks{% \let\\\@normalcr \interlinepenalty 200% \def\par{\@@par\penalty 200\relax}} @@ -1004,7 +1005,7 @@ % declaration--null if none. % \end{itemize} % \begin{macrocode} -\newcommand*{\opening}[1]{\ifx\@empty\fromaddress +\newcommand*\opening[1]{\ifx\@empty\fromaddress \thispagestyle{firstpage}% {\raggedleft\@date\par}% \else % home address @@ -1039,7 +1040,7 @@ % \item |\stopbreaks| : a macro that inhibits page breaking. % \end{itemize} % \begin{macrocode} -\newcommand{\closing}[1]{\par\nobreak\vspace{\parskip}% +\newcommand\closing[1]{\par\nobreak\vspace{\parskip}% \stopbreaks \noindent \ifx\@empty\fromaddress\else @@ -1085,7 +1086,7 @@ % \changes{v1.2s}{1995/05/25}{replace \cs{reset@font} with % \cs{normalfont}; remove \cs{rm}} % \begin{macrocode} -\newcommand*{\cc}[1]{% +\newcommand*\cc[1]{% \par\noindent \parbox[t]{\textwidth}{% \@hangfrom{\normalfont\ccname: }% @@ -1100,7 +1101,7 @@ % & Bar % \end{tabular} % \begin{macrocode} -\newcommand*{\encl}[1]{% +\newcommand*\encl[1]{% \par\noindent \parbox[t]{\textwidth}{% \@hangfrom{\normalfont\enclname: }% @@ -1110,7 +1111,7 @@ % The only thing |\ps| needs to do is call |\startbreaks|, % which allows page breaking again. % \begin{macrocode} -\newcommand*{\ps}{\par\startbreaks} +\newcommand*\ps{\par\startbreaks} % \end{macrocode} % \end{macro} % \end{macro} @@ -1137,7 +1138,7 @@ % |\protect\standardreturnaddress|. % \end{itemize} % \begin{macrocode} -\newcommand*{\stopletter}{} +\newcommand*\stopletter{} % \end{macrocode} % \end{macro} % @@ -1159,7 +1160,7 @@ % The return address for the mailing labels can be stored in this % macro. % \begin{macrocode} -\newcommand*{\returnaddress}{} +\newcommand*\returnaddress{} % \end{macrocode} % \end{macro} % @@ -1177,7 +1178,7 @@ % 5352 address labels. % \changes{v1.2q}{1995/03/14}{changed value of \cs{columnsep} by 1pt} % \begin{macrocode} -\newcommand*{\startlabels}{\labelcount\z@ +\newcommand*\startlabels{\labelcount\z@ \pagestyle{empty}% \let\@texttop\relax \topmargin -50\p@ @@ -1226,7 +1227,7 @@ % \changes{v1.2q}{1995/03/14}{changed width of the labels slightly to % prevent \LaTeX\ stuffing two on each line} % \begin{macrocode} -\newcommand*{\mlabel}[2]{% +\newcommand*\mlabel[2]{% \parbox[b][2in][c]{262\p@}{\strut\ignorespaces #2}% } % \end{macrocode} @@ -1267,7 +1268,7 @@ % For efficiency, level-one list's values are defined at top level, and % |\@listi| is defined to set only |\leftmargin|. % \begin{macrocode} -\setlength\leftmargini {2.5em} +\setlength\leftmargini {2.5em} % \end{macrocode} % The following three are calculated so that they are larger than % the sum of |\labelsep| and the width of the default labels (which @@ -1276,8 +1277,8 @@ \setlength\leftmarginii {2.2em} \setlength\leftmarginiii {1.87em} \setlength\leftmarginiv {1.7em} -\setlength\leftmarginv {1em} -\setlength\leftmarginvi {1em} +\setlength\leftmarginv {1em} +\setlength\leftmarginvi {1em} % \end{macrocode} % Here we set the top level leftmargin. % \begin{macrocode} @@ -1453,11 +1454,30 @@ % \changes{v1.2x}{1997/04/16}{Changed to \cs{textbullet}, % \cs{textasteriskcentered} and \cs{textperiodcentered}} % \begin{macrocode} -\newcommand\labelitemi{\textbullet} -\newcommand\labelitemii{\normalfont\bfseries \textendash} -\newcommand\labelitemiii{\textasteriskcentered} -\newcommand\labelitemiv{\textperiodcentered} +\newcommand\labelitemi {\labelitemfont \textbullet} +\newcommand\labelitemii {\labelitemfont \bfseries \textendash} +\newcommand\labelitemiii{\labelitemfont \textasteriskcentered} +\newcommand\labelitemiv {\labelitemfont \textperiodcentered} % \end{macrocode} +% +% \begin{macro}{\labelitemfont} +% The default definition for \cs{labelitemfont} is to reset the +% font to \cs{normalfont} so that always the same symbol is +% produced regardless of surrounding conditions. +% +% \changes{v1.3a}{2020/03/07}{Normalize label fonts} +% A possible alternative would be +%\begin{verbatim} +%\renewcommand\labelitemfont{% +% \fontseries\seriesdefault +% \fontshape\shapedefault\selectfont} +%\end{verbatim} +% which resets series and shape doesn't touch the family. +% \begin{macrocode} +\newcommand\labelitemfont{\normalfont} +% \end{macrocode} +% \changes{v1.3b}{2020/03/11}{Added a missing \cs{end{macro}} statement} +% \end{macro} % \end{macro} % \end{macro} % \end{macro} @@ -1484,8 +1504,8 @@ % % \changes{v1.2q}{1995/03/14}{made command short} % \begin{macrocode} -\newcommand*{\descriptionlabel}[1]{\hspace\labelsep - \normalfont\bfseries #1} +\newcommand*\descriptionlabel[1]{\hspace\labelsep + \normalfont\bfseries #1} % \end{macrocode} % \end{macro} % @@ -1795,8 +1815,10 @@ % |\parindent| to the appropriate value for succeeding paragraphs % and put the proper indentation before the mark. % +% \changes{v1.3b}{2020/03/11}{make the switch to the use of +% \cs{newcommand} complete.} % \begin{macrocode} -\long\def\@makefntext#1{% +\newcommand\@makefntext[1]{% \noindent \hangindent 5\p@ \hb@xt@5\p@{\hss\@makefnmark}#1} @@ -1808,10 +1830,12 @@ % footnotes should be produced by the macro |\@makefnmark|. We use % the default definition for it. % \begin{macrocode} -%\def\@makefnmark{\hbox{$^{\@thefnmark}\m@th$}} +%\renewcommand\@makefnmark{\hbox{$^{\@thefnmark}\m@th$}} % \end{macrocode} % \end{macro} % +% \section{Initialization} +% % \subsection{Words} % % \begin{macro}{\ccname} @@ -1823,10 +1847,10 @@ % English words must be replaced. All the English words that % require replacement are defined below in command names. % \begin{macrocode} -\newcommand*{\ccname}{cc} -\newcommand*{\enclname}{encl} -\newcommand*{\pagename}{Page} -\newcommand*{\headtoname}{To} +\newcommand*\ccname{cc} +\newcommand*\enclname{encl} +\newcommand*\pagename{Page} +\newcommand*\headtoname{To} % \end{macrocode} % \end{macro} % \end{macro} @@ -1839,7 +1863,7 @@ % This macro uses the \TeX\ primitives |\month|, |\day| and |\year| % to provide the date of the \LaTeX-run. % \begin{macrocode} -\newcommand*{\today}{\ifcase\month\or +\newcommand*\today{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} diff --git a/Master/texmf-dist/source/latex/base/ltboxes.dtx b/Master/texmf-dist/source/latex/base/ltboxes.dtx index 61ea87235ab..39c134b3bfd 100644 --- a/Master/texmf-dist/source/latex/base/ltboxes.dtx +++ b/Master/texmf-dist/source/latex/base/ltboxes.dtx @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltboxes.dtx} - [2019/08/27 v1.3b LaTeX Kernel (Box Commands)] + [2020/09/27 v1.4a LaTeX Kernel (Box Commands)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltboxes.dtx} @@ -365,8 +365,13 @@ % \begin{macro}{\@imakepicbox} % picture mode version % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@imakepicbox}{default units}% \long\def\@imakepicbox(#1,#2)[#3]#4{% - \vbox to#2\unitlength + \@defaultunitsset\@tempdimc{#2}\unitlength + \vbox to\@tempdimc {\let\mb@b\vss \let\mb@l\hss\let\mb@r\hss \let\mb@t\vss \@tfor\reserved@a :=#3\do{% @@ -376,14 +381,38 @@ \expandafter\let\csname mb@\reserved@a\endcsname\relax \fi}% \mb@t - \hb@xt@ #1\unitlength{\mb@l #4\mb@r}% + \@defaultunitsset\@tempdimc{#1}\unitlength + \hb@xt@\@tempdimc{\mb@l #4\mb@r}% \mb@b % \end{macrocode} % This kern ensures that a |b| option aligns on the bottom of the % text rather than the baseline. this is the documented behaviour in -% the \LaTeX Book. The kern is removed in compatibility mode. +% the \LaTeX\ Book. The kern is removed in compatibility mode. % \begin{macrocode} \kern\z@}} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@imakepicbox}{default units}% +%<latexrelease>\long\def\@imakepicbox(#1,#2)[#3]#4{% +%<latexrelease> \vbox to#2\unitlength +%<latexrelease> {\let\mb@b\vss \let\mb@l\hss\let\mb@r\hss +%<latexrelease> \let\mb@t\vss +%<latexrelease> \@tfor\reserved@a :=#3\do{% +%<latexrelease> \if s\reserved@a +%<latexrelease> \let\mb@l\relax\let\mb@r\relax +%<latexrelease> \else +%<latexrelease> \expandafter\let\csname mb@\reserved@a\endcsname\relax +%<latexrelease> \fi}% +%<latexrelease> \mb@t +%<latexrelease> \hb@xt@ #1\unitlength{\mb@l #4\mb@r}% +%<latexrelease> \mb@b +%<latexrelease> \kern\z@}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -1290,13 +1319,21 @@ % % \begin{macro}{\rlap} % \begin{macro}{\llap} +% \begin{macro}{\clap} % These macros place text to the left or right of the current % reference point without taking up space. -% \end{macro} % \begin{macrocode} \DeclareRobustCommand\rlap[1]{\hb@xt@\z@{#1\hss}} \DeclareRobustCommand\llap[1]{\hb@xt@\z@{\hss#1}} % \end{macrocode} +% And here is the version that centers, it was initially introduced by +% \texttt{mathtools}. +% \changes{v1.3c}{2020/03/06}{Macro \cs{clap} added} +% \begin{macrocode} +\DeclareRobustCommand\clap[1]{\hb@xt@\z@{\hss#1\hss}} +% \end{macrocode} +% \end{macro} +% \end{macro} % \end{macro} % % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/base/ltclass.dtx b/Master/texmf-dist/source/latex/base/ltclass.dtx index 578443921b8..bc6500541e5 100644 --- a/Master/texmf-dist/source/latex/base/ltclass.dtx +++ b/Master/texmf-dist/source/latex/base/ltclass.dtx @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltclass.dtx} - [2020/02/20 v1.3j LaTeX Kernel (Class & Package Interface)] + [2020/10/01 v1.3r LaTeX Kernel (Class & Package Interface)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltclass.dtx} @@ -44,6 +44,9 @@ \date{\filedate} \MaintainedByLaTeXTeam{latex} \maketitle + + \providecommand\pkg[1]{\texttt{#1}} + \DocInput{\filename} \end{document} %</driver> @@ -64,6 +67,7 @@ % \changes{v1.0l}{1994/11/17}{\cs{@tempa} to \cs{reserved@a}} % \changes{v1.0z}{1998/03/21}{Added to documentation of filecontents} % \changes{v1.1c}{1998/08/17}{(RmS) Minor documentation fixes.} +% \changes{v1.3o}{2020/08/21}{Integration of new hook management interface} % % % \section{Introduction} @@ -161,7 +165,7 @@ % option \texttt{nosearch} will only check the current directory % when looking if the file exists. This can be useful if you want to % generate a local (modified) copy of some file that is already in the -% search tree of \TeX{}. Finally, you can use \texttt{nopremable} to +% search tree of \TeX{}. Finally, you can use \texttt{noheader} to % prevent it from writing the standard blurb at the top of the file % (this is actually the same as using the star form of the environment). % @@ -256,8 +260,9 @@ % \PassOptionsToPackage{foo,bar}{fred} % \RequirePackage[baz]{fred}\end{verbatim} % is the same as: -% \begin{verbatim} -% \RequirePackage[foo,bar,baz]{fred}\end{verbatim} +%\begin{verbatim} +% \RequirePackage[foo,bar,baz]{fred} +%\end{verbatim} % % \DescribeMacro\LoadClassWithOptions % |\LoadClassWithOptions|\marg{name}\oarg{version}:\\ @@ -458,7 +463,9 @@ % \end{macro} % % \begin{macro}{\@documentclasshook} -% The hook called after the first |\documentclass| command. By +% This legacy hook is called after the first |\documentclass| command. +% It is \emph{not} integrated with the new 2020 hook management system! +% By % default this checks to see if |\@normalsize| is undefined, and if % so, sets it to |\normalsize|. % \changes{v0.2q}{1993/12/17} @@ -552,22 +559,75 @@ % |#2| current extension. \\ % |#3| current catcode of |@|. \\ % |#4| Rest of the stack. +% \changes{v1.3l}{2020/06/05}{Added \cs{@expl@push@filename@@} +% and \cs{@expl@push@filename@aux@@}} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}{\@pushfilename}% +%<latexrelease> {Add \@expl@push@filename@@ and \@expl@push@filename@aux@@}% \def\@pushfilename{% +% \end{macrocode} +% The push and pop macros are injected in \cs{@pushfilename} and +% \cs{@popfilename} so that they correctly keep track of the hook +% labels. +% +% This needs cleanup with the \pkg{expl3} interfaces also playing +% here, e.g., \cs{@expl@push@filename@@} needs cleanup and (and +% should probably not have this name either). +% \begin{macrocode} + \@expl@@@hook@curr@name@push@@n{}% + \@expl@push@filename@@ \xdef\@currnamestack{% {\@currname}% {\@currext}% {\the\catcode`\@}% - \@currnamestack}} + \@currnamestack}% + \@expl@push@filename@aux@@} +%<latexrelease>\EndIncludeInRelease +%<latexrelease> +%<latexrelease>\IncludeInRelease{0000/00/00}{\@pushfilename}% +%<latexrelease> {Add \@expl@push@filename@@ and \@expl@push@filename@aux@@}% +%<latexrelease>\def\@pushfilename{% +%<latexrelease> \xdef\@currnamestack{% +%<latexrelease> {\@currname}% +%<latexrelease> {\@currext}% +%<latexrelease> {\the\catcode`\@}% +%<latexrelease> \@currnamestack}} +%<latexrelease>\EndIncludeInRelease \@onlypreamble\@pushfilename % \end{macrocode} % +% +% +% +% +% \changes{v1.3l}{2020/06/05}{Added \cs{@expl@pop@filename@@}} % \begin{macrocode} -\def\@popfilename{\expandafter\@p@pfilename\@currnamestack\@nil} +%<latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}{\@popfilename}% +%<latexrelease> {Add \@expl@pop@filename@@}% +\def\@popfilename{\@expl@@@hook@curr@name@pop@@ + \expandafter\@p@pfilename\@currnamestack\@nil + \@expl@pop@filename@@} +%<latexrelease>\EndIncludeInRelease +%<latexrelease> +%<latexrelease>\IncludeInRelease{0000/00/00}{\@popfilename}% +%<latexrelease> {Add \@expl@push@filename@@ and \@expl@push@filename@aux@@}% +%<latexrelease>\def\@popfilename{\expandafter\@p@pfilename\@currnamestack\@nil} +%<latexrelease>\EndIncludeInRelease \@onlypreamble\@popfilename % \end{macrocode} % % \begin{macrocode} +%</2ekernel|latexrelease> +%<*2ekernel> +% \end{macrocode} +% +% +% +% \begin{macrocode} \def\@p@pfilename#1#2#3#4\@nil{% \gdef\@currname{#1}% \gdef\@currext{#2}% @@ -620,15 +680,60 @@ % % \begin{macro}{\@ifpackagelater} % \begin{macro}{\@ifclasslater} -% |\@ifpackagelater{|\meta{name}|}{YYYY/MM/DD}| -% Checks that the package loaded is more recent than the given date. +% |\@ifpackagelater{|\meta{name}|}{YYYY/MM/DD}{|\meta{true +% code}|}{|\meta{false code}|}| +% Checks that the package loaded is more recent or equal to the +% given date. +% A better name for it would therefore been +% |\@ifpackagelaterorequal| but it is in use for more than 30 +% years, so \ldots % \begin{macrocode} \def\@ifpackagelater{\@ifl@ter\@pkgextension} \def\@ifclasslater{\@ifl@ter\@clsextension} \@onlypreamble\@ifpackagelater \@onlypreamble\@ifclasslater % \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% \begin{macro}{\IfPackageAtLeastTF} +% \begin{macro}{\IfClassAtLeastTF} +% \begin{macro}{\IfFormatAtLeastTF} +% |\IfFormatAtLeastTF{YYYY/MM/DD}{|\meta{true +% code}|}{|\meta{false code}|}| +% Test if the format is later or equal to the given date. +% \changes{v1.3k}{2020/04/07}{Macro added; also in rollback (gh/168)} +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\IfFormatAtLeastTF}{Test format date}% +\def\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} +\let\IfPackageAtLeastTF\@ifpackagelater +\let\IfClassAtLeastTF\@ifclasslater +\@onlypreamble\IfFormatAtLeastTF +\@onlypreamble\IfPackageAtLeastTF +\@onlypreamble\IfClassAtLeastTF +% \end{macrocode} +% For rollback pretend it was available since the beginning of dawn. +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\IfFormatAtLeastTF}{Test format date}% +%<latexrelease>\def\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} +%<latexrelease>\let\IfPackageAtLeastTF\@ifpackagelater +%<latexrelease>\let\IfClassAtLeastTF\@ifclasslater +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} % +% \begin{macro}{\@ifl@ter} % \begin{macrocode} \def\@ifl@ter#1#2{% \expandafter\@ifl@t@r @@ -675,6 +780,7 @@ % \begin{macrocode} \@onlypreamble\@ifl@t@r % \end{macrocode} +% \end{macro} % % \changes{v1.1j}{2016/06/20} % {don't declare as \cs{@onlypreamble}} @@ -695,8 +801,8 @@ %</2ekernel|latexreleasefirst> %<*2ekernel> % \end{macrocode} -% \end{macro} -% \end{macro} +% +% % % \begin{macro}{\@ifpackagewith} % \begin{macro}{\@ifclasswith} @@ -800,14 +906,17 @@ % 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} % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2020/02/02}% -%<latexrelease> {\@pr@videpackage}{Protection for package info}% +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@pr@videpackage}{Allow for package subsitution}% \def\@pr@videpackage[#1]{% \expandafter\protected@xdef % <-- protected... - \csname ver@\@currname.\@currext\endcsname{#1}% + \csname ver@\@currname.\@currext\endcsname{#1}% Loaded package + \expandafter\protected@xdef % <-- protected... + \csname ver@\@currpkg@reqd\endcsname{#1}% Requested package \ifx\@currext\@clsextension \typeout{Document Class: \@gtempa\space#1}% \else @@ -832,6 +941,19 @@ % \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/02/02}% +%<latexrelease> {\@pr@videpackage}{Protection for package info}% +%<latexrelease> +%<latexrelease>\def\@pr@videpackage[#1]{% +%<latexrelease> \expandafter\protected@xdef % <-- protected... +%<latexrelease> \csname ver@\@currname.\@currext\endcsname{#1}% +%<latexrelease>\ifx\@currext\@clsextension +%<latexrelease> \typeout{Document Class: \@gtempa\space#1}% +%<latexrelease> \else +%<latexrelease> \protected@wlog{Package: \@gtempa\space#1}% <--- protected +%<latexrelease> \fi} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\@pr@videpackage}{Protection for package info}% %<latexrelease> @@ -915,11 +1037,28 @@ % 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. % \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2020/10/01}{\@pass@ptions} +%<latexrelease> {Add file replacement in \@pass@ptions}% +%<*2ekernel|latexrelease> \def\@pass@ptions#1#2#3{% - \expandafter\xdef\csname opt@#3.#1\endcsname{% - \@ifundefined{opt@#3.#1}\@empty - {\csname opt@#3.#1\endcsname,}% + \edef\reserved@a{\@expl@@@filehook@resolve@file@subst@@w #3.#1\@nil}% + \expandafter\xdef\csname opt@\reserved@a\endcsname{% + \@ifundefined{opt@\reserved@a}\@empty + {\csname opt@\reserved@a\endcsname,}% \zap@space#2 \@empty}} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% +%<latexrelease>\IncludeInRelease{0000/00/00}{\@pass@ptions} +%<latexrelease> {\@pass@ptions}% +%<latexrelease>\def\@pass@ptions#1#2#3{% +%<latexrelease> \expandafter\xdef\csname opt@#3.#1\endcsname{% +%<latexrelease> \@ifundefined{opt@#3.#1}\@empty +%<latexrelease> {\csname opt@#3.#1\endcsname,}% +%<latexrelease> \zap@space#2 \@empty}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> \@onlypreamble\@pass@ptions % \end{macrocode} % @@ -1050,6 +1189,10 @@ % % The common part of |\ProcessOptions| and |\ProcessOptions*|. % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@process@pti@ns}{Unused options issue}% \def\@process@pti@ns{% \@for\CurrentOption:=\@curroptions\do{% \@ifundefined{ds@\CurrentOption}% @@ -1073,11 +1216,33 @@ % \end{macrocode} % \changes{v1.0r}{1995/10/17} % {Reset \cs{CurrentOption} for graphics/1873} +% \changes{v1.3k}{2020/04/07}{Use different method to ignore +% unprocessed options (gh/22)} % \begin{macrocode} \let\CurrentOption\@empty \let\@fileswith@pti@ns\@@fileswith@pti@ns - \AtEndOfPackage{\let\@unprocessedoptions\relax}} + \AtEndOfPackage{\expandafter\let + \csname unprocessedoptions-\@currname.\@currext\endcsname + \relax}} \@onlypreamble\@process@pti@ns +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@process@pti@ns}{Unused options issue}% +%<latexrelease> +%<latexrelease>\def\@process@pti@ns{% +%<latexrelease> \@for\CurrentOption:=\@curroptions\do{% +%<latexrelease> \@ifundefined{ds@\CurrentOption}% +%<latexrelease> {\@use@ption +%<latexrelease> \default@ds}% +%<latexrelease> \@use@ption}% +%<latexrelease> \@for\CurrentOption:=\@declaredoptions\do{% +%<latexrelease> \expandafter\let\csname ds@\CurrentOption\endcsname\relax}% +%<latexrelease> \let\CurrentOption\@empty +%<latexrelease> \let\@fileswith@pti@ns\@@fileswith@pti@ns +%<latexrelease> \AtEndOfPackage{\let\@unprocessedoptions\relax}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % \end{macro} @@ -1243,13 +1408,45 @@ % \changes{v1.0v}{1996/10/04}{Reset \cs{@unprocessedoptions} for /2269} % Load package `|#1|' with the current option list. % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\RequirePackageWithOptions}{Unused options issue}% \def\RequirePackageWithOptions{% - \AtEndOfPackage{\let\@unprocessedoptions\relax}% +% \end{macrocode} +% The resetting of the unprocessed options is now done on a par package basis. +% \changes{v1.3k}{2020/04/07}{Use different method to ignore +% unprocessed options (gh/22)} +% \begin{macrocode} + \AtEndOfPackage{\expandafter\let + \csname unprocessedoptions-\@currname.\@currext\endcsname + \relax}% \@loadwithoptions\@pkgextension\RequirePackage} \@onlypreamble\RequirePackageWithOptions +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\RequirePackageWithOptions}{Unused options issue}% +%<latexrelease> +%<latexrelease>\def\RequirePackageWithOptions{% +%<latexrelease> \AtEndOfPackage{\let\@unprocessedoptions\relax}% +%<latexrelease> \@loadwithoptions\@pkgextension\RequirePackage} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % +% + + + + + + +% % \begin{macro}{\usepackage} % To begin with, |\usepackage| produces an error. This is reset by % |\documentclass|. @@ -1469,6 +1666,9 @@ \@onlypreamble\@fileswith@pti@ns % \end{macrocode} % +% \begin{macro}{\load@onefilewithoptions} +% This macro is used when loading packages or classes. +% % Have the main argument as |#1|, so we only need one |\expandafter| % above. % \changes{v0.2a}{1993/11/14} @@ -1482,91 +1682,338 @@ % \changes{v1.3d}{2019/10/18}{Initialize \cs{...-h@@k} only when loading % the package or class (gh/198)} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@onefilewithoptions}{Hooks and unused options issue}% \def\@onefilewithoptions#1[#2][#3]#4{% \@pushfilename \xdef\@currname{#1}% \global\let\@currext#4% +% \end{macrocode} +% The command \cs{ver@\meta{file}.\meta{ext}} is used to signal that +% a package is already loaded, either because it is in fact loaded, or +% because it's loading was suppressed. In minimal installations, said +% package may not exist but still have its loading suppressed with +% \cs{ver@\meta{file}.\meta{ext}}, so before checking if the file +% exists we have to check that we do need to load it with +% \cs{@ifl@aded}. If we don't, then there's no point in checking for +% a typo or load-disabling. +% \begin{macrocode} + \@ifl@aded\@currext\@currname +% \end{macrocode} +% If the package is already loaded, check that there were no option +% clashes: +% \changes{v1.1b}{1998/05/07} +% {Modify help message for latex/2805} +% \begin{macrocode} + {\@if@ptions\@currext{\@currname}{#2}{}% + {\@latex@error + {Option clash for \@cls@pkg\space \@currname}% + {The package \@currname\space has already been loaded + with options:\MessageBreak + \space\space[\@ptionlist{\@currname.\@currext}]\MessageBreak + There has now been an attempt to load it + with options\MessageBreak + \space\space[#2]\MessageBreak + Adding the global options:\MessageBreak + \space\space + \@ptionlist{\@currname.\@currext},#2\MessageBreak + to your \noexpand\documentclass declaration may fix this.% + \MessageBreak + Try typing \space <return> \space to proceed.}}% + \@firstofone}% + {\makeatletter +% \end{macrocode} +% The next line seems to be necessary for 2.09 compatibility (the +% way the code is written there) This seems questionable and should be +% look at as in 2e it is definitely unnecessary at this point! +% \begin{macrocode} + \@reset@ptions +% \end{macrocode} +% First we take the \meta{name} and \meta{ext} given in the argument +% and check if the file exists, and issue an error otherwise asking +% for a correction with \cs{@missingfileerror}. +% \begin{macrocode} + \IfFileExists{\@currname.\@currext}{}% + {\@missing@onefilewithoptions{#2}}% +% \end{macrocode} +% If \cs{@currname} is empty (the user replied to the ``Enter file +% name'' prompt with \meta{RETURN}), so stop here +% (do \cs{@popfilename} to pop the item just added above). +% +% This \cs{@gobble} omits the date check at the end. +% \begin{macrocode} + \ifx\@currname\@empty + \expandafter\@gobble + \else +% \end{macrocode} +% If the file exists, check if it was load-prevented, and otherwise +% do the bookkeeping with \cs{@filehook@file@push} +% then call \cs{set@curr@file} to set \cs{@curr@file} (and do any +% required substitution), then actually load the class/package with +% \cs{load@onefile@withoptions}. +% \begin{macrocode} + \@disable@packageload@do{\@currname.\@currext}% + {\@expl@@@filehook@file@push@@ + \set@curr@file{\@currname.\@currext}% + \@filehook@set@CurrentFile +% \end{macrocode} +% \changes{v1.3q}{2020/09/06} +% {Save \cs{@currpkg@reqd} so that we don't lose track of +% package substitutions.} +% The \cs{set@curr@file} line above might have replaced the file, so +% \cs{@currname} and \cs{@currext} may no longer hold the actual +% package being loaded, so in that case we need to update these two +% token lists (\cs{@curr@file} holds the file name after replacement, +% so we parse that). +% +% The requested file is saved in \cs{@currpkg@reqd} to be used in +% \cs{InputIfFileExists} later: if the updated \cs{@currname} and +% \cs{@currext} are used we lose track of the substitution, so +% \cs{CurrentFile} and \cs{CurrentFileUsed} will be (incorrectly) +% the same. +% \begin{macrocode} + \edef\@currpkg@reqd{\@currname.\@currext}% + \ifx\CurrentFile\CurrentFileUsed + \else + \filename@parse\@curr@file + \edef\@currname{\string@makeletter\filename@base}% + \edef\@currext{\string@makeletter\filename@ext}% + \fi + \load@onefile@withoptions{#2}% +% \end{macrocode} +% Now just clean up and exit. +% \begin{macrocode} + \@expl@@@filehook@file@pop@@}% + \expandafter\@firstofone + \fi}% +% \end{macrocode} +% Except in the case where \cs{@currname} is empty, the date is +% checked against the date marked in the package file: +% \begin{macrocode} + {\@ifl@ter\@currext{\@currname}{#3}{}% + {\@latex@warning@no@line + {You have requested,\on@line, + version\MessageBreak + `#3' of \@cls@pkg\space \@currname,\MessageBreak + but only version\MessageBreak + `\csname ver@\@currname.\@currext\endcsname'\MessageBreak + is available}}% +% \end{macrocode} +% \changes{v0.2c}{1993/11/17} +% {Added trap for two \cs{LoadClass} commands.} +% \begin{macrocode} + \ifx\@currext\@clsextension\let\LoadClass\@twoloadclasserror\fi}% + \@popfilename + \@reset@ptions} +% \end{macrocode} +% +% \begin{macrocode} +\@onlypreamble\@onefilewithoptions +% \end{macrocode} +% +% The kernel no longer uses \cs{@unprocessedoptions} +% \begin{macrocode} +\let\@unprocessedoptions\@undefined +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@missing@onefilewithoptions} +% Now the action taken when a file is not found. +% \begin{macrocode} +\def\@missing@onefilewithoptions#1{% + \@missingfileerror\@currname\@currext + \xdef\@currname{\@missingfile@area\@missingfile@base}% + \global\let\@currext\@missingfile@ext} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\load@onefile@withoptions} +% Now the code that actually does the file loading: +% \begin{macrocode} +\def\load@onefile@withoptions#1{% \let\CurrentOption\@empty \@reset@ptions - \makeatletter % \end{macrocode} % Grab everything in a macro, so the parameter stack is popped before % any processing begins. % \changes{v0.2s}{1994/01/17} % {Modify to reduce parameter stack usage} -% \changes{v1.1b}{1998/05/07} -% {Modify help message for latex/2805} % \begin{macrocode} \def\reserved@a{% - \@ifl@aded\@currext{#1}% - {\@if@ptions\@currext{#1}{#2}{}% - {\@latex@error - {Option clash for \@cls@pkg\space #1}% - {The package #1 has already been loaded - with options:\MessageBreak - \space\space[\@ptionlist{#1.\@currext}]\MessageBreak - There has now been an attempt to load it - with options\MessageBreak - \space\space[#2]\MessageBreak - Adding the global options:\MessageBreak - \space\space - \@ptionlist{#1.\@currext},#2\MessageBreak - to your \noexpand\documentclass declaration may fix this.% - \MessageBreak - Try typing \space <return> \space to proceed.}}}% - {\@pass@ptions\@currext{#2}{#1}% -% \end{macrocode} -% \changes{v0.3c}{1994/03/12} -% {Do not use \cs{@pr@videpackage} to avoid typeout} -% \begin{macrocode} - \global\expandafter - \let\csname ver@\@currname.\@currext\endcsname\@empty + \@pass@ptions\@currext{#1}{\@currname}% + \global\expandafter + \let\csname ver@\@currname.\@currext\endcsname\@empty % \end{macrocode} % We initialize \cs{...-h@@k} here and only if we load the file so that it % remains undefined otherwise. % \begin{macrocode} - \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty - \InputIfFileExists - {\@currname.\@currext}% - {}% - {\@missingfileerror\@currname\@currext}% + \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty +% \end{macrocode} +% When the current extension is \cs{@pkgextension} we are loading a +% package otherwise, if it is \cs{@clsextension}, a class, so +% depending on that we execute different hooks. If the extension is +% neither, then it is another type of file without special hooks. +% \begin{macrocode} +%----------------------------------------- + \ifx\@currext\@pkgextension + \UseHook{package/before}% + \UseHook{package/before/\@currname}% + \else + \ifx\@currext\@clsextension + \UseHook{class/before}% + \UseHook{class/before/\@currname}% + \fi + \fi % \end{macrocode} -% |\@unprocessedoptions| will generate an error for each specified -% option in a package unless a |\ProcessOptions| has appeared in the -% package file. +% Now actually load the file (at this point we are certain it exists, +% but use \cs{InputIfFileExists} so that file hooks are executed): +% \begin{macrocode} + \InputIfFileExists{\@currpkg@reqd}{}% + {\@latex@error + {The \@cls@pkg\space\@currpkg@reqd\space failed to load.}\@ehd}% +%----------------------------------------- +% \end{macrocode} +% In older versions of the code |\@unprocessedoptions| would +% generate an error for each specified +% option in a package unless a |\ProcessOptions| has appeared in the +% package file. % \changes{v0.2v}{1994/01/29} % {All options raise error if no \cs{ProcessOptions} appears} % \changes{v0.2x}{1994/02/02} -% {Only run the hook and options check if the file was loaded.} -% \begin{macrocode} - \let\@unprocessedoptions\@@unprocessedoptions +% {Only run the hook and options check if the file was +% loaded.} +% +% This has changed in 2020. We now use a separate macro per package +% to avoid interferences 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 +% unprocessed options (gh/22)} +% \begin{macrocode} + \expandafter\let\csname unprocessedoptions-\@currname.\@currext\endcsname + \@@unprocessedoptions \csname\@currname.\@currext-h@@k\endcsname \expandafter\let\csname\@currname.\@currext-h@@k\endcsname \@undefined - \@unprocessedoptions}% % \end{macrocode} -% +% Catch the case where the packages has handled the options and +% redefined \cs{@unprocessedoptions} to \cs{relax} (old interface). +% In that case no error should be produced. +% \changes{v1.3k}{2020/04/07}{Use different method to ignore +% unprocessed options (gh/22)} % \begin{macrocode} - \@ifl@ter\@currext{#1}{#3}{}% - {\@latex@warning@no@line - {You have requested,\on@line, - version\MessageBreak - `#3' of \@cls@pkg\space #1,\MessageBreak - but only version\MessageBreak - `\csname ver@#1.\@currext\endcsname'\MessageBreak - is available}}% + \ifx\@unprocessedoptions\relax + \let\@unprocessedoptions\@undefined % \end{macrocode} -% \changes{v0.2c}{1993/11/17} -% {Added trap for two \cs{LoadClass} commands.} +% Otherwise run the per package set of unused options. % \begin{macrocode} - \ifx\@currext\@clsextension\let\LoadClass\@twoloadclasserror\fi - \@popfilename - \@reset@ptions}% - \reserved@a} -\@onlypreamble\@onefilewithoptions + \else + \csname unprocessedoptions-\@currname.\@currext\endcsname + \fi +% \end{macrocode} +% In either case we drop the macro afterwards as it is no longer needed. +% \begin{macrocode} + \expandafter\let + \csname unprocessedoptions-\@currname.\@currext\endcsname + \@undefined +% \end{macrocode} +% And same procedure, James, when we are finished loading, except +% that the hook order is now reversed. +% \begin{macrocode} +%----------------------------------------- + \ifx\@currext\@pkgextension + \UseHook{package/after/\@currname}% + \UseHook{package/after}% + \else + \ifx\@currext\@clsextension + \UseHook{class/after/\@currname}% + \UseHook{class/after}% + \fi + \fi}% +%----------------------------------------- + \@ifl@aded\@currext\@currname{}{\reserved@a}} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@onefilewithoptions}{Hooks and unused options issue}% +%<latexrelease> +% \end{macrocode} +% Because of the way \cs{@onfilewithoptions} is changed for +% rollback handling below we have to define +% \cs{load@onefilewithoptions} when rolling back! +% \begin{macrocode} +%<latexrelease>\def\load@onefilewithoptions#1[#2][#3]#4{% +%<latexrelease> \@pushfilename +%<latexrelease> \xdef\@currname{#1}% +%<latexrelease> \global\let\@currext#4% +%<latexrelease> \let\CurrentOption\@empty +%<latexrelease> \@reset@ptions +%<latexrelease> \makeatletter +%<latexrelease> \def\reserved@a{% +%<latexrelease> \@ifl@aded\@currext{#1}% +%<latexrelease> {\@if@ptions\@currext{#1}{#2}{}% +%<latexrelease> {\@latex@error +%<latexrelease> {Option clash for \@cls@pkg\space #1}% +%<latexrelease> {The package #1 has already been loaded +%<latexrelease> with options:\MessageBreak +%<latexrelease> \space\space[\@ptionlist{#1.\@currext}]\MessageBreak +%<latexrelease> There has now been an attempt to load it +%<latexrelease> with options\MessageBreak +%<latexrelease> \space\space[#2]\MessageBreak +%<latexrelease> Adding the global options:\MessageBreak +%<latexrelease> \space\space +%<latexrelease> \@ptionlist{#1.\@currext},#2\MessageBreak +%<latexrelease> to your \noexpand\documentclass declaration may fix this.% +%<latexrelease> \MessageBreak +%<latexrelease> Try typing \space <return> \space to proceed.}}}% +%<latexrelease> {\@pass@ptions\@currext{#2}{#1}% +%<latexrelease> \global\expandafter +%<latexrelease> \let\csname ver@\@currname.\@currext\endcsname\@empty +%<latexrelease> \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty +%<latexrelease> \InputIfFileExists +%<latexrelease> {\@currname.\@currext}% +%<latexrelease> {}% +%<latexrelease> {\@missingfileerror\@currname\@currext}% +%<latexrelease> \let\@unprocessedoptions\@@unprocessedoptions +%<latexrelease> \csname\@currname.\@currext-h@@k\endcsname +%<latexrelease> \expandafter\let\csname\@currname.\@currext-h@@k\endcsname +%<latexrelease> \@undefined +%<latexrelease> \@unprocessedoptions}% +%<latexrelease> \@ifl@ter\@currext{#1}{#3}{}% +%<latexrelease> {\@latex@warning@no@line +%<latexrelease> {You have requested,\on@line, +%<latexrelease> version\MessageBreak +%<latexrelease> `#3' of \@cls@pkg\space #1,\MessageBreak +%<latexrelease> but only version\MessageBreak +%<latexrelease> `\csname ver@#1.\@currext\endcsname'\MessageBreak +%<latexrelease> is available}}% +%<latexrelease> \ifx\@currext\@clsextension\let\LoadClass\@twoloadclasserror\fi +%<latexrelease> \@popfilename +%<latexrelease> \@reset@ptions}% +%<latexrelease> \reserved@a} +%<latexrelease> +%<latexrelease>\let \load@onefile@withoptions \@undefined +%<latexrelease>\let \@missing@onefilewithoptions \@undefined +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % +% +% +% +% +% % \begin{macro}{\@@fileswith@pti@ns} % Save the definition (for error checking). % \changes{v0.2c}{1993/11/17} @@ -1593,9 +2040,12 @@ % \end{macrocode} % \end{macro} % +% +% +% % \subsection{Hooks} % -% Allow code do be saved to be executed at specific later times. +% Allow code to be saved to be executed at specific later times. % % Save things in macros, I considered using toks registers, (and % |\addto@hook| from the NFSS code, that would require stacking the @@ -1615,25 +2065,6 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\g@addto@macro} -% Globally add to the end of a macro. -% \changes{v0.2a}{1993/11/14}{Made global} -% \changes{v0.2w}{1994/01/31} -% {Use toks register to avoid `hash' problems} -% \changes{v1.0o}{1995/05/17} -% {Make long for latex/1522} -% \changes{v1.0w}{1996/12/17} -% {Use \cs{begingroup} to save making a mathord} -% \changes{v1.0x}{1997/02/05} -% {missing percent /2402} -% \begin{macrocode} -\long\def\g@addto@macro#1#2{% - \begingroup - \toks@\expandafter{#1#2}% - \xdef#1{\the\toks@}% - \endgroup} -% \end{macrocode} -% \end{macro} % % \begin{macro}{\AtEndOfPackage} % \begin{macro}{\AtEndOfClass} @@ -1652,8 +2083,29 @@ % \end{macrocode} % % \begin{macrocode} -\DeclareRobustCommand\AtBeginDocument{\g@addto@macro\@begindocumenthook} -\DeclareRobustCommand\AtEndDocument{\g@addto@macro\@enddocumenthook} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\AtBeginDocument}{Use hook system}% +\DeclareRobustCommand\AtBeginDocument{\AddToHook{begindocument}} +\DeclareRobustCommand\AtEndDocument {\AddToHook{enddocument}} +%\DeclareRobustCommand\AtEndDocument {\AddToHook{env/document/end}} % alternative impl +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\AtBeginDocument}{Use hook system}% +%<latexrelease> +%<latexrelease>\DeclareRobustCommand\AtBeginDocument{\g@addto@macro\@begindocumenthook} +%<latexrelease>\DeclareRobustCommand\AtEndDocument{\g@addto@macro\@enddocumenthook} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% \begin{macrocode} \@onlypreamble\AtBeginDocument % \end{macrocode} % \end{macro} @@ -1760,6 +2212,7 @@ % \end{macrocode} % \end{macro} % +% \begin{environment}{filecontents} % \begin{macro}{\filecontents} % \begin{macro}{\endfilecontents} % This environment implements inline files. @@ -1776,17 +2229,16 @@ % \changes{v1.0m}{1995/04/21} % {Close input check stream: latex/1487} % \changes{v1.0p}{1995/05/25}{Delete \cs{filec@ntents} after preamble} -% \begin{macrocode} % \changes{v1.3a}{2019/07/01}{Support UTF8 and spaces in % filecontents environment file name} % \changes{v1.3b}{2019/08/27}{Make various commands robust} % \changes{v1.3c}{2019/09/11}{Support optional argument for filecontents} % \changes{v1.3f}{2020/01/05}{Support more write streams in LuaTeX gh/238} -% +% \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}% +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\filec@ntents}{Define \q@curr@file directly (gh/220)}% % % \end{macrocode} % We use |@tempswa| to mean no preamble writing and reuse |@filesw| @@ -1817,7 +2269,7 @@ \filec@ntents } % \end{macrocode} -% Option \texttt{force}) (or \texttt{overwrite}) changes the +% Option \texttt{force} (or \texttt{overwrite}) changes the % overwriting switch % \begin{macrocode} \let\filec@ntents@force\@fileswfalse @@ -1829,7 +2281,7 @@ \let\filec@ntents@noheader\@tempswafalse % \end{macrocode} % Option \texttt{nosearch} only checks the current directory not -% the how \TeX{} tree for the existence of the file to write. +% the whole \TeX{} tree for the existence of the file to write. % \begin{macrocode} \def\filec@ntents@nosearch{% \let\filec@ntents@checkdir\@currdir @@ -1855,10 +2307,12 @@ \catcode`\^^I\active% % \end{macrocode} % +% \changes{v1.3m}{2020-08-08}{define \cs{q@curr@file} directly as the +% quotes have already been removed (gh/220)} % \begin{macrocode} \gdef\filec@ntents#1{% \set@curr@file{\filec@ntents@checkdir#1}% - \edef\q@curr@file{\expandafter\quote@name\expandafter{\@curr@file}}% + \edef\q@curr@file{"\@curr@file"}% % \end{macrocode} % % Lua\TeX\ has more writes (and 18 is safe here). @@ -2019,6 +2473,136 @@ % \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}% +%<latexrelease>\def\filecontents{\@tempswatrue\@fileswtrue +%<latexrelease> \@ifnextchar[\filec@ntents@opt\filec@ntents +%<latexrelease>} +%<latexrelease>\@namedef{filecontents*}{\@tempswafalse\@fileswtrue +%<latexrelease> \@ifnextchar[\filec@ntents@opt\filec@ntents +%<latexrelease>} +%<latexrelease>\def\filec@ntents@opt[#1]{% +%<latexrelease> \edef\@fortmp{\zap@space#1 \@empty}% +%<latexrelease> \@for\reserved@a:=\@fortmp\do{% +%<latexrelease> \ifcsname filec@ntents@\reserved@a\endcsname +%<latexrelease> \csname filec@ntents@\reserved@a\endcsname +%<latexrelease> \else +%<latexrelease> \@latex@error{Unknown filecontents option \reserved@a}% +%<latexrelease> {Valid options are force (or overwrite), nosearch, noheader}% +%<latexrelease> \fi}% +%<latexrelease> \filec@ntents +%<latexrelease>} +%<latexrelease>\let\filec@ntents@force\@fileswfalse +%<latexrelease>\let\filec@ntents@overwrite\@fileswfalse % alternative name +%<latexrelease>\let\filec@ntents@noheader\@tempswafalse +%<latexrelease>\def\filec@ntents@nosearch{% +%<latexrelease> \let\filec@ntents@checkdir\@currdir +%<latexrelease> \def\filec@ntents@where{in current directory}} +%<latexrelease>\let\filec@ntents@checkdir\@empty +%<latexrelease>\def\filec@ntents@where{exists on the system} +%<latexrelease>\begingroup% +%<latexrelease>\@tempcnta=1 +%<latexrelease>\loop +%<latexrelease> \catcode\@tempcnta=12 % +%<latexrelease> \advance\@tempcnta\@ne % +%<latexrelease>\ifnum\@tempcnta<32 % +%<latexrelease>\repeat % +%<latexrelease>\catcode`\*=11 % +%<latexrelease>\catcode`\^^M\active% +%<latexrelease>\catcode`\^^L\active\let^^L\relax% +%<latexrelease>\catcode`\^^I\active% +%<latexrelease>\gdef\filec@ntents#1{% +%<latexrelease> \set@curr@file{\filec@ntents@checkdir#1}% +%<latexrelease> \edef\q@curr@file{\expandafter\quote@name\expandafter{\@curr@file}}% +%<latexrelease> \chardef\reserved@c\ifx\directlua\@undefined 15 \else 127 \fi% +%<latexrelease> \openin\@inputcheck\q@curr@file \space % +%<latexrelease> \ifeof\@inputcheck% +%<latexrelease> \@latex@warning@no@line% +%<latexrelease> {Writing file `\@currdir\@curr@file'}% +%<latexrelease> \ch@ck7\reserved@c\write\relax% +%<latexrelease> \immediate\openout\reserved@c\q@curr@file\relax% +%<latexrelease> \else% +%<latexrelease> \if@filesw% +%<latexrelease> \@latex@warning@no@line% +%<latexrelease> {File `\@curr@file' already \filec@ntents@where.\MessageBreak% +%<latexrelease> Not generating it from this source}% +%<latexrelease> \let\write\@gobbletwo% +%<latexrelease> \let\closeout\@gobble% +%<latexrelease> \else% +%<latexrelease> \edef\reserved@a{#1}% +%<latexrelease> \edef\reserved@a{\detokenize\expandafter{\reserved@a}}% +%<latexrelease> \edef\reserved@b{\detokenize\expandafter{\jobname}}% +%<latexrelease> \ifx\reserved@a\reserved@b% +%<latexrelease> \@fileswtrue% +%<latexrelease> \else% +%<latexrelease> \edef\reserved@b{\reserved@b\detokenize{.tex}}% +%<latexrelease> \ifx\reserved@a\reserved@b +%<latexrelease> \@fileswtrue% +%<latexrelease> \fi% +%<latexrelease> \fi% +%<latexrelease> \ch@ck7\reserved@c\write\relax% +%<latexrelease> \if@filesw% % Foul ... trying to overwrite \jobname! +%<latexrelease> \@latex@error{Trying to overwrite `\jobname.tex'}{You can't % +%<latexrelease> write to the file you are reading from!\MessageBreak% +%<latexrelease> Data is written to screen instead.}% +%<latexrelease> \else% +%<latexrelease> \@latex@warning@no@line% +%<latexrelease> {Writing or overwriting file `\@currdir\@curr@file'}% +%<latexrelease> \immediate\openout\reserved@c\q@curr@file\relax% +%<latexrelease> \fi% +%<latexrelease> \fi% +%<latexrelease> \fi% +%<latexrelease> \closein\@inputcheck% +%<latexrelease> \if@tempswa% +%<latexrelease> \immediate\write\reserved@c{% +%<latexrelease> \@percentchar\@percentchar\space% +%<latexrelease> \expandafter\@gobble\string\LaTeX2e file `\@curr@file'^^J% +%<latexrelease> \@percentchar\@percentchar\space generated by the % +%<latexrelease> `\@currenvir' \expandafter\@gobblefour\string\newenvironment^^J% +%<latexrelease> \@percentchar\@percentchar\space from source `\jobname' on % +%<latexrelease> \number\year/\two@digits\month/\two@digits\day.^^J% +%<latexrelease> \@percentchar\@percentchar}% +%<latexrelease> \fi% +%<latexrelease> \let\do\@makeother\dospecials% +%<latexrelease> \count@ 128\relax% +%<latexrelease> \loop% +%<latexrelease> \catcode\count@ 11\relax% +%<latexrelease> \advance\count@ \@ne% +%<latexrelease> \ifnum\count@<\@cclvi% +%<latexrelease> \repeat% +%<latexrelease> \edef\E{\@backslashchar end\string{\@currenvir\string}}% +%<latexrelease> \edef\reserved@b{% +%<latexrelease> \def\noexpand\reserved@b% +%<latexrelease> ####1\E####2\E####3\relax}% +%<latexrelease> \reserved@b{% +%<latexrelease> \ifx\relax##3\relax% +%<latexrelease> \immediate\write\reserved@c{##1}% +%<latexrelease> \else% +%<latexrelease> \edef^^M{\noexpand\end{\@currenvir}}% +%<latexrelease> \ifx\relax##1\relax% +%<latexrelease> \else% +%<latexrelease> \@latex@warning{Writing text `##1' before % +%<latexrelease> \string\end{\@currenvir}\MessageBreak as last line of \@curr@file}% +%<latexrelease> \immediate\write\reserved@c{##1}% +%<latexrelease> \fi% +%<latexrelease> \ifx\relax##2\relax% +%<latexrelease> \else% +%<latexrelease> \@latex@warning{% +%<latexrelease> Ignoring text `##2' after \string\end{\@currenvir}}% +%<latexrelease> \fi% +%<latexrelease> \fi% +%<latexrelease> ^^M}% +%<latexrelease> \catcode`\^^L\active% +%<latexrelease> \let\L\@undefined% +%<latexrelease> \def^^L{\expandafter\ifx\csname L\endcsname\relax\fi ^^J^^J}% +%<latexrelease> \catcode`\^^I\active% +%<latexrelease> \let\I\@undefined% +%<latexrelease> \def^^I{\expandafter\ifx\csname I\endcsname\relax\fi\space}% +%<latexrelease> \catcode`\^^M\active% +%<latexrelease> \edef^^M##1^^M{% +%<latexrelease> \noexpand\reserved@b##1\E\E\relax}}% +%<latexrelease>\endgroup% +%<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}% %<latexrelease> @@ -2142,6 +2726,7 @@ % \end{macrocode} % \end{macro} % \end{macro} +% \end{environment} % % % @@ -2763,7 +3348,7 @@ %<*afterpreamble> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{pkgindoc} - [1994/10/20 v1.1 Package Interface in Document (DPC)] + [2020-08-08 v1.3m Package Interface in Document (DPC)] \def\reserved@a#1\do\@classoptionslist#2\do\filec@ntents#3\relax{% \gdef\@preamblecmds{#1#3}} \expandafter\reserved@a\@preamblecmds\relax diff --git a/Master/texmf-dist/source/latex/base/ltdefns.dtx b/Master/texmf-dist/source/latex/base/ltdefns.dtx index 303b9e5604b..569c9db4df9 100644 --- a/Master/texmf-dist/source/latex/base/ltdefns.dtx +++ b/Master/texmf-dist/source/latex/base/ltdefns.dtx @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltdefns.dtx} - [2020/02/27 v1.5g LaTeX Kernel (definition commands)] + [2020/09/25 v1.5n LaTeX Kernel (definition commands)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltdefns.dtx} @@ -90,6 +90,7 @@ % \changes{v1.0p}{1995/07/13}{Updates to documentation} % \changes{v1.4b}{2015/02/21} % {Removed autoload support} +% \changes{v1.5l}{2020/08/21}{Integration of new hook management interface} % % \section{Definitions} % @@ -101,6 +102,7 @@ %<*2ekernel> % \end{macrocode} % +% % \subsection{Initex initialisations} % % \task{???}{This section needs extension} @@ -118,9 +120,25 @@ % % \begin{macro}{\typeout} % Display something on the terminal. +% \changes{v1.5g}{2020/05/15}{Allow \cs{par} in the argument (gh/335)} % \begin{macrocode} -\def\typeout#1{\begingroup\set@display@protect - \immediate\write\@unused{#1}\endgroup} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\typeout}{Allow "par" in \typeout}% +\protected\long\def\typeout#1{\begingroup + \set@display@protect + \def\par{^^J^^J}% + \immediate\write\@unused{#1}\endgroup} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\typeout}{Allow "par" in \typeout}% +%<latexrelease> +%<latexrelease>\def\typeout#1{\begingroup\set@display@protect +%<latexrelease> \immediate\write\@unused{#1}\endgroup} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -366,8 +384,9 @@ % % \begin{macro}{\@carcube} % |\@carcube T1 ... Tn\@nil| = |T1| |T2| |T3| , $n > 3$ +% \changes{v1.5k}{2020/08/19}{Made \cs{long} for \cs{NewCommandCopy}} % \begin{macrocode} -\def\@carcube#1#2#3#4\@nil{#1#2#3} +\long\def\@carcube#1#2#3#4\@nil{#1#2#3} % \end{macrocode} % \end{macro} % @@ -645,7 +664,7 @@ % \begin{macro}{\@ifdefinable} % \begin{macro}{\@@ifdefinable} % \begin{macro}{\@rc@ifdefinable} -% Test is user is allowed to define a command. +% Test if user is allowed to define a command. % \begin{macrocode} \long\def\@ifdefinable #1#2{% \edef\reserved@a{\expandafter\@gobble\string #1}% @@ -980,7 +999,7 @@ % evaluates its argument fully. % \end{itemize} % The method \LaTeX{} uses for making fragile commands robust is to -% precede them with |\protect|. This can have one of five possible +% precede them with |\protect|. This can have one of four possible % values: % \begin{itemize} % \item |\relax|, for normal typesetting. So |\protect\foo| will @@ -1174,6 +1193,8 @@ % \changes{v1.4a}{2015/01/08}{Added macro} % \changes{v1.5f}{2019/08/27}{Make the assignments global as we may % need to apply them inside a group} +% \changes{v1.5m}{2020/08/21}{Make \cs{MakeRobust} produce the same +% command structure as \cs{DeclareRobustCommand}} % % This macro makes an existing fragile macro robust, but only if it % hasn't been robust in the past, i.e., it checks for the existence @@ -1192,9 +1213,11 @@ % at all. % \begin{macrocode} %</2ekernel> -%<latexrelease>\IncludeInRelease{2019/10/01}{\MakeRobust}{\MakeRobust}% +%<latexrelease>\IncludeInRelease{2020/10/01}{\MakeRobust}{\MakeRobust}% %<*2ekernel|latexrelease> \def\MakeRobust#1{% + \count@=\escapechar + \escapechar=`\\ \@ifundefined{\expandafter\@gobble\string#1}{% \@latex@error{The control sequence `\string#1' is undefined!% \MessageBreak There is nothing here to make robust}% @@ -1206,12 +1229,15 @@ % \verb*=\foo =. If it is already defined do nothing, otherwise set % \verb*=\foo = equal to \verb*=\foo= and redefine \verb*=\foo= so % that it acts like a macro defined with \verb=\DeclareRobustCommand=. +% We use \cs{@kernel@rename@newcommand} to copy \verb*=\foo= over to +% \verb*=\foo =, including a possible default optional argument. % \begin{macrocode} {% \@ifundefined{\expandafter\@gobble\string#1\space}% {% - \global\expandafter\let\csname - \expandafter\@gobble\string#1\space\endcsname=#1% + \expandafter\@kernel@rename@newcommand + \csname\expandafter\@gobble\string#1\space\endcsname + #1% \edef\reserved@a{\string#1}% \def\reserved@b{#1}% \edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}% @@ -1223,10 +1249,72 @@ \csname\expandafter\@gobble\string#1\space\endcsname}% }% {\@latex@info{The control sequence `\string#1' is already robust}}% - }% + }% + \escapechar=\count@ }% +% \end{macrocode} +% +% \begin{macro}{\@kernel@rename@newcommand} +% This macro renames a command, possibly with an optional argument (defined +% with \cs{newcommand}) from |#2| to |#1|, by renaming the internal macro +% \verb=\\#2= to \verb=\\#1= and defining \verb=\#1= appropriately, then +% undefining \verb=\#2= and \verb=\\#2=. The \cs{afterassignment} trick is +% to make both definitions in \cs{@copy@newcommand} global (which are local +% by default). +% +% In case the macro was defined with \cs{newcommand} and an optional +% argument, to replicate exactly the behaviour of \cs{DeclareRobustCommand} +% we have to move also the internal \verb*=\\foo= to \verb*=\\foo =. In that +% case, \verb=#1= will be a parameterless macro (\cs{robust@command@chk@safe} +% checks that), and \cs{@if@newcommand} will return true (both defined below +% in this file). If so, we can use \cs{@copy@newcommand} rather than plain +% \cs{let} to copy the command over. \cs{@kernel@rename@newcommand} does +% this test and carries out the renaming. +% \begin{macrocode} +\def\@kernel@rename@newcommand#1#2{% + \robust@command@chk@safe#2% + {\@if@newcommand#2% + {\afterassignment\global + \global\@copy@newcommand#1#2% + \global\let#2\@undefined + \global\expandafter\let\csname\string#2\endcsname\@undefined}% + {\global\let#1=#2}}% + {\global\let#1=#2}} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +% +%<latexrelease>\IncludeInRelease{2019/10/01}{\MakeRobust}{\MakeRobust}% +%<latexrelease>\def\MakeRobust#1{% +%<latexrelease> \@ifundefined{\expandafter\@gobble\string#1}{% +%<latexrelease> \@latex@error{The control sequence `\string#1' is undefined!% +%<latexrelease> \MessageBreak There is nothing here to make robust}% +%<latexrelease> \@eha +%<latexrelease> }% +%<latexrelease> {% +%<latexrelease> \@ifundefined{\expandafter\@gobble\string#1\space}% +%<latexrelease> {% +%<latexrelease> \global\expandafter\let\csname +%<latexrelease> \expandafter\@gobble\string#1\space\endcsname=#1% +%<latexrelease> \edef\reserved@a{\string#1}% +%<latexrelease> \def\reserved@b{#1}% +%<latexrelease> \edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}% +%<latexrelease> \xdef#1{% +%<latexrelease> \ifx\reserved@a\reserved@b +%<latexrelease> \noexpand\x@protect\noexpand#1% +%<latexrelease> \fi +%<latexrelease> \noexpand\protect\expandafter\noexpand +%<latexrelease> \csname\expandafter\@gobble\string#1\space\endcsname}% +%<latexrelease> }% +%<latexrelease> {\@latex@info{The control sequence `\string#1' is already robust}}% +%<latexrelease> }% +%<latexrelease>}% +%<latexrelease>\let\@kernel@rename@newcommand\@undefined +%<latexrelease>\EndIncludeInRelease +% %<latexrelease>\IncludeInRelease{2015/01/01}{\MakeRobust}{\MakeRobust}% %<latexrelease>\def\MakeRobust#1{% %<latexrelease> \@ifundefined{\expandafter\@gobble\string#1}{% @@ -1252,17 +1340,17 @@ %<latexrelease> {\@latex@info{The control sequence `\string#1' is already robust}}% %<latexrelease> }% %<latexrelease>}% +%<latexrelease>\let\@kernel@rename@newcommand\@undefined %<latexrelease>\EndIncludeInRelease +% %<latexrelease>\IncludeInRelease{0000/00/00}{\MakeRobust}{\MakeRobust}% %<latexrelease>\let\MakeRobust\@undefined +%<latexrelease>\let\@kernel@rename@newcommand\@undefined %<latexrelease>\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % -% -% - % \begin{macro}{\kernel@make@fragile} % The opposite of |\MakeRobust| execpt that it doesn't do many % checks as it is internal to the kernel. Why does one want such a @@ -1276,7 +1364,7 @@ % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease>\IncludeInRelease{2020/10/01}% %<latexrelease> {\kernel@make@fragile}{Undo robustness}% \def\kernel@make@fragile#1{% \@ifundefined{\expandafter\@gobble\string#1\space}% @@ -1285,16 +1373,39 @@ % \begin{macrocode} {}% % \end{macrocode} -% Otherwise copy \verb*=\foo = back to \verb=\foo= and then undefine -% the payload command. +% Otherwise copy \verb*=\foo = back to \verb=\foo=. +% Then use \cs{@kernel@rename@newcommand} to check and copy +% \verb*=\\foo = back to \verb*=\\foo= in case the command has an optional +% argument. If so, also undefine \verb*=\\foo =, and at the end undefine +% \verb*=\foo =. % \begin{macrocode} {% \global\expandafter\let\expandafter #1\csname - \expandafter\@gobble\string#1\space\endcsname + \expandafter\@gobble\string#1\space\endcsname + \expandafter\@kernel@rename@newcommand + \csname\expandafter\@gobble\string#1\expandafter\endcsname + \csname\expandafter\@gobble\string#1\space\endcsname \global\expandafter\let\csname - \expandafter\@gobble\string#1\space\endcsname\@undefined + \expandafter\@gobble\string#1\space\endcsname\@undefined }% } +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +% +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\kernel@make@fragile}{Undo robustness}% +%<latexrelease>\def\kernel@make@fragile#1{% +%<latexrelease> \@ifundefined{\expandafter\@gobble\string#1\space}% +%<latexrelease> {}% +%<latexrelease> {% +%<latexrelease> \global\expandafter\let\expandafter #1\csname +%<latexrelease> \expandafter\@gobble\string#1\space\endcsname +%<latexrelease> \global\expandafter\let\csname +%<latexrelease> \expandafter\@gobble\string#1\space\endcsname\@undefined +%<latexrelease> }% +%<latexrelease>} %<latexrelease>\EndIncludeInRelease %</2ekernel|latexrelease> %<*2ekernel> @@ -1302,6 +1413,552 @@ % \end{macro} % % +% \subsection{Acting on robust commands} +% +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2020-10-01}{\robust@command@act} +%<latexrelease> {Add \robust@command@act}% +%<*2ekernel|latexrelease> +% \end{macrocode} +% +% With most document level commands being robust now there is more of a +% requirement to have a standard way of aliasing (or copying) a command to a +% new name, for example to save an original definition before changing a +% command. \cs{DeclareCommandCopy} is analogous to \TeX's \cs{let}, except +% that it copes with the different types of robust commands defined by +% \LaTeX's mechanisms. +% +% A couple of ``types of robustness'' are defined by the \LaTeXe{} kernel, +% namely robust commands defined with \cs{DeclareRobustCommand} and commands +% with optional arguments defined with \cs{newcommand}. However there are +% other types of robust commands that are frequently used, which are not +% defined in the \LaTeXe{} kernel, like commands defined with +% \textsf{xparse}'s \cs{NewDocumentCommand} and \textsf{etoolbox}'s +% \cs{newrobustcmd}. +% +% In this section we will define a generic extensible machinery to act on +% 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. +% +% \begin{macro}{\robust@command@act} +% \changes{v1.5k}{2020/08/19}{Made \cs{robust@command@act} +% (was \cs{declare@command@copy}) more generic} +% +% The looping machinery is generic and knows nothing about what is to be done +% for each case. The syntax of the main macro \cs{robust@command@act} is: +% \begin{quote} +% |\robust@command@act|\meta{action-list}\meta{robust-cmd}\\ +% \meta{fallback-action}\meta{act-arg} +% \end{quote} +% \meta{action-list} is a token list of the form: +% \begin{quote} +% |{|\meta{if-type-1} \meta{act-type-1}|}|\\ +% |{|\meta{if-type-2} \meta{act-type-2}|}|\\ +% \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}|}|. +% 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 +% the same way, until either one of the conditionals return \meta{true}, or +% the end of the \meta{action-list} is reached. If the end is reached, then +% \meta{fallback-action}\meta{act-arg} is executed before +% \cs{robust@command@act} exits. +% +% \cs{robust@command@act} will start by using \cs{robust@command@act@chk@args} +% to check if the \meta{robust-cmd} (|#2|) is a parameterless (possibly +% \cs{protected}) macro. If it is not, the command is not a robust command: +% these always start with a parameterless user-level macro; in that case, +% \cs{robust@command@act@end} is used to short-circuit the process and do the +% \meta{fallback-action} (|#3|). This first test is necessary because later +% on we need to be able to expand the \meta{robust-cmd} without the risk of it +% Breaking Badly, and as a bonus, this speeds up the process in case we used +% \cs{NewCommandCopy} in a ``normal'' macro. +% \begin{macrocode} +\long\def\robust@command@act#1#2#3#4{% + \robust@command@chk@safe#2% + {\expandafter\robust@command@act@loop + \expandafter#2% + #1{\@nnil\@nnil}% + \robust@command@act@end}% + {\robust@command@act@end}% + {#3}{#4}}% +% \end{macrocode} +% +% \begin{macro}{\robust@command@act@loop} +% \begin{macro}{\robust@command@act@loop@aux} +% \begin{macro}{\robust@command@act@do} +% If \cs{robust@command@act@chk@args} branched to false, then +% \cs{robust@command@act@loop} will loop over the list of items in the +% \meta{action-list} (|#1|), and process each item as described earlier. +% If the \meta{if-type-$n$} command expands to \meta{true} then +% \cs{robust@command@act@do} is used to execute \meta{act-type-$n$} on the +% \meta{act-arg}, otherwise the loop resumes with the next item. +% \begin{macrocode} +\long\def\robust@command@act@loop#1#2{\robust@command@act@loop@aux#1#2} +\long\def\robust@command@act@loop@aux#1#2#3{% + \ifx\@nnil#2% + \else + #2{#1}% + {\robust@command@act@do{#3}}% + {\expandafter\robust@command@act@loop\expandafter#1}% + \fi} +\long\def\robust@command@act@do#1% + \fi#2% + \robust@command@act@end#3#4{% + \fi + #1#4} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\robust@command@act@end} +% If the end is reached and no action was taken, then do +% \meta{fallback-action}\meta{act-arg}. +% \begin{macrocode} +\long\def\robust@command@act@end#1#2{#1#2} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\robust@command@chk@safe} +% \begin{macro}{\robust@command@act@chk@args} +% \begin{macrocode} +\long\def\robust@command@chk@safe#1{% + \begingroup + \escapechar=`\\ + \expandafter\endgroup\expandafter + \robust@command@act@chk@args\meaning#1:->\@nil} +\def\robust@command@act@chk@args#1:->#2\@nil{% + \@expl@str@if@eq@@nnTF{#1}{macro}% + {\@firstoftwo}% + {\@expl@str@if@eq@@nnTF{#1}{\protected macro}% + {\@firstoftwo}% + {\@secondoftwo}}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000-00-00}{\robust@command@act} +%<latexrelease> {Add \robust@command@act}% +%<latexrelease>\let\robust@command@act\@undefined +%<latexrelease>\let\robust@command@act@loop\@undefined +%<latexrelease>\let\robust@command@act@loop@aux\@undefined +%<latexrelease>\let\robust@command@act@do\@undefined +%<latexrelease>\let\robust@command@act@end\@undefined +%<latexrelease>\let\robust@command@chk@safe\@undefined +%<latexrelease>\let\robust@command@act@chk@args\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% \end{macro} +% +% +% \subsubsection{Copying robust commands} +% +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2020-10-01}{\DeclareCommandCopy} +%<latexrelease> {Add \NewCommandCopy, \RenewCommandCopy, and \DeclareCommandCopy}% +%<*2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macro}{\NewCommandCopy} +% \begin{macro}{\RenewCommandCopy} +% \begin{macro}{\DeclareCommandCopy} +% \changes{v1.5j}{2020/05/09}{Added \cs{DeclareCommandCopy} (gh/239)} +% +% \cs{NewCommandCopy} starts by checking if \verb=#1= is already defined, and +% raises an error if so, otherwise the definition is carried out. +% \cs{RenewCommandCopy} does (almost) the opposite. If the command is +% \emph{not} defined, then an error is raised. But the definition is carried +% out anyhow, so the behaviour is consistent with \cs{renewcommand}. +% +% A \cs{ProvideCommandCopy} isn't defined because it's not reasonably useful. +% \verb=\provide...= commands mean ``define this if there's no other +% definition'', but copying a command (usually) implies that the command being +% copied is defined, so \cs{ProvideCommandCopy} doesn't make a lot of sense. +% But more importantly, the most common use case of copying a command is to +% redefine it later, while preserving the old definition, as in: +% \begin{verbatim} +% \ProvideComandCopy \A \B +% \renewcommand \B { ... \A ... } +% \end{verbatim} +% then, if \verb=\A= is already defined the first line is skipped, an in this +% case \verb=\B= won't work as expected. +% +% The three versions call the internal \cs{declare@commandcopy} with the +% proper action. \cs{@firstofone} will carry out the copy. The only case +% when the copy is not made is the \meta{false} case for \cs{NewCommandCopy}, +% in which the command already exists and the definition is aborted. +% \begin{macrocode} +\def\NewCommandCopy{% + \declare@commandcopy + {\@firstofone}% + {\@firstoftwo\@notdefinable}} +\def\RenewCommandCopy{% + \declare@commandcopy + {\@latex@error{Command \@backslashchar\reserved@a\space undefined}\@ehc + \@firstofone}% + {\@firstofone}} +\def\DeclareCommandCopy{% + \declare@commandcopy + {\@firstofone}% + {\@firstofone}} +% \end{macrocode} +% +% \begin{macro}{\declare@commandcopy} +% Start by checking if the command is already defined. The proper action is +% taken by each specific command above. If all's good, then +% \cs{robust@command@act} is called with the proper arguments as described +% earlier, with \cs{@declarecommandcopylisthook} as the \meta{action-list} and +% \cs{declare@commandcopy@let} as the \meta{fallback-action}. +% \begin{macrocode} +\long\def\declare@commandcopy#1#2#3#4{% + \edef\reserved@a{\@expl@cs@to@str@@N#3}% + \@ifundefined\reserved@a{#1}{#2}% + {\robust@command@act + \@declarecommandcopylisthook#4% + \declare@commandcopy@let{#3#4}}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@declarecommandcopylisthook} +% The initial definition of \cs{@declarecommandcopylisthook} contains the +% tests for the two types of robust command in the kernel. +% \begin{macrocode} +\def\@declarecommandcopylisthook{% + {\@if@DeclareRobustCommand \@copy@DeclareRobustCommand}% + {\@if@newcommand \@copy@newcommand}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\declare@commandcopy@let} +% The initial definition of \cs{@declarecommandcopylisthook} contains the +% tests for the two types of robust command in the kernel. +% \begin{macrocode} +\long\def\declare@commandcopy@let#1#2{\let#1=#2\relax} +% \end{macrocode} +% \end{macro} +% +% Now the rollback code. +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000-00-00}{\DeclareCommandCopy} +%<latexrelease> {Undefine \NewCommandCopy, \RenewCommandCopy, and \DeclareCommandCopy}% +%<latexrelease>\let\NewCommandCopy\@undefined +%<latexrelease>\let\RenewCommandCopy\@undefined +%<latexrelease>\let\DeclareCommandCopy\@undefined +%<latexrelease>\let\declare@commandcopy\@undefined +%<latexrelease>\let\@declarecommandcopylisthook\@undefined +%<latexrelease>\let\declare@commandcopy@let\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsubsection{Showing robust commands} +% +% \begin{macro}{\ShowCommand} +% \changes{v1.5k}{2020/08/19}{Added \cs{ShowCommand} (gh/373)} +% +% Most of the machinery defined for \cs{NewCommandCopy} can be used to show +% the definition of a robust command, in a similar fashion to \texttt{texdef}. +% The difference is that after the command's is detected to has a given type +% of robustness, rather than making a copy, we use a separate routine to show +% its definition. +% +% With all the machinery in place, \cs{ShowCommand} itself is quite simple: +% use \cs{robust@command@act} to iterate through the \cs{@showcommandlisthook} +% list, and if nothing is found, fallback to \cs{show}. +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2020-10-01}{\ShowCommand}% +%<latexrelease> {Add \ShowCommand}% +%<*2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +\long\def\ShowCommand#1{% + \robust@command@act + \@showcommandlisthook#1% + \show#1} +% \end{macrocode} +% +% \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 +% \cs{newcommand} with optional arguments. +% \begin{macrocode} +\def\@showcommandlisthook{% + {\@if@DeclareRobustCommand \@show@DeclareRobustCommand}% + {\@if@newcommand \@show@newcommand}} +% \end{macrocode} +% \end{macro} +% +% Now the rollback code. +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000-00-00}{\ShowCommand} +%<latexrelease> {Undefine \ShowCommand}% +%<latexrelease>\let\ShowCommand\@undefined +%<latexrelease>\let\@showcommandlisthook\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2020-10-01}{\@if@DeclareRobustCommand} +%<latexrelease> {Add \@if@DeclareRobustCommand, \@if@newcommand, +%<latexrelease> \@copy@DeclareRobustCommand, \@copy@newcommand, +%<latexrelease> \@show@DeclareRobustCommand, \@show@newcommand}% +%<*2ekernel|latexrelease> +% \end{macrocode} +% +% \subsubsection{Commands defined with \cs{DeclareRobustCommand}} +% +% \begin{macro}{\@if@DeclareRobustCommand} +% \changes{v1.5j}{2020/05/09}{Added \cs{DeclareCommandCopy} (gh/239)} +% +% Now that we provided a generic way to copy one macro to another, we need to +% define a way to check if a command is one of \LaTeXe's robust types. These +% tests are heavily based on Heiko's \cs{LetLtxMacro}, but chopped into +% separate macros. +% +% \cs{@if@DeclareRobustCommand} checks if a command \verb=\cmd= was defined by +% \cs{DeclareRobustCommand}. The test returns true if the expansion of +% \verb=\cmd= is exactly \verb*=\protect\cmd =. +% +% \begin{macrocode} +\long\def\@if@DeclareRobustCommand#1{% + \begingroup + \escapechar=`\\ + \edef\reserved@a{\string#1}% + \edef\reserved@b{\detokenize{#1}}% + \xdef\@gtempa{% + \ifx\reserved@a\reserved@b + \noexpand\x@protect + \noexpand#1% + \fi + \noexpand\protect + \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname}% + \endgroup + \ifx\@gtempa#1\relax + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi} +% \end{macrocode} +% +% \begin{macro}{\@copy@DeclareRobustCommand} +% \begin{macro}{\copy@kernel@robust@command} +% If a command was defined by \cs{DeclareRobustCommand} (that is, +% \cs{@if@DeclareRobustCommand} returns true), then to make a copy of \verb=\cmd= +% into \verb=\foo= we define the latter such that it expands to +% \verb*=\protect\foo =, then make \verb*=\foo = equal to \verb*=\cmd =. +% +% There is one detail we need to take care of: if a command was defined with +% \cs{DeclareRobustCommand} it may still have an optional argument, in which +% case there is one more macro layer before the actual definition of the +% command. We use \cs{@if@newcommand} to check that and +% \cs{@copy@newcommand} to do the copying. +% \begin{macrocode} +\long\def\@copy@DeclareRobustCommand#1#2{% + \begingroup + \escapechar=`\\ + \edef\reserved@a{\string#1}% + \edef\reserved@b{\detokenize{#1}}% + \edef\reserved@a{% + \endgroup + \def\noexpand#1{% + \ifx\reserved@a\reserved@b + \noexpand\x@protect + \noexpand#1% + \fi + \noexpand\protect + \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname}% + \noexpand\copy@kernel@robust@command + \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname + \expandafter\noexpand\csname\@expl@cs@to@str@@N#2 \endcsname}% + \reserved@a} +\long\def\copy@kernel@robust@command#1#2{% + \robust@command@chk@safe#2% + {\@if@newcommand#2% + {\@copy@newcommand}% + {\declare@commandcopy@let}} + {\declare@commandcopy@let}% + #1#2} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@show@DeclareRobustCommand} +% \begin{macro}{\show@kernel@robust@command} +% Showing the command is pretty simple. This command prints the top-level +% expansion as \TeX's \cs{show} would, but with |robust macro:| rather than +% just |macro:|, then a blank line and then \cs{show} the inner command. +% For a macro defined with, say, |\DeclareRobustCommand\foo[1]{bar}|, it will +% print: +% \begin{verbatim} +% > \foo=robust macro: +% ->\protect \foo . +% +% > \foo =\long macro: +% #1->bar. +% \end{verbatim} +% If the inner command is defined with an optional argument, then +% \cs{@show@newcommand} is also used. +% +% The value of \cs{escapechar} is deliberately not enforced, so +% \cs{ShowCommand} behaves more like \cs{show}. +% \begin{macrocode} +\long\def\@show@DeclareRobustCommand#1{% + \typeout{> \string#1=robust macro:}% + \typeout{->\@expl@cs@replacement@spec@@N#1.^^J}% + \expandafter\show@kernel@robust@command + \csname\@expl@cs@to@str@@N#1 \endcsname} +\long\def\show@kernel@robust@command#1{% + \robust@command@chk@safe#1% + {\@if@newcommand#1% + {\@show@newcommand}% + {\show}}% + {\show}% + #1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \end{macro} +% +% \subsubsection{Commands defined with \cs{newcommand} (with optional argument)} +% +% \begin{macro}{\@if@newcommand} +% A command \verb=\cmd= (or \verb*=\cmd =, if it was defined with +% \cs{DeclareRobustCommand}) with an optional argument will expand to +% \verb*=\@protected@testopt\cmd\\cmd{<opt>}=. To check that we look at the +% first three tokens in the expansion of \verb=\cmd=, and return true or false +% accordingly. +% +% This test \emph{requires} that the command be a parameterless macro, +% otherwise it will not work (and probably break). This is ensured with +% \cs{robust@command@chk@safe} before calling \cs{@if@newcommand}. +% \begin{macrocode} +\long\def\@if@newcommand#1{% + \edef\reserved@a{% + \noexpand\@protected@testopt + \noexpand#1% + \expandafter\noexpand\csname\@backslashchar\@expl@cs@to@str@@N#1\endcsname}% + \edef\reserved@b{% + \unexpanded\expandafter\expandafter\expandafter + {\expandafter\@carcube#1{}{}{}\@nil}}% + \ifx\reserved@a\reserved@b + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi} +% \end{macrocode} +% +% \begin{macro}{\@copy@newcommand} +% Then, if a command \verb=\cmd= takes an optional argument, we copy it to +% \verb=\foo= by defining the latter to expand to +% \verb=\@protected@testopt\foo\\foo{<opt>}=. +% \begin{macrocode} +\long\def\@copy@newcommand#1#2{% + \edef#1{\noexpand\@protected@testopt + \noexpand#1% + \expandafter\noexpand\csname\@backslashchar\@expl@cs@to@str@@N#1\endcsname + \unexpanded\expandafter\expandafter\expandafter + {\expandafter\@gobblethree#2}}% + \expandafter + \let\csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname + \csname\@backslashchar\@expl@cs@to@str@@N#2\endcsname} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@show@newcommand} +% \begin{macro}{\@show@newcommand@aux} +% A command being \cs{show}n here is guaranteed to have an optional argument. +% Start by showing the top-level expansion of the command (using \cs{typeout} +% to avoid TeX asking for interaction and extra context lines), then call +% \cs{@show@newcommand@aux} with the internal command, which contains the +% actual definition, and with the expansion of the command to extract the +% default value of the optional argument. +% \begin{macrocode} +\long\def\@show@newcommand#1{% + \typeout{> \string#1=robust macro:}% + \typeout{->\@expl@cs@replacement@spec@@N#1.^^J}% + \expandafter\@show@newcommand@aux + \csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname + \expandafter{#1}} +% \end{macrocode} +% +% For a macro defined with, say, |\newcommand\foo[1][opt]{bar}|, it will +% print: +% \begin{verbatim} +% > \foo=robust macro: +% ->\@protected@testopt \foo \\foo {opt}. +% +% > \\foo=\long macro: +% > default #1=opt. +% [#1]->bar. +% \end{verbatim} +% If the command was defined with \cs{DeclareRobustCommand}, then another pair +% of lines show the top-level expansion \verb*|\protect \foo |. +% +% The extra gymnastics with \cs{showtokens} ensures that \cs{showtokens} +% itself, and the internals of this macro aren't showed in the context lines. +% \begin{macrocode} +\long\def\@show@newcommand@aux#1#2{% + \typeout{> \string#1=\@expl@cs@prefix@spec@@N#1macro:}% + \edef\reserved@a{% + default \string##1=\expandafter\detokenize\@gobblethree#2.^^J% + \@expl@cs@argument@spec@@N#1->\@expl@cs@replacement@spec@@N#1}% + \showtokens\expandafter\expandafter\expandafter{\expandafter\reserved@a}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% Now the rollback code. +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000-00-00}{\@if@DeclareRobustCommand} +%<latexrelease> {Undefine \@if@DeclareRobustCommand, \@if@newcommand, +%<latexrelease> \@copy@DeclareRobustCommand, \@copy@newcommand, +%<latexrelease> \@show@DeclareRobustCommand, \@show@newcommand}% +%<latexrelease>\let\@if@DeclareRobustCommand\@undefined +%<latexrelease>\let\@copy@DeclareRobustCommand\@undefined +%<latexrelease>\let\@show@DeclareRobustCommand\@undefined +%<latexrelease>\let\@if@newcommand\@undefined +%<latexrelease>\let\@copy@newcommand\@undefined +%<latexrelease>\let\@show@newcommand\@undefined +% +%<latexrelease>\let\copy@kernel@robust@command\@undefined +%<latexrelease>\let\show@kernel@robust@command\@undefined +%<latexrelease>\let\@show@newcommand@aux\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% \end{macro} +% % % \subsection{Internal defining commands} % @@ -1537,6 +2194,56 @@ % \end{macro} % % +% \begin{macro}{\string@makeletter} +% \begin{macro}{\@string@makeletter} +% \begin{macro}{\char@if@alph} +% Iterates through a string, turning each alphabetic character into +% a catcode-11 token (partly undoes a \cs{detokenize}). Useful for +% \cs{ifx}-based string comparisons where \cs{detokenize}-ing the +% other string would break too much code. +% +% \changes{v1.5n}{2020/09/06} +% {Macro added} +% +% The macro uses \textsf{expl3}'s \cs{@expl@str@map@function@@NN} to +% iterate on the string (without losing spaces) and applies +% \cs{@string@makeletter} on each character. The latter checks if +% character is between a--z or A--Z, and uses \cs{@alph} or \cs{@Alph} +% to get the corresponding catcode-11 token. Other tokens are passed +% through unchanged. +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2020/10/01}{\string@makeletter} +%<latexrelease> {Add \string@makeletter}% +%<*2ekernel|latexrelease> +\def\string@makeletter#1{% + \@expl@str@map@function@@NN#1\@string@makeletter} +\def\@string@makeletter#1{% + \char@if@alph{#1}% + {\@expl@char@generate@@nn{`#1}{11}}% + {#1}} +\def\char@if@alph#1{% + \ifnum0\ifnum`#1<`A 1\fi\ifnum`#1>`z 1\fi + \if\ifnum`#1>`Z @\fi\ifnum`#1<`a @\fi01\fi>0 + \expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% +%<latexrelease>\IncludeInRelease{0000/00/00}{\string@makeletter} +%<latexrelease> {Undefine \string@makeletter}% +%<latexrelease>\let\string@makeletter\@undefined +%<latexrelease>\let\@string@makeletter\@undefined +%<latexrelease>\let\char@if@alph\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% % % \begin{macro}{\makeatletter} % \begin{macro}{\makeatother} @@ -1550,7 +2257,6 @@ % \end{macro} % \end{macro} % - % % \section{Discretionary Hyphenation} % \begin{macro}{\-} @@ -1560,6 +2266,7 @@ % \changes{v1.0g}{1994/04/12} % {Define \cs{@dischyph}, was previously in ltboxes.dtx} % \changes{v1.5b}{2017/03/27}{Define \cs{@dischyph} after \cs{-}} +% \changes{v1.5j}{2020/05/11}{Do not overwrite \cs{-} under Lua\TeX} % \end{macro} % Moved here to be after the definition of |\DeclareRobustCommand|. % @@ -1589,35 +2296,56 @@ % older \LaTeX\ definition accessible via \textsf{latexrelease} % as usual. % -% \begin{macrocode} -%</2ekernel> -%<latexrelease>\IncludeInRelease{2017/04/15}{\-}{Use \hyphenchar in \-}% -% \end{macrocode} +% In Lua\LaTeX\ the primitive definition of \cs{-} is used directly +% because it's use of extended hyphenation parameters means that \cs{-} +% works correctly even with \cs{hyphenchar} set to $-1$. This change +% makes \cs{-} under Lua\LaTeX\ compatible with language specific +% hyphenation characters. +% % Temporary definition of |\@latex@info|, final definition is later. % \begin{macrocode} -%<*2ekernel> \def\@latex@info#1{} -%</2ekernel> % \end{macrocode} % % \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2020/10/01}{\-}{Use primitive \- in Lua\LaTeX}% %<*2ekernel|latexrelease> -\DeclareRobustCommand{\-}{% - \discretionary{% - \char \ifnum\hyphenchar\font<\z@ - \defaulthyphenchar - \else - \hyphenchar\font - \fi - }{}{}% -} -\let\@dischyph=\- +\ifx\directlua\@undefined + \DeclareRobustCommand{\-}{% + \discretionary{% + \char \ifnum\hyphenchar\font<\z@ + \defaulthyphenchar + \else + \hyphenchar\font + \fi + }{}{}% + } +\else + \let\-\@@hyph +\fi %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2017/04/15}{\-}{Use \hyphenchar in \-}% +%<latexrelease>\DeclareRobustCommand{\-}{% +%<latexrelease> \discretionary{% +%<latexrelease> \char \ifnum\hyphenchar\font<\z@ +%<latexrelease> \defaulthyphenchar +%<latexrelease> \else +%<latexrelease> \hyphenchar\font +%<latexrelease> \fi +%<latexrelease> }{}{}% +%<latexrelease>} +%<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}{\-}{Use \hyphenchar in \-}% %<latexrelease>\def\-{\discretionary{-}{}{}} -%<latexrelease>\let\@dischyph=\- %<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<*2ekernel|latexrelease> +\let\@dischyph=\- +%</2ekernel|latexrelease> %<*2ekernel> % \end{macrocode} % \end{macro} @@ -1678,6 +2406,28 @@ %<*2ekernel> % \end{macrocode} % +% +% \begin{macro}{\g@addto@macro} +% Globally add to the end of a macro. +% \changes{v0.2a}{1993/11/14}{Made global} +% \changes{v0.2w}{1994/01/31} +% {Use toks register to avoid `hash' problems} +% \changes{v1.0o}{1995/05/17} +% {Make long for latex/1522} +% \changes{v1.0w}{1996/12/17} +% {Use \cs{begingroup} to save making a mathord} +% \changes{v1.0x}{1997/02/05} +% {missing percent /2402} +% \begin{macrocode} +\long\def\g@addto@macro#1#2{% + \begingroup + \toks@\expandafter{#1#2}% + \xdef#1{\the\toks@}% + \endgroup} +% \end{macrocode} +% \end{macro} +% +% % \begin{macrocode} %</2ekernel> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/base/ltdirchk.dtx b/Master/texmf-dist/source/latex/base/ltdirchk.dtx index 25fb9480ddd..3abd49aced5 100644 --- a/Master/texmf-dist/source/latex/base/ltdirchk.dtx +++ b/Master/texmf-dist/source/latex/base/ltdirchk.dtx @@ -37,7 +37,7 @@ %<*driver> % \fi \ProvidesFile{ltdirchk.dtx} - [2019/11/01 v1.3a LaTeX Kernel (System Dependent Parts)] + [2020/08/21 v1.3a LaTeX Kernel (System Dependent Parts)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltdirchk.dtx} @@ -172,7 +172,9 @@ %, \LaTeX\ will not work around a bug in old \TeX\ versions, and % so error messages will appear in a very strange format, with |^^J| % appearing instead of line breaks: -% \begingroup\catcode`\==\active \def=#1#2{}\hfuzz\maxdimen +% \begingroup +% ^^A FMi next line doesn't work with hacked class +% ^^A\catcode`\==\active \def=#1#2{}\hfuzz\maxdimen %\begin{verbatim} %! LaTeX Error: \rubbish undefined.^^J^^JSee the LaTeX manual or LaTeX= % Companion diff --git a/Master/texmf-dist/source/latex/base/ltexpl.dtx b/Master/texmf-dist/source/latex/base/ltexpl.dtx index 230cd911588..4100da79c28 100644 --- a/Master/texmf-dist/source/latex/base/ltexpl.dtx +++ b/Master/texmf-dist/source/latex/base/ltexpl.dtx @@ -33,67 +33,278 @@ %<*driver> % \fi \ProvidesFile{ltexpl.dtx} - [2019-10-02 v0.0 LaTeX Kernel (expl3-dependent code)] + [2020/09/06 v1.2f LaTeX Kernel (expl3-dependent code)] % \iffalse \documentclass{ltxdoc} -\GetFileInfo{ltfinal.dtx} +\GetFileInfo{ltexpl.dtx} \title{\filename} \date{\filedate} \author{% Joseph Wright} + +\providecommand\pkg[1]{\texttt{#1}} + \begin{document} \MaintainedByLaTeXTeam{latex} \maketitle - \DocInput{ltfinal.dtx} + \DocInput{ltexpl.dtx} \end{document} %</driver> % \fi % +% +% \changes{v1.2d}{2020/08/21}{Dropped unused command} +% % \section{\pkg{expl3}-dependent code} % % \StopEventually{} % % \changes{v0.0}{2019-10-02}{Initial version} % +% \subsection{Loader} +% +% \changes{v1.0a}{2020/03/02} +% {Don't load expl3 if already in the format (gh/295)} +% \changes{v1.1}{2020/03/05} +% {Load xparse.ltx if \cs{NewDocumentCommand} is not defined +% by expl3.ltx} +% \changes{v1.2c}{2020/06/04} +% {Define a local version of some \LaTeXe{} basic macros to support +% package loading} +% +% 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. % \begin{macrocode} %<*2ekernel> +\def\@expl@sys@load@backend@@{} +\def\@expl@push@filename@@{} +\def\@expl@push@filename@aux@@{} +\def\@expl@pop@filename@@{} +%</2ekernel> % \end{macrocode} % -% \subsection{Loader} +% \changes{v1.2d}{2020/07/08} +% {Add a last-minute hook for \textsf{expl3}} +% Create a hook for last-minute \pkg{expl3} material. +% \begin{macrocode} +%<*2ekernel> +\def\@expl@finalise@setup@@{} +%</2ekernel> +% \end{macrocode} +% +% Now define some basics to support loading \textsf{expl3}. These macros can +% be defined here safely, because they are redefined later on by the kernel, +% so we define simpler versions just to suit our needs. +% \begin{macrocode} +%<*2ekernel> +\long\def\@gobble#1{} +\long\def\@firstofone#1{#1} +\long\def\@firstoftwo#1#2{#1} +\long\def\@secondoftwo#1#2{#2} +\long\def\IfFileExists#1{% + \openin\@inputcheck"#1" % + \ifeof\@inputcheck + \expandafter\@secondoftwo + \else + \closein\@inputcheck + \expandafter\@firstoftwo + \fi} +\long\def\@ifnextchar#1#2#3{% + \let\reserved@d=#1% + \def\reserved@a{#2}% + \def\reserved@b{#3}% + \futurelet\@let@token\@ifnch} +\def\@ifnch{% + \ifx\@let@token\reserved@d + \expandafter\reserved@a + \else + \expandafter\reserved@b + \fi} +%</2ekernel> +% \end{macrocode} +% +% If we are doing a rollback with a format containing expl3 we +% aren't reloading it as that creates havoc. This may need a +% refined version! +% \begin{macrocode} +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {expl3}{Pre-load expl3}% +\expandafter\ifx\csname tex\string _let:D\endcsname\relax + \expandafter\@firstofone +\else + \GenericInfo{}{Skipping: expl3 code already part of the format}% +%<2ekernel> \expandafter\endinput +%<latexrelease> \expandafter\@gobble +\fi +% \end{macrocode} % % Check for the required primitive/engine support and the existence of % a loader. % \begin{macrocode} + {% + \IfFileExists{expl3.ltx} + {% + \ifnum0% + \ifdefined\pdffilesize 1\fi + \ifdefined\filesize 1\fi + \ifdefined\luatexversion\ifnum\luatexversion>94 1\fi\fi + \ifdefined\kanjiskip 1\fi + >0 % + \expandafter\@firstofone + \else +% \end{macrocode} +% +% 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)= +% 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. +% \begin{macrocode} +%<2ekernel> \def~{ }\def\MessageBreak{^^J~~~~~~~~~~~~~~~}% +%<2ekernel> \errmessage{LaTeX Error: +%<latexrelease> \@latex@error{% + LaTeX requires the e-TeX primitives and additional\MessageBreak + functionality available in the engines:\MessageBreak + - pdfTeX v1.40\MessageBreak + - XeTeX v0.99992\MessageBreak + - LuaTeX v0.95\MessageBreak + - e-(u)pTeX mid-2012\MessageBreak + or later% +%<latexrelease> }\@ehd \expandafter\@gobble +%<2ekernel> }\batchmode \read -1 to \reserved@a + \fi + } + {% +%<*2ekernel> + \errmessage{LaTeX requires expl3}% + \batchmode \read -1 to \reserved@a %</2ekernel> -%<*2ekernel|latexrelease> +%<*latexrelease> + \@latex@error{LaTeX requires expl3}\@ehd + \@gobble +%</latexrelease> + }% + {% + \input expl3.ltx + \ifdefined\NewDocumentCommand + \else + \IfFileExists{xparse.ltx} + {\input xparse.ltx } + {}% + \fi + }% + } +%<latexrelease>\EndIncludeInRelease +%<latexrelease> %<latexrelease>\IncludeInRelease{2020/02/02}% %<latexrelease> {expl3}{Pre-load expl3}% -\IfFileExists{expl3.ltx} - {% - \ifnum0% - \ifdefined\pdffilesize 1\fi - \ifdefined\filesize 1\fi - \ifdefined\luatexversion\ifnum\luatexversion>94 1\fi\fi - >0 % - \else - \message{Skipping expl3-dependent extensions} -%<2ekernel> \expandafter\endinput +%<latexrelease>\IfFileExists{expl3.ltx} +%<latexrelease> {% +%<latexrelease> \ifnum0% +%<latexrelease> \ifdefined\pdffilesize 1\fi +%<latexrelease> \ifdefined\filesize 1\fi +%<latexrelease> \ifdefined\luatexversion\ifnum\luatexversion>94 1\fi\fi +%<latexrelease> >0 % +%<latexrelease> \else +%<latexrelease> \message{Skipping expl3-dependent extensions} %<latexrelease> \expandafter\@gobbletwo - \fi - } - {% - \message{Skipping expl3-dependent extensions}% -%<2ekernel> \endinput +%<latexrelease> \fi +%<latexrelease> } +%<latexrelease> {% +%<latexrelease> \message{Skipping expl3-dependent extensions}% %<latexrelease> \@gobbletwo - }% -\input{expl3.ltx} -%</2ekernel|latexrelease> +%<latexrelease> }% +%<latexrelease>\input{expl3.ltx} %<latexrelease>\EndIncludeInRelease -%<*2ekernel> % \end{macrocode} % +% \subsection{Using expl3 code} +% +% In order to ease the implemantation 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 +% unannounced. They are there for internal use in the \LaTeXe\ +% kernel and are not meant to be used in third-party +% packages. These macros will always have the \verb|@expl@| +% prefix in their name. +% +% The rest of the name matches the \pkg{expl3} name but with all +% underscores replaced by \texttt{@}s and the \texttt{:} replaced +% by \texttt{@@}, e.g., +%\begin{verbatim} +% \cs_new_eq:NN \@expl@tl@trim@spaces@apply@@nN \tl_trim_spaces_apply:nN +%\end{verbatim} +% if that \pkg{expl3} command is needed in places that are others +% coded in \LaTeXe{} conventions. +% % \begin{macrocode} -%</2ekernel> +\ExplSyntaxOn +% \end{macrocode} +% +% In this file, each release of LaTeX adds an \cs{IncludeInRelease} +% block, in which the macros copied for that release were defined. +% In case a rollback is requested, the entire block is changed. +% +% Each macro copied has a \cs{changes} entry to explain when and why +% it was copied, so that further to that may spot it easily. +% +% Here \cs{cs\string_gset\string_eq:NN} is used, instead of the |new| +% variant because if different releases use that same name for +% different purposes, each can copy the macro without worrying about +% redefinitions. +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{expl3~2020-10-01}% +%<latexrelease> {expl3~macros~added~for~the~2020-10-01~release}% +% \end{macrocode} +% +% \changes{v1.2e}{2020/08/19} +% {Add \cs{@expl@cs@to@str@@N} and \cs{@expl@str@if@eq@@nnTF} +% for \cs{NewCommandCopy} (gh/239)} +% \begin{macrocode} +\cs_gset_eq:NN \@expl@cs@to@str@@N \cs_to_str:N +\cs_gset_eq:NN \@expl@str@if@eq@@nnTF \str_if_eq:nnTF +% \end{macrocode} +% +% \changes{v1.2e}{2020/08/19} +% {Add \cs{@expl@cs@\meta{thing}@spec@@N} +% for \cs{ShowCommand} (gh/373)} +% \begin{macrocode} +\cs_gset_eq:NN \@expl@cs@prefix@spec@@N \cs_prefix_spec:N +\cs_gset_eq:NN \@expl@cs@argument@spec@@N \cs_argument_spec:N +\cs_gset_eq:NN \@expl@cs@replacement@spec@@N \cs_replacement_spec:N +% \end{macrocode} +% +% \changes{v1.2f}{2020/09/06} +% {Add \cs{@expl@str@map@function@@NN +% and \cs{@expl@char@generate@@nn}} +% for \cs{string@makeletter} (gh/386)} +% \begin{macrocode} +\cs_gset_eq:NN \@expl@str@map@function@@NN \str_map_function:NN +\cs_gset_eq:NN \@expl@char@generate@@nn \char_generate:nn +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}{expl3~2020-10-01}% +%<latexrelease> {expl3~macros~added~for~the~2020-10-01~release}% +%<latexrelease>\cs_undefine:N \@expl@cs@to@str@@N +%<latexrelease>\cs_undefine:N \@expl@str@if@eq@@nnTF +%<latexrelease>\cs_undefine:N \@expl@cs@prefix@spec@@N +%<latexrelease>\cs_undefine:N \@expl@cs@argument@spec@@N +%<latexrelease>\cs_undefine:N \@expl@cs@replacement@spec@@N +%<latexrelease>\cs_undefine:N \@expl@str@map@function@@NN +%<latexrelease>\EndIncludeInRelease +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOff % \end{macrocode} % % \Finale diff --git a/Master/texmf-dist/source/latex/base/ltfilehook.dtx b/Master/texmf-dist/source/latex/base/ltfilehook.dtx new file mode 100644 index 00000000000..24ba88f576c --- /dev/null +++ b/Master/texmf-dist/source/latex/base/ltfilehook.dtx @@ -0,0 +1,1543 @@ +% \iffalse meta-comment +%% +%% File: ltfilehook.dtx (C) Copyright 2020 Frank Mittelbach, +%% Phelype Oleinik & LaTeX Team +% +% 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: ltfilehook.dtx +% +% \begin{macrocode} +\providecommand\ltfilehookversion{v1.0b} +\providecommand\ltfilehookdate{2020/09/26} +% \end{macrocode} +% +%<*driver> + +\documentclass{l3doc} + +% bug fix fo l3doc.cls +\ExplSyntaxOn +\cs_set_protected:Npn \__codedoc_macro_typeset_one:nN #1#2 + { + \vbox_set:Nn \l__codedoc_macro_box + { + \vbox_unpack_drop:N \l__codedoc_macro_box + \hbox { \llap { \__codedoc_print_macroname:nN {#1} #2 + \MacroFont % <----- without it the \ is in lmr10 if a link is made + \ + } } + } + \int_incr:N \l__codedoc_macro_int + } +\ExplSyntaxOff + +\usepackage{structuredlog} % for demonstration + +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{ltfilehook.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \long\def\fmi#1{\begin{quote}\itshape Todo: #1\end{quote}} +% +% \let\hook\texttt +% +% \title{The \texttt{ltfilehook} package\thanks{This package has version +% \ltfilehookversion\ dated \ltfilehookdate, \copyright\ \LaTeX\ +% Project.}} +% +% \author{Frank Mittelbach} +% +% \maketitle +% +% +% +% \tableofcontents +% +% \section{Introduction} +% +% +% +% \subsection{Provided hooks} +% +% The code offers a number of hooks into which packages (or the +% user) can add code to support different use cases. +% Many hooks are offered as pairs (i.e., the second hook is +% reversed. Also important to know is that these pairs are +% properly nested with respect to other pairs of hooks. +% +% There are hooks that are executed for all files of a certain type +% (if they contain code), e.g., for all \enquote{include files} or +% all \enquote{packages}, +% and there are also hooks that are specific to a single file, +% e.g., do something after the package \texttt{foo.sty} has been +% loaded. +% +% +% \subsection{General hooks for file reading} +% \label{sec:general-file-hooks} +% +% There are four hooks that are called for each file that is read +% using document-level commands such as \cs{input}, \cs{include}, +% \cs{usepackage}, etc. They are not called for files read using +% internal low-level methods, such as \cs{@input} or \cs{openin}. +% +% \begin{variable}{file/before,file/before/..., +% file/after/...,file/after, +% } +% These are: +% \begin{description} +% \item[\texttt{file/before}, \texttt{file/before/\meta{file-name}}] +% +% These hooks are executed in that order just before the file is +% loaded for reading. The code of the first hook is used +% with every file, while the second is executed only for the +% file with matching \meta{file-name} allowing you to specify +% code that only applies to one file. +% +% \item[\texttt{file/after/\meta{file-name}}, \texttt{file/after}] +% +% These hooks are after the file with name \meta{file-name} has +% been fully consumed. The order is swapped (the specific one +% comes first) so that the \texttt{before} and \texttt{after} +% hooks nest properly, which is important if any of them involve +% grouping (e.g., contain environments, for example). +% Furthermore both hooks are reversed hooks to support correct +% nesting of different packages adding code to both +% \texttt{/before} and \texttt{/after} hooks. +% +% \end{description} +% \end{variable} +% +% +% So the overall sequence of hook processing for any file read +% through the user interface commands of \LaTeX{} is: +% +% \begin{tabbing} +% mm\=mm\=mm\=mm\=\kill +% \>\cs{UseHook}\marg{\hook{file/before}} \\ +% \>\cs{UseHook}\marg{\hook{file/before/\meta{file name}}} \\ +% \>\> \meta{file contents} \\ +% \>\cs{UseHook}\marg{\hook{file/after/\meta{file name}}} \\ +% \>\cs{UseHook}\marg{\hook{file/after}} +% \end{tabbing} +% +% The file hooks only refer to the file by its name and extension, +% so the \meta{file name} should be the file name as it is on the +% filesystem with extension (if any) and without paths. Different +% from \cs{input} and similar commands, the \texttt{.tex} +% extension is not assumed in hook \meta{file name}, so \texttt{.tex} +% files must be specified +% with their extension to be recognized. +% Files within subfolders should also be addressed by their name and +% extension only. +% +% Extensionless files also work, and should then be given without +% extension. Note however that \TeX{} prioritizes \texttt{.tex} +% files, so if two files \texttt{foo} and \texttt{foo.tex} exist in +% the search path, only the latter will be seen. +% +% When a file is input, the \meta{file name} is available in +% \cs{CurrentFile}, which is then used when accessing the +% \hook{file/before/\meta{file name}} and +% \hook{file/after/\meta{file name}}. +% +% \begin{variable}{\CurrentFile} +% The name of the file about to be read (or just finished) is +% available to the hooks through \cs{CurrentFile} (there is no +% \texttt{expl3} name for it for now). The file is always provided +% with its extension, i.e., how it appears on your hard drive, but +% without any specified path to it. For example, +% \verb=\input{sample}= and \verb=\input{app/sample.tex}= would +% both have \cs{CurrentFile} being \texttt{sample.tex}. +% \end{variable} +% +% \begin{variable}{\CurrentFilePath} +% The path to the current file (complement to \cs{CurrentFile}) is +% available in \cs{CurrentFilePath} if needed. +% The paths returned in \cs{CurrentFilePath} are only user paths, +% given through \cs{input@path} (or \pkg{expl3}'s equivalent +% \cs{l_file_search_path_seq}) or by directly typing in the path +% in the \cs{input} command or equivalent. Files located by +% \texttt{kpsewhich} get the path added internally by the \TeX{} +% implementation, so at the macro level it looks as if the file were +% in the current folder, so the path in \cs{CurrentFilePath} is empty +% in these cases (package and class files, mostly). +% \end{variable} +% +% \begin{variable}{\CurrentFileUsed,\CurrentFilePathUsed} +% In normal circumstances these are identical to \cs{CurrentFile} and +% \cs{CurrentFilePath}. They will differ when a file substitution +% has occurred for \cs{CurrentFile}. In that case, +% \cs{CurrentFileUsed} and \cs{CurrentFilePathUsed} will hold the +% actual file name and path loaded by \LaTeX, while \cs{CurrentFile} +% and \cs{CurrentFilePath} will hold the names that were +% \emph{asked for}. Unless doing very specific work on the file +% being read, \cs{CurrentFile} and \cs{CurrentFilePath} should be +% enough. +% \end{variable} +% +% \subsection{Hooks for package and class files} +% +% Commands to load package and class files (e.g., \cs{usepackage}, +% \cs{RequirePackage}, \cs{LoadPackageWithOptions}, etc.) offer the +% hooks from section~\ref{sec:general-file-hooks} when they are +% used to load a package or class file, e.g., +% \texttt{file/after/array.sty} would be called after the +% \pkg{array} package got loaded. But as packages and classes form as special group +% of files, there are some additional hooks available that only +% apply when a package or class is loaded. +% +% +% \begin{variable}{ +% package/before,package/after, +% package/before/...,package/after/..., +% class/before,class/after, +% class/before/...,class/after/..., +% } +% These are: +% \begin{description} +% \item[\texttt{package/before}, \texttt{package/after}] +% +% These hooks are called for each package being loaded. +% +% \item[\texttt{package/before/\meta{name}}, +% \texttt{package/after/\meta{name}}] +% +% These hooks are additionally called if the package name is +% \meta{name} (without extension). +% +% \item[\texttt{class/before}, \texttt{class/after}] +% +% These hooks are called for each class being loaded. +% +% \item[\texttt{class/before/\meta{name}}, \texttt{class/after/\meta{name}}] +% +% These hooks are additionally called if the class name is +% \meta{name} (without extension). +% +% \end{description} +% \end{variable} +% All \hook{/after} hooks are implemented as reversed hooks. +% +% \noindent The overall sequence of execution for \cs{usepackage} +% and friends is therefore: +% \begin{tabbing} +% mm\=mm\=mm\=mm\=\kill +% \>\cs{UseHook}\marg{\hook{package/before}} \\ +% \>\cs{UseHook}\marg{\hook{package/before/\meta{package name}}} \\[5pt] +% \>\>\cs{UseHook}\marg{\hook{file/before}} \\ +% \>\>\cs{UseHook}\marg{\hook{file/before/\meta{package name}.sty}} \\ +% \>\>\> \meta{package contents} \\ +% \>\>\cs{UseHook}\marg{\hook{file/after/\meta{package name}.sty}} \\ +% \>\>\cs{UseHook}\marg{\hook{file/after}} \\[5pt] +% \>\>\emph{code from \cs{AtEndOfPackage} if +% used inside the package} \\[5pt] +% \>\cs{UseHook}\marg{\hook{package/after/\meta{package name}}} \\ +% \>\cs{UseHook}\marg{\hook{package/after}} +% \end{tabbing} +% and similar for class file loading, except that \texttt{package/} +% is replaced by \texttt{class/} and \cs{AtEndOfPackage} by +% \cs{AtEndOfClass}. +% +% If a package or class is not loaded (or it was loaded before the +% hooks were set) none of the hooks are executed! +% +% \subsection{Hooks for \cs{include} files} +% +% To manage \cs{include} files, \LaTeX{} issues a \cs{clearpage} +% before and after loading such a file. Depending on the use case +% one may want to execute code before or after these +% \cs{clearpage}s especially for the one that is issued at the end. +% +% Executing code before the final \cs{clearpage}, means that the +% code is processed while the last page of the included material is +% still under construction. Executing code after it means that all +% floats from inside the include file are placed (which +% might have added further pages) and the final page has finished. +% +% Because of these different scenarios we offer hooks in three +% places.\footnote{If you want to execute code before the first +% \cs{clearpage} there is no need to use a hook---you can write it +% directly in front of the \cs{include}.} +% None of the hooks are executed when an \cs{include} file is +% bypassed because of an \cs{includeonly} declaration. They are, +% however, all executed if \LaTeX{} makes an attempt to load the +% \cs{include} file (even if it doesn't exist and all that happens +% is \enquote{\texttt{No file \meta{filename}.tex}}). +% +% +% \begin{variable}{include/before,include/before/..., +% include/end,include/end/..., +% include/after,include/after/..., +% } +% These are: +% \begin{description} +% +% \item[\texttt{include/before}, \texttt{include/before/\meta{name}}] +% +% These hooks are executed (in that order) after the initial +% \cs{clearpage} and after \texttt{.aux} file is changed to use +% \texttt{\meta{name}.aux}, but before the +% \texttt{\meta{name}.tex} file is loaded. In other words they are executed +% at the very beginning of the first page of the \cs{include} +% file. +% +% +% \item[\texttt{include/end/\meta{name}}, \texttt{include/end}] +% +% These hooks are executed (in that order) after \LaTeX{} has +% stopped reading from the \cs{include} file, but before it has +% issued a \cs{clearpage} to output any deferred floats. +% +% +% \item[\texttt{include/after/\meta{name}}, \texttt{include/after}] +% +% These hooks are executed (in that order) after \LaTeX{} has +% issued the \cs{clearpage} but before is has switched back +% writing to the main \texttt{.aux} file. Thus technically we are +% still inside the \cs{include} and if the hooks generate any +% further typeset material including anything that writes to the +% \texttt{.aux} file, then it would be considered part of the +% included material and bypassed if it is not loaded because of +% some \cs{includeonly} statement.\footnotemark +% +% \end{description} +% \end{variable}\footnotetext{For that reason +% another \cs{clearpage} is executed after these hooks which +% normally does nothing, but starts a new page if further material +% got added this way.} +% +% \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. +% +% +% +% \subsection{Internal interfaces for \LaTeX{}} +% +% \begin{function}{\declare@file@substitution,\undeclare@file@substitution} +% \begin{syntax} +% \cs{declare@file@substitution} \Arg{file} \Arg{replacement-file} +% \cs{undeclare@file@substitution} \Arg{file} +% \end{syntax} +% If \meta{file} is requested for loading replace it with +% \meta{replacement-file}. \cs{CurrentFile} remains pointing to +% \meta{file} but \cs{CurrentFileUsed} will show the file actually +% loaded. +% +% The main use case for this declaration is to provide a corrected +% version of a package that can't be changed (due to its license) +% but no longer functions because of \LaTeX{} kernel changes, for +% example, or to provide a version that makes use of new kernel +% functionality while the original package remains available for +% use with older releases. +% +% The \cs{undeclare@file@substitution} declaration undoes a +% substitution made earlier. +% +% \begin{quote} +% \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! +% \end{quote} +% \end{function} +% +% \begin{function}{\disable@package@load,\reenable@package@load} +% \begin{syntax} +% \cs{disable@package@load} \Arg{package} \Arg{alternate-code} +% \cs{reenable@package@load} \Arg{package} +% \end{syntax} +% If \meta{package} is requested do not load it but instead run +% \meta{alternate-code} which could issue a warning, error or any +% other code. +% +% The main use case is for classes that want to restrict the set of +% supported packages or contain code that make the use of some +% packages impossible. So rather than waiting until the document +% breaks they can set up informative messages why certain packages +% are not available. +% +% The function is only implemented for packages not for arbitrary +% files. +% \end{function} +% +% +% \subsection{A sample package for structuring the log output} +% +% As an application we provide the package \pkg{structuredlog} that +% adds lines to the \texttt{.log} when a file is opened and closed +% for reading keeping track of nesting level es well. +% For example, for the current document it adds the lines +%\begin{verbatim} +% = (LEVEL 1 START) t1lmr.fd +% = (LEVEL 1 STOP) t1lmr.fd +% = (LEVEL 1 START) supp-pdf.mkii +% = (LEVEL 1 STOP) supp-pdf.mkii +% = (LEVEL 1 START) nameref.sty +% == (LEVEL 2 START) refcount.sty +% == (LEVEL 2 STOP) refcount.sty +% == (LEVEL 2 START) gettitlestring.sty +% == (LEVEL 2 STOP) gettitlestring.sty +% = (LEVEL 1 STOP) nameref.sty +% = (LEVEL 1 START) ltfilehook-doc.out +% = (LEVEL 1 STOP) ltfilehook-doc.out +% = (LEVEL 1 START) ltfilehook-doc.out +% = (LEVEL 1 STOP) ltfilehook-doc.out +% = (LEVEL 1 START) ltfilehook-doc.hd +% = (LEVEL 1 STOP) ltfilehook-doc.hd +% = (LEVEL 1 START) ltfilehook.dtx +% == (LEVEL 2 START) ot1lmr.fd +% == (LEVEL 2 STOP) ot1lmr.fd +% == (LEVEL 2 START) omllmm.fd +% == (LEVEL 2 STOP) omllmm.fd +% == (LEVEL 2 START) omslmsy.fd +% == (LEVEL 2 STOP) omslmsy.fd +% == (LEVEL 2 START) omxlmex.fd +% == (LEVEL 2 STOP) omxlmex.fd +% == (LEVEL 2 START) umsa.fd +% == (LEVEL 2 STOP) umsa.fd +% == (LEVEL 2 START) umsb.fd +% == (LEVEL 2 STOP) umsb.fd +% == (LEVEL 2 START) ts1lmr.fd +% == (LEVEL 2 STOP) ts1lmr.fd +% == (LEVEL 2 START) t1lmss.fd +% == (LEVEL 2 STOP) t1lmss.fd +% = (LEVEL 1 STOP) ltfilehook.dtx +%\end{verbatim} +% Thus if you inspect an issue in the \texttt{.log} it is easy to +% figure out in which file it occurred, simply by searching back for +% \texttt{LEVEL} and if it is a \texttt{STOP} then remove 1 from +% the level value and search further for \texttt{LEVEL} with that value +% which should then be the \texttt{START} level of the file you are in. +% +% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } +% +% +% \section{The Implementation} +% \begin{macrocode} +%<*2ekernel> +% \end{macrocode} +% +% \begin{macrocode} +%<@@=filehook> +% \end{macrocode} +% +% +% \subsection{Document and package-level commands} +% +% +% \begin{macro}{\CurrentFile,\CurrentFilePath} +% \begin{macro}{\CurrentFileUsed,\CurrentFilePathUsed} +% User-level macros that hold the current file name and file path. +% These are used internally as well because the code takes care to +% protect against a possible redefinition of these macros in the +% loaded file (it's necessary anyway to make hooks work with nested +% \cs{input}). The versions |\...Used| hold the \emph{actual} file +% name and path that is loaded by \LaTeX, whereas the other two hold +% the name as requested. They will differ in case there's a file +% substitution. +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\CurrentFile}{Hook management file}% +\ExplSyntaxOn +\tl_new:N \CurrentFile +\tl_new:N \CurrentFilePath +\tl_new:N \CurrentFileUsed +\tl_new:N \CurrentFilePathUsed +\ExplSyntaxOff +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\CurrentFile}{Hook management file}% +%<latexrelease> +%<latexrelease>\let \CurrentFile \@undefined +%<latexrelease>\let \CurrentFilePath \@undefined +%<latexrelease>\let \CurrentFileUsed \@undefined +%<latexrelease>\let \CurrentFilePathUsed \@undefined +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% \subsection{\pkg{expl3} helpers} +% +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@@_file_parse_full_name:nN}{File helpers}% +\ExplSyntaxOn +% \end{macrocode} +% +% \begin{macro}{ +% \@@_file_parse_full_name:nN, +% \@@_full_name:nn, +% \@@_set_curr_file_assign:nnnNN +% } +% 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. +% 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. +% +% \begin{macrocode} +\cs_new:Npn \@@_file_parse_full_name:nN #1 + { + \exp_args:Nf \file_parse_full_name_apply:nN + { + \exp_args:Nf \@@_full_name:nn + { \file_full_name:n {#1} } {#1} + } + } +\cs_new:Npn \@@_full_name:nn #1 #2 + { + \tl_if_empty:nTF {#1} + { \tl_trim_spaces:n {#2} } + { \tl_trim_spaces:n {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ +% \@@_if_no_extension:nTF, +% \@@_drop_extension:N +% } +% Some actions depend on whether the file extension was explicitly +% given, and sometimes the extension has to be removed. The macros +% below use \cs{@@_file_parse_full_name:nN} to split up the file name +% and either check if \meta{ext} (|#3|) is empty, or discard it. +% \begin{macrocode} +\cs_new:Npn \@@_if_no_extension:nTF #1 + { + \exp_args:Ne \tl_if_empty:nTF + { \file_parse_full_name_apply:nN {#1} \use_iii:nnn } + } +\cs_new_protected:Npn \@@_drop_extension:N #1 + { + \tl_gset:Nx #1 + { + \exp_args:NV \@@_file_parse_full_name:nN #1 + \@@_drop_extension_aux:nnn + } + } +\cs_new:Npn \@@_drop_extension_aux:nnn #1 #2 #3 + { \tl_if_empty:nF {#1} { #1 / } #2 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\g_@@_input_file_seq,\l_@@_internal_tl} +% \begin{macro}{\@@_file_push:,\@@_file_pop:} +% \begin{macro}{\@@_file_pop_assign:nnnn} +% Yet another stack, to keep track of \cs{CurrentFile} and +% \cs{CurrentFilePath} with nested \cs{input}s. At the beginning of +% \cs{InputIfFileExists}, the current value of \cs{CurrentFilePath} +% and \cs{CurrentFile} is pushed to \cs{g_@@_input_file_seq}, and +% at the end, it is popped and the value reassigned. Some other +% places don't use \cs{InputIfFileExists} directly (\cs{include}) or +% need \cs{CurrentFile} earlier (\cs{@onefilewithoptions}), so these +% are manually used elsewhere as well. +% \begin{macrocode} +\tl_new:N \l_@@_internal_tl +\seq_new:N \g_@@_input_file_seq +\cs_new_protected:Npn \@@_file_push: + { + \seq_gpush:Nx \g_@@_input_file_seq + { + { \CurrentFilePathUsed } { \CurrentFileUsed } + { \CurrentFilePath } { \CurrentFile } + } + } +\cs_new_protected:Npn \@@_file_pop: + { + \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 } + { Tried~to~pop~from~an~empty~file~name~stack. } + } + } +\cs_new_protected:Npn \@@_file_pop_assign:nnnn #1 #2 #3 #4 + { + \tl_set:Nn \CurrentFilePathUsed {#1} + \tl_set:Nn \CurrentFileUsed {#2} + \tl_set:Nn \CurrentFilePath {#3} + \tl_set:Nn \CurrentFile {#4} + } +\ExplSyntaxOff +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% \subsection{Declaring the file-related hooks} +% +% All hooks starting with \texttt{file/} \texttt{include/}, +% \texttt{class/} or \texttt{package/} are generic and will be +% allocated if code is added to them. Thus there is no need to +% explicitly declare any hook in the code below. +% +% Furthermore, those named \texttt{.../after} or \texttt{.../end} are +% automatically declared as reversed hooks if filled with code, so this +% is also automatically taken care of. +% +% +% +% +% \subsection{Patching \LaTeX{}'s \cs{InputIfFileExists} command} +% +% Most of what we have to do is adding \cs{UseHook} into several +% \LaTeXe{} core commands, because of some circular dependencies in the +% kernel we do this only now and not in \texttt{ltfiles}. +% +% \begin{macro}{\InputIfFileExists} +% \cs{InputIfFileExists} loads any file if it is available so we +% have to add the hooks \texttt{file/before} and +% \texttt{file/after} in the right places. If the file doesn't +% exist no hooks should be executed. +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\InputIfFileExists}{Hook management (files)}% +%<*2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +\let\InputIfFileExists\@undefined +\DeclareRobustCommand \InputIfFileExists[2]{% + \IfFileExists{#1}% + {% + \@expl@@@filehook@file@push@@ + \@filehook@set@CurrentFile +% \end{macrocode} +% If the file exists then \cs{CurrentFile} holds its name. But we +% can't rely on that still being true after the file has been +% processed. Thus for using the name in the file hooks we need to +% preserve the name and then restored it for the +% \texttt{file/after/...} hook. +% +% The hook always refers to the file requested by the user. The hook +% is \emph{always} loaded for \cs{CurrentFile} which usually is the +% same as \cs{CurrentFileUsed}. In the case of a file replacement, +% the \cs{CurrentFileUsed} holds the actual file loaded. In any case +% the file names are normalized so that the hooks work on the real +% file name, rather than what the user typed in. +% +% \pkg{expl3}'s \cs{file_full_name:n} normalizes the file +% name (to factor out differences in the |.tex| extension), and +% then does a file lookup to take into account a possible path from +% \cs{l_file_search_path_seq} and \cs{input@path}. However only +% the file name and extension are returned so that file hooks can +% refer to the file by their name only. The path to the file is +% returned in \cs{CurrentFilePath}. +% \begin{macrocode} + \edef\reserved@a{\@filef@und + \@expl@@@filehook@file@pop@assign@@nnnn + {\CurrentFilePathUsed}% + {\CurrentFileUsed}% + {\CurrentFilePath}% + {\CurrentFile}}% + \expandafter\@swaptwoargs\expandafter + {\reserved@a}% + {% + #2% + \@addtofilelist{#1}% + \UseHook{file/before}% +% \end{macrocode} +% The current file name is available in \cs{CurrentFile} so we use +% that in the specific hook. +% \begin{macrocode} + \UseHook{file/before/\CurrentFile}% + \@@input + }% +% \end{macrocode} +% And it is restored here so we can use it once more. +% \begin{macrocode} + \UseHook{file/after/\CurrentFile}% + \UseHook{file/after}% + \@expl@@@filehook@file@pop@@ + }% +} +%<latexrelease>\EndIncludeInRelease +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \changes{v0.9b} +% {1993/12/04}{Macro added} +% \changes{v0.9p} +% {1994/01/18}{New Definition} +% \changes{v0.3b}{1994/03/13} +% {Use new cmd \cs{@addtofilelist}} +% Now define |\InputIfFileExists| to input |#1| if it seems to exist. +% Immediately prior to the input, |#2| is executed. +% If the file |#1| does not exist, execute `|#3|'. +% \changes{v1.0t}{1995/05/25} +% {(CAR) added \cs{long}} +% \changes{v1.1o}{2019/02/07}{Expand \cs{@filef@und} before executing +% second argument (github/109)} +% \changes{v1.2b}{2019/08/27}{Make command robust} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\InputIfFileExists}{Hook management (files)}% +%<latexrelease> +%<latexrelease>\DeclareRobustCommand \InputIfFileExists[2]{% +%<latexrelease> \IfFileExists{#1}% +%<latexrelease> {% +%<latexrelease> \expandafter\@swaptwoargs\expandafter +%<latexrelease> {\@filef@und}{#2\@addtofilelist{#1}\@@input}}} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\InputIfFileExists}{Hook management (files)}% +%<latexrelease>\long\def \InputIfFileExists#1#2{% +%<latexrelease> \IfFileExists{#1}% +%<latexrelease> {#2\@addtofilelist{#1}\@@input \@filef@und}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% \subsection{Declaring a file substitution} +% +% \begin{macrocode} +%<@@=filehook> +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@@_subst_add:nn}{Declaring file substitution}% +\ExplSyntaxOn +% \end{macrocode} +% +% +% \begin{macro}{\@@_subst_add:nn,\@@_subst_remove:n, +% \@@_subst_file_normalize:n,\@@_subst_empty_name_chk:NN} +% \cs{@@_substitution_lthooadd:nn} declares a file substitution by +% doing a (global) definition of the form +% |\def|\cs{@file-subst@\meta{file}}|{|\meta{replacement}|}|. +% The file names are properly sanitised, and normalized with the same +% treatment done for the file hooks. That is, a file replacement is +% declared by using the file name (and extension, if any) only, and +% the file path should not be given. If a file name is empty it is +% replaced by |.tex| (the empty csname is used to check that). +% \begin{macrocode} +\cs_new_protected:Npn \@@_subst_add:nn #1 #2 + { + \group_begin: + \cs_set:cpx { } { \exp_not:o { \cs:w\cs_end: } } + \int_set:Nn \tex_escapechar:D { -1 } + \cs_gset:cpx { @file-subst@ \@@_subst_file_normalize:n {#1} } + { \@@_subst_file_normalize:n {#2} } + \group_end: + } +\cs_new_protected:Npn \@@_subst_remove:n #1 + { + \group_begin: + \cs_set:cpx { } { \exp_not:o { \cs:w\cs_end: } } + \int_set:Nn \tex_escapechar:D { -1 } + \cs_undefine:c { @file-subst@ \@@_subst_file_normalize:n {#1} } + \group_end: + } +\cs_new:Npn \@@_subst_file_normalize:n #1 + { + \exp_after:wN \@@_subst_empty_name_chk:NN + \cs:w \exp_after:wN \cs_end: + \cs:w \@@_file_parse_full_name:nN {#1} \use_ii_iii:nnn \cs_end: + } +\cs_new:Npn \@@_subst_empty_name_chk:NN #1 #2 + { \if_meaning:w #1 #2 .tex \else: \token_to_str:N #2 \fi: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\use_ii_iii:nnn} +% A variant of \cs[no-index]{use_...} to discard the first of three +% arguments. +% \fmi{this should move to \pkg{expl3}} +% \begin{macrocode} +\cs_gset:Npn \use_ii_iii:nnn #1 #2 #3 {#2 #3} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macrocode} +\ExplSyntaxOff +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% +% +% \begin{macro}{\declare@file@substitution} +% \begin{macro}{\undeclare@file@substitution} +% For two internals we provide \LaTeXe{} names so that we can use +% them elsewhere in the kernel (and so that they can be used in +% packages if really needed, e.g., \pkg{scrlfile}). +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\declare@file@substitution}{File substitution}% +\ExplSyntaxOn +\cs_new_eq:NN \declare@file@substitution \@@_subst_add:nn +\cs_new_eq:NN \undeclare@file@substitution \@@_subst_remove:n +\ExplSyntaxOff +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \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> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% +% \begin{macrocode} +%<@@=> +\ExplSyntaxOff +% \end{macrocode} +% +% \subsection{Selecting a file (\cs{set@curr@file})} +% +% \begin{macro}{\set@curr@file,\@curr@file,\@curr@file@reqd} +% Now we hook into \cs{set@curr@file} to resolve a possible file +% substitution, and add \cs{@expl@@@filehook@set@curr@file@@N} at the end, after +% \cs{@curr@file} is set. +% +% 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 +% substitution, returning a control sequence with the same name as the +% file. +% +% It happens that when \meta{filename} is empty, the generated control +% sequence is \cs{csname\cs{endcsname}}, and doing \cs{string} on +% that results in the file |csnameendcsname.tex|. To guard against +% that we \cs{ifx}-compare the generated control sequence with the +% empty csname. To do so, \cs{csname\cs{endcsname}} has to be +% defined, otherwise it would be equal to \cs{relax} and we would have +% false positives. Here we define \cs{csname\cs{endcsname}} to +% expand to itself to avoid it matching the definition of some other +% control sequence. +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\set@curr@file}{Setting current file name}% +\def\set@curr@file#1{% + \begingroup + \escapechar\m@ne + \expandafter\def\csname\expandafter\endcsname + \expandafter{\csname\endcsname}% +% \end{macrocode} +% Two file names are set here: \cs{@curr@file@reqd} which is the file +% requested by the user, and \cs{@curr@file} which should be the same, +% except when we have a file substitution, in which case it holds the +% 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 +% executed. +% +% At this stage the file name is parsed and normalized, but if the +% input doesn't have an extension, the default |.tex| is \emph{not} +% added to \cs{@curr@file} because for applications other than +% \cs{input} (graphics, for example) the default extension may not +% be |.tex|. First check if the input has an extension, then if the +% input had no extension, call \cs{@expl@@@filehook@drop@extension@@N}. In case +% of a file substitution, \cs{@curr@file} will have an extension. +% \begin{macrocode} + \@expl@@@filehook@if@no@extension@@nTF{#1}% + {\@tempswatrue}{\@tempswafalse}% + \@kernel@make@file@csname\@curr@file + \@expl@@@filehook@resolve@file@subst@@w {#1}% + \@expl@@@filehook@if@file@replaced@@TF + {\@kernel@make@file@csname\@curr@file@reqd + \@expl@@@filehook@normalize@file@name@@w{#1}% + \if@tempswa \@expl@@@filehook@drop@extension@@N\@curr@file@reqd \fi}% + {\if@tempswa \@expl@@@filehook@drop@extension@@N\@curr@file \fi + \global\let\@curr@file@reqd\@curr@file}% + \endgroup} +%</2ekernel|latexrelease> +%<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{% +%<latexrelease> \begingroup +%<latexrelease> \escapechar\m@ne +%<latexrelease> \xdef\@curr@file{% +%<latexrelease> \expandafter\expandafter\expandafter\unquote@name +%<latexrelease> \expandafter\expandafter\expandafter{% +%<latexrelease> \expandafter\string +%<latexrelease> \csname\@firstofone#1\@empty\endcsname}}% +%<latexrelease> \endgroup +%<latexrelease>} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\set@curr@file}{Setting current file name}% +%<latexrelease>\let\set@curr@file\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{\@filehook@set@CurrentFile} +% \begin{macro}{\@kernel@make@file@csname,\@set@curr@file@aux} +% +% \fmi{This should get internalized using \texttt{@expl@} names} +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@kernel@make@file@csname}{Make file csname}% +% \end{macrocode} +% +% \begin{macrocode} +\def\@kernel@make@file@csname#1#2#3{% + \xdef#1{\expandafter\@set@curr@file@aux + \csname\expandafter#2\@firstofone#3\@nil\endcsname}} +% \end{macrocode} +% This auxiliary compares \cs{\meta{filename}} with +% \cs{csname\cs{endcsname}} to check if the empty |.tex| file was +% requested. +% \begin{macrocode} +\def\@set@curr@file@aux#1{% + \expandafter\ifx\csname\endcsname#1% + .tex\else\string#1\fi} +% \end{macrocode} +% +% Then we call \cs{@expl@@@filehook@set@curr@file@@N} 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)}. +% Here too the slower route is only used if a substitution happened, +% but here \cs{@expl@@@filehook@if@file@replaced@@TF} can't be used because the +% flag is reset at the \cs{endgroup} above, so we check if +% \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. +% \begin{macrocode} +\def\@filehook@set@CurrentFile{% + \@expl@@@filehook@set@curr@file@@N{\@curr@file}% + \CurrentFileUsed\CurrentFilePathUsed + \ifx\@curr@file@reqd\@curr@file + \let\CurrentFile\CurrentFileUsed + \let\CurrentFilePath\CurrentFilePathUsed + \else + \@expl@@@filehook@set@curr@file@@N{\@curr@file@reqd}% + \CurrentFile\CurrentFilePath + \fi} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% \begin{macro}{\@@_set_curr_file:N, +% \@@_set_curr_file:nNN, +% \@@_set_curr_file_assign:nnnNN} +% When inputting a file, \cs{set@curr@file} does a file lookup +% (in \cs{input@path} and \cs{l_file_search_path_seq}) and returns the +% actual file name (\meta{base} plus \meta{ext}) in +% \cs{CurrentFileUsed}, and in case there's a file substitution, the +% requested file in \cs{CurrentFile} (otherwise both are the same). +% Only the base and extension are returned, +% regardless of the input (both \texttt{path/to/file.tex} and +% \texttt{file.tex} end up as \texttt{file.tex} in \cs{CurrentFile}). +% The path is returned in \cs{CurrentFilePath}, in case it's needed. +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {@@_set_curr_file:N}{Set curr file}% +\ExplSyntaxOn +%<@@=filehook> +\cs_new_protected:Npn \@@_set_curr_file:N #1 + { \exp_args:NV \@@_set_curr_file:nNN #1 } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_curr_file:nNN #1 + { + \@@_file_parse_full_name:nN {#1} + \@@_set_curr_file_assign:nnnNN + } +\cs_new_protected:Npn \@@_set_curr_file_assign:nnnNN #1 #2 #3 #4 #5 + { + \str_set:Nn #5 {#1} + \str_set:Nn #4 {#2#3} + } +\ExplSyntaxOff +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsection{Replacing a file and detecting loops} +% +% \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} +% 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}% +\ExplSyntaxOn +\cs_new:Npn \@@_resolve_file_subst:w #1 \@nil + { \@@_file_parse_full_name:nN {#1} \@@_file_subst_begin:nnn } +\cs_new:Npn \@@_normalize_file_name:w #1 \@nil + { \@@_file_parse_full_name:nN {#1} \@@_file_name_compose:nnn } +\cs_new:Npn \@@_file_name_compose:nnn #1 #2 #3 + { \tl_if_empty:nF {#1} { #1 / } #2#3 } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{flag @@_file_replaced} +% \begin{macro}{\@@_if_file_replaced:TF} +% Since the file replacement is done expandably in a \cs{csname}, use +% 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). +% \begin{macrocode} +\flag_new:n { @@_file_replaced } +\cs_new:Npn \@@_if_file_replaced:TF #1 #2 + { \flag_if_raised:nTF { @@_file_replaced } {#1} {#2} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_file_subst_begin:nnn} +% First off, start by checking if the current file ($\meta{name} + +% \meta{ext}$) has a declared substitution. If not, then just put +% that as the name (including a possible \meta{path} in this case): +% this is the default case with no substitutions, so it's the first to +% be checked. The auxiliary \cs{@@_file_subst_tortoise_hare:nn} sees +% that there's no replacement for |#2#3| and does nothing else. +% \begin{macrocode} +\cs_new:Npn \@@_file_subst_begin:nnn #1 #2 #3 + { + \@@_file_subst_tortoise_hare:nn { #2#3 } { #2#3 } + { \@@_file_name_compose:nnn {#1} {#2} {#3} } + } +\ExplSyntaxOff +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsubsection{The Tortoise and Hare algorithm} +% +% \begin{macro}{\@@_file_subst_tortoise_hare:nn} +% \begin{macro}{\@@_file_subst_loop:NN,\@@_file_subst_loop:cc} +% If there is a substitution (\meta{true} in the first +% \cs{cs_if_exist:cTF} below), then first check if there is no +% substitution down the line: this should be the second most common +% case, of one file replaced by another. In that case just leave the +% substitution there and the job is done. If any substitution +% happens, then the \cs{flag @@_file_replaced} is raised +% (conditionally, because checking if a flag is raised is much faster +% than raising it over and over again). +% +% If, however there are more substitutions, then we need to check for +% a possible loop in the substitutions, which would otherwise put +% \TeX{} in an infinite loop if just an exhaustive expansion was used. +% +% To detect a loop, the \emph{Tortoise and Hare} algorithm is used. +% The name of the algorithm is an analogy to Aesop's fable, in which +% the Hare outruns a Tortoise. The two pointers here are the csnames +% which contains each file replacement, both of which start at the +% position zero, which is the file requested. In the inner part of +% 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. +% +% Within \cs{@@_file_subst_loop:NN} the two substitutions are +% compared, and if they lead to the same file it means that there is +% a loop in the substitutions. If there's no loop, +% \cs{@@_file_subst_tortoise_hare:nn} is called again with the +% Tortoise at position~1 and the hare at~2. Again, the substitutions +% are checked ahead of the Hare pointer to check that it won't run too +% far; in case there is no loop in the declarations, eventually one +% of the \cs{cs_if_exist:cTF} below will go \meta{false} and the +% algorithm will end; otherwise it will run until the Hare reaches +% the same spot as the tortoise and a loop is detected. +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@@_file_subst_tortoise_hare:nn}{Tortoise and Hare}% +\ExplSyntaxOn +\cs_new:Npn \@@_file_subst_tortoise_hare:nn #1 #2 #3 + { + \cs_if_exist:cTF { @file-subst@ #2 } + { + \flag_if_raised:nF { @@_file_replaced } + { \flag_raise:n { @@_file_replaced } } + \cs_if_exist:cTF { @file-subst@ \use:c { @file-subst@ #2 } } + { + \@@_file_subst_loop:cc + { @file-subst@ #1 } + { @file-subst@ \use:c { @file-subst@ #2 } } + } + { \use:c { @file-subst@ #2 } } + } + { #3 } + } +% \end{macrocode} +% This is just an auxiliary to check if a loop was found, and continue +% the algorithm otherwise. If a loop is found, the |.tex| file is +% used as fallback and \cs{@@_file_subst_cycle_error:cN} is called to +% report the error. +% \begin{macrocode} +\cs_new:Npn \@@_file_subst_loop:NN #1 #2 + { + \token_if_eq_meaning:NNTF #1 #2 + { + .tex + \@@_file_subst_cycle_error:cN { @file-subst@ #1 } #1 + } + { \@@_file_subst_tortoise_hare:nn {#1} {#2} {#2} } + } +\cs_generate_variant:Nn \@@_file_subst_loop:NN { cc } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{ +% \@@_file_subst_cycle_error:NN, +% \@@_file_subst_cycle_error:cN, +% } +% Showing this type of error expandably is tricky, as we have a very +% limited amount of characters to show and a potentially large list. +% As a work around, several errors are printed, each showing one step +% of the loop, until all the error messages combined show the loop. +% \begin{macrocode} +\cs_new:Npn \@@_file_subst_cycle_error:NN #1 #2 + { + \__kernel_msg_expandable_error:nnff { kernel } { file-cycle } + {#1} { \use:c { @file-subst@ #1 } } + \token_if_eq_meaning:NNF #1 #2 + { \@@_file_subst_cycle_error:cN { @file-subst@ #1 } #2 } + } +\cs_generate_variant:Nn \@@_file_subst_cycle_error:NN { c } +% \end{macrocode} +% +% And the error message: +% \begin{macrocode} +\__kernel_msg_new:nnn { kernel } { file-cycle } + { File~loop!~#1~replaced~by~#2... } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +\ExplSyntaxOff +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% +% \subsection{Preventing a package from loading} +% +% We support the use case of preventing a package from loading but not +% any other type of files (e.g., classes). +% +% \begin{macro}{\disable@package@load} +% \begin{macro}{\reenable@package@load} +% \begin{macro}{\@disable@packageload@do} +% \cs{disable@package@load} defines +% \cs[no-index]{@pkg-disable@\meta{package}} to expand to some code |#2| +% instead of loading the package. +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\disable@package@load}{Disable packages}% +\def\disable@package@load#1#2{% + \global\@namedef{@pkg-disable@#1.\@pkgextension}{#2}} +% \end{macrocode} +% +% \begin{macrocode} +\def\@disable@packageload@do#1#2{% + \@ifundefined{@pkg-disable@#1}{#2}% + {\@nameuse{@pkg-disable@#1}}} +% \end{macrocode} +% +% \cs{reenable@package@load} undefines +% \cs[no-index]{@pkg-disable@\meta{package}} to reallow loading a package. +% \begin{macrocode} +\def\reenable@package@load#1{% + \global\expandafter\let + \csname @pkg-disable@#1.\@pkgextension \endcsname \@undefined} +% \end{macrocode} +% +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\disable@package@load}{Disable packages}% +%<latexrelease> +%<latexrelease>\let\disable@package@load \@undefined +%<latexrelease>\let\@disable@packageload@do\@undefined +%<latexrelease>\let\reenable@package@load \@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% +% +% \subsection{High-level interfaces for \LaTeX{}} +% +% None so far and the general feeling for now is that the hooks are +% enough. Packages like \pkg{filehook}, etc., may use them to set +% up their interfaces (samples are given below) but for the now the +% kernel will not provide any. +% +% +% +% \subsection{Internal commands needed elsewhere} +% +% Here we set up a few horrible (but consistent) \LaTeXe{} names to +% allow for internal commands to be used outside this module (and +% in parts that still use \LaTeXe{} syntax. We have to unset the +% \texttt{@\/@} since we want double ``at'' sign in place of double +% underscores. +% +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@expl@@@filehook@if@no@extension@@nTF}{2e tmp interfaces}% +\ExplSyntaxOn +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@if@no@extension@@nTF + \__filehook_if_no_extension:nTF +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@set@curr@file@@N + \__filehook_set_curr_file:N +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@resolve@file@subst@@w + \__filehook_resolve_file_subst:w +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@normalize@file@name@@w + \__filehook_normalize_file_name:w +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@if@file@replaced@@TF + \__filehook_if_file_replaced:TF + +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@drop@extension@@N + \__filehook_drop_extension:N +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@file@push@@ + \__filehook_file_push: +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@file@pop@@ + \__filehook_file_pop: +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@filehook@file@pop@assign@@nnnn + \__filehook_file_pop_assign:nnnn +% \end{macrocode} +% +% +% \begin{macrocode} +\ExplSyntaxOff +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% This ends the kernel code in this file. +% \begin{macrocode} +%</2ekernel> +% \end{macrocode} +% +% +% +% \section{A sample package for structuring the log output} +% +% \begin{macrocode} +%<*structuredlog> +%<@@=filehook> +% \end{macrocode} +% +% \begin{macrocode} +\ProvidesExplPackage + {structuredlog}{\ltfilehookdate}{\ltfilehookversion} + {Structuring the TeX transcript file} +% \end{macrocode} +% +% \begin{macro}{\g_@@_nesting_level_int} +% Stores the current package nesting level. +% \begin{macrocode} +\int_new:N \g_@@_nesting_level_int +% \end{macrocode} +% Initialise the counter with the number of files in the +% \cs{@currnamestack} (the number of items divided by $3$) minus one, +% because this package is skipped when printing to the log. +% \begin{macrocode} +\int_gset:Nn \g_@@_nesting_level_int + { ( \tl_count:N \@currnamestack ) / 3 - 1 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_log_file_record:n} +% This macro is responsible for increasing and decresing 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. +% \begin{macrocode} +\cs_new_protected:Npn \@@_log_file_record:n #1 + { + \str_if_eq:nnT {#1} {START} { \int_gincr:N \g_@@_nesting_level_int } + \iow_term:x + { + \prg_replicate:nn { \g_@@_nesting_level_int } { = } ~ + ( LEVEL ~ \int_use:N \g_@@_nesting_level_int \c_space_tl #1 ) ~ + \CurrentFileUsed +% \end{macrocode} +% If there was a file replacement, show that as well: +% \begin{macrocode} + \str_if_eq:NNF \CurrentFileUsed \CurrentFile + { ~ ( \CurrentFile \c_space_tl requested ) } + \iow_newline: + } + \str_if_eq:nnT {#1} {STOP} { \int_gdecr:N \g_@@_nesting_level_int } + } +% \end{macrocode} +% +% Now just hook the macro above in the generic |file/before|\ldots +% \begin{macrocode} +\AddToHook{file/before}{ \@@_log_file_record:n { START } } +% \end{macrocode} +% \ldots and |file/after| hooks. +% We don't want to install the \hook{file/after} hook immediately, +% because that would mean it is the first time executed when the +% package finishes. We therefore put the declaration inside +% \cs{AddToHookNext} so that it gets only installed when we have +% left this package. +% \begin{macrocode} +\AddToHookNext{file/after} + { \AddToHook{file/after}{ \@@_log_file_record:n { STOP } } } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<@@=> +%</structuredlog> +% \end{macrocode} +% +% +% +% +% +% +% \section{Package emulations} +% +% +% \subsection{Package \pkg{atveryend} emulation} +% +% With the new hook management and the hooks in \cs{enddocument} +% all of \pkg{atveryend} is taken care of. +% We can make an emulation only here after the substitution +% functionality is available: +% \begin{macrocode} +%<*2ekernel> +\declare@file@substitution{atveryend.sty}{atveryend-ltx.sty} +%</2ekernel> +% \end{macrocode} +% +% Here is the package file we point to: +% \begin{macrocode} +%<*atveryend-ltx> +\ProvidesPackage{atveryend-ltx} + [2020/08/19 v1.0a + Emulation of the original atvery package^^Jwith kernel methods] +% \end{macrocode} +% +% +% Here are new definitions for its interfaces now pointing to the +% hooks in \cs{enddocument} +% \begin{macrocode} +\newcommand\AfterLastShipout {\AddToHook{enddocument/afterlastpage}} +\newcommand\AtVeryEndDocument {\AddToHook{enddocument/afteraux}} +% \end{macrocode} +% Next one is a bit of a fake, but the result should normally be as +% expected. If not, one needs to add a rule to sort the code chunks +% in \hook{enddocument/info}. +% \begin{macrocode} +\newcommand\AtEndAfterFileList{\AddToHook{enddocument/info}} +% \end{macrocode} +% +% \begin{macrocode} +\newcommand\AtVeryVeryEnd {\AddToHook{enddocument/end}} +% \end{macrocode} +% +% \begin{macro}{\BeforeClearDocument} +% This one is the only one we don't implement or rather don't have +% a dedicated hook in the code. +% \begin{macrocode} +\ExplSyntaxOn +\newcommand\BeforeClearDocument[1] + { \AtEndDocument{#1} + \atveryend@DEPRECATED{BeforeClearDocument \tl_to_str:n{#1}} + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Npn\atveryend@DEPRECATED #1 + {\iow_term:x{======~DEPRECATED~USAGE~#1~==========}} +\ExplSyntaxOff +% \end{macrocode} +% \end{macro} +% +% +% \begin{macrocode} +%</atveryend-ltx> +% \end{macrocode} +% +% +% +% \Finale +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\endinput +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% + diff --git a/Master/texmf-dist/source/latex/base/ltfiles.dtx b/Master/texmf-dist/source/latex/base/ltfiles.dtx index 33594a7b912..835f600e323 100644 --- a/Master/texmf-dist/source/latex/base/ltfiles.dtx +++ b/Master/texmf-dist/source/latex/base/ltfiles.dtx @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltfiles.dtx} - [2019/11/11 v1.2f LaTeX Kernel (File Handling)] + [2020/08/21 v1.2i LaTeX Kernel (File Handling)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltfiles.dtx} @@ -47,6 +47,8 @@ Chris Rowley\and Rainer Sch\"opf} +\providecommand\pkg[1]{\texttt{#1}} + \begin{document} \MaintainedByLaTeXTeam{latex} \maketitle @@ -55,6 +57,8 @@ %</driver> % \fi % +% \providecommand\hook[1]{\texttt{#1}} +% % % \changes{v1.0h}{1994/05/21}{Use new error commands} % \changes{v1.0n}{1994/11/17} @@ -62,6 +66,7 @@ % \changes{v1.0u}{1995/07/13}{Updates to docu} % \changes{v1.1m}{2015/02/21} % {Removed autoload support} +% \changes{v1.2i}{2020/08/21}{Integration of new hook management interface} % % \section{File Handling} % @@ -234,18 +239,28 @@ % \changes{v0.9e}{1993/12/09}{Hook added} % \begin{macrocode} %</2ekernel> -%<latexrelease>\IncludeInRelease{2017/04/15}% -%<latexrelease> {\document}{Save language for hyphenation}% +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\document}{Added hook to load l3backend code}% %<*2ekernel|latexrelease> +\def\document{% % \end{macrocode} -% Cancel the |\begingroup| from |\begin|. +% We do cancel the grouping as part of the \cs{begin} handling +% (this is now done inside \cs{begin} instead) so that the +% \hook{env/\meta{env}/begin} hook is not hidden inside \cs{begingroup} +% \texttt{...} \cs{endgroup}. % \begin{macrocode} -\def\document{\endgroup +% \endgroup % \end{macrocode} -% If some options on |\documentclass| haven't been used by any -% package we will now give a warning since this is most certainly a -% misspelling. +% % \begin{macrocode} + \UseOneTimeHook{begindocument/before}% + \@kernel@after@begindocument@before +% \end{macrocode} +% +% Added hook to load \textsf{l3backend} code: +% \changes{v1.2h}{2020/06/05}{Added hook to load \textsf{l3backend} code} +% \begin{macrocode} + \@expl@sys@load@backend@@ \ifx\@unusedoptionlist\@empty\else \@latex@warning@no@line{Unused global option(s):^^J% \@spaces[\@unusedoptionlist]}% @@ -348,9 +363,11 @@ % \changes{v1.1e}{1996/04/24} % {(DPC) Reset \cs{AtBeginDocument} eg for latex/1297} % \begin{macrocode} - \let\AtBeginDocument\@firstofone - \@begindocumenthook + \@kernel@before@begindocument + \UseOneTimeHook{begindocument}% + \@kernel@after@begindocument % \end{macrocode} +% % Most of the following assignments will be done globally in case % the user adds something like |\begin{multicols}| to the document % hook, i.e. starts are group in |\begin{document}|. @@ -399,13 +416,128 @@ % \begin{macrocode} \global\let\do\noexpand % \end{macrocode} +% +% \begin{macrocode} + \UseOneTimeHook{begindocument/end}% +% \end{macrocode} % \changes{v1.1c}{1995/12/05}{\cs{ignorespaces} added for latex/1933} -% Use of |\AtBeginDocument| hook might mean that we are already in +% Use of the hook might mean that we are already in % horizontal mode, so ignore the space after |\begin{document}|. % \begin{macrocode} \ignorespaces} +% \end{macrocode} +% +% The \hook{begindocument} hook already existed in the kernel since +% 1994 under the name \cs{atbegindocumenthook} the +% additional ones are originally from the \pkg{etoolbox} +% package under the names \cs{@endpreamblehook} \cs{afterpreamble}. +% \begin{macrocode} +\NewHook{begindocument} +\NewHook{begindocument/before} +\NewHook{begindocument/end} +% \end{macrocode} + + + +% \begin{macro}{\@kernel@after@begindocument@before, +% \@kernel@before@begindocument, +% \@kernel@after@begindocument} +% +% Above we used two kernel only hooks to be run after the public +% \hook{begindocument/before} and after \hook{begindocument} +% hooks. +% +% In \cs{@kernel@after@begindocument@before} we already place one +% action: drop the fast execution code for the +% \hook{env/document/begin} hook. That hook marks the end of the +% preamble and should therefore only be run once. In a normal +% document that is anyway the case (so the code would just sit +% there taking up space afterwards, which these days is rather +% 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 +% due to the name of the macro which requires constructing. +% \begin{macrocode} +\edef \@kernel@after@begindocument@before {% + \let\expandafter\noexpand\csname + __hook env/document/begin\endcsname + \noexpand\@empty} +% \end{macrocode} +% +% \begin{macrocode} +\let \@kernel@before@begindocument \@empty +\let \@kernel@after@begindocument \@empty +% \end{macrocode} +% +% \end{macro} +% + +% +% \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2017/04/15}% +%<latexrelease> {\document}{Save language for hyphenation}% +%<latexrelease> +%<latexrelease>\def\document{\endgroup +%<latexrelease> \ifx\@unusedoptionlist\@empty\else +%<latexrelease> \@latex@warning@no@line{Unused global option(s):^^J% +%<latexrelease> \@spaces[\@unusedoptionlist]}% +%<latexrelease> \fi +%<latexrelease> \@colht\textheight +%<latexrelease> \@colroom\textheight \vsize\textheight +%<latexrelease> \columnwidth\textwidth +%<latexrelease> \@clubpenalty\clubpenalty +%<latexrelease> \if@twocolumn +%<latexrelease> \advance\columnwidth -\columnsep +%<latexrelease> \divide\columnwidth\tw@ \hsize\columnwidth \@firstcolumntrue +%<latexrelease> \fi +%<latexrelease> \hsize\columnwidth \linewidth\hsize +%<latexrelease> \begingroup\@floatplacement\@dblfloatplacement +%<latexrelease> \makeatletter\let\@writefile\@gobbletwo +%<latexrelease> \global \let \@multiplelabels \relax +%<latexrelease> \@input{\jobname.aux}% +%<latexrelease> \endgroup +%<latexrelease> \if@filesw +%<latexrelease> \immediate\openout\@mainaux\jobname.aux +%<latexrelease> \immediate\write\@mainaux{\relax}% +%<latexrelease> \fi +%<latexrelease> \process@table +%<latexrelease> \let\glb@currsize\@empty % Force math initialization. +%<latexrelease> \normalsize +%<latexrelease> \everypar{}% +%<latexrelease> \ifx\normalsfcodes\@empty +%<latexrelease> \ifnum\sfcode`\.=\@m +%<latexrelease> \let\normalsfcodes\frenchspacing +%<latexrelease> \else +%<latexrelease> \let\normalsfcodes\nonfrenchspacing +%<latexrelease> \fi +%<latexrelease> \fi +%<latexrelease> \ifx\document@default@language\m@ne +%<latexrelease> \chardef\document@default@language\language +%<latexrelease> \fi +%<latexrelease> \@noskipsecfalse +%<latexrelease> \let \@refundefined \relax +%<latexrelease> \let\AtBeginDocument\@firstofone +%<latexrelease> \@begindocumenthook +%<latexrelease> \ifdim\topskip<1sp\global\topskip 1sp\relax\fi +%<latexrelease> \global\@maxdepth\maxdepth +%<latexrelease> \global\let\@begindocumenthook\@undefined +%<latexrelease> \ifx\@listfiles\@undefined +%<latexrelease> \global\let\@filelist\relax +%<latexrelease> \global\let\@addtofilelist\@gobble +%<latexrelease> \fi +%<latexrelease> \gdef\do##1{\global\let ##1\@notprerr}% +%<latexrelease> \@preamblecmds +%<latexrelease> \global\let \@nodocument \relax +%<latexrelease> \global\let\do\noexpand +%<latexrelease> \ignorespaces} +%<latexrelease>\EndIncludeInRelease +%<latexrelease> %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\document}{Save language for hyphenation} %<latexrelease>\def\document{\endgroup @@ -539,26 +671,14 @@ % \end{macrocode} % % -% \begin{macro}{\includeonly} +% \begin{macro}{\include,\includeonly} +% \changes{v0.9p}{1994/01/18} +% {Use \cs{@input@} so include files are listed.} % \changes{v1.0p}{1995/04/22}{Allow blanks in argument} % \changes{v1.2a}{2019/07/01}{Support UTF-8} -% \begin{macrocode} -%</2ekernel> -%<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\includeonly}{Spaces in file names}% -\def\includeonly#1{% - \@partswtrue - \set@curr@file{\zap@space#1 \@empty}% - \let\@partlist\@curr@file - } -\@onlypreamble\includeonly -% \end{macrocode} -% \end{macro} +% \changes{v1.2g}{2020/05/02}{Improved support for spaces in filenames +% (gh/217)} % -% \begin{macro}{\include} -% \changes{v0.9p}{1994/01/18} -% {Use \cs{@input@} so include files are listed.} % In the definition of |\include|, |\def\reserved@b| changed to % |\edef\reserved@b| to be consistent with the |\edef| in % |\includeonly|. @@ -572,21 +692,113 @@ % % Made |\include| check for being used inside an |\include|'d file, as % this will not work and cause surprising results. +% \changes{v1.2g}{2020/05/02}{Get rid of leading and trailing spaces +% from the filename (gh/217)} +% \changes{v1.2g}{2020-05-02}{Pass the filename to \cs{@include} by +% value instead of by reference (gh/217)} +% +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\includeonly}{Spaces in file names}% +% \end{macrocode} +% % \begin{macrocode} \def\include#1{\relax \ifnum\@auxout=\@partaux \@latex@error{\string\include\space cannot be nested}\@eha \else - \set@curr@file{#1 }% - \expandafter\@include\@curr@file +% \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 +% 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 +% errors in other packages that use \cs{@include} directly. +% \begin{macrocode} + \expandafter\@include\expandafter{\@curr@file} % deliberate space \fi} % \end{macrocode} -% \end{macro} % +% Here in \cs{includeonly} we also need to strip |.tex| after +% normalisation: +% \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 +% 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. +% \begin{macrocode} + \let\@partlist\@empty + \@for\reserved@a:=#1 \do + {% + \expandafter\set@curr@file\expandafter{\reserved@a}% + \ifx\@partlist\@empty + \edef\@partlist{\@strip@tex@ext\@curr@file}% + \else + \edef\@partlist{\@partlist,\@strip@tex@ext\@curr@file}% + \fi + }% + } +\@onlypreamble\includeonly +% \end{macrocode} +% \end{macro} % +% \begin{macro}{\@strip@tex@ext,\@strip@tex@ext@aux} +% These macros take a (\cs{detokenize}d file name and remove any +% |.tex| extension). Extra care is taken to not remove the string +% |.tex| from the middle of a file name: it is only removed if it's +% the very last thing in the file name. % \begin{macrocode} +\def\reserved@a#1{% +\def\@strip@tex@ext##1{% + \expandafter\@strip@tex@ext@aux + ##1\@nil\@nil + #1\@nil\relax\@nnil} +\def\@strip@tex@ext@aux##1#1\@nil##2\@nnil{% + \ifx\relax##2\@empty + \expandafter\@cdr\expandafter\@empty\@cdr{}##1% + \else##1\fi}}% +\expandafter\reserved@a +\expandafter{\detokenize{.tex}} %</2ekernel|latexrelease> +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\includeonly}{Spaces in file names}% +%<latexrelease> +%<latexrelease>\def\includeonly#1{% +%<latexrelease> \@partswtrue +%<latexrelease> \set@curr@file{\zap@space#1 \@empty}% +%<latexrelease> \let\@partlist\@curr@file +%<latexrelease> } +%<latexrelease> +%<latexrelease>\def\include#1{\relax +%<latexrelease> \ifnum\@auxout=\@partaux +%<latexrelease> \@latex@error{\string\include\space cannot be nested}\@eha +%<latexrelease> \else +%<latexrelease> \set@curr@file{#1 }% +%<latexrelease> \expandafter\@include\@curr@file +%<latexrelease> \fi} +%<latexrelease> +%<latexrelease>\let\@strip@tex@ext\@undefined +%<latexrelease>\let\@strip@tex@ext@aux\@undefined +%<latexrelease> %<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\includeonly}{Spaces in file names}% %<latexrelease>\def\includeonly#1{% @@ -601,14 +813,22 @@ %<latexrelease>\EndIncludeInRelease %<*2ekernel> % \end{macrocode} - % % \begin{macro}{\@include} +% \changes{v1.2g}{2020/05/02}{Support spaces in filenames by enclosing +% the names of \texttt{.aux}-files in quotes (gh/217)} +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@include}{Spaces in file names and hooks}% +% \end{macrocode} +% % \begin{macrocode} \def\@include#1 {% \clearpage \if@filesw - \immediate\write\@mainaux{\string\@input{#1.aux}}% + \immediate\write\@mainaux{\string\@input{"#1.aux"}}% \fi \@tempswatrue \if@partsw @@ -620,11 +840,41 @@ \if@tempswa \let\@auxout\@partaux \if@filesw - \immediate\openout\@partaux #1.aux + \immediate\openout\@partaux "#1.aux" \immediate\write\@partaux{\relax}% \fi +% \end{macrocode} +% Now before going to the hooks we need to set \cs{CurrentFile}: +% \begin{macrocode} +%----------------------------------------- + \@filehook@set@CurrentFile +% \end{macrocode} +% Execute the \texttt{before} hooks just after we switched the +% \texttt{.aux} file \ldots +% \begin{macrocode} + \UseHook{include/before}% + \UseHook{include/before/#1}% +%----------------------------------------- \@input@{#1.tex}% +%----------------------------------------- +% \end{macrocode} +% \ldots{} then \texttt{end} hooks \ldots +% \begin{macrocode} + \UseHook{include/end/#1}% + \UseHook{include/end}% +%----------------------------------------- \clearpage +%----------------------------------------- +% \end{macrocode} +% \ldots{} and after the \cs{clearpage} the \texttt{after} hooks +% followed by another \cs{clearpage} just in case new material got +% added (after all we need to be in well defined state after the +% \cs{include}). +% \begin{macrocode} + \UseHook{include/after/#1}% + \UseHook{include/after}% + \clearpage +%----------------------------------------- \@writeckpt{#1}% \if@filesw \immediate\closeout\@partaux @@ -640,6 +890,45 @@ \@nameuse{cp@#1}% \fi \let\@auxout\@mainaux} +%<latexrelease>\EndIncludeInRelease +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@include}{Spaces in file names}% +%<latexrelease>\def\@include#1 {% +%<latexrelease> \clearpage +%<latexrelease> \if@filesw +%<latexrelease> \immediate\write\@mainaux{\string\@input{#1.aux}}% +%<latexrelease> \fi +%<latexrelease> \@tempswatrue +%<latexrelease> \if@partsw +%<latexrelease> \@tempswafalse +%<latexrelease> \edef\reserved@b{#1}% +%<latexrelease> \@for\reserved@a:=\@partlist\do +%<latexrelease> {\ifx\reserved@a\reserved@b\@tempswatrue\fi}% +%<latexrelease> \fi +%<latexrelease> \if@tempswa +%<latexrelease> \let\@auxout\@partaux +%<latexrelease> \if@filesw +%<latexrelease> \immediate\openout\@partaux #1.aux +%<latexrelease> \immediate\write\@partaux{\relax}% +%<latexrelease> \fi +%<latexrelease> \@input@{#1.tex}% +%<latexrelease> \clearpage +%<latexrelease> \@writeckpt{#1}% +%<latexrelease> \if@filesw +%<latexrelease> \immediate\closeout\@partaux +%<latexrelease> \fi +%<latexrelease> \else +%<latexrelease> \deadcycles\z@ +%<latexrelease> \@nameuse{cp@#1}% +%<latexrelease> \fi +%<latexrelease> \let\@auxout\@mainaux} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -688,7 +977,6 @@ % % % - % \begin{macro}{\@curr@file} % \begin{macro}{\set@curr@file} % @@ -698,8 +986,8 @@ % the code in \texttt{utf8.def}). By setting \cs{escapchar} to % \texttt{-1} we ensure that we don't get a backslash in front. As a % result we end up with all characters as catcode 12 (plus -% spaces). We then sometimes add quotes around the contruct -% (removing any existing inner quotes. Somes we only remove the +% spaces). We then sometimes add quotes around the construct +% (removing any existing inner quotes. Sometimes we only remove the % quotes if they have been supplied by the user. There is clearly % some room for improvement. % @@ -716,11 +1004,11 @@ % \changes{v1.2c}{2019/10/11}{Remove one brace group} % \changes{v1.2d}{2019/10/26}{remove quotes} % \changes{v1.2e}{2019/11/09}{expand and \cs{string} before removing quotes} +% +% The definition below is from 2019 and only used during kernel +% bootstrapping, later on in \texttt{ltfilehook.dtx} it will get +% overwritten. % \begin{macrocode} -%</2ekernel> -%<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\set@curr@file}{Quote file names}% \def\set@curr@file#1{% \begingroup \escapechar\m@ne @@ -747,6 +1035,10 @@ % -> "" %\end{verbatim} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\quote@name}{Quote file names}% \def\quote@name#1{"\quote@@name#1\@gobble""} \def\quote@@name#1"{#1\quote@@name} % \end{macrocode} @@ -828,12 +1120,11 @@ %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% -%<latexrelease> {\set@curr@file}{Quote file names}% +%<latexrelease> {\quote@name}{Quote file names}% %<latexrelease> %<latexrelease>\let\quote@name\@undefined %<latexrelease>\let\quote@@name\@undefined %<latexrelease>\let\unquote@name\@undefined -%<latexrelease>\let\set@curr@file\@undefined %<latexrelease> %<latexrelease>\let\IfFileExists@\@undefined %<latexrelease> @@ -873,25 +1164,14 @@ % % % \begin{macro}{\InputIfFileExists} -% \changes{v0.9b} -% {1993/12/04}{Macro added} -% \changes{v0.9p} -% {1994/01/18}{New Definition} -% \changes{v0.3b}{1994/03/13} -% {Use new cmd \cs{@addtofilelist}} -% Now define |\InputIfFileExists| to input |#1| if it seems to exist. -% Immediately prior to the input, |#2| is executed. -% If the file |#1| does not exist, execute `|#3|'. -% \changes{v1.0t}{1995/05/25} -% {(CAR) added \cs{long}} -% \changes{v1.1o}{2019/02/07}{Expand \cs{@filef@und} before executing -% second argument (github/109)} -% \changes{v1.2b}{2019/08/27}{Make command robust} -% \begin{macrocode} -%</2ekernel> -%<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\InputIfFileExists}{Don't lose the file name}% -%<*2ekernel|latexrelease> +% +% Now define |\InputIfFileExists| to input |#1| if it seems to exist. +% Immediately prior to the input, |#2| is executed. +% If the file |#1| does not exist, execute `|#3|'. +% +% This here is a temporary definition for the kernel. The real one +% comes somewhat later in the file \texttt{ltfilehook.dtx}. +% % \begin{macrocode} \DeclareRobustCommand \InputIfFileExists[2]{% \IfFileExists{#1}% @@ -908,25 +1188,23 @@ % Swap two arguments and return them unbraced (like % \cs{@firstoftwo} etc). % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\@swaptwoargs}{Don't lose the file name}% \long\def\@swaptwoargs#1#2{#2#1} % \end{macrocode} -% \end{macro} -% % % \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% -%<latexrelease> {\InputIfFileExists}{Don't lose the file name}% -%<latexrelease>\long\def \InputIfFileExists#1#2{% -%<latexrelease> \IfFileExists{#1}% -%<latexrelease> {#2\@addtofilelist{#1}\@@input \@filef@und}} -%<latexrelease> +%<latexrelease> {\@swaptwoargs}{Don't lose the file name}% %<latexrelease>\let\@swaptwoargs\@undefined %<latexrelease>\EndIncludeInRelease %<*2ekernel> % \end{macrocode} -% +% \end{macro} % % % \begin{macro}{\input} @@ -943,20 +1221,51 @@ % Define |\@iinput| (i.e., |\input|) in terms of % |\InputIfIfileExists|. % \changes{v0.9b}{1993/12/04}{Macro reimplemented} +% +% Changes to \cs{@iinput}: adapt to the changes to +% \cs{@missingfileerror}. % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\@iinput}{Quote file names}% +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@iinput}{Change in file error handling}% \def\@iinput#1{% \InputIfFileExists{#1}{}% {\filename@parse\@curr@file \edef\reserved@a{\noexpand\@missingfileerror {\filename@area\filename@base}% {\ifx\filename@ext\relax tex\else\filename@ext\fi}}% +% \end{macrocode} +% This line now just sets \cs[no-index]{@missingfile@\meta{part}}: +% \begin{macrocode} + \reserved@a +% \end{macrocode} +% Now here we have to use it. The file here is guaranteed to exist, +% because \cs{@missingfileerror} ensures so, but we have to use +% \cs{InputIfFileExists} because it executes the file hooks. +% \begin{macrocode} + \edef\reserved@a{\noexpand\@iinput{% + \@missingfile@area\@missingfile@base.\@missingfile@ext}}% \reserved@a}} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\@iinput}{Quote file names}% +%<latexrelease> +%<latexrelease>\def\@iinput#1{% +%<latexrelease> \InputIfFileExists{#1}{}% +%<latexrelease> {\filename@parse\@curr@file +%<latexrelease> \edef\reserved@a{\noexpand\@missingfileerror +%<latexrelease> {\filename@area\filename@base}% +%<latexrelease> {\ifx\filename@ext\relax tex\else\filename@ext\fi}}% +%<latexrelease> \reserved@a}} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\@iinput}{Quote file names}% %<latexrelease>\def\@iinput#1{% @@ -1001,6 +1310,11 @@ % \end{macrocode} % \end{macro} % +% +% +% +% +% % \begin{macro}{\@missingfileerror} % This `error' command avoids \TeX's primitive missing file loop. % @@ -1018,7 +1332,16 @@ % {Move here from ltclass} % \changes{v1.0w}{1995/10/06} % {Autoload error} +% +% Changes to \cs{@missingfileerror}: rather than trying to input the +% file by force, now \cs{@missingfileerror} just returns three +% \cs[no-index]{@missingfile@\meta{part}} and the caller macro is +% responsible for doing the right thing with it. % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@missingfileerror}{Do not load missing file immediately}% \gdef\@missingfileerror#1#2{% \typeout{^^J! LaTeX Error: File `#1.#2' not found.^^J^^J% Type X to quit or <RETURN> to proceed,^^J% @@ -1027,20 +1350,74 @@ {\endlinechar\m@ne \global\read\m@ne to\@gtempa}% \ifx\@gtempa\@empty +% \end{macrocode} +% If the user answers with \meta{return}, fallback to the |.tex| file +% (previously it did nothing). +% \begin{macrocode} + \let\@missingfile@area\@empty + \let\@missingfile@base\@empty + \def\@missingfile@ext{tex}% \else - \def\reserved@a{x}\ifx\reserved@a\@gtempa\batchmode\@@end\fi - \def\reserved@a{X}\ifx\reserved@a\@gtempa\batchmode\@@end\fi +% \end{macrocode} +% Use \cs{batchmode}\cs{read}|-1 to |\meta{tl} to end the \TeX{} run, +% same as \pkg{expl3} does (it was \cs{batchmode}\cs{@@end} before). +% \begin{macrocode} + \def\reserved@b{\batchmode\read-1 to \reserved@a}% + \def\reserved@a{x}\ifx\reserved@a\@gtempa\reserved@b\fi + \def\reserved@a{X}\ifx\reserved@a\@gtempa\reserved@b\fi \filename@parse\@gtempa \edef\filename@ext{% \ifx\filename@ext\relax#2\else\filename@ext\fi}% \edef\reserved@a{% - \noexpand\InputIfFileExists +% \end{macrocode} +% Only check \cs{IfFileExists} (it was \cs{InputIfFileExists}). +% \begin{macrocode} + \noexpand\IfFileExists {\filename@area\filename@base.\filename@ext}% - {}% +% \end{macrocode} +% If the file exists, define \cs[no-index]{@missingfile@\meta{part}}. +% \begin{macrocode} + {\def\noexpand\@missingfile@area{\filename@area}% + \def\noexpand\@missingfile@base{\filename@base}% + \def\noexpand\@missingfile@ext {\filename@ext}}% {\noexpand\@missingfileerror {\filename@area\filename@base}{\filename@ext}}}% \reserved@a - \fi} + \fi +} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@missingfileerror}{Do not load missing file immediately}% +%<latexrelease> +%<latexrelease>\gdef\@missingfileerror#1#2{% +%<latexrelease> \typeout{^^J! LaTeX Error: File `#1.#2' not found.^^J^^J% +%<latexrelease> Type X to quit or <RETURN> to proceed,^^J% +%<latexrelease> or enter new name. (Default extension: #2)^^J}% +%<latexrelease> \message{Enter file name: }% +%<latexrelease> {\endlinechar\m@ne +%<latexrelease> \global\read\m@ne to\@gtempa}% +%<latexrelease> \ifx\@gtempa\@empty +%<latexrelease> \else +%<latexrelease> \def\reserved@a{x}\ifx\reserved@a\@gtempa\batchmode\@@end\fi +%<latexrelease> \def\reserved@a{X}\ifx\reserved@a\@gtempa\batchmode\@@end\fi +%<latexrelease> \filename@parse\@gtempa +%<latexrelease> \edef\filename@ext{% +%<latexrelease> \ifx\filename@ext\relax#2\else\filename@ext\fi}% +%<latexrelease> \edef\reserved@a{% +%<latexrelease> \noexpand\InputIfFileExists +%<latexrelease> {\filename@area\filename@base.\filename@ext}% +%<latexrelease> {}% +%<latexrelease> {\noexpand\@missingfileerror +%<latexrelease> {\filename@area\filename@base}{\filename@ext}}}% +%<latexrelease> \reserved@a +%<latexrelease> \fi} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/base/ltfinal.dtx b/Master/texmf-dist/source/latex/base/ltfinal.dtx index 56549507624..aa4219723af 100644 --- a/Master/texmf-dist/source/latex/base/ltfinal.dtx +++ b/Master/texmf-dist/source/latex/base/ltfinal.dtx @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltfinal.dtx} - [2019-10-02 v2.2 LaTeX Kernel (Final Settings)] + [2020-09-26 v2.2j LaTeX Kernel (Final Settings)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltfinal.dtx} @@ -88,6 +88,7 @@ % argument.} % \changes{v2.0r}{2016/10/15}{Require e\TeX{}} % \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} % @@ -460,6 +461,14 @@ \fi % \end{macrocode} % +% \changes{v2.2b}{2020/07/08} +% {Add a last-minute hook for \textsf{expl3}} +% At this stage, we can install any last-minute \textsf{expl3} set-up. +% \begin{macrocode} +\@expl@finalise@setup@@ +\def\@expl@finalise@setup@@{} +% \end{macrocode} +% % This is as good a place as any to active a few Xe\TeX{}-specific % settings % \begin{macrocode} @@ -582,7 +591,7 @@ % Skip this section in Unicode TeX, or if MLTeX and EncTeX are enabled. % \begin{macrocode} \ifnum0% - \ifx\Umathchar\@undefined\else 1\fi + \ifx\Umathcode\@undefined\else 1\fi \ifx\mubyte\@undefined\else 1\fi \ifx\charsubdef\@undefined\else 1\fi =\z@ @@ -1044,13 +1053,8 @@ % }{} % \end{macrocode} % -% \subsection{Loading further extensions} -% % \changes{v2.2}{2019-10-02}{Load \textsf{ltexpl}} -% Simply load further code: it's deliberately separate -% \begin{macrocode} -\input{ltexpl.ltx} -% \end{macrocode} +% \changes{v2.2a}{2020-06-04}{Load \textsf{ltexpl} in \texttt{ltdefns}} % % \subsection{Freeing Memory} % @@ -1124,14 +1128,6 @@ % \end{macro} % \end{macro} % -% \subsection{Some last minute initializations \ldots} -% -% This initializes the 2020/02/02 extensions to NFSS after any changes -% in the preamble. -% \begin{macrocode} -\AtBeginDocument{\reinstall@nfss@defs\init@series@setup} -% \end{macrocode} -% % % % \subsection{Do some temporary work for pre-release} @@ -1139,9 +1135,18 @@ % This is a good place to load code that hasn't yet been % integrated into the other files \ldots % \begin{macrocode} -%\input ... % \end{macrocode} % +% \subsection{Some last minute initializations \ldots} +% +% Load the first aid set of definitions for external packages that await updates. +% \changes{v2.2j}{2020/09/26} +% {Load first aid file if existing} +% \begin{macrocode} +\@input{latex2e-first-aid-for-external-files.ltx} +% \end{macrocode} +% +% % \subsection{Dumping the format} % Finally we make |@| into a letter, ensure the format will % be in the `normal' error mode, and dump everything into the diff --git a/Master/texmf-dist/source/latex/base/ltfloat.dtx b/Master/texmf-dist/source/latex/base/ltfloat.dtx index 23c3f464d3f..dee9a10197e 100644 --- a/Master/texmf-dist/source/latex/base/ltfloat.dtx +++ b/Master/texmf-dist/source/latex/base/ltfloat.dtx @@ -31,7 +31,7 @@ % %<*driver> % \fi -\ProvidesFile{ltfloat.dtx}[2015/02/21 v1.2c LaTeX Kernel (Floats)] +\ProvidesFile{ltfloat.dtx}[2020/04/09 v1.2d LaTeX Kernel (Floats)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltfloat.dtx} @@ -1327,13 +1327,36 @@ % always start with a font selection command, to activate the font % size switch. % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@textsuperscript}{superscript baseline}% \def\@textsuperscript#1{% - {\m@th\ensuremath{^{\mbox{\fontsize\sf@size\z@#1}}}}} + {\m@th\ensuremath{^{\mbox{\fontsize\sf@size\sf@size#1}}}}} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@textsuperscript}{superscript baseline}% +%<latexrelease> +%<latexrelease>\def\@textsuperscript#1{% +%<latexrelease> {\m@th\ensuremath{^{\mbox{\fontsize\sf@size\z@#1}}}}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % +% +% +% +% +% +% % \begin{macro}{\textsubscript} % \changes{v1.2a}{2014/12/30}{Command added (latexrelease)} +% \changes{v1.2d}{2020/04/09}{Set non-zero baseline (gh/249)} % \begin{macrocode} %</2ekernel> %<latexrelease>\IncludeInRelease{2015/01/01}% @@ -1345,27 +1368,54 @@ \DeclareRobustCommand*\textsubscript[1]{% \@textsubscript{\selectfont#1}}% % \end{macrocode} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\textsubscript}{\textsubscript}% +%<latexrelease>\let\textsubscript\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} % \end{macro} % +% +% +% % \begin{macro}{\@textsubscript} % \changes{v1.2a}{2014/12/30}{Command added (latexrelease)} -% +% \changes{v1.2d}{2020/04/09}{Set non-zero baseline (gh/249)} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@textsubscript}{subscript baseline}% \def\@textsubscript#1{% - {\m@th\ensuremath{_{\mbox{\fontsize\sf@size\z@#1}}}}} + {\m@th\ensuremath{_{\mbox{\fontsize\sf@size\sf@size#1}}}}} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2015/01/01}% +%<latexrelease> {\@textsubscript}{subscript baseline}% +%<latexrelease> +%<latexrelease>\def\@textsubscript#1{% +%<latexrelease> {\m@th\ensuremath{_{\mbox{\fontsize\sf@size\z@#1}}}}} % \end{macrocode} -% \end{macro} % % \begin{macrocode} -%</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% -%<latexrelease> {\textsubscript}{\textsubscript}% -%<latexrelease>\let\textsubscript\@undefined +%<latexrelease> {\@textsubscript}{subscript baseline}% %<latexrelease>\let\@textsubscript\@undefined %<latexrelease>\EndIncludeInRelease %<*2ekernel> % \end{macrocode} +% \end{macro} +% +% % % \begin{macro}{\footnotesep} % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/base/ltfssaxes.dtx b/Master/texmf-dist/source/latex/base/ltfssaxes.dtx index 02a49a3122d..d8e4286b786 100644 --- a/Master/texmf-dist/source/latex/base/ltfssaxes.dtx +++ b/Master/texmf-dist/source/latex/base/ltfssaxes.dtx @@ -35,7 +35,7 @@ % % \ProvidesFile{ltfssaxes.dtx} - [2020/02/27 v1.0d LaTeX Kernel (NFSS Axes handing)] + [2020/08/21 v1.0g LaTeX Kernel (NFSS Axes handing)] % \iffalse \documentclass{ltxdoc} \begin{document} @@ -695,7 +695,7 @@ % % \begin{macro}{\fontseriesforce} % To change unconditionally to a new series you can use -% \cs{fontseriesforce}. If course, if the series doesn't exist for +% \cs{fontseriesforce}. Of course, if the series doesn't exist for % the current family substitution still happens, but there is not % dependency on the current series. % \changes{v1.0c}{2020/02/10}{Switch \cs{if@forced@series} added} @@ -849,7 +849,7 @@ % \changes{v1.0d}{2020/02/27}{Drop ``m'' only in a specific set of values (gh/293)} % \begin{macrocode} \edef\f@series{#1}% - \expandafter\series@maybe@drop@one@m\expandafter{\f@series}\f@series + \series@maybe@drop@one@m\f@series\f@series } % \end{macrocode} % \end{macro} @@ -865,7 +865,13 @@ % \changes{v1.0d}{2020/02/27}{Drop ``m'' in certain values from a % fixed list (gh/293)} % \begin{macrocode} -\def\series@maybe@drop@one@m#1#2{% +\def\series@maybe@drop@one@m#1{% + \expandafter\series@maybe@drop@one@m@x\expandafter{#1}} +% \end{macrocode} +% +% \begin{macrocode} + +\def\series@maybe@drop@one@m@x#1#2{% % \end{macrocode} % The code below is an inline version of the \cs{in@} macro without % the group, so that it works in \cs{accent}. @@ -875,7 +881,16 @@ ,ulm,elm,lm,slm,mm,sbm,bm,ebm,ubm,muc,mec,mc,msc,msx,mx,mex,mux,{}{},#1,}% \edef\in@@{\the\series@check@toks}% \ifx\in@@\@empty - \def#2{#1}% +% \end{macrocode} +% The default definition for \cs{bfdefault} etc is actually +% \texttt{b\cs{@empty}} so that we can detect if the user has +% changed the default. However that means a) the above test will +% definitely fail (maybe something to change) and b) we better use +% \cs{edef} on the next line to get rid of it as otherwise the test +% against \verb=#2= (e.g. \cs{bfdef@ult}) will fail in other places. +% \changes{v1.0e}{2020/05/19}{Need to use \cs{edef} (gh/336)} +% \begin{macrocode} + \edef#2{#1}% \else \edef#2{\expandafter\series@drop@one@m #1m\series@drop@one@m}% \fi @@ -891,7 +906,7 @@ % \begin{macro}{\series@drop@one@m} % Drop up to two \texttt{m}s but keep one if that makes the series % value empty. Actually, with the current implementation we know -% that there is at least one in the series value istelf and we +% that there is at least one in the series value itself and we % added one after it, so all we have to do is now returning % \verb=#1#2= and dropping the rest. % \begin{macrocode} @@ -949,6 +964,7 @@ \DeclareRobustCommand\ulcshape {\not@math@alphabet\ulcshape\relax \fontshape\ulcdefault\selectfont} +\let\ulcdefault\@undefined % for rollback \newcommand\ulcdefault{ulc} % \end{macrocode} % \end{macro} @@ -969,6 +985,7 @@ \DeclareRobustCommand\swshape {\not@math@alphabet\swshape\relax \fontshape\swdefault\selectfont} +\let\swdefault\@undefined % for rollback \newcommand\swdefault{sw} % \end{macrocode} % \end{macro} @@ -992,6 +1009,7 @@ \DeclareRobustCommand\sscshape {\not@math@alphabet\sscshape\relax \fontshape\sscdefault\selectfont} +\let\sscdefault\@undefined % for rollback \newcommand\sscdefault{ssc} % \end{macrocode} % \end{macro} @@ -1276,6 +1294,35 @@ %<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}% +\g@addto@macro\@kernel@after@begindocument@before + {\reinstall@nfss@defs\init@series@setup} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% The initialization was introduced in 2020/02/02 but +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/02/02}% +%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}% +%<latexrelease>\AtBeginDocument{\reinstall@nfss@defs\init@series@setup} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}% +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> %</2ekernel> % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/base/ltfssbas.dtx b/Master/texmf-dist/source/latex/base/ltfssbas.dtx index f51d742d466..4a6afca3ace 100644 --- a/Master/texmf-dist/source/latex/base/ltfssbas.dtx +++ b/Master/texmf-dist/source/latex/base/ltfssbas.dtx @@ -282,7 +282,7 @@ % \cs{reservedb} so we use that and also issue a warning. % \begin{macrocode} \edef\reserved@a{#3}% - \expandafter\series@maybe@drop@one@m\expandafter{#3}\reserved@b + \series@maybe@drop@one@m\reserved@a\reserved@b \ifx\reserved@a\reserved@b\else \@latex@warning{Font shape declaration has incorrect series value `#3'.\MessageBreak It should not contain an `m'! @@ -1850,7 +1850,7 @@ % Finally, it is not possible to simply call the new definition % since we % have an argument (the third argument of |\use@mathgroup| -% or more exactly the argument od |\math@egroup| if the {\ttfamily +% or more exactly the argument of |\math@egroup| if the {\ttfamily % margid} option is in force) % which would swallow our closing |\fi|. So % we use the |\expandafter| technique to remove the |\fi| diff --git a/Master/texmf-dist/source/latex/base/ltfssdcl.dtx b/Master/texmf-dist/source/latex/base/ltfssdcl.dtx index 951c6de2e5a..291cd1368f2 100644 --- a/Master/texmf-dist/source/latex/base/ltfssdcl.dtx +++ b/Master/texmf-dist/source/latex/base/ltfssdcl.dtx @@ -36,7 +36,7 @@ % % \ProvidesFile{ltfssdcl.dtx} - [2020/01/20 v3.0t LaTeX Kernel (NFSS Declarative Interface)] + [2020/03/19 v3.0v LaTeX Kernel (NFSS Declarative Interface)] % \iffalse \documentclass{ltxdoc} \begin{document} @@ -465,7 +465,7 @@ % \changes{v3.0q}{2015/03/18}{Introduce \cs{e@mathgroup@top}} % \begin{macrocode} %</2ekernel> -%<latexrelease>\IncludeInRelease{2015/01/01} +%<latexrelease>\IncludeInRelease{2020/10/01} %<latexrelease> {\document@select@group}{\document@select@group}% %<*2ekernel|latexrelease> \def\document@select@group#1#2#3#4{% @@ -491,13 +491,54 @@ \@eha \fi \else \expandafter\non@alpherr\fi - #1{#4}% +% \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 +% surround \verb=#4= with braces, because then we get +% \verb={\relax}= into the formula and introduce an extra Ord +% atom. The two different cases can be distinguished by looking at +% the current value of \cs{math@bgroup}. +% \changes{v3.0u}{2020/03/19}{fix for (gnats/3357)} +% \begin{macrocode} + \expandafter#1\ifx\math@bgroup\bgroup{#4}\else#4\fi }% } %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2015/01/01} +%<latexrelease> {\document@select@group}{\document@select@group}% +%<latexrelease> +%<latexrelease>\def\document@select@group#1#2#3#4{% +%<latexrelease> \ifx\math@bgroup\bgroup\else\relax\expandafter\@firstofone\fi +%<latexrelease> {% +%<latexrelease> \ifmmode +%<latexrelease> \ifnum\csname c@mv@\math@version\endcsname<\e@mathgroup@top +%<latexrelease> \begingroup +%<latexrelease> \escapechar\m@ne +%<latexrelease> \getanddefine@fonts{\csname c@mv@\math@version\endcsname}#3% +%<latexrelease> \globaldefs\@ne \math@fonts +%<latexrelease> \endgroup +%<latexrelease> \expandafter\extract@alph@from@version +%<latexrelease> \csname mv@\math@version\expandafter\endcsname +%<latexrelease> \expandafter{\number\csname +%<latexrelease> c@mv@\math@version\endcsname}% +%<latexrelease> #1% +%<latexrelease> \global\advance\csname c@mv@\math@version\endcsname\@ne +%<latexrelease> \else +%<latexrelease> \let#1\relax +%<latexrelease> \@latex@error{Too many math alphabets used +%<latexrelease> in version \math@version}% +%<latexrelease> \@eha +%<latexrelease> \fi +%<latexrelease> \else \expandafter\non@alpherr\fi +%<latexrelease> #1{#4}% +%<latexrelease> }% +%<latexrelease>} +%<latexrelease>\EndIncludeInRelease +%<latexrelease> %<latexrelease>\IncludeInRelease{0000/00/00} %<latexrelease> {\document@select@group}{\document@select@group}% +%<latexrelease> %<latexrelease>\def\document@select@group#1#2#3#4{% %<latexrelease> \ifx\math@bgroup\bgroup\else\relax\expandafter\@firstofone\fi %<latexrelease> {% @@ -582,17 +623,19 @@ % \begin{macrocode} \let\select@group\document@select@group % \end{macrocode} -% Install the default font attributes they are currently pointing -% to error font shape. +% Install the default font attributes as they are currently pointing +% to error font face. We can speed up the process by just using +% \cs{edef}, thereby avoiding all kind of extra processing. % Don't use |\reset@font| since that would trigger |\selectfont|. +% \changes{v3.0v}{2020/04/13}{Small update for speed.} % \begin{macrocode} - \fontencoding{\encodingdefault}% - \fontfamily{\familydefault}% - \fontseries{\seriesdefault}% - \fontshape{\shapedefault}% + \fontencoding\encodingdefault + \edef\f@family{\familydefault}% + \edef\f@series{\seriesdefault}% + \edef\f@shape{\shapedefault}% % \end{macrocode} -% kill all macros not longer needed. -% we need to add many more!!!!!! +% Drop stuff not longer needed. +% We need to add many more!!!!!! % \begin{macrocode} \everyjob{}% } diff --git a/Master/texmf-dist/source/latex/base/ltfssini.dtx b/Master/texmf-dist/source/latex/base/ltfssini.dtx index 98f465ae9b9..10f3dc5863b 100644 --- a/Master/texmf-dist/source/latex/base/ltfssini.dtx +++ b/Master/texmf-dist/source/latex/base/ltfssini.dtx @@ -36,7 +36,7 @@ % % \ProvidesFile{ltfssini.dtx} - [2020/02/18 v3.1i LaTeX Kernel (NFSS Initialisation)] + [2020/09/30 v3.2d LaTeX Kernel (NFSS Initialisation)] % \iffalse \documentclass{ltxdoc} \begin{document} @@ -244,7 +244,7 @@ % \DescribeMacro\DeclareFontSeriesDefault % We now support this concept directly from within \LaTeX{} and for % use in font packages (or the document preamble) we offer -% \cs{DeclareSeriesDefault}. This declaration takes three +% \cs{DeclareFontSeriesDefault}. This declaration takes three % arguments: % \begin{description} % \item[document family interface:] Can either be \texttt{rm}, @@ -278,6 +278,7 @@ % The command to declare font series defaults for the ``rm'', ``sf'' or % ``tt'' family. % \begin{macrocode} +\let\DeclareFontSeriesDefault\@undefined % for rollback \newcommand\DeclareFontSeriesDefault[3][]{% \def\reserved@a{#1}% % \end{macrocode} @@ -287,11 +288,19 @@ \ifx\reserved@a\@empty \ifcsname #2series\endcsname % supported are % \[md/bf]default +% \end{macrocode} +% Adding \cs{@empty} allows us to detect if the default gets +% redefined with \cs{renewcommand} or \cs{def} by the user. +% \changes{v3.1k}{2020/03/19}{Support legacy use of \cs{bfdefault} +% and \cs{mddefault} (gh/306)} +% \begin{macrocode} + \expandafter\def + \csname #2default\endcsname{#3\@empty}% \expandafter\def - \csname #2default\endcsname{#3}% + \csname #2default@previous\endcsname{#3\@empty}% \else % \end{macrocode} -% +% % \changes{v3.1g}{2020/02/05}{Clarrified error text} % \begin{macrocode} \@latex@error{Wrong syntax for \string\DeclareFontSeriesDefault}% @@ -379,243 +388,6 @@ -% \begin{macro}{\expand@font@defaults} -% -% The family specific defaults are fully expanded, i.e., they are -% defined via \cs{edef} inside \cs{DeclareFontSeriesDefault}. -% However, the overall defaults, e.g., \cs{bfdefault} may have been -% redefined by the user and thus may not be fully expanded. So to -% enable reliable comparison we make expanded versions of -% them. That we rerun each time. The alternative would be to only -% allow for changes before begin document. -% \begin{macrocode} -\def\expand@font@defaults{% - \edef\rmdef@ult{\rmdefault}% - \edef\sfdef@ult{\sfdefault}% - \edef\ttdef@ult{\ttdefault}% - \edef\bfdef@ult{\bfdefault}% - \edef\mddef@ult{\mddefault}% - \edef\famdef@ult{\familydefault}% -} -% \end{macrocode} -% -% \end{macro} - - - -% \begin{macro}{\bfseries} -% This document command switches to the bold series. -% \begin{macrocode} -\DeclareRobustCommand\bfseries{% - \not@math@alphabet\bfseries\mathbf -% \end{macrocode} -% In the original NFSS definition it then called \cs{fontseries} -% with the value \cs{bfdefault}. In the new scheme we have more -% alternatives and therefore check if the current family -% (\cs{f@family}) is the current \cs{rmdef@ult}, \cs{sfdef@ult} or -% \cs{ttdef@ult} and the select the correct family default in that case. -% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside -% of \cs{fontseries} argument so that it is not done several times} -% \begin{macrocode} - \expand@font@defaults - \ifx\f@family\rmdef@ult \fontseries\bfseries@rm - \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf - \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt -% \end{macrocode} -% If not \cs{bfdefault} is used. -% \begin{macrocode} - \else \fontseries\bfdefault - \fi\fi\fi - \selectfont -} -% \end{macrocode} -% \end{macro} - - - -% \begin{macro}{\mdseries} -% This document command switches to the medium series. -% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside -% of \cs{fontseries} argument so that it is not done several times} -% \begin{macrocode} -\DeclareRobustCommand\mdseries{% - \not@math@alphabet\mdseries\relax - \expand@font@defaults - \ifx\f@family\rmdef@ult \fontseries\mdseries@rm - \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf - \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt - \else \fontseries\mddefault - \fi\fi\fi - \selectfont -} -% \end{macrocode} -% \end{macro} - - -% \begin{macro}{\rmfamily} -% Here are the document level commands for changing the main font -% families, or rather, here is a documented outline of the code, -% the actual code is then streamlined and somewhat generalized. -%\begin{verbatim} -%\DeclareRobustCommand\rmfamily{% -% \not@math@alphabet\rmfamily\mathrm -%\end{verbatim} -% If families are changed then we have to do a bit more work. -% In the original NFSS implementation -% a family change kept encoding, series shape and size unchanged -% but now we can't any -% longer simply reuse the current series value. Instead we may have -% to change it from one family default to the next. -%\begin{verbatim} -% \expand@font@defaults -%\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 -% hold the target series (if any). -%\begin{verbatim} -% \let\target@series@value\@empty -%\end{verbatim} -% Thus, if the current family is the sans family -%\begin{verbatim} -% \ifx\f@family\sfdef@ult -%\end{verbatim} -% and if we using the medium series of the sans family -%\begin{verbatim} -% \ifx\f@series\mdseries@sf -%\end{verbatim} -% then lets switch to the medium series for the serif family -%\begin{verbatim} -% \let\target@series@value\mdseries@rm -%\end{verbatim} -% and if we use the bold series of the sans family switch to the -% bold default of the serif family: -%\begin{verbatim} -% \else\ifx\f@series\bfseries@sf \let\target@series@value\bfseries@rm -%\end{verbatim} -% However, the sans family may not have any specific defaults set, -% so we also compare with the overall defaults. -%\begin{verbatim} -% \else\ifx\f@series\mddef@ult \let\target@series@value\mdseries@rm -% \else\ifx\f@series\bfdef@ult \let\target@series@value\bfseries@rm -%\end{verbatim} -% If neither test was true we leave the series alone. This way a -% special manual setting such as \verb=\fontseries{lc}= is not -% undone if the family changes (of course there may not be any -% support for it in the new family but then the NFSS -% substitution kicks in and sorts it out). -%\begin{verbatim} -% \fi\fi\fi\fi -% -%\end{verbatim} -% We need to do the same if the current family is the typewriter family: -%\begin{verbatim} -% \else\ifx\f@family\ttdef@ult -% \ifx\f@series\mdseries@tt \let\target@series@value\mdseries@rm -% \else\ifx\f@series\bfseries@tt \let\target@series@value\bfseries@rm -% \else\ifx\f@series\mddef@ult \let\target@series@value\mdseries@rm -% \else\ifx\f@series\bfdef@ult \let\target@series@value\bfseries@rm -% \fi\fi\fi\fi -% \fi\fi -%\end{verbatim} -% With these preparations for series out of the way we can now -% change the font family to \cs{rmdefault}. -%\begin{verbatim} -% \fontfamily\rmdefault -%\end{verbatim} -% -% If \cs{target@series@value} is still empty there is nothing more -% to do other than selecting the new family. However, if not then -% we should update the font series now as well. But there is one -% further subtle issue. We may not have loaded an \texttt{.fd} file -% for our target font family yet. In the past that was done in -% \cs{selectfont} if necessary but since we are now doing all the -% comparisons in \cs{fontseries} we need to make sure that the font -% family specifications are already loaded prior to calling -% \cs{fontseries}. -%\begin{verbatim} -% \ifx\target@series@value\@empty \else -% \maybe@load@fontshape -%\end{verbatim} -% Updating the series in this case means directly changing -% \cs{f@series} to the target value. We don't want to go through -% \cs{fontseries} because that would apply the mappings and then -% \texttt{bx + b} would keep \texttt{bx} instead of changing to -% \texttt{b} as desired. -% as -%\begin{verbatim} -% \let\f@series\target@series@value -% \fi -% \selectfont} -%\end{verbatim} -% -% So now for the real definition: most of the code above gets -% delegated to a helper command \cs{prepare@family@series@update} -% so that the definition becomes again fairly short. In addition we -% add a hook, mainly for our Japanese friends so that the code can -% be extended prior to the call to \cs{selectfont}. -% -% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook} -% \begin{macrocode} -\DeclareRobustCommand\rmfamily{% - \not@math@alphabet\rmfamily\mathrm -% \end{macrocode} -% This holds all the code discussed above, first argument is the -% meta family, i.e., \texttt{rm} in this case, and second argument -% is the default family name, e.g., \texttt{cmr} indirectly -% accessed via \cs{rmdefault}. This is calling \cs{fontfamily} and -% if necessary \cs{fontseries} as outline above. -% \begin{macrocode} - \prepare@family@series@update{rm}\rmdefault -% \end{macrocode} -% Then comes the hook code (by default a no-op) and finally the call -% to \cs{selectfont}. -% \begin{macrocode} - \@rmfamilyhook - \selectfont} -% \end{macrocode} -% -% \begin{macro}{\sffamily} -% \begin{macro}{\ttfamily} -% The definitions for \cs{sffamily} and \cs{ttfamily} are similar, -% the differences are only in what font families get checked. -% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook} -% \begin{macrocode} -\DeclareRobustCommand\sffamily{% - \not@math@alphabet\sffamily\mathsf - \prepare@family@series@update{sf}\sfdefault - \@sffamilyhook - \selectfont} -% \end{macrocode} -% -% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook} -% \begin{macrocode} -\DeclareRobustCommand\ttfamily{% - \not@math@alphabet\ttfamily\mathtt - \prepare@family@series@update{tt}\ttdefault - \@ttfamilyhook - \selectfont} -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% -% \begin{macro}{\@rmfamilyhook} -% \begin{macro}{\@sffamilyhook} -% \begin{macro}{\@ttfamilyhook} -% By default the hooks do nothing. -% \begin{macrocode} -\let\@rmfamilyhook\@empty -\let\@sffamilyhook\@empty -\let\@ttfamilyhook\@empty -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% % % % @@ -675,7 +447,7 @@ % \begin{itemize} % \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 the meta +% \item Switch to a font family that is none of the meta % families, e.g., via \verb=\fontfamily{ptm}\selectfont= % \item Then none of the real meta families, match but the final % \verb=\@elt{??}= will. @@ -718,7 +490,16 @@ \maybe@load@fontshape %<+debug> \series@change@debug{Target series: %<+debug> \f@series \space -> \target@series@value}% - \let\f@series\target@series@value +% \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} +% first. +% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from +% \cs{target@series@value} (gh/291)} +% \begin{macrocode} +% \let\f@series\target@series@value + \series@maybe@drop@one@m\target@series@value\f@series \fi \fi \fi @@ -776,10 +557,30 @@ % \cs{rmfamily}. This is now covered by looping and stopping the % loop when a match was found. % \begin{macrocode} - \expandafter\ifx\csname mdseries@#1\endcsname\f@series +% \end{macrocode} +% We have to sanitize the default value first because it may +% contain something like \texttt{mc} and that would never match +% \cs{f@series} because there it would be called \texttt{c} with +% the \texttt{m} dropped. It would be probably better to do that +% differently these days, but it is hard to adjust without causing +% a lot of issues, so we do the dropping in various places instead. +% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from \cs{reserved@d} +% (gh/291)} +% \begin{macrocode} + \expandafter\series@maybe@drop@one@m + \csname mdseries@#1\endcsname\reserved@d + \ifx\reserved@d\f@series %<+debug> \series@change@debug{mdseries@#1 matched -> \reserved@b}% \let\target@series@value\reserved@b - \else\expandafter\ifx\csname bfseries@#1\endcsname\f@series + \else +% \end{macrocode} +% Again do some sanitizing. +% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from \cs{reserved@d} +% (gh/291)} +% \begin{macrocode} + \expandafter\series@maybe@drop@one@m + \csname bfseries@#1\endcsname\reserved@d + \ifx\reserved@d\f@series %<+debug> \series@change@debug{bfseries@#1 matched -> \reserved@c}% \let\target@series@value\reserved@c \else\ifx\f@series\mddef@ult \let\target@series@value\reserved@b @@ -823,37 +624,59 @@ % \cs{DeclareFontSeriesDefault} interface. % \begin{macrocode} \ifx\bfseries@rm@kernel\bfseries@rm - \expandafter\in@\expandafter{\rmdefault}{cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}% + \expandafter\in@\expandafter{\rmdefault}% + {cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}% \ifin@ \else \def\bfseries@rm{b}\fi\fi % \end{macrocode} % Same approach for \cs{bfseries@sf} and \cs{bfseries@tt}: % \begin{macrocode} \ifx\bfseries@sf@kernel\bfseries@sf - \expandafter\in@\expandafter{\sfdefault}{cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}% + \expandafter\in@\expandafter{\sfdefault}% + {cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}% \ifin@ \else \def\bfseries@sf{b}\fi\fi \ifx\bfseries@tt@kernel\bfseries@tt - \expandafter\in@\expandafter{\ttdefault}{cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}% + \expandafter\in@\expandafter{\ttdefault}% + {cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}% \ifin@ \else \def\bfseries@tt{b}\fi\fi % \end{macrocode} % % If the document preamble has changed the \cs{familydefault} or if -% the if the \cs{rmdefault} contains a new font family, we have to +% the if the \cs{rmdefault} contains a new font family, we may have to % adjust the series defaults accordingly, before starting % typesetting. -% -% On the other hand if we still typeset in CM or LM then -% \cs{bfdefault} is wrong since it is now saying \texttt{b} and not -% \texttt{bx}. - -% To fix this we run \cs{rmfamily}, \cs{sffamily} or -% \cs{ttfamily} depending on the situation and this will correct -% the setup for us. -% \begin{macrocode} - \expand@font@defaults - \ifx\famdef@ult\rmdef@ult \rmfamily - \else\ifx\famdef@ult\sfdef@ult \sffamily - \else\ifx\famdef@ult\ttdef@ult \ttfamily - \fi\fi\fi +% +% Similarly, if the user has changed the \cs{mddefault} or the +% medium series for the family selected as document font we may +% also have to adjust the \cs{seriesdefault}. +% +% On the other hand if the document font is still CM or LM then +% \cs{bfdefault} is wrong, because it is now saying \texttt{b} and not +% \texttt{bx} as it should for such fonts. +% +% To fix all this we first run \cs{reset@font} (the internal kernel +% name for \cs{normalfont}). This will set up the document encoding, +% family, series and shape based on the current values of +% \cs{encodingdefault}, \cs{familydefault}, \cs{seriesdefault} and +% \cs{shapedefault}. +% However, if the family (from \cs{familydefault}) has special medium +% default we should switch to that (and not use what is current +% value from \cs{seriesdefault}). This can be achieved by afterwards +% calling \cs{mediumseries} and then changing \cs{seriesdefault} to +% 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 +% 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 +% \cs{mdseries} or change \cs{seriesdefault}. +% \changes{v3.1n}{2020/04/13}{Handling \cs{seriesdefault} changes (gh/315)} +% \begin{macrocode} + \reset@font + \ifx\seriesdefault\seriesdefault@kernel + \mdseries + \let\seriesdefault\f@series + \fi }% % \end{macrocode} % \end{macro} @@ -893,9 +716,435 @@ %<latexrelease>\let\mdseries@rm\@undefined %<latexrelease>\let\mdseries@sf\@undefined %<latexrelease>\let\mdseries@tt\@undefined -%<latexrelease>\let\expand@font@defaults\@undefined %<latexrelease>\expandafter\let\csname ver@mweights.sty\endcsname\@undefined %<latexrelease> +%<latexrelease>\let\@meta@family@list\@undefined +%<latexrelease>\let\prepare@family@series@update\@undefined +%<latexrelease>\let\update@series@target@value\@undefined +%<latexrelease> +% \end{macrocode} +% This is always called in \cs{document} so don't make it undefined. +% \begin{macrocode} +%<latexrelease>\let\init@series@setup\relax +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\bfseries}{Custom series with hooks}% +% \end{macrocode} + + +% \begin{macro}{\expand@font@defaults} +% \begin{macro}{\rm@def@ult} +% \begin{macro}{\sf@def@ult} +% \begin{macro}{\tt@def@ult} +% \begin{macro}{\md@def@ult} +% \begin{macro}{\bf@def@ult} +% +% The family specific defaults are fully expanded, i.e., they are +% defined via \cs{edef} inside \cs{DeclareFontSeriesDefault}. +% However, the overall defaults, e.g., \cs{bfdefault} may have been +% redefined by the user and thus may not be fully expanded. So to +% enable reliable comparison we make expanded versions of +% them. That we rerun each time. The alternative would be to only +% allow for changes before begin document. +% \begin{macrocode} +\def\expand@font@defaults{% + \edef\rmdef@ult{\rmdefault}% + \edef\sfdef@ult{\sfdefault}% + \edef\ttdef@ult{\ttdefault}% +% \end{macrocode} +% The series defaults may contain some surplus \texttt{m} that we +% need to drop here. +% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from \cs{bfdef@ult} +% and \cs{mddef@ult} (gh/291)} +% \begin{macrocode} + \series@maybe@drop@one@m\bfdefault\bfdef@ult + \series@maybe@drop@one@m\mddefault\mddef@ult +% \end{macrocode} +% Formats that set up parallel fonts, e.g., for Japanese, can use +% this hook to add additional code here. +% \changes{v3.1m}{2020/04/06}{Hook added (gh/306)} +% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface} +% \begin{macrocode} + \UseHook{expand@font@defaults}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} + + +% \begin{macro}{\bfseries} +% This document command switches to the bold series. +% \begin{macrocode} +\DeclareRobustCommand\bfseries{% + \not@math@alphabet\bfseries\mathbf +% \end{macrocode} +% In the original NFSS definition it then called \cs{fontseries} +% with the value \cs{bfdefault}. In the new scheme we have more +% alternatives and therefore check if the current family +% (\cs{f@family}) is the current \cs{rmdef@ult}, \cs{sfdef@ult} or +% \cs{ttdef@ult} and the select the correct family default in that case. +% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside +% of \cs{fontseries} argument so that it is not done several times} +% \begin{macrocode} + \expand@font@defaults +% \end{macrocode} +% If \cs{bfdefault} and \cs{bfdefault@previous} are different then +% the default got changed directly through the legacy interface +% (i.e., via \cs{def} or \cs{renewcommand}. In that case we reset +% all meta family defaults so that the document behaves like it was +% the case before the new mechanism was introduced. +% \changes{v3.1k}{2020/03/19}{Support legacy use of \cs{bfdefault} +% and \cs{mddefault} (gh/306)} +% \begin{macrocode} + \ifx\bfdefault\bfdefault@previous\else +% \end{macrocode} +% We add \cs{@empty} and then let \cs{bfdefault@previous} to +% \cs{bfdefault} so that we can detect any further change. +% \changes{v3.2d}{2020/09/30}{\cs{bfdefault@previous} not \cs{bfseries@previous} +% (gh/395)} +% \begin{macrocode} + \expandafter\def\expandafter\bfdefault + \expandafter{\bfdefault\@empty}% + \let\bfdefault@previous\bfdefault +% \end{macrocode} +% And we reset the meta family defaults (\cs{bfdef@ult} is an +% expanded version of \cs{bfdefault}. +% \begin{macrocode} + \let\bfseries@rm\bfdef@ult + \let\bfseries@sf\bfdef@ult + \let\bfseries@tt\bfdef@ult +% \end{macrocode} +% +% Formats that set up parallel fonts, e.g., for Japanese, can use +% this hook to add resets here. Not that this hook is only run when +% resets are necessary. +% \changes{v3.1m}{2020/04/06}{Hook added (gh/306)} +% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface} +% \begin{macrocode} + \UseHook{bfseries/defaults}% + \fi +% \end{macrocode} +% +% \begin{macrocode} + \ifx\f@family\rmdef@ult \fontseries\bfseries@rm + \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf + \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt +% \end{macrocode} +% If not \cs{bfdefault} is used. +% \begin{macrocode} + \else \fontseries\bfdefault + \fi\fi\fi +% \end{macrocode} +% This hook in contrast is always executed. +% \begin{macrocode} + \UseHook{bfseries}% + \selectfont +} +% \end{macrocode} +% \end{macro} + + + +% \begin{macro}{\mdseries} +% This document command switches to the medium series. +% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside +% of \cs{fontseries} argument so that it is not done several times} +% \changes{v3.1k}{2020/03/19}{Support legacy use of \cs{bfdefault} +% and \cs{mddefault} (gh/306)} +% \changes{v3.2d}{2020/09/30}{\cs{mddefault@previous} not \cs{mdseries@previous} +% (gh/395)} +% \begin{macrocode} +\DeclareRobustCommand\mdseries{% + \not@math@alphabet\mdseries\relax + \expand@font@defaults + \ifx\mddefault\mddefault@previous\else + \expandafter\def\expandafter\mddefault\expandafter{\mddefault\@empty}% + \let\mddefault@previous\mddefault + \let\mdseries@rm\mddef@ult + \let\mdseries@sf\mddef@ult + \let\mdseries@tt\mddef@ult +% \end{macrocode} +% +% Formats that set up parallel fonts, e.g., for Japanese, can use +% this hook to add resets here. +% \changes{v3.1m}{2020/04/06}{Hook added (gh/306)} +% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface} +% \begin{macrocode} + \UseHook{mdseries/defaults}% + \fi + \ifx\f@family\rmdef@ult \fontseries\mdseries@rm + \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf + \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt + \else \fontseries\mddefault + \fi\fi\fi + \UseHook{mdseries}% + \selectfont +} +% \end{macrocode} +% \end{macro} + + +% \begin{macro}{\rmfamily} +% Here are the document level commands for changing the main font +% families, or rather, here is a documented outline of the code, +% the actual code is then streamlined and somewhat generalized. +%\begin{verbatim} +%\DeclareRobustCommand\rmfamily{% +% \not@math@alphabet\rmfamily\mathrm +%\end{verbatim} +% If families are changed then we have to do a bit more work. +% In the original NFSS implementation +% a family change kept encoding, series shape and size unchanged +% but now we can't any +% longer simply reuse the current series value. Instead we may have +% to change it from one family default to the next. +%\begin{verbatim} +% \expand@font@defaults +%\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 +% hold the target series (if any). +%\begin{verbatim} +% \let\target@series@value\@empty +%\end{verbatim} +% Thus, if the current family is the sans family +%\begin{verbatim} +% \ifx\f@family\sfdef@ult +%\end{verbatim} +% and if we using the medium series of the sans family +%\begin{verbatim} +% \ifx\f@series\mdseries@sf +%\end{verbatim} +% then lets switch to the medium series for the serif family +%\begin{verbatim} +% \let\target@series@value\mdseries@rm +%\end{verbatim} +% and if we use the bold series of the sans family switch to the +% bold default of the serif family: +%\begin{verbatim} +% \else\ifx\f@series\bfseries@sf \let\target@series@value\bfseries@rm +%\end{verbatim} +% However, the sans family may not have any specific defaults set, +% so we also compare with the overall defaults. +%\begin{verbatim} +% \else\ifx\f@series\mddef@ult \let\target@series@value\mdseries@rm +% \else\ifx\f@series\bfdef@ult \let\target@series@value\bfseries@rm +%\end{verbatim} +% If neither test was true we leave the series alone. This way a +% special manual setting such as \verb=\fontseries{lc}= is not +% undone if the family changes (of course there may not be any +% support for it in the new family but then the NFSS +% substitution kicks in and sorts it out). +%\begin{verbatim} +% \fi\fi\fi\fi +% +%\end{verbatim} +% We need to do the same if the current family is the typewriter family: +%\begin{verbatim} +% \else\ifx\f@family\ttdef@ult +% \ifx\f@series\mdseries@tt \let\target@series@value\mdseries@rm +% \else\ifx\f@series\bfseries@tt \let\target@series@value\bfseries@rm +% \else\ifx\f@series\mddef@ult \let\target@series@value\mdseries@rm +% \else\ifx\f@series\bfdef@ult \let\target@series@value\bfseries@rm +% \fi\fi\fi\fi +% \fi\fi +%\end{verbatim} +% With these preparations for series out of the way we can now +% change the font family to \cs{rmdefault}. +%\begin{verbatim} +% \fontfamily\rmdefault +%\end{verbatim} +% +% If \cs{target@series@value} is still empty there is nothing more +% to do other than selecting the new family. However, if not then +% we should update the font series now as well. But there is one +% further subtle issue. We may not have loaded an \texttt{.fd} file +% for our target font family yet. In the past that was done in +% \cs{selectfont} if necessary but since we are now doing all the +% comparisons in \cs{fontseries} we need to make sure that the font +% family specifications are already loaded prior to calling +% \cs{fontseries}. +%\begin{verbatim} +% \ifx\target@series@value\@empty \else +% \maybe@load@fontshape +%\end{verbatim} +% Updating the series in this case means directly changing +% \cs{f@series} to the target value. We don't want to go through +% \cs{fontseries} because that would apply the mappings and then +% \texttt{bx + b} would keep \texttt{bx} instead of changing to +% \texttt{b} as desired. +% as +%\begin{verbatim} +% \let\f@series\target@series@value +% \fi +% \selectfont} +%\end{verbatim} +% +% So now for the real definition: most of the code above gets +% delegated to a helper command \cs{prepare@family@series@update} +% so that the definition becomes again fairly short. In addition we +% add a hook, mainly for our Japanese friends so that the code can +% be extended prior to the call to \cs{selectfont}. +% +% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook} +% \begin{macrocode} +\DeclareRobustCommand\rmfamily{% + \not@math@alphabet\rmfamily\mathrm +% \end{macrocode} +% This holds all the code discussed above, first argument is the +% meta family, i.e., \texttt{rm} in this case, and second argument +% is the default family name, e.g., \texttt{cmr} indirectly +% accessed via \cs{rmdefault}. This is calling \cs{fontfamily} and +% if necessary \cs{fontseries} as outline above. +% \begin{macrocode} + \prepare@family@series@update{rm}\rmdefault +% \end{macrocode} +% Then comes the hook code (by default a no-op) and finally the call +% to \cs{selectfont}. +% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface} +% \begin{macrocode} + \UseHook{rmfamily}% + \selectfont} +% \end{macrocode} +% +% \begin{macro}{\sffamily} +% \begin{macro}{\ttfamily} +% The definitions for \cs{sffamily} and \cs{ttfamily} are similar, +% the differences are only in what font families get checked. +% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook} +% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface} +% \begin{macrocode} +\DeclareRobustCommand\sffamily{% + \not@math@alphabet\sffamily\mathsf + \prepare@family@series@update{sf}\sfdefault + \UseHook{sffamily}% + \selectfont} +% \end{macrocode} +% +% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook} +% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface} +% \begin{macrocode} +\DeclareRobustCommand\ttfamily{% + \not@math@alphabet\ttfamily\mathtt + \prepare@family@series@update{tt}\ttdefault + \UseHook{ttfamily}% + \selectfont} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{rmfamily,sffamily,ttfamily,normalfont,expand@font@defaults, +% bfseries,bfseries/defaults,mdseries,mdseries/defaults} +% Declare the hooks used above. +% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface} +% \begin{macrocode} +\NewHook{rmfamily} +\NewHook{sffamily} +\NewHook{ttfamily} +\NewHook{normalfont} +\NewHook{expand@font@defaults} +\NewHook{bfseries} +\NewHook{bfseries/defaults} +\NewHook{mdseries} +\NewHook{mdseries/defaults} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@rmfamilyhook} +% \begin{macro}{\@sffamilyhook} +% \begin{macro}{\@ttfamilyhook} +% These four hooks have legacy versions used in 2020/02/02 so we +% should support them until they aren't any longer used. +% \begin{macrocode} +\let\@rmfamilyhook\@empty +\let\@sffamilyhook\@empty +\let\@ttfamilyhook\@empty +\let\@defaulfamilyhook\@empty +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/02/02}% +%<latexrelease> {\bfseries}{Custom series with hooks}% +%<latexrelease> +%<latexrelease>\def\expand@font@defaults{% +%<latexrelease> \edef\rmdef@ult{\rmdefault}% +%<latexrelease> \edef\sfdef@ult{\sfdefault}% +%<latexrelease> \edef\ttdef@ult{\ttdefault}% +%<latexrelease> \edef\bfdef@ult{\bfdefault}% +%<latexrelease> \edef\mddef@ult{\mddefault}% +%<latexrelease> \edef\famdef@ult{\familydefault}% +%<latexrelease>} +%<latexrelease> +%<latexrelease>\DeclareRobustCommand\bfseries{% +%<latexrelease> \not@math@alphabet\bfseries\mathbf +%<latexrelease> \expand@font@defaults +%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\bfseries@rm +%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf +%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt +%<latexrelease> \else \fontseries\bfdefault +%<latexrelease> \fi\fi\fi +%<latexrelease> \selectfont +%<latexrelease>} +%<latexrelease> +%<latexrelease>\DeclareRobustCommand\mdseries{% +%<latexrelease> \not@math@alphabet\mdseries\relax +%<latexrelease> \expand@font@defaults +%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\mdseries@rm +%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf +%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt +%<latexrelease> \else \fontseries\mddefault +%<latexrelease> \fi\fi\fi +%<latexrelease> \selectfont +%<latexrelease>} +%<latexrelease> +%<latexrelease>\DeclareRobustCommand\rmfamily{% +%<latexrelease> \not@math@alphabet\rmfamily\mathrm +%<latexrelease> \prepare@family@series@update{rm}\rmdefault +%<latexrelease> \@rmfamilyhook +%<latexrelease> \selectfont} +%<latexrelease>\DeclareRobustCommand\sffamily{% +%<latexrelease> \not@math@alphabet\sffamily\mathsf +%<latexrelease> \prepare@family@series@update{sf}\sfdefault +%<latexrelease> \@sffamilyhook +%<latexrelease> \selectfont} +%<latexrelease>\DeclareRobustCommand\ttfamily{% +%<latexrelease> \not@math@alphabet\ttfamily\mathtt +%<latexrelease> \prepare@family@series@update{tt}\ttdefault +%<latexrelease> \@ttfamilyhook +%<latexrelease> \selectfont} +%<latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\bfseries}{Custom series with hooks}% +%<latexrelease> +%<latexrelease>\let\expand@font@defaults\@undefined +%<latexrelease> %<latexrelease>\DeclareRobustCommand\bfseries %<latexrelease> {\not@math@alphabet\bfseries\mathbf %<latexrelease> \fontseries\bfdefault\selectfont} @@ -915,21 +1164,173 @@ %<latexrelease>\let\@rmfamilyhook\@undefined %<latexrelease>\let\@sffamilyhook\@undefined %<latexrelease>\let\@ttfamilyhook\@undefined -%<latexrelease>\let\@meta@family@list\@undefined -%<latexrelease>\let\prepare@family@series@update\@undefined -%<latexrelease>\let\update@series@target@value\@undefined %<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} -% This is always called in \cs{document} so don't make it undefined. +% +% +% +% \begin{macro}{\IfFontSeriesContextTF} +% +% With the ability for \cs{bfseries} or \cs{mdseries} to be mapped +% 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?'' +% +% This is provided by the test \cs{IfFontSeriesContextTF}. It takes +% three arguments: +% \begin{itemize} +% \item +% The context we try to check (either \texttt{bf} for bold or +% \texttt{md} for medium, i.e., the same that can go into the +% first mandatory argument of \cs{DeclareFontSeriesDefault}), +% +% \item +% what to do if we are in this context (true case) and +% +% \item +% what to do if we are not (false case). +% \end{itemize} +% This allows you to define commands like \cs{IfBold}, e.g., +%\begin{verbatim} +% \newcommand\IfBold[2]{\IfSeriesContextTF{bf}{#1}{#2}} +%\end{verbatim} +% and then do +%\begin{verbatim} +% This is \IfBold{bold}{non-bold} text. +%\end{verbatim} +% and get the appropriate result. +% +% \changes{v3.2a}{2020/05/19}{Macros added (gh/335)} % \begin{macrocode} -%<latexrelease>\let\init@series@setup\relax +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\IfFontSeriesContextTF}{Font series context}% +% \end{macrocode} +% +% \begin{macrocode} +\DeclareRobustCommand\IfFontSeriesContextTF[1]{% + \expand@font@defaults +% \end{macrocode} +% In the beginning we haven't found the context we are loking for. +% \begin{macrocode} + \@font@series@contextfalse +% \end{macrocode} +% We store the requested context away for use in the tests. +% \begin{macrocode} + \def\requested@test@context{#1}% +% \end{macrocode} +% The next definition is there to ensure that get a final match +% during testing +% even if the current family is non of the meta families +% (\texttt{rm}, \texttt{sf} or \texttt{tt}). This will then +% basically tests if the current font family matches the overall default. +% \begin{macrocode} + \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 +% \texttt{??} and test each of them in turn using +% \cs{test@font@series@context} as the testing command. +% \begin{macrocode} + \let\@elt\test@font@series@context + \@meta@family@list + \@elt{??}% + \let\@elt\relax +% \end{macrocode} +% Following that we evaluate the status of +% \cs{if@font@series@context} to determine which of the remaining +% arguments (true/false case) we have to execute. +% \begin{macrocode} + \if@font@series@context + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi +} +% \end{macrocode} +% \end{macro} + + + +% \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. +% \begin{macrocode} +\def\test@font@series@context#1{% +% \end{macrocode} +% First task is to figure out whether the current family matches +% \cs{rmfamily}, \cs{sffamily}, etc.\ so in \cs{reserved@a} we +% store the value of \cs{rmdef@ult} (or whatever the given meta +% family is) and compare that to \cs{f@family}. +% \begin{macrocode} + \edef\reserved@a{\csname #1def@ult\endcsname}% + \ifx\f@family\reserved@a +% \end{macrocode} +% If they match we have found the right meta family so we don't +% need to test any of the remaining meta family and therefore +% change \cs{@elt} to \cs{@gobble}. +% \begin{macrocode} + \let\@elt\@gobble +% \end{macrocode} +% Now we have to test if \cs{f@series} matches the requested +% context (e.g., whether \cs{bfseries@rm} has that value if the +% current meta family is \texttt{rm} and we are looking for the +% \texttt{bf} context). +% \begin{macrocode} + \expandafter\ifx + \csname\requested@test@context series@#1\endcsname\f@series +% \end{macrocode} +% If yes we change the boolean and are done. +% \begin{macrocode} + \@font@series@contexttrue +% \end{macrocode} +% If not then maybe the reason is that nothing special was set up +% for that meta family so we also check now check if \cs{f@series} +% matches the overall default (e.g., \cs{bfdef@ult} if we are +% looking for the bold context). If that matches we change the boolean. +% \begin{macrocode} + \else + \expandafter\ifx + \csname\requested@test@context def@ult\endcsname\f@series + \@font@series@contexttrue + \fi\fi\fi +} +% \end{macrocode} +% \end{macro} + + +% \begin{macro}{\if@font@series@context} +% The boolean to signal if we found the requested font series context. +% \begin{macrocode} +\newif\if@font@series@context +% \end{macrocode} +% \end{macro} +% +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\IfFontSeriesContextTF}{Font series context}% %<latexrelease> +%<latexrelease>\let\IfFontSeriesContextTF\@undefined +%<latexrelease>\let\test@font@series@context\@undefined +%<latexrelease>\let\if@font@series@context\@undefined +%<latexrelease>\let\@font@series@contexttrue\@undefined +%<latexrelease>\let\@font@series@contextfalse\@undefined %<latexrelease>\EndIncludeInRelease %<*2ekernel> % \end{macrocode} -% -% + + % % \section{Supporting nested emphasis} % @@ -1201,26 +1602,50 @@ \def\math@version{normal} % \end{macrocode} % -% \subsection{Miscellaneous} +% \subsection{Legacy} % -% \begin{macro}{\newfont} -% \changes{v1.2g}{1991/03/30}{Definition added.} -% \changes{v2.2e}{1995/05/23}{Font assignment made local again.} -% \begin{macro}{\symbol} -% \changes{v1.2g}{1991/03/30}{Definition added.} % We start by defining a few macros that are part of % standard \LaTeX's user interface. The use of these functions is % not encouraged, but they will allow to process older documents % without changes to the source. +% +% \begin{macro}{\newfont} +% \changes{v1.2g}{1991/03/30}{Definition added.} +% \changes{v2.2e}{1995/05/23}{Font assignment made local again.} % \begin{macrocode} \def\newfont#1#2{\@ifdefinable#1{\font#1=#2\relax}} % \end{macrocode} +% \end{macro} % +% \begin{macro}{\symbol} +% \changes{v1.2g}{1991/03/30}{Definition added.} +% \changes{v3.1h}{2020/02/07}{XeTeX-specific version to avoid bug in maths mode.} % \begin{macrocode} -\DeclareRobustCommand\symbol[1]{\char #1\relax} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\symbol}{XeTeX change for math}% +\ifdefined\XeTeXversion + \DeclareRobustCommand\symbol[1]{\Ucharcat#1 12\relax} +\else + \DeclareRobustCommand\symbol[1]{\char#1\relax} +\fi +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\symbol}{XeTeX change for math}% +%<latexrelease> +%<latexrelease>\DeclareRobustCommand\symbol[1]{\char#1\relax} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} -% \end{macro} +% +% \subsection{Miscellaneous} % % \begin{macro}{\@setfontsize} % \begin{macro}{\@setsize} @@ -1344,8 +1769,14 @@ \edef\f@shape{\shapedefault}% % \end{macrocode} % +% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface} % \begin{macrocode} - \@defaultfamilyhook + \UseHook{normalfont}% +% \end{macrocode} +% This is the old name for the hook introduced in 2020/02/02. +% It will be removed in one of the future releases! +% \begin{macrocode} + \@defaultfamilyhook % hookname from 2020/02 will vanish \selectfont} % \end{macrocode} % @@ -1360,7 +1791,7 @@ % By default the hooks do nothing. % \changes{v3.1h}{2020/02/10}{Add \cs{@defaultfamilyhook} to \cs{normalfont} (gh/269)} % \begin{macrocode} -\let\@defaultfamilyhook\@empty +\let\@defaultfamilyhook\@empty %FMi sort out % \end{macrocode} % \end{macro} % @@ -1505,6 +1936,26 @@ % \end{macrocode} % % +% +% \begin{macro}{\seriesdefault} +% \begin{macro}{\seriesdefault@kernel} +% After \cs{seriesdefault} got defined inside \texttt{fonttext.ltx} +% or a \texttt{.cfg} file overwriting it, we alter its value by +% appending \cs{@empty} to it. This will vanish if expanded but +% allows us to check if the default gets altered (even to the same +% value) in the document preamble. All we have to do is to save the +% current value somewhere and later compare the two. For this we +% use \cs{seriesdefault@kernel}. +% \changes{v3.1n}{2020/04/13}{Handling \cs{seriesdefault} changes (gh/315)} +% \begin{macrocode} +\expandafter\def\expandafter\seriesdefault\expandafter{\seriesdefault\@empty} +\let\seriesdefault@kernel\seriesdefault +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% % \begin{macro}{\@acci} % \begin{macro}{\@accii} % \begin{macro}{\@acciii} diff --git a/Master/texmf-dist/source/latex/base/ltfsstrc.dtx b/Master/texmf-dist/source/latex/base/ltfsstrc.dtx index e997e5be552..055f408ceb3 100644 --- a/Master/texmf-dist/source/latex/base/ltfsstrc.dtx +++ b/Master/texmf-dist/source/latex/base/ltfsstrc.dtx @@ -37,7 +37,7 @@ %<package> [2019/10/11 v3.0l Standard LaTeX package (font tracing)] % \fi % \ProvidesFile{ltfsstrc.dtx} -% [2019/10/11 v3.0l LaTeX Kernel (NFSS tracing)] +% [2020/02/03 v3.0l LaTeX Kernel (NFSS tracing)] % % \iffalse %<+checkmem>\CHECKMEM @@ -1731,7 +1731,7 @@ % the optional argument (if present) is ignored. The font encoding % scheme cannot be changed. Therefore, the first thing we do is to % prepend the encoding scheme. -% {documentation fixes} +% \changes{v2.0b}{1992/07/26}{documentation fixes} % \begin{macrocode} \DeclareSizeFunction{sub}{\sub@sfcnt\@font@warning} \DeclareSizeFunction{ssub}{\sub@sfcnt\@font@info} @@ -1803,7 +1803,7 @@ % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2020/02/01}% +%<latexrelease>\IncludeInRelease{2020/02/02}% %<latexrelease> {\@font@aliasinfo}{alias size function}% \DeclareSizeFunction{alias}{\sub@sfcnt\@font@aliasinfo} \def\@font@aliasinfo#1{% diff --git a/Master/texmf-dist/source/latex/base/lthooks.dtx b/Master/texmf-dist/source/latex/base/lthooks.dtx new file mode 100644 index 00000000000..cb48570a0d8 --- /dev/null +++ b/Master/texmf-dist/source/latex/base/lthooks.dtx @@ -0,0 +1,4012 @@ +% \iffalse meta-comment +%% +%% File: lthooks.dtx (C) Copyright 2020 Frank Mittelbach, +%% Phelype Oleinik & LaTeX Team +% +% 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: lthooks.dtx +% +% \begin{macrocode} +\def\lthooksversion{v1.0b} +\def\lthooksdate{2020/09/21} +% \end{macrocode} +% +%<*driver> +\documentclass{l3doc} + +% bug fix fo l3doc.cls +\ExplSyntaxOn +\cs_set_protected:Npn \__codedoc_macro_typeset_one:nN #1#2 + { + \vbox_set:Nn \l__codedoc_macro_box + { + \vbox_unpack_drop:N \l__codedoc_macro_box + \hbox { \llap { \__codedoc_print_macroname:nN {#1} #2 + \MacroFont % <----- without it the \ is in lmr10 if a link is made + \ + } } + } + \int_incr:N \l__codedoc_macro_int + } +\ExplSyntaxOff + +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{lthooks.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \long\def\fmi#1{\begin{quote}\itshape FMi: #1\end{quote}} +% \long\def\pho#1{\begin{quote}\itshape PhO: #1\end{quote}} +% +% \newcommand\hook[1]{\texttt{#1}} +% +% +% \title{The \texttt{lthooks} package\thanks{This package has version +% \lthooksversion\ dated \lthooksdate, \copyright\ \LaTeX\ +% Project.}} +% +% \author{Frank Mittelbach\thanks{Code improvements for speed and other goodies by Phelype Oleinik}} +% +% \maketitle +% +% +% \tableofcontents +% +% \section{Introduction} +% +% Hooks are points in the code of commands or environments where it +% is possible to add processing code into existing commands. This +% can be done by different packages that do not know about each +% other and to allow for hopefully safe processing it is necessary +% to sort different chunks of code added by different packages into +% a suitable processing order. +% +% This is done by the packages adding chunks of code (via +% \cs{AddToHook}) and labeling their code with some label by +% default using the package name as a label. +% +% At \verb=\begin{document}= all code for a hook is then sorted +% according to some rules (given by \cs{DeclareHookRule}) for fast +% execution without processing overhead. If the hook code is +% modified afterwards (or the rules are changed), +% a new version for fast processing is generated. +% +% Some hooks are used already in the preamble of the document. If +% that happens then the hook is prepared for execution (and sorted) +% already at that point. +% +% +% \section{Package writer interface} +% +% The hook management system is offered as a set of CamelCase +% commands for traditional \LaTeXe{} packages (and for use in the +% document preamble if needed) as well as \texttt{expl3} commands +% for modern packages, that use the L3 programming layer of +% \LaTeX{}. Behind the scenes, a single set of data structures is +% accessed so that packages from both worlds can coexist and access +% hooks in other packages. +% +% +% +% \subsection{\LaTeXe\ interfaces} +% +% \subsubsection{Declaring hooks and using them in code} +% +% 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. +% +% +% \begin{function}{\NewHook} +% \begin{syntax} +% \cs{NewHook} \Arg{hook} +% \end{syntax} +% Creates a new \meta{hook}. +% If this is a hook provided as part of a package it is suggested +% that the \meta{hook} name is always structured as follows: +% \meta{package-name}\texttt{/}\meta{hook-name}. If necessary you +% can further subdivide the name by adding more \texttt{/} parts. +% If a hook name is already taken, an error is raised and the hook +% is not created. +% +% 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}{\NewReversedHook} +% \begin{syntax} +% \cs{NewReversedHook} \Arg{hook} +% \end{syntax} +% Like \cs{NewHook} declares a new \meta{hook}. +% the difference is that the code chunks for this hook are in +% reverse order by default (those added last are executed first). +% Any rules for the hook are applied after the default ordering. +% See sections~\ref{sec:order} and \ref{sec:reversed-order} +% for further details. +% +% 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}{\NewMirroredHookPair} +% \begin{syntax} +% \cs{NewMirroredHookPair} \Arg{hook-1} \Arg{hook-2} +% \end{syntax} +% A shorthand for +% \cs{NewHook}\Arg{hook-1}\cs{NewReversedHook}\Arg{hook-2}. +% +% The \meta{hooks} can be specified using the dot-syntax to denote +% the current package name. See section~\ref{sec:default-label}. +% \end{function} +% +% +% +% +% \begin{function}{\UseHook} +% \begin{syntax} +% \cs{UseHook} \Arg{hook} +% \end{syntax} +% Execute the hook code inside a command or environment. +% +% Before \verb=\begin{document}= the fast execution code for a hook +% is not set up, so in order to use a hook there it is explicitly +% initialized first. As that involves assignments using a hook at +% those times is not 100\% the same as using it after +% \verb=\begin{document}=. +% +% The \meta{hook} \emph{cannot} be specified using the dot-syntax. +% A leading |.| is treated literally. +% \end{function} +% +% \begin{function}{\UseOneTimeHook} +% \begin{syntax} +% \cs{UseOneTimeHook} \Arg{hook} +% \end{syntax} +% 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., +% \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 +% \cs{\meta{addto-cmd}} to simply process its argument, i.e., +% essentially make it behave like \cs{@firstofone}. +% +% \cs{UseOneTimeHook} does that: it records that the hook has been +% 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?} +% +% The \meta{hook} \emph{cannot} be specified using the dot-syntax. +% A leading |.| is treated literally. +% \end{function} +% +% +% \subsubsection{Updating code for hooks} +% +% \begin{function}{\AddToHook} +% \begin{syntax} +% \cs{AddToHook} \Arg{hook}\oarg{label}\Arg{code} +% \end{syntax} +% Adds \meta{code} to the \meta{hook} labeled by \meta{label}. If +% the optional argument \meta{label} is not provided, if \cs{AddToHook} +% is used in a package/class, then the current +% package/class name is used, otherwise \hook{top-level} is +% used~(see section~\ref{sec:default-label}). +% +% If there already exists code under the \meta{label} then the new +% \meta{code} is appended to the existing one (even if this is a reversed hook). +% If you want to replace existing code under the +% \meta{label}, first apply \cs{RemoveFromHook}. +% +% The hook doesn't have to exist for code to be added to +% it. However, if it is not declared later then obviously the +% added \meta{code} will never be executed. This +% allows for hooks to work regardless of package loading order and +% enables packages to add to hook of other packages without +% worrying whether they are actually used in the current document. +% See section~\ref{sec:querying}. +% +% The \meta{hook} and \meta{label} can be specified using the +% dot-syntax to denote the current package name. +% See section~\ref{sec:default-label}. +% \end{function} +% +% \begin{function}{\RemoveFromHook} +% \begin{syntax} +% \cs{RemoveFromHook} \Arg{hook}\oarg{label} +% \end{syntax} +% Removes any code labeled by \meta{label} from the \meta{hook}. +% If the optional +% argument \meta{label} is not provided, if \cs{AddToHook} +% is used in a package/class, then the current +% package/class name is used, otherwise \hook{top-level} is used. +% +% If the optional 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! +% +% The \meta{hook} and \meta{label} can be specified using the +% dot-syntax to denote the current package name. +% See section~\ref{sec:default-label}. +% \end{function} +% +% \medskip +% +% In contrast to the \texttt{voids} relationship between two labels +% in a \cs{DeclareHookrule} this is a destructive operation as the +% labeled code is removed from the hook data structure, whereas the +% relationship setting can be undone by providing a different +% relationship later. +% +% A useful application for this declaration inside the document body +% is when one wants to temporarily add code to hooks and later remove +% it again, e.g., +%\begin{verbatim} +% \AddToHook{env/quote/before}{\small} +% \begin{quote} +% A quote set in a smaller typeface +% \end{quote} +% ... +% \RemoveFromHook{env/quote/before} +% ... now back to normal for further quotes +%\end{verbatim} +% Note that you can't cancel the setting with +%\begin{verbatim} +% \AddToHook{env/quote/before}{} +%\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 +% changes for no good reason. +% +% The above is only needed if one wants to typeset several quotes in a +% smaller typeface. If the hook is only needed once then +% \cs{AddToHookNext} is simpler, because it resets itself after one use. +% +% +% \begin{function}{\AddToHookNext} +% \begin{syntax} +% \cs{AddToHookNext} \Arg{hook}\Arg{code} +% \end{syntax} +% Adds \meta{code} to the next invocation of the \meta{hook}. +% The code is executed after the normal hook code has finished and +% it is executed only once, i.e. it is deleted after it was used. +% +% Using the declaration is a global operation, i.e., the code is +% not lost, even if the declaration is used inside a group and the +% next invocation happens after the group. If the declaration is +% used several times before the hook is executed then all code is +% executed in the order in which it was declared.\footnotemark +% +% It is possible to nest declarations using the same hook (or +% different hooks), e.g., +% \begin{quote} +% \cs{AddToHookNext}\Arg{hook}\verb={=\meta{code-1}^^A +% \cs{AddToHookNext}\Arg{hook}\Arg{code-2}\verb=}= +% \end{quote} +% will execute \meta{code-1} next time the \meta{hook} is used and at +% that point puts \meta{code-2} into the \meta{hook} so that it gets +% executed on following time the hook is run. +% +% A hook doesn't have to exist for code to be added to it. This +% allows for hooks to work regardless of package loading +% order. +% See section~\ref{sec:querying}. +% +% The \meta{hook} can be specified using the dot-syntax to denote +% the current package name. See section~\ref{sec:default-label}. +% \end{function}\footnotetext{There is +% no mechanism to reorder such code chunks (or delete them).} +% +% \subsubsection{Hook names and default labels} +% \label{sec:default-label} +% +% It is best practice to use \cs{AddToHook} in packages or classes +% \emph{without specifying a \meta{label}} because then the package +% or class name is automatically used, which is helpful if rules are +% needed, and avoids mistyping the \meta{label}. +% +% Using an explicit \meta{label} is only necessary in very specific +% situations, e.g., if you want to add several chunks of code into a +% single hook and have them placed in different parts of the hook +% (by providing some rules). +% +% The other case is when you develop a larger package with several +% sub-packages. In that case you may want to use the same +% \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} +% 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 +% \meta{hook} or \meta{label} contains a non-expandable non-character +% 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} and \cs{UseOneTimeHook} are +% processed much in the same way except that spaces are not trimmed +% around the argument, for better performance. +% +% It is not enforced, but highly recommended that the hooks defined by +% a package, and the \meta{labels} used to add code to other hooks +% contain the package name to easily identify the source of the code +% chunk and to prevent clashes. This should be the standard practice, +% so this hook management code provides a shortcut to refer to the +% current package in the name of a \meta{hook} and in a \meta{label}. +% If \meta{hook} name or \meta{label} consist just of a single dot +% (|.|), or starts with a dot followed by a slash (|./|) then the dot +% denotes the \meta{default label} (usually the current package or class +% name---see~\cs{DeclareDefaultHookLabel}). +% A \enquote{|.|} or \enquote{|./|} anywhere else in a \meta{hook} or in +% \meta{label} is treated literally and is not replaced. +% +% For example, +% inside the package \texttt{mypackage.sty}, the default label is +% \texttt{mypackage}, so the instructions: +% \begin{verbatim} +% \NewHook {./hook} +% \AddToHook {./hook}[.]{code} % Same as \AddToHook{./hook}{code} +% \AddToHook {./hook}[./sub]{code} +% \DeclareHookRule{begindocument}{.}{before}{babel} +% \AddToHook {file/after/foo.tex}{code} +% \end{verbatim} +% are equivalent to: +% \begin{verbatim} +% \NewHook {mypackage/hook} +% \AddToHook {mypackage/hook}[mypackage]{code} +% \AddToHook {mypackage/hook}[mypackage/sub]{code} +% \DeclareHookRule{begindocument}{mypackage}{before}{babel} +% \AddToHook {file/after/foo.tex}{code} % unchanged +% \end{verbatim} +% +% The \meta{default label} is automatically set to the name of the +% current package or class (using \cs{@currname}). If \cs{@currname} +% is not set (because the hook command is used outside of a package, or +% the current file wasn't loaded with \cs{usepackage} or +% \cs{documentclass}), then the \texttt{top-level} is used as the +% \meta{default label}. +% +% This syntax is available in all \meta{label} arguments and most +% \meta{hook}, both in the \LaTeXe{} interface, and the \LaTeX3 +% interface described in section~\ref{sec:l3hook-interface}. +% +% Note, however, that the replacement of |.| by the \meta{default label} +% takes place when the hook command is executed, so actions that are +% somehow executed after the package ends will have the wrong +% \meta{default label} if the dot-syntax is used. For that reason, +% 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 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. +% +% In some cases, for example in large packages, one may want to separate +% it in logical parts, but still use the main package name as +% \meta{label}, then the \meta{default label} can be set using +% \cs{DeclareDefaultHookLabel}: +% +% \begin{function}{\DeclareDefaultHookLabel} +% \begin{syntax} +% \cs{DeclareDefaultHookLabel} \Arg{default label} +% \end{syntax} +% Sets the \meta{default label} to be used in \meta{label} arguments. +% If \cs{DeclareDefaultHookLabel} is not used in the +% current package, \cs{@currname} is used instead. If \cs{@currname} +% is not set, the code is assumed to be in the main document, in which +% case \texttt{top-level} is used. +% +% The effect of \cs{DeclareDefaultHookLabel} holds for the current +% file, and is reset to the previous value when the file is closed. +% \end{function} +% +% +% \subsubsection{Defining relations between hook code} +% +% The default assumption is that code added to hooks by different +% packages is independent and the order in which it is executed is +% irrelevant. While this is true in many case it is obviously false +% in many others. +% +% Before the hook management system was introduced +% packages had to take elaborate precaution to determine of some other +% package got loaded as well (before or after) and find some ways to +% alter its behavior accordingly. In addition is was often the user's +% responsibility to load packages in the right order so that code +% added to hooks got added in the right order and some cases even +% altering the loading order wouldn't resolve the conflicts. +% +% With the new hook management system it is now possible to define +% rules (i.e., relationships) between code chunks added by different +% packages and explicitly describe in which order they should be +% processed. +% +% \begin{function}{\DeclareHookRule} +% \begin{syntax} +% \cs{DeclareHookRule} \Arg{hook}\Arg{label1}\Arg{relation}\Arg{label2} +% \end{syntax} +% Defines a relation between \meta{label1} and \meta{label2} for a +% given \meta{hook}. If \meta{hook} is \texttt{??} this defines a default +% relation for all hooks that use the two labels, i.e., that have +% chunks of code labeled with \meta{label1} and \meta{label2}. +% Rules specific to a given hook take precedence over default +% rules that use \texttt{??} as the \meta{hook}. +% +% Currently, the supported relations are the following: +% \begin{itemize} +% +% \item[\texttt{before} or \texttt{\string<}] +% +% Code for \meta{label1} comes before code for \meta{label2}. +% +% \item[\texttt{after} or \texttt{\string>}] +% Code for \meta{label1} comes after code for \meta{label2}. +% +% \item[\texttt{incompatible-warning}] +% +% Only code for either \meta{label1} or \meta{label2} can appear +% for that hook (a way to say that two packages---or parts of +% them---are incompatible). A warning is raised if both labels +% appear in the same hook. +% +% \item[\texttt{incompatible-error}] +% +% Like \texttt{incompatible-error} but instead of a warning a +% \LaTeX{} error is raised, and the code for both labels are +% dropped from that hook until the conflict is resolved. +% +% \item[\texttt{voids}] +% +% Code for \meta{label1} overwrites code for \meta{label2}. More +% precisely, code for \meta{label2} is dropped for that +% hook. This can be used, for example if one package is a +% superset in functionality of another one and therefore wants to +% undo code in some hook and replace it with its own version. +% +% \item[\texttt{unrelated}] +% +% The order of code for \meta{label1} and \meta{label2} is +% irrelevant. This rule is there to undo an incorrect rule +% specified earlier. +% +% \end{itemize} +% There can only be a single relation between two labels for a +% given hook, +% i.e., a later \cs{DeclareHookrule} overwrites any previous +% delcaration. +% +% The \meta{hook} and \meta{label} can be specified using the +% dot-syntax to denote the current package name. +% See section~\ref{sec:default-label}. +% +% \end{function} +% +% +% \begin{function}{\ClearHookRule} +% \begin{syntax} +% \cs{ClearHookRule}\Arg{hook}\Arg{label1}\Arg{label2} +% \end{syntax} +% Syntactic sugar for saying that \meta{label1} and \meta{label2} +% are unrelated for the given \meta{hook}. +% \end{function} +% +% +% +% \begin{function}{\DeclareDefaultHookRule} +% \begin{syntax} +% \cs{DeclareDefaultHookRule}\Arg{label1}\Arg{relation}\Arg{label2} +% \end{syntax} +% This sets up a relation between \meta{label1} and \meta{label2} +% for all hooks unless overwritten by a specific rule for a hook. +% Useful for cases where one package has a specific relation to +% some other package, e.g., is \texttt{incompatible} or always +% needs a special ordering \texttt{before} or \texttt{after}. +% (Technically it is just a shorthand for using \cs{DeclareHookRule} +% with \texttt{??} as the hook name.) +% +% Declaring default rules is only supported in the document +% preamble.\footnotemark{} +% +% The \meta{label} can be specified using the dot-syntax to denote +% the current package name. See section~\ref{sec:default-label}. +% \end{function}\footnotetext{Trying to do so, e.g., via +% \cs{DeclareHookRule} with \texttt{??} has bad side-effects and +% is not supported (though not explicitly caught for performance +% reasons).} +% +% +% +% \subsubsection{Querying hooks} +% \label{sec:querying} +% +% Simpler data types, like token lists, have three possible states; they +% can: +% \begin{itemize} +% \item exist and be empty; +% \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. +% +% This seemingly strange state may happen when, for example, package~$A$ +% defines hook \hook{A/foo}, and package $B$ adds some code to that +% hook. However, a document may load package $B$ before package $A$, or +% may not load package $A$ at all. In both cases some code is added to +% hook \hook{A/foo} without that hook being defined yet, thus that +% hook is said to be non-empty, whereas it doesn't exist. Therefore, +% querying the existence of a hook doesn't imply its emptiness, neither +% does the other way around. +% +% 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. +% +% \begin{function}[EXP]{\IfHookEmptyTF} +% \begin{syntax} +% \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 +% branches to either \meta{true code} or \meta{false code} depending +% on the result. +% +% The \meta{hook} \emph{cannot} be specified using the dot-syntax. +% 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} +% +% If one has to adjust the code execution in a hook using a hook +% rule it is helpful to get some information about the code +% associated with a hook, its current order and the existing rules. +% +% \begin{function}{\ShowHook,\LogHook} +% \begin{syntax} +% \cs{ShowHook} \Arg{hook} +% \end{syntax} +% Displays information about the \meta{hook} such as +% \begin{itemize} +% \item +% the code chunks (and their labels) added to it, +% \item +% any rules set up to order them, +% \item +% the computed order in which the chunks are executed, +% \item +% any code executed on the next invocation only. +% \end{itemize} +% +% \cs{LogHook} prints the information to the |.log| file, and +% \cs{ShowHook} prints them to the terminal/command window and starts +% \TeX's prompt (only if \cs{errorstopmode}) to wait for user action. +% +% The \meta{hook} can be specified using the dot-syntax to denote +% the current package name. See section~\ref{sec:default-label}. +% \end{function} +% +% +% \subsubsection{Debugging hook code} +% +% \begin{function}{\DebugHooksOn,\DebugHooksOff} +% \begin{syntax} +% \cs{DebugHooksOn} +% \end{syntax} +% Turn the debugging of hook code on or off. This displays changes +% made to the hook data structures. The output is rather coarse and +% not really intended for normal use. +% \end{function} +% +% +% \subsection{L3 programming layer (\texttt{expl3}) interfaces} +% \label{sec:l3hook-interface} +% +% +% This is a quick summary of the \LaTeX3 programming interfaces for +% use with packages written in \texttt{expl3}. In contrast to the +% \LaTeXe{} interfaces they always use mandatory arguments only, e.g., +% you always have to specify the \meta{label} for a code chunk. We +% therefore suggest to use the declarations discussed in the previous +% section even in \texttt{expl3} packages, but the choice is yours. +% +% +% \begin{function} +% {\hook_new:n,\hook_new_reversed:n,\hook_new_pair:nn} +% \begin{syntax} +% \cs{hook_new:n}\Arg{hook} +% \cs{hook_new_pair:nn}\Arg{hook-1}\Arg{hook-2} +% \end{syntax} +% Creates a new \meta{hook} with normal or reverse ordering of code +% chunks. \cs{hook_new_pair:nn} creates a pair of such hooks with +% \Arg{hook-2} being a reversed hook. +% If a hook name is already taken, an error is raised and the hook +% is not created. +% +% 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_use:n} +% \begin{syntax} +% \cs{hook_use:n} \Arg{hook} +% \end{syntax} +% Executes the \Arg{hook} code followed (if set up) by the code for next +% invocation only, then empties that next invocation code. +% +% The \meta{hook} \emph{cannot} be specified using the dot-syntax. +% A leading |.| is treated literally. +% \end{function} +% +% \begin{function}{\hook_use_once:n} +% \begin{syntax} +% \cs{hook_use_once:n} \Arg{hook} +% \end{syntax} +% Changes the \Arg{hook} status so that from now on any addition to +% the hook code is executed immediately. Then execute any +% \Arg{hook} code already set up. +% \fmi{better L3 name?} +% +% The \meta{hook} \emph{cannot} be specified using the dot-syntax. +% A leading |.| is treated literally. +% \end{function} +% +% \begin{function}{\hook_gput_code:nnn} +% \begin{syntax} +% \cs{hook_gput_code:nnn} \Arg{hook} \Arg{label} \Arg{code} +% \end{syntax} +% Adds a chunk of \meta{code} to the \meta{hook} labeled +% \meta{label}. If the label already exists the \meta{code} is +% appended to the already existing code. +% +% If code is added to an external \meta{hook} (of the kernel or +% another package) then the convention is to use the package name +% as the \meta{label} not some internal module name or some other +% arbitrary string. +% +% The \meta{hook} and \meta{label} can be specified using the +% dot-syntax to denote the current package name. +% See section~\ref{sec:default-label}. +% \end{function} +% +% \begin{function} +% {\hook_gput_next_code:nn} +% \begin{syntax} +% \cs{hook_gput_next_code:nn} \Arg{hook} \Arg{code} +% \end{syntax} +% Adds a chunk of \meta{code} for use only in the next invocation of the +% \meta{hook}. Once used it is gone. +% +% This is simpler than \cs{hook_gput_code:nnn}, the code is simply +% appended to the hook in the order of declaration at the very end, +% i.e., after all standard code for the hook got executed. +% +% Thus if one needs to undo what the standard does one has to do +% that as part of \meta{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_gremove_code:nn} +% \begin{syntax} +% \cs{hook_gremove_code:nn} \Arg{hook} \Arg{label} +% \end{syntax} +% Removes any code for \meta{hook} labeled \meta{label}. +% +% If the code for that \meta{label} wasn't yet added to the +% \meta{hook}, an order is set so that when some code attempts to add +% that label, the removal order takes action and the code is not +% added. +% +% If the second 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, so think twice before using +% that! +% +% The \meta{hook} and \meta{label} can be specified using the +% dot-syntax to denote the current package name. +% See section~\ref{sec:default-label}. +% \end{function} +% +% +% \begin{function}{\hook_gset_rule:nnnn} +% \begin{syntax} +% \cs{hook_gset_rule:nnnn} \Arg{hook} \Arg{label1} \Arg{relation} \Arg{label2} +% \end{syntax} +% Relate \meta{label1} with \meta{label2} when used in \meta{hook}. +% See \cs{DeclareHookRule} for the allowed \meta{relation}s. +% If \meta{hook} is \texttt{??} a default rule is specified. +% +% The \meta{hook} and \meta{label} can be specified using the +% dot-syntax to denote the current package name. +% See section~\ref{sec:default-label}. +% The dot-syntax is parsed in both \meta{label} arguments, but it +% usually makes sense to be used in only one of them. +% \end{function} +% +% \begin{function}[pTF]{\hook_if_empty:n} +% \begin{syntax} +% \cs{hook_if_empty:nTF} \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 +% branches to either \meta{true code} or \meta{false code} depending +% on the result. +% +% The \meta{hook} \emph{cannot} be specified using the dot-syntax. +% 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} +% \cs{hook_show:n} \Arg{hook} +% \end{syntax} +% Displays information about the \meta{hook} such as +% \begin{itemize} +% \item +% the code chunks (and their labels) added to it, +% \item +% any rules set up to order them, +% \item +% the computed order in which the chunks are executed, +% \item +% any code executed on the next invocation only. +% \end{itemize} +% +% \cs{hook_log:n} prints the information to the |.log| file, and +% \cs{hook_show:n} prints them to the terminal/command window and starts +% \TeX's prompt (only if \cs{errorstopmode}) to wait for user action. +% +% 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_debug_on:,\hook_debug_off:} +% \begin{syntax} +% \cs{hook_debug_on:} +% \end{syntax} +% Turns the debugging of hook code on or off. This displays changes +% to the hook data. +% \end{function} +% +% +% +% \subsection{On the order of hook code execution} \label{sec:order} +% +% Chunks of code for a \meta{hook} under different labels are supposed +% to be independent if there are no special rules set up that +% define a relation between the chunks. This means that you can't +% make assumptions about the order of execution! +% +% Suppose you have the following declarations: +%\begin{verbatim} +% \NewHook{myhook} +% \AddToHook{myhook}[packageA]{\typeout{A}} +% \AddToHook{myhook}[packageB]{\typeout{B}} +% \AddToHook{myhook}[packageC]{\typeout{C}} +%\end{verbatim} +% then executing the hook with \cs{UseHook} will produce the +% typeout \texttt{A} \texttt{B} \texttt{C} in that order. In other +% words, the execution order is computed to be \texttt{packageA}, +% \texttt{packageB}, \texttt{packageC} which you can verify with +% \cs{ShowHook}\texttt{\{myhook\}}: +%\begin{verbatim} +% The hook 'myhook': +% Code chunks: +% packageA -> \typeout {A} +% packageB -> \typeout {B} +% packageC -> \typeout {C} +% Extra code next invocation: +% --- +% Rules: +% --- +% Execution order: +% packageA, packageB, packageC +%\end{verbatim} +% The reason is that the code chunks are internally saved in a property list +% and the initial order of such a property list is the order in +% which key-value pairs got added. However, that is only true if +% nothing other than adding happens! +% +% Suppose, or example, you want to replace the code chunk for +% \texttt{packageA}, e.g., +%\begin{verbatim} +% \RemoveFromHook{myhook}[packageA] +% \AddToHook{myhook}[packageA]{\typeout{A alt}} +%\end{verbatim} +% then your order becomes \texttt{packageB}, +% \texttt{packageC}, \texttt{packageA} because the label got removed +% from the property list and then re-added (at its end). +% +% While that may not be too surprising, the execution order is +% also sometimes altered if you add a redundant rule, e.g. if you specify +%\begin{verbatim} +% \DeclareHookRule{myhook}{packageA}{before}{packageB} +%\end{verbatim} +% instead of the previous lines we get +%\begin{verbatim} +% The hook 'myhook': +% Code chunks: +% packageA -> \typeout {A} +% packageB -> \typeout {B} +% packageC -> \typeout {C} +% Extra code next invocation: +% --- +% Rules: +% packageA|packageB with relation before +% Execution order (after applying rules): +% packageA, packageC, packageB +%\end{verbatim} +% As you can see the code chunks are still in the same order, but +% in the execution order for the labels \texttt{packageB} and +% \texttt{packageC} have +% swapped places. +% The reason is that, with the rule there are two orders that +% satisfy it, and the algorithm for sorting happened to pick a +% different one compared to the case without rules (where it +% doesn't run at all as there is nothing to resolve). +% Incidentally, if we had instead specified the redundant rule +%\begin{verbatim} +% \DeclareHookRule{myhook}{packageB}{before}{label-3} +%\end{verbatim} +% the execution order would not have changed. +% +% In summary: it is not possible to rely on the order of execution +% unless there are rules that partially or fully define the order +% (in which you can rely on them being fulfilled). +% +% +% \subsection{The use of \enquote{reversed} hooks} \label{sec:reversed-order} +% +% You may have wondered why you can declare a \enquote{reversed} hook +% with \cs{NewReversedHook} and what that does exactly. +% +% In short: the execution order of a reversed hook (without any +% rules!) is exactly reversed to the order you would have gotten for +% a hook declared with \cs{NewHook}. +% +% This is helpful if you have a pair of hooks where you expect to see +% code added that involves grouping, e.g., starting an environment +% in the first and closing that environment in the second hook. +% To give a somewhat contrived example\footnote{there are simpler +% ways to achieve the same effect.}, suppose there is a package +% adding the following: +%\begin{verbatim} +% \AddToHook{env/quote/before}[package-1]{\begin{itshape}} +% \AddToHook{env/quote/after} [package-1]{\end{itshape}} +%\end{verbatim} +% As a result, all quotes will be in italics. +% Now suppose further that the user wants the quotes also in blue +% and therefore adds: +%\begin{verbatim} +% \usepackage{color} +% \AddToHook{env/quote/before}{\begin{color}{blue}} +% \AddToHook{env/quote/after} {\end{color}} +%\end{verbatim} +% Now if the \hook{env/quote/after} hook would be a normal hook we +% would get the same execution order in both hooks, namely: +%\begin{verbatim} +% package-1, top-level +%\end{verbatim} +% (or vice versa) and as a result, would get: +%\begin{verbatim} +% \begin{itshape}\begin{color}{blue} ... +% \end{itshape}\end{color} +%\end{verbatim} +% and an error message that \verb=\begin{color}= ended by +% \verb=\end{itshape}=. +% With \hook{env/quote/after} declared as a reversed hook the +% execution order is reversed and so all environments are closed in +% the correct sequence and \cs{ShowHook} would give us the +% following output: +%\begin{verbatim} +% The hook 'env/quote/after': +% Code chunks: +% package-1 -> \end {itshape} +% top-level -> \end {color} +% Extra code next invocation: +% --- +% Rules: +% --- +% Execution order (after reversal): +% top-level, package-1 +%\end{verbatim} +% +% The reversal of the execution order happens before applying any +% rules, so if you alter the order you will probably have to alter +% it in both hooks, not just in one, but that depends on the use case. +% +% +% +% +% \subsection{Difference between \enquote{normal} and +% \enquote{one-time} hooks} +% +% When executing a hook a developer has the choice of using +% either \cs{UseHook} or \cs{UseOneTimeHook} (or their \pkg{expl3} +% equivalents \cs{hook_use:n} and \cs{hook_use_once:n}). +% This choice affects how \cs{AddToHook} is handled after the hook +% has been executed for the first time. +% +% With normal hooks adding code via \cs{AddToHook} means that the +% code chunk is added to the hook data structure and then used each time +% \cs{UseHook} is called. +% +% With one-time hooks it this is handled slightly differently: +% After \cs{UseOneTimeHook} has been called, any further attempts to +% add code to the hook via \cs{AddToHook} will simply execute the +% \meta{code} immediately. +% +% This has some consequences one needs to be aware of: +% \begin{itemize} +% \item +% +% If \meta{code} is added to a normal hook after the hook was +% executed and it is never executed again for one or the other +% reason, then this new \meta{code} will never be executed. +% +% \item +% +% In contrast if that happens with a one-time hook the \meta{code} is +% executed immediately. +% +% \end{itemize} +% In particular this means that construct such as +%\begin{quote} +% \cs{AddToHook}\verb={myhook}=\\ +% \phantom{\cs{AddToHook}}\verb={= \meta{code-1} +% \cs{AddToHook}\verb={myhook}=\Arg{code-2} +% \meta{code-3} \verb=}= +%\end{quote} +% works for one-time hooks\footnote{This is sometimes used with +% \cs{AtBeginDocument} which is why it is supported.} (all three +% code chunks are executed one after another), but it makes little +% sense with a normal hook, because with a normal hook the first time +% \verb=\UseHook{myhook}= is executed it would +% \begin{itemize} +% \item +% execute \meta{code-1}, +% \item +% then execute \verb=\AddToHook{myhook}{code-2}= which adds the +% code chunk \meta{code-2} to the hook for use on the next invocation, +% \item +% and finally execute \meta{code-3}. +% \end{itemize} +% The second time \cs{UseHook} is called it would execute the +% above and in addition \meta{code-2} as that was added as a code +% chunk to the hook in the meantime. So each time the hook is used +% another copy of \meta{code-2} is added and so that code chunk +% is executed $\meta{\# of invocations} -1$ times. +% +% +% +% +% +% \subsection{Private \LaTeX{} kernel hooks} +% +% There are a few places where it is absolutely essential for +% \LaTeX{} to function correctly that code is executed in a precisely +% defined order. Even that could have been implemented with the +% hook management (by adding various rules to ensure the +% appropriate ordering with respect to other code added by +% packages). However, this makes every document unnecessary +% slow, because there has to be sorting even through the result is +% predetermined. Furthermore it forces package writers to +% unnecessarily add such rules if they add further code to the hook +% (or break \LaTeX{}). +% +% 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 +% \cs{enddocument} you find +%\begin{verbatim} +% \UseHook{enddocument}% +% \@kernel@after@enddocument +%\end{verbatim} +% which means first the user/package-accessible \hook{enddocument} +% hook is executed and then the internal kernel hook. As their name +% indicates these kernel commands should not be altered by third-party +% packages, so please refrain from that in the interest of +% stability and instead use the public hook next to it.\footnote{As +% with everything in \TeX{} there is not enforcement of this rule, +% and by looking at the code it is easy to find out how the kernel +% adds to them. The main reason of this section is therefore to say +% \enquote{please don't do that, this is unconfigurable code!}} +% +% +% +% \subsection{Legacy \LaTeXe{} interfaces} +% +% \LaTeXe{} offered a small number of hooks together with commands to +% add to them. They are listed here and are retained for backwards +% compatibility. +% +% With the new hook management several additional hooks have been added +% to \LaTeX\ and more will follow. See the next section for what +% is already available. +% +% +% \begin{function}{\AtBeginDocument} +% \begin{syntax} +% \cs{AtBeginDocument} \oarg{label} \Arg{code} +% \end{syntax} +% If used without the optional argument \meta{label}, it works essentially +% like before, i.e., it is adding \meta{code} to the hook +% \hook{begindocument} +% (which is executed inside \verb=\begin{document}=). +% However, all code added this way is labeled with the label +% \hook{top-level} if done outside of a package or class or with the +% package/class name if called inside such a file. +% +% This way one can add further code to the hook using +% \cs{AddToHook} or \cs{AtBeginDocument} using a different label +% and explicitly order the code chunks as necessary, e.g., run some +% code before or after the \hook{top-level} code. When using the +% optional argument the call is equivalent to running +% \cs{AddToHook} \texttt{\{begindocument\}} \oarg{label} +% \Arg{code}. +% +% For important packages with known order requirement we may over +% time add rules to the kernel (or to those packages) so that they +% work regardless of the loading-order in the document. +% \end{function} +% +% \begin{function}{\AtEndDocument} +% \begin{syntax} +% \cs{AtEndDocument} \oarg{label} \Arg{code} +% \end{syntax} +% 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} +% +% \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 +% \cs{AtBeginDocumement}. 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 +% system under the label \texttt{legacy} so that it doesn't get +% lost. +% +% However, over time the remaining cases of direct usage need +% updating because in one of the future release of \LaTeX{} we will +% turn this legacy support off, as it does unnecessary slow down +% the processing. +% +% +% \subsection{\LaTeXe{} commands and environments augmented by +% hooks} +% +% \emph{intro to be written} +% +% \subsubsection{Generic hooks for all environments} +% +% Every environment \meta{env} has now four associated hooks coming +% with it: +% \begin{description} +% \item[\hook{env/\meta{env}/before}] +% +% This hook is executed as part of \cs{begin} as the very first +% action, in particular prior to starting the environment group. +% Its scope is therefore not restricted by the environment. +% +% \item[\hook{env/\meta{env}/begin}] +% +% This hook is executed as part of \cs{begin} directly in front +% of the code specific to the environment start (e.g., the +% second argument of \cs{newenvironment}). Its scope is the +% environment body. +% +% \item[\hook{env/\meta{env}/end}] +% +% This hook is executed as part of \cs{end} directly in front of the +% code specific to the end of the environment (e.g., the third +% argument of \cs{newenvironment}). +% +% \item[\hook{env/\meta{env}/after}] +% +% This hook is executed as part of \cs{end} after the +% code specific to the environment end and after the environment +% group has ended. +% Its scope is therefore not restricted by the environment. +% +% The hook is implemented as a reversed hook so if two packages +% add code to \hook{env/\meta{env}/before} and to +% \hook{env/\meta{env}/after} they can add surrounding +% environments and the order of closing them happens in the +% right sequence. +% +% \end{description} +% Generic environment hooks are never one-time hooks even with +% environments that are supposed to appear only once in a +% document.\footnote{Thus if one adds code to such hooks after the +% environment has been processed, it will only be executed if the +% environment appears again and if that doesn't happen the code +% will never get executed.} In contrast to other hooks there is +% also no need to declare them using \cs{NewHook}. +% +% 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}} +% (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 +%\begin{verbatim} +% \UseHook{env/quote/before}\quote +% ... +% \endquote\UseHook{env/quote/after} +%\end{verbatim} +% to add the outer hooks, etc. +% +% +% \begin{function}{\BeforeBeginEnvironment} +% \begin{syntax} +% \cs{BeforeBeginEnvironment} \oarg{label} \Arg{code} +% \end{syntax} +% This declaration adds to the \hook{env/\meta{env}/before} hook +% using by default the current package or class name as a label or +% \texttt{top-level} if used in the document directly. +% \end{function} +% +% \begin{function}{\AtBeginEnvironment} +% \begin{syntax} +% \cs{AtBeginEnvironment} \oarg{label} \Arg{code} +% \end{syntax} +% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/begin} hook. +% \end{function} +% +% \begin{function}{\AtEndEnvironment} +% \begin{syntax} +% \cs{AtEndEnvironment} \oarg{label} \Arg{code} +% \end{syntax} +% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/end} hook. +% \end{function} +% +% \begin{function}{\AfterEndEnvironment} +% \begin{syntax} +% \cs{AfterEndEnvironment} \oarg{label} \Arg{code} +% \end{syntax} +% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/after} hook. +% \end{function} +% +% +% +% +% \subsubsection{Hooks provided by \cs{begin}\texttt{\{document\}}} +% +% Until 2020 \cs{begin}\texttt{\{document\}} offered exactly one +% hook that one could add to using +% \cs{AtBeginDocument}. Experiences over the years have shown that +% this single hook in one place was not enough and as part of +% adding the general hook management system a number of additional +% hooks have been added at this point. The places for these hooks have +% been chosen to provide the same support as offered by external +% packages, such as \pkg{etoolbox} and others that augmented +% \cs{document} to gain better control. +% +% Supported are now the following hooks (all of them one-time hooks): +% \begin{description} +% +% +% \item[\hook{begindocument/before}] +% +% This hook is executed at the very start of \cs{document}, one can +% think of it as a hook for code at the end of the preamble +% section and this is how it is used by \pkg{etoolbox}'s +% \cs{AtEndPreamble}. +% +% +% +% \item[\hook{begindocument}] +% +% This hook is added to when using \cs{AtBeginDocument} and it is executed +% after the \texttt{.aux} file as be read in and most +% initialization are done, so they can be altered and inspected by +% the hook code. It is followed by a small number of further +% initializations that shouldn't be altered and are therefore +% coming later. +% +% The hook should not be used to add material for typesetting as +% we are still in \LaTeX's initialization phase and not in the +% document body. If such material needs to be added to the document +% body use the next hook instead. +% +% \item[\hook{begindocument/end}] +% +% This hook is executed at the end of the \cs{document} code in +% other words at the beginning of the document body. The only +% command that follows it is \cs{ignorespaces}. +% +% \end{description} +% The generic hooks executed by \cs{begin} also exist, i.e., +% \hook{env/document/before} and \hook{env/document/begin}, but +% with this special environment it is better use the dedicated +% one-time hooks above. +% +% +% +% +% \subsubsection{Hooks provided by \cs{end}\texttt{\{document\}}} +% +% \LaTeXe{} always provided \cs{AtEndDocument} to add code to the +% execution of \verb=\end{document}= just in front of the code that +% is normally executed there. While this was a big improvement over +% the situation in \LaTeX\,2.09 it was not flexible enough for a +% number of use cases and so packages, such as \pkg{etoolbox}, +% \pkg{atveryend} and others patched \cs{enddocument} to add +% additional points where code could be hooked into. +% +% Patching using packages is always problematical as leads to +% conflicts (code availability, ordering of patches, incompatible +% patches, etc.). For this reason a number of additional hooks +% have been added to the \cs{enddocument} code to allow packages +% to add code in various places in a controlled way without the +% need for overwriting or patching the core code. +% +% Supported are now the following hooks (all of them one-time hooks): +% \begin{description} +% +% \item[\hook{enddocument}] +% +% The hook associated with \cs{AtEndDocument}. It is immediately +% called at the beginning of \cs{enddocument}. +% +% When this hook is executed there may be still unprocessed +% material (e.g., floats on the deferlist) and the hook may add +% further material to be typeset. After it, \cs{clearpage} is +% called to ensure that all such material gets typeset. If there +% is nothing waiting the \cs{clearpage} has no effect. +% +% +% \item[\hook{enddocument/afterlastpage}] +% +% As the name indicates this hook should not receive code that +% 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 +% set up any testing code to be run when the \texttt{.aux} file +% is re-read in the next step. +% +% +% After this hook has been executed the \texttt{.aux} file is +% closed for writing and then read back in to do some tests +% (e.g., looking for missing references or duplicated labels, etc.). +% +% \item[\hook{enddocument/afteraux}] +% +% At this point, the \texttt{.aux} file has been reprocessed and so +% this is a possible place for final checks and display of +% information to the user. However, for the latter you might +% prefer the next hook, so that your information is displayed after the +% (possibly longish) list of files if that got requested via \cs{listfiles}. +% +% \item[\hook{enddocument/info}] +% +% This hook is meant to receive code that write final information +% messages to the terminal. It follows immediately after the +% previous hook (so both could have been combined, but then +% packages adding further code would always need to also supply +% an explicit rule to specify where it should go. +% +% This hook already contains some code added by the kernel (under +% the labels \texttt{kernel/filelist} and +% \texttt{kernel/warnings}), namely the list of files when +% \cs{listfiles} has been used and the warnings for duplicate +% labels, missing references, font substitutions etc. +% +% \item[\hook{enddocument/end}] +% +% Finally, this hook is executed just in front of the final call +% to \cs{@{}@end}. +% +% \end{description} +% +% +% There is also the hook \hook{shipout/lastpage}. This hook is +% executed as part of the last \cs{shipout} in the document to +% allow package to add final \cs{special}'s to that page. Where +% this hook is executed in relation to those from the above list +% can vary from document to document. Furthermore to determine correctly +% which of the \cs{shipout}s is the last one, \LaTeX{} needs to be run +% several times, so initially it might get executed on the wrong +% page. See section~\ref{sec:shipout} for where to find the details. +% +% +% 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 +% 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 +% processing. +% +% +% +% +% \subsubsection{Hooks provided \cs{shipout} operations} +% \label{sec:shipout} +% +% There are several hooks and mechanisms added to \LaTeX{}'s +% process of generating pages. These are documented in +% \texttt{ltshipout-doc.pdf} or with code in +% \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} +% +% In languages that need to support for more than one script in +% parallel (and thus several sets of fonts), e.g., Latin and +% Japanese fonts, NFSS font commands, such as \cs{sffamily}, need +% to switch both the Latin family to ``Sans Serif'' and in addition +% alter a second set of fonts. +% +% To support this several NFSS have hooks in which such support can +% be added. +% \begin{description} +% +% \item[\hook{rmfamily}] +% +% After \cs{rmfamily} has done its initial checks and prepared a +% any font series update this hook is executed and only +% afterwards \cs{selectfont}. +% +% \item[\hook{sffamily}] +% +% Like the \hook{rmfamily} hook but for the \cs{sffamily} command. +% +% \item[\hook{ttfamily}] +% +% Like the \hook{rmfamily} hook but for the \cs{ttfamily} command. +% +% \item[\hook{normalfont}] +% +% The \cs{normalfont} command resets font encoding family series +% and shape to their document defaults. It then executes this +% hook and finally calls \cs{selectfont}. +% +% \item[\hook{expand@font@defaults}] +% +% The internal \cs{expand@font@defaults} command expands and +% saves the current defaults for the meta families (rm/sf/tt) and +% the meta series (bf/md). If the NFSS machinery has been +% augmented, e.g., for Chinese or Japanese fonts, then further +% defaults may need to be set at this point. This can be done in +% this hook which is executed at the end of this macro. +% +% \item[\hook{bfseries/defaults}, \hook{bfseries}] +% +% If the \cs{bfdefault} was explicitly changed by the user its +% new value is used to set the bf series defaults for the meta +% families (rm/sf/tt) when \cs{bfseries} is called. In the +% \hook{bfseries/defaults} hook further adjustments can be made +% in this case. This hook is only executed if such a change is +% detected. In contrast the \hook{bfseries} hook is always +% executed just before \cs{selectfont} is called to change to the +% new series. +% +% +% \item[\hook{mdseries/defaults}, \hook{mdseries}] +% +% These two hooks are like the previous ones but used in +% \cs{mdseries} command. +% +% \end{description} +% +% +% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } +% +% +% \section{The Implementation} +% +% +% \subsection{Loading further extensions} +% +% \begin{macrocode} +%<@@=hook> +% \end{macrocode} +% +% +% 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 +% \end{macrocode} +% +% +% \subsection{Debugging} +% +% \begin{macro}{\g_@@_debug_bool} +% Holds the current debugging state. +% \begin{macrocode} +\bool_new:N \g_@@_debug_bool +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\hook_debug_on:,\hook_debug_off:} +% \begin{macro}{\@@_debug:n} +% \begin{macro}{\@@_debug_gset:} +% Turns debugging on and off by redefining \cs{@@_debug:n}. +% \begin{macrocode} +\cs_new_eq:NN \@@_debug:n \use_none:n +\cs_new_protected:Npn \hook_debug_on: + { + \bool_gset_true:N \g_@@_debug_bool + \@@_debug_gset: + } +\cs_new_protected:Npn \hook_debug_off: + { + \bool_gset_false:N \g_@@_debug_bool + \@@_debug_gset: + } +\cs_new_protected:Npn \@@_debug_gset: + { + \cs_gset_protected:Npx \@@_debug:n ##1 + { \bool_if:NT \g_@@_debug_bool {##1} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% \subsection{Borrowing from internals of other kernel modules} +% +% +% \begin{macro}[EXP]{\@@_str_compare:nn} +% Private copy of \cs{__str_if_eq:nn} +% \begin{macrocode} +\cs_new_eq:NN \@@_str_compare:nn \__str_if_eq:nn +% \end{macrocode} +% \end{macro} +% +% \subsection{Declarations} +% +% \begin{macro}{\l_@@_tmpa_bool} +% Scratch boolean used throughout the package. +% \begin{macrocode} +\bool_new:N \l_@@_tmpa_bool +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_return_tl,\l_@@_tmpa_tl,\l_@@_tmpb_tl} +% Scratch variables used throughout the package. +% \begin{macrocode} +\tl_new:N \l_@@_return_tl +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpb_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\g_@@_all_seq} +% In a few places we need a list of all hook names ever defined so +% we keep track if them in this sequence. +% \begin{macrocode} +\seq_new:N \g_@@_all_seq +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\g_@@_removal_list_prop} +% A token list to hold delayed removals. +% \begin{macrocode} +\tl_new:N \g_@@_removal_list_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_cur_hook_tl} +% Stores the name of the hook currently being sorted. +% \begin{macrocode} +\tl_new:N \l_@@_cur_hook_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_work_prop} +% A property list holding a copy of the +% \cs[no-index]{g_@@_\meta{hook}_code_prop} of the hook being sorted +% to work on, so that changes don't act destructively on the hook data +% structure. +% \begin{macrocode} +\prop_new:N \l_@@_work_prop +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\g_@@_execute_immediately_prop} +% List of hooks that from no on should not longer receive code. +% \begin{macrocode} +\prop_new:N \g_@@_execute_immediately_prop +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\g_@@_used_prop} +% All hooks that receive code (for use in debugging display). +% \begin{macrocode} +\prop_new:N \g_@@_used_prop +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\g_@@_hook_curr_name_tl,\g_@@_name_stack_seq} +% Default label used for hook commands, and a stack to keep track of +% packages within packages. +% \begin{macrocode} +\tl_new:N \g_@@_hook_curr_name_tl +\seq_new:N \g_@@_name_stack_seq +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_tmp:w} +% Temporary macro for generic usage. +% \begin{macrocode} +\cs_new_eq:NN \@@_tmp:w ? +% \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{macrocode} +\cs_generate_variant:Nn \tl_gremove_once:Nn { Nx } +\cs_generate_variant:Nn \tl_show:n { x } +\cs_generate_variant:Nn \tl_log:n { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\s_@@_mark} +% Scan mark used for delimited arguments. +% \begin{macrocode} +\scan_new:N \s_@@_mark +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Providing new hooks} +% +% \begin{macro}{\g_@@_..._code_prop,\@@~...,\@@_next~...} +% +% Hooks have a \meta{name} 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 +% 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}}] +% A token list holding the relation between \meta{label1} and +% \meta{label2} in the \meta{name}. 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 |??|. +% +% \item[\cs{@@~\meta{name}}] 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. +% This token list is named like that so that in case of an error +% inside the hook, the reported token list in the error is shorter, +% and to make it simpler to normalize hook names in +% \cs{@@_make_name:n}. +% +% \item[\cs{g_@@_\meta{name}_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{@@_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}. +% +% \end{description} +% \end{macro} +% +% +% +% +% \begin{macro}{\hook_new:n} +% The \cs{hook_new:n} declaration declare 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} } +\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. +% \begin{macrocode} + \hook_if_exist:nTF {#1} + { \msg_error:nnn { hooks } { exists } {#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. +% \begin{macrocode} + { + \seq_gput_right:Nn \g_@@_all_seq {#1} +% \end{macrocode} +% This is only used by the actual code of the current hook, so +% declare it normally: +% \begin{macrocode} + \tl_new:c { @@~#1 } +% \end{macrocode} +% Now ensure that the base data structure for the hook exists: +% \begin{macrocode} + \@@_declare: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} +% \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 +% and contains a \verb=-= for reversed hooks. +% \begin{macrocode} + \tl_new:c { g_@@_#1_reversed_tl } +% \end{macrocode} +% The above is all in L3 convention, but we also provide an +% interface to legacy \LaTeXe{} hooks of the form \cs{@...hook}, +% e.g., \cs{@begindocumenthook}. +% there have been a few of them and they have been added to +% using \cs{g@addto@macro}. If there exists such a macro matching +% the name of the new hook, i.e., +% \verb+\@+\meta{hook-name}\texttt{hook} and it is not empty then +% we add its contents as a code chunk under the label \texttt{legacy}. +% \begin{quote} +% \textbf{Warning: this support will vanish in future releases!} +% \end{quote} +% +% \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 both +% variables exist, since both are declared at the same time (either +% both exist, or neither). +% \begin{macrocode} +\cs_new_protected:Npn \@@_declare:n #1 + { + \@@_if_exist:nF {#1} + { + \prop_new:c { g_@@_#1_code_prop } + \tl_new:c { @@_next~#1 } + } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\hook_new_reversed:n,\@@_new_reversed:n} +% +% Declare a new hook. The default ordering of code chunks is +% reversed, signaled by setting the token list to a minus sign. +% \begin{macrocode} +\cs_new_protected:Npn \hook_new_reversed:n #1 + { \@@_normalize_hook_args:Nn \@@_new_reversed:n {#1} } +\cs_new_protected:Npn \@@_new_reversed:n #1 + { + \@@_new:n {#1} +% \end{macrocode} +% If the hook already exists the above will generate an error +% message, so the next line should be executed (but it is --- too +% bad). +% \begin{macrocode} + \tl_gset:cn { g_@@_#1_reversed_tl } { - } + } +% \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} +\cs_new_protected:Npn \hook_new_pair:nn #1#2 + { \hook_new:n {#1} \hook_new_reversed:n {#2} } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_include_legacy_code_chunk:n} +% The \LaTeX{} legacy concept for hooks uses with hooks the +% following naming scheme in the code: \cs{@...hook}. +% +% If this macro is not empty we add it under the label +% \texttt{legacy} to the current hook and then empty it globally. +% This way packages or classes directly manipulating commands such +% as \cs{@begindocumenthook} still get their hook data added. +% \begin{quote} +% \textbf{Warning: this support will vanish in future releases!} +% \end{quote} +% \begin{macrocode} +\cs_new_protected:Npn \@@_include_legacy_code_chunk:n #1 + { +% \end{macrocode} +% If the \pkg{expl3} code is run with checking on then assigning or +% using non L3 names such as \cs{@enddocumenthook} with \pkg{expl3} +% functions will trigger warnings so we run this code with +% debugging explicitly suspended. +% \begin{macrocode} + \debug_suspend: +% \end{macrocode} +% If the macro doesn't exist (which is the usual case) then nothing +% needs to be done. +% \begin{macrocode} + \tl_if_exist:cT { @#1hook } +% \end{macrocode} +% Of course if the legacy hook exists but is empty, there is no need +% to add anything under \texttt{legacy} the legacy label. +% \begin{macrocode} + { + \tl_if_empty:cF { @#1hook } + { + \exp_args:Nnnv \@@_hook_gput_code_do:nnn {#1} + { legacy } { @#1hook } +% \end{macrocode} +% Once added to the hook, we need to clear it otherwise it might +% get added again later if the hook data gets updated. +% \begin{macrocode} + \tl_gclear:c { @#1hook } + } + } + \debug_resume: + } +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Parsing a label} +% +% \begin{macro}[EXP]{\@@_parse_label_default:n} +% This macro checks if a label was given (not \cs{c_novalue_tl}), and +% if so, tries to parse the label looking for a leading \verb|.| to +% replace for \cs{@currname}. Otherwise \cs{@@_currname_or_default:n} +% is used to pick \cs{@currname} or the fallback value. +% +% The default |top-level| is hard-coded here. It once was an +% argument, but it's no longer needed. \pho{can't remember why} +% \begin{macrocode} +\cs_new:Npn \@@_parse_label_default:n #1 + { + \tl_if_novalue:nTF {#1} + { \@@_currname_or_default:n { top-level } } + { + \tl_trim_spaces_apply:nN {#1} + \@@_parse_dot_label:nn { top-level } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_parse_dot_label:nn} +% \begin{macro}[EXP]{ +% \@@_parse_dot_label:nw, +% \@@_parse_dot_label_cleanup:w, +% \@@_parse_dot_label_aux:nw +% } +% Start by checking if the label is empty, which raises an error, and +% uses the fallback value. If not, +% split the label at a \verb|./|, if any, and check if no tokens are +% before the \verb|./|, or if the only character is a \verb|.|. +% If these requirements are fulfilled, the leading +% \verb|.| is replaced with \cs{@@_currname_or_default:n}. Otherwise +% the label is returned unchanged. +% \begin{macrocode} +\cs_new:Npn \@@_parse_dot_label:nn #1 #2 + { + \tl_if_empty:nTF {#1} + { + \msg_expandable_error:nnn { hooks } { empty-label } {#2} + #2 + } + { + \str_if_eq:nnTF {#1} { . } + { \@@_currname_or_default:n {#2} } + { \@@_parse_dot_label:nw {#2} #1 ./ \s_@@_mark } + } + } +\cs_new:Npn \@@_parse_dot_label:nw #1 #2 ./ #3 \s_@@_mark + { + \tl_if_empty:nTF {#2} + { \@@_parse_dot_label_aux:nw {#1} #3 \s_@@_mark } + { + \tl_if_empty:nTF {#3} + { \@@_make_name:n {#2} } + { \@@_parse_dot_label_cleanup:w #2 ./ #3 \s_@@_mark } + } + } +\cs_new:Npn \@@_parse_dot_label_cleanup:w #1 ./ \s_@@_mark {#1} +\cs_new:Npn \@@_parse_dot_label_aux:nw #1 #2 ./ \s_@@_mark + { \@@_currname_or_default:n {#1} / \@@_make_name:n {#2} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_currname_or_default:n} +% Uses \cs{g_@@_hook_curr_name_tl} if it is set, otherwise tries +% \cs{@currname}. If neither is set, uses the fallback value +% \verb|#1| (usually \texttt{top-level}). +% \begin{macrocode} +\cs_new:Npn \@@_currname_or_default:n #1 + { + \tl_if_empty:NTF \g_@@_hook_curr_name_tl + { + \tl_if_empty:NTF \@currname + { \@@_make_name:n {#1} } + { \@currname } + } + { \g_@@_hook_curr_name_tl } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_make_name:n,\@@_make_name:w} +% Provides a standard sanitisation 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 +% 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. +% \begin{macrocode} +\cs_new:Npn \@@_make_name:n #1 + { + \exp_after:wN \exp_after:wN \exp_after:wN \@@_make_name:w + \exp_after:wN \token_to_str:N \cs:w @@~ #1 \cs_end: + } +\exp_last_unbraced:NNNNo +\cs_new:Npn \@@_make_name:w #1 \tl_to_str:n { @@~ } { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_normalize_hook_args:Nn} +% \begin{macro}{\@@_normalize_hook_args:Nnn} +% \begin{macro}{\@@_normalize_hook_rule_args:Nnnnn} +% \begin{macro}{\@@_normalize_hook_args_aux:Nn} +% Standard route for normalising hook and label arguments. The main +% macro does the entire operation within a group so that csnames made +% by \cs{@@_make_name:n} are wiped off before continuing. This means +% that this function cannot be used for \cs{hook_use:n}! +% \begin{macrocode} +\cs_new_protected:Npn \@@_normalize_hook_args_aux:Nn #1 #2 + { + \group_begin: + \use:e + { + \group_end: + \exp_not:N #1 #2 + } + } +\cs_new_protected:Npn \@@_normalize_hook_args:Nn #1 #2 + { + \@@_normalize_hook_args_aux:Nn #1 + { { \@@_parse_label_default:n {#2} } } + } +\cs_new_protected:Npn \@@_normalize_hook_args:Nnn #1 #2 #3 + { + \@@_normalize_hook_args_aux:Nn #1 + { + { \@@_parse_label_default:n {#2} } + { \@@_parse_label_default:n {#3} } + } + } +\cs_new_protected:Npn \@@_normalize_hook_rule_args:Nnnnn #1 #2 #3 #4 #5 + { + \@@_normalize_hook_args_aux:Nn #1 + { + { \@@_parse_label_default:n {#2} } + { \@@_parse_label_default:n {#3} } + { \tl_trim_spaces:n {#4} } + { \@@_parse_label_default:n {#5} } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\hook_gput_code:nnn} +% \begin{macro}{\@@_gput_code:nnn,\@@_gput_code:nxv,\@@_hook_gput_code_do:nnn} +% +% With \cs{hook_gput_code:nnn}\Arg{hook}\Arg{label}\Arg{code} a +% chunk of \meta{code} is added to an existing \meta{hook} labeled +% with \meta{label}. +% \begin{macrocode} +\cs_new_protected:Npn \hook_gput_code:nnn #1 #2 + { \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} } +\cs_new_protected:Npn \@@_gput_code:nnn #1 #2 #3 + { +% \end{macrocode} +% First check if the hook was used as a one-time hook: +% \begin{macrocode} + \prop_if_in:NnTF \g_@@_execute_immediately_prop {#1} + {#3} + { +% \end{macrocode} +% Then check if the current \meta{hook}/\meta{label} pair was marked +% for removal, in which case \cs{@@_unmark_removal:nn} is used to +% remove that mark (once). This may happen when a package removes +% code from another package which was not yet loaded: the removal +% order is stored, and at this stage it is executed by not adding to +% the hook. +% \begin{macrocode} + \@@_if_marked_removal:nnTF {#1} {#2} + { \@@_unmark_removal:nn {#1} {#2} } + { +% \end{macrocode} +% If no removal is queued, we are free to add. Start by checking if +% the hook exists. +% \begin{macrocode} + \hook_if_exist: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}= +% this is then sorted into a token list for fast execution. +% \begin{macrocode} + { + \@@_hook_gput_code_do:nnn {#1} {#2} {#3} +% \end{macrocode} +% However, if there is an update within the document we need to alter +% this execution code which is done by +% \cs{@@_update_hook_code:n}. In the preamble this does nothing. +% \begin{macrocode} + \@@_update_hook_code:n {#1} + } +% \end{macrocode} +% +% If the hook does not exist, however, before giving up try to +% 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} } + } + } + } +\cs_generate_variant:Nn \@@_gput_code:nnn { nxv } +% \end{macrocode} +% +% This macro will unconditionally add a chunk of code to the given hook. +% \begin{macrocode} +\cs_new_protected:Npn \@@_hook_gput_code_do:nnn #1 #2 #3 + { +% \end{macrocode} +% However, first some debugging info if debugging is enabled: +% \begin{macrocode} + \@@_debug:n{\iow_term:x{****~ Add~ to~ + \hook_if_exist:nF {#1} { undeclared~ } + hook~ #1~ (#2) + \on@line\space <-~ \tl_to_str:n{#3}} } +% \end{macrocode} +% Then try to get the code chunk labeled \verb=#2= from the hook. +% If there's code already there, then append \verb=#3= to that, +% otherwise just put \verb=#3=. +% \begin{macrocode} + \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl + { + \prop_gput:cno { g_@@_#1_code_prop } {#2} + { \l_@@_return_tl #3 } + } + { \prop_gput:cnn { g_@@_#1_code_prop } {#2} {#3} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_gput_undeclared_hook:nnn} +% Often it may happen that a package $A$ defines a hook \verb=foo=, +% but package $B$, that adds code to that hook, is loaded before $A$. +% In such case we need to add code to the hook before its declared. +% \begin{macrocode} +\cs_new_protected:Npn \@@_gput_undeclared_hook:nnn #1 #2 #3 + { + \@@_declare: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} +% 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. +% +% The wrapper \cs{@@_try_declaring_generic_hook:nnn} then defers +% \cs{hook_gput_code:nnn} if the generic hook was declared, or to +% \cs{@@_gput_undeclared_hook:nnn} otherwise (the hook was tested for +% existence before, so at this point if it isn't generic, it doesn't +% exist). +% +% The wrapper \cs{@@_try_declaring_generic_next_hook:nn} for +% next-execution hooks does the same: it defers the code to +% \cs{hook_gput_next_code:nn} if the generic hook was declared, or +% to \cs{@@_gput_next_do:nn} otherwise. +% \begin{macrocode} +\cs_new_protected:Npn \@@_try_declaring_generic_hook:nnn #1 + { + \@@_try_declaring_generic_hook:nNNnn {#1} + \hook_gput_code:nnn \@@_gput_undeclared_hook:nnn + } +\cs_new_protected:Npn \@@_try_declaring_generic_next_hook:nn #1 + { + \@@_try_declaring_generic_hook:nNNnn {#1} + \hook_gput_next_code:nn \@@_gput_next_do:nn + } +% \end{macrocode} +% +% \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 +% 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 +% predefined set for generic names. We also split off the second +% component to see if we have to make a reversed hook. In either case +% the function returns \meta{true} for a generic hook and \meta{false} +% in other cases. +% \begin{macrocode} +\cs_new_protected:Npn \@@_try_declaring_generic_hook:nNNnn #1 + { + \@@_if_file_hook:wTF #1 / / \s_@@_mark + { + \exp_args:Ne \@@_try_declaring_generic_hook_split:nNNnn + { \exp_args:Ne \@@_file_hook_normalize:n {#1} } + } + { \@@_try_declaring_generic_hook_split:nNNnn {#1} } + } +\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} + } +\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn + #1 / #2 / #3 / #4 \scan_stop: #5 { TF } + { + \tl_if_empty:nTF {#2} + { \prg_return_false: } + { + \prop_if_in:NnTF \c_@@_generics_prop {#1} + { + \hook_if_exist:nF {#5} { \hook_new:n {#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. +% \begin{macrocode} + \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: } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[pTF]{\@@_if_file_hook:w} +% \cs{@@_if_file_hook:wTF} checks if the argument is a valid +% file-specific hook (not, for example, |file/before|, but +% |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}}. +% 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 +% \meta{position} is in the \cs{c_@@_generics_file_prop}. +% +% A property list is used here to avoid having to worry with catcodes, +% because \pkg{expl3}'s file name parsing turns all characters into +% catcode-12 tokens, which might differ from hand-input letters. +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_if_file_hook:w + #1 / #2 / #3 \s_@@_mark { TF } + { + \str_if_eq:nnTF {#1} { file } + { + \bool_lazy_or:nnTF + { \tl_if_empty_p:n {#3} } + { \str_if_eq_p:nn {#3} { / } } + { \prg_return_false: } + { + \prop_if_in:NnTF \c_@@_generics_file_prop {#2} + { \prg_return_true: } + { \prg_return_false: } + } + } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_file_hook_normalize:n} +% \begin{macro}[EXP]{\@@_strip_double_slash:n,\@@_strip_double_slash:w} +% When a file-specific hook is found, before being declared it is +% lightly normalized by \cs{@@_file_hook_normalize:n}. The current +% implementation just replaces two consecutive slashes (|//|) by a +% single one, to cope with simple cases where the user did something +% like \verb|\def\input@path{{./mypath/}}|, in which case a hook would +% have to be \verb|\AddToHook{file/after/./mypath//file.tex}|. +% \begin{macrocode} +\cs_new:Npn \@@_file_hook_normalize:n #1 + { \@@_strip_double_slash:n {#1} } +\cs_new:Npn \@@_strip_double_slash:n #1 + { \@@_strip_double_slash:w #1 // \s_@@_mark } +\cs_new:Npn \@@_strip_double_slash:w #1 // #2 \s_@@_mark + { + \tl_if_empty:nTF {#2} + {#1} + { \@@_strip_double_slash:w #1 / #2 \s_@@_mark } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\c_@@_generics_prop} +% 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{env}] +% The generic hooks used in \cs{begin} and \cs{end}. +% \item[\texttt{file}] +% 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=} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\c_@@_generics_reversed_ii_prop, +% \c_@@_generics_reversed_iii_prop, +% \c_@@_generics_file_prop} +% Some of the generic hooks are supposed to use reverse ordering, these are +% the following (only the second or third sub-component is checked): +% \begin{macrocode} +\prop_const_from_keyval:Nn \c_@@_generics_reversed_ii_prop {after=,end=} +\prop_const_from_keyval:Nn \c_@@_generics_reversed_iii_prop {after=} +\prop_const_from_keyval:Nn \c_@@_generics_file_prop {before=,after=} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\hook_gremove_code:nn} +% \begin{macro}{\@@_gremove_code:nn} +% +% With \cs{hook_gremove_code:nn}\Arg{hook}\Arg{label} any code +% for \meta{hook} stored under \meta{label} is removed. +% \begin{macrocode} +\cs_new_protected:Npn \hook_gremove_code:nn #1 #2 + { \@@_normalize_hook_args:Nnn \@@_gremove_code:nn {#1} {#2} } +\cs_new_protected:Npn \@@_gremove_code:nn #1 #2 + { +% \end{macrocode} +% First check that the hook code pool exists. \cs{hook_if_exist: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} +% \end{macrocode} +% Then remove the chunk and run \cs{@@_update_hook_code:n} so +% that the execution token list reflects the change if we are after +% \verb=\begin{document}=. +% \begin{macrocode} + { + \str_if_eq:nnTF {#2} {*} + { \prop_gclear:c { g_@@_#1_code_prop } } + { +% \end{macrocode} +% Check if the label being removed exists in the code pool. If it does, +% just call \cs{@@_gremove_code_do:nn} to do the removal, otherwise mark it +% to be removed. +% \begin{macrocode} + \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl + { \@@_gremove_code_do:nn } + { \@@_mark_removal:nn } + {#1} {#2} + } +% \end{macrocode} +% Finally update the code, if the hook exists. +% \begin{macrocode} + \hook_if_exist:nT {#1} + { \@@_update_hook_code:n {#1} } + } +% \end{macrocode} +% +% If the code pool for this hook doesn't exist it means that nothing +% tried to add to it before, so we just queue this removal order for +% later. +% \begin{macrocode} + { \@@_mark_removal:nn {#1} {#2} } + } +% \end{macrocode} +% +% \begin{macro}{\@@_gremove_code_do:nn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_gremove_code_do:nn #1 #2 + { \prop_gremove:cn { g_@@_#1_code_prop } {#2} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_mark_removal:nn} +% Marks \meta{label} (\verb=#2=) to be removed from \meta{hook} +% (\verb=#1=). The number of removals should be fairly small, and +% \cs{tl_gremove_once:Nx} is fairly efficient even for longer token +% lists, so we use a single global token list, rather than one for +% each hook. +% +% A hand-crafted token list is used here because property lists don't +% hold repeated items, so multiple usages of \cs{@@_mark_removal:nn} +% would be cancelled by a single \cs{@@_unmark_removal:nn}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_mark_removal:nn #1 #2 + { + \tl_gput_right:Nx \g_@@_removal_list_tl + { \@@_removal_tl:nn {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_unmark_removal:nn} +% Unmarks \meta{label} (\verb=#2=) to be removed from \meta{hook} +% (\verb=#1=). \cs{tl_gremove_once:Nx} is used rather than +% \cs{tl_gremove_all:Nx} so that two additions are needed to cancel +% two marked removals, rather than only one. +% \begin{macrocode} +\cs_new_protected:Npn \@@_unmark_removal:nn #1 #2 + { + \tl_gremove_once:Nx \g_@@_removal_list_tl + { \@@_removal_tl:nn {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{\@@_if_marked_removal:nn} +% Checks if the \cs{g_@@_removal_list_tl} contains the current +% \meta{label} (\verb=#2=) and \meta{hook} (\verb=#1=). +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_if_marked_removal:nn #1 #2 { TF } + { + \exp_args:NNx \tl_if_in:NnTF \g_@@_removal_list_tl + { \@@_removal_tl:nn {#1} {#2} } + { \prg_return_true: } { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[rEXP]{\@@_removal_tl:nn} +% Builds a token list with \verb=#1= and \verb=#2= which can only be +% matched by \verb=#1= and \verb=#2=. The |&|$_4$ anchors a removal, +% so that \verb=#1= can't be mistaken by \verb=#2= and vice versa, and +% the two |$|$_3$ delimit the two arguments +% \begin{macrocode} +\cs_new:Npn \@@_removal_tl:nn #1 #2 + { & \tl_to_str:n {#2} $ \tl_to_str:n {#1} $ } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{ +% \g_@@_??_code_prop, +% \@@~??, +% \g_@@_??_reversed_tl, +% } +% +% Initially these variables simply used an empty ``label'' name (not +% two question marks). This was a bit unfortunate, because then +% \texttt{l3doc} complains about \verb=__= in the middle of a +% command name when trying to typeset the documentation. However +% using a ``normal'' name such as \texttt{default} has the +% 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} +% expansion in the code later on. +% +% \cs{@@~??} 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} +\prop_new:c {@@~??} +% \end{macrocode} +% +% Default rules are always given in normal ordering (never in +% reversed ordering). If such a rule is applied to a reversed +% hook it behaves as if the rule is reversed (e.g., +% \texttt{after} becomes \texttt{before}) +% because those rules are applied first and then the order is reversed. +% \begin{macrocode} +\tl_new:c {g_@@_??_reversed_tl} +% \end{macrocode} +% \end{macro} +% +% \subsection{Setting rules for hooks code} +% +% \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. +% \begin{macrocode} +\cs_new_protected:Npn \hook_gset_rule:nnnn #1#2#3#4 + { + \@@_normalize_hook_rule_args:Nnnnn \@@_gset_rule:nnnn + {#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} +% \end{macrocode} +% Then we clear any previous relationship between both labels. +% \begin{macrocode} + \@@_rule_gclear:nnn {#1} {#2} {#4} +% \end{macrocode} +% Then we call the function to handle the given rule. Throw an error if the +% rule is invalid. +% \begin{macrocode} + \debug_suspend: + \cs_if_exist_use:cTF { @@_rule_#3_gset:nnn } + { + {#1} {#2} {#4} + \@@_update_hook_code:n {#1} + } + { \msg_error:nnnnnn { hooks } { unknown-rule } + {#1} {#2} {#3} {#4} } + \debug_resume: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_rule_before_gset:nnn, \@@_rule_after_gset:nnn, +% \@@_rule_<_gset:nnn, \@@_rule_>_gset:nnn} +% Then we add the new rule. We need to normalize the rules here to +% allow for faster processing later. Given a pair of labels +% $l_A$ and $l_B$, the rule $l_A>l_B$ is the same as $l_B<l_A$ +% only presented differently. But by normalizing the +% forms of the rule to a single representation, say, $l_B<l_A$, reduces +% the time spent looking for the rules later considerably. +% +% Here we do that normalization by using \cs[no-index]{(pdf)strcmp} to +% lexically sort labels $l_A$ and $l_B$ to a fixed order. This order +% is then enforced every time these two labels are used together. +% +% Here we use \cs{@@_label_pair:nn}~\Arg{hook}~\Arg{l_A}~\Arg{l_B} +% to build a string \texttt{$l_B$\string|$l_A$} with a fixed order, and +% use \cs{@@_label_ordered:nnTF} to apply the correct rule to the pair +% of labels, depending if it was sorted or not. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rule_before_gset:nnn #1#2#3 + { + \tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl } + { \@@_label_ordered:nnTF {#2} {#3} { < } { > } } + } +\cs_new_eq:cN { @@_rule_<_gset:nnn } \@@_rule_before_gset:nnn +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_rule_after_gset:nnn #1#2#3 + { + \tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#3} {#2} _tl } + { \@@_label_ordered:nnTF {#3} {#2} { < } { > } } + } +\cs_new_eq:cN { @@_rule_>_gset:nnn } \@@_rule_after_gset:nnn +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_rule_voids_gset:nnn} +% This rule removes (clears, actually) the code from label |#3| if +% label |#2| is in the hook |#1|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rule_voids_gset:nnn #1#2#3 + { + \tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl } + { \@@_label_ordered:nnTF {#2} {#3} { -> } { <- } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ +% \@@_rule_incompatible-error_gset:nnn, +% \@@_rule_incompatible-warning_gset:nnn, +% } +% These relations make an error/warning if labels |#2| and |#3| appear +% 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 } } +\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 } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_rule_unrelated_gset:nnn, \@@_rule_gclear:nnn} +% Undo a setting. \cs{@@_rule_unrelated_gset:nnn} doesn't need to do anything, +% since we use \cs{@@_rule_gclear:nnn} before setting any rule. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rule_unrelated_gset:nnn #1#2#3 { } +\cs_new_protected:Npn \@@_rule_gclear:nnn #1#2#3 + { \cs_undefine:c { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_label_pair:nn} +% Ensure that the lexically greater label comes first. +% \begin{macrocode} +\cs_new:Npn \@@_label_pair:nn #1#2 + { + \if_case:w \@@_str_compare:nn {#1} {#2} \exp_stop_f: + #1 | #1 % 0 + \or: #1 | #2 % +1 + \else: #2 | #1 % -1 + \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF]{\@@_label_ordered:nn} +% Check that labels |#1| and |#2| are in the correct order (as +% returned by \cs{@@_label_pair:nn}) and if so return true, else +% return false. +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_label_ordered:nn #1#2 { TF } + { + \if_int_compare:w \@@_str_compare:nn {#1} {#2} > 0 \exp_stop_f: + \prg_return_true: + \else + \prg_return_false: + \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_if_label_case:nnnnn} +% To avoid doing the string comparison twice in \cs{@@_initialize_single:NNNn} +% (once with \cs{str_if_eq:nn} and again with \cs{@@_label_ordered:nn}), +% we use a three-way branching macro that will compare |#1| and |#2| +% and expand to \cs{use_i:nnn} if they are equal, \cs{use_ii:nn} if +% |#1| is lexically greater, and \cs{use_iii:nn} otherwise. +% \begin{macrocode} +\cs_new:Npn \@@_if_label_case:nnnnn #1#2 + { + \cs:w use_ + \if_case:w \@@_str_compare:nn {#1} {#2} + i \or: ii \else: iii \fi: :nnn + \cs_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_update_hook_code:n} +% Before \verb=\begin{document}= this does nothing, in the body it +% reinitializes the hook code using the altered data. +% \begin{macrocode} +\cs_new_eq:NN \@@_update_hook_code:n \use_none:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_initialize_all:} +% Initialize all known hooks (at \verb=\begin{document}=), i.e., +% update the fast execution token lists to hold the necessary code +% in the right order. +% \begin{macrocode} +\cs_new_protected:Npn \@@_initialize_all: { +% \end{macrocode} +% First we change \cs{@@_update_hook_code:n} which so far was a +% no-op to now initialize one hook. This way any later updates to +% the hook will run that code and also update the execution token +% list. +% \begin{macrocode} + \cs_gset_eq:NN \@@_update_hook_code:n \@@_initialize_hook_code:n +% \end{macrocode} +% Now we loop over all hooks that have been defined and update each +% of them. +% \begin{macrocode} + \@@_debug:n { \prop_gclear:N \g_@@_used_prop } + \seq_map_inline:Nn \g_@@_all_seq + { + \@@_update_hook_code:n {##1} + } +% \end{macrocode} +% If we are debugging we show results hook by hook for all hooks +% that have data. +% \begin{macrocode} + \@@_debug:n + { \iow_term:x{^^JAll~ initialized~ (non-empty)~ hooks:} + \prop_map_inline:Nn \g_@@_used_prop + { \iow_term:x{^^J~ ##1~ ->~ + \exp_not:v {@@~##1}~ } + } + } +% \end{macrocode} +% After all hooks are initialized we change the ``use'' to just +% call the hook code and not initialize it (as it was done in the +% preamble. +% \begin{macrocode} + \cs_gset_eq:NN \hook_use:n \@@_use_initialized:n + \cs_gset_eq:NN \@@_preamble_hook:n \use_none:n +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_initialize_hook_code:n} +% Initializing or reinitializing the fast execution hook code. In +% the preamble this is selectively done in case a hook gets used +% and at \verb=\begin{document}= this is done for all hooks and +% afterwards only if the hook code changes. +% \begin{macrocode} +\cs_new_protected:Npn \@@_initialize_hook_code:n #1 + { + \debug_suspend: + \@@_debug:n{ \iow_term:x{^^JUpdate~ code~ for~ hook~ + '#1' \on@line :^^J} } +% \end{macrocode} +% This does the sorting and the updates. +% First thing we do is to check if a legacy hook macro exists and +% if so we add it to the hook under the label \texttt{legacy}. This +% might make the hook non-empty so we have to do this before +% the then following test. +% \begin{macrocode} + \@@_include_legacy_code_chunk:n {#1} +% \end{macrocode} +% 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 next +% code. If there are code chunks we call +% \cs{@@_initialize_single:NNNn} 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} + { + \prop_if_empty:cTF {g_@@_#1_code_prop} + { \tl_gset:co { @@~#1 } + { \cs:w @@_next~#1 \cs_end: } } + { +% \end{macrocode} +% By default the algorithm sorts the code chunks and then saves the +% result in a token list for fast execution by adding the code one +% after another using \cs{tl_gput_right:NV}. When we sort code for +% a reversed hook, all we have to do is to add the code chunks in +% the opposite order into the token list. So all we have to do +% in preparation is to change two definitions used later on. +% \begin{macrocode} + \@@_if_reversed:nTF {#1} + { \cs_set_eq:NN \@@_tl_gput:NV \tl_gput_left:NV + \cs_set_eq:NN \@@_clist_gput:NV \clist_gput_left:NV } + { \cs_set_eq:NN \@@_tl_gput:NV \tl_gput_right:NV + \cs_set_eq:NN \@@_clist_gput:NV \clist_gput_right:NV } +% \end{macrocode} +% +% When sorting, some relations (namely \verb|voids|) need to +% act destructively on the code property lists to remove code that +% shouldn't appear in the sorted hook token list, so we temporarily +% save the old code property list so that it can be restored later. +% \begin{macrocode} + \prop_set_eq:Nc \l_@@_work_prop { g_@@_#1_code_prop } + \@@_initialize_single:cccn + { @@~#1 } { @@_next~#1 } + { g_@@_#1_labels_clist } {#1} +% \end{macrocode} +% For debug display we want to keep track of those hooks that +% actually got code added to them, so we record that in plist. We +% use a plist to ensure that we record each hook name only once, +% i.e., we are only interested in storing the keys and the value is +% arbitrary. +% \begin{macrocode} + \@@_debug:n{ \exp_args:NNx \prop_gput:Nnn + \g_@@_used_prop {#1}{} } + } + } + \debug_resume: + } +% \end{macrocode} +% \end{macro} +% +% +% \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} +% \begin{macrocode} +\cs_new:Npn \@@_tl_csname:n #1 { l_@@_label_#1_tl } +\cs_new:Npn \@@_seq_csname:n #1 { l_@@_label_#1_seq } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\l_@@_labels_seq,\l_@@_labels_int,\l_@@_front_tl, +% \l_@@_rear_tl,\l_@@_label_0_tl} +% +% For the sorting I am basically implementing Knuth's algorithm for +% topological sorting as given in TAOCP volume 1 pages 263--266. +% For this algorithm we need a number of local variables: +% \begin{itemize} +% \item +% List of labels used in the current hook to label code chunks: +% \begin{macrocode} +\seq_new:N \l_@@_labels_seq +% \end{macrocode} +% \item +% Number of labels used in the current hook. In Knuth's algorithm +% this is called $N$: +% \begin{macrocode} +\int_new:N \l_@@_labels_int +% \end{macrocode} +% \item +% The sorted code list to be build is managed using two pointers +% one to the front of the queue and one to the rear. We model this +% using token list pointers. Knuth calls them $F$ and $R$: +% \begin{macrocode} +\tl_new:N \l_@@_front_tl +\tl_new:N \l_@@_rear_tl +% \end{macrocode} +% \item +% The data for the start of the queue is kept in this token list, +% it corresponds to what Don calls \texttt{QLINK[0]} but since we +% aren't manipulating individual words in memory it is slightly +% differently done: +% \begin{macrocode} +\tl_new:c { \@@_tl_csname:n { 0 } } +% \end{macrocode} +% +% \end{itemize} +% \end{macro} +% +% +% \begin{macro}{\@@_initialize_single:NNNn,\@@_initialize_single:cccn} +% +% \cs{@@_initialize_single:NNNn} implements the sorting of the code +% chunks for a hook and saves the result in the token list for fast +% execution (\verb=#3=). The arguments are \meta{hook-code-plist}, +% \meta{hook-code-tl}, \meta{hook-next-code-tl}, +% \meta{hook-ordered-labels-clist} and \meta{hook-name} (the latter +% is only used for debugging---the \meta{hook-rule-plist} is accessed +% using the \meta{hook-name}). +% +% The additional complexity compared to Don's algorithm is that we +% do not use simple positive integers but have arbitrary +% alphanumeric labels. As usual Don's data structures are chosen in +% 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} +% \begin{macrocode} +\cs_new_protected:Npn \@@_initialize_single:NNNn #1#2#3#4 + { +% \end{macrocode} +% Step T1: Initialize the data structure \ldots +% \begin{macrocode} + \seq_clear:N \l_@@_labels_seq + \int_zero:N \l_@@_labels_int +% \end{macrocode} +% +% Store the name of the hook: +% \begin{macrocode} + \tl_set:Nn \l_@@_cur_hook_tl {#4} +% \end{macrocode} +% +% We loop over the property list holding the code and record all +% labels listed there. Only rules for those labels are of interest +% to us. While we are at it we count them (which gives us the $N$ +% in Knuth's algorithm. The prefix |label_| is added to the variables +% to ensure that labels named |front|, |rear|, |labels|, or |return| +% don't interact with our code. +% \begin{macrocode} + \prop_map_inline:Nn \l_@@_work_prop + { + \int_incr:N \l_@@_labels_int + \seq_put_right:Nn \l_@@_labels_seq {##1} + \tl_set:cn { \@@_tl_csname:n {##1} }{0} + \seq_clear_new:c { \@@_seq_csname:n {##1} } + } +% \end{macrocode} +% Steps T2 and T3: Sort the relevant rules into the data structure\ldots +% +% This loop constitutes a square matrix of the labels in +% \cs{l_@@_work_prop} in the +% vertical and the horizontal directions. However since the rule +% $l_A\meta{rel}l_B$ is the same as $l_B\meta{rel}^{-1}l_A$ we can cut +% the loop short at the diagonal of the matrix (\emph{i.e.}, when +% both labels are equal), saving a good amount of time. The way the +% rules were set up (see the implementation of \cs{@@_rule_before_gset:nnn} +% above) ensures that we have no rule in the ignored side of the +% matrix, and all rules are seen. The rules are applied in +% \cs{@@_apply_label_pair:nnn}, which takes the properly-ordered pair +% of labels as argument. +% \begin{macrocode} + \prop_map_inline:Nn \l_@@_work_prop + { + \prop_map_inline:Nn \l_@@_work_prop + { + \@@_if_label_case:nnnnn {##1} {####1} + { \prop_map_break: } + { \@@_apply_label_pair:nnn {##1} {####1} } + { \@@_apply_label_pair:nnn {####1} {##1} } + {#4} + } + } +% \end{macrocode} +% Take a breath and take a look at the data structures that have +% been set up: +% \begin{macrocode} + \@@_debug:n { \@@_debug_label_data:N \l_@@_work_prop } +% \end{macrocode} +% +% +% Step T4: +% \begin{macrocode} + \tl_set:Nn \l_@@_rear_tl { 0 } + \tl_set:cn { \@@_tl_csname:n { 0 } } { 0 } + \seq_map_inline:Nn \l_@@_labels_seq + { + \int_compare:nNnT { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0 + { + \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } }{##1} + \tl_set:Nn \l_@@_rear_tl {##1} + } + } + \tl_set_eq:Nc \l_@@_front_tl { \@@_tl_csname:n { 0 } } +% \end{macrocode} +% +% \begin{macrocode} + \tl_gclear:N #1 + \clist_gclear:N #3 +% \end{macrocode} +% +% The whole loop combines steps T5--T7: +% \begin{macrocode} + \bool_while_do:nn { ! \str_if_eq_p:Vn \l_@@_front_tl { 0 } } + { +% \end{macrocode} +% This part is step T5: +% \begin{macrocode} + \int_decr:N \l_@@_labels_int + \prop_get:NVN \l_@@_work_prop \l_@@_front_tl \l_@@_return_tl + \@@_tl_gput:NV #1 \l_@@_return_tl +% \end{macrocode} +% +% \begin{macrocode} + \@@_clist_gput:NV #3 \l_@@_front_tl + \@@_debug:n{ \iow_term:x{Handled~ code~ for~ \l_@@_front_tl} } +% \end{macrocode} +% +% This is step T6 except that we don't use a pointer $P$ to move +% through the successors, but instead use \verb=##1= of the mapping +% function. +% \begin{macrocode} + \seq_map_inline:cn { \@@_seq_csname:n { \l_@@_front_tl } } + { + \tl_set:cx { \@@_tl_csname:n {##1} } + { \int_eval:n + { \cs:w \@@_tl_csname:n {##1} \cs_end: - 1 } + } + \int_compare:nNnT + { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0 + { + \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } } {##1} + \tl_set:Nn \l_@@_rear_tl {##1} + } + } +% \end{macrocode} +% and step T7: +% \begin{macrocode} + \tl_set_eq:Nc \l_@@_front_tl + { \@@_tl_csname:n { \l_@@_front_tl } } +% \end{macrocode} +% +% This is step T8: If we haven't moved the code for all labels +% (i.e., if \cs{l_@@_labels_int} is still greater than zero) we +% have a loop and our partial order can't be flattened out. +% \begin{macrocode} + } + \int_compare:nNnF \l_@@_labels_int = 0 + { + \iow_term:x{====================} + \iow_term:x{Error:~ label~ rules~ are~ incompatible:} +% \end{macrocode} +% +% This is not really the information one needs in the error case +% but will do for now \ldots \fmi{fix} +% \begin{macrocode} + \@@_debug_label_data:N \l_@@_work_prop + \iow_term:x{====================} + } +% \end{macrocode} +% After we have added all hook code to \verb=#1= we finish it off +% with adding extra code for a one time execution. That is stored +% in \verb=#2= but is normally empty. +% \begin{macrocode} + \tl_gput_right:Nn #1 {#2} + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_generate_variant:Nn \@@_initialize_single:NNNn {ccc} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_tl_gput:NV,\@@_clist_gput:NV} +% These append either on the right (normal hook) or on the left +% (reversed hook). This is setup up in +% \cs{@@_initialize_hook_code:n}, elsewhere their behavior is undefined. +% \begin{macrocode} +\cs_new:Npn \@@_tl_gput:NV {\ERROR} +\cs_new:Npn \@@_clist_gput:NV {\ERROR} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_apply_label_pair:nnn,\@@_label_if_exist_apply:nnnF} +% +% This is the payload of steps T2 and T3 executed in the loop described +% above. This macro assumes |#1| and |#2| are ordered, which means that +% any rule pertaining the pair |#1| and |#2| is +% \cs{g_@@_\meta{hook}_rule_\#1\string|\#2_tl}, and not +% \cs{g_@@_\meta{hook}_rule_\#2\string|\#1_tl}. This also saves a great deal +% of time since we only need to check the order of the labels once. +% +% The arguments here are \meta{label1}, \meta{label2}, \meta{hook}, and +% \meta{hook-code-plist}. We are about to apply the next rule and +% enter it into the data structure. \cs{@@_apply_label_pair:nnn} will +% just call \cs{@@_label_if_exist_apply:nnnF} for the \meta{hook}, and +% if no rule is found, also try the \meta{hook} name \verb=??= +% denoting a default hook rule. +% +% \cs{@@_label_if_exist_apply:nnnF} will check if the rule exists for +% the given hook, and if so call \cs{@@_apply_rule:nnn}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_apply_label_pair:nnn #1#2#3 + { +% \end{macrocode} +% Extra complication: as we use default rules and local hook specific +% rules we first have to check if there is a local rule and if that +% exist use it. Otherwise check if there is a default rule and use +% that. +% \begin{macrocode} + \@@_label_if_exist_apply:nnnF {#1} {#2} {#3} + { +% \end{macrocode} +% If there is no hook-specific rule we check for a default one and +% use that if it exists. +% \begin{macrocode} + \@@_label_if_exist_apply:nnnF {#1} {#2} { ?? } { } + } + } +\cs_new_protected:Npn \@@_label_if_exist_apply:nnnF #1#2#3 + { + \if_cs_exist:w g_@@_ #3 _rule_ #1 | #2 _tl \cs_end: +% \end{macrocode} +% What to do precisely depends on the type of rule we have +% encountered. If it is a \texttt{before} rule it will be handled by the +% algorithm but other types need to be managed differently. All +% this is done in \cs{@@_apply_rule:nnnN}. +% \begin{macrocode} + \@@_apply_rule:nnn {#1} {#2} {#3} + \exp_after:wN \use_none:n + \else: + \use:nn + \fi: + } +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{\@@_apply_rule:nnn} +% This is the code executed in steps T2 and T3 while looping through +% the matrix This is part of step T3. We are about to apply the next +% rule and enter it into the data structure. The arguments are +% \meta{label1}, \meta{label2}, \meta{hook-name}, and \meta{hook-code-plist}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_apply_rule:nnn #1#2#3 + { + \cs:w @@_apply_ + \cs:w g_@@_#3_reversed_tl \cs_end: rule_ + \cs:w g_@@_ #3 _rule_ #1 | #2 _tl \cs_end: :nnn \cs_end: + {#1} {#2} {#3} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_apply_rule_<:nnn,\@@_apply_rule_>:nnn} +% The most common cases are \texttt{\string<} and \texttt{\string>} so we handle +% that first. They are relations $\prec$ and $\succ$ in TAOCP, and +% they dictate sorting. +% \begin{macrocode} +\cs_new_protected:cpn { @@_apply_rule_<:nnn } #1#2#3 + { + \@@_debug:n { \@@_msg_pair_found:nnn {#1} {#2} {#3} } + \tl_set:cx { \@@_tl_csname:n {#2} } + { \int_eval:n{ \cs:w \@@_tl_csname:n {#2} \cs_end: + 1 } } + \seq_put_right:cn{ \@@_seq_csname:n {#1} }{#2} + } +\cs_new_protected:cpn { @@_apply_rule_>:nnn } #1#2#3 + { + \@@_debug:n { \@@_msg_pair_found:nnn {#1} {#2} {#3} } + \tl_set:cx { \@@_tl_csname:n {#1} } + { \int_eval:n{ \cs:w \@@_tl_csname:n {#1} \cs_end: + 1 } } + \seq_put_right:cn{ \@@_seq_csname:n {#2} }{#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_apply_rule_xE:nnn,\@@_apply_rule_xW:nnn} +% These relations make two labels incompatible within a hook. +% |xE| makes raises an error if the labels are found in the same +% hook, and |xW| makes it a warning. +% \begin{macrocode} +\cs_new_protected:cpn { @@_apply_rule_xE:nnn } #1#2#3 + { + \@@_debug:n { \@@_msg_pair_found:nnn {#1} {#2} {#3} } + \msg_error:nnnnnn { hooks } { labels-incompatible } + {#1} {#2} {#3} { 1 } + \use:c { @@_apply_rule_->:nnn } {#1} {#2} {#3} + \use:c { @@_apply_rule_<-:nnn } {#1} {#2} {#3} + } +\cs_new_protected:cpn { @@_apply_rule_xW:nnn } #1#2#3 + { + \@@_debug:n { \@@_msg_pair_found:nnn {#1} {#2} {#3} } + \msg_warning:nnnnnn { hooks } { labels-incompatible } + {#1} {#2} {#3} { 0 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_apply_rule_->:nnn,\@@_apply_rule_<-:nnn} +% If we see \texttt{\detokenize{->}} we have to drop code for label +% \verb=#3= and carry on. We could do a little better and drop +% everything for that label since it doesn't matter where we sort +% in the empty code. However that would complicate the algorithm a +% lot with little gain.\footnote{This also hase the advantage that +% the result of the sorting doesn't change which might otherwise +% (for unrelated chunks) if we aren't careful.} So we still +% unnecessarily try to sort it in and depending on the rules that +% might result in a loop that is otherwise resolved. If that turns +% out to be a real issue, we can improve the code. +% +% Here the code is removed from \cs{l_@@_cur_hook_tl} rather than +% \verb=#3= because the latter may be \verb=??=, and the default +% hook doesn't store any code. Removing from \cs{l_@@_cur_hook_tl} +% makes default rules \verb=->= and \verb=<-= work properly. +% \begin{macrocode} +\cs_new_protected:cpn { @@_apply_rule_->:nnn } #1#2#3 + { + \@@_debug:n + { + \@@_msg_pair_found:nnn {#1} {#2} {#3} + \iow_term:x{--->~ Drop~ '#2'~ code~ from~ + \iow_char:N \\ g_@@_ \l_@@_cur_hook_tl _code_prop ~ + because~ of~ '#1' } + } + \prop_put:Nnn \l_@@_work_prop {#2} { } + } +\cs_new_protected:cpn { @@_apply_rule_<-:nnn } #1#2#3 + { + \@@_debug:n + { + \@@_msg_pair_found:nnn {#1} {#2} {#3} + \iow_term:x{--->~ Drop~ '#1'~ code~ from~ + \iow_char:N \\ g_@@_ \l_@@_cur_hook_tl _code_prop ~ + because~ of~ '#2' } + } + \prop_put:Nnn \l_@@_work_prop {#1} { } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ +% \@@_apply_-rule_<:nnn, +% \@@_apply_-rule_>:nnn, +% \@@_apply_-rule_<-:nnn, +% \@@_apply_-rule_->:nnn, +% \@@_apply_-rule_x:nnn, +% } +% Reversed rules. +% \begin{macrocode} +\cs_new_eq:cc { @@_apply_-rule_<:nnn } { @@_apply_rule_>:nnn } +\cs_new_eq:cc { @@_apply_-rule_>:nnn } { @@_apply_rule_<:nnn } +\cs_new_eq:cc { @@_apply_-rule_<-:nnn } { @@_apply_rule_<-:nnn } +\cs_new_eq:cc { @@_apply_-rule_->:nnn } { @@_apply_rule_->:nnn } +\cs_new_eq:cc { @@_apply_-rule_xE:nnn } { @@_apply_rule_xE:nnn } +\cs_new_eq:cc { @@_apply_-rule_xW:nnn } { @@_apply_rule_xW:nnn } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_msg_pair_found:nnn} +% A macro to avoid moving this many tokens around. +% \begin{macrocode} +\cs_new_protected:Npn \@@_msg_pair_found:nnn #1#2#3 + { + \iow_term:x{~ \str_if_eq:nnTF {#3} {??} {default} {~normal} ~ + rule~ \@@_label_pair:nn {#1} {#2}:~ + \use:c { g_@@_#3_rule_ \@@_label_pair:nn {#1} {#2} _tl } ~ + found} + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_debug_label_data:N} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_debug_label_data:N #1 { + \iow_term:x{Code~ labels~ for~ sorting:} + \iow_term:x{~ \seq_use:Nnnn\l_@@_labels_seq {~and~}{,~}{~and~} } + \iow_term:x{^^J Data~ structure~ for~ label~ rules:} + \prop_map_inline:Nn #1 + { + \iow_term:x{~ ##1~ =~ \tl_use:c{ \@@_tl_csname:n {##1} }~ ->~ + \seq_use:cnnn{ \@@_seq_csname:n {##1} }{~->~}{~->~}{~->~} + } + } + \iow_term:x{} +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\hook_show:n,\hook_log:n} +% \begin{macro}{\@@_log_line:x,\@@_log_line_indent:x} +% \begin{macro}{\@@_log:nN} +% This writes out information about the hook given in its argument +% onto the \texttt{.log} file and the terminal, if \cs{show_hook:n} is +% used. Internally both share the same structure, except that at the +% end, \cs{hook_show:n} triggers \TeX's prompt. +% \begin{macrocode} +\cs_new_protected:Npn \hook_log:n #1 + { + \cs_set_eq:NN \@@_log_cmd:x \iow_log:x + \@@_normalize_hook_args:Nn \@@_log:nN {#1} \tl_log:x + } +\cs_new_protected:Npn \hook_show:n #1 + { + \cs_set_eq:NN \@@_log_cmd:x \iow_term:x + \@@_normalize_hook_args:Nn \@@_log:nN {#1} \tl_show:x + } +\cs_new_protected:Npn \@@_log_line:x #1 + { \@@_log_cmd:x { >~#1 } } +\cs_new_protected:Npn \@@_log_line_indent:x #1 + { \@@_log_cmd:x { >~\@spaces #1 } } +\cs_new_protected:Npn \@@_log:nN #1 #2 + { + \@@_preamble_hook:n {#1} + \iow_term:x { ^^J ->~The~hook~'#1': } +% \end{macrocode} +% +% \begin{macrocode} + \hook_if_exist:nF {#1} + { \@@_log_line:x { is~not~declared! } } + \@@_if_exist:nTF {#1} + { + \@@_log_line:x { Code~chunks: } + \prop_if_empty:cTF { g_@@_#1_code_prop } + { \@@_log_line_indent:x { --- } } + { + \prop_map_inline:cn { g_@@_#1_code_prop } + { \@@_log_line_indent:x { ##1~->~\tl_to_str:n {##2} } } + } +% \end{macrocode} +% +% \begin{macrocode} + \@@_log_line:x { Extra~code~for~next~invocation:} + \@@_log_line_indent:x + { + \tl_if_empty:cTF { @@_next~#1 } + { --- } +% \end{macrocode} +% +% If the token list is not empty we want to display it but without +% the first tokens (the code to clear itself) so we call a helper +% command to get rid of them. +% \begin{macrocode} + { ->~ \exp_args:Nv \@@_log_next_code:n { @@_next~#1 } } + } +% \end{macrocode} +% +% Loop through the rules in a hook and for every rule found, print it. +% If no rule is there, print |---|. The boolean \cs{l_@@_tmpa_bool} +% here indicates if the hook has no rules. +% \begin{macrocode} + \@@_log_line:x { Rules: } + \bool_set_true:N \l_@@_tmpa_bool + \@@_list_rules:nn {#1} + { + \bool_set_false:N \l_@@_tmpa_bool + \@@_log_line_indent:x + { + ##2~ with~ + \str_if_eq:nnT {##3} {??} { default~ } + relation~ ##1 + } + } + \bool_if:NT \l_@@_tmpa_bool + { \@@_log_line_indent:x { --- } } +% \end{macrocode} +% +% When the hook is declared (that is, the sorting algorithm is applied +% to that hook) and not empty +% \begin{macrocode} + \bool_lazy_and:nnTF + { \hook_if_exist_p:n {#1} } + { ! \hook_if_empty_p:n {#1} } + { + \@@_log_line:x + { + Execution~order + \bool_if:NTF \l_@@_tmpa_bool + { \@@_if_reversed:nT {#1} { ~(after~reversal) } } + { ~(after~ + \@@_if_reversed:nT {#1} { reversal~and~ } + applying~rules) + } : + } + #2 % \tl_show:n + { + \@spaces + \clist_if_empty:cTF { g_@@_#1_labels_clist } + { --- } + { \clist_use:cn {g_@@_#1_labels_clist} { ,~ } } + } + } + { + #2 + { + Hook~ \hook_if_exist:nTF {#1} + {code~pool~empty} {not~declared} + } + } + } + { #2 { The~hook~is~empty. } } + } +% \end{macrocode} +% +% \begin{macro}{\@@_log_next_code:n} +% To display the code for next invocation only (i.e., from +% \cs{AddToHookNext} we have to remove the first two tokens at the +% front which are \cs{tl_gclear:N} and the token list to clear. +% \begin{macrocode} +\cs_new:Npn \@@_log_next_code:n #1 + { \exp_args:No \tl_to_str:n { \use_none:nn #1 } } +% \end{macrocode} +% \end{macro} +% +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_list_rules:nn} +% \begin{macro}{\@@_list_one_rule:nnn,\@@_list_if_rule_exists:nnnF} +% This macro takes a \meta{hook} and an \meta{inline function} and +% loops through each pair of \meta{labels} in the \meta{hook}, and if +% there is a relation between this pair of \meta{labels}, the +% \meta{inline function} is executed with |#1|${}={}$\meta{relation}, +% |#2|${}={}$\meta{label_1}\verb=|=\meta{label_2}, +% and |#3|${}={}$\meta{hook} (the latter may be the argument |#1| to +% \cs{@@_list_rules:nn}, or |??| if it is a default rule). +% \begin{macrocode} +\cs_new_protected:Npn \@@_list_rules:nn #1 #2 + { + \cs_set_protected:Npn \@@_tmp:w ##1 ##2 ##3 {#2} + \prop_map_inline:cn { g_@@_#1_code_prop } + { + \prop_map_inline:cn { g_@@_#1_code_prop } + { + \@@_if_label_case:nnnnn {##1} {####1} + { \prop_map_break: } + { \@@_list_one_rule:nnn {##1} {####1} } + { \@@_list_one_rule:nnn {####1} {##1} } + {#1} + } + } + } +% \end{macrocode} +% +% These two are quite similar to \cs{@@_apply_label_pair:nnn} and +% \cs{@@_label_if_exist_apply:nnnF}, respectively, but rather than +% applying the rule, they pass it to the \meta{inline function}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_list_one_rule:nnn #1#2#3 + { + \@@_list_if_rule_exists:nnnF {#1} {#2} {#3} { } + { \@@_list_if_rule_exists:nnnF {#1} {#2} { ?? } { } } + } +\cs_new_protected:Npn \@@_list_if_rule_exists:nnnF #1#2#3 + { + \if_cs_exist:w g_@@_ #3 _rule_ #1 | #2 _tl \cs_end: + \exp_args:Nv \@@_tmp:w + { g_@@_ #3 _rule_ #1 | #2 _tl } { #1 | #2 } {#3} + \fi: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_debug_print_rules:n} +% A shorthand for debugging that prints similar to \cs{prop_show:N}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_debug_print_rules:n #1 + { + \iow_term:n { The~hook~#1~contains~the~rules: } + \cs_set_protected:Npn \@@_tmp:w ##1 + { + \@@_list_rules:nn {#1} + { + \iow_term:x + { + > ##1 {####2} ##1 => ##1 {####1} + \str_if_eq:nnT {####3} {??} { ~(default) } + } + } + } + \exp_args:No \@@_tmp:w { \use:nn { ~ } { ~ } } + } +% \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} } +\cs_new_protected:Npn \@@_gput_next_code:nn #1 #2 + { + \debug_suspend: + \@@_declare:n {#1} + \hook_if_exist:nTF {#1} + { \@@_gput_next_do:nn {#1} {#2} } + { \@@_try_declaring_generic_next_hook:nn {#1} {#2} } + \debug_resume: + } +\cs_new_protected:Npn \@@_gput_next_do:nn #1 + { + \exp_args:Nc \@@_gput_next_do:Nnn + { @@_next~#1 } {#1} + } +% \end{macrocode} +% First check if the ``next code'' token list is empty: if so we need +% to add a \cs{tl_gclear:c} to clear it, so the code lasts for one +% usage only. The token list is cleared early so that nested usages +% don't get lost. \cs{tl_gclear:c} is used instead of +% \cs{tl_gclear:N} in case the hook is used in an expansion-only +% context, so the token list doesn't expand before \cs{tl_gclear:N}: +% that would make an infinite loop. Also in case the main code token +% list is empty, the hook code has to be updated to add the next +% execution token list. +% \begin{macrocode} +\cs_new_protected:Npn \@@_gput_next_do:Nnn #1 #2 + { + \tl_if_empty:cT { @@~#2 } + { \@@_update_hook_code:n {#2} } + \tl_if_empty:NT #1 + { \tl_gset:Nn #1 { \@@_clear_next:n {#2} } } + \tl_gput_right:Nn #1 + } +\cs_new_protected:Npn \@@_clear_next:n #1 + { \cs_gset_eq:cN { @@_next~#1 } \c_empty_tl } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \subsection{Using the hook} +% +% \begin{macro}{\hook_use:n} +% \begin{macro}[EXP]{\@@_use_initialized:n} +% \begin{macro}{\@@_use_undefined:w,\@@_use_end:} +% \begin{macro}{\@@_preamble_hook:n} +% \cs{hook_use:n} as defined here is used in the preamble, where +% hooks aren't initialized by default. \cs{@@_use_initialized:n} is +% also defined, which is the non-\tn{protected} version for use within +% the document. Their definition is identical, except for the +% \cs{@@_preamble_hook:n} (which wouldn't hurt in the expandable +% version, but it would be an unnecessary extra expansion). +% +% \cs{@@_use_initialized:n} holds the expandable definition while in +% the preamble. \cs{@@_preamble_hook:n} initializes the hook in the +% preamble, and is redefined to \cs{use_none:n} at |\begin{document}|. +% +% Both versions do the same internally: check if the hook exist as +% given, and if so use it as quickly as possible. If it doesn't +% exist, the a call to \cs{@@_use:wn} checks for file hooks. +% +% At |\begin{document}|, all hooks are initialized, and any change in +% 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 +% csname. In contrast to the \TeX{} low-level +% \verb=\csname ...\endcsname= construct \cs{tl_if_exist:c} is +% careful to avoid this. +% \begin{macrocode} +\cs_new_protected:Npn \hook_use:n #1 + { + \tl_if_exist:cTF { @@~#1 } + { + \@@_preamble_hook:n {#1} + \cs:w @@~#1 \cs_end: + } + { \@@_use:wn #1 / \s_@@_mark {#1} } + } +\cs_new:Npn \@@_use_initialized:n #1 + { + \if_cs_exist:w @@~#1 \cs_end: + \else: + \@@_use_undefined:w + \fi: + \cs:w @@~#1 \@@_use_end: + } +\cs_new:Npn \@@_use_undefined:w #1 #2 @@~#3 \@@_use_end: + { + #1 % fi + \@@_use:wn #3 / \s_@@_mark {#3} + } +\cs_new_protected:Npn \@@_preamble_hook:n #1 + { \@@_initialize_hook_code:n {#1} } +\cs_new_eq:NN \@@_use_end: \cs_end: +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_use:wn} +% \begin{macro}{\@@_try_file_hook:n,\@@_if_exist_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, +% and checks that the current hook is a file-specific hook using +% \cs{@@_if_file_hook:wTF}. If it's not, then it's a generic |file/| +% hook and is used if it exist. +% +% 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{@@_preamble_hook:n} if so, then uses the hook. +% \begin{macrocode} +\cs_new:Npn \@@_use:wn #1 / #2 \s_@@_mark #3 + { + \str_if_eq:nnTF {#1} { file } + { \@@_try_file_hook:n {#3} } + { } % Hook doesn't exist + } +\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 \@@_file_hook_normalize:n {#1} } + } + { \@@_if_exist_use:n {#1} } % file/ generic hook (e.g. file/before) + } +\cs_new_protected:Npn \@@_if_exist_use:n #1 + { + \tl_if_exist:cT { @@~#1 } + { + \@@_preamble_hook:n {#1} + \cs:w @@~#1 \cs_end: + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\hook_use_once:n} +% For hooks that can and should be used only once we have a special +% use command that remembers the hook name in +% \cs{g_@@_execute_immediately_prop}. This has the effect that any +% further code added to the hook is executed immediately rather +% than stored in the hook. +% +% The code needs some gymnastics to prevent space trimming from the +% 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 + { + \tl_if_exist:cT { @@~#1 } + { + \tl_set:Nn \l_@@_return_tl {#1} + \@@_normalize_hook_args:Nn \@@_use_once_store:n + { \l_@@_return_tl } + \hook_use:n {#1} + } + } +\cs_new_protected:Npn \@@_use_once_store:n #1 + { \prop_gput:Nnn \g_@@_execute_immediately_prop {#1} { } } +% \end{macrocode} +% \end{macro} +% +% \subsection{Querying a hook} +% +% Simpler data types, like token lists, have three possible states; they +% can exist and be empty, exist and be non-empty, and they may not +% 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. +% 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). +% +% 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 +% (it may happen that a package $A$ defines a hook \hook{foo}, but +% it's loaded after package $B$, which adds some code to that hook. +% 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. +% +% \begin{macro}[pTF]{\hook_if_empty:n} +% Test if a hook is empty (that is, no code was added to that hook). +% A hook being empty means that \emph{both} its +% \cs[no-index]{g_@@_\meta{hook}_code_prop} and its +% \cs[no-index]{@@_next~\meta{hook}} are empty. +% \begin{macrocode} +\prg_new_conditional:Npnn \hook_if_empty:n #1 { p , T , F , TF } + { + \@@_if_exist:nTF {#1} + { + \bool_lazy_and:nnTF + { \prop_if_empty_p:c { g_@@_#1_code_prop } } + { \tl_if_empty_p:c { @@_next~#1 } } + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_true: } + } +% \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 +% 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 +% because often it is necessary to add code to a hook without knowing +% 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 } + { + \tl_if_exist:cTF { @@~#1 } + { \prg_return_true: } + { \prg_return_false: } + } +% \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 +% (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 } + { + \prop_if_exist:cTF { g_@@_#1_code_prop } + { \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. +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_if_reversed:n #1 { p , T , F , TF } + { + \if_int_compare:w \cs:w g_@@_#1_reversed_tl \cs_end: 1 < 0 \exp_stop_f: + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { hooks } { labels-incompatible } + { + 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. } + } + { LaTeX~found~two~incompatible~labels~in~the~same~hook.~ + This~indicates~an~incompatibility~between~packages. } +% \end{macrocode} +% +% \begin{macrocode} +\msg_new:nnnn { hooks } { exists } + { 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:nnn { hooks } { empty-label } + { Empty~code~label~\msg_line_context:.~Using~`#1'~instead. } +% \end{macrocode} +% +% \begin{macrocode} +\msg_new:nnnn { hooks } { unknown-rule } + { 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'. + } +% \end{macrocode} +% +% \begin{macrocode} +\msg_new:nnn { hooks } { should-not-happen } + { + ERROR!~This~should~not~happen.~#1 \\ + Please~report~at~https://github.com/latex3/latex2e. + } +% \end{macrocode} +% +% \subsection{\LaTeXe{} package interface commands} +% +% +% +% \begin{macro}{\NewHook,\NewReversedHook,\NewMirroredHookPair} +% Declaring new hooks \ldots +% \begin{macrocode} +\NewDocumentCommand \NewHook { m }{ \hook_new:n {#1} } +\NewDocumentCommand \NewReversedHook { m }{ \hook_new_reversed:n {#1} } +\NewDocumentCommand \NewMirroredHookPair { mm }{ \hook_new_pair:nn {#1}{#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\AddToHook} +% +% \begin{macrocode} +\NewDocumentCommand \AddToHook { m o +m } + { \hook_gput_code:nnn {#1} {#2} {#3} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\AddToHookNext} +% +% \begin{macrocode} +\NewDocumentCommand \AddToHookNext { m +m } + { \hook_gput_next_code:nn {#1} {#2} } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\RemoveFromHook} +% +% \begin{macrocode} +\NewDocumentCommand \RemoveFromHook { m o } + { \hook_gremove_code:nn {#1} {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DeclareDefaultHookLabel} +% \begin{macro}{\@@_curr_name_push:n,\@@_curr_name_pop:} +% The token list \cs{g_@@_hook_curr_name_tl} stores the name of the +% current package/file to be used as label for hooks. +% Providing a consistent interface is tricky, because packages can +% be loaded within packages, and some packages may not use +% \cs{DeclareDefaultHookLabel} to change the default label (in which case +% \cs{@currname} is used, if set). +% +% To pull that off, we keep a stack that contains the default label +% for each level of input. The bottom of the stack contains the +% default label for the top-level. Since the string \verb|top-level| +% is hardcoded, here this item of the stack is empty. Also, since +% we're in an input level, add \verb|lthooks| to the stack as well. +% This stack should never go empty. An empty entry is added to the +% stack to account for the \verb|top-level|. The item is empty so +% that the hard-coded default is used, but a call to +% \cs{DeclareDefaultHookLabel} will change it if needed. +% \begin{macrocode} +\seq_gpush:Nn \g_@@_name_stack_seq { } +% \end{macrocode} +% +% +% Two commands keep track of the stack: when a file is input, +% \cs{@@_curr_name_push:n} pushes an (empty by default) label to the +% stack: +% \begin{macrocode} +\cs_new_protected:Npn \@@_curr_name_push:n #1 + { + \seq_gpush:Nn \g_@@_name_stack_seq {#1} + \tl_gset:Nn \g_@@_hook_curr_name_tl {#1} + } +% +% \end{macrocode} +% and when an input is over, the topmost item of the stack is popped, +% since the label will not be used again, and \cs{g_@@_hook_curr_name_tl} +% is updated to the now topmost item of the stack: +% \begin{macrocode} +\cs_new_protected:Npn \@@_curr_name_pop: + { + \seq_gpop:NN \g_@@_name_stack_seq \l_@@_return_tl + \seq_get:NNTF \g_@@_name_stack_seq \l_@@_return_tl + { \tl_gset_eq:NN \g_@@_hook_curr_name_tl \l_@@_return_tl } + { + \msg_error:nnn { hooks } { should-not-happen } + { Tried~to~pop~from~an~empty~default~label~stack. } + } + } +% \end{macrocode} +% +% The token list \cs{g_@@_hook_curr_name_tl} is but a mirror of the top +% of the stack. +% +% Now define a wrapper that replaces the top of the stack with the +% argument, and updates \cs{g_@@_hook_curr_name_tl} accordingly. +% \begin{macrocode} +\NewDocumentCommand \DeclareDefaultHookLabel { m } + { + \seq_gpop:NN \g_@@_name_stack_seq \l_@@_return_tl + \@@_curr_name_push:n {#1} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% +% \begin{macro}{\UseHook,\UseOneTimeHook} +% Avoid the overhead of \pkg{xparse} and its protection that we +% don't want here (since the hook should vanish without trace if empty)! +% \begin{macrocode} +\cs_new:Npn \UseHook { \hook_use:n } +\cs_new:Npn \UseOneTimeHook { \hook_use_once:n } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\ShowHook,\LogHook} +% \begin{macrocode} +\cs_new_protected:Npn \ShowHook { \hook_show:n } +\cs_new_protected:Npn \LogHook { \hook_log:n } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DebugHooksOn,\DebugHooksOff} +% +% \begin{macrocode} +\cs_new_protected:Npn \DebugHooksOn { \hook_debug_on: } +\cs_new_protected:Npn \DebugHooksOff { \hook_debug_off: } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\DeclareHookRule} +% +% \begin{macrocode} +\NewDocumentCommand \DeclareHookRule { m m m m } + { \hook_gset_rule:nnnn {#1}{#2}{#3}{#4} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DeclareDefaultHookRule} +% This declaration is only supported before \verb=\begin{document}=. +% \begin{macrocode} +\NewDocumentCommand \DeclareDefaultHookRule { m m m } + { \hook_gset_rule:nnnn {??}{#1}{#2}{#3} } +\@onlypreamble\DeclareDefaultHookRule +% \end{macrocode} +% \end{macro} +% +% \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?} +% \begin{macrocode} +\NewDocumentCommand \ClearHookRule { m m m } +{ \hook_gset_rule:nnnn {#1}{#2}{unrelated}{#3} } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[EXP]{\IfHookExistsTF,\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} +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 +% +% \subsection{Internal commands needed elsewhere} +% +% Here we set up a few horrible (but consistent) \LaTeXe{} names to +% allow for internal commands to be used outside this module. We +% have to unset the \texttt{@\/@} since we want double ``at'' sign +% in place of double underscores. +% +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% \begin{macro}{\@expl@@@initialize@all@@, +% \@expl@@@hook@curr@name@push@@n, +% \@expl@@@hook@curr@name@pop@@} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@initialize@all@@ + \__hook_initialize_all: +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@hook@curr@name@push@@n + \__hook_curr_name_push:n +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_eq:NN \@expl@@@hook@curr@name@pop@@ + \__hook_curr_name_pop: +% \end{macrocode} +% \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. +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\NewHook}{The hook management}% +%<latexrelease> +%<latexrelease>\def \NewHook#1{} +%<latexrelease>\def \NewReversedHook#1{} +%<latexrelease>\def \NewMirroredHookPair#1#2{} +%<latexrelease> +%<latexrelease>\long\def \AddToHook#1#2{} +%<latexrelease> +%<latexrelease>\def \AddToHookNext#1{\@gobble@AddToHook@args} +%<latexrelease>\providecommand\@gobble@AddToHook@args[2][]{} +%<latexrelease> +%<latexrelease>\def\RemoveFromHook#1{\@gobble@RemoveFromHook@arg} +%<latexrelease>\providecommand\@gobble@RemoveFromHook@arg[1][]{} +%<latexrelease> +%<latexrelease>\def \UseHook #1{} +%<latexrelease>\def \UseOneTimeHook #1{} +%<latexrelease>\def \ShowHook #1{} +%<latexrelease>\let \DebugHooksOn \@empty +%<latexrelease>\let \DebugHooksOff\@empty +%<latexrelease> +%<latexrelease>\def \DeclareHookRul#1#2#3#4{} +%<latexrelease>\def \DeclareDefaultHookRule #1#2#3{} +%<latexrelease>\def \ClearHookRule#1#2#3{} +% \end{macrocode} +% If the hook management is not provided we make the test for existence +% false and the test for empty true in the hope that this is most +% of the time reasonable. If not a package would need to guard +% against running in an old kernel. +% \begin{macrocode} +%<latexrelease>\def \IfHookExistTF #1#2#3{#3} +%<latexrelease>\def \IfHookEmptyTF #1#2#3{#2} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% +% \Finale +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\endinput +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/Master/texmf-dist/source/latex/base/ltlists.dtx b/Master/texmf-dist/source/latex/base/ltlists.dtx index e8c9ebc16bd..653e4e2edd2 100644 --- a/Master/texmf-dist/source/latex/base/ltlists.dtx +++ b/Master/texmf-dist/source/latex/base/ltlists.dtx @@ -31,7 +31,7 @@ %<*driver> % \fi \ProvidesFile{ltlists.dtx} - [2015/05/10 v1.0t LaTeX Kernel (List Environments)] + [2020/04/24 v1.0t LaTeX Kernel (List Environments)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltlists.dtx} @@ -546,6 +546,7 @@ % \end{macrocode} % \end{macro}\end{macro}\end{macro} % +% \begin{environment}{list} % \begin{macro}{\list} % \begin{macrocode} \def\list#1#2{% @@ -572,6 +573,7 @@ \ignorespaces} % \end{macrocode} % \end{macro} +% \end{environment} % % \begin{macro}{\par@deathcycles} % \begin{macrocode} @@ -626,8 +628,9 @@ % \end{macrocode} % \end{macro} % -% \changes{0.0}{1992/03/18}{RmS: added \cs{@nmbrlistfalse}} +% \begin{environment}{trivlist} % \begin{macro}{\trivlist} +% \changes{0.0}{1992/03/18}{RmS: added \cs{@nmbrlistfalse}} % \begin{macrocode} \def\trivlist{% \parsep\parskip @@ -647,6 +650,7 @@ \def\makelabel##1{##1}} % \end{macrocode} % \end{macro} +% \end{environment} % % \begin{macro}{\endlist} % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/base/ltluatex.dtx b/Master/texmf-dist/source/latex/base/ltluatex.dtx index 1f9ab8d1332..8573b3e6ca6 100644 --- a/Master/texmf-dist/source/latex/base/ltluatex.dtx +++ b/Master/texmf-dist/source/latex/base/ltluatex.dtx @@ -23,12 +23,12 @@ %<tex> \ProvidesFile\undefined\begingroup\def\ProvidesFile %<tex> #1#2[#3]{\endgroup\immediate\write-1{File: #1 #3}} %<tex>\fi -%<plain>\ProvidesFile{ltluatex.tex} +%<plain>\ProvidesFile{ltluatex.tex}% %<*driver> \ProvidesFile{ltluatex.dtx} %</driver> %<*tex> -[2020/02/02 v1.1l +[2020/09/25 v1.1s %</tex> %<plain> LuaTeX support for plain TeX (core) %<*tex> @@ -406,6 +406,14 @@ \fi % \end{macrocode} % +% \changes{v1.1n}{2020/06/10}{Define \cs{@gobble}/\cs{@firstofone} even for \LaTeX\ to allow early loading.} +% Two simple \LaTeX\ macros from |ltdefns.dtx| have to be defined here +% because ltdefns.dtx is not loaded yet when ltluatex.dtx is executed. +% \begin{macrocode} +\long\def\@gobble#1{} +\long\def\@firstofone#1{#1} +% \end{macrocode} +% % \subsection{Older \LaTeX{}/Plain \TeX\ setup} % % \begin{macrocode} @@ -451,7 +459,7 @@ % \end{macrocode} % luatex/xetex also allow more math fam. % \begin{macrocode} -\edef \et@xmaxfam {\ifx\Umathchar\@undefined\sixt@@n\else\@cclvi\fi} +\edef \et@xmaxfam {\ifx\Umathcode\@undefined\sixt@@n\else\@cclvi\fi} % \end{macrocode} % % \begin{macrocode} @@ -521,12 +529,6 @@ \fi}% % \end{macrocode} % -% Two simple \LaTeX\ macros used in |ltlatex.sty|. -% \begin{macrocode} -\long\def\@gobble#1{} -\long\def\@firstofone#1{#1} -% \end{macrocode} -% % Fix up allocations not to clash with |etex.src|. % % \begin{macrocode} @@ -544,23 +546,23 @@ %</tex> % \end{macrocode} % -% % \subsection{Attributes} % % \begin{macro}{\newattribute} % \changes{v1.0a}{2015/09/24}{Macro added} +% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional} % As is generally the case for the Lua\TeX{} registers we start here % from~$1$. Notably, some code assumes that |\attribute0| is never used so % this is important in this case. % \begin{macrocode} \ifx\e@alloc@attribute@count\@undefined \countdef\e@alloc@attribute@count=258 + \e@alloc@attribute@count=\z@ \fi \def\newattribute#1{% \e@alloc\attribute\attributedef \e@alloc@attribute@count\m@ne\e@alloc@top#1% } -\e@alloc@attribute@count=\z@ % \end{macrocode} % \end{macro} % @@ -585,13 +587,13 @@ % \begin{macrocode} \ifx\e@alloc@ccodetable@count\@undefined \countdef\e@alloc@ccodetable@count=259 + \e@alloc@ccodetable@count=\z@ \fi \def\newcatcodetable#1{% \e@alloc\catcodetable\chardef \e@alloc@ccodetable@count\m@ne{"8000}#1% \initcatcodetable\allocationnumber } -\e@alloc@ccodetable@count=\z@ % \end{macrocode} % \end{macro} % @@ -698,18 +700,19 @@ % % \begin{macro}{\newluafunction} % \changes{v1.0a}{2015/09/24}{Macro added} +% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional} % Much the same story for allocating Lua\TeX{} functions except here they are % just numbers so they are allocated in the same way as boxes. % Lua indexes from~$1$ so once again slot~$0$ is skipped. % \begin{macrocode} \ifx\e@alloc@luafunction@count\@undefined \countdef\e@alloc@luafunction@count=260 + \e@alloc@luafunction@count=\z@ \fi \def\newluafunction{% \e@alloc\luafunction\e@alloc@chardef \e@alloc@luafunction@count\m@ne\e@alloc@top } -\e@alloc@luafunction@count=\z@ % \end{macrocode} % \end{macro} % @@ -717,17 +720,18 @@ % % \begin{macro}{\newwhatsit} % \changes{v1.0a}{2015/09/24}{Macro added} +% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional} % These are only settable from Lua but for consistency are definable % here. % \begin{macrocode} \ifx\e@alloc@whatsit@count\@undefined \countdef\e@alloc@whatsit@count=261 + \e@alloc@whatsit@count=\z@ \fi \def\newwhatsit#1{% \e@alloc\whatsit\e@alloc@chardef \e@alloc@whatsit@count\m@ne\e@alloc@top#1% } -\e@alloc@whatsit@count=\z@ % \end{macrocode} % \end{macro} % @@ -735,17 +739,18 @@ % % \begin{macro}{\newluabytecode} % \changes{v1.0a}{2015/09/24}{Macro added} +% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional} % These are only settable from Lua but for consistency are definable % here. % \begin{macrocode} \ifx\e@alloc@bytecode@count\@undefined \countdef\e@alloc@bytecode@count=262 + \e@alloc@bytecode@count=\z@ \fi \def\newluabytecode#1{% \e@alloc\luabytecode\e@alloc@chardef \e@alloc@bytecode@count\m@ne\e@alloc@top#1% } -\e@alloc@bytecode@count=\z@ % \end{macrocode} % \end{macro} % @@ -753,12 +758,14 @@ % \begin{macro}{\newluachunkname} % \changes{v1.0a}{2015/09/24}{Macro added} +% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional} % As for bytecode registers, but in addition we need to add a string % to the \verb|lua.name| table to use in stack tracing. We use the % name of the command passed to the allocator, with no backslash. % \begin{macrocode} \ifx\e@alloc@luachunk@count\@undefined \countdef\e@alloc@luachunk@count=263 + \e@alloc@luachunk@count=\z@ \fi \def\newluachunkname#1{% \e@alloc\luachunk\e@alloc@chardef @@ -766,19 +773,31 @@ {\escapechar\m@ne \directlua{lua.name[\the\allocationnumber]="\string#1"}}% } -\e@alloc@luachunk@count=\z@ % \end{macrocode} % \end{macro} % % \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 +% duplicated code: +% +% \begin{macrocode} +\def\now@and@everyjob#1{% + \everyjob\expandafter{\the\everyjob + #1% + }% + #1% +} +% \end{macrocode} % % Load the Lua code at the start of every job. % For the conversion of \TeX{} into numbers at the Lua side we need some % known registers: for convenience we use a set of systematic names, which % means using a group around the Lua loader. % \begin{macrocode} -%<2ekernel>\everyjob\expandafter{% -%<2ekernel> \the\everyjob +%<2ekernel>\now@and@everyjob{% \begingroup \attributedef\attributezero=0 % \chardef \charzero =0 % @@ -1321,6 +1340,7 @@ local callbacktypes = callbacktypes or { % \changes{v1.1k}{2019/10/02}{process\_rule is \texttt{exclusive}} % \changes{v1.1k}{2019/10/02}{mlist\_to\_hlist is \texttt{exclusive}} % \changes{v1.1l}{2020/02/02}{post\_linebreak\_filter is \texttt{reverselist}} +% \changes{v1.1p}{2020/08/01}{new\_graf is \texttt{exclusive}} % \begin{macrocode} contribute_filter = simple, buildpage_filter = simple, @@ -1342,7 +1362,7 @@ local callbacktypes = callbacktypes or { pre_mlist_to_hlist_filter = list, mlist_to_hlist = exclusive, post_mlist_to_hlist_filter = reverselist, - new_graf = simple, + new_graf = exclusive, % \end{macrocode} % Section 8.5: information reporting callbacks. % \changes{v1.0m}{2016/02/11}{show\_warning\_message added} @@ -1481,6 +1501,7 @@ end % \end{macrocode} % Handler for |list| callbacks. % \changes{v1.0k}{2015/12/02}{resolve name and i.description (PHG)} +% \changes{v1.1s}{2020/12/02}{Fix return value of list callbacks} % \begin{macrocode} local function list_handler(name) return function(head, ...) @@ -1493,7 +1514,7 @@ local function list_handler(name) "Function `" .. i.description .. "' returned false\n" .. "in callback `" .. name .."'" ) - break + return false end if ret ~= true then alltrue = false @@ -1526,7 +1547,7 @@ local function reverselist_handler(name) "Function `" .. cb.description .. "' returned false\n" .. "in callback `" .. name .."'" ) - break + return false end if ret ~= true then alltrue = false @@ -1716,6 +1737,7 @@ luatexbase.add_to_callback = add_to_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}{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. % \begin{macrocode} local function remove_from_callback(name, description) @@ -1761,7 +1783,9 @@ local function remove_from_callback(name, description) ) if #l == 0 then callbacklist[name] = nil - callback_register(name, nil) + if user_callbacks_defaults[name] == nil then + callback_register(name, nil) + end end return cb.func,cb.description end diff --git a/Master/texmf-dist/source/latex/base/ltmath.dtx b/Master/texmf-dist/source/latex/base/ltmath.dtx index 18688068b04..36b8bb7ec46 100644 --- a/Master/texmf-dist/source/latex/base/ltmath.dtx +++ b/Master/texmf-dist/source/latex/base/ltmath.dtx @@ -38,7 +38,7 @@ %<*driver> % \fi \ProvidesFile{ltmath.dtx} - [2019/08/27 v1.2c LaTeX Kernel (Math Setup)] + [2020/07/27 v1.2g LaTeX Kernel (Math Setup)] % \iffalse %</driver> % @@ -407,15 +407,17 @@ % \begin{macro}{\cases} % \changes{LaTeX2.09}{1991/08/14} % {(RmS) inserted extra braces around entry for NFSS} +% \changes{v1.2g}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\cases[1]{\left\{\,\vcenter{\normalbaselines\m@th +\DeclareRobustCommand*\cases[1]{\left\{\,\vcenter{\normalbaselines\m@th \ialign{$##\hfil$&\quad{##}\hfil\crcr#1\crcr}}\right.} % \end{macrocode} % \end{macro} % % \begin{macro}{\matrix} +% \changes{v1.2g}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\matrix[1]{\null\,\vcenter{\normalbaselines\m@th +\DeclareRobustCommand*\matrix[1]{\null\,\vcenter{\normalbaselines\m@th \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr \mathstrut\crcr\noalign{\kern-\baselineskip} #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}\,} @@ -423,8 +425,9 @@ % \end{macro} % % \begin{macro}{\pmatrix} +% \changes{v1.2g}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\pmatrix[1]{\left(\matrix{#1}\right)} +\DeclareRobustCommand*\pmatrix[1]{\left(\matrix{#1}\right)} % \end{macrocode} % \end{macro} % @@ -509,18 +512,103 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\>} -% \begin{macro}{\;} -% \begin{macro}{\!} + + +% +% \begin{macro}{\tmspace} +% \begin{macro}{\,} +% \begin{macro}{\thinspace} +% \begin{macro}{\!} +% \begin{macro}{\negthinspace} +% \begin{macro}{\:} +% \begin{macro}{\medspace} +% \begin{macro}{\negmedspace} +% \begin{macro}{\;} +% \begin{macro}{\thickspace} +% \begin{macro}{\negthickspace} +% +% 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 +% provided all of them in text and math. This code has now been +% moved to the kernel so that it is generally available. +% +% % \begin{macrocode} -%\def\,{\mskip\thinmuskip} % already defined in ltspace -\def\>{\mskip\medmuskip} -\def\;{\mskip\thickmuskip} -\def\!{\mskip-\thinmuskip} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\tmspace}{amsmath spacing commands}% +% \end{macrocode} +% \cs{tmspace} is really meant to be an internal command so it +% doesn't necessarily has to be robust but it was robust in +% \texttt{amsmath} so we leave it like that. +% \changes{v1.2e}{2020/03/07}{Add \texttt{amsmath} math/text spacing +% commands to the kernel (gh/303)} +% \begin{macrocode} +\DeclareRobustCommand\tmspace[3]{% + \ifmmode\mskip#1#2\else\leavevmode@ifvmode\kern#1#3\fi\relax} +% \end{macrocode} +% In \texttt{amsmath} the text kern is \texttt{.1667em}. For +% compatibility reasons we keep the longer one. +% \begin{macrocode} +\DeclareRobustCommand\,{\tmspace+\thinmuskip{.16667em}} +\let\thinspace\, % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} +% +% \begin{macrocode} +\DeclareRobustCommand\!{\tmspace-\thinmuskip{.16667em}} +\let\negthinspace\! +% \end{macrocode} +% +% \begin{macrocode} +\DeclareRobustCommand\:{\tmspace+\medmuskip{.2222em}} +\let\medspace\: +% \end{macrocode} +% \LaTeX{} has a second name for this in its manual: +% \begin{macrocode} +\let\>=\: +\DeclareRobustCommand\negmedspace{\tmspace-\medmuskip{.2222em}} +% \end{macrocode} +% +% \begin{macrocode} +\DeclareRobustCommand\;{\tmspace+\thickmuskip{.2777em}} +\let\thickspace\; +\DeclareRobustCommand\negthickspace{\tmspace-\thickmuskip{.2777em}} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\tmspace}{amsmath spacing commands}% +%<latexrelease> +%<latexrelease>\let\tmspace\@undefined +%<latexrelease>\DeclareRobustCommand{\,}{% +%<latexrelease> \relax\ifmmode\mskip\thinmuskip\else\thinspace\fi} +%<latexrelease>\DeclareRobustCommand\thinspace{\leavevmode@ifvmode\kern .16667em } +%<latexrelease>\DeclareRobustCommand\negthinspace{\leavevmode@ifvmode\kern-.16667em } +%<latexrelease>\def\>{\mskip\medmuskip} +%<latexrelease>\let\:=\> +%<latexrelease>\def\;{\mskip\thickmuskip} +%<latexrelease>\def\!{\mskip-\thinmuskip} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% % % \begin{macro}{\*} % \begin{macrocode} @@ -532,7 +620,7 @@ % Nickname for the medium space since |\>| is not available inside % \texttt{tabbing}. % \begin{macrocode} -\let\:=\> +%\let\:=\> % \end{macrocode} % \end{macro} % @@ -884,12 +972,32 @@ \def\@yeqncr{\@testopt\@xeqncr\z@skip} % \end{macrocode} % +% \changes{v1.2f}{2020/04/21}{Support calc syntax (gh/152)} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@xeqncr}{eqnarray support calc syntax}% \def\@xeqncr[#1]{% \ifnum0=`{\fi}% \@@eqncr - \noalign{\penalty\@eqpen\vskip\jot\vskip #1\relax}% + \noalign{\penalty\@eqpen\vskip\jot\@vspace@calcify{#1}}% } +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@xeqncr}{eqnarray support calc syntax}% +%<latexrelease> +%<latexrelease>\def\@xeqncr[#1]{% +%<latexrelease> \ifnum0=`{\fi}% +%<latexrelease> \@@eqncr +%<latexrelease> \noalign{\penalty\@eqpen\vskip\jot\vskip #1\relax}% +%<latexrelease>} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % % \end{macro} @@ -1009,9 +1117,11 @@ % % \begin{macro}{\mathindent} % The amount of indentation of the equations is stored in a register. +% \changes{v1.2d}{2020/02/18}{Make \cs{mathindent} a skip register to match +% amsmath (gh/252)} % \begin{macrocode} %<*fleqn> -\newdimen\mathindent +\newskip\mathindent % \end{macrocode} % The setting of |\mathindent| has to be deferred until the class % file has been processed, because |\leftmargini| is still 0pt @@ -1097,7 +1207,13 @@ \hb@xt@\linewidth\bgroup $\m@th% $ \displaystyle \hskip\mathindent}% - {$\hfil % $ +% \end{macrocode} +% Ensure that there is at least a space between formula and +% equation number so that they don't bump in each other. +% \changes{v1.2d}{2020/02/18}{Separate formula and eqn number by at +% least a space in fleqn option} +% \begin{macrocode} + {$\hskip .3em minus.3em\hfil % $ \displaywidth\linewidth\hbox{\@eqnnum}% \egroup \endtrivlist} diff --git a/Master/texmf-dist/source/latex/base/ltmiscen.dtx b/Master/texmf-dist/source/latex/base/ltmiscen.dtx index 97b1f4a572b..0c115d3be1b 100644 --- a/Master/texmf-dist/source/latex/base/ltmiscen.dtx +++ b/Master/texmf-dist/source/latex/base/ltmiscen.dtx @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltmiscen.dtx} - [2019/11/02 v1.1s LaTeX Kernel (Misc. Environments)] + [2020/08/21 v1.1v LaTeX Kernel (Misc. Environments)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltmiscen.dtx} @@ -73,6 +73,7 @@ % \cs{@noligs}.} % \changes{v1.1g}{1998/08/17}{(RmS) Minor documentation fixes.} % \changes{v1.1p}{2019/08/27}{Make various commands robust} +% \changes{v1.1v}{2020/08/21}{Integration of new hook management interface} % % \section{Miscellaneous Environments} % This section implements the basic environment mechanism, and also @@ -182,6 +183,7 @@ % \end{macrocode} % \end{macro} % +% \begin{environment}{document} % \begin{macro}{\enddocument} % \changes{LaTeX2.09}{1993/08/03} % {Changed redefinition of \cs{global} to redefinition @@ -190,6 +192,10 @@ % {Added warning in case of undefined references.}% % \changes{v0.9e}{1993/12/09}{Hook added} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\enddocument}{Use Hooks}% \def\enddocument{% % \end{macrocode} % The |\end{document}| hook is executed first. If necessary it can @@ -208,10 +214,15 @@ % \changes{v1.1i}{2000/05/19} % {Reset \cs{AtEndDocument} for latex/3060} % \begin{macrocode} - \let\AtEndDocument\@firstofone - \@enddocumenthook + \UseOneTimeHook{enddocument}% + \@kernel@after@enddocument +% \end{macrocode} +% +% \begin{macrocode} \@checkend{document}% \clearpage + \UseOneTimeHook{enddocument/afterlastpage}% + \@kernel@after@enddocument@afterlastpage \begingroup \if@filesw \immediate\closeout\@mainaux @@ -234,11 +245,52 @@ \@tempswafalse \makeatletter \@@input\jobname.aux \fi + \UseHook{enddocument/afteraux}% % \end{macrocode} -% \changes{v1.0w}{1994/11/30} -% {(DPC) Use \cs{@dofilelist}} +% Next hook is expect to contain only code for writing info +% messages on the terminal. +% \begin{macrocode} + \UseOneTimeHook{enddocument/info}% + \endgroup + \UseOneTimeHook{enddocument/end}% + \deadcycles\z@\@@end} +% \end{macrocode} +% +% The public hooks used in \cs{enddocument}: +% \begin{macrocode} +\NewHook{enddocument} +\NewHook{enddocument/afterlastpage} +\NewHook{enddocument/afteraux} +\NewHook{enddocument/info} +\NewHook{enddocument/end} +% \end{macrocode} +% +% This is one of the few places where we already add data and rules +% to a hook already in the kernel. +% \changes{v1.0w}{1994/11/30}{(DPC) Use \cs{@dofilelist}} +% \begin{macrocode} +\AddToHook{enddocument/info}[kernel/filelist]{\@dofilelist} +\AddToHook{enddocument/info}[kernel/warnings]{\@enddocument@kernel@warnings} +\DeclareHookRule{enddocument/info}{kernel/filelist}{before}{kernel/warnings} +% \end{macrocode} +% \end{macro} +% \end{environment} +% +% +% \begin{macro}{\@kernel@after@enddocument, +% \@kernel@after@enddocument@afterlastpage} +% +% The two kernel hooks above are used by the shipout code. +% \begin{macrocode} +\let\@kernel@after@enddocument\@empty +\let\@kernel@after@enddocument@afterlastpage\@empty +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@enddocument@kernel@warnings} +% % \begin{macrocode} - \@dofilelist +\def\@enddocument@kernel@warnings{% % \end{macrocode} % First we check for font size substitution bigger than % |\fontsubfuzz|. The |\relax| is necessary because this is a macro @@ -246,29 +298,29 @@ % \changes{v1.0w}{1994/11/30} % {(DPC) Do warnings even for \cs{nofiles}} % \begin{macrocode} - \ifdim \font@submax >\fontsubfuzz\relax + \ifdim \font@submax >\fontsubfuzz\relax % \end{macrocode} % In case you wonder about the |\@gobbletwo| inside the message % below, this is a horrible hack to remove the tokens |\on@line.| % that are added by |\@font@warning| at the end. % \changes{v1.1j}{2000/07/11}{Fix typo in warning} % \begin{macrocode} - \@font@warning{Size substitutions with differences\MessageBreak - up to \font@submax\space have occurred.\@gobbletwo}% - \fi + \@font@warning{Size substitutions with differences\MessageBreak + up to \font@submax\space have occurred.\@gobbletwo}% + \fi % \end{macrocode} % The macro |\@defaultsubs| is initially |\relax| but gets redefined % to produce % a warning if there have been some default font substitutions. % \changes{v1.0z}{1995/07/13}{Use \cs{@defaultsubs} instead of switch} % \begin{macrocode} - \@defaultsubs + \@defaultsubs % \end{macrocode} % The macro |\@refundefined| is initially |\relax| but gets redefined % to produce a warning if there are undefined refs. % \changes{v1.1b}{1995/10/24}{Use \cs{@refundefined} instead of switch} % \begin{macrocode} - \@refundefined + \@refundefined % \end{macrocode} % If a label is defined more than once, |\@tempswa| will always be % true and thus produce a ``Label(s) may \ldots'' warning. But @@ -280,21 +332,78 @@ % \changes{v1.1b}{1995/10/24}{Changed logic for producing % warning messages and removed switch} % \begin{macrocode} - \if@filesw - \ifx \@multiplelabels \relax - \if@tempswa - \@latex@warning@no@line{Label(s) may have changed. - Rerun to get cross-references right}% - \fi - \else - \@multiplelabels + \if@filesw + \ifx \@multiplelabels \relax + \if@tempswa + \@latex@warning@no@line{Label(s) may have changed. + Rerun to get cross-references right}% \fi + \else + \@multiplelabels + \fi + \ifx \@extra@page@added \relax + \@latex@warning@no@line{Temporary extra page added at the end. + Rerun to get it removed}% \fi - \endgroup - \deadcycles\z@\@@end} +% \end{macrocode} +% We could think of adding a warning that nothing can be corrected +% while \cs{nofiles} is in force. In the past the warnings related +% to the \texttt{aux} file are simply suppressed in this case. +% \begin{macrocode} + \fi +} % \end{macrocode} % \end{macro} % +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\enddocument}{Use Hooks}% +%<latexrelease> +%<latexrelease>\def\enddocument{% +%<latexrelease> \let\AtEndDocument\@firstofone +%<latexrelease> \@enddocumenthook +%<latexrelease> \@checkend{document}% +%<latexrelease> \clearpage +%<latexrelease> \begingroup +%<latexrelease> \if@filesw +%<latexrelease> \immediate\closeout\@mainaux +%<latexrelease> \let\@setckpt\@gobbletwo +%<latexrelease> \let\@newl@bel\@testdef +%<latexrelease> \@tempswafalse +%<latexrelease> \makeatletter \@@input\jobname.aux +%<latexrelease> \fi +%<latexrelease> \@dofilelist +%<latexrelease> \ifdim \font@submax >\fontsubfuzz\relax +%<latexrelease> \@font@warning{Size substitutions with differences\MessageBreak +%<latexrelease> up to \font@submax\space have occurred.\@gobbletwo}% +%<latexrelease> \fi +%<latexrelease> \@defaultsubs +%<latexrelease> \@refundefined +%<latexrelease> \if@filesw +%<latexrelease> \ifx \@multiplelabels \relax +%<latexrelease> \if@tempswa +%<latexrelease> \@latex@warning@no@line{Label(s) may have changed. +%<latexrelease> Rerun to get cross-references right}% +%<latexrelease> \fi +%<latexrelease> \else +%<latexrelease> \@multiplelabels +%<latexrelease> \fi +%<latexrelease> \fi +%<latexrelease> \endgroup +%<latexrelease> \deadcycles\z@\@@end} +%<latexrelease> +%<latexrelease>\let\@kernel@after@enddocument\@undefined +%<latexrelease>\let\@kernel@after@enddocument@afterlastpage\@undefined +%<latexrelease>\let\@enddocument@kernel@warnings\@undefined +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% +% % \begin{macro}{\@testdef} % \begin{macrocode} \def\@testdef #1#2#3{% @@ -523,17 +632,107 @@ % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\begin}{Making \begin/\end robust}% -\DeclareRobustCommand\begin[1]{% +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\begin}{Use hook system}% +\DeclareRobustCommand*\begin[1]{% + \UseHook{env/#1/before}% \@ifundefined{#1}% {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}% {\def\reserved@a{\def\@currenvir{#1}% - \edef\@currenvline{\on@line}% - \csname #1\endcsname}}% + \edef\@currenvline{\on@line}% + \@execute@begin@hook{#1}% + \csname #1\endcsname}}% \@ignorefalse \begingroup\@endpefalse\reserved@a} % \end{macrocode} +% +% Before the \cs{document} code is executed we have to first undo +% the \cs{endgroup} as there should be none for this environment to +% avoid that changes on top-level unnecessarily go to \TeX's +% savestack, and we have to initialize all hooks in the hook system. +% So we need to test for this environment name. But once it has be +% found all this testing is no longer needed and so we redefine +% \cs{@execute@begin@hook} to simply use the hook. +% \begin{macrocode} +\def\@execute@begin@hook #1{% + \expandafter\ifx\csname #1\endcsname\document + \endgroup + \gdef\@execute@begin@hook##1{\UseHook{env/##1/begin}}% + \@expl@@@initialize@all@@ + \fi +% \end{macrocode} +% If this is an environment before \verb=\begin{document}= we just +% run the hook so this can be outside the test. +% \begin{macrocode} + \UseHook{env/#1/begin}% +} +% \end{macrocode} +% +% The top level definition for \cs{end}. for an explanation see +% below (this is the same as the 2019 version where it was +% introduced, but for rollback we have to repeat it). +% \begin{macrocode} +\edef\end + {\unexpanded{% + \romannumeral + \ifx\protect\@typeset@protect + \expandafter %1 + \expandafter %2 + \expandafter %1 + \expandafter %3 expands the \csname inside \end<space> + \expandafter %1 + \expandafter %2 expands \end<space> + \expandafter %1 expands the \else + \z@ + \else + \expandafter\z@\expandafter\protect + \fi + }% + \expandafter\noexpand\csname end \endcsname + } +% \end{macrocode} +% Version that adds hooks (so different from the 2019 version). It +% fixes tlb3722 but the change should perhaps be made in +% \texttt{tabularx} instead. +% \begin{macrocode} +\@namedef{end }#1{% + \romannumeral + \IfHookEmptyTF{env/#1/end}% + {\expandafter\z@}% + {\z@\UseHook{env/#1/end}}% + \csname end#1\endcsname\@checkend{#1}% + \expandafter\endgroup\if@endpe\@doendpe\fi + \UseHook{env/#1/after}% + \if@ignore\@ignorefalse\ignorespaces\fi +} +% \end{macrocode} +% Version without the fix for tlb3722 for the record: +% \begin{macrocode} +%\@namedef{end }#1{% +% \UseHook{env/#1/end}% +% \csname end#1\endcsname\@checkend{#1}% +% \expandafter\endgroup\if@endpe\@doendpe\fi +% \UseHook{env/#1/after}% +% \if@ignore\@ignorefalse\ignorespaces\fi}% +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\begin}{Making \begin/\end robust}% +%<latexrelease>\DeclareRobustCommand\begin[1]{% +%<latexrelease> \@ifundefined{#1}% +%<latexrelease> {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}% +%<latexrelease> {\def\reserved@a{\def\@currenvir{#1}% +%<latexrelease> \edef\@currenvline{\on@line}% +%<latexrelease> \csname #1\endcsname}}% +%<latexrelease> \@ignorefalse +%<latexrelease> \begingroup\@endpefalse\reserved@a} +% \end{macrocode} % A version that doesn't start out with \cs{relax} when in % typesetting mode would be the following, but since \cs{begin} % issues a \cs{begingroup} it wouldn't help much with respect to @@ -606,41 +805,50 @@ % \changes{v1.1p}{2019/08/27}{Make command robust} % % \begin{macrocode} -\edef\end - {\unexpanded{% - \romannumeral - \ifx\protect\@typeset@protect - \expandafter %1 - \expandafter %2 - \expandafter %1 - \expandafter %3 expands the \csname inside \end<space> - \expandafter %1 - \expandafter %2 expands \end<space> - \expandafter %1 expands the \else - \z@ - \else - \expandafter\z@\expandafter\protect - \fi - }% - \expandafter\noexpand\csname end \endcsname - } +%<latexrelease>\edef\end +%<latexrelease> {\unexpanded{% +%<latexrelease> \romannumeral +%<latexrelease> \ifx\protect\@typeset@protect +%<latexrelease> \expandafter %1 +%<latexrelease> \expandafter %2 +%<latexrelease> \expandafter %1 +%<latexrelease> \expandafter %3 expands the \csname inside \end<space> +%<latexrelease> \expandafter %1 +%<latexrelease> \expandafter %2 expands \end<space> +%<latexrelease> \expandafter %1 expands the \else +%<latexrelease> \z@ +%<latexrelease> \else +%<latexrelease> \expandafter\z@\expandafter\protect +%<latexrelease> \fi +%<latexrelease> }% +%<latexrelease> \expandafter\noexpand\csname end \endcsname +%<latexrelease> } % \end{macrocode} % And here is the original definition of \cs{end} the way it was in % \LaTeX{} for several decades now hidden in \verb*=\end =. % \begin{macrocode} -\@namedef{end }#1{% - \csname end#1\endcsname\@checkend{#1}% - \expandafter\endgroup\if@endpe\@doendpe\fi - \if@ignore\@ignorefalse\ignorespaces\fi} -%</2ekernel|latexrelease> +%<latexrelease>\@namedef{end }#1{% +%<latexrelease> \csname end#1\endcsname\@checkend{#1}% +%<latexrelease> \expandafter\endgroup\if@endpe\@doendpe\fi +%<latexrelease> \if@ignore\@ignorefalse\ignorespaces\fi} %<latexrelease>\EndIncludeInRelease % \end{macrocode} % An here the rollback in case that is ever needed. % \begin{macrocode} %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\begin}{Making \begin/\end robust}% -%<latexrelease>\kernel@make@fragile\begin -%<latexrelease>\kernel@make@fragile\end +%<latexrelease>\def\begin#1{% +%<latexrelease> \@ifundefined{#1}% +%<latexrelease> {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}% +%<latexrelease> {\def\reserved@a{\def\@currenvir{#1}% +%<latexrelease> \edef\@currenvline{\on@line}% +%<latexrelease> \csname #1\endcsname}}% +%<latexrelease> \@ignorefalse +%<latexrelease> \begingroup\@endpefalse\reserved@a} +%<latexrelease>\def\end#1{% +%<latexrelease> \csname end#1\endcsname\@checkend{#1}% +%<latexrelease> \expandafter\endgroup\if@endpe\@doendpe\fi +%<latexrelease> \if@ignore\@ignorefalse\ignorespaces\fi} %<latexrelease> %<latexrelease>\EndIncludeInRelease %<*2ekernel> @@ -672,6 +880,47 @@ % \end{macro} % % +% +% \begin{macro}{\AtBeginEnvironment,\AtEndEnvironment, +% \BeforeBeginEnvironment,\AfterEndEnvironment} +% +% We provide 4 high-level hook interfaces directly, the others only when +% etoolbox is loaded +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\AtBeginEnvironment}{Hooks for environments}% +% \end{macrocode} +% +% \begin{macrocode} +\newcommand\AtBeginEnvironment[2][.] {\AddToHook{env/#2/begin}[#1]} +\newcommand\AtEndEnvironment[2][.] {\AddToHook{env/#2/end}[#1]} +\newcommand\BeforeBeginEnvironment[2][.]{\AddToHook{env/#2/before}[#1]} +\newcommand\AfterEndEnvironment[2][.] {\AddToHook{env/#2/after}[#1]} +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\AtBeginEnvironment}{Hooks for environments}% +%<latexrelease> +%<latexrelease>\let\AtBeginEnvironment\@undefined +%<latexrelease>\let\AtEndEnvironment\@undefined +%<latexrelease>\let\BeforeBeginEnvironment\@undefined +%<latexrelease>\let\AfterEndEnvironment\@undefined +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% +% % \subsection{Center, Flushright, Flushleft} % % \begin{macrocode} @@ -738,10 +987,25 @@ % \end{macro} % % \begin{macro}{\@icentercr} +% \changes{v1.1t}{2020/04/21}{Support calc syntax (gh/152)} % \begin{macrocode} -\def\@icentercr[#1]{\vskip #1\ignorespaces} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@icentercr}{centering, etc support calc}% +\def\@icentercr[#1]{\@vspace@calcify{#1}\ignorespaces} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@icentercr}{centering, etc support calc}% +%<latexrelease> +%<latexrelease>\def\@icentercr[#1]{\vskip #1\ignorespaces} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} -% % \end{macro} % % @@ -763,33 +1027,39 @@ % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\centering}{Make commands robust}% +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\centering}{Set finaldhypendemerits}% % \end{macrocode} % % \begin{macro}{\centering} +% \changes{v1.1u}{2020/05/31}{Added \cs{finalhyphendemerits} setting (gh/247)} % \begin{macrocode} \DeclareRobustCommand\centering{% \let\\\@centercr \rightskip\@flushglue\leftskip\@flushglue + \finalhyphendemerits=\z@ \parindent\z@\parfillskip\z@skip} % \end{macrocode} % \end{macro} % % \begin{macro}{\raggedright} +% \changes{v1.1u}{2020/05/31}{Added \cs{finalhyphendemerits} setting (gh/247)} % \begin{macrocode} \DeclareRobustCommand\raggedright{% \let\\\@centercr\@rightskip\@flushglue \rightskip\@rightskip + \finalhyphendemerits=\z@ \leftskip\z@skip \parindent\z@} % \end{macrocode} % \end{macro} % % \begin{macro}{\raggedleft} +% \changes{v1.1u}{2020/05/31}{Added \cs{finalhyphendemerits} setting (gh/247)} % \begin{macrocode} \DeclareRobustCommand\raggedleft{% \let\\\@centercr \rightskip\z@skip\leftskip\@flushglue + \finalhyphendemerits=\z@ \parindent\z@\parfillskip\z@skip} % \end{macrocode} % \end{macro} @@ -797,6 +1067,23 @@ % \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\centering}{Make commands robust}% +%<latexrelease> +%<latexrelease>\DeclareRobustCommand\centering{% +%<latexrelease> \let\\\@centercr +%<latexrelease> \rightskip\@flushglue\leftskip\@flushglue +%<latexrelease> \parindent\z@\parfillskip\z@skip} +%<latexrelease>\DeclareRobustCommand\raggedright{% +%<latexrelease> \let\\\@centercr\@rightskip\@flushglue \rightskip\@rightskip +%<latexrelease> \leftskip\z@skip +%<latexrelease> \parindent\z@} +%<latexrelease>\DeclareRobustCommand\raggedleft{% +%<latexrelease> \let\\\@centercr +%<latexrelease> \rightskip\z@skip\leftskip\@flushglue +%<latexrelease> \parindent\z@\parfillskip\z@skip} +%<latexrelease>\EndIncludeInRelease +%<latexrelease> %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\centering}{Make commands robust}% %<latexrelease> @@ -983,6 +1270,7 @@ % \end{macrocode} % \end{macro} % +% \begin{environment}{verbatim} % \begin{macro}{\verbatim} % \begin{macro}{\endverbatim} % (RmS 93/09/19) Protected against `missing item' error message @@ -993,6 +1281,7 @@ % \end{macrocode} % \end{macro} % \end{macro} +% \end{environment} % % \begin{macro}{\verbatim@font} % \changes{v0.9a}{1993/11/21}{Macro added} @@ -1010,7 +1299,7 @@ %</2ekernel> %<*2ekernel|latexrelease> %<latexrelease>\IncludeInRelease{2018/12/01}% -%<latexrelease> {\verbvisiblespace}{Setup visible space for verb}% +%<latexrelease> {\verbvisiblespace}{Setup visible space for \verb}% % \end{macrocode} % % @@ -1092,15 +1381,71 @@ % \end{macrocode} % \end{macro} % +%^^A \@sverb was here +% +% \begin{environment}{verbatim*} +% For \texttt{verbatim*} we also set up the correct visible space +% character definition and then run |\@vobeyspaces|. As this code +% is not called as part of the normal verbatim environment (the +% method is done the other way around this time) we don't have to +% check if space is already active---it shouldn't be. +% \changes{v1.1o}{2018/10/11} +% {Provide visible space in \cs{verb*} also for XeTeX and LuaTeX (github/69)} +% \begin{macrocode} +\@namedef{verbatim*}{\@verbatim + \@setupverbvisiblespace + \frenchspacing\@vobeyspaces\@sxverbatim} +\expandafter\let\csname endverbatim*\endcsname =\endverbatim +% \end{macrocode} +% \end{environment} +% +% +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\verbvisiblespace}{Setup visible space for \verb}% +%<latexrelease> +%<latexrelease>\@namedef{verbatim*}{\@verbatim\@sxverbatim} +%<latexrelease> +%<latexrelease>\let\asciispace \@undefined +%<latexrelease>\let\verbvisiblespace \@undefined +%<latexrelease>\let\@setupverbvisiblespace\@undefined +%<latexrelease>\let\@verbvisiblespacebox \@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% % % \begin{macro}{\@sverb} +% \begin{macro}{\@@sverb} % \changes{v1.0j}{1994/05/10}{Slight change in error message text.} % Definitions of |\@sverb| and |\@verb| changed so |\verb+ foo+| % does not lose leading blanks when it comes at the beginning of a line. % Change made 24 May 89. Suggested by Frank Mittelbach and Rainer % Sch\"opf. % \begin{macrocode} -\def\@sverb#1{% +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@sverb}{Drop spaces before \verb delimiter}% +% \end{macrocode} +% +% If the users types \verb=\verb !~! foo= then surprisingly we would +% get the space as the delimiter and thus +% ``\verb=!~!foo='' in the output. +% To avoid this scenario we check if \verb=#1= has the character +% code of a space, if so we recurse otherwise we call \cs{@@sverb} +% (which is the original definition of \cs{@sverb}. +% \changes{v1.1u}{2020/04/22}{Drop spaces before \cs{verb} delimiter (gh/327)} +% \begin{macrocode} +\def\@sverb#1{\if\noexpand#1 \expandafter\@sverb\else\@@sverb{#1}\fi} +% \end{macrocode} +% +% \begin{macrocode} +\def\@@sverb#1{% \catcode`#1\active \lccode`\~`#1% \gdef\verb@balance@group{\verb@egroup @@ -1120,39 +1465,28 @@ \else \@setupverbvisiblespace \@vobeyspaces \fi } % \end{macrocode} -% \end{macro} -% -% \begin{environment}{verbatim*} -% For \texttt{verbatim*} we also set up the correct visible space -% character definition and then run |\@vobeyspaces|. As this code -% is not called as part of the normal verbatim environment (the -% method is done the other way around this time) we don't have to -% check if space is already active---it shouldn't be. -% \changes{v1.1o}{2018/10/11} -% {Provide visible space in \cs{verb*} also for XeTeX and LuaTeX (github/69)} -% \begin{macrocode} -\@namedef{verbatim*}{\@verbatim - \@setupverbvisiblespace - \frenchspacing\@vobeyspaces\@sxverbatim} -\expandafter\let\csname endverbatim*\endcsname =\endverbatim -% \end{macrocode} -% \end{environment} -% -% -% +% % \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease -%<latexrelease>\IncludeInRelease{0000/00/00}% -%<latexrelease> {\verbvisiblespace}{Setup visible space for verb}% -%<latexrelease> -%<latexrelease>\@namedef{verbatim*}{\@verbatim\@sxverbatim} +%<latexrelease>\IncludeInRelease{2018/12/01}% +%<latexrelease> {\@sverb}{Setup visible space for \verb}% %<latexrelease> -%<latexrelease>\let\asciispace \@undefined -%<latexrelease>\let\verbvisiblespace \@undefined -%<latexrelease>\let\@setupverbvisiblespace\@undefined -%<latexrelease>\let\@verbvisiblespacebox \@undefined +%<latexrelease>\def\@sverb#1{% +%<latexrelease> \catcode`#1\active +%<latexrelease> \lccode`\~`#1% +%<latexrelease> \gdef\verb@balance@group{\verb@egroup +%<latexrelease> \@latex@error{\noexpand\verb illegal in command argument}\@ehc}% +%<latexrelease> \aftergroup\verb@balance@group +%<latexrelease> \lowercase{\let~\verb@egroup}% +%<latexrelease> \ifnum\catcode`\ =\active +%<latexrelease> \else \@setupverbvisiblespace \@vobeyspaces \fi +%<latexrelease>} +%<latexrelease>\let\@@sverb\@undefined +%<latexrelease>\EndIncludeInRelease %<latexrelease> +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@sverb}{Setup visible space for \verb}% %<latexrelease>\def\@sverb#1{% %<latexrelease> \catcode`#1\active %<latexrelease> \lccode`\~`#1% @@ -1164,8 +1498,8 @@ %<latexrelease>\EndIncludeInRelease %<*2ekernel> % \end{macrocode} -% -% +% \end{macro} +% \end{macro} % % % \begin{macro}{\@makeother} diff --git a/Master/texmf-dist/source/latex/base/ltoutenc.dtx b/Master/texmf-dist/source/latex/base/ltoutenc.dtx index f3c19000edf..c6bfc149b7c 100644 --- a/Master/texmf-dist/source/latex/base/ltoutenc.dtx +++ b/Master/texmf-dist/source/latex/base/ltoutenc.dtx @@ -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/02/11 v2.0o +%<OT1|T1|OMS|OML|OT4|TU|package> [2020/08/10 v2.0s %<OT1|T1|OMS|OML|OT4|TS1|TU> Standard LaTeX file] %<package> Standard LaTeX package] % %<*driver> % \fi \ProvidesFile{ltoutenc.dtx} - [2020/02/11 v2.0o LaTeX Kernel (font encodings)] + [2020/08/10 v2.0s LaTeX Kernel (font encodings)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltoutenc.dtx} @@ -188,6 +188,8 @@ % like.} % \changes{v1.99m}{2015/02/21} % {Removed autoload code} +% \changes{v2.0p}{2020/04/22} +% {corrected \=y unicode value in tuenc.def} % % % \section{Font encodings} @@ -1080,8 +1082,9 @@ % deficiencies, see pr/3160. % \task{?}{Improve this and document its problems, see pr/3160} % \changes{v1.9z}{2000/01/30}{Macro reimplemented (pr/3160)} +% \changes{v2.0r}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\UseTextAccent[3]{% +\DeclareRobustCommand*\UseTextAccent[3]{% \hmode@start@before@group {% % \end{macrocode} @@ -1096,8 +1099,9 @@ % \end{macrocode} % % \changes{v1.9z}{2000/01/30}{Macro reimplemented (pr/3160)} +% \changes{v2.0r}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\UseTextSymbol[2]{% +\DeclareRobustCommand*\UseTextSymbol[2]{% \hmode@start@before@group {% \def\@wrong@font@char{\MessageBreak @@ -2867,28 +2871,64 @@ % \end{macrocode} % % LuaTeX. +% For Lua\TeX~1.10+, define a Lua function to disable any handing by the font code. +% Otherwise we reload the font without TeX ligatures. +% \changes{v2.0q}{2020/07/04}{% +% Implement \cs{remove@tlig} in Lua\TeX without font reloading} % \begin{macrocode} \def\UnicodeFontTeXLigatures{+tlig;} -% \end{macrocode} -% -% \begin{macrocode} - \def\reserved@a#1{% - \def\@remove@tlig##1{\@remove@tlig@##1\@nil#1\@nil\relax} - \def\@remove@tlig@##1#1{\@remove@tlig@@##1}} - \edef\reserved@b{\detokenize{+tlig;}} - \expandafter\reserved@a\expandafter{\reserved@b} - \def\@remove@tlig@@#1\@nil#2\relax{#1} -% \end{macrocode} -% -% \begin{macrocode} - \def\remove@tlig#1{% - \begingroup - \font\remove@tlig - \expandafter\@remove@tlig\expandafter{\fontname\font}% - \remove@tlig - \char#1\relax - \endgroup - } + \ifnum\luatexversion<110 +% \end{macrocode} +% +% \begin{macrocode} + \def\reserved@a#1{% + \def\@remove@tlig##1{\@remove@tlig@##1\@nil#1\@nil\relax} + \def\@remove@tlig@##1#1{\@remove@tlig@@##1}} + \edef\reserved@b{\detokenize{+tlig;}} + \expandafter\reserved@a\expandafter{\reserved@b} + \def\@remove@tlig@@#1\@nil#2\relax{#1} +% \end{macrocode} +% +% \begin{macrocode} + \def\remove@tlig#1{% + \begingroup + \font\remove@tlig + \expandafter\@remove@tlig\expandafter{\fontname\font}% + \remove@tlig + \char#1\relax + \endgroup + } + \else + \newluafunction\@remove@tlig@@@@ +% \end{macrocode} +% Now we can define the function. Mostly we just have to insert a protected glyph +% node, which is a glyph node with subtype 256. But we have to keep track of the +% current mode to avoid inserting the glyph into a vlist. +% \begin{macrocode} + \now@and@everyjob{\directlua{ + local rawchar_func = token.create'@remove@tlig@@@@'.index + local forcehmode = tex.forcehmode + local put_next = token.put_next + local glyph_id = node.id'glyph' + local rawchar_token = token.new(rawchar_func, token.command_id'lua_call') + lua.get_functions_table()[rawchar_func] = function() + local mode = tex.nest.top.mode + if mode == 1 or mode == -1 then + put_next(rawchar_token) + return forcehmode(true) + end + local n = node.new(glyph_id, 256) + n.font = font.current() + n.char = token.scan_int() + return node.write(n) + end + token.set_lua('@remove@tlig@@@', rawchar_func, 'global', 'protected') + }} +% \end{macrocode} +% Now \verb+\remove@tlig+ can be implemented almost as in XeTeX. +% \begin{macrocode} + \def\remove@tlig#1{\@remove@tlig@@@#1\relax} + \fi % \end{macrocode} % % \begin{macrocode} @@ -3370,7 +3410,7 @@ \DeclareUnicodeComposite{\textcommabelow}{T}{"021A} \DeclareUnicodeComposite{\textcommabelow}{t}{"021B} \DeclareUnicodeComposite{\=} {Y}{"0232} -\DeclareUnicodeComposite{\=} {y}{"0232} +\DeclareUnicodeComposite{\=} {y}{"0233} \DeclareUnicodeComposite{\.} {B}{"1E02} \DeclareUnicodeComposite{\.} {b}{"1E03} \DeclareUnicodeComposite{\d} {B}{"1E04} @@ -3601,7 +3641,7 @@ \xdef\@fontenc@load@list{\@fontenc@load@list \@elt{\csname opt@fontenc.sty\endcsname}} % \end{macrocode} -% +% % \begin{macrocode} \global\expandafter\let\csname ver@fontenc.sty\endcsname\relax \global\expandafter\let\csname opt@fontenc.sty\endcsname\relax diff --git a/Master/texmf-dist/source/latex/base/ltoutput.dtx b/Master/texmf-dist/source/latex/base/ltoutput.dtx index c3b27baf42d..35d049b9590 100644 --- a/Master/texmf-dist/source/latex/base/ltoutput.dtx +++ b/Master/texmf-dist/source/latex/base/ltoutput.dtx @@ -37,7 +37,7 @@ %<*driver> % \fi \ProvidesFile{ltoutput.dtx} - [2019/08/27 v1.4e LaTeX Kernel (Output Routine)] + [2020/08/21 v1.4f LaTeX Kernel (Output Routine)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltoutput.dtx} @@ -791,12 +791,17 @@ % % The stuff in the box should not add any typeset material to the % page when it is unboxed. +% +% This interface is no longer used. Instead a new one is inside +% \texttt{ltshipout.dtx}. We only keep the box in case some old +% code refers to it directly (or we do some rollback). +% \changes{v1.4f}{2020/08/21}{Integration of new hook management interface} % \begin{macrocode} \newbox\@begindvibox -\DeclareRobustCommand \AtBeginDvi [1]{% - \global \setbox \@begindvibox - \vbox{\unvbox \@begindvibox #1}% -} +%\DeclareRobustCommand \AtBeginDvi [1]{% +% \global \setbox \@begindvibox +% \vbox{\unvbox \@begindvibox #1}% +%} % \end{macrocode} % \end{macro} % \end{macro} diff --git a/Master/texmf-dist/source/latex/base/ltpage.dtx b/Master/texmf-dist/source/latex/base/ltpage.dtx index f926f330605..8c7aac0a7b8 100644 --- a/Master/texmf-dist/source/latex/base/ltpage.dtx +++ b/Master/texmf-dist/source/latex/base/ltpage.dtx @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltpage.dtx} - [2019/08/27 v1.0l LaTeX Kernel (page style setup)] + [2020/07/27 v1.0m LaTeX Kernel (page style setup)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltpage.dtx} @@ -201,8 +201,9 @@ % expansion, CAR} % \changes{v1.0j}{2000/05/26}{Reimplementation to fix expansion % error (pr/3203).} +% \changes{v1.0m}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\markboth[2]{% +\DeclareRobustCommand*\markboth[2]{% \begingroup \let\label\relax \let\index\relax \let\glossary\relax \unrestored@protected@xdef\@themark {{#1}{#2}}% @@ -212,8 +213,9 @@ \if@nobreak\ifvmode\nobreak\fi\fi} % \end{macrocode} % +% \changes{v1.0m}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\markright[1]{% +\DeclareRobustCommand*\markright[1]{% \begingroup \let\label\relax \let\index\relax \let\glossary\relax % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/base/ltpictur.dtx b/Master/texmf-dist/source/latex/base/ltpictur.dtx index 9440fc783ad..5bef40375cd 100644 --- a/Master/texmf-dist/source/latex/base/ltpictur.dtx +++ b/Master/texmf-dist/source/latex/base/ltpictur.dtx @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltpictur.dtx} - [2019/08/27 v1.1m LaTeX Kernel (Picture Mode)] + [2020/08/14 v1.2a LaTeX Kernel (Picture Mode)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltpictur.dtx} @@ -191,6 +191,46 @@ % \end{macro} % \end{macro} % +% \begin{macro}{\@defaultunitsset} +% \changes{v1.2a}{2020/08/15}{Macro added} +% Set a length register, |#1|, +% accepting number or an etex length expression, |#2|, +% with default unit, |#3|. +% +% The register name in |#1| can be prefixed by |\advance| so that +% the register is incremented by the supplied value. +% +% |\@defaultunitsset{\advance\@vxx}{\textwidth-15pt}\unitlength| +% +% |#3| can be a literal unit such as |cm| or a length register such +% as |\unitlength|. +% +% This is used in all |picture| commands that take picture coordinates. +% So |\put(2,2)| as previously but now |\put(\textwidth-5cm,0.4\texteight)| +% Note that you can only use expressions with lengths, |\put(1+2,0)| is not +% supported. +% +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@defaultunitsset}{default units}% +\def\@defaultunitsset#1#2#3{% + \@defaultunits#1\dimexpr#2#3\relax\relax\@nnil} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@defaultunitsset}{default units}% +%<latexrelease>\let\@defaultunitsset\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{picture} % \begin{macro}{\picture} % \changes{v0.1c}{1994/04/28}{(DPC) Ignore spaces before (} % |#1| should be white space. @@ -207,12 +247,34 @@ % % \begin{macro}{\@picture} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@picture}{default units}% \def\@picture(#1,#2)(#3,#4){% - \@picht#2\unitlength - \setbox\@picbox\hb@xt@#1\unitlength\bgroup - \hskip -#3\unitlength - \lower #4\unitlength\hbox\bgroup + \@defaultunitsset\@picht{#2}\unitlength + \@defaultunitsset\@tempdimc{#1}\unitlength + \setbox\@picbox\hb@xt@\@tempdimc\bgroup + \@defaultunitsset\@tempdimc{#3}\unitlength + \hskip -\@tempdimc + \@defaultunitsset\@tempdimc{#4}\unitlength + \lower\@tempdimc\hbox\bgroup \ignorespaces} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@picture}{default units}% +%<latexrelease>\def\@picture(#1,#2)(#3,#4){% +%<latexrelease> \@picht#2\unitlength +%<latexrelease> \setbox\@picbox\hb@xt@#1\unitlength\bgroup +%<latexrelease> \hskip -#3\unitlength +%<latexrelease> \lower #4\unitlength\hbox\bgroup +%<latexrelease> \ignorespaces} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -229,16 +291,41 @@ \mbox{\box\@picbox}} % \end{macrocode} % \end{macro} +% \end{environment} % % In the definitions of |\put| and |\multiput|, |\hskip| was replaced by % |\kern| just in case arg |#3| = ``plus''. (Bug detected by Don Knuth. % changed 20 Jul 87). % % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\put}{default units}% +%<latexrelease>\expandafter\let\csname put \endcsname\@undefind \long\def\put(#1,#2)#3{% - \@killglue\raise#2\unitlength - \hb@xt@\z@{\kern#1\unitlength #3\hss}% + \@killglue + \@defaultunitsset\@tempdimc{#2}\unitlength + \raise\@tempdimc + \hb@xt@\z@{% + \@defaultunitsset\@tempdimc{#1}\unitlength + \kern\@tempdimc + #3\hss}% \ignorespaces} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\put}{default units}% +%<latexrelease>\expandafter\let\csname put \endcsname\@undefind +%<latexrelease>\long\def\put(#1,#2)#3{% +%<latexrelease> \@killglue\raise#2\unitlength +%<latexrelease> \hb@xt@\z@{\kern#1\unitlength #3\hss}% +%<latexrelease> \ignorespaces} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % % @@ -246,23 +333,63 @@ % \changes{v0.1c}{1994/04/28}{(DPC) Ignore spaces between )(} % |#3| had better be a |(|. % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\multiput}{default units}% +%<latexrelease>\expandafter\let\csname multiput \endcsname\@undefind \def\multiput(#1,#2)#3{% - \@xdim #1\unitlength - \@ydim #2\unitlength + \@defaultunitsset\@xdim{#1}\unitlength + \@defaultunitsset\@ydim{#2}\unitlength \@multiput(} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\multiput}{default units}% +%<latexrelease>\expandafter\let\csname multiput \endcsname\@undefind +%<latexrelease>\def\multiput(#1,#2)#3{% +%<latexrelease> \@xdim #1\unitlength +%<latexrelease> \@ydim #2\unitlength +%<latexrelease> \@multiput(} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % -% \begin{macro}{\multiput} +% \begin{macro}{\@multiput} % \changes{v0.1c}{1994/04/28}{(DPC) Macro added} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@multiput}{default units}% \long\def\@multiput(#1,#2)#3#4{% \@killglue\@multicnt #3\relax \@whilenum \@multicnt >\z@\do {\raise\@ydim\hb@xt@\z@{\kern\@xdim #4\hss}% \advance\@multicnt\m@ne - \advance\@xdim#1\unitlength\advance\@ydim#2\unitlength}% + \@defaultunitsset{\advance\@xdim}{#1}\unitlength + \@defaultunitsset{\advance\@ydim}{#2}\unitlength}% \ignorespaces} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@multiput}{default units}% +%<latexrelease>\long\def\@multiput(#1,#2)#3#4{% +%<latexrelease> \@killglue\@multicnt #3\relax +%<latexrelease> \@whilenum \@multicnt >\z@\do +%<latexrelease> {\raise\@ydim\hb@xt@\z@{\kern\@xdim #4\hss}% +%<latexrelease> \advance\@multicnt\m@ne +%<latexrelease> \advance\@xdim#1\unitlength\advance\@ydim#2\unitlength}% +%<latexrelease> \ignorespaces} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -275,18 +402,22 @@ % \begin{macro}{\thinlines} % \begin{macro}{\thicklines} % \begin{macrocode} -\DeclareRobustCommand\thinlines{\let\@linefnt\tenln \let\@circlefnt\tencirc +\DeclareRobustCommand\thinlines{\let\@linefnt\tenln + \let\@circlefnt\tencirc \@wholewidth\fontdimen8\tenln \@halfwidth .5\@wholewidth} -\DeclareRobustCommand\thicklines{\let\@linefnt\tenlnw \let\@circlefnt\tencircw +\DeclareRobustCommand\thicklines{\let\@linefnt\tenlnw + \let\@circlefnt\tencircw \@wholewidth\fontdimen8\tenlnw \@halfwidth .5\@wholewidth} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\linethickness} +% \changes{v1.1n}{2020/02/14}{Suppress spaces following the declaration (gh/274)} +% \changes{v1.1p}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\linethickness[1] - {\@wholewidth #1\relax \@halfwidth .5\@wholewidth} +\DeclareRobustCommand*\linethickness[1] + {\@wholewidth #1\relax \@halfwidth .5\@wholewidth \ignorespaces} % \end{macrocode} % \end{macro} % @@ -332,8 +463,24 @@ % \end{macro} % % \begin{macro}{\@istackcr} +% \changes{v1.1o}{2020/04/21}{Support calc syntax (gh/152)} % \begin{macrocode} -\def\@istackcr[#1]{\cr\noalign{\vskip #1}\ignorespaces} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@istackcr}{\shortstack calc support}% +\def\@istackcr[#1]{\cr\noalign{\@vspace@calcify{#1}}\ignorespaces} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@istackcr}{\shortstack calc support}% +%<latexrelease> +%<latexrelease>\def\@istackcr[#1]{\cr\noalign{\vskip #1}\ignorespaces} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -510,13 +657,35 @@ % % \begin{macro}{\line} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\line}{default units}% +%<latexrelease>\expandafter\let\csname line \endcsname\@undefind \def\line(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax - \@linelen #3\unitlength + \@defaultunitsset\@linelen{#3}\unitlength \ifdim\@linelen<\z@\@badlinearg\else \ifnum\@xarg =\z@ \@vline \else \ifnum\@yarg =\z@ \@hline \else \@sline\fi \fi \fi} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\line}{default units}% +%<latexrelease>\expandafter\let\csname line \endcsname\@undefind +%<latexrelease>\def\line(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax +%<latexrelease> \@linelen #3\unitlength +%<latexrelease> \ifdim\@linelen<\z@\@badlinearg\else +%<latexrelease> \ifnum\@xarg =\z@ \@vline +%<latexrelease> \else \ifnum\@yarg =\z@ \@hline \else \@sline\fi +%<latexrelease> \fi +%<latexrelease> \fi} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -600,16 +769,41 @@ % % \begin{macro}{\vector} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\vector}{default units}% +%<latexrelease>\expandafter\let\csname vector \endcsname\@undefind \def\vector(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax \@tempcnta \ifnum\@xarg<\z@ -\@xarg\else\@xarg\fi \ifnum\@tempcnta<5\relax - \@linelen #3\unitlength + \@defaultunitsset\@linelen{#3}\unitlength \ifdim\@linelen<\z@\@badlinearg\else \ifnum\@xarg =\z@ \@vvector \else \ifnum\@yarg =\z@ \@hvector \else \@svector\fi \fi \fi \else\@badlinearg\fi} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\vector}{default units}% +%<latexrelease>\expandafter\let\csname vector \endcsname\@undefind +%<latexrelease>\def\vector(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax +%<latexrelease> \@tempcnta \ifnum\@xarg<\z@ -\@xarg\else\@xarg\fi +%<latexrelease> \ifnum\@tempcnta<5\relax +%<latexrelease> \@linelen #3\unitlength +%<latexrelease> \ifdim\@linelen<\z@\@badlinearg\else +%<latexrelease> \ifnum\@xarg =\z@ \@vvector +%<latexrelease> \else \ifnum\@yarg =\z@ \@hvector \else \@svector\fi +%<latexrelease> \fi +%<latexrelease> \fi +%<latexrelease> \else\@badlinearg\fi} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -803,11 +997,17 @@ % % \begin{macro}{\dashbox} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\dashbox}{default units}% +%<latexrelease>\expandafter\let\csname dashbox \endcsname\@undefind \def\dashbox#1(#2,#3){\leavevmode\hb@xt@\z@{\baselineskip \z@skip \lineskip \z@skip -\@dashdim #2\unitlength +\@defaultunitsset\@dashdim{#2}\unitlength \@dashcnt \@dashdim \advance\@dashcnt 200 -\@dashdim #1\unitlength\divide\@dashcnt \@dashdim +\@defaultunitsset\@dashdim{#1}\unitlength +\divide\@dashcnt \@dashdim \ifodd\@dashcnt\@dashdim \z@ \advance\@dashcnt \@ne \divide\@dashcnt \tw@ \else \divide\@dashdim \tw@ \divide\@dashcnt \tw@ @@ -819,15 +1019,19 @@ \put(#2,#3){\hskip-\@dashdim\box\@dashbox}% \multiply\@dashdim \thr@@ \fi -\setbox\@dashbox \hbox{\vrule \@height \@halfwidth \@depth \@halfwidth -\@width #1\unitlength\hskip #1\unitlength}\@tempcnta\z@ +\setbox\@dashbox \hbox{% + \@defaultunitsset\@tempdimc{#1}\unitlength + \vrule \@height \@halfwidth \@depth \@halfwidth \@width \@tempdimc + \hskip\@tempdimc}% +\@tempcnta\z@ \put(0,0){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt \do{\copy\@dashbox\advance\@tempcnta \@ne }}\@tempcnta\z@ \put(0,#3){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt \do{\copy\@dashbox\advance\@tempcnta \@ne }}% -\@dashdim #3\unitlength +\@defaultunitsset\@dashdim{#3}\unitlength \@dashcnt \@dashdim \advance\@dashcnt 200 -\@dashdim #1\unitlength\divide\@dashcnt \@dashdim +\@defaultunitsset\@dashdim{#1}\unitlength +\divide\@dashcnt \@dashdim \ifodd\@dashcnt \@dashdim \z@ \advance\@dashcnt \@ne \divide\@dashcnt \tw@ \else @@ -841,14 +1045,79 @@ \put(#2,#3){\lower\@dashdim\copy\@dashbox}% \multiply\@dashdim \thr@@ \fi -\setbox\@dashbox\hbox{\vrule \@width \@wholewidth -\@height #1\unitlength}\@tempcnta\z@ +\@defaultunitsset\@tempdimb{#1}\unitlength +\setbox\@dashbox\hbox{% + \vrule \@width \@wholewidth \@height\@tempdimb}% +\@tempcnta\z@ \put(0,0){\hskip -\@halfwidth \vbox{\@whilenum \@tempcnta <\@dashcnt -\do{\vskip #1\unitlength\copy\@dashbox\advance\@tempcnta \@ne }% +\do{\vskip\@tempdimb\copy\@dashbox\advance\@tempcnta \@ne }% \vskip\@dashdim}}\@tempcnta\z@ \put(#2,0){\hskip -\@halfwidth \vbox{\@whilenum \@tempcnta<\@dashcnt -\do{\vskip #1\unitlength\copy\@dashbox\advance\@tempcnta \@ne }% +\do{\vskip\@tempdimb\copy\@dashbox\advance\@tempcnta \@ne }% \vskip\@dashdim}}}\@makepicbox(#2,#3)} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\dashbox}{default units}% +%<latexrelease>\expandafter\let\csname dashbox \endcsname\@undefind +%<latexrelease>\def\dashbox#1(#2,#3){% +%<latexrelease>\leavevmode\hb@xt@\z@{\baselineskip \z@skip +%<latexrelease>\lineskip \z@skip +%<latexrelease>\@dashdim #2\unitlength +%<latexrelease>\@dashcnt \@dashdim \advance\@dashcnt 200 +%<latexrelease>\@dashdim #1\unitlength\divide\@dashcnt \@dashdim +%<latexrelease>\ifodd\@dashcnt\@dashdim \z@ +%<latexrelease>\advance\@dashcnt \@ne \divide\@dashcnt \tw@ +%<latexrelease>\else \divide\@dashdim \tw@ \divide\@dashcnt \tw@ +%<latexrelease>\advance\@dashcnt \m@ne +%<latexrelease>\setbox\@dashbox \hbox{% +%<latexrelease> \vrule \@height \@halfwidth \@depth \@halfwidth +%<latexrelease> \@width \@dashdim}\put(0,0){\copy\@dashbox}% +%<latexrelease>\put(0,#3){\copy\@dashbox}% +%<latexrelease>\put(#2,0){\hskip-\@dashdim\copy\@dashbox}% +%<latexrelease>\put(#2,#3){\hskip-\@dashdim\box\@dashbox}% +%<latexrelease>\multiply\@dashdim \thr@@ +%<latexrelease>\fi +%<latexrelease>\setbox\@dashbox \hbox{% +%<latexrelease> \vrule \@height \@halfwidth \@depth \@halfwidth +%<latexrelease> \@width #1\unitlength\hskip #1\unitlength}\@tempcnta\z@ +%<latexrelease>\put(0,0){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt +%<latexrelease>\do{\copy\@dashbox\advance\@tempcnta \@ne }}\@tempcnta\z@ +%<latexrelease>\put(0,#3){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt +%<latexrelease>\do{\copy\@dashbox\advance\@tempcnta \@ne }}% +%<latexrelease>\@dashdim #3\unitlength +%<latexrelease>\@dashcnt \@dashdim \advance\@dashcnt 200 +%<latexrelease>\@dashdim #1\unitlength\divide\@dashcnt \@dashdim +%<latexrelease>\ifodd\@dashcnt \@dashdim \z@ +%<latexrelease>\advance\@dashcnt \@ne \divide\@dashcnt \tw@ +%<latexrelease>\else +%<latexrelease>\divide\@dashdim \tw@ \divide\@dashcnt \tw@ +%<latexrelease>\advance\@dashcnt \m@ne +%<latexrelease>\setbox\@dashbox\hbox{\hskip -\@halfwidth +%<latexrelease>\vrule \@width \@wholewidth +%<latexrelease>\@height \@dashdim}\put(0,0){\copy\@dashbox}% +%<latexrelease>\put(#2,0){\copy\@dashbox}% +%<latexrelease>\put(0,#3){\lower\@dashdim\copy\@dashbox}% +%<latexrelease>\put(#2,#3){\lower\@dashdim\copy\@dashbox}% +%<latexrelease>\multiply\@dashdim \thr@@ +%<latexrelease>\fi +%<latexrelease>\setbox\@dashbox\hbox{\vrule \@width \@wholewidth +%<latexrelease>\@height #1\unitlength}\@tempcnta\z@ +%<latexrelease>\put(0,0){% +%<latexrelease> \hskip -\@halfwidth \vbox{\@whilenum \@tempcnta <\@dashcnt +%<latexrelease> \do{\vskip #1\unitlength\copy\@dashbox +%<latexrelease> \advance\@tempcnta\@ne }% +%<latexrelease> \vskip\@dashdim}}\@tempcnta\z@ +%<latexrelease>\put(#2,0){% +%<latexrelease> \hskip -\@halfwidth \vbox{\@whilenum \@tempcnta<\@dashcnt +%<latexrelease> \do{\vskip #1\unitlength\copy\@dashbox +%<latexrelease> \advance\@tempcnta \@ne }% +%<latexrelease> \vskip\@dashdim}}}\@makepicbox(#2,#3)} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -1143,12 +1412,26 @@ % \begin{macrocode} \newif\if@ovvline \@ovvlinetrue \newif\if@ovhline \@ovhlinetrue +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@ovhlinetrue}% +%<latexrelease> {Avoid almost zero length leaders}% +%<latexrelease>\let\if@ovvline\@undefined +%<latexrelease>\let\if@ovhline\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@oval} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@oval}{default units}% \def\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue % \end{macrocode} @@ -1157,9 +1440,10 @@ \@ovvlinefalse \@ovhlinefalse % \end{macrocode} % \begin{macrocode} - \@tfor\reserved@a :=#3\do{\csname @ov\reserved@a false\endcsname}% - \@ovxx #1\unitlength - \@ovyy #2\unitlength + \@tfor\reserved@a :=#3\do{% + \csname @ov\reserved@a false\endcsname}% + \@defaultunitsset\@ovxx{#1}\unitlength + \@defaultunitsset\@ovyy{#2}\unitlength % \end{macrocode} % \changes{v1.1l}{2016/03/29}{add setting of line tests} % \begin{macrocode} @@ -1187,11 +1471,79 @@ \advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@ \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}% \endgroup} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2016/03/31}% +%<latexrelease> {\@oval}{default units}% +%<latexrelease>\def\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen +%<latexrelease> \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue +%<latexrelease> \@ovvlinefalse \@ovhlinefalse +%<latexrelease> \@tfor\reserved@a :=#3\do{% +%<latexrelease> \csname @ov\reserved@a false\endcsname}% +%<latexrelease> \@ovxx #1\unitlength +%<latexrelease> \@ovyy #2\unitlength +%<latexrelease> \@tempdimb \ifdim \@ovyy >\@ovxx \@ovxx \@ovvlinetrue +%<latexrelease> \else \@ovyy \ifdim \@ovyy =\@ovxx \else \@ovhlinetrue +%<latexrelease> \fi\fi +%<latexrelease> \advance \@tempdimb -2\p@ +%<latexrelease> \@getcirc \@tempdimb +%<latexrelease> \@ovro \ht\@tempboxa \@ovri \dp\@tempboxa +%<latexrelease> \@ovdx\@ovxx \advance\@ovdx -\@tempdima \divide\@ovdx \tw@ +%<latexrelease> \@ovdy\@ovyy \advance\@ovdy -\@tempdima \divide\@ovdy \tw@ +%<latexrelease> \ifdim \@ovdx >\z@ \@ovhlinetrue \fi +%<latexrelease> \ifdim \@ovdy >\z@ \@ovvlinetrue \fi +%<latexrelease> \@circlefnt \setbox\@tempboxa +%<latexrelease> \hbox{\if@ovr \@ovvert32\kern -\@tempdima \fi +%<latexrelease> \if@ovl +%<latexrelease> \kern \@ovxx \@ovvert01\kern -\@tempdima \kern -\@ovxx +%<latexrelease> \fi +%<latexrelease> \if@ovt \@ovhorz \kern -\@ovxx \fi +%<latexrelease> \if@ovb \raise \@ovyy \@ovhorz \fi}\advance\@ovdx\@ovro +%<latexrelease> \advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@ +%<latexrelease> \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}% +%<latexrelease> \endgroup} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@oval}{default units}% +%<latexrelease>\def\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen +%<latexrelease> \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue +%<latexrelease> \@tfor\reserved@a :=#3\do +%<latexrelease> {\csname @ov\reserved@a false\endcsname}% +%<latexrelease> \@ovxx #1\unitlength +%<latexrelease> \@ovyy #2\unitlength +%<latexrelease> \@tempdimb \ifdim \@ovyy >\@ovxx \@ovxx\else \@ovyy \fi +%<latexrelease> \advance \@tempdimb -2\p@ +%<latexrelease> \@getcirc \@tempdimb +%<latexrelease> \@ovro \ht\@tempboxa \@ovri \dp\@tempboxa +%<latexrelease> \@ovdx\@ovxx \advance\@ovdx -\@tempdima \divide\@ovdx \tw@ +%<latexrelease> \@ovdy\@ovyy \advance\@ovdy -\@tempdima \divide\@ovdy \tw@ +%<latexrelease> \@circlefnt \setbox\@tempboxa +%<latexrelease> \hbox{\if@ovr \@ovvert32\kern -\@tempdima \fi +%<latexrelease> \if@ovl +%<latexrelease> \kern \@ovxx \@ovvert01\kern -\@tempdima \kern -\@ovxx +%<latexrelease> \fi +%<latexrelease> \if@ovt \@ovhorz \kern -\@ovxx \fi +%<latexrelease> \if@ovb \raise \@ovyy \@ovhorz \fi}\advance\@ovdx\@ovro +%<latexrelease> \advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@ +%<latexrelease> \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}% +%<latexrelease> \endgroup} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % % \begin{macro}{\@ovvert} % \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2016/03/31}% +%<latexrelease> {\@ovvert}{Avoid almost zero length leaders}% +%<*2ekernel|latexrelease> \def\@ovvert#1#2{\vbox to\@ovyy{% \if@ovb \@tempcntb \@tempcnta \advance \@tempcntb #1\relax \kern -\@ovro \hbox{\char \@tempcntb}\nointerlineskip @@ -1207,11 +1559,32 @@ \if@ovt \@tempcntb \@tempcnta \advance \@tempcntb #2\relax \hbox{\char \@tempcntb}% \else \kern \@ovdy \kern \@ovro \fi}} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@ovvert}{Avoid almost zero length leaders}% +%<latexrelease>\def\@ovvert#1#2{\vbox to\@ovyy{% +%<latexrelease> \if@ovb \@tempcntb \@tempcnta \advance \@tempcntb #1\relax +%<latexrelease> \kern -\@ovro \hbox{\char \@tempcntb}\nointerlineskip +%<latexrelease> \else \kern \@ovri \kern \@ovdy \fi +%<latexrelease> \leaders\vrule \@width \@wholewidth\vfil \nointerlineskip +%<latexrelease> \if@ovt \@tempcntb \@tempcnta \advance \@tempcntb #2\relax +%<latexrelease> \hbox{\char \@tempcntb}% +%<latexrelease> \else \kern \@ovdy \kern \@ovro \fi}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % % \begin{macro}{\@ovhorz} % \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2016/03/31}% +%<latexrelease> {\@ovhorz}{Avoid almost zero length leaders}% +%<*2ekernel|latexrelease> \def\@ovhorz{\hb@xt@\@ovxx{\kern \@ovro \if@ovr \else \kern \@ovdx \fi % \end{macrocode} @@ -1220,51 +1593,18 @@ % \begin{macrocode} \if@ovhline \leaders \hrule \@height \@wholewidth \fi % \end{macrocode} +% % \begin{macrocode} \hfil \if@ovl \else \kern \@ovdx \fi \kern \@ovri}} +%</2ekernel|latexrelease> % \end{macrocode} -% \end{macro} -% +% % \begin{macrocode} -%</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% -%<latexrelease> {\@ovhlinetrue}% -%<latexrelease> {Avoid almost zero length leaders}% -%<latexrelease>\let\if@ovvline\@undefined -%<latexrelease>\let\if@ovhline\@undefined -%<latexrelease>\def\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen -%<latexrelease> \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue -%<latexrelease> \@tfor\reserved@a :=#3\do -%<latexrelease> {\csname @ov\reserved@a false\endcsname}% -%<latexrelease> \@ovxx #1\unitlength -%<latexrelease> \@ovyy #2\unitlength -%<latexrelease> \@tempdimb \ifdim \@ovyy >\@ovxx \@ovxx\else \@ovyy \fi -%<latexrelease> \advance \@tempdimb -2\p@ -%<latexrelease> \@getcirc \@tempdimb -%<latexrelease> \@ovro \ht\@tempboxa \@ovri \dp\@tempboxa -%<latexrelease> \@ovdx\@ovxx \advance\@ovdx -\@tempdima \divide\@ovdx \tw@ -%<latexrelease> \@ovdy\@ovyy \advance\@ovdy -\@tempdima \divide\@ovdy \tw@ -%<latexrelease> \@circlefnt \setbox\@tempboxa -%<latexrelease> \hbox{\if@ovr \@ovvert32\kern -\@tempdima \fi -%<latexrelease> \if@ovl -%<latexrelease> \kern \@ovxx \@ovvert01\kern -\@tempdima \kern -\@ovxx -%<latexrelease> \fi -%<latexrelease> \if@ovt \@ovhorz \kern -\@ovxx \fi -%<latexrelease> \if@ovb \raise \@ovyy \@ovhorz \fi}\advance\@ovdx\@ovro -%<latexrelease> \advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@ -%<latexrelease> \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}% -%<latexrelease> \endgroup} -%<latexrelease>\def\@ovvert#1#2{\vbox to\@ovyy{% -%<latexrelease> \if@ovb \@tempcntb \@tempcnta \advance \@tempcntb #1\relax -%<latexrelease> \kern -\@ovro \hbox{\char \@tempcntb}\nointerlineskip -%<latexrelease> \else \kern \@ovri \kern \@ovdy \fi -%<latexrelease> \leaders\vrule \@width \@wholewidth\vfil \nointerlineskip -%<latexrelease> \if@ovt \@tempcntb \@tempcnta \advance \@tempcntb #2\relax -%<latexrelease> \hbox{\char \@tempcntb}% -%<latexrelease> \else \kern \@ovdy \kern \@ovro \fi}} +%<latexrelease> {\@ovhorz}{Avoid almost zero length leaders}% %<latexrelease>\def\@ovhorz{\hb@xt@\@ovxx{\kern \@ovro %<latexrelease> \if@ovr \else \kern \@ovdx \fi %<latexrelease> \leaders \hrule \@height \@wholewidth \hfil @@ -1273,6 +1613,7 @@ %<latexrelease>\EndIncludeInRelease %<*2ekernel> % \end{macrocode} +% \end{macro} % % \begin{macro}{\circle} % \changes{LaTeX2.09}{1993/08/05} @@ -1284,8 +1625,13 @@ % % \begin{macro}{\@circle} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@circle}{default units}% \def\@circle#1{% - \begingroup \boxmaxdepth \maxdimen \@tempdimb #1\unitlength + \begingroup \boxmaxdepth \maxdimen + \@defaultunitsset\@tempdimb{#1}\unitlength \ifdim \@tempdimb >15.5\p@ \@getcirc\@tempdimb \@ovro\ht\@tempboxa \setbox\@tempboxa\hbox{\@circlefnt @@ -1296,13 +1642,52 @@ \box\@tempboxa}\ht\@tempboxa\z@ \dp\@tempboxa\z@ \@put{-\@ovro}{-\@ovro}{\box\@tempboxa}% \else \@circ\@tempdimb{96}\fi\endgroup} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@circle}{default units}% +%<latexrelease>\def\@circle#1{% +%<latexrelease> \begingroup \boxmaxdepth \maxdimen \@tempdimb #1\unitlength +%<latexrelease> \ifdim \@tempdimb >15.5\p@ \@getcirc\@tempdimb +%<latexrelease> \@ovro\ht\@tempboxa +%<latexrelease> \setbox\@tempboxa\hbox{\@circlefnt +%<latexrelease> \advance\@tempcnta\tw@ \char \@tempcnta +%<latexrelease> \advance\@tempcnta\m@ne \char \@tempcnta +%<latexrelease> \kern -2\@tempdima +%<latexrelease> \advance\@tempcnta\tw@ +%<latexrelease> \raise \@tempdima \hbox{\char\@tempcnta}% +%<latexrelease> \raise \@tempdima +%<latexrelease> \box\@tempboxa}\ht\@tempboxa\z@ \dp\@tempboxa\z@ +%<latexrelease> \@put{-\@ovro}{-\@ovro}{\box\@tempboxa}% +%<latexrelease> \else \@circ\@tempdimb{96}\fi\endgroup} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % % \begin{macro}{\@dot} % Internal form of |\circle*|. % \begin{macrocode} -\def\@dot#1{\@tempdimb #1\unitlength \@circ\@tempdimb{112}} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@dot}{default units}% +\def\@dot#1{% + \@defaultunitsset\@tempdimb{#1}\unitlength + \@circ\@tempdimb{112}} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@dot}{default units}% +%<latexrelease>\def\@dot#1{\@tempdimb #1\unitlength \@circ\@tempdimb{112}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -1340,7 +1725,7 @@ % \end{macro} % % \begin{macro}{\@xdim} -% \begin{macro}{\yxdim} +% \begin{macro}{\@ydim} % Length registers. % \begin{macrocode} \newdimen\@xdim @@ -1482,35 +1867,45 @@ % % \begin{macro}{\@bezier} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@bezier}{default units}% \def\@bezier#1(#2,#3)(#4,#5)(#6,#7){% \ifnum #1=\z@ - \@ovxx #4\unitlength - \advance\@ovxx -#2\unitlength + \@defaultunitsset\@ovxx{#4}\unitlength + \@defaultunitsset{\advance\@ovxx}{-#2}\unitlength \ifdim \@ovxx<\z@ \@ovxx -\@ovxx \fi - \@ovdx #6\unitlength - \advance\@ovdx -#4\unitlength + \@defaultunitsset\@ovdx{#6}\unitlength + \@defaultunitsset{\advance\@ovdx}{-#4}\unitlength \ifdim \@ovdx<\z@ \@ovdx -\@ovdx \fi \ifdim \@ovxx<\@ovdx \@ovxx \@ovdx \fi - \@ovyy #5\unitlength - \advance\@ovyy -#3\unitlength + \@defaultunitsset\@ovyy{#5}\unitlength + \@defaultunitsset{\advance\@ovyy}{-#3}\unitlength \ifdim \@ovyy<\z@ \@ovyy -\@ovyy \fi - \@ovdy #7\unitlength - \advance\@ovdy -#5\unitlength + \@defaultunitsset\@ovdy{#7}\unitlength + \@defaultunitsset{\advance\@ovdy}{-#5}\unitlength \ifdim \@ovdy<\z@ \@ovdy -\@ovdy \fi \ifdim \@ovyy<\@ovdy \@ovyy \@ovdy \fi \@multicnt \ifdim \@ovxx>\@ovyy \@ovxx \else \@ovyy \fi \@ovxx .5\@halfwidth \divide\@multicnt\@ovxx - \ifnum \qbeziermax<\@multicnt \@multicnt\qbeziermax\relax \fi + \ifnum \qbeziermax<\@multicnt + \@multicnt\qbeziermax\relax + \fi \else \@multicnt#1\relax \fi \@tempcnta\@multicnt \advance\@tempcnta\@ne - \@ovdx #4\unitlength \advance\@ovdx -#2\unitlength + \@defaultunitsset\@ovdx{#4}\unitlength + \@defaultunitsset{\advance\@ovdx}{-#2}\unitlength \multiply\@ovdx \tw@ - \@ovxx #6\unitlength \advance\@ovxx -#2\unitlength + \@defaultunitsset\@ovxx{#6}\unitlength + \@defaultunitsset{\advance\@ovxx}{-#2}\unitlength \advance\@ovxx -\@ovdx \divide\@ovxx\@multicnt - \@ovdy #5\unitlength \advance\@ovdy -#3\unitlength + \@defaultunitsset\@ovdy{#5}\unitlength + \@defaultunitsset{\advance\@ovdy}{-#3}\unitlength \multiply\@ovdy \tw@ - \@ovyy #7\unitlength \advance\@ovyy -#3\unitlength + \@defaultunitsset\@ovyy{#7}\unitlength + \@defaultunitsset{\advance\@ovyy}{-#3}\unitlength \advance\@ovyy -\@ovdy \divide\@ovyy\@multicnt % \end{macrocode} % @@ -1536,6 +1931,67 @@ \hb@xt@\z@{\kern\@xdim \unhcopy\@tempboxa\hss}% \advance\count@\@ne}}} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@bezier}{default units}% +%<latexrelease>\def\@bezier#1(#2,#3)(#4,#5)(#6,#7){% +%<latexrelease> \ifnum #1=\z@ +%<latexrelease> \@ovxx #4\unitlength +%<latexrelease> \advance\@ovxx -#2\unitlength +%<latexrelease> \ifdim \@ovxx<\z@ \@ovxx -\@ovxx \fi +%<latexrelease> \@ovdx #6\unitlength +%<latexrelease> \advance\@ovdx -#4\unitlength +%<latexrelease> \ifdim \@ovdx<\z@ \@ovdx -\@ovdx \fi +%<latexrelease> \ifdim \@ovxx<\@ovdx \@ovxx \@ovdx \fi +%<latexrelease> \@ovyy #5\unitlength +%<latexrelease> \advance\@ovyy -#3\unitlength +%<latexrelease> \ifdim \@ovyy<\z@ \@ovyy -\@ovyy \fi +%<latexrelease> \@ovdy #7\unitlength +%<latexrelease> \advance\@ovdy -#5\unitlength +%<latexrelease> \ifdim \@ovdy<\z@ \@ovdy -\@ovdy \fi +%<latexrelease> \ifdim \@ovyy<\@ovdy \@ovyy \@ovdy \fi +%<latexrelease> \@multicnt +%<latexrelease> \ifdim \@ovxx>\@ovyy \@ovxx \else \@ovyy \fi +%<latexrelease> \@ovxx .5\@halfwidth \divide\@multicnt\@ovxx +%<latexrelease> \ifnum +%<latexrelease> \qbeziermax<\@multicnt \@multicnt\qbeziermax\relax +%<latexrelease> \fi +%<latexrelease> \else \@multicnt#1\relax \fi +%<latexrelease> \@tempcnta\@multicnt \advance\@tempcnta\@ne +%<latexrelease> \@ovdx #4\unitlength \advance\@ovdx -#2\unitlength +%<latexrelease> \multiply\@ovdx \tw@ +%<latexrelease> \@ovxx #6\unitlength \advance\@ovxx -#2\unitlength +%<latexrelease> \advance\@ovxx -\@ovdx \divide\@ovxx\@multicnt +%<latexrelease> \@ovdy #5\unitlength \advance\@ovdy -#3\unitlength +%<latexrelease> \multiply\@ovdy \tw@ +%<latexrelease> \@ovyy #7\unitlength \advance\@ovyy -#3\unitlength +%<latexrelease> \advance\@ovyy -\@ovdy \divide\@ovyy\@multicnt +%<latexrelease> \setbox\@tempboxa\hbox{% +%<latexrelease> \hskip -\@halfwidth +%<latexrelease> \vrule \@height\@halfwidth +%<latexrelease> \@depth \@halfwidth +%<latexrelease> \@width \@wholewidth}% +%<latexrelease> \put(#2,#3){% +%<latexrelease> \count@\z@ +%<latexrelease> \@whilenum{\count@<\@tempcnta}\do +%<latexrelease> {\@xdim\count@\@ovxx +%<latexrelease> \advance\@xdim\@ovdx +%<latexrelease> \divide\@xdim\@multicnt +%<latexrelease> \multiply\@xdim\count@ +%<latexrelease> \@ydim\count@\@ovyy +%<latexrelease> \advance\@ydim\@ovdy +%<latexrelease> \divide\@ydim\@multicnt +%<latexrelease> \multiply\@ydim\count@ +%<latexrelease> \raise \@ydim +%<latexrelease> \hb@xt@\z@{\kern\@xdim +%<latexrelease> \unhcopy\@tempboxa\hss}% +%<latexrelease> \advance\count@\@ne}}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % \end{macro} diff --git a/Master/texmf-dist/source/latex/base/ltplain.dtx b/Master/texmf-dist/source/latex/base/ltplain.dtx index 06602780664..7949b836d46 100644 --- a/Master/texmf-dist/source/latex/base/ltplain.dtx +++ b/Master/texmf-dist/source/latex/base/ltplain.dtx @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltplain.dtx} - [2017/04/10 v2.3c LaTeX Kernel (Plain TeX)] + [2020/08/20 v2.3d LaTeX Kernel (Plain TeX)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltplain.dtx} @@ -691,12 +691,32 @@ % \end{macro} % % \begin{macro}{\alloc@} +% \changes{v2.3d}{2020/08/20} +% {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 +% run out, so it is now defined to call |\e@alloc| internally. % \begin{macrocode} -\def\alloc@#1#2#3#4#5{\global\advance\count1#1\@ne - \ch@ck#1#4#2% - \allocationnumber\count1#1% - \global#3#5\allocationnumber - \wlog{\string#5=\string#2\the\allocationnumber}} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01} +%<latexrelease> {\alloc@}{emulate alloc@}% +\def\alloc@#1#2#3#4{\e@alloc#2#3{\count1#1}#4\float@count} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\alloc@}{emulate alloc@}% +%<latexrelease>\def\alloc@#1#2#3#4#5{\global\advance\count1#1\@ne +%<latexrelease> \ch@ck#1#4#2% +%<latexrelease> \allocationnumber\count1#1% +%<latexrelease> \global#3#5\allocationnumber +%<latexrelease> \wlog{\string#5=\string#2\the\allocationnumber}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/base/ltsect.dtx b/Master/texmf-dist/source/latex/base/ltsect.dtx index 9ccd042fb4e..359b445f453 100644 --- a/Master/texmf-dist/source/latex/base/ltsect.dtx +++ b/Master/texmf-dist/source/latex/base/ltsect.dtx @@ -31,7 +31,7 @@ %%% From File: ltsect.dtx %<*driver> % \fi -\ProvidesFile{ltsect.dtx}[2019/08/27 v1.1d LaTeX Kernel (Sectioning)] +\ProvidesFile{ltsect.dtx}[2020/07/27 v1.1e LaTeX Kernel (Sectioning)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltsect.dtx} @@ -137,20 +137,22 @@ % % \begin{macro}{\author} % \changes{LaTeX2e}{1993/12/11}{Added default} +% \changes{v1.1e}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % % |\author| for use in |\maketitle|. If not given |\maketitle| will % produce a warning message. % % \begin{macrocode} -\DeclareRobustCommand\author[1]{\gdef\@author{#1}} +\DeclareRobustCommand*\author[1]{\gdef\@author{#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\date} % |\date| for use in |\maketitle|. If not given |\maketitle| will % produce |\today| as the default. +% \changes{v1.1e}{2020/07/27}{Don't make the command \cs{long} (gh/354)} % \begin{macrocode} -\DeclareRobustCommand\date[1]{\gdef\@date{#1}} +\DeclareRobustCommand*\date[1]{\gdef\@date{#1}} % \end{macrocode} % \end{macro} % @@ -776,20 +778,33 @@ % \cs{addcontentsline}. ASAJ.} % \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} % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\addcontentsline}{fourth argument}% +\def\addcontentsline#1#2#3{% +% \end{macrocode} +% We add an empty brace pair at the end of \cs{contentsline} +% so that the number of argument is identical in documents +% with and without hyperref. +% \begin{macrocode} + \addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}{}% + \protected@file@percent}} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{2018/12/01}% %<latexrelease> {\addcontentsline}{Mask line endings}% -\def\addcontentsline#1#2#3{% - \addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}% +%<latexrelease> \def\addcontentsline#1#2#3{% +%<latexrelease> \addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}% % \end{macrocode} % We add \cs{protected@file@percent} at the end which is turned inside % \cs{@writefile} into a percent character to mask the newline after % the closing argument brace. % \begin{macrocode} - \protected@file@percent}} -%</2ekernel|latexrelease> +%<latexrelease> \protected@file@percent}} %<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\addcontentsline}{Mask line endings}% diff --git a/Master/texmf-dist/source/latex/base/ltshipout.dtx b/Master/texmf-dist/source/latex/base/ltshipout.dtx new file mode 100644 index 00000000000..8f0422c887b --- /dev/null +++ b/Master/texmf-dist/source/latex/base/ltshipout.dtx @@ -0,0 +1,1739 @@ +% \iffalse meta-comment +%% +%% File: ltshipout.dtx (C) Copyright 2020 Frank Mittelbach, LaTeX Team +%% +% +% 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: ltshipout.dtx +% +% \begin{macrocode} +\providecommand\ltshipoutversion{v1.0c} +\providecommand\ltshipoutdate{2020/09/27} +% \end{macrocode} +% +%<*driver> + +\documentclass{l3doc} + +% bug fix fo l3doc.cls +\ExplSyntaxOn +\cs_set_protected:Npn \__codedoc_macro_typeset_one:nN #1#2 + { + \vbox_set:Nn \l__codedoc_macro_box + { + \vbox_unpack_drop:N \l__codedoc_macro_box + \hbox { \llap { \__codedoc_print_macroname:nN {#1} #2 + \MacroFont % <----- without it the \ is in lmr10 if a link is made + \ + } } + } + \int_incr:N \l__codedoc_macro_int + } +\ExplSyntaxOff + +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{ltshipout.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \long\def\fmi#1{\begin{quote}\itshape Todo: #1\end{quote}} +% +% \providecommand\hook[1]{\texttt{#1}} +% \providecommand\pkg[1]{\texttt{#1}} +% +% +% \title{The \texttt{ltshipout} package\thanks{This package has version +% \ltshipoutversion\ dated \ltshipoutdate, \copyright\ \LaTeX\ +% Project.}} +% +% \author{Frank Mittelbach} +% +% \maketitle +% +% +% \tableofcontents +% +% \section{Introduction} +% +% The code provides an interface to the \cs{shipout} primitive of +% \TeX{} which is called when a finished pages is finally +% \enquote{shipped out} to the target output file, e.g., the +% \texttt{.dvi} or \texttt{.pdf} file. +% A good portion of the code is based on ideas by Heiko Oberdiek +% implemented in his packages \pkg{atbegshi} and \pkg{atenddvi} +% even though the interfaces are somewhat +% different.\footnote{Heiko's interfaces are emulated by the kernel +% code, if a document requests his packages, so older documents +% will continue to work.} +% +% \subsection{Overloading the \cs{shipout} primitive} +% +% +% \begin{function}{\shipout} +% With this implementation \TeX's shipout primitive is no longer +% available for direct use. Instead \cs{shipout} is running some +% (complicated) code that picks up the box to be shipped out +% regardless of how that is done, i.e., as a constructed \cs{vbox} +% or \cs{hbox} or as a box register. +% +% 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. +% \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}). +% \end{variable} +% +% +% \begin{variable}{\l_shipout_box_ht_dim, +% \l_shipout_box_dp_dim,\l_shipout_box_wd_dim, +% \l_shipout_box_ht_plus_dp_dim} +% The shipout box dimensions are available in the L3 registers +% \cs{l_shipout_box_ht_dim}, etc.\ (there are no \LaTeXe{} +% names).\footnotemark{} These variables can be used +% inside the hook code for \hook{shipout/before}, +% \hook{shipout/foreground} and \hook{shipout/background} if needed. +% \end{variable} +% \footnotetext{Might need changing, but HO's version as strings +% is not really helpful I think).} +% +% +% +% +% \subsection{Provided hooks} +% +% \begin{variable}{shipout/before, +% shipout/foreground,shipout/background, +% shipout/firstpage, +% shipout/lastpage} +% The code offers a number of hooks into which packages (or the +% user) can add code to support different use cases. +% These are: +% \begin{description} +% \item[\hook{shipout/before}] +% +% This hook is executed after the finished page has been stored in +% \cs{ShipoutBox} / \cs{l_shipout_box}). +% It can be used to alter that box content or to discard it +% completely (see \cs{DiscardShipoutBox} below). +% +% \item[\hook{shipout/background}] +% +% This hook adds a picture environment into the background of +% the page with the \texttt{(0,0)} coordinate in the top-left +% corner using a \cs{unitlength} of \texttt{1pt}. +% +% It should therefore only receive \cs{put} commands or other +% commands suitable in a \texttt{picture} environment and the +% vertical coordinate values would normally be +% negative. +% +% Technically this is implemented by adding a zero-sized +% \cs{hbox} as the very first item into the \cs{ShipoutBox} +% containing that \texttt{picture} environment. Thus the rest of +% the box content will overprint what ever is typeset by that hook. +% +% +% \item[\hook{shipout/foreground}] +% +% This hook adds a picture environment into the foreground of +% the page with the \texttt{(0,0)} coordinate in the top-left +% corner using a \cs{unitlength} of \texttt{1pt}. +% +% Technically this is implemented by adding a zero-sized +% \cs{hbox} as the very last item into the \cs{ShipoutBox} and +% raising it up so that it still has its \texttt{(0,0)} point in +% the top-left corner. +% But being placed after the main box content it will be typeset +% later and thus overprints it (i.e., is in the foreground). +% +% +% \item[\hook{shipout/firstpage}] +% +% The material from this hook is executed only once at the very +% beginning of the first output page that is shipped out (i.e., +% 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 +% +% ^^A \fmi{not sure it has to be that restrictive.} +% +% +% \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 --- +% or rather on the page that \LaTeX{} believes is the last one. +% +% It may not be possible for \LaTeX{} to correctly determine +% which page is the last one without several reruns. If this +% happens and the hook is non-empty then \LaTeX{} will add an +% extra page to place the material and also request a rerun to +% get the correct placement sorted out. +% +% \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: +% \begin{center} +% \begin{tabular}{ll} +% \hook{shipout/firstpage} & only on the first page \\ +% \hook{shipout/background} & \\ +% \meta{boxed content of \cs{ShipoutBox}} & \\ +% \hook{shipout/foreground} & \\ +% \hook{shipout/lastpage} & only on the last page \\ +% \end{tabular} +% \end{center} +% If any of the hooks has no code then that particular no box is +% added at that point. +% +% 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{shipout}) not even the \hook{shipout/lastpage} hook. +% +% \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}. +% +% \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. +% +% \fmi{better names? Any suggestions?} +% +% \end{function} +% +% \subsection{Special commands for use inside the hooks} +% +% \begin{function}{\DiscardShipoutBox,\shipout_discard_box:} +% \begin{syntax} +% \cs{AddToHookNext} \texttt{\{shipout/before\} \{...\cs{DiscardShipoutBox}...\}} +% \end{syntax} +% The \cs{DiscardShipoutBox} declaration (L3 name +% \cs{shipout_discard_box:}) +% requests that on the next +% shipout the page box is thrown away instead of being shipped to +% the \texttt{.dvi} or \texttt{.pdf} file. +% +% Typical applications wouldn't do this unconditionally, but have +% some processing logic that decides to use or not to use the page. +% +% 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! +% +% \fmi{Once we have a new mark mechanism available we can improve +% on that and make sure that the declaration applies to the page +% that contains it.} +% \end{function} +% +% In the \pkg{atbegshi} package there are a number of additional +% commands for use inside the \hook{shipout/before} hook. They +% should normally not be needed any more as one can instead simply +% add code to the hooks \hook{shipout/before}, +% \hook{shipout/background} or +% \hook{shipout/foreground}.\footnote{If that assumption turns out to +% be wrong it would be trivial to change them to public functions +% (right now they are private).} If \pkg{atbegshi} gets loaded then +% those commands become available as public functions with their original +% names as given below. +% +% +% \subsection{Information counters} +% +% +% \begin{variable}{\ReadonlyShipoutCounter,\g_shipout_readonly_int} +% \begin{syntax} +% \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 +% (including the one to be shipped out when inside the output +% 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)! +% +% Just like with the \texttt{page} counter its value is +% only accurate within the output routine. In the body of the +% document it may be off by one as the output routine is called +% 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. +% \end{variable} +% +% \begin{variable}{totalpages,\g_shipout_totalpages_int} +% \begin{syntax} +% \cs{arabic}\texttt{\{totalpages\}} +% \cs{int_use:N} \cs{g_shipout_totalpage_int} \texttt{\% expl3 usage} +% \end{syntax} +% In contrast to \cs{ReadonlyShipoutCounter}, the +% \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). +% +% 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 +% code, for example, to additionally count a number of pages that +% are not build by \LaTeX\ but are added in a later part of the +% process, e.g., cover pages or picture pages made externally. +% +% Important: as this is a page-related counter its value is only +% reliable inside the output routine! +% \end{variable} +% +% \begin{variable}{\PreviousTotalPages} +% \begin{syntax} +% \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 +% preamble it expands to +% \texttt{0}. Note that this is a command to 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} +% +% +% \subsection{Debugging shipout code} +% +% \begin{function}{\DebugShipoutsOn,\DebugShipoutsOff, +% \shipout_debug_on:,\shipout_debug_off:} +% \begin{syntax} +% \cs{DebugShipoutsOn} +% \end{syntax} +% Turn the debugging of shipout code on or off. This displays +% changes made to the shipout data structures. \fmi{This needs +% some rationalizing and may not stay this way.} +% \end{function} +% +% +% +% +% \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}. +% +% +% \subsection{Emulating \pkg{atbegshi}} +% +% +% \begin{function}{\AtBeginShipoutUpperLeft,\AtBeginShipoutUpperLeftForeground} +% \begin{syntax} +% \cs{AddToHook} \texttt{\{shipout/before\} \{...\cs{AtBeginShipoutUpperLeft}}\Arg{code}\texttt{...\}} +% \end{syntax} +% This adds a \texttt{picture} environment into the background of the shipout +% box expecting \meta{code} to contain \texttt{picture} +% commands. The same effect can be obtained by simply using kernel +% features as follows: +% \begin{quote} +% \cs{AddToHook}\texttt{\{shipout/background\}}\Arg{code} +% \end{quote} +% There is one technical difference: if +% \cs{AtBeginShipoutUpperLeft} is used several times each +% invocation is put into its own box inside the shipout box whereas +% all \meta{code} going into \hook{shipout/background} ends up +% all in the same box in the order it is added or sorted based on +% the rules for the hook chunks. +% +% \cs{AtBeginShipoutUpperLeftForeground} is similar with the +% difference that the \texttt{picture} environment is placed in the +% foreground. To model it with the kernel functions use the hook +% \hook{shipout/foreground} instead. +% \end{function} +% +% +% \begin{function}{\AtBeginShipoutAddToBox,\AtBeginShipoutAddToBoxForeground} +% \begin{syntax} +% \cs{AddToHook} \texttt{\{shipout/before\} \{...\cs{AtBeginShipoutAddToBox}}\Arg{code}\texttt{...\}} +% \end{syntax} +% These work like \cs{AtBeginShipoutUpperLeft} and +% \cs{AtBeginShipoutUpperLeftForeground} with the difference that +% \meta{code} is directly placed into an \cs{hbox} inside the +% shipout box and not surrounded by a \texttt{picture} environment. +% +% To emulate them using \hook{shipout/background} or +% \hook{shipout/foreground} you may have to wrap \meta{code} into +% a \cs{put} statement but if the code is not doing any typesetting +% just adding it to the hook should be sufficient. +% \end{function} +% +% +% +% \begin{function}{\AtBeginShipoutBox} +% This is the name of the shipout box as \pkg{atbegshi} knows it. +% \end{function} +% +% \begin{function}{\AtBeginShipoutInit} +% By default \pkg{atbegshi} delayed its action until +% \verb=\begin{document}=. This command was forcing it in an earlier +% place. With the new concept it does nothing. +% \end{function} +% +% \begin{function}{\AtBeginShipout,\AtBeginShipoutNext} +% \begin{syntax} +% \cs{AtBeginShipout}\Arg{code} $\equiv$ \cs{AddToHook}\texttt{\{shipout/before\}}\Arg{code} +% \cs{AtBeginShipoutNext}\Arg{code} $\equiv$ \cs{AddToHookNext}\texttt{\{shipout/before\}}\Arg{code} +% \end{syntax} +% This is equivalent to filling the \hook{shipout/before} hook +% by either using \cs{AddToHook} or \cs{AddToHookNext}, respectively. +% \end{function} +% +% \begin{function}{\AtBeginShipoutFirst,\AtBeginShipoutDiscard} +% The \pkg{atbegshi} names for \cs{AtBeginDvi} and \cs{DiscardShipoutBox}. +% \end{function} +% +% +% +% +% \subsection{Emulating \pkg{everyshi}} +% +% +% \begin{function}{\EveryShipout} +% \begin{syntax} +% \cs{EveryShipout}\Arg{code} $\equiv$ \cs{AddToHook}\texttt{\{shipout/before\}}\Arg{code} +% \end{syntax} +% \end{function} +% +% \begin{function}{\AtNextShipout} +% \begin{syntax} +% \cs{AtNextShipout}\Arg{code} $\equiv$ \cs{AddToHookNext}\texttt{\{shipout/before\}}\Arg{code} +% \end{syntax} +% \end{function} +% +% +% +% \subsection{Emulating \pkg{atenddvi}} +% +% The \pkg{atenddvi} package implemented only a single command: +% \cs{AtEndDvi} and that is now available out of the box. +% +% +% +% \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. +% +% +% +% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } +% +% +% \section{The Implementation} +% \begin{macrocode} +%<@@=shipout> +% \end{macrocode} +% +% 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> {\shipout}{Hook mangement (shipout)}% +% \end{macrocode} +% +% +% \begin{macrocode} +\ExplSyntaxOn +% \end{macrocode} +% +% +% \subsection{Debugging} +% +% \begin{macro}{\g_@@_debug_bool} +% Holds the current debugging state. +% \begin{macrocode} +\bool_new:N \g_@@_debug_bool +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\shipout_debug_on:,\shipout_debug_off:} +% \begin{macro}{\@@_debug:n} +% \begin{macro}{\@@_debug_gset:} +% Turns debugging on and off by redefining \cs{@@_debug:n}. +% \begin{macrocode} +\cs_new_eq:NN \@@_debug:n \use_none:n +\cs_new_protected:Npn \shipout_debug_on: + { + \bool_gset_true:N \g_@@_debug_bool + \@@_debug_gset: + } +\cs_new_protected:Npn \shipout_debug_off: + { + \bool_gset_false:N \g_@@_debug_bool + \@@_debug_gset: + } +\cs_new_protected:Npn \@@_debug_gset: + { + \cs_gset_protected:Npx \@@_debug:n ##1 + { \bool_if:NT \g_@@_debug_bool {##1} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% +% +% \begin{macro}{\ShipoutBox,\l_shipout_box} +% The box filled with the page to be shipped out (both L3 and +% \LaTeXe{} name). +% \begin{macrocode} +\box_new:N \l_shipout_box +% \end{macrocode} +% +% \begin{macrocode} +\cs_set_eq:NN \ShipoutBox \l_shipout_box +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{\@@_execute:} +% This is going to the be the code run by \cs{shipout}. The code +% follows closely the ideas from \pkg{atbegshi}, so not +% documenting that here for now. +% \begin{macrocode} +\cs_set_protected:Npn \@@_execute: { + \tl_set:Nx \l_@@_group_level_tl + { \int_value:w \tex_currentgrouplevel:D } + \tex_afterassignment:D \@@_execute_test_level: + \tex_setbox:D \l_shipout_box +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\shipout} +% Overloading the \cs{shipout} primitive: +% \begin{macrocode} +\cs_gset_eq:NN \shipout \@@_execute: +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\l_@@_group_level_tl} +% Helper token list to record the group level at which +% \cs{@@_execute:} is encountered. \begin{macrocode} +\tl_new:N \l_@@_group_level_tl +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_execute_test_level:} +% If the group level has changed then we are still constructing +% \cs{l_shipout_box} and to continue we need to wait until the +% current group has finished, hence the \cs{tex_aftergroup:D}. +% \begin{macrocode} +\cs_new:Npn \@@_execute_test_level: { + \int_compare:nNnT + \l_@@_group_level_tl < \tex_currentgrouplevel:D + \tex_aftergroup:D + \@@_execute_cont: +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_execute_cont:} +% 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).. +% +% 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 +% processing logic to do.} +% \begin{macrocode} +\cs_new:Npn \@@_execute_cont: { + \box_if_empty:NTF \l_shipout_box + { \PackageWarning{ltshipout}{Ignoring~ void~ shipout~ box} } + { +% \end{macrocode} +% Otherwise we assume that we will ship something and prepare for +% final adjustments (in particular setting the state of +% \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 + \cs_set_eq:NN \@@_saved_protect: \protect + \set@typeset@protect +% \end{macrocode} +% We also store the current shipout box dimension in registers, so that +% they can be used in the hook code.\footnote{This is not really +% 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 +% \end{macrocode} +% Then we execute the \hook{shipout/before} hook. +% \begin{macrocode} + \hook_use:n {shipout/before} +% \end{macrocode} +% In \cs{g_shipout_totalpages_int} we count all shipout attempts so +% we increment that counter already here (the other one is +% incremented later when we know for sure that we do a +% \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 +% hook is executed (in the case that totalpages isn't manually +% altered or through discarding pages that is). +% \begin{macrocode} + \int_gincr:N \g_shipout_totalpages_int +% \end{macrocode} +% The above hook might contain code that requests the page to be discarded so +% we now test for it. +% \begin{macrocode} + \bool_if:NTF \g_@@_discard_bool + { \PackageInfo{ltshipout}{Completed~ page~ discarded} + \bool_gset_false:N \g_@@_discard_bool +% \end{macrocode} +% As we are discarding the page box and not shipping anything out, +% we need to do some house cleaning and reset \TeX's deadcycles so +% that it doesn't complain about too many calls to the OR without +% any shipout. +% \begin{macrocode} + \tex_deadcycles:D \c_zero_int +% \end{macrocode} +% \fmi{In \pkg{atbegshi} the box was dropped but is that actually +% 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 +% \group_end: +% \cs_set_eq:NN \protect \exp_not:N + } +% \end{macrocode} +% Even if there was no explicit request to discard the box it is +% possible that the code for the hook \hook{shipout/before} has +% voided the box (by mistake or deliberately). We therefore test +% 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}{ + Shipout~ box~ was~ voided~ by~ hook,\MessageBreak + ignoring~ shipout~ box } + } +% \end{macrocode} +% Finally, if the box is still non-empty we are nearly ready to +% ship it out. +% First we increment the total page counter so that we can later +% test if we have reached the final page according to our available +% information.\footnote{Doing that earlier would be wrong because we +% might end up with the last page counted but discard and then we +% have no place to add the final objects into the output file.} +% \begin{macrocode} + { + \int_gincr:N \g_shipout_readonly_int + \@@_debug:n { + \typeout{Absolute~ page~ =~ \int_use:N \g_shipout_readonly_int + \space (target:~ \@abspage@last)} + } +% \end{macrocode} +% Then we store the box sizes again (as they may have +% 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 +% 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} } } +% \end{macrocode} +% We then run \cs{@@_execute_firstpage_hook:} 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: +% \end{macrocode} +% The we check if we have to add the \hook{shipout/lastpage} hook +% because we have reached the last page. This test will be false for +% all but one (and hopefully the correct) page. +% \begin{macrocode} + \int_compare:nNnT \@abspage@last = \g_shipout_readonly_int + { \hook_if_empty:nF {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 } + } + \bool_gset_true:N \g_@@_lastpage_handled_bool + } +% \end{macrocode} +% Finally we run the actual \TeX{} primitive for shipout. As that will +% expand delayed \cs{write} statements inside the page in which +% protected commands should not expand we first change \cs{protect} +% to the appropriate definition for that case. +% \begin{macrocode} + \cs_set_eq:NN \protect \exp_not:N + \tex_shipout:D \box_use:N \l_shipout_box + } + } +% \end{macrocode} +% Restore the value of \cs{protect} in case \cs{shipout} is called +% outside of the output routine (where it is automatically restored +% because of the implicit group). +% \begin{macrocode} + \cs_set_eq:NN \protect \@@_saved_protect: + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_saved_protect:} +% Remeber the current \cs{protect} state. +% \begin{macrocode} +\cs_new_eq:NN \@@_saved_protect: \protect +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{shipout/before, +% 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/foreground} +\hook_new:n{shipout/background} +\hook_new:n{shipout/firstpage} +\hook_new:n{shipout/lastpage} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@kernel@after@shipout@lastpage, +% \@kernel@before@shipout@background} +% And here are the internal kernel hooks going before or after the +% public ones where needed. +% \begin{macrocode} +\let\@kernel@after@shipout@lastpage\@empty +\let\@kernel@before@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{macrocode} +\cs_new:Npn \@@_execute_firstpage_hook: { +% \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. +% \begin{macrocode} + \hook_if_empty:nF {shipout/firstpage} + { \@@_add_background_box:n { \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 +% is never used again. +% \begin{macrocode} + \cs_gset_eq:NN \@@_execute_firstpage_hook: \prg_do_nothing: + \cs_gset:Npn \@@_add_firstpage_material:Nn ##1 ##2 { + \@latex@warning{ + First~ page~ is~ already~ shipped~ out,~ ignoring\MessageBreak + \string##1 } + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\g_@@_lastpage_handled_bool} +% A boolean to signal if we have already handled the +% \hook{shipout/lastpage} hook. +% \begin{macrocode} +\bool_new:N \g_@@_lastpage_handled_bool +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_add_firstpage_material:Nn} +% This command adds material to the +% \hook{shipout/firstpage} hook. It is used in +% \cs{AtBeginDvi}, etc. The first argument is the +% command through which is it called. Initially this is ignored but +% once we are passed the first page it can be used to generate a +% warning message mentioning the right user command. +% \begin{macrocode} +\cs_new:Npn \@@_add_firstpage_material:Nn #1#2 { + \AddToHook{shipout/firstpage}{#2} +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% +% \begin{macro}{\@@_get_box_size:N} +% Store the box dimensions in dimen registers. +% \fmi{This could/should perhaps be generalized to set height depth and +% width given an arbitrary box.} +% \begin{macrocode} +\cs_new:Npn \@@_get_box_size:N #1 { + \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 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_shipout_box_ht_dim, +% \l_shipout_box_dp_dim,\l_shipout_box_wd_dim, +% \l_shipout_box_ht_plus_dp_dim} +% And here are the variables set by \cs{@@_get_box_size:N}. +% \begin{macrocode} +\dim_new:N \l_shipout_box_ht_dim +\dim_new:N \l_shipout_box_dp_dim +\dim_new:N \l_shipout_box_wd_dim +\dim_new:N \l_shipout_box_ht_plus_dp_dim +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% \begin{macro}{\g_@@_discard_bool} +% Indicate whether or not the current page box should be discarded +% \begin{macrocode} +\bool_new:N \g_@@_discard_bool +% \end{macrocode} +% \end{macro} +% +% +% +% \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. +% \begin{macrocode} +\box_new:N \l_@@_tmp_box +\tl_new:N \l_@@_saved_badness_tl +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_add_background_box:n} +% In standard \LaTeX{} the shipout box is always a \cs{vbox} but +% here we are allow for other usage as well, in case some package +% has its own output routine. +% \begin{macrocode} +\cs_new:Npn \@@_add_background_box:n #1 +{ \@@_get_box_size:N \l_shipout_box +% \end{macrocode} +% But we start testing for a vertical box as that should be the +% normal case. +% \begin{macrocode} + \box_if_vertical:NTF \l_shipout_box + { +% \end{macrocode} +% Save current values of \cs{vfuzz} and \cs{vbadness} then change +% them to allow box manipulations without warnings. +% \begin{macrocode} + \tl_set:Nx \l_@@_saved_badness_tl + { \vfuzz=\the\vfuzz\relax + \vbadness=\the\vbadness\relax } + \vfuzz=\c_max_dim + \vbadness=\c_max_int +% \end{macrocode} +% Then we reconstruct \cs{l_shipout_box} \ldots +% \begin{macrocode} + \vbox_set_to_ht:Nnn \l_shipout_box \l_shipout_box_ht_plus_dp_dim + { +% \end{macrocode} +% \ldots{} the material in \verb=#1= is placed into a horizontal +% box with zero dimensions. +% \begin{macrocode} + \hbox_set:Nn \l_@@_tmp_box + { \l_@@_saved_badness_tl #1 } + \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim + \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim + \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim +% \end{macrocode} +% The we typeset that box followed by whatever was in +% \cs{l_shipout_box} before (unpacked). +% \begin{macrocode} + \skip_zero:N \baselineskip + \skip_zero:N \lineskip + \skip_zero:N \lineskiplimit + \box_use:N \l_@@_tmp_box + \vbox_unpack:N \l_shipout_box +% \end{macrocode} +% The \cs{kern} ensures that the box has no depth which is +% afterwards explicitly corrected. +% \begin{macrocode} + \kern \c_zero_dim + } + \box_set_ht:Nn \l_shipout_box \l_shipout_box_ht_dim + \box_set_dp:Nn \l_shipout_box \l_shipout_box_dp_dim +% \end{macrocode} +% \fmi{The whole boxing maneuver looks a bit like overkill to me, but for +% the moment I leave.} +% \begin{macrocode} + \l_@@_saved_badness_tl + } + { +% \end{macrocode} +% A horizontal box is handled in a similar way. The last case would +% be a void box in which case we do nothing hence the missing +% \texttt{F} branch. +% \begin{macrocode} + \box_if_horizontal:NT \l_shipout_box + { + \tl_set:Nx \l_@@_saved_badness_tl + { \hfuzz=\the\hfuzz\relax + \hbadness=\the\hbadness\relax } + \hfuzz=\c_max_dim + \hbadness=\c_max_int + \hbox_set_to_wd:Nnn \l_shipout_box \l_shipout_box_wd_dim + { + \hbox_set:Nn \l_@@_tmp_box + { \l_@@_saved_badness_tl #1 } + \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim + \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim + \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim + \box_move_up:nn + \l_shipout_box_ht_dim + { \box_use:N \l_@@_tmp_box } + \hbox_unpack:N \l_shipout_box + } + \l_@@_saved_badness_tl + } + } +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{\@@_add_foreground_box:n} +% Foreground boxes are done in the same way, only the order and +% placement of boxes has to be done differently. +% \begin{macrocode} +\cs_new:Npn \@@_add_foreground_box:n #1 +{ + \box_if_vertical:NTF \l_shipout_box + { + \tl_set:Nx \l_@@_saved_badness_tl + { \vfuzz=\the\vfuzz\relax + \vbadness=\the\vbadness\relax } + \vfuzz=\c_max_dim + \vbadness=\c_max_int + \vbox_set_to_ht:Nnn \l_shipout_box \l_shipout_box_ht_plus_dp_dim + { + \hbox_set:Nn \l_@@_tmp_box + { \l_@@_saved_badness_tl #1 } + \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim + \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim + \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim + \skip_zero:N \baselineskip + \skip_zero:N \lineskip + \skip_zero:N \lineskiplimit + \vbox_unpack:N \l_shipout_box + \kern -\l_shipout_box_ht_plus_dp_dim + \box_use:N \l_@@_tmp_box + \kern \l_shipout_box_ht_plus_dp_dim + } + \l_@@_saved_badness_tl + \box_set_ht:Nn \l_shipout_box \l_shipout_box_ht_dim + \box_set_dp:Nn \l_shipout_box \l_shipout_box_dp_dim + } + { + \box_if_horizontal:NT \l_shipout_box + { + \tl_set:Nx \l_@@_saved_badness_tl + { \hfuzz=\the\hfuzz\relax + \hbadness=\the\hbadness\relax } + \hfuzz=\c_max_dim + \hbadness=\c_max_int + \hbox_set_to_wd:Nnn \l_shipout_box \l_shipout_box_wd_dim + { + \hbox_unpack:N \l_shipout_box + \kern -\box_wd:N \l_shipout_box + \hbox_set:Nn \l_@@_tmp_box + { \l_@@_saved_badness_tl #1 } + \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim + \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim + \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim + \box_move_up:nn { \box_ht:N \l_shipout_box } + { \box_use:N \l_@@_tmp_box } + \kern \box_wd:N \l_shipout_box + }% + \l_@@_saved_badness_tl + } + } +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{\@@_init_page_origins:,\c_@@_horigin_tl,\c_@@_vorigin_tl} +% Two constants holding the offset of the top-left with respect to +% the media box. +% +% Setting the constants this way is courtesy of Bruno. +% +% We delay setting the constants to the last possible place as +% there might be updates in the preamble or even in the +% \hook{begindocument} hook that affects their setup. +% \begin{macrocode} +\cs_new:Npn \@@_init_page_origins: { + \tl_const:Nx \c_@@_horigin_tl + { + \cs_if_exist_use:NTF \pdfvariable { horigin } + { \cs_if_exist_use:NF \pdfhorigin { 1in } } + } + \tl_const:Nx \c_@@_vorigin_tl + { + \cs_if_exist_use:NTF \pdfvariable { vorigin } + { \cs_if_exist_use:NF \pdfvorigin { 1in } } + } +% \end{macrocode} +% After the constants have been set there is no need to execute +% this command again, in fact it would raise an error, so we +% redefine it to do nothing. +% \begin{macrocode} + \cs_gset_eq:NN \@@_init_page_origins: \prg_do_nothing: +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_picture_overlay:n} +% Put the argument into a \texttt{picture} environment that doesn't take up +% any size and uses \texttt{1pt} for \cs{unitlength}. +% \fmi{Could perhaps be generalized as it might be useful elsewhere. For +% now it is not.} +% \begin{macrocode} +\cs_new:Npn \@@_picture_overlay:n #1 { +% \end{macrocode} +% The very first time this is executed we have to initializes (and +% freeze) the origins. +% \begin{macrocode} + \@@_init_page_origins: +% \end{macrocode} +% +% \begin{macrocode} + \kern -\c_@@_horigin_tl \scan_stop: + \vbox_to_zero:n { + \kern -\c_@@_vorigin_tl \scan_stop: + \unitlength 1pt \scan_stop: +% \end{macrocode} +% This mimics a simple zero-sized picture environment. The \cs{hss} +% is need in case there is horizontal material (without using +% \cs{put} with a positive width. +% \changes{v1.0b}{2020/09/09} +% {Prevent overfull box warnings (gh/387)} +% \begin{macrocode} + \hbox_set_to_wd:Nnn \l_@@_tmp_box \c_zero_dim + { \ignorespaces #1 \hss } + \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim + \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim + \box_use:N \l_@@_tmp_box + \tex_vss:D + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_add_background_picture:n} +% Put a \texttt{picture} env in the background of the shipout box +% with its reference point in the top-left corner. +% +% \begin{macrocode} +\cs_new:Npn \@@_add_background_picture:n #1 { + \@@_add_background_box:n { \@@_picture_overlay:n {#1} } +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_add_foreground_picture:n} +% +% Put a \texttt{picture} env in the foreground of the shipout box +% with its reference point in the top-left corner. +% \begin{macrocode} +\cs_new:Npn \@@_add_foreground_picture:n #1 { + \@@_add_foreground_box:n { \@@_picture_overlay:n {#1} } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\shipout_discard:} +% Request that the next shipout box should be discarded. At the +% moment this is just setting a boolean, but we may want to augment +% this behavior that the position of the call is taken into account +% (in case \LaTeX{} looks ahead and is not using the position for +% on the next page). +% \begin{macrocode} +\cs_new_protected:Npn \shipout_discard: { + \bool_gset_true:N \g_@@_discard_bool +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsection{Handling the end of job hook} +% +% At the moment this is partly solved by using the existing hooks. +% But rather than putting the code into these hooks it should be +% moved to the right place directly as we shouldn't prefill hooks +% with material unless it needs to interact with other code. +% +% +% +% \begin{macro}{\g_shipout_readonly_int,\ReadonlyShipoutCounter} +% We count every shipout activity that makes a page (but not those +% that are discarded) in order to know how many pages got produced. +% \begin{macrocode} +\int_new:N \g_shipout_readonly_int +% \end{macrocode} +% For \LaTeXe{} it is available as a command (i.e., a \TeX{} +% counter only. +% \begin{macrocode} +\cs_new_eq:NN \ReadonlyShipoutCounter \g_shipout_readonly_int +% \end{macrocode} +% \end{macro} +% +% \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 +% code. +% \begin{macrocode} +\int_new:N \g_shipout_totalpages_int +% \end{macrocode} +% For \LaTeXe{} this is offered as a \LaTeX{} counter so can be +% easily typeset inside the output routine to display things like +% \enquote{\cs{thepage}\texttt{/}\cs{thetotalpages}}, etc. +% \begin{macrocode} +\cs_new_eq:NN \c@totalpages \g_shipout_totalpages_int +\cs_new:Npn \thetotalpages { \arabic{totalpages} } +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{\@abspage@last} +% In \cs{@abspage@last} record the number of pages from the last +% run. This is written to the \texttt{.aux} and this way made +% available to the next run. In case there is no \texttt{.aux} file +% 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 +% multipage document. +% \begin{macrocode} +\xdef\@abspage@last{\number\maxdimen} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\enddocument} +% +% 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 +% 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 +% 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 +% shipout will run the \hook{shipout/lastpage} code. Of course, +% if there are floats that still need a placement this guess will +% be wrong but then rerunning the document will give us the correct +% value next time around. +% +% \begin{macro}{\@kernel@after@enddocument} +% \begin{macrocode} +\g@addto@macro \@kernel@after@enddocument { + \int_compare:nNnT \@abspage@last = \maxdimen + { +% \end{macrocode} +% We use \LaTeXe{} coding as \cs{@abspage@last} is not an L3 name. +% \begin{macrocode} + \xdef\@abspage@last{ \int_eval:n {\g_shipout_readonly_int + 1} } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@kernel@after@enddocument@afterlastpage} +% Once the \cs{clearpage} has done its work inside \cs{enddocument} +% we know for sure how many pages this document has, so we record +% that in the \texttt{.aux} file for the next run. +% +% \begin{macrocode} +\g@addto@macro \@kernel@after@enddocument@afterlastpage { +% \end{macrocode} +% There is one special case: If no output is produced then there is +% no point in a) recording the number as 0 will never match the +% page number of a real page and b) adding an extra page to ran the +% \hook{shipout/lastpage} is pointless as well (as it would +% remain forever). So we test for this and run the code only if +% there have been pages. +% \begin{macrocode} + \int_compare:nNnF \g_shipout_readonly_int = 0 + { +% \end{macrocode} +% This ends up in the \texttt{.aux} so we use \LaTeXe{} names here. +% \fmi{This needs an interface for \cs{nofiles} in expl3, doesn't at the moment!} +% \begin{macrocode} + \if@filesw + \iow_now:Nx \@auxout { + \gdef\string\@abspage@last {\int_use:N \g_shipout_readonly_int}} + \fi +% \end{macrocode} +% But we may have guessed wrongly earlier and we still have to run the +% \hook{shipout/lastpage} even though there is no page to place +% it into. If that is the case we make a trivial extra page and put +% it there. This temporary page will then vanish again on the next +% run but helps to keep pdf viewers happy. +% \begin{macrocode} + \bool_if:NF \g_@@_lastpage_handled_bool + { +% \end{macrocode} +% However, making this extra page in case the hook is actually +% empty would be forcing a rerun without any reason, so we check +% that condition and also check if +% \cs{@kernel@after@shipout@lastpage} contains any code. If both +% are empty we omit the page generation. +% \begin{macrocode} + \bool_lazy_and:nnF + { \hook_if_empty_p:n {shipout/lastpage} } + { \tl_if_empty_p:N \@kernel@after@shipout@lastpage } + { + \tex_shipout:D\vbox to\textheight + { + \hbox:n { \UseHook{shipout/lastpage} + \@kernel@after@shipout@lastpage } +% \end{macrocode} +% This extra page could be totally empty except for the hook +% content, but to help the user understanding why it is there we +% put some text into it. +% \begin{macrocode} + \@@_excuse_extra_page: + \null + } +% \end{macrocode} +% 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}. +% \begin{macrocode} + \cs_gset_eq:NN \@extra@page@added \relax + } + } + } +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% \begin{macro}{\@@_excuse_extra_page:} +% Say mea culpa \ldots +% \begin{macrocode} +\cs_new:Npn \@@_excuse_extra_page: { + \vfil + \begin{center} + \bfseries Temporary~ page! + \end{center} + \LaTeX{}~ was~ unable~ to~ guess~ the~ total~ number~ of~ pages~ + correctly.~ ~ As~ there~ was~ some~ unprocessed~ data~ that~ + should~ have~ been~ added~ to~ the~ final~ page~ this~ extra~ + page~ has~ been~ added~ to~ receive~ it. + \par + If~ you~ rerun~ the~ document~ (without~ altering~ it)~ this~ + surplus~ page~ will~ go~ away,~ because~ \LaTeX{}~ now~ knows~ + how~ many~ pages~ to~ expect~ for~ this~ document. + \vfil +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\PreviousTotalPages,\@kernel@before@begindocument} +% In the preamble before the \texttt{aux} file was read +% \cs{PreviousTotalPages} is always zero. +% \begin{macrocode} +\def\PreviousTotalPages{0} +% \end{macrocode} +% In the \texttt{aux} file there should be an update for +% \cs{@abspage@last} recording the number of pages from the +% previous run. If not that macro holds the value of +% \cs{maxdimen}. So we test for it and update +% \cs{PreviousTotalPages} if there was a real value. This should +% happen just before the \hook{begindocument} hook is executed so +% that the value can be used inside that hook. +% \begin{macrocode} +\g@addto@macro\@kernel@before@begindocument + {\ifnum\@abspage@last<\maxdimen + \xdef\PreviousTotalPages{\@abspage@last}\fi} +% \end{macrocode} +% \end{macro} +% +% +% \section{Legacy \LaTeXe{} interfaces} +% +% +% +% \begin{macro}{\DiscardShipoutBox} +% Request that the next shipout box is to be discarded. +% \begin{macrocode} +\cs_new_eq:NN \DiscardShipoutBox \shipout_discard: +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\AtBeginDvi} +% +% \begin{macrocode} +\cs_new_protected:Npn \AtBeginDvi {\@@_add_firstpage_material:Nn \AtBeginDvi} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\DebugShipoutsOn,\DebugShipoutsOff} +% +% \begin{macrocode} +\cs_new_eq:NN \DebugShipoutsOn \shipout_debug_on: +\cs_new_eq:NN \DebugShipoutsOff \shipout_debug_off: +% \end{macrocode} +% \end{macro} +% +% +% \section{Internal commands needed elsewhere} +% +% These internal commands use double and triple \texttt{@} signs so +% we need to stop getting them translated to the module name. +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% \begin{macro}{\@expl@@@shipout@add@firstpage@material@@Nn, +% \@expl@@@shipout@add@background@box@@n, +% \@expl@@@shipout@add@foreground@box@@n, +% \@expl@@@shipout@add@background@picture@@n, +% \@expl@@@shipout@add@foreground@picture@@n} +% Some internals needed elsewhere. +% +% \begin{macrocode} +\cs_set_eq:NN \@expl@@@shipout@add@firstpage@material@@Nn + \__shipout_add_firstpage_material:Nn +% \end{macrocode} +% +% \begin{macrocode} +\cs_set_eq:NN \@expl@@@shipout@add@background@box@@n + \__shipout_add_background_box:n +% \end{macrocode} +% +% \begin{macrocode} +\cs_set_eq:NN \@expl@@@shipout@add@foreground@box@@n + \__shipout_add_foreground_box:n +% \end{macrocode} +% +% \begin{macrocode} +\cs_set_eq:NN \@expl@@@shipout@add@background@picture@@n + \__shipout_add_background_picture:n +% \end{macrocode} +% +% \begin{macrocode} +\cs_set_eq:NN \@expl@@@shipout@add@foreground@picture@@n + \__shipout_add_foreground_picture:n +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\ExplSyntaxOff +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \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. +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\shipout}{The hook management (shipout)}% +%<latexrelease>\expandafter\let\expandafter\shipout\csname tex_shipout:D\endcsname +%<latexrelease> +%<latexrelease>\let \ShipoutBox\@undefined +%<latexrelease>\let \ReadonlyShipoutCounter \@undefined +%<latexrelease>\let \c@totalpages \@undefined +%<latexrelease>\let \thetotalpages \@undefined +%<latexrelease> +%<latexrelease>\let \DiscardShipoutBox \@undefined +%<latexrelease>\let \DebugShipoutsOn \@undefined +%<latexrelease>\let \DebugShipoutsOff \@undefined +%<latexrelease> +%<latexrelease>\DeclareRobustCommand \AtBeginDvi [1]{% +%<latexrelease> \global \setbox \@begindvibox +%<latexrelease> \vbox{\unvbox \@begindvibox #1}% +%<latexrelease>} +%<latexrelease> +%<latexrelease>\let \AtBeginShipout \@undefined +%<latexrelease>\let \AtBeginShipoutNext \@undefined +%<latexrelease> +%<latexrelease>\let \AtBeginShipoutFirst \@undefined +%<latexrelease> +%<latexrelease>\let \ShipoutBoxHeight \@undefined +%<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 +% commands) and properly removing it would mean we need to make the +% \cs{unclare@...} 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> +%<latexrelease>\let \AtEndDvi \@undefined +% \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 +% 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). +% \begin{macrocode} +%\reenable@package@load{atenddvi} +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease> +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% +% +% +% \section{Package emulation for compatibility} +% +% +% \subsection{Package \pkg{atenddvi} emulation} +% +% +% \begin{macro}{\AtEndDvi} +% This package has only one public command to simulating it is easy +% and actually sensible to provide as part of the kernel. +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\AtEndDvi}{atenddvi emulation}% +\ExplSyntaxOn +\cs_new_protected:Npn \AtEndDvi {\AddToHook{shipout/lastpage}} +\ExplSyntaxOff +% \end{macrocode} +% As the package is integrate we prevent loading (no need to roll that back): +% \begin{macrocode} +\disable@package@load{atenddvi} + {\PackageWarning{atenddvi} + {Functionality of this package is already\MessageBreak + provided by LaTeX.\MessageBreak\MessageBreak + It is there no longer necessary to load it\MessageBreak + and you can safely remove it.\MessageBreak + Found on}} +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\AtEndDvi}{atenddvi emulation}% +%<latexrelease>\let \AtEndDvi \@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macrocode} +%</2ekernel> +% \end{macrocode} +% +% +% \subsection{Package \pkg{atbegshi} emulation} +% +% +% +% +% +% \begin{macrocode} +%<*atbegshi-ltx> +\ProvidesPackage{atbegshi-ltx} + [2020/08/17 v1.0a + Emulation of the original atbegshi package^^Jwith kernel methods] +% \end{macrocode} +% +% +% \begin{macro}{\AtBeginShipoutBox} +% \begin{macrocode} +\let \AtBeginShipoutBox \ShipoutBox +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\AtBeginShipoutInit} +% Compatibility only, we aren't delaying \ldots +% \begin{macrocode} +\let \AtBeginShipoutInit \@empty +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\AtBeginShipout,\AtBeginShipoutNext} +% Filling hooks +% \begin{macrocode} +\protected \def \AtBeginShipout {\AddToHook{shipout/before}} +\protected \def \AtBeginShipoutNext {\AddToHookNext{shipout/before}} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\AtBeginShipoutFirst} +% Slightly more complex as we need to know the name of the command under which the +% \hook{shipout/firstpage} hook is filled. +% \begin{macrocode} +\protected \def \AtBeginShipoutFirst + {\@expl@@@shipout@add@firstpage@material@@Nn \AtBeginShipoutFirst} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\AtBeginShipoutDiscard} +% Just a different name. +% \begin{macrocode} +\let \AtBeginShipoutDiscard \DiscardShipoutBox +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\AtBeginShipoutAddToBox,\AtBeginShipoutAddToBoxForeground, +% \AtBeginShipoutUpperLeft,\AtBeginShipoutUpperLeftForeground} +% We don't expose them. +% \begin{macrocode} +\let \AtBeginShipoutAddToBox + \@expl@@@shipout@add@background@box@@n +\let \AtBeginShipoutAddToBoxForeground + \@expl@@@shipout@add@foreground@box@@n +% \end{macrocode} +% +% \begin{macrocode} +\let \AtBeginShipoutUpperLeft + \@expl@@@shipout@add@background@picture@@n +\let \AtBeginShipoutUpperLeftForeground + \@expl@@@shipout@add@foreground@picture@@n +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\ShipoutBoxHeight,\ShipoutBoxWidth,\ShipoutoBoxDepth} +% 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 } +\ExplSyntaxOff +% \end{macrocode} +% \end{macro} +% +% +% \begin{macrocode} +%</atbegshi-ltx> +% \end{macrocode} +% +% If the package is requested we substitute the one above: +% \begin{macrocode} +%<*2ekernel> +\declare@file@substitution{atbegshi.sty}{atbegshi-ltx.sty} +%</2ekernel> +% \end{macrocode} +% +% +% +% +% +% +% \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} +% +% +% Rather important :-) +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% \Finale +% +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\endinput +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/Master/texmf-dist/source/latex/base/ltspace.dtx b/Master/texmf-dist/source/latex/base/ltspace.dtx index 16d7dcb43aa..1a672c6455d 100644 --- a/Master/texmf-dist/source/latex/base/ltspace.dtx +++ b/Master/texmf-dist/source/latex/base/ltspace.dtx @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltspace.dtx} - [2019/11/02 v1.3k LaTeX Kernel (spacing)] + [2020/05/06 v1.3n LaTeX Kernel (spacing)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltspace.dtx} @@ -63,6 +63,8 @@ % \changes{v1.2r}{1996/07/27}{Correct documentation of problems} % \changes{v1.2w}{1998/08/17}{Documentation fixes.} % \changes{v1.3j}{2019/08/27}{Make various commands robust} +% \changes{v1.3l}{2020/03/07}{Moved \cs{thinspace}, \cs{negthinspace} +% and \cs{,} to ltmath.dtx (gh/303)} % % % \section{Spacing} @@ -428,6 +430,37 @@ % \end{macrocode} % \end{macro} % \end{macro} +% +% +% +% \begin{macro}{\@vspace@calcify} +% Helper command to produce a \cs{vskip} that is first run through +% \cs{setlength}. This way the \texttt{calc} package can operate on +% the argument value. +% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)} +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@vspace@calcify}{Add calc support}% +\def\@vspace@calcify#1{\begingroup\setlength\skip@{#1}\vskip\skip@\endgroup} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@vspace@calcify}{Add calc support}% +%<latexrelease> +%<latexrelease>\let\@vspace@calcify\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% + + % \begin{macro}{\newline} % A simple form of the `normal' definition of |\\|. % \changes{v1.2v}{1997/05/07}{Made completely robust.} @@ -445,12 +478,31 @@ % \end{macro} % % \begin{macro}{\@newline} +% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@newline}{\newline calc support}% \def\@newline[#1]{\let \reserved@e \vadjust - \@gnewline {\vskip #1}} + \@gnewline {\@vspace@calcify{#1}}} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@newline}{\newline calc support}% +%<latexrelease> +%<latexrelease>\def\@newline[#1]{\let \reserved@e \vadjust +%<latexrelease> \@gnewline {\vskip #1}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % +% +% % \begin{macro}{\@gnewline} % \changes{v1.2u}{1996/10/29}{Added macro} % The |\nobreak| added to prevent null lines when |\\| @@ -518,7 +570,7 @@ % |\begin{@float}| \ldots |\end{@float}| % that want to be invisible --- i.e., % not leave any extra space when used in the middle of text. Such -% a macro should begin with |\@bsphack| and end with |\@esphack| +% a macro should begin with |\@bsphack| and end with |\@esphack|. % The macro in question should not create any text, nor change the % mode. % @@ -823,20 +875,48 @@ % \changes{v1.2c}{1994/11/13}{Recorrected error message} % Add vertical space taking into account space already added, as % described above. +% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)} % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\addvspace}{\addvspace calc support}% \def\addvspace#1{% \ifvmode \if@minipage\else \ifdim \lastskip =\z@ - \vskip #1\relax + \@vspace@calcify{#1}% \else - \@tempskipb#1\relax + \setlength\@tempskipb{#1}% \@xaddvskip \fi \fi \else \@noitemerr \fi} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\addvspace}{\addvspace calc support}% +%<latexrelease> +%<latexrelease>\def\addvspace#1{% +%<latexrelease> \ifvmode +%<latexrelease> \if@minipage\else +%<latexrelease> \ifdim \lastskip =\z@ +%<latexrelease> \vskip #1\relax +%<latexrelease> \else +%<latexrelease> \@tempskipb#1\relax +%<latexrelease> \@xaddvskip +%<latexrelease> \fi +%<latexrelease> \fi +%<latexrelease> \else +%<latexrelease> \@noitemerr +%<latexrelease> \fi} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % @@ -938,6 +1018,8 @@ % \end{macrocode} % \end{macro} % +% +% % \begin{macro}{\vspace} % \changes{v1.2m}{1996/01/20}{Made robust} % \begin{macro}{\@vspace} @@ -957,14 +1039,25 @@ % \end{itemize} % \begin{macrocode} \DeclareRobustCommand\vspace{\@ifstar\@vspacer\@vspace} +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@vspace}{Support calc in \vspace}% +% \end{macrocode} +% We support calc syntax in the argument and therefore use \cs{setlength}. +% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)} +% \begin{macrocode} \def\@vspace #1{% \ifvmode - \vskip #1 + \@vspace@calcify{#1}% \vskip\z@skip \else \@bsphack \vadjust{\@restorepar - \vskip #1 + \@vspace@calcify{#1}% \vskip\z@skip }% \@esphack @@ -977,7 +1070,7 @@ \dimen@\prevdepth \hrule \@height\z@ \nobreak - \vskip #1 + \@vspace@calcify{#1}% \vskip\z@skip \prevdepth\dimen@ \else @@ -985,10 +1078,46 @@ \vadjust{\@restorepar \hrule \@height\z@ \nobreak - \vskip #1 + \@vspace@calcify{#1}% \vskip\z@skip}% \@esphack \fi} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@vspace}{Support calc in \vspace}% +%<latexrelease> +%<latexrelease>\def\@vspace #1{% +%<latexrelease> \ifvmode +%<latexrelease> \vskip #1 +%<latexrelease> \vskip\z@skip +%<latexrelease> \else +%<latexrelease> \@bsphack +%<latexrelease> \vadjust{\@restorepar +%<latexrelease> \vskip #1 +%<latexrelease> \vskip\z@skip +%<latexrelease> }% +%<latexrelease> \@esphack +%<latexrelease> \fi} +%<latexrelease>\def\@vspacer#1{% +%<latexrelease> \ifvmode +%<latexrelease> \dimen@\prevdepth +%<latexrelease> \hrule \@height\z@ +%<latexrelease> \nobreak +%<latexrelease> \vskip #1 +%<latexrelease> \vskip\z@skip +%<latexrelease> \prevdepth\dimen@ +%<latexrelease> \else +%<latexrelease> \@bsphack +%<latexrelease> \vadjust{\@restorepar +%<latexrelease> \hrule \@height\z@ +%<latexrelease> \nobreak +%<latexrelease> \vskip #1 +%<latexrelease> \vskip\z@skip}% +%<latexrelease> \@esphack +%<latexrelease> \fi} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % \end{macro} @@ -1094,17 +1223,6 @@ % \end{macrocode} % % -% \begin{macro}{\,} -% Used in paragraph mode produces a |\thinspace|. It has the -% ordinary definition in math mode. Useful for quotes inside quotes, -% as in |``\,`Foo', he said.''| -% \changes{v1.0o}{1994/05/11}{Use \cs{DeclareRobustCommand}. ASAJ.} -% \begin{macrocode} -\DeclareRobustCommand{\,}{% - \relax\ifmmode\mskip\thinmuskip\else\thinspace\fi -} -% \end{macrocode} -% \end{macro} % % \begin{macro}{\@} % Placed before a '.', makes it a sentence-ending period. Does the @@ -1142,20 +1260,37 @@ % \changes{LaTeX2e}{1993/08/05} % {(RmS) Removed superfluous \cs{leavevmode} in \cs{@hspace} and % \cs{@hspacer}, as suggested by CAR.} +% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)} +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@hspace}{Support calc with \hspace}% +\def\@hspace#1{\begingroup\setlength\skip@{#1}\hskip\skip@\endgroup} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% % \begin{macrocode} -\def\@hspace#1{\hskip #1\relax} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@hspace}{Support calc with \hspace}% + +%<latexrelease> +%<latexrelease>\def\@hspace#1{\hskip #1\relax} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % % % \begin{macro}{\@hspacer} -% extra |\hskip 0pt| added 1985/17/12 to guard +% Extra |\hskip 0pt| added 1985/17/12 to guard % against a following |\unskip| % |\relax| added 13 Oct 88 for usual \TeX\ lossage % replaced both changes by |\hskip\z@skip| 27 Nov 91 % \begin{macrocode} \def\@hspacer#1{\vrule \@width\z@\nobreak - \hskip #1\hskip \z@skip} + \@hspace{#1}\hskip \z@skip} % \end{macrocode} % \end{macro} % @@ -1184,19 +1319,12 @@ %<latexrelease> {\thinspace}{Start LR-mode}% % \end{macrocode} % -% -% \begin{macro}{\thinspace} -% \begin{macro}{\negthinspace} % \begin{macro}{\enspace} % \changes{v1.3h}{2018/09/24}{Start LR-mode if necessary (git/49)} % \begin{macrocode} -\DeclareRobustCommand\thinspace{\leavevmode@ifvmode\kern .16667em } -\DeclareRobustCommand\negthinspace{\leavevmode@ifvmode\kern-.16667em } \DeclareRobustCommand\enspace{\leavevmode@ifvmode\kern.5em } % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} % % \begin{macro}{\leavevmode@ifvmode} % Leave vmode but only if we are really in vmode, otherwise the @@ -1234,6 +1362,18 @@ % \end{macro} % \end{macro} % +% \changes{v1.3n}{2020/05/06}{Made softhyphen active in TU engines} +% +% For Unicode engines, make the Unicode soft hyphen an active +% character defined as \cs{-}. +% +% \begin{macrocode} +\ifx\Umathcode\@undefined\else + \catcode "AD=13 + \def^^ad{\-} +\fi +% \end{macrocode} +% % \begin{macro}{\obeycr} % \begin{macro}{\restorecr} % The following definitions will probably get deleted or moved to diff --git a/Master/texmf-dist/source/latex/base/lttab.dtx b/Master/texmf-dist/source/latex/base/lttab.dtx index 47cf4a66184..dedd9e5d375 100644 --- a/Master/texmf-dist/source/latex/base/lttab.dtx +++ b/Master/texmf-dist/source/latex/base/lttab.dtx @@ -31,7 +31,7 @@ %%% From File: lttab.dtx %<*driver> % \fi -\ProvidesFile{lttab.dtx}[2019/10/07 v1.1q LaTeX Kernel (Columns)] +\ProvidesFile{lttab.dtx}[2020/04/24 v1.1r LaTeX Kernel (Columns)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{lttab.dtx} @@ -475,11 +475,28 @@ % \end{macro} % % \begin{macro}{\@itabcr} +% \changes{v1.1r}{2020/04/21}{Support calc syntax (gh/152)} % \begin{macrocode} -\def\@itabcr[#1]{\vskip #1\@startline\ignorespaces} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@itabcr}{Tabbing calc syntax}% +\def\@itabcr[#1]{\@vspace@calcify{#1}\@startline\ignorespaces} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@itabcr}{Tabbing calc syntax}% +%<latexrelease> +%<latexrelease>\def\@itabcr[#1]{\vskip #1\@startline\ignorespaces} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % % +% \begin{environment}{tabbing} % \begin{macro}{\tabbing} % \changes{v1.1f}{1995/10/23}{(CAR)Make \cs{@hightab} consistently a % local variable} @@ -513,6 +530,8 @@ \@stopline\ifnum\@tabpush >\z@ \@badpoptabs \fi\endtrivlist} % \end{macrocode} % \end{macro} +% \end{environment} +% % % \begin{macro}{\@rtab} % Omitted |\global| added to |\@rtab| 17 Jun 86 @@ -815,6 +834,7 @@ % \end{macrocode} % \end{macro} % +% \begin{environment}{array} % \begin{macro}{\array} % \begin{macrocode} \def\array{\let\@acol\@arrayacol \let\@classz\@arrayclassz @@ -822,6 +842,7 @@ \let\\\@arraycr\let\@halignto\@empty\@tabarray} % \end{macrocode} % \end{macro} +% \end{environment} % % \begin{macro}{\endarray} % \begin{macro}{\endtabular} @@ -835,11 +856,13 @@ % \end{macro} % \end{macro} % +% \begin{environment}{tabular} % \begin{macro}{\tabular} % \begin{macrocode} \def\tabular{\let\@halignto\@empty\@tabular} % \end{macrocode} % \end{macro} +% \end{environment} % % \begin{macro}{\tabular*} % \changes{v1.1j}{1998/05/18}{Use \cs{setlength}, so that @@ -1003,8 +1026,24 @@ % \end{macro} % % \begin{macro}{\@yargarraycr} +% \changes{v1.1r}{2020/04/21}{Support calc syntax (gh/152)} % \begin{macrocode} -\def\@yargarraycr#1{\cr\noalign{\vskip #1}} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\@yargarraycr}{tabular support calc syntax}% +\def\@yargarraycr#1{\cr\noalign{\@vspace@calcify{#1}}} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@yargarraycr}{tabular support calc syntax}% +%<latexrelease> +%<latexrelease>\def\@yargarraycr#1{\cr\noalign{\vskip #1}} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> % \end{macrocode} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/base/lttextcomp.dtx b/Master/texmf-dist/source/latex/base/lttextcomp.dtx index ed37b9d9957..3b6231dafdf 100644 --- a/Master/texmf-dist/source/latex/base/lttextcomp.dtx +++ b/Master/texmf-dist/source/latex/base/lttextcomp.dtx @@ -33,7 +33,7 @@ % % \ProvidesFile{lttextcomp.dtx} - [2020/02/10 v1.0c LaTeX Kernel (text companion symbols)] + [2020/04/29 v1.0d LaTeX Kernel (text companion symbols)] % \iffalse \documentclass{ltxdoc} \begin{document} @@ -445,7 +445,7 @@ % Using \cs{UndeclareTextCommand} above is enough only if the % encoding definition files are not reloaded afterwards. In the % past that happened if \texttt{fontenc} was used in the document -% preamble (not not any longer). So in some sense it is better to fully remove +% preamble (not any longer). So in some sense it is better to fully remove % them from the encoding files, but for rollbacks it is easier to % keep them in for now. % @@ -565,24 +565,25 @@ % % 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)} % \begin{macrocode} \else - \def\capitalacute{\@tabacckludge'} - \def\capitalbreve{\u} - \def\capitalcaron{\v} - \def\capitalcedilla{\c} - \def\capitalcircumflex{\^} - \def\capitaldieresis{\"} - \def\capitaldotaccent{\.} - \def\capitalgrave{\@tabacckludge`} - \def\capitalhungarumlaut{\H} - \def\capitalmacron{\@tabacckludge=} - \def\capitalnewtie{\t} - \def\capitalogonek{\k} - \def\capitalring{\r} - \def\capitaltie{\t} - \def\capitaltilde{\~} - \def\newtie{\t} + \DeclareTextCommandDefault\capitalacute{\@tabacckludge'} + \DeclareTextCommandDefault\capitalbreve{\u} + \DeclareTextCommandDefault\capitalcaron{\v} + \DeclareTextCommandDefault\capitalcedilla{\c} + \DeclareTextCommandDefault\capitalcircumflex{\^} + \DeclareTextCommandDefault\capitaldieresis{\"} + \DeclareTextCommandDefault\capitaldotaccent{\.} + \DeclareTextCommandDefault\capitalgrave{\@tabacckludge`} + \DeclareTextCommandDefault\capitalhungarumlaut{\H} + \DeclareTextCommandDefault\capitalmacron{\@tabacckludge=} + \DeclareTextCommandDefault\capitalnewtie{\t} + \DeclareTextCommandDefault\capitalogonek{\k} + \DeclareTextCommandDefault\capitalring{\r} + \DeclareTextCommandDefault\capitaltie{\t} + \DeclareTextCommandDefault\capitaltilde{\~} + \DeclareTextCommandDefault\newtie{\t} \fi % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/base/ltvers.dtx b/Master/texmf-dist/source/latex/base/ltvers.dtx index f13a6ae6851..2813670115d 100644 --- a/Master/texmf-dist/source/latex/base/ltvers.dtx +++ b/Master/texmf-dist/source/latex/base/ltvers.dtx @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltvers.dtx} - [2020/01/31 v1.1e LaTeX Kernel (Version Info)] + [2020/03/02 v1.1e LaTeX Kernel (Version Info)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltvers.dtx} @@ -112,10 +112,10 @@ %</2ekernel> %<latexrelease>\edef\latexreleaseversion %<*2ekernel|latexrelease> - {2020-02-02} + {2020-10-01} %</2ekernel|latexrelease> %<*2ekernel> -\def\patch@level{5} +\def\patch@level{0} % \end{macrocode} % % \begin{macro}{\development@branch@name} @@ -250,6 +250,14 @@ \def\@IncludeInRele@se#1#2#3{% \toks@{[#1] #3}% \expandafter\ifx\csname\string#2+\@currname+IIR\endcsname\relax +% \end{macrocode} +% If we roll back and the first patch already match then applying +% 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 +% 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 \GenericInfo{}{Skipping: \the\toks@}% diff --git a/Master/texmf-dist/source/latex/base/ltxdoc.dtx b/Master/texmf-dist/source/latex/base/ltxdoc.dtx index f250b2cb193..696af32ab15 100644 --- a/Master/texmf-dist/source/latex/base/ltxdoc.dtx +++ b/Master/texmf-dist/source/latex/base/ltxdoc.dtx @@ -30,7 +30,7 @@ % %<class>\NeedsTeXFormat{LaTeX2e} %<class>\ProvidesClass{ltxdoc} -%<class> [2019/09/16 v2.0y Standard LaTeX documentation class] +%<class> [2020/08/21 v2.1a Standard LaTeX documentation class] % %<*driver> \documentclass{ltxdoc} @@ -54,6 +54,7 @@ % % \changes{v2.0i}{1994/04/29}{Update the documentation.} % \changes{v2.0s}{1998/08/17}{(RmS) Documentation fixes.} +% \changes{v2.1a}{2020/08/21}{Integration of new hook management interface} % % \section{Documentation of the \LaTeX\ sources} % @@ -422,6 +423,10 @@ \def\partname{File} % \end{macrocode} % +% +% +% \changes{v2.0z}{2020/05/17}{Support spaces \emph{within} filenames +% (gh/218)} % \begin{macrocode} \newcommand*{\DocInclude}[1]{% \relax @@ -432,14 +437,19 @@ {\def\currentfile{#1.dtx}}% \ifnum\@auxout=\@partaux \@latexerr{\string\include\space cannot be nested}\@eha - \else \@docinclude#1 \fi} + \else + \set@curr@file{#1}% + \edef\@curr@file{\@strip@tex@ext\@curr@file}% + \expandafter\@docinclude\expandafter{\@curr@file} + \fi} \def\@docinclude#1 {\clearpage -\if@filesw \immediate\write\@mainaux{\string\@input{#1.aux}}\fi +\if@filesw \immediate\write\@mainaux{\string\@input{"#1.aux"}}\fi \@tempswatrue\if@partsw \@tempswafalse\edef\@tempb{#1}\@for \@tempa:=\@partlist\do{\ifx\@tempa\@tempb\@tempswatrue\fi}\fi \if@tempswa \let\@auxout\@partaux \if@filesw -\immediate\openout\@partaux #1.aux +\immediate\openout\@partaux "#1.aux" \immediate\write\@partaux{\relax}\fi +\@filehook@set@CurrentFile % \end{macrocode} % We need to save (and later restore) various index-related % commands which might be changed by the included file. diff --git a/Master/texmf-dist/source/latex/base/ltxref.dtx b/Master/texmf-dist/source/latex/base/ltxref.dtx index c20a3245588..56ae09c1650 100644 --- a/Master/texmf-dist/source/latex/base/ltxref.dtx +++ b/Master/texmf-dist/source/latex/base/ltxref.dtx @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltxref.dtx} - [2019/09/16 v1.1m LaTeX Kernel (Cross Referencing)] + [2020/08/23 v1.1o LaTeX Kernel (Cross Referencing)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltxref.dtx} @@ -311,14 +311,18 @@ % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\refstepcounter}{Add \labelformat and \Ref}% +%<latexrelease>\IncludeInRelease{2020/10/01}% +%<latexrelease> {\refstepcounter}{Add \@currentcounter}% % \end{macrocode} % % \begin{macro}{\refstepcounter} % Step the counter and allow for labels to point to its current value. +% \changes{v1.1n}{2020/05/05}{record the counter name in \cs{@currentcounter}} +% \changes{v1.1o}{2020/08/23}{add default definition of \cs{@currentcounter}} % \begin{macrocode} +\def\@currentcounter{} \def\refstepcounter#1{\stepcounter{#1}% + \edef\@currentcounter{#1}% \protected@edef\@currentlabel % \end{macrocode} % By generating the second csname first the |\p@...| command can @@ -381,6 +385,17 @@ % \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\refstepcounter}{Add \labelformat and \Ref}% +%<latexrelease>\let\@currentcounter\@undefined +%<latexrelease>\def\refstepcounter#1{\stepcounter{#1}% +%<latexrelease> \protected@edef\@currentlabel +%<latexrelease> {\csname p@#1\expandafter\endcsname\csname the#1\endcsname}% +%<latexrelease>} +%<latexrelease>\def\labelformat#1{\expandafter\def\csname p@#1\endcsname##1} +%<latexrelease>\DeclareRobustCommand\Ref[1]{\protected@edef\@tempa{\ref{#1}}% +%<latexrelease> \expandafter\MakeUppercase\@tempa} +%<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% %<latexrelease> {\refstepcounter}{Add \labelformat and \Ref}% %<latexrelease> diff --git a/Master/texmf-dist/source/latex/base/slides.dtx b/Master/texmf-dist/source/latex/base/slides.dtx index a0dbdabe5f0..8b7276f492d 100644 --- a/Master/texmf-dist/source/latex/base/slides.dtx +++ b/Master/texmf-dist/source/latex/base/slides.dtx @@ -53,7 +53,7 @@ %<*driver> \ProvidesFile{slides.drv} %</driver> - [2019/11/04 v2.4b + [2020/02/20 v2.4b %<+class> Standard LaTeX document class] %<+cmd> SLiTeX definitions] % \end{macrocode} @@ -162,7 +162,7 @@ % % \section{Fonts} % -% Note, that that with NFSS you can easily produce slides with special +% Note, that with NFSS you can easily produce slides with special % fonts just by calling an appropriate style file (like |times|) in a % |\usepackage| command. This works, for example, with all % fonts that are defined to be scaleable (e.g., PostScript fonts) since @@ -2536,14 +2536,14 @@ COLOR LAYER\\[.75in]% % \overline, \underline, \frac and \sqrt % % \@mathbox{STYLE}{BOX}{MTEXT} : Called in math mode, typesets MTEXT and -% stores result in BOX, using style STYLE. +% stores result in BOX, using STYLE. % % \@bphant{BOX} : Creates a phantom with dimensions BOX. % \@vbphant{BOX} : Creates a phantom with ht of BOX and zero width. % \@hbphant{BOX} : Creates a phantom with width of BOX % and zero ht & dp. % \@hvsmash{STYLE}{MTEXT} : Creates a copy of MTEXT with zero height and -% width in style STYLE. +% width in STYLE. %\end{verbatim} % \begin{macrocode} \def\@mathbox#1#2#3{\setbox#2\hbox{$\m@th#1{#3}$}} diff --git a/Master/texmf-dist/source/latex/base/unpack.ins b/Master/texmf-dist/source/latex/base/unpack.ins index b03dd5c6b1b..3264a401d9e 100644 --- a/Master/texmf-dist/source/latex/base/unpack.ins +++ b/Master/texmf-dist/source/latex/base/unpack.ins @@ -123,7 +123,6 @@ \batchinput{latexrelease.ins} - \Msg{} \Msg{*********************************************} \Msg{*} diff --git a/Master/texmf-dist/source/latex/graphics/color.dtx b/Master/texmf-dist/source/latex/graphics/color.dtx index ad5df89a7ee..cdc2dbe5fed 100644 --- a/Master/texmf-dist/source/latex/graphics/color.dtx +++ b/Master/texmf-dist/source/latex/graphics/color.dtx @@ -19,7 +19,7 @@ %<driver> \ProvidesFile{color.drv} % \fi % \ProvidesFile{color.dtx} - [2019/11/23 v1.2a Standard LaTeX Color (DPC)] + [2020/02/24 v1.2b Standard LaTeX Color (DPC)] % % \iffalse %<*driver> @@ -558,6 +558,8 @@ % {usenames option added} % \changes{v0.3f}{1994/10/04} % {Give info about redefinitions} +% \changes{v1.2b}{2020/02/24} +% {corrected test, see https://www.latex-project.org/cgi-bin/ltxbugs2html?pr=graphics/3635} % % Driver files may opt to define a `named' colour model. % Placing colour names rather than numeric specifications into the dvi @@ -603,7 +605,7 @@ {\c@lor@error{model `#1'}}% {\@ifundefined{color@#3}% {\c@lor@error{model `#3'}}% - {\@ifundefined{c@lor@#1@#2}{}% + {\@ifundefined{col@#2}{}% {\PackageInfo{color}{Redefining color #2 in named color model}}% \csname color@#3\endcsname\@tempa{#4}% \csname define@color@#1\endcsname{#2}\@tempa diff --git a/Master/texmf-dist/source/latex/graphics/graphics.dtx b/Master/texmf-dist/source/latex/graphics/graphics.dtx index b88ef1e0666..51ef9a4ee39 100644 --- a/Master/texmf-dist/source/latex/graphics/graphics.dtx +++ b/Master/texmf-dist/source/latex/graphics/graphics.dtx @@ -25,7 +25,7 @@ %<driver> \ProvidesFile{graphics.drv} % \fi % \ProvidesFile{graphics.dtx} - [2019/11/30 v1.4a Standard LaTeX Graphics (DPC,SPQR)] + [2020/08/30 v1.4c Standard LaTeX Graphics (DPC,SPQR)] % % \iffalse %<*driver> @@ -1134,30 +1134,40 @@ \else \Gin@getbase{\Gin@sepdefault\filename@ext}% % \end{macrocode} -% At this point try adding an extension, even if the filename has one so -% that \verb|a.b| may find \verb|a.b.png| if no file is found then revert -% to the extension as given to get better error reporting. +% At this point try adding an extension, either if the given file name +% has none, or if the extension matches no existing graphics inclusion +% rule, so that \verb|a.b| may find \verb|a.b.png|, if only the latter +% or if both files exist. If no file is found then revert to the +% extension as given to get better error reporting. % % \changes{v1.3d}{2019/11/01} -% {Try adding an extension even if the filenam had a dot.} -% \begin{macrocode} -\ifx\Gin@ext\relax -\let\Gin@savedbase\filename@base -\let\Gin@savedext\filename@ext - \edef\filename@base{\filename@base\Gin@sepdefault\filename@ext}% - \let\filename@ext\relax - \@for\Gin@temp:=\Gin@extensions\do{% - \ifx\Gin@ext\relax - \Gin@getbase\Gin@temp - \fi}% -% \end{macrocode} -% Restore if no file found using theknown extensions. +% {Try adding an extension even if the filename had a dot.} +% \changes{v1.4c}{2020/08/30} +% {Try adding an extension even if the filename had a dot AND +% if the filename without the extension exists (but doesn't have +% a known extension).} +% \begin{macrocode} + \ifnum0% + \ifx\Gin@ext\relax 1% + \else \@ifundefined{Gin@rule@\Gin@ext}{1}{0}% + \fi >0 + \let\Gin@ext\relax + \let\Gin@savedbase\filename@base + \let\Gin@savedext\filename@ext + \edef\filename@base{\filename@base\Gin@sepdefault\filename@ext}% + \let\filename@ext\relax + \@for\Gin@temp:=\Gin@extensions\do{% + \ifx\Gin@ext\relax + \Gin@getbase\Gin@temp + \fi}% +% \end{macrocode} +% Restore if no file found using the known extensions. % \begin{macrocode} - \ifx\Gin@ext\relax - \let\filename@base\Gin@savedbase - \let\filename@ext\Gin@savedext - \fi -\fi + \ifx\Gin@ext\relax + \let\filename@base\Gin@savedbase + \let\filename@ext\Gin@savedext + \fi + \fi % \end{macrocode} % % \begin{macrocode} @@ -1428,7 +1438,7 @@ % starting with |%%BoundingBox| and returns the result % by setting four dimension registers % |\Gin@llx|, |\Gin@lly|, |\Gin@urx| and |\Gin@ury|. -% \changes{v0.5e}{1994/1l/02} +% \changes{v0.5e}{1994/11/02} % {Fix the catcodes of \cs{endlinechar} and ctrl-D} % \changes{v0.7a}{1995/04/11} % {Fix more catcodes, for binary headers of eps files} @@ -1474,9 +1484,12 @@ % {Allow TAB in DSC comments graphics/2587} % \changes{v1.0i}{1999/01/07} % {Fix catcode of hyphen. graphics/2846} +% \changes{v1.4b}{2020/08/09} +% {Normalise \cs{endlinechar} gh/286} % \begin{macrocode} \catcode`\ 10 % \catcode`\^^I10 % + \endlinechar13 % \catcode\endlinechar5 % \@makeother\:% \@makeother\-% @@ -1574,6 +1587,7 @@ \fi} % \end{macrocode} % \end{macro} +% % \begin{macro}{\Gread@parse@bb} % We have |%%BoundingBox| and what follows is not `(atend)' so we % will parse the rest of the line as a BB with four elements. @@ -1596,6 +1610,68 @@ % \end{macrocode} % \end{macro} % +% Viewport and trim, originally in |graphicx|. +% +% \begin{macro}{\Gin@viewport} +% \changes{v1.0c}{1996/10/31}{Original bb saved} +% If a viewport is specified, reset the bounding box coordinates +% by adding the original origin, |\Gin@llx|, |\Gin@lly| to the new +% values specified as the viewport. The original Bounding box +% coordinates are saved in |\Gin@ollx|\ldots\ some drivers +% might need this information (currently just |tcidvi|). +% \begin{macrocode} +\def\Gin@viewport{% + \let\Gin@ollx\Gin@llx + \let\Gin@olly\Gin@lly + \let\Gin@ourx\Gin@urx + \let\Gin@oury\Gin@ury + \dimen@\Gin@llx\p@\advance\dimen@ \Gin@vurx\p@ + \edef\Gin@urx{\strip@pt\dimen@}% + \dimen@\Gin@lly\p@\advance\dimen@ \Gin@vury\p@ + \edef\Gin@ury{\strip@pt\dimen@}% + \dimen@\Gin@llx\p@\advance\dimen@ \Gin@vllx\p@ + \edef\Gin@llx{\strip@pt\dimen@}% + \dimen@\Gin@lly\p@\advance\dimen@ \Gin@vlly\p@ + \edef\Gin@lly{\strip@pt\dimen@}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\Gin@trim} +% \changes{v1.0c}{1996/10/31}{Original bb saved} +% If a trim is specified, reset the bounding box coordinates +% by trimming the four specified values off each side of the +% graphic. +% \begin{macrocode} +\def\Gin@trim{% + \let\Gin@ollx\Gin@llx + \let\Gin@olly\Gin@lly + \let\Gin@ourx\Gin@urx + \let\Gin@oury\Gin@ury + \dimen@\Gin@llx\p@\advance\dimen@ \Gin@vllx\p@ + \edef\Gin@llx{\strip@pt\dimen@}% + \dimen@\Gin@lly\p@\advance\dimen@ \Gin@vlly\p@ + \edef\Gin@lly{\strip@pt\dimen@}% + \dimen@\Gin@urx\p@\advance\dimen@ -\Gin@vurx\p@ + \edef\Gin@urx{\strip@pt\dimen@}% + \dimen@\Gin@ury\p@\advance\dimen@ -\Gin@vury\p@ + \edef\Gin@ury{\strip@pt\dimen@}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\Gin@vllx} +% \begin{macro}{\Gin@vlly} +% \begin{macro}{\Gin@vurx} +% \begin{macro}{\Gin@vury} +% Four macros to hold the modifiers for the bounding box for viewport +% and trim specifications. +% \begin{macrocode} +\let\Gin@vllx\Gin@llx\let\Gin@vlly\Gin@llx +\let\Gin@vurx\Gin@llx\let\Gin@vury\Gin@llx +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % \subsection{Rotation} % diff --git a/Master/texmf-dist/source/latex/graphics/graphicx.dtx b/Master/texmf-dist/source/latex/graphics/graphicx.dtx index 3cf15925d3f..b10c67c7946 100644 --- a/Master/texmf-dist/source/latex/graphics/graphicx.dtx +++ b/Master/texmf-dist/source/latex/graphics/graphicx.dtx @@ -17,7 +17,7 @@ %<driver> \ProvidesFile{graphicx.drv} % \fi % \ProvidesFile{graphicx.dtx} - [2019/11/30 v1.2a Enhanced LaTeX Graphics (DPC,SPQR)] + [2020/09/09 v1.2b Enhanced LaTeX Graphics (DPC,SPQR)] % % \iffalse %<*driver> @@ -342,66 +342,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\Gin@viewport} -% \changes{v1.0c}{1996/10/31}{Original bb saved} -% If a viewport is specified, reset the bounding box coordinates -% by adding the original origin, |\Gin@llx|, |\Gin@lly| to the new -% values specified as the viewport. The original Bounding box -% coordinates are saved in |\Gin@ollx|\ldots\ some drivers -% might need this information (currently just |tcidvi|). -% \begin{macrocode} -\def\Gin@viewport{% - \let\Gin@ollx\Gin@llx - \let\Gin@olly\Gin@lly - \let\Gin@ourx\Gin@urx - \let\Gin@oury\Gin@ury - \dimen@\Gin@llx\p@\advance\dimen@ \Gin@vurx\p@ - \edef\Gin@urx{\strip@pt\dimen@}% - \dimen@\Gin@lly\p@\advance\dimen@ \Gin@vury\p@ - \edef\Gin@ury{\strip@pt\dimen@}% - \dimen@\Gin@llx\p@\advance\dimen@ \Gin@vllx\p@ - \edef\Gin@llx{\strip@pt\dimen@}% - \dimen@\Gin@lly\p@\advance\dimen@ \Gin@vlly\p@ - \edef\Gin@lly{\strip@pt\dimen@}} -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\Gin@trim} -% \changes{v1.0c}{1996/10/31}{Original bb saved} -% If a trim is specified, reset the bounding box coordinates -% by trimming the four specified values off each side of the -% graphic. -% \begin{macrocode} -\def\Gin@trim{% - \let\Gin@ollx\Gin@llx - \let\Gin@olly\Gin@lly - \let\Gin@ourx\Gin@urx - \let\Gin@oury\Gin@ury - \dimen@\Gin@llx\p@\advance\dimen@ \Gin@vllx\p@ - \edef\Gin@llx{\strip@pt\dimen@}% - \dimen@\Gin@lly\p@\advance\dimen@ \Gin@vlly\p@ - \edef\Gin@lly{\strip@pt\dimen@}% - \dimen@\Gin@urx\p@\advance\dimen@ -\Gin@vurx\p@ - \edef\Gin@urx{\strip@pt\dimen@}% - \dimen@\Gin@ury\p@\advance\dimen@ -\Gin@vury\p@ - \edef\Gin@ury{\strip@pt\dimen@}} -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\Gin@vllx} -% \begin{macro}{\Gin@vlly} -% \begin{macro}{\Gin@vurx} -% \begin{macro}{\Gin@vury} -% Four macros to hold the modifiers for the bounding box for viewport -% and trim specifications. -% \begin{macrocode} -\let\Gin@vllx\Gin@llx\let\Gin@vlly\Gin@llx -\let\Gin@vurx\Gin@llx\let\Gin@vury\Gin@llx -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % \begin{key}{Gin}{angle} % Specify a rotation. This is just handled by wrapping the diff --git a/Master/texmf-dist/source/latex/graphics/lscape.dtx b/Master/texmf-dist/source/latex/graphics/lscape.dtx index e14462c9d42..ac5c16d7c20 100644 --- a/Master/texmf-dist/source/latex/graphics/lscape.dtx +++ b/Master/texmf-dist/source/latex/graphics/lscape.dtx @@ -17,7 +17,7 @@ %<driver> \ProvidesFile{lscape.drv} % \fi % \ProvidesFile{lscape.dtx} - [2000/10/22 v3.01 Landscape Pages (DPC)] + [2020/05/28 v3.02 Landscape Pages (DPC)] % % \iffalse %<*driver> @@ -61,6 +61,7 @@ % \changes{v3.00}{1994/10/05}{Update using LaTeX2e graphics package} % \changes{v3.01}{1999/06/22}{Added better pdfTeX support % by Scott Pakin, from graphics/3063} +% \changes{v3.02}{2020/05/28}{delay saving \cs{@makefcolumn} gh340} % % % \begin{macrocode} @@ -90,8 +91,6 @@ % \end{macrocode} % % \begin{macrocode} -\let\LS@makecol=\@makecol -\let\LS@makefcolumn=\@makefcolumn \def\LS@rot{% \setbox\@outputbox\vbox{\hbox{\rotatebox{90}{\box\@outputbox}}}} % \end{macrocode} @@ -99,6 +98,8 @@ % First set up the page size for landscape. % \begin{macrocode} \def\landscape{% + \let\LS@makecol=\@makecol + \let\LS@makefcolumn=\@makefcolumn \clearpage \begingroup \vsize=\textwidth diff --git a/Master/texmf-dist/source/latex/tools/array.dtx b/Master/texmf-dist/source/latex/tools/array.dtx index acfa5609373..ff963d7f514 100644 --- a/Master/texmf-dist/source/latex/tools/array.dtx +++ b/Master/texmf-dist/source/latex/tools/array.dtx @@ -29,10 +29,11 @@ %<+package>\providecommand\DeclareCurrentRelease[2]{} %<+package> %<+package>\DeclareRelease{}{2016-10-06}{array-2016-10-06.sty} -%<+package>\DeclareCurrentRelease{}{2019-10-01} +%<+package>\DeclareRelease{v2.4}{2020-02-10}{array-2020-02-10.sty} +%<+package>\DeclareCurrentRelease{}{2020-10-01} %<+package> %<+package>\ProvidesPackage{array} -%<+package> [2019/08/31 v2.4l Tabular extension package (FMi)] +%<+package> [2020/10/01 v2.5c Tabular extension package (FMi)] % % \fi % @@ -551,14 +552,16 @@ % \item rules can be placed between columns or rows thereby enlarging % the table. % \end{enumerate} -% \texttt{array.sty} implements the second possibility while the -% default implementation in the \LaTeX{} kernel implements the first -% concept. Both concepts have their merits but one has to be aware of -% the individual implications. +% For vertical rules \texttt{array.sty} implements the second +% possibility while the default implementation in the \LaTeX{} kernel +% implements the first concept. +% Both concepts have their merits but +% one has to be aware of the individual implications. % \begin{itemize} % \item -% With standard \LaTeX{} adding rules to a table will not affect the -% width or height of the table (unless double rules are used), e.g., +% With standard \LaTeX{} adding vertical rules to a table will +% not affect the +% width of the table (unless double rules are used), e.g., % changing a preamble from \verb=lll= to \verb=l|l|l= does not % affect the document other than adding rules to the table. In % contrast, with \texttt{array.sty} a table that just fit the @@ -601,6 +604,12 @@ % \end{center} % \end{itemize} % +% Horizontal rules produced with \cs{hline} add to the table height in +% both implementations but they differ in handling double \cs{hline}s. +% In contrast a \cs{cline} does not change the table +% height.\footnote{All a bit inconsistent, but nothing that can be +% changed after being 30+ years in existence.} +% % \subsection{Comparisons with older versions of \texttt{array.sty}} % % There are some differences in the way version 2.1 treats incorrect @@ -730,7 +739,11 @@ \NeedsTeXFormat{LaTeX2e}[1995/12/01] \documentclass{ltxdoc} -\AtBeginDocument{\DeleteShortVerb{\|}} % undo the default is not used +% undo the default is not used: + +\IfFormatAtLeastTF {2020/10/01} + {\AtBeginDocument[ltxdoc]{\DeleteShortVerb{\|}} } + {\AtBeginDocument{\DeleteShortVerb{\|}} } \usepackage{array} @@ -746,6 +759,7 @@ %\OnlyDescription % comment out for implementation details %\OldMakeindex % use if your MakeIndex is pre-v2.9 + \begin{document} \DocInput{array.dtx} \end{document} @@ -2206,8 +2220,13 @@ \let\do@row@strut\relax % \end{macrocode} % +% \cs{@yargarraycr} is the same as in the \LaTeX{} kernel +% (depending on the date of the kernel with one of the two +% definitions below). We therefore do not define it again. +% \changes{v2.5b}{2020/04/22}{Don't define \cs{@yargarraycr} unnecessarily} % \begin{macrocode} -\def\@yargarraycr#1{\cr\noalign{\vskip #1}} +%\def\@yargarraycr#1{\cr\noalign{\@vspace@calcify{#1}}} % 2020-10-01 +%\def\@yargarraycr#1{\cr\noalign{\vskip #1}} % \end{macrocode} % \end{macro} % \end{macro} @@ -2916,10 +2935,13 @@ % % We start by producing a single tabular row without any visible % content that will produce the external reference point in case -% "[t]" is used. +% "[t]" is used. We need to suppress the \cs{tabcolsep} in the +% \cs{multicolumn} in case there wasn't any in the real column. +% +% \changes{v2.5c}{2020/07/20}{Suppress all column space (gh/322)} % \begin{macrocode} \newcommand{\firsthline}{% - \multicolumn1c{% + \multicolumn1{@{}c@{}}{% % \end{macrocode} % Within this row we calculate "\backup@length" to be the height % plus depth of a standard line. In addition we have to add the @@ -2936,6 +2958,10 @@ % \begin{macrocode} \raise\extratabsurround\copy\@arstrutbox % \end{macrocode} +% And we should also cancel the guard otherwise we end up with two. +% \begin{macrocode} + \kern-1sp% +% \end{macrocode} % Having done all this we end the line and back up by the value of % "\backup@length" and then finally place our "\hline". This should % place the line exactly at the right place but keep the reference @@ -2957,9 +2983,12 @@ % depth of this last line increased by "\extratabsurround" without % changing the placement "\hline". % -% We start by placing the rule followed by an invisible row. +% We start by placing the rule followed by an invisible row. We +% need to suppress the \cs{tabcolsep} in the multicol in case there +% wasn't any in the real column. +% \changes{v2.5c}{2020/07/20}{Suppress all column space (gh/322)} % \begin{macrocode} -\newcommand{\lasthline}{\hline\multicolumn1c{% +\newcommand{\lasthline}{\hline\multicolumn1{@{}c@{}}{% % \end{macrocode} % We now calculate "\backup@length" to be the height and depth of % two lines plus the width of the rule. @@ -2977,8 +3006,9 @@ % reference for the whole tabular). Since this row is invisible we % can enlarge its depth by the desired amount. % \begin{macrocode} - \multicolumn1c{% + \multicolumn1{@{}c@{}}{% \lower\extratabsurround\copy\@arstrutbox + \kern-1sp% }% } % \end{macrocode} @@ -3034,14 +3064,18 @@ % alignment which is either "l", "c", or "r" and the second is the % nominal width of the column. % \changes{v2.4f}{2017/11/07}{Column type added} +% \changes{v2.5a}{2020/04/06}{Use \cs{d@llarbegin} and \cs{d@llarend} so +% that cell is typeset in math mode inside \texttt{array} (gh/297)} % \begin{macrocode} \newcolumntype{w}[2]{% % \end{macrocode} % Before the cell content we start an "lrbox"-environment to % collect the cell material into the previously allocated box -% "\ar@cellbox". +% "\ar@cellbox". We add \cs{d@llarbegin} (and later \cs{d@llarend}) +% so that the content is typeset in math mode if we are in an +% \texttt{array} environment. % \begin{macrocode} - >{\begin{lrbox}\ar@cellbox}% + >{\begin{lrbox}\ar@cellbox\d@llarbegin}% % \end{macrocode} % Then comes a specifier for the cell content. We use "c", but % that doesn't matter as in the end we will always put a box of a @@ -3056,10 +3090,13 @@ % of the cell content is now in box "\ar@cellbox". As a final step we % put that box into a "\makebox" using the optional arguments of % that command to achieve the correct width and the desired -% alignment within that width. +% alignment within that width. We unbox the collected material so +% that any stretchable glue inside can interact with the alignment. +% \changes{v2.4m}{2020/02/10}{Unbox collected material so that +% stretchable glue inside can act (gh/270)} % \begin{macrocode} - <{\end{lrbox}% - \makebox[#2][#1]{\usebox\ar@cellbox}}} + <{\d@llarend \end{lrbox}% + \makebox[#2][#1]{\unhbox\ar@cellbox}}} % \end{macrocode} % \end{macro} @@ -3069,11 +3106,13 @@ % The \texttt{W} is similar but in this case we want a warning if % the cell content is too wide. % \changes{v2.4f}{2017/11/07}{Column type added} +% \changes{v2.5a}{2020/04/06}{Use \cs{d@llarbegin} and \cs{d@llarend} so +% that cell is typeset in mathmode inside \texttt{array} (gh/297)} % \begin{macrocode} \newcolumntype{W}[2] - {>{\begin{lrbox}\ar@cellbox}% + {>{\begin{lrbox}\ar@cellbox\d@llarbegin}% c% - <{\end{lrbox}% + <{\d@llarend\end{lrbox}% \let\hss\hfil \makebox[#2][#1]{\unhbox\ar@cellbox}}} % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/tools/varioref.dtx b/Master/texmf-dist/source/latex/tools/varioref.dtx index 077103eb97a..2bba60465e0 100644 --- a/Master/texmf-dist/source/latex/tools/varioref.dtx +++ b/Master/texmf-dist/source/latex/tools/varioref.dtx @@ -40,7 +40,7 @@ %<package>\DeclareCurrentRelease{}{2019-10-01} %<package> %<package>\ProvidesPackage{varioref} -%<package> [2020/01/23 v1.6c package for extended references (FMi)] +%<package> [2020/08/11 v1.6e package for extended references (FMi)] % \fi % %% @@ -70,7 +70,7 @@ % \PackageWarning{inputenc}{Unicode character \expandafter % \UTFviii@splitcsname\string##1\relax % \MessageBreak -% not set up for use with LaTeX}^^A +% not set up for use with LaTeX -- ignored}^^A % \raisebox{.8pt}{\fboxsep1pt\kern.1pt\fbox{$\cdot$}\kern.1pt}^^A % }} % \makeatother @@ -390,6 +390,8 @@ %\end{verbatim} % textual references can be suppressed. % +% +% % \section{Multi-lingual usage} % % The package works well together with the babel system if it is @@ -475,6 +477,19 @@ % describes the range of figures, tables, or whatever the labels refer % to, the default for English is ``|\ref{#1} to~\ref{#2}|''. % +% +% \NewIn{2020} +% \DescribeMacro\vrefformat +% \DescribeMacro\Vrefformat +% \DescribeMacro\vrefrangeformat +% \DescribeMacro\fullrefformat +% In some languages (currently only for Japanese) the generated text +% has to typeset in different word order to most other (Western) languages. +% To accomodate for this \cs{vrefformat}, etc.\ has been +% added to allow to alter this on a per language basis. +% There should be normally no need to alter the setup. For details see +% the code section. +% % \subsection{\ldots\ if Babel is used} % % \begin{itshape} If babel is being used then the above commands need to be @@ -556,6 +571,7 @@ % |\fullref| is also provided. This command can be used whenever you % know for sure that label and reference can't fall onto nearby pages. % +% % \StopEventually{\PrintIndex\PrintChanges} % % @@ -708,6 +724,10 @@ \def\reftextfaraway#1{op bladsy~\pageref{#1}}% \def\reftextpagerange#1#2{op bladsye~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} tot~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % @@ -723,6 +743,10 @@ \def\reftextfaraway#1{on page~\pageref{#1}}% \def\reftextpagerange#1#2{on pages~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} to~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Arabic option text was contributed by Ihab Samir Mattar @@ -743,6 +767,10 @@ \def\reftextfaraway#1{بالصفحة رقم~\pageref{#1}}% \def\reftextpagerange#1#2{بالصفحات~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} حتى~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % \end{allowtofu} @@ -759,6 +787,7 @@ \def\reftextfaraway#1{auf Seite~\pageref{#1}}% \def\reftextpagerange#1#2{auf Seiten~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} bis~\ref{#2}}% + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % \changes{v1.2d}{2000/01/11}{Added naustrian defaults (identical to german)} @@ -774,6 +803,10 @@ \def\reftextfaraway#1{auf Seite~\pageref{#1}}% \def\reftextpagerange#1#2{auf Seiten~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} bis~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Text for basque defaults was contributed by @@ -791,6 +824,10 @@ \def\reftextfaraway#1{~\pageref{#1}. orrialdean}% \def\reftextpagerange#1#2{~\pageref{#1}--\pageref{#2} orrialdeetan}% \def\reftextlabelrange#1#2{\ref{#1}.etik \ref{#2}.eraino}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Text for the Bahasa Malaysia defaults was contributed by @@ -815,6 +852,10 @@ \def\reftextfaraway#1{pada muka surat~\pageref{#1}}% \def\reftextpagerange#1#2{pada muka surat~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1}--\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Text for brazil defaults was contributed by @@ -837,6 +878,10 @@ \def\reftextfaraway#1{na p\'agina~\pageref{#1}}% \def\reftextpagerange#1#2{nas p\'aginas~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} a~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Text for Breton defaults was contributed by @@ -858,6 +903,10 @@ on pages~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\vref@stringwarning\reflabelpagerange \ref{#1} to~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Text for Bulgarian defaults was contributed by @@ -892,6 +941,10 @@ \cyrs\cyrt\cyrr\cyra\cyrn\cyri\cyrc\cyri ~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} \cyrd\cyro~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Text for catalan defaults was contributed by Robert Fuster\\ @@ -910,6 +963,10 @@ \def\reftextpagerange#1#2{a les p\`agines~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} a~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Text for croatian defaults was contributed by \v{S}ime Ungar @@ -926,6 +983,10 @@ \def\reftextfaraway#1{na stranici~\pageref{#1}}% \def\reftextpagerange#1#2{na stranicama~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} do~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Defaults for the Czech option provided by Milan Vancura @@ -943,6 +1004,10 @@ \def\reftextfaraway#1{na stran\v{e}~\pageref{#1}}% \def\reftextpagerange#1#2{na stran\'ach~\pageref{#1}\--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} a\v{z}~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Defaults for Danish provided by Torsten Martinsen @@ -965,6 +1030,10 @@ \def\reftextfaraway#1{p\aa{} side~\pageref{#1}}% \def\reftextpagerange#1#2{p\aa{} side~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} til~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Default string for dutch have been contributed by Frank Poppe @@ -1004,6 +1073,10 @@ % \begin{macrocode} \def\reftextpagerange#1#2{op pagina's~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1}--\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % \changes{v1.2a}{1998/08/22}{Added english defaults for @@ -1021,6 +1094,10 @@ \def\reftextfaraway#1{on page~\pageref{#1}}% \def\reftextpagerange#1#2{on pages~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} to~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % @@ -1041,6 +1118,10 @@ \def\reftextfaraway#1{en pa\^go~\pageref{#1}}% \def\reftextpagerange#1#2{en pa\^goj~\pageref{#1} \^gis \pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} \^gis~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % The finnish strings were suggested by Matti Rintala @@ -1064,6 +1145,10 @@ % Can't combine numbers with the necessary suffix well. % \begin{macrocode} \def\reftextlabelrange#1#2{\ref{#1}--\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % French defaults are provided by Daniel Flippo @@ -1083,6 +1168,10 @@ \def\reftextfaraway#1{page~\pageref{#1}}% \def\reftextpagerange#1#2{pages~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} \`a~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Galician defaults are provided by Matthias Moebius\\ @@ -1104,6 +1193,10 @@ \def\reftextpagerange#1#2{% nas p\'axinas~\pageref{#1}-\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} a~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % There are no good variants for German (I think and still think but @@ -1138,6 +1231,10 @@ \def\reftextfaraway#1{auf Seite~\pageref{#1}}% \def\reftextpagerange#1#2{auf den Seiten~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} bis~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % \changes{v1.2d}{2000/01/11}{Added ngerman defaults (identical to german)} @@ -1155,6 +1252,10 @@ \def\reftextfaraway#1{auf Seite~\pageref{#1}}% \def\reftextpagerange#1#2{auf den Seiten~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} bis~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Defaults for greek suggested by Apostolos Syropoulos\\ @@ -1174,6 +1275,10 @@ \def\reftextpagerange#1#2{stis sel'ides\nobreakspace \pageref{#1}---\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} ws\nobreakspace\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Icelandic defaults suggested by Thorhallur Sverrisson @@ -1194,6 +1299,10 @@ \def\reftextfaraway#1{\'{a} s\'{i}{\dh}u~\pageref{#1}}% \def\reftextpagerange#1#2{\'{a} s\'{i}{\dh}um~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} til~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Defaults for Italian suggested by Giovanni Pensa @@ -1218,8 +1327,44 @@ \def\reftextfaraway#1{a pagina~\pageref{#1}}% \def\reftextpagerange#1#2{nelle pagine~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{da~\ref{#1} a~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} +% Defaults for Japanese. It needs a special \cs{vrefformat}, +% \cs{Vrefformat}, \cs{fullrefformat} and \cs{vrefrangeformat} +% for gramatical reasons. As our standard documentation +% workflow uses pdf\TeX{} the Japanese letters can't be displayed +% easily, so you will see missing glyphs below. To see the real +% letters you have to look at the source or package file. +% \changes{v1.6d}{2020/07/20}{Option japanese added (gh/352)} +% \changes{v1.6e}{2020/07/25}{Option japanese changed (gh/352)} +% \begin{allowtofu} +% \begin{macrocode} +\DeclareOption{japanese} + {\vref@addto\extrasjapanese{% + \def\reftextfaceafter {\reftextvario{見開き}{次}ページ}% + \def\reftextfacebefore{\reftextvario{見開き}{前}ページ}% + \def\reftextafter {\reftextvario{直後の}{次}ページ}% + \def\reftextbefore {\reftextvario{直前の}{前}ページ}% + \def\reftextcurrent {\reftextvario{この}{現}ページ}% + \def\reftextfaraway#1{\pageref{#1}ページ}% + \def\reftextpagerange#1#2{\pageref{#1}から\pageref{#2}ページ}% + \def\reftextlabelrange#1#2{\ref{#1}から\ref{#2}}% +% \end{macrocode} +% Note that the parentheses beow are not normal ones but full width +% ones U+FF08 and U+FF09! +% \begin{macrocode} + \def\vrefformat#1#2{\ref{#2}(\vpageref[#1]{#2})}% + \def\Vrefformat#1#2{\Ref{#2}(\vpageref[#1]{#2})}% + \def\fullrefformat#1{\ref{#1}(\reftextfaraway{#1})}% + \def\vrefrangeformat#1#2#3{\reftextlabelrange{#2}{#3}% + (\vpagerefrange[{#1}]{#2}{#3})}% + }} +% \end{macrocode} +% \end{allowtofu} % Defaults for Hungarian by Jeff Goldberg % (\verb=jeffrey@goldmark.org=). % There is a problem with the use of the definite article @@ -1264,6 +1409,10 @@ on pages~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\vref@stringwarning\reflabelpagerange \ref{#1} to~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }% % \end{macrocode} % The |\AtBeginDocument| needs to be executed when the option is @@ -1304,6 +1453,10 @@ \def\reftextfaraway#1{p\aa{} side~\pageref{#1}}% \def\reftextpagerange#1#2{p\aa{} side~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} til~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} \DeclareOption{nynorsk} {\vref@addto\extrasnynorsk{% @@ -1315,6 +1468,10 @@ \def\reftextfaraway#1{p\aa{} side~\pageref{#1}}% \def\reftextpagerange#1#2{p\aa{} side~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} til~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % The polish translations have been provided by @@ -1342,6 +1499,10 @@ \def\reftextfaraway#1{na stronie~\pageref{#1}}% \def\reftextpagerange#1#2{na stronach~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{od~\ref{#1} do~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % The portuguese default text has been provided by @@ -1362,6 +1523,10 @@ \def\reftextfaraway#1{na p\'agina~\pageref{#1}}% \def\reftextpagerange#1#2{nas p\'aginas~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} a~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Updates to the default text for Romanian have been suggested by Florin Oprina @@ -1381,6 +1546,10 @@ \def\reftextfaraway#1{pe pagina~\pageref{#1}}% \def\reftextpagerange#1#2{pe paginile~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} la~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % The text for russian was taken from the book in Russian by @@ -1414,6 +1583,10 @@ \def\reftextpagerange#1#2{\cyrn\cyra\ \cyrs\cyrt\cyrr\cyra\cyrn \cyri\cyrc\cyra\cyrh~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\cyrs~\ref{#1}\ \cyrp\cyro~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % The text for slovak defaults was contributed by Miroslav Sedivy\\ @@ -1434,6 +1607,10 @@ \def\reftextfaraway#1{na strane~\pageref{#1}}% \def\reftextpagerange#1#2{na stran\'ach~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} a\v z~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % The text for slovene defaults was contributed by Roman Maurer\\ @@ -1450,6 +1627,10 @@ \def\reftextfaraway#1{na strani~\pageref{#1}}% \def\reftextpagerange#1#2{na straneh~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{od~\ref{#1} do~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % Text for spanish defaults was contributed by Julio Sanchez @@ -1470,6 +1651,10 @@ \def\reftextpagerange#1#2{en las p\'aginas~\pageref{#1}% -\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} a~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % The text for swedish was contributed by Mats Dahlgren @@ -1492,6 +1677,10 @@ \def\reftextpagerange#1#2{p\aa\ sidorna~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} till~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} \DeclareOption{turkish} {\vref@excuse{turkish}% @@ -1505,6 +1694,7 @@ \def\reftextfaraway#1{on page~\pageref{#1}}% \def\reftextpagerange#1#2{on pages~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\ref{#1} to~\ref{#2}}% + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % The text for Ukrainian defaults was contributed by Mykola Lyakhovych\\ @@ -1532,6 +1722,10 @@ \def\reftextpagerange#1#2{\cyrn\cyra\ \cyrs\cyrt\cyro\cyrr\cyrii \cyrn\cyrk\cyra\cyrh~\pageref{#1}--\pageref{#2}}% \def\reftextlabelrange#1#2{\cyrz~\ref{#1}\ \cyrd\cyro~\ref{#2}}% + \let\vrefformat\vrefdefaultformat + \let\Vrefformat\Vrefdefaultformat + \let\fullrefformat\fullrefdefaultformat + \let\vrefrangeformat\vrefrangedefaultformat }} % \end{macrocode} % We support francais as an alternative to french since people @@ -1585,7 +1779,6 @@ % \pkg{babel} package). % \begin{macrocode} \ExecuteOptions{english,final,space} -\ProcessOptions* % \end{macrocode} % % @@ -2062,11 +2255,26 @@ % |\vpageref|, it that is needed one has to call both commands % explicitly % \changes{v1.6a}{2019/08/25}{Command added to support hyperref better} +% \changes{v1.6e}{2020/07/25}{Changed for Japanese (gh/352)} +% \begin{macrocode} +\newcommand\vref@star[1][]{\vrefformat{#1}} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\vrefformat,\vrefdefaultformat} +% Japanese needs a different word order in \cs{vref@star} so this +% is separated out o that it can be changed on language level. +% \changes{v1.6e}{2020/07/25}{Macro added (gh/352)} % \begin{macrocode} -\newcommand\vref@star[2][]{% +\def\vrefdefaultformat#1#2{% \ref{#2} \vpageref[#1]{#2}} % \end{macrocode} +% Most languages need the above definition. +% \begin{macrocode} +\let\vrefformat\vrefdefaultformat +% \end{macrocode} % \end{macro} % \begin{macro}{\vr@f} @@ -2172,8 +2380,24 @@ % \begin{macro}{\fullref} % And here is the primitive command that always produces a |\ref| % and a |\pageref|. +% \changes{v1.6e}{2020/07/25}{Changed for Japanese (gh/352)} +% \begin{macrocode} +\newcommand\fullref{\fullrefformat} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\fullrefformat,\fullrefdefaultformat} +% Japanese needs a different word order in \cs{fullref} so this +% is separated out o that it can be changed on language level. +% \changes{v1.6e}{2020/07/25}{Macro added (gh/352)} % \begin{macrocode} -\def\fullref#1{\ref{#1} \reftextfaraway{#1}} +\def\fullrefdefaultformat#1{% + \ref{#1} \reftextfaraway{#1}} +% \end{macrocode} +% Most languages need the above definition. +% \begin{macrocode} +\let\fullrefformat\fullrefdefaultformat % \end{macrocode} % \end{macro} % @@ -2286,13 +2510,28 @@ % \changes{v1.2a}{1998/08/01}{Macro added} % \changes{v1.4s}{2006/08/07} % {Prevent loss of brackets} +% \changes{v1.6d}{2020/07/20}{Changed for Japanese (gh/352)} +% Argument two and three are implicitly picked up. % \begin{macrocode} -\newcommand\vrefrange[3][\reftextcurrent] - {\reftextlabelrange{#2}{#3} \vpagerefrange[{#1}]{#2}{#3}} +\newcommand\vrefrange[1][\reftextcurrent]{\vrefrangeformat{#1}} % \end{macrocode} +% % \end{macro} % % +% \begin{macro}{\vrefrangeformat,\vrefrangedefaultformat} +% Japanese needs a different word order in \cs{vrefrange} so this +% is separated out o that it can be changed on language level. +% \changes{v1.6d}{2020/07/20}{Macro added (gh/352)} +% \begin{macrocode} +\def\vrefrangedefaultformat#1#2#3{% + \reftextlabelrange{#2}{#3} \vpagerefrange[{#1}]{#2}{#3}} +% \end{macrocode} +% Most languages need the above definition. +% \begin{macrocode} +\let\vrefrangeformat\vrefrangedefaultformat +% \end{macrocode} +% \end{macro} % % \begin{macro}{\Vref} % \changes{v1.4a}{2002/02/24}{Macro added} @@ -2308,11 +2547,26 @@ % % \begin{macro}{\Vref@star} % \changes{v1.6a}{2019/08/25}{Command added to support hyperref better} +% \changes{v1.6e}{2020/07/25}{Changed for Japanese (gh/352)} % \begin{macrocode} -\newcommand\Vref@star[2][]{% +\newcommand\Vref@star[1][]{\Vrefformat{#1}} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\Vrefformat,\Vrefdefaultformat} +% Japanese needs a different word order in \cs{Vref} so this +% is separated out o that it can be changed on language level. +% \changes{v1.6e}{2020/07/25}{Macro added (gh/352)} +% \begin{macrocode} +\def\Vrefdefaultformat#1#2{% \Ref{#2} \vpageref[#1]{#2}} % \end{macrocode} +% Most languages need the above definition. +% \begin{macrocode} +\let\Vrefformat\Vrefdefaultformat +% \end{macrocode} % \end{macro} % % \begin{macro}{\Vr@f} @@ -2443,6 +2697,12 @@ % \end{macro} % \end{macro} % +% \changes{v1.6e}{2020/07/25}{Move to handle +% the language-specific reference formats. (gh/352)} +% \begin{macrocode} +\ProcessOptions* +% \end{macrocode} +% % \begin{macrocode} %</package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/tools/verbatim.dtx b/Master/texmf-dist/source/latex/tools/verbatim.dtx index 121e2d4b39c..e62886e0033 100644 --- a/Master/texmf-dist/source/latex/tools/verbatim.dtx +++ b/Master/texmf-dist/source/latex/tools/verbatim.dtx @@ -69,6 +69,8 @@ %\fi % % +% \changes{v1.5u}{2020-07-07}{Typo repair and added a missing comment +% character} % \changes{v1.5q}{2003/08/22}{Reintroduced \cs{@noligs}, by popular % request.} % \changes{v1.5i}{1996/06/04}{Move setting of verbatim font and @@ -462,9 +464,12 @@ % the spacing. % Then we open the file and set the category codes of all special % characters: +% \changes{v1.5t}{2020-07-05}{Added quotes around the filename in +% order to allow a filename with spaces; also added a space and +% comment-character to allow for thespace dlimited argument.} % \begin{verbatim} % \@bsphack -% \immediate\openout \verbatim@out #1 +% \immediate\openout \verbatim@out "#1" % % \let\do\@makeother\dospecials % \catcode`\^^M\active %\end{verbatim} @@ -503,7 +508,7 @@ %<*package> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{verbatim} - [2019/11/10 v1.5r LaTeX2e package for verbatim enhancements] + [2020-07-07 v1.5u LaTeX2e package for verbatim enhancements] \@ifundefined{verbatim@@@}{}{\endinput} % \end{macrocode} % @@ -1567,19 +1572,31 @@ % existence of file.} % |\verbatim@input| first checks whether the file exists, using % the standard macro |\IfFileExists| which leaves the name of the -% file found in |\@filef@und|. -% Then everything is set up as in the |\verbatim| macro. +% file found in |\@filef@und|. +% Then everything is set up as in the |\verbatim| macro. But, as +% |\@verbatim| contains a call to |\every@verbatim| which +% \emph{might} contain an |\input| statement, which would overwrite +% the contents of |\@filef@und|, we need to save it by expanding it +% first. The use of |\@swaptwoargs| makes it so that the +% \emph{expansion} of |\@filef@und| gets to be the second argument +% of |\verbatim@readfile|. +% \changes{v1.5t}{2020-07-06}{Expand \cs{@filef@und} before the call +% of \cs{@verbatim} (gh/222)}m % \begin{macrocode} \def\verbatim@input#1#2{% - \IfFileExists {#2}{\@verbatim #1\relax + \IfFileExists {#2}{% + \expandafter\@swaptwoargs\expandafter + {\expandafter{\@filef@und}}% + {\@verbatim #1\relax % \end{macrocode} % Then it reads in the file, finishes off the \texttt{trivlist} % environment started by |\@verbatim| and closes the group. % This restores everything to its normal settings. % \begin{macrocode} - \verbatim@readfile{\@filef@und}\endtrivlist\endgroup\@doendpe}% + \verbatim@readfile}% + \endtrivlist\endgroup\@doendpe}% % \end{macrocode} -% If the file is not found a more or less helpful message is +% If the file is not found a more or less helpful message is % printed. The final |\endgroup| is needed to close the group % started in |\verbatiminput| above. % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/tools/xr.dtx b/Master/texmf-dist/source/latex/tools/xr.dtx index a6b2ffd8193..a963886cde7 100644 --- a/Master/texmf-dist/source/latex/tools/xr.dtx +++ b/Master/texmf-dist/source/latex/tools/xr.dtx @@ -25,7 +25,7 @@ % %<package>\NeedsTeXFormat{LaTeX2e} %<package>\ProvidesPackage{xr} -%<package> [2019/07/22 v5.05 eXternal References (DPC)] +%<package> [2020-05-10 v5.06 eXternal References (DPC)] % %<*driver> \documentclass{ltxdoc} @@ -103,12 +103,15 @@ \let\externalcitedocument\externaldocument % \end{macrocode} % -% Save the optional prefix. Start processing the first |aux| file. +% Save the optional prefix. Start processing the first |aux| file. +% \changes{v5.06}{2020-05-10}{Remove leading and trailing sapces from +% the filename (gh/2223)} % \begin{macrocode} \def\XR@[#1]#2{{% \makeatletter \def\XR@prefix{#1}% - \XR@next#2.aux\relax\\}} + \set@curr@file{#2}% + \expandafter\XR@next\@curr@file.aux\relax\\}} % \end{macrocode} % % Process the next |aux| file in the list and remove it from the head of @@ -135,8 +138,10 @@ % If the |aux| file exists, loop through line by line, looking for % |\newlabel| and |\@input|. Otherwise process the next file in the % list. +% \changes{v5.06}{2020-05-10}{Add braces around the filename to +% support filenames with spaces (gh/223)} % \begin{macrocode} -\def\XR@loop#1{\openin\@inputcheck#1\relax +\def\XR@loop#1{\openin\@inputcheck{#1}\relax \ifeof\@inputcheck \PackageWarning{xr}{^^JNo file #1^^JLABELS NOT IMPORTED.^^J}% \expandafter\XR@aux |