diff options
author | Norbert Preining <norbert@preining.info> | 2023-06-10 03:04:15 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-06-10 03:04:15 +0000 |
commit | 779e1e8aae671dfb73e0c5a19791be243af01cbe (patch) | |
tree | a9dba6085be5122eec4a3659d01dd33a5b1c774b /macros | |
parent | 33607c11aca40cfb1f454d818091f19aa47ba651 (diff) |
CTAN sync 202306100304
Diffstat (limited to 'macros')
412 files changed, 23507 insertions, 2617 deletions
diff --git a/macros/latex/base/README.md b/macros/latex/base/README.md index eb19004b01..bccadab2d9 100644 --- a/macros/latex/base/README.md +++ b/macros/latex/base/README.md @@ -1,7 +1,7 @@ The LaTeX kernel ================ -Release 2022-11-01 patch level 1 +Release 2023-06-01 Overview -------- diff --git a/macros/latex/base/alltt.dtx b/macros/latex/base/alltt.dtx index 908fe92400..548b91bcea 100644 --- a/macros/latex/base/alltt.dtx +++ b/macros/latex/base/alltt.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/alltt.ins b/macros/latex/base/alltt.ins index f46404bcf4..3f40ddc0f0 100644 --- a/macros/latex/base/alltt.ins +++ b/macros/latex/base/alltt.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/alltt.pdf b/macros/latex/base/alltt.pdf Binary files differindex f2614d73e0..e01f937daa 100644 --- a/macros/latex/base/alltt.pdf +++ b/macros/latex/base/alltt.pdf diff --git a/macros/latex/base/cfgguide.pdf b/macros/latex/base/cfgguide.pdf Binary files differindex 724ae8aebe..4a9e45c7e4 100644 --- a/macros/latex/base/cfgguide.pdf +++ b/macros/latex/base/cfgguide.pdf diff --git a/macros/latex/base/cfgguide.tex b/macros/latex/base/cfgguide.tex index 53f53d90b4..e0f76b74fb 100644 --- a/macros/latex/base/cfgguide.tex +++ b/macros/latex/base/cfgguide.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -41,7 +41,7 @@ \author{\copyright~Copyright 1998, 2001, 2003 \LaTeX\ Project Team.\\ All rights reserved.% - \footnote{This file may distributed and/or modified under the + \footnote{This file 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. See the source \texttt{cfgguide.tex} for full details.}% diff --git a/macros/latex/base/changes.txt b/macros/latex/base/changes.txt index fed7e96be3..a8eabd5dd1 100644 --- a/macros/latex/base/changes.txt +++ b/macros/latex/base/changes.txt @@ -11,6 +11,231 @@ All changes above are only part of the development branch for the next release. ================================================================================ ######################### +# 2023-06-01 Release +######################### + +2023-05-21 Phelype Oleinik <phelype.oleinik@latex-project.org> + + * lthooks.dtx (subsection{Adding or removing hook code}): + Short-circuit when the hook is declared without args (gh1078). + +2023-05-31 Joseph Wright <Joseph.Wright@latex-project.org> + + * usrguide.text + Correct syntax of opt. arg. for \DeclareLowercaseMapping, etc. + +2023-05-30 Joseph Wright <Joseph.Wright@latex-project.org> + + * ltfinal.dtx + Fix implementation of \DeclareLowercaseMapping + +2023-05-26 Yukai Chou <muzimuzhi@gmail.com> + + * ltcmd.dtx (subsection{Structure of \pkg{xparse} commands}): + Use simpler 'NNno' variant instead of 'NNVo' for + \cs_generate_from_arg_count:NNnn + +2023-05-22 Joseph Wright <Joseph.Wright@latex-project.org> + + * usrguide.tex + Ensure url package is always loaded + +2023-05-21 Phelype Oleinik <phelype.oleinik@latex-project.org> + + * lthooks.dtx, ltcmdhooks.dtx: + Add support for accessing arguments in 'cmd' hooks. + +2023-05-19 Joseph Wright <Joseph.Wright@latex-project.org> + + * usrguide.tex (section Creating document commands and environments) + Add details of result of trailing optional arguments on + \inputlineno + +2023-05-12 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * ltxref.dtx + extend \label to store five values and add a hook with argument + +2023-05-17 Joseph Wright <Joseph.Wright@latex-project.org> + + * usrguide.tex (section Creating document commands and environments) + Add details of brace stripping by \SplitList + Add guidance on creating commands to use at start of + tabular cells + +2023-05-15 Joseph Wright <Joseph.Wright@latex-project.org> + + * ltfiles.dtx: + Use expl3-based file-existence test + +2023-05-13 David Carlisle <David.Carlisle@latex-project.org> + + * ltmath.dtx: Add \ignorespaces to \eqno (gh/1059) + +2023-04-19 Joseph Wright <joseph.wright@latex-project.org> + + * ltfinal.dtx (subsection{Lccodes and uccodes}): + Add \DeclareLowercaseMapping, \DeclareTitlecaseMapping and + \DeclareUppercaseMapping (gh/1033) + +2023-04-19 Phelype Oleinik <phelype.oleinik@latex-project.org> + + * lthooks.dtx (subsection{Specifying code for next invocation}): + Initialise hook structure when adding 'next' code (gh/1052) + +2023-04-17 Joseph Wright <Joseph.Wright@latex-project.org> + + * ltfinal.dtx (subsubsection{Lccodes and uccodes}): + Add \BCPdata (gh/1035) + Adapt \MakeLowercase, \MakeTitlecase and \MakeLowercase + to use \BCPdata for locale info + +2023-04-16 Phelype Oleinik <phelype.oleinik@latex-project.org> + + * lthooks.dtx (subsubsection{Setting hooks up}): + Use \@@_replacing_args_false: in \@@_include_legacy_code_chunk:n. + +2023-04-15 David Carlisle <David.Carlisle@latex-project.org> + + * ltplain.dtx: adjust \extrafloats so it does not error if thousands + of float boxes are allocated. github/1041 + +2023-04-14 Phelype Oleinik <phelype.oleinik@latex-project.org> + + * ltclass.dtx (\@onefilewithoptions): + When in latexrelease.sty, define \load@onefilewithoptions (gh/992). + +2023-04-13 David Carlisle <David.Carlisle@latex-project.org> + + * cmfonts.fdd: add missing substitution for U/cmtt/bx/sl gh/1037 + +2023-04-12 Phelype Oleinik <phelype.oleinik@latex-project.org> + + * ltcmd.dtx (subsection{Grabbing arguments}): + Set \tex_endlinechar:D earlier to correct parsing of newlines in + special catcode settings (e.g., \ExplSyntaxOn) (gh/876). + +2023-04-02 David Carlisle <David.Carlisle@latex-project.org> + + * ltfilehook.dtx: allow par as a filename. (gh/942) + +2023-04-06 Phelype Oleinik <phelype.oleinik@latex-project.org> + + * lthooks.dtx, ltcmdhooks.dtx: + Add support for providing and using arguments in hooks: + - Modify hook data structures to allow access to arguments; + - Add commands to declare hooks with arguments; + - Add commands to add code that references hook arguments; + - Add commands to use hooks with arguments. + +2023-04-01 David Carlisle <David.Carlisle@latex-project.org> + + * ltfssbas.dtx: locally reset frozen mathversions when the math + version changes. (gh/1028) + +2023-03-28 Joseph Wright <Joseph.Wright@latex-project.org> + + * ltclass.dtx: + Add \IfFileAtLeastTF (gh/1015) + +2023-03-28 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * ltxdoc.dtx (section{Options}): + Define \cs if doc is rolled back to v2 (gh/981) + +2023-03-28 David Carlisle <David.Carlisle@latex-project.org> + + * ltfinal.dtx: Restore groups to \MakeUppercase and + \MakeLowercase, and add a group to \MakeTitlecase. (gh/1021) + +2023-03-22 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * ltspace.dtx: + Add \predisplaypenalty setting of 10000 to \samepage in case + that was changed (gh/1022) + +2023-03-11 Yukai Chou <muzimuzhi@gmail.com> + + * ltcmd.dtx (subsubsection{Showing the definition of a command}), + (subsubsection{Copying a command and its internal structure}): + Correctly recognize (non-expandable) document commands with empty or only + m-type arguments (gh/1009) + +2023-01-30 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * ltpara.dtx (subsection{Providing hooks for paragraphs}): + Backout \parskip at top of minipage if it shouldn't be there + but is due to whatsits (gh/989) + +2023-02-05 Yukai Chou <muzimuzhi@gmail.com> + + * fntguide.tex: + Adjusted pagination due to recently added doc paragraphs (gh/994) + +2023-01-16 Yukai Chou <muzimuzhi@gmail.com> + + * ltnews.cls: + Added full release date yyyy-mm-dd to _all_ ltnews issues (gh/982) + Added \publicationday{<day>} to specify day in a month in ltnews<n>.tex. + <day> defaults to 01. + +2023-01-12 Joseph Joseph <Joseph.Joseph@latex-project.org> + + * clsguide.tex, clsguide-historic,tex + Pre-2023 source moved to new name, re-worked material which remains + relevant in updated file + +2023-01-19 Josef Friedrich <josef@friedrich.rocks> + + * ltluatex.dtx: + Remove unused local variable tex_setattribute (gh/978) + +2022-11-24 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * ltdefns.dtx (subsubsection{Copying robust commands}): + Added \NewEnvironmentCopy, \RenewEnvironmentCopy, and \DeclareEnvironmentCopy (gh/963) + Also added \ShowEnvironment. + +2022-11-16 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * ltclass.dtx: + Introduce key 'nowarn' on filecontents (gh/958) + Do not show "current dir" in message (gh/917) + +2022-11-14 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * latexrelease.dtx (subsection{Ignoring \texttt{\string_new} errors when rolling back}): + Silence \cs{NewMarkClass} in rollback (gh/955) + +2022-11-13 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * doc.dtx: + Redefinitions of \verb removed as no longer needed (gh/953) + + Redefinitions of \@verbatim changed to match the kernel + definition (gh/953) + +2022-11-08 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * ltshipout.dtx: + Add a shipout hook to be executed just before we + actually do the shipout (gh/920) + +2022-11-07 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * ltvers.dtx (section{Version Identification}): + Store release data in \LaTeXReleaseInfo for reuse at the end of + the .log file (gh/944) + + * ltmiscen.dtx (subsection{Environments}): Add to a hook in + \end{document} to (re)display the LaTeX release information (gh/944) + +2022-11-03 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * doc.dtx: correctly handle \<space> and allow it to be excluded + from the index (gh/943) + +######################### # 2022-11-01 PL1 Release ######################### @@ -145,7 +370,7 @@ All changes above are only part of the development branch for the next release. * doc.dtx recast Package Option declarations using \DeclareKeys - + 2022-06-10 Ulrike Fischer <Ulrike.Fischer@latex-project.org> * cmfonts.fdd diff --git a/macros/latex/base/classes.dtx b/macros/latex/base/classes.dtx index 188679d4d9..58690e8375 100644 --- a/macros/latex/base/classes.dtx +++ b/macros/latex/base/classes.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -53,7 +53,7 @@ %<*driver> \ProvidesFile{classes.drv} %</driver> - [2022/07/02 v1.4n + [2023/05/17 v1.4n %<article|report|book> Standard LaTeX document class] %<10pt|11pt|12pt> Standard LaTeX file (size option)] % \end{macrocode} @@ -3688,9 +3688,8 @@ % % A |\caption| command in a `figure' environment writes % -% |\contentsline{figure}{\numberline{|\meta{num}|}{|% +% |\contentsline{figure}{\numberline{|\meta{num}|}{|^^A % \meta{caption}|}}{|\meta{page}|}| -% % on the .\file{lof} file, where \meta{num} is the number produced % by |\thefigure| and \meta{caption} is the figure caption. It % works similarly for a `table' environment. @@ -3707,8 +3706,8 @@ % \meta{title}|}{|\meta{page}|}| % % \begin{description} -% \item[\meta{level}] An entry is produced only if\meta{ level} -% $<=$ value of the \Lcount{tocdepth} counter. Note, +% \item[\meta{level}] An entry is produced only if \meta{level} +% $\leq$ value of the \Lcount{tocdepth} counter. Note, % |\chapter| is level 0, |\section| is level 1, etc. % \item[\meta{indent}] The indentation from the outer left margin % of the start of the contents line. diff --git a/macros/latex/base/classes.ins b/macros/latex/base/classes.ins index 1f7b331691..50a51ea666 100644 --- a/macros/latex/base/classes.ins +++ b/macros/latex/base/classes.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/classes.pdf b/macros/latex/base/classes.pdf Binary files differindex a8296800a3..5ce9be9aa0 100644 --- a/macros/latex/base/classes.pdf +++ b/macros/latex/base/classes.pdf diff --git a/macros/latex/base/clsguide-historic.pdf b/macros/latex/base/clsguide-historic.pdf Binary files differnew file mode 100644 index 0000000000..bc95e39dff --- /dev/null +++ b/macros/latex/base/clsguide-historic.pdf diff --git a/macros/latex/base/clsguide-historic.tex b/macros/latex/base/clsguide-historic.tex new file mode 100644 index 0000000000..d7a27e3c40 --- /dev/null +++ b/macros/latex/base/clsguide-historic.tex @@ -0,0 +1,1881 @@ +% \iffalse meta-comment +% +% Copyright (C) 1993-2023 +% The LaTeX Project and any individual authors listed elsewhere +% in this file. +% +% This file is part of the LaTeX base system. +% ------------------------------------------- +% +% It may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3c +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3c or later is part of all distributions of LaTeX +% version 2008 or later. +% +% This file has the LPPL maintenance status "maintained". +% +% The list of all files belonging to the LaTeX base distribution is +% given in the file `manifest.txt'. See also `legal.txt' for additional +% information. +% +% The list of derived (unpacked) files belonging to the distribution +% and covered by LPPL is defined by the unpacking scripts (with +% extension .ins) which are part of the distribution. +% +% \fi +% Filename: clsguide-historic.tex + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] + +\documentclass{ltxguide}[1995/11/28] + +\title{\LaTeXe~for class and package writers --- historic version} + +\author{Copyright \copyright~1995--2006 The \LaTeX\ Project\\ + All rights reserved.% + \footnote{This file 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. See the source + \texttt{clsguide.tex} for full details.}% +} + +\date{11 January 2023} + +\begin{document} + +\maketitle + +\tableofcontents + +\section{Introduction} + +This document is an introduction to writing classes and packages for +\LaTeX{}, with special attention given to upgrading existing +\LaTeX~2.09 packages to \LaTeXe{}. The latter subject is also +covered in an article by Johannes Braams published in TUGboat~15.3. + +It is somewhat of an historical document now, since \LaTeXe{} came into +existence in 1994. + +\subsection{Writing classes and packages for \LaTeXe} + +\LaTeX{} is a document preparation system that enables the document +writer to concentrate on the contents of their text, without bothering +too much about the formatting of it. For example, chapters are +indicated by |\chapter{<title>}| rather than by selecting 18pt bold. + +The file that contains the information about how to turn logical +structure (like `|\chapter|') into formatting (like `18pt bold ragged +right') is a \emph{document class}. In addition, some features (such +as colour or included graphics) are independent of the document class +and these are contained in \emph{packages}. + +One of the largest differences between \LaTeX~2.09 and \LaTeXe{} is in +the commands used to write packages and classes. In \LaTeX~2.09, +there was very little support for writing |.sty| files, and so writers +had to resort to using low-level commands. + +\LaTeXe{} provides high-level commands for structuring packages. +It is also much easier to build classes and packages on top of each +other, for example writing a local technical report class |cetechr| +(for the Chemical Engineering department) based on |article|. + +\subsection{Overview} + +This document contains an overview of how to write classes and +packages for \LaTeX{}. It does \emph{not} introduce all of the +commands necessary to write packages: these can be found in either +\emph{\LaTeXbook} or \emph{\LaTeXcomp}. But it does describe the new +commands for structuring classes and packages. + +\begin{description} + +\item[Section~\ref{Sec:general}] contains some general advice about + writing classes and packages. It describes the difference between + classes and packages, the command naming conventions, the use of + |doc| and |docstrip|, how \TeX's primitive file and box commands + interact with \LaTeX{}. It also contains some hints about general + \LaTeX{} style. + +\item[Section~\ref{Sec:structure}] describes the structure of classes + and packages. This includes building classes and packages on top of + other classes and packages, declaring options and declaring + commands. It also contains example classes. + +\item[Section~\ref{Sec:commands}] lists the new class and package + commands. + + \item[Section~\ref{Sec:upgrade}] gives detailed advice on how to + upgrade existing \LaTeX~2.09 classes and packages to \LaTeXe{}. + +\end{description} + +\subsection{Further information} + +For a general introduction to \LaTeX{}, including the new features of +\LaTeXe{}, you should read \emph{\LaTeXbook} +by Leslie Lamport~\cite{A-W:LLa94}. + +A more detailed description of the new features of \LaTeX, including an +overview of more than 200 packages and nearly 1000 ready to run examples, is +to be found in \emph{\LaTeXcomp\ second edition} by Frank Mittelbach and +Michel Goossens~\cite{A-W:MG2004}. + +The \LaTeX{} system is based on \TeX{}, which is +described in \emph{The \TeX book} by Donald E.~Knuth~\cite{A-W:DEK91}. + +There are a number of documentation files which accompany every copy +of \LaTeX{}. A copy of \emph{\LaTeX{} News} will come out with each +six-monthly release of \LaTeX{}, and is found in the files +|ltnews*.tex|. The author's guide \emph{\usrguide} describes the new +\LaTeX{} document features; it is in |usrguide.tex|. The guide +\emph{\fntguide} describes the \LaTeX{} font selection scheme for +class- and package-writers; it is in |fntguide.tex|. Configuring +\LaTeX{} is covered by the guide \emph{\cfgguide} in +\texttt{cfgguide.tex} whilst the philosophy behind our policy on +modifying \LaTeX{} is described in \emph{\modguide} in +\texttt{modguide.tex}. + +The documented source code (from the files used to produce the kernel +format via |latex.ltx|) is now available as +\emph{The \LaTeXe\ Sources}. +This very large document also includes an index of +\LaTeX{} commands. It can be typeset from the \LaTeX{} file +|source2e.tex| in the |base| directory, using the source files and +the class file |ltxdoc.cls| from this directory. + +For more information about \TeX{} and \LaTeX{}, please contact your +local \TeX{} Users Group, or the international \TeX{} Users Group. +Addresses and other details can be found at: +\begin{quote}\small\label{addrs} + \texttt{http://www.tug.org/lugs.html} +\end{quote} + + +\subsection{Policy on standard classes} + +Many of the problem reports we receive concerning the standard classes +are not concerned with bugs but are suggesting, more or less politely, +that the design decisions embodied in them are `not optimal' and +asking us to modify them. + +There are several reasons why we should not make such changes to these +files. +\begin{itemize} +\item + However misguided, the current behaviour is clearly what was + intended when these classes were designed. +\item + It is not good practice to change such aspects of `standard classes' + because many people will be relying on them. +\end{itemize} + +We have therefore decided not to even consider making such +modifications, nor to spend time justifying that decision. This does +not mean that we do not agree that there are many deficiencies in the +design of these classes, but we have many tasks with higher priority +than continually explaining why the standard classes for \LaTeX{} +cannot be changed. + +We would, of course, welcome the production of better classes, or of +packages that can be used to enhance these classes. So your first +thought when you consider such a deficiency will, we hope, be ``what +can I do to improve this?'' + +Similar considerations apply to those parts of the kernel that are +implementing design decisions, many of which should be left to the +class file but are not in the current system. We realise that in such +cases it is much more difficult for you to rectify the problem +yourself but it is also the case that making such changes in the +kernel would probably be a major project for us; therefore such +enhancements will have to wait for \LaTeX3. + +\section{Writing classes and packages} +\label{Sec:writing} + +This section covers some general points concerned with writing +\LaTeX{} classes and packages. + + +\subsection{Old versions} + +If you are upgrading an existing \LaTeX~2.09 style file then we +recommend freezing the 2.09 version and no longer maintaining it. +Experience with the various dialects of \LaTeX{} which existed in the +early 1990's suggests that maintaining packages for different versions +of \LaTeX{} is almost impossible. It will, of course, be necessary +for some organisations to maintain both versions in parallel for some +time but this is not essential for those packages and classes +supported by individuals: they should support only the new standard +\LaTeXe{}, not obsolete versions of \LaTeX{}. + + +\subsection{Using `docstrip' and `doc'} + +If you are going to write a large class or package for \LaTeX{} then +you should consider using the |doc| software which comes with +\LaTeX{}. +\LaTeX{} classes and packages written using this can be +processed in two ways: they can be run through \LaTeX{}, to produce +documentation; and they can be processed with |docstrip|, to produce +the |.cls| or |.sty| file. + +The |doc| software can automatically generate indexes of definitions, +indexes of command use, and change-log lists. It is very useful for +maintaining and documenting large \TeX{} sources. + +The documented sources of the \LaTeX{} kernel itself, and of the +standard classes, etc, are |doc| documents; they are in the |.dtx| +files in the distribution. You can, in fact, typeset the source code +of the kernel as one long document, complete with index, by running +\LaTeX{} on |source2e.tex|. Typesetting these documents uses the +class file |ltxdoc.cls|. + +For more information on |doc| and |docstrip|, consult the files +|docstrip.dtx|, |doc.dtx|, and \emph{\LaTeXcomp}. For examples of its +use, look at the |.dtx| files. + +\subsection{Is it a class or a package?} +\label{Sec:classorpkg} + +The first thing to do when you want to put some new \LaTeX{} commands +in a file is to decide whether it should be a \emph{document class} or a +\emph{package}. The rule of thumb is: +\begin{quote} + If the commands could be used with any document class, then make + them a package; and if not, then make them a class. +\end{quote} + +There are two major types of class: those like |article|, |report| or +|letter|, which are free-standing; and those which are extensions or +variations of other classes---for example, the |proc| document class, +which is built on the |article| document class. + +Thus, a company might have a local |ownlet| class for printing letters +with their own headed note-paper. Such a class would build on top of +the existing |letter| class but it cannot be used with any other +document class, so we have |ownlet.cls| rather than |ownlet.sty|. + +The |graphics| package, in contrast, provides commands for including +images into a \LaTeX{} document. Since these commands can be used +with any document class, we have |graphics.sty| rather than +|graphics.cls|. + + +\subsection{Command names} + +\LaTeX{} has three types of command. + +There are the author commands, such as |\section|, |\emph| and +|\times|: most of these have short names, all in lower case. + +There are also the class and package writer commands: +most of these have long mixed-case names such as the following. +\begin{verbatim} + \InputIfFileExists \RequirePackage \PassOptionsToClass +\end{verbatim} + +Finally, there are the internal commands used in the \LaTeX{} +implementation, such as |\@tempcnta|, |\@ifnextchar| and |\@eha|: +most of these commands contain |@| in their name, which means they +cannot be used in documents, only in class and package files. + +Unfortunately, for historical reasons the distinction between these +commands is often blurred. For example, |\hbox| is an internal +command which should only be used in the \LaTeX{} kernel, whereas +|\m@ne| is the constant $-1$ and could have been |\MinusOne|. + +However, this rule of thumb is still useful: if a command has |@| in +its name then it is not part of the supported \LaTeX{} language---and +its behaviour may change in future releases! If a command is +mixed-case, or is described in \emph{\LaTeXbook}, then you can rely on +future releases of \LaTeXe{} supporting the command. + +\subsection{Box commands and colour} +\label{Sec:colour} + +Even if you do not intend to use colour in your own documents, by +taking note of the points in this section you can ensure that your +class or package is compatible with the |color| package. This may +benefit people using your class or package who have access to colour +printers. + +The simplest way to ensure `colour safety' is to always use \LaTeX{} +box commands rather than \TeX{} primitives, that is use |\sbox| rather +than |\setbox|, |\mbox| rather than |\hbox| and |\parbox| or +the |minipage| environment rather than |\vbox|. +The \LaTeX{} box commands have new options which mean that they are now +as powerful as the \TeX{} primitives. + +As an example of what can go wrong, consider that in +|{\ttfamily <text>}| +the font is restored just \emph{before} the |}|, whereas in the +similar looking construction +|{\color{green} <text>}| +the colour is restored just \emph{after} the final |}|. Normally this +distinction does not matter at all; but consider a primitive \TeX{} +box assignment such as: +\begin{verbatim} + \setbox0=\hbox{\color{green} <text>} +\end{verbatim} +Now the colour-restore occurs after the |}| and so is \emph{not} +stored in the box. Exactly what bad effects this can have depends on +how colour is implemented: it can range from getting the wrong +colours in the rest of the document, to causing errors in the +dvi-driver used to print the document. + +Also of interest is the command |\normalcolor|. This is +normally just |\relax| (i.e., does nothing) +but you can use it rather like |\normalfont| to +set regions of the page such as captions or section headings to the +`main document colour'. + + +\subsection{Defining text and math characters} +\label{Sec:chars} + +Because \LaTeXe{} supports different encodings, definitions of commands +for producing symbols, accents, composite glyphs, etc.\ must be +defined using the commands provided for this purpose and described in +\emph{\fntguide}. This part of the system is still under development +so such tasks should be undertaken with great caution. + +Also, |\DeclareRobustCommand| should be used for encoding-independent +commands of this type. + +Note that it is no longer possible to refer to the math font set-up +outside math mode: for example, neither |\textfont 1| nor +|\scriptfont 2| are guaranteed to be defined in other modes. + + +\subsection{General style} +\label{Sec:general} + +The new system provides many commands designed to help you produce +well-structured class and package files that are both robust and +portable. This section outlines some ways to make intelligent use of +these. + +\subsubsection{Loading other files} +\label{Sec:loading} + +\NEWdescription{1995/12/01} +\LaTeX{} provides these commands: +\begin{verbatim} + \LoadClass \LoadClassWithOptions + \RequirePackage \RequirePackageWithOptions +\end{verbatim} +for using classes or packages inside other classes or packages. We +recommend strongly that you use them, rather than the primitive +|\input| command, for a number of reasons. + +Files loaded with |\input <filename>| will not be listed in the +|\listfiles| list. + +If a package is always loaded with |\RequirePackage...| or |\usepackage| +then, even if its loading is requested several times, it will be +loaded only once. By contrast, if it is loaded with |\input| then it +can be loaded more than once; such an extra loading may waste time and +memory and it may produce strange results. + +If a package provides option-processing then, again, strange results +are possible if the package is |\input| rather than loaded by means of +|\usepackage| or |\RequirePackage...|. + +If the package |foo.sty| loads the package |baz.sty| by use of +|\input baz.sty| then the user will get a warning: +\begin{verbatim} + LaTeX Warning: You have requested package `foo', + but the package provides `baz'. +\end{verbatim} +Thus, for several reasons, using |\input| to load packages is not a +good idea. + +Unfortunately, if you are upgrading the file |myclass.sty| to a class +file then you have to make sure that any old files which contain +|\input myclass.sty| still work. + +This was also true for the standard classes (|article|, |book| and +|report|), since a lot of existing \LaTeX~2.09 document styles contain +|\input article.sty|. The approach which we use to solve this is +to provide minimal files |article.sty|, |book.sty| and |report.sty|, +which simply load the appropriate class files. + +For example, |article.sty| contains just the following lines: +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e} + \@obsoletefile{article.cls}{article.sty} + \LoadClass{article} +\end{verbatim} +You may wish to do the same or, if you think that it is safe to do so, +you may decide to just remove |myclass.sty|. + +\subsubsection{Make it robust} + +We consider it good practice, when writing packages and classes, to use +\LaTeX{} commands as much as possible. + +Thus, instead of using |\def...| we recommend using one of +|\newcommand|, |\renewcommand| or |\providecommand|; |\CheckCommand| is +also useful. Doing this makes +it less likely that you will inadvertently redefine a command, giving +unexpected results. + +When you define an environment, use |\newenvironment| or +|\renewenvironment| instead |\def\foo{...}| and |\def\endfoo{...}|. + +If you need to set or change the value of a \m{dimen} or \m{skip} +register, use |\setlength|. + +To manipulate boxes, use \LaTeX{} commands such as |\sbox|, +|\mbox| and |\parbox| rather than |\setbox|, |\hbox| and |\vbox|. + +Use |\PackageError|, |\PackageWarning| or |\PackageInfo| (or the +equivalent class commands) rather than |\@latexerr|, |\@warning| or +|\wlog|. + +It is still possible to declare options by defining |\ds@<option>| and +calling |\@options|; but we recommend the |\DeclareOption| and +|\ProcessOptions| commands instead. These are more powerful and use +less memory. So rather than using: +\begin{verbatim} + \def\ds@draft{\overfullrule 5pt} + \@options +\end{verbatim} +you should use: +\begin{verbatim} + \DeclareOption{draft}{\setlength{\overfullrule}{5pt}} + \ProcessOptions\relax +\end{verbatim} + +The advantage of this kind of practice is that your code is more +readable and, more important, that it is less likely to break when +used with future versions of \LaTeX{}. + +\subsubsection{Make it portable} + +It is also sensible to make your files are as portable as possible. To +ensure this; they should contain only visible 7-bit text; and the +filenames should contain at most eight characters (plus the three +letter extension). Also, of course, it \textbf{must not} have the +same name as a file in the standard \LaTeX{} distribution, however +similar its contents may be to one of these files. + +It is also useful if local classes or packages have a common prefix, +for example the University of Nowhere classes might begin with |unw|. +This helps to avoid every University having its own thesis class, all +called |thesis.cls|. + +If you rely on some features of the \LaTeX{} kernel, or on a package, +please specify the release-date you need. For example, the package +error commands were introduced in the June 1994 release so, if you use +them then you should put: +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e}[1994/06/01] +\end{verbatim} + +\subsubsection{Useful hooks} + +Some packages and document styles had to redefine the command +|\document| or |\enddocument| to achieve their goal. This is no +longer necessary. You can now use the `hooks' |\AtBeginDocument| and +|\AtEndDocument| (see Section~\ref{Sec:delays}). Again, using these +hooks makes it less likely that your code breaks with future versions +of \LaTeX{}. It also makes it more likely that your package can work +together with someone else's. + +\NEWdescription{1996/12/01} +However, note that code in the |\AtBeginDocument| hook is part of the +preamble. Thus there are restrictions on what can be put there; in +particular, no typesetting can be done. + +\section{The structure of a class or package} +\label{Sec:structure} + +\LaTeXe{} classes and packages have more structure than \LaTeX~2.09 +style files did. The outline of a class or package file is: +\begin{description} +\item[Identification] The file says that it is a \LaTeXe{} package or + class, and gives a short description of itself. +\item[Preliminary declarations] + Here the file declares some commands and can also load + other files. Usually these commands will be just those needed for + the code used in the declared options. +\item[Options] The file declares and processes its options. +\item[More declarations] This is where the file does most of its work: + declaring new variables, commands and fonts; and loading other files. +\end{description} + +\subsection{Identification} + +The first thing a class or package file does is identify itself. +Package files do this as follows: +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e} + \ProvidesPackage{<package>}[<date> <other information>] +\end{verbatim} +For example: +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e} + \ProvidesPackage{latexsym}[1994/06/01 Standard LaTeX package] +\end{verbatim} +Class files do this as follows: +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e} + \ProvidesClass{<class-name>}[<date> <other information>] +\end{verbatim} +For example: +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e} + \ProvidesClass{article}[1994/06/01 Standard LaTeX class] +\end{verbatim} +\NEWdescription{1998/06/19} +The \m{date} should be given in the form `\textsc{yyyy/mm/dd}' and +must be present if the optional argument is used (this is also true +for the |\NeedsTeXFormat| command). +Any derivation from this syntax will result in low-level \TeX{} +errors---the commands expect a valid syntax to speed up the daily +usage of the package or class and make no provision for the case that +the developer made a mistake! + +This date is checked whenever a user specifies a date in their +|\documentclass| or |\usepackage| command. For example, if you wrote: +\begin{verbatim} + \documentclass{article}[1995/12/23] +\end{verbatim} +then users at a different location +would get a warning that their copy of |article| was out of +date. + +The description of a class is displayed when the class is used. The +description of a package is put into the log file. These descriptions +are also displayed by the |\listfiles| command. The phrase +\texttt{Standard LaTeX} \textbf{must not} be used in the identification +banner of any file other than those in the standard \LaTeX{} +distribution. + + +\subsection{Using classes and packages} + +The first major difference between \LaTeX~2.09 style files and +\LaTeXe{} packages and classes is that \LaTeXe{} supports +\emph{modularity}, in the sense of building files from small +building-blocks rather than using large single files. + +A \LaTeX{} package or class can load a package as follows: +\begin{verbatim} + \RequirePackage[<options>]{<package>}[<date>] +\end{verbatim} +For example: +\begin{verbatim} + \RequirePackage{ifthen}[1994/06/01] +\end{verbatim} +This command has the same syntax as the author command |\usepackage|. +It allows packages or classes to use features provided by other +packages. For example, by loading the |ifthen| package, a package +writer can use the `if\dots then\dots else\dots' commands provided +by that package. + +A \LaTeX{} class can load one other class as follows: +\begin{verbatim} + \LoadClass[<options>]{<class-name>}[<date>] +\end{verbatim} +For example: +\begin{verbatim} + \LoadClass[twocolumn]{article} +\end{verbatim} +This command has the same syntax as the author command |\documentclass|. +It allows classes to be based on the syntax and appearance of another +class. For example, by loading the |article| class, a class writer +only has to change the bits of |article| they don't like, rather than +writing a new class from scratch. + +\NEWfeature{1995/12/01} +The following commands can be used in the common case that you want to +simply load a class or package file with exactly those options that +are being used by the current class. +\begin{verbatim} + \LoadClassWithOptions{<class-name>}[<date>] + \RequirePackageWithOptions{<package>}[<date>] +\end{verbatim} +For example: +\begin{verbatim} + \LoadClassWithOptions{article} + \RequirePackageWithOptions{graphics}[1995/12/01] +\end{verbatim} + +\subsection{Declaring options} + +\NEWdescription{1998/12/01} +The other major difference between \LaTeX~2.09 styles and \LaTeXe{} +packages and classes is in option handling. Packages and classes can +now declare options and these can be specified by authors; for +example, the |twocolumn| option is declared by the |article| class. +Note that the name of an option should contain only those characters +allowed in a `\LaTeX{} name'; in particular it must not contain any +control sequences. + +An option is declared as follows: +\begin{verbatim} + \DeclareOption{<option>}{<code>} +\end{verbatim} +For example, the |dvips| option (slightly simplified) +to the |graphics| package is implemented as: +\begin{verbatim} + \DeclareOption{dvips}{\input{dvips.def}} +\end{verbatim} +This means that when an author writes |\usepackage[dvips]{graphics}|, +the file |dvips.def| is loaded. As another example, the |a4paper| +option is declared in the |article| class to set the |\paperheight| +and |\paperwidth| lengths: +\begin{verbatim} + \DeclareOption{a4paper}{% + \setlength{\paperheight}{297mm}% + \setlength{\paperwidth}{210mm}% + } +\end{verbatim} +Sometimes a user will request an option which the class +or package has not explicitly declared. By default this will produce +a warning (for classes) or error (for packages); this behaviour +can be altered as follows: +\begin{verbatim} + \DeclareOption*{<code>} +\end{verbatim} +For example, to make the package |fred| produce a warning rather than +an error for unknown options, you could specify: +\begin{verbatim} + \DeclareOption*{% + \PackageWarning{fred}{Unknown option `\CurrentOption'}% + } +\end{verbatim} +Then, if an author writes |\usepackage[foo]{fred}|, they will get a +warning \texttt{Package fred Warning: Unknown option `foo'.} As +another example, the |fontenc| package tries to load a file +|<ENC>enc.def| whenever the \m{ENC} option is used. This +can be done by writing: +\begin{verbatim} + \DeclareOption*{% + \input{\CurrentOption enc.def}% + } +\end{verbatim} +\NEWdescription{1998/12/01} +It is possible to pass options on to another package or class, using +the command |\PassOptionsToPackage| or |\PassOptionsToClass| (note +that this is a specialised operation that works only for option +names). For example, to pass every unknown option on to the |article| +class, you can use: +\begin{verbatim} + \DeclareOption*{% + \PassOptionsToClass{\CurrentOption}{article}% + } +\end{verbatim} +If you do this then you should make sure you load the class at some +later point, otherwise the options will never be processed! + +So far, we have explained only how to declare options, not how to +execute them. To process the options with which the file was called, +you should use: +\begin{verbatim} + \ProcessOptions\relax +\end{verbatim} +This executes the \m{code} for each option that was both specified and +declared (see Section~\ref{Sec:commands.options} for details of how +this is done). + +For example, if the |jane| package file contains: +\begin{verbatim} + \DeclareOption{foo}{\typeout{Saw foo.}} + \DeclareOption{baz}{\typeout{Saw baz.}} + \DeclareOption*{\typeout{What's \CurrentOption?}} + \ProcessOptions\relax +\end{verbatim} +and an author writes |\usepackage[foo,bar]{jane}|, then they will see +the messages \texttt{Saw foo.} and \texttt{What's bar?} + +\subsection{A minimal class file} + +Most of the work of a class or package is in defining new commands, or +changing the appearance of documents. This is done in the body of the +package, using commands such as |\newcommand| or |\setlength|. + +\LaTeXe{} provides several new commands to help class and package +writers; these are described in detail in Section~\ref{Sec:commands}. + +There are four things that every class file \emph{must} contain: these +are a definition of |\normalsize|, values for |\textwidth| and +|\textheight| and a specification for page-numbering. So a minimal +document class file\footnote {This class is now in the standard +distribution, as \texttt{minimal.cls}.} looks like this: +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e} + \ProvidesClass{minimal}[1995/10/30 Standard LaTeX minimal class] + \renewcommand{\normalsize}{\fontsize{10pt}{12pt}\selectfont} + \setlength{\textwidth}{6.5in} + \setlength{\textheight}{8in} + \pagenumbering{arabic} % needed even though this class will + % not show page numbers +\end{verbatim} +However, this class file will not support footnotes, marginals, +floats, etc., nor will it provide any of the 2-letter font commands +such as |\rm|; thus most classes will contain more than this minimum! + +\subsection{Example: a local letter class} + +A company may have its own letter class, for setting letters in the +company style. This section shows a simple implementation of such a +class, although a real class would need more structure. + +The class begins by announcing itself as |neplet.cls|. +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e} + \ProvidesClass{neplet}[1995/04/01 NonExistent Press letter class] +\end{verbatim} +Then this next bit passes any options on to the |letter| class, which +is loaded with the |a4paper| option. +\begin{verbatim} + \DeclareOption*{\PassOptionsToClass{\CurrentOption}{letter}} + \ProcessOptions\relax + \LoadClass[a4paper]{letter} +\end{verbatim} +In order to use the company letter head, it redefines the +|firstpage| page style: this is the page style that is used on +the first page of letters. +\begin{verbatim} + \renewcommand{\ps@firstpage}{% + \renewcommand{\@oddhead}{<letterhead goes here>}% + \renewcommand{\@oddfoot}{<letterfoot goes here>}% + } +\end{verbatim} +And that's it! + +\subsection{Example: a newsletter class} + +A simple newsletter can be typeset with \LaTeX{}, using a variant of the +|article| class. +The class begins by announcing itself as |smplnews.cls|. +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e} + \ProvidesClass{smplnews}[1995/04/01 The Simple News newsletter class] + + \newcommand{\headlinecolor}{\normalcolor} +\end{verbatim} +It passes most specified options on to the |article| class: apart from +the |onecolumn| option, which is switched off, and the |green| option, +which sets the headline in green. +\begin{verbatim} + \DeclareOption{onecolumn}{\OptionNotUsed} + \DeclareOption{green}{\renewcommand{\headlinecolor}{\color{green}}} + + \DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}} + + \ProcessOptions\relax +\end{verbatim} +It then loads the class |article| with the option |twocolumn|. +\begin{verbatim} + \LoadClass[twocolumn]{article} +\end{verbatim} +Since the newsletter is to be printed in colour, it now loads the +|color| package. The class does not specify a device driver option +since this should be specified by the user of the |smplnews| class. +\begin{verbatim} + \RequirePackage{color} +\end{verbatim} +The class then redefines |\maketitle| to produce the title in 72pt +Helvetica bold oblique, in the appropriate colour. +\begin{verbatim} + \renewcommand{\maketitle}{% + \twocolumn[% + \fontsize{72}{80}\fontfamily{phv}\fontseries{b}% + \fontshape{sl}\selectfont\headlinecolor + \@title + ]% + } +\end{verbatim} +It redefines |\section| and switches off section numbering. +\begin{verbatim} + \renewcommand{\section}{% + \@startsection + {section}{1}{0pt}{-1.5ex plus -1ex minus -.2ex}% + {1ex plus .2ex}{\large\sffamily\slshape\headlinecolor}% + } + + \setcounter{secnumdepth}{0} +\end{verbatim} +It also sets the three essential things. +\begin{verbatim} + \renewcommand{\normalsize}{\fontsize{9}{10}\selectfont} + \setlength{\textwidth}{17.5cm} + \setlength{\textheight}{25cm} +\end{verbatim} +In practice, a class would need more than this: it would provide +commands for issue numbers, authors of articles, page styles and so +on; but this skeleton gives a start. The |ltnews| class file is not +much more complex than this one. + +\section{Commands for class and package writers} +\label{Sec:commands} + +This section describes briefly each of the new commands for class and +package writers. To find out about other aspects of the new system, +you should also read \emph{\LaTeXbook}, \emph{\LaTeXcomp} and +\emph{\usrguide}. + +\subsection{Identification} + +The first group of commands discussed here are those used +to identify your class or package file. + +\begin{decl} +|\NeedsTeXFormat| \arg{format-name} \oarg{release-date} +\end{decl} +This command tells \TeX{} that this file should be processed using a +format with name \m{format-name}. You can use the optional argument +\m{release-date} to further specify the earliest release date of the +format that is needed. When the release date of the format is older +than the one specified a warning will be generated. The standard +\m{format-name} is \texttt{LaTeX2e}. The date, if present, must be in +the form \textsc{yyyy/mm/dd}. + +Example: +\begin{verbatim} + \NeedsTeXFormat{LaTeX2e}[1994/06/01] +\end{verbatim} + +\begin{decl} +|\ProvidesClass| \arg{class-name} \oarg{release-info} \\ +|\ProvidesPackage| \arg{package-name} \oarg{release-info} +\end{decl} +This declares that the current file contains the definitions for the +document class \m{class-name} or package \m{package-name}. + +The optional \m{release-info}, if used, must contain: +\begin{itemize} + \item the release date of + this version of the file, in the form \textsc{yyyy/mm/dd}; +\item optionally followed by a space and a short description, possibly + including a version number. +\end{itemize} +The above syntax must be followed exactly so that this information +can be used by |\LoadClass| or |\documentclass| (for classes) or +|\RequirePackage| or |\usepackage| (for packages) to test that the +release is not too old. + +The whole of this \m{release-info} information is displayed by +|\listfiles| and should therefore not be too long. + +Example: +\begin{verbatim} + \ProvidesClass{article}[1994/06/01 v1.0 Standard LaTeX class] + \ProvidesPackage{ifthen}[1994/06/01 v1.0 Standard LaTeX package] +\end{verbatim} + +\begin{decl} + |\ProvidesFile| \arg{file-name} \oarg{release-info} +\end{decl} +This is similar to the two previous commands except that here the full +filename, including the extension, must be given. It is used for +declaring any files other than main class and package files. + +Example: +\begin{verbatim} + \ProvidesFile{T1enc.def}[1994/06/01 v1.0 Standard LaTeX file] +\end{verbatim} + +Note that the phrase \texttt{Standard LaTeX} \textbf{must not} be used +in the identification banner of any file other than those in the +standard \LaTeX{} distribution. + +\subsection{Loading files} +\label{Sec:loadf} + +\NEWfeature{1995/12/01} +This group of commands can be used to create your own document class or +package by building on existing classes or packages. +\begin{decl} + |\RequirePackage| \oarg{options-list} \arg{package-name} + \oarg{release-info}\\ + |\RequirePackageWithOptions| \arg{package-name} + \oarg{release-info} +\end{decl} +Packages and classes should use these commands to load other packages. + +The use of |\RequirePackage| is the same as the author command +|\usepackage|. + +Examples: +\begin{verbatim} + \RequirePackage{ifthen}[1994/06/01] + \RequirePackageWithOptions{graphics}[1995/12/01] +\end{verbatim} + +\begin{decl} + |\LoadClass| \oarg{options-list} \arg{class-name} + \oarg{release-info}\\ + |\LoadClassWithOptions| \arg{class-name} + \oarg{release-info} +\end{decl} +\NEWfeature{1995/12/01} +These commands are for use \emph{only} in class files, they cannot be +used in packages files; +they can be used at most once within a class file. + +The use of |\LoadClass| is the same as +the use of |\documentclass| to load a class file. + +Examples: +\begin{verbatim} + \LoadClass{article}[1994/06/01] + \LoadClassWithOptions{article}[1995/12/01] +\end{verbatim} + +\NEWfeature{1995/12/01} +The two |WithOptions| versions simply load the class (or package) file +with exactly those options that are being used by the current file +(class or package). See below, in \ref{Sec:opmove}, for further +discussion of their use. + + +\subsection{Option declaration} +\label{Sec:commands.options.dec} + +\NEWdescription{1998/12/01} +The following commands deal with the declaration and handling of +options to document classes and packages. Every option name must be a +`\LaTeX{} name'. + +There are some commands designed especially for use within the +\m{code} argument of these commands (see below). + +\begin{decl} + |\DeclareOption| \arg{option-name} \arg{code} +\end{decl} +This makes \m{option-name} a `declared option' of the class or package +in which it is put. + +The \m{code} argument contains the code to be executed if that option +is specified for the class or package; it can contain any valid +\LaTeXe{} construct. + +Example: +\begin{verbatim} + \DeclareOption{twoside}{\@twosidetrue} +\end{verbatim} + +\begin{decl} + |\DeclareOption*| \arg{code} +\end{decl} +This declares the \m{code} to be executed for every option which is +specified for, but otherwise not explicitly declared by, the class or +package; this code is called the `default option code' and it can +contain any valid \LaTeXe{} construct. + +If a class file contains no |\DeclareOption*| then, by default, all +specified but undeclared options for that class will be silently +passed to all packages (as will the specified and declared options for +that class). + +If a package file contains no |\DeclareOption*| then, by default, each +specified but undeclared option for that package will produce an error. + + +\subsection{Commands within option code} +\label{Sec:within.code} + +These two commands can be used only within the \m{code} argument of +either |\DeclareOption| or |\DeclareOption*|. Other commands commonly +used within these arguments can be found in the next few subsections. + +\begin{decl} + |\CurrentOption| +\end{decl} +This expands to the name of the current option. + +\begin{decl} + |\OptionNotUsed| +\end{decl} +This causes the current option to +be added to the list of `unused options'. + +\NEWfeature{1995/06/01} + You can now include hash marks (\texttt{\#}) within these \m{code} + arguments without special treatment (formerly, it had been + necessary to double them). + +\subsection{Moving options around} +\label{Sec:opmove} + +These two commands are also very useful within the \m{code} argument +of |\DeclareOption| or |\DeclareOption*|: +\begin{decl} + |\PassOptionsToPackage| \arg{options-list} \arg{package-name}\\ + |\PassOptionsToClass| \arg{options-list} \arg{class-name} +\end{decl} +The command |\PassOptionsToPackage| passes the option names in +\m{options-list} to package \m{package-name}. +This means that it adds the \m{option-list} to the +list of options used by any future |\RequirePackage| or |\usepackage| +command for package \m{package-name}. + +Example: +\begin{verbatim} + \PassOptionsToPackage{foo,bar}{fred} + \RequirePackage[baz]{fred} +\end{verbatim} +is the same as: +\begin{verbatim} + \RequirePackage[foo,bar,baz]{fred} +\end{verbatim} + +Similarly, |\PassOptionsToClass| may be used in a class file to pass +options to another class to be loaded with |\LoadClass|. + +\NEWdescription{1995/12/01} +The effects and use of these two commands should be contrasted with +those of the following two (documented above, in \ref{Sec:loadf}): +\begin{verbatim} + \LoadClassWithOptions + \RequirePackageWithOptions +\end{verbatim} +The command |\RequirePackageWithOptions| is similar to +|\RequirePackage|, but it always loads the required package with +exactly the same option list as that being used by the current class +or package, rather than with any option explicitly supplied or passed +on by |\PassOptionsToPackage|. + +The main purpose of |\LoadClassWithOptions| is to allow one class to +simply build on another, for example: +\begin{verbatim} + \LoadClassWithOptions{article} +\end{verbatim} +This should be compared with the slightly different construction +\begin{verbatim} + \DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}} + \ProcessOptions\relax + \LoadClass{article} +\end{verbatim} +As used above, the effects are more or less the same, but the first is +a lot less to type; also the |\LoadClassWithOptions| method runs +slightly quicker. + +If, however, the class declares options of its own then +the two constructions are different. Compare, for example: +\begin{verbatim} + \DeclareOption{landscape}{\@landscapetrue} + \ProcessOptions\relax + \LoadClassWithOptions{article} +\end{verbatim} +with: +\begin{verbatim} + \DeclareOption{landscape}{\@landscapetrue} + \DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}} + \ProcessOptions\relax + \LoadClass{article} +\end{verbatim} +In the first example, the \textsf{article} class will be loaded with +option |landscape| precisely when the current class is called with +this option. By contrast, in the second example it will never be +called with option \texttt{landscape} as in that case \textsf{article} +is passed options only by the default option handler, but this handler +is not used for |landscape| because that option is explicitly +declared. + +\subsection{Delaying code} +\label{Sec:delays} + +These first two commands are also intended primarily for use within +the \m{code} argument of |\DeclareOption| or |\DeclareOption*|. + +\begin{decl} + |\AtEndOfClass| \arg{code}\\ + |\AtEndOfPackage| \arg{code} +\end{decl} +These commands declare \m{code} that is saved away internally and then +executed after processing the whole of the current class or package +file. + +Repeated use of these commands is permitted: the code in the +arguments is stored (and later executed) in the order of their +declarations. + +\begin{decl} + |\AtBeginDocument| \arg{code}\\ + |\AtEndDocument| \arg{code} +\end{decl} +These commands declare \m{code} to be saved internally and executed +while \LaTeX{} is executing |\begin{document}| or |\end{document}|. + +The \m{code} specified in the argument to |\AtBeginDocument| is +executed near the end of the |\begin{document}| code, \emph{after} the +font selection tables have been set up. It is therefore a useful +place to put code which needs to be executed after everything has been +prepared for typesetting and when the normal font for the document is +the current font. + +\NEWdescription{1995/12/01} +The |\AtBeginDocument| hook should not be used for code that does any +typesetting since the typeset result would be unpredictable. + +The \m{code} specified in the argument to |\AtEndDocument| is +executed at the beginning of the |\end{document}| code, +\emph{before} the final page is finished and before any leftover +floating environments are processed. If some of the \m{code} is to be +executed after these two processes, you should include a |\clearpage| +at the appropriate point in \m{code}. + +Repeated use of these commands is permitted: the code in the +arguments is stored (and later executed) in the order of their +declarations. + +\begin{decl}[1994/12/01] + |\AtBeginDvi| \arg{specials} +\end{decl} +These commands save in a box register things which are written to the +|.dvi| file at the beginning of the `shipout' of the first page of the +document. + +This should not be used for anything that will add any typeset +material to the |.dvi| file. + +Repeated use of this command is permitted. + + +\subsection{Option processing} +\label{Sec:commands.options} + +\begin{decl} + |\ProcessOptions| +\end{decl} +This command executes the \m{code} for each selected option. + +We shall first describe how |\ProcessOptions| works in a package file, +and then how this differs in a class file. + +To understand in detail what |\ProcessOptions| does in a package file, +you have to know the difference between \emph{local} and \emph{global} +options. +\begin{itemize} +\item \textbf{Local options} are those which have been explicitly + specified for this particular package in the \m{options} argument of + any of these: +\begin{quote} + |\PassOptionsToPackage{<options>}| \ |\usepackage[<options>]|\\ + |\RequirePackage[<options>]| +\end{quote} +\item \textbf{Global options} are any other options that are specified + by the author in the \m{options} argument of + |\documentclass[<options>]|. +\end{itemize} +For example, suppose that a document begins: +\begin{verbatim} + \documentclass[german,twocolumn]{article} + \usepackage{gerhardt} +\end{verbatim} +whilst package |gerhardt| calls package |fred| with: +\begin{verbatim} + \PassOptionsToPackage{german,dvips,a4paper}{fred} + \RequirePackage[errorshow]{fred} +\end{verbatim} +then: +\begin{itemize} +\item |fred|'s local options are |german|, |dvips|, |a4paper| + and |errorshow|; +\item |fred|'s only global option is |twocolumn|. +\end{itemize} + +When |\ProcessOptions| is called, the following happen. +\begin{itemize} +\item \emph{First}, for each option so far declared in |fred.sty| + by |\DeclareOption|, it looks to see if that option is either a + global or a local option for |fred|: if it is then the corresponding + code is executed. + + This is done in the order in which these options + were declared in |fred.sty|. +\item \emph{Then}, for each remaining \emph{local} option, the command + |\ds@<option>| is executed if it has been defined somewhere (other + than by a |\DeclareOption|); otherwise, the `default option code' is + executed. If no default option code has been declared then an error + message is produced. + + This is done in the order in which these + options were specified. +\end{itemize} +Throughout this process, the system ensures that the code declared for +an option is executed at most once. + +Returning to the example, if |fred.sty| contains: +\begin{verbatim} + \DeclareOption{dvips}{\typeout{DVIPS}} + \DeclareOption{german}{\typeout{GERMAN}} + \DeclareOption{french}{\typeout{FRENCH}} + \DeclareOption*{\PackageWarning{fred}{Unknown `\CurrentOption'}} + \ProcessOptions\relax +\end{verbatim} +then the result of processing this document will be: +\begin{verbatim} + DVIPS + GERMAN + Package fred Warning: Unknown `a4paper'. + Package fred Warning: Unknown `errorshow'. +\end{verbatim} +Note the following: + +\begin{itemize} +\item the code for the |dvips| option is executed before that for the + |german| option, because that is the order in which they are declared + in |fred.sty|; +\item the code for the |german| option is executed only once, when the + declared options are being processed; +\item the |a4paper| and |errorshow| options produce the warning from + the code declared by |\DeclareOption*| (in the order in which they + were specified), whilst the |twocolumn| option does not: this is + because |twocolumn| is a global option. +\end{itemize} + +In a class file, |\ProcessOptions| works in the same way, except +that: \emph{all} options are local; and the default value for +|\DeclareOption*| is |\OptionNotUsed| rather than an error. + +\NEWdescription{1995/12/01} +Note that, because |\ProcessOptions| has a |*|-form, it is wise to +follow the non-star form with |\relax|, as in the previous examples, +since this prevents unnecessary look ahead and possibly misleading +error messages being issued. + +\begin{decl} + |\ProcessOptions*| \\ + |\@options| +\end{decl} +This is like |\ProcessOptions| but it executes the options in the +order specified in the calling commands, rather than in the order of +declaration in the class or package. For a package this means that the +global options are processed first. + +The |\@options| command from \LaTeX~2.09 has been made equivalent to +this in order to ease the task of updating old document styles to +\LaTeXe{} class files. + +\begin{decl} + |\ExecuteOptions| \arg{options-list} +\end{decl} + +For each option in the \m{options-list}, in order, +this command simply executes the command +|\ds@<option>| (if this command is not defined, then that option is +silently ignored). + +It can be used to provide a `default option list' just before +|\ProcessOptions|. For example, suppose that in a class file you want +to set up the default design to be: two-sided printing; 11pt fonts; +in two columns. Then it could specify: +\begin{verbatim} + \ExecuteOptions{11pt,twoside,twocolumn} +\end{verbatim} + + +\subsection{Safe file commands} + +These commands deal with file input; they ensure that the non-existence +of a requested file can be handled in a user-friendly way. + +\begin{decl} +|\IfFileExists| \arg{file-name} \arg{true} \arg{false} +\end{decl} +If the file exists then the code specified in \m{true} is +executed. + +If the file does not exist then the code specified in \m{false} is +executed. + +This command does \emph{not} input the file. + +\begin{decl} + |\InputIfFileExists| \arg{file-name} \arg{true} \arg{false} +\end{decl} +This inputs the file \m{file-name} if it exists and, immediately +before the input, the code specified in \m{true} is executed. + +If the file does not exist then the code specified in \m{false} is +executed. + +It is implemented using |\IfFileExists|. + + +\subsection{Reporting errors, etc} + +These commands should be used by third party classes and packages to +report errors, or to provide information to authors. + +\begin{decl} + |\ClassError| \arg{class-name} \arg{error-text} \arg{help-text}\\ + |\PackageError| \arg{package-name} \arg{error-text} \arg{help-text} +\end{decl} +These produce an error message. The \m{error-text} is displayed and the +|?| error prompt is shown. If the user types |h|, they will be shown +the \m{help-text}. + +Within the \m{error-text} and \m{help-text}: |\protect| can be used to +stop a command from expanding; |\MessageBreak| causes a line-break; +and |\space| prints a space. + +Note that the \m{error-text} will have a full stop added to it, so do +not put one into the argument. + +For example: +\begin{verbatim} + \newcommand{\foo}{FOO} + \PackageError{ethel}{% + Your hovercraft is full of eels,\MessageBreak + and \protect\foo\space is \foo + }{% + Oh dear! Something's gone wrong.\MessageBreak + \space \space Try typing \space <<return>> + \space to proceed, ignoring \protect\foo. + } +\end{verbatim} +produces this display: +\begin{verbatim} + ! Package ethel Error: Your hovercraft is full of eels, + (ethel) and \foo is FOO. + + See the ethel package documentation for explanation. +\end{verbatim} +If the user types |h|, this will be shown: +\begin{verbatim} + Oh dear! Something's gone wrong. + Try typing <<return>> to proceed, ignoring \foo. +\end{verbatim} + +\begin{decl} + |\ClassWarning| \arg{class-name} \arg{warning-text}\\ + |\PackageWarning| \arg{package-name} \arg{warning-text}\\ + |\ClassWarningNoLine| \arg{class-name} \arg{warning-text}\\ + |\PackageWarningNoLine| \arg{package-name} \arg{warning-text}\\ + |\ClassInfo| \arg{class-name} \arg{info-text}\\ + |\PackageInfo| \arg{package-name} \arg{info-text} +\end{decl} +The four |Warning| commands are similar to the error commands, except +that they produce only a warning on the screen, with no error prompt. + +The first two, |Warning| versions, also show the line number where the +warning occurred, whilst the second two, |WarningNoLine| versions, do +not. + +The two |Info| commands are similar except that they log the +information only in the transcript file, including the line number. +There are no |NoLine| versions of these two. + +Within the \m{warning-text} and \m{info-text}: |\protect| can be used to +stop a command from expanding; |\MessageBreak| causes a line-break; +and |\space| prints a space. +Also, these should not end with a full stop as one is +automatically added. + + +\subsection{Defining commands} +\label{Sec:commands.define} + +\LaTeXe{} provides some extra methods of (re)defining commands that are +intended for use in class and package files. + +\NEWfeature{1994/12/01} +The \texttt{*}-forms of these commands should be used to define +commands that are not, in \TeX{} terms, long. This can be useful for +error-trapping with commands whose arguments are not intended to +contain whole paragraphs of text. + +\begin{decl} + |\DeclareRobustCommand| \arg{cmd} \oarg{num} \oarg{default} + \arg{definition}\\ + |\DeclareRobustCommand*| \arg{cmd} \oarg{num} \oarg{default} + \arg{definition} +\end{decl} +This command takes the same arguments as |\newcommand| but it declares +a robust command, even if some code within the \m{definition} is +fragile. You can use this command to define new robust commands, or +to redefine existing commands and make them robust. A log is put into +the transcript file if a command is redefined. + +For example, if |\seq| is defined as follows: +\begin{verbatim} + \DeclareRobustCommand{\seq}[2][n]{% + \ifmmode + #1_{1}\ldots#1_{#2}% + \else + \PackageWarning{fred}{You can't use \protect\seq\space in text}% + \fi + } +\end{verbatim} +Then the command |\seq| can be used in moving arguments, even though +|\ifmmode| cannot, for example: +\begin{verbatim} + \section{Stuff about sequences $\seq{x}$} +\end{verbatim} + +Note also that there is no need to put a |\relax| before the +|\ifmmode| at the beginning of the definition; this is because the +protection given by this |\relax| against expansion at the wrong time +will be provided internally. + +\begin{decl} + |\CheckCommand| \arg{cmd} \oarg{num} \oarg{default} + \arg{definition}\\ + |\CheckCommand*| \arg{cmd} \oarg{num} \oarg{default} + \arg{definition} +\end{decl} +This takes the same arguments as |\newcommand| but, rather than define +\m{cmd}, it just checks that the current definition of \m{cmd} is +exactly as given by \m{definition}. An error is raised if these +definitions differ. + +This command is useful for checking the state of the system before +your package starts altering the definitions of commands. It allows +you to check, in particular, that no other package has redefined the +same command. + +\subsection{Moving arguments} + +\NEWdescription{1994/12/01} +The setting of protect whilst processing (i.e.~moving) moving arguments +has been reimplemented, as has the method of writing information from +the |.aux| file to other files such as the |.toc| file. Details can +be found in the file |ltdefns.dtx|. + +We hope that these changes will not affect many packages. + +\section{Miscellaneous commands, etc} +\label{Sec:commands.misc} + +\subsection{Layout parameters} + +\begin{decl} +|\paperheight|\\ +|\paperwidth| +\end{decl} +These two parameters are usually set by the class to be the size of +the paper being used. This should be actual paper size, unlike +|\textwidth| and |\textheight| which are the size of the main text +body within the margins. + + +\subsection{Case changing} +\label{sec:case} + +\begin{decl} + |\MakeUppercase| \arg{text} \\ + |\MakeLowercase| \arg{text} +\end{decl} + +\NEWfeature{1995/06/01} +\TeX{} provides two primitives |\uppercase| and |\lowercase| for +changing the case of text. These are sometimes used in document +classes, for example to set information in running heads in all +capitals. + +Unfortunately, these \TeX{} primitives do not change the case of +characters accessed by commands like |\ae| or |\aa|. To overcome this +problem, \LaTeX{} provides two new commands |\MakeUppercase| and +|\MakeLowercase| to do this. + +For example: +\begin{quotation} +\begin{tabular}{rl} + |\uppercase{aBcD\ae\AA\ss\OE}| & \uppercase{aBcD\ae\AA\ss\OE}\\ + |\lowercase{aBcD\ae\AA\ss\OE}| & \lowercase{aBcD\ae\AA\ss\OE}\\ + |\MakeUppercase{aBcD\ae\AA\ss\OE}| & + \MakeUppercase{aBcD\ae\AA\ss\OE}\\ + |\MakeLowercase{aBcD\ae\AA\ss\OE}| & \MakeLowercase{aBcD\ae\AA\ss\OE} +\end{tabular} +\end{quotation} + +The commands |\MakeUppercase| and |\MakeLowercase| themselves are +robust, but they have moving arguments. + +The commands use the \TeX{} primitives |\uppercase| and |\lowercase|, +and so have a number of unexpected `features'. In particular, they +change the case of everything (except characters in the names of +control-sequences) in their text argument: this includes mathematics, +environment names, and label names. + +For example: +\begin{verbatim} + \MakeUppercase{$x+y$ in \ref{foo}} +\end{verbatim} +produces $X+Y$ and the warning: +\begin{verbatim} + LaTeX Warning: Reference `FOO' on page ... undefined on ... +\end{verbatim} +In the long run, we would like to use all-caps fonts rather than any +command like |\MakeUppercase| but this is not possible at the moment +because such fonts do not exist. + +\NEWdescription{1995/12/01} +In order that upper/lower-casing will work reasonably well, and in +order to provide any correct hyphenation, \LaTeXe{} \emph{must} use, +throughout a document, the same fixed table for changing case. +The table used is designed for the font encoding |T1|; this works well +with the standard \TeX{} fonts for all Latin alphabets but will cause +problems when using other alphabets. + +\subsection{The `openany' option in the `book' class} + +\NEWdescription{1996/06/01} +The |openany| option allows chapter and similar openings to +occur on left hand pages. Previously this option affected only +|\chapter| and |\backmatter|. It now also affects +|\part|, |\frontmatter| and |\mainmatter|. + +\subsection{Better user-defined math display environments} + +\begin{decl} + |\ignorespacesafterend| +\end{decl} + +\NEWfeature{1996/12/01} +\NEWdescription{2003/12/01} +Suppose that you want to define an environment for displaying text +that is numbered as an equation. A straightforward way to do this is +as follows: +\begin{verbatim} + \newenvironment{texteqn} + {\begin{equation} + \begin{minipage}{0.9\linewidth}} + {\end{minipage} + \end{equation}} +\end{verbatim} +However, if you have tried this then you will probably have noticed +that it does not work perfectly when used in the middle of a paragraph +because an inter-word space appears at the beginning of the first +line after the environment. + +There is now an extra command (with a very long name) available that +you can use to avoid this problem; it should be inserted as shown here: +\begin{verbatim} + \newenvironment{texteqn} + {\begin{equation} + \begin{minipage}{0.9\linewidth}} + {\end{minipage} + \end{equation} + \ignorespacesafterend} +\end{verbatim} + +This command may also have other uses. + +\subsection{Normalising spacing} + +\begin{decl} + |\normalsfcodes| +\end{decl} + +\NEWfeature{1997/06/01} +This command should be used to restore the normal settings of the +parameters that affect spacing between words, sentences, etc. + +An important use of this feature is to correct a problem, reported by +Donald Arseneau, that punctuation in page headers has always (in all +known \TeX{} formats) been potentially wrong whenever a page break +happens while a local setting of the space codes is in effect. These +space codes are changed by, for example, the command +\verb|\frenchspacing|) and the \textsf{verbatim} environment. + +It is normally given the correct definition automatically in +|\begin{document}| and so need not be explicitly set; however, if it +is explicitly made nonempty in a class file then automatic +default setting will be over-ridden. + + +\section{Upgrading \LaTeX~2.09 classes and packages} +\label{Sec:upgrade} + +This section describes the changes you may need to make when you +upgrade an existing \LaTeX{} style to a package or class but we shall +start in optimistic mode. + +Many existing style files will run with \LaTeXe{} without any +modification to the file itself. When everything is running OK, +please put a note in the newly created package or class file to record +that it runs with the new standard \LaTeX{}; then distribute it to +your users. + +\subsection{Try it first!} +\label{Sec:try-it} + +The first thing you should do is to test your style in `compatibility +mode'. The only change you need to make in order to do this is, +possibly, to change the extension of the file to |.cls|: you should +make this change only if your file was used as a main document style. +Now, without any other modifications, run \LaTeXe{} on a document that +uses your file. This assumes that you have a suitable collection of +files that tests all the functionality provided by your style file. +(If you haven't, now is the time to make one!) + +You now need to change the test document files so that they are +\LaTeXe{} documents: see \emph{\usrguide} for details of how to do +this and then try them again. You have now tried the test documents +in both \LaTeXe{} native mode and \LaTeX~2.09 compatibility mode. + +\subsection{Troubleshooting} +\label{Sec:trouble} + +If your file does not work with \LaTeXe{}, there are two likely +reasons. +\begin{itemize} +\item \LaTeX{} now has a robust, well-defined designer's interface for + selecting fonts, which is very different from the \LaTeX~2.09 + internals. +\item Your style file may have used some \LaTeX~2.09 internal commands + which have changed, or which have been removed. +\end{itemize} + +When you are debugging your file, you will probably need more +information than is normally displayed by \LaTeXe. This is achieved +by resetting the counter |errorcontextlines| from its default value of +$-1$ to a much higher value, e.g.~999. + +\subsection{Accommodating compatibility mode} + +Sometimes an existing collection of \LaTeX~2.09 documents makes it +inconvenient or impossible to abandon the old commands entirely. +If this is the case, then it is possible to accommodate both conventions +by making special provision for documents processed in compatibility +mode. + +\begin{decl} +|\if@compatibility| +\end{decl} +This switch is set when a document begins with |\documentstyle| rather +than |\documentclass|. Appropriate code can be supplied for either +condition, as follows: +\begin{verbatim} + \if@compatibility + <code emulating LaTeX 2.09 behavior> + \else + <code suitable for LaTeX2e> + \fi +\end{verbatim} + + +\subsection{Font commands} + +Some font and size commands are now defined by the document class +rather than by the \LaTeX{} kernel. If you are upgrading a +\LaTeX~2.09 document style to a class that does not load one of the +standard classes, then you will probably need to add definitions for +these commands. + +\begin{decl} + |\rm| |\sf| |\tt| |\bf| |\it| |\sl| |\sc| +\end{decl} +None of these short-form font selection commands are defined in the +\LaTeXe{} kernel. They are defined by all the standard class files. + +If you want to define them in your class file, there are several +reasonable ways to do this. + +One possible definition is: +\begin{verbatim} + \newcommand{\rm}{\rmfamily} + ... + \newcommand{\sc}{\scshape} +\end{verbatim} +This would make the font commands orthogonal; for example +|{\bf\it text}| would produce bold italic, thus: \textbf{\textit{text}}. +It will also make them produce an error if used in math mode. + +Another possible definition is: +\begin{verbatim} + \DeclareOldFontCommand{\rm}{\rmfamily}{\mathrm} + ... + \DeclareOldFontCommand{\sc}{\scshape}{\mathsc} +\end{verbatim} +This will make |\rm| act like |\rmfamily| in text mode (see above) and +it will make |\rm| select the |\mathrm| math alphabet in math mode. + +Thus |${\rm math} = X + 1$| will produce `${\rm math} = X + 1$'. + +If you do not want font selection to be orthogonal then you can +follow the standard classes and define: +\begin{verbatim} + \DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm} + ... + \DeclareOldFontCommand{\sc}{\normalfont\scshape}{\mathsc} +\end{verbatim} +This means, for example, that |{\bf\it text}| will produce medium +weight (rather than bold) italic, thus: \textit{text}. + +\begin{decl} + |\normalsize| \\ + |\@normalsize| +\end{decl} +The command |\@normalsize| is retained for compatibility with +\LaTeX~2.09 packages which may have used its value; but redefining it +in a class file will have no effect since it is always reset to have +the same meaning as |\normalsize|. + +This means that classes \emph{must} now redefine |\normalsize| rather +than redefining |\@normalsize|; for example (a rather incomplete one): +\begin{verbatim} + \renewcommand{\normalsize}{\fontsize{10}{12}\selectfont} +\end{verbatim} +Note that |\normalsize| is defined by the \LaTeX{} kernel to be an +error message. + +\begin{decl} + |\tiny| |\footnotesize| |\small| |\large|\\ + |\Large| |\LARGE| |\huge| |\Huge| +\end{decl} +None of these other `standard' size-changing commands are defined in +the kernel: each needs to be defined in a class file if you need it. +They are all defined by the standard classes. + +This means you should use |\renewcommand| for |\normalsize| and +|\newcommand| for the other size-changing commands. + + +\subsection{Obsolete commands} + +Some packages will not work with \LaTeXe{}, normally because they relied +on an internal \LaTeX{} command which was never supported and has now +changed, or been removed. + +In many cases there will now be a robust, high-level means of +achieving what previously required low-level commands. Please consult +Section~\ref{Sec:commands} to see if you can now use the \LaTeXe{} +class and package writers commands. + +Also, of course, if your package or class redefined any of the kernel +commands (i.e.~those defined in the files |latex.tex|, |slitex.tex|, +|lfonts.tex|, |sfonts.tex|) then you will need to check it very +carefully against the new kernel in case the implementation has +changed or the command no longer exists in the \LaTeX2e{} kernel. + +Too many of the internal commands of \LaTeX~2.09 have been +re-implemented or removed to be able to list them all here. You must +check any that you have used or changed. + +We shall, however, list some of the more important commands which are +no longer supported. + +\begin{decl} + |\tenrm| |\elvrm| |\twlrm| \dots\\ + |\tenbf| |\elvbf| |\twlbf| \dots\\ + |\tensf| |\elvsf| |\twlsf| \dots\\ + \qquad$\vdots$ +\end{decl} +The (approximately) seventy internal commands of this form are no longer +defined. If your class or package uses them then \emph{please} +replace them with new font commands described in \emph{\fntguide}. + +For example, the command |\twlsf| should be replaced by: +\begin{verbatim} + \fontsize{12}{14}\normalfont\sffamily\selectfont +\end{verbatim} + +Another possibility is to use the |rawfonts| package, described in +\emph{\usrguide}. + +Also, remember that many of the fonts preloaded by \LaTeX~2.09 +are no longer preloaded. + +\begin{decl} + |\vpt| |\vipt| |\viipt| \dots +\end{decl} +These were the internal size-selecting commands in \LaTeX~2.09. +(They can still be used in \LaTeX~2.09 compatibility mode.) +Please use the command |\fontsize| instead: see \emph{\fntguide} for +details. + +For example, |\vpt| should be replaced by: +\begin{verbatim} + \fontsize{5}{6}\normalfont\selectfont +\end{verbatim} + +\begin{decl} + |\prm|, |\pbf|, |\ppounds|, |\pLaTeX| \dots +\end{decl} +\LaTeX~2.09 used several commands beginning with |\p| in order to +provide `protected' commands. For example, |\LaTeX| was defined to be +|\protect\pLaTeX|, and |\pLaTeX| was defined to produce the \LaTeX{} +logo. This made |\LaTeX| robust, even though |\pLaTeX| was not. + +These commands have now been reimplemented using +|\DeclareRobustCommand| +(described in Section~\ref{Sec:commands.define}). +If your package redefined one of the |\p|-commands then you must +remove the redefinition and use |\DeclareRobustCommand| to redefine the +non-|\p| command. + +\begin{decl} +|\footheight|\\ +|\@maxsep|\\ +|\@dblmaxsep| +\end{decl} +These parameters are not used by \LaTeXe{} so they have been removed, +except in \LaTeX~2.09 compatibility mode. Classes should no longer +set them. + +\begin{thebibliography}{1} + +\bibitem{A-W:DEK91} +Donald~E. Knuth. +\newblock {\em The \TeX book}. +\newblock Addison-Wesley, Reading, Massachusetts, 1986. +\newblock Revised to cover \TeX3, 1991. + +\bibitem{A-W:LLa94} +Leslie Lamport. +\newblock {\em {\LaTeX:} A Document Preparation System}. +\newblock Addison-Wesley, Reading, Massachusetts, second edition, 1994. + +\bibitem{A-W:MG2004} +Frank Mittelbach and Michel Goossens. +\newblock {\em The {\LaTeX} Companion second edition}. +\newblock With Johannes Braams, David Carlisle, and Chris Rowley. +\newblock Addison-Wesley, Reading, Massachusetts, 2004. + +\end{thebibliography} + +\newpage +\thispagestyle{empty} + +\section*{\LaTeXe{} Summary sheet: updating old styles} + +Section references below are to \emph{\clsguide}. + +\begin{enumerate} + +\item Should it become a class or a package? + See Section~\ref{Sec:classorpkg} for how to answer this question. + +\item If it uses another style file, then you will need to obtain an + updated version of this other file. Look at Section~\ref{Sec:loading} + for information on how to load other class and package files. + +\item Try it: see Section~\ref{Sec:try-it}. + +\item It worked? Excellent, but there are probably still some things + you should change in order to make your file into a well-structured + \LaTeXe{} file that is both robust and portable. So you should now + read Section~\ref{Sec:writing}, especially~\ref{Sec:general}. You + will also find some useful examples in Section~\ref{Sec:structure}. + + If your file sets up new fonts, font-changing commands or symbols, + you should also read \emph{\fntguide}. + +\item It did not work? There are three possibilities here: + \begin{itemize} + \item error messages are produced whilst reading your file; + \item error messages are produced whilst processing test documents; + \item there are no errors but the output is not as it should be. + \end{itemize} + Don't forget to check carefully for this last possibility. + + If you have got to this stage then you will need to read + Section~\ref{Sec:upgrade} to find the solutions that will make your + file work. +\end{enumerate} + +\end{document} diff --git a/macros/latex/base/clsguide.pdf b/macros/latex/base/clsguide.pdf Binary files differindex 14152ab987..aa9fe4f90a 100644 --- a/macros/latex/base/clsguide.pdf +++ b/macros/latex/base/clsguide.pdf diff --git a/macros/latex/base/clsguide.tex b/macros/latex/base/clsguide.tex index 0ed5e60817..7225425ec8 100644 --- a/macros/latex/base/clsguide.tex +++ b/macros/latex/base/clsguide.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -28,13 +28,13 @@ % \fi % Filename: clsguide.tex -\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\documentclass{ltxguide} -\documentclass{ltxguide}[1995/11/28] +\usepackage[T1]{fontenc} % needed for \textbackslash in tt +\usepackage{csquotes} -\title{\LaTeXe~for class and package writers} - -\author{Copyright \copyright~1995--2006 The \LaTeX\ Project\\ +\title{\LaTeX\ for package and class authors --- current version} +\author{\copyright~Copyright 2023, \LaTeX\ Project Team.\\ All rights reserved.% \footnote{This file may distributed and/or modified under the conditions of the \LaTeX{} Project Public License, either version 1.3c @@ -42,7 +42,18 @@ \texttt{clsguide.tex} for full details.}% } -\date{15 February 2006} +\date{2023-01-12} + +\NewDocumentCommand\cs{m}{\texttt{\textbackslash\detokenize{#1}}} +\NewDocumentCommand\marg{m}{\arg{#1}} +\NewDocumentCommand\meta{m}{\ensuremath{\langle}\textit{#1}\ensuremath{\rangle}} +\NewDocumentCommand\pkg{m}{\textsf{#1}} +\NewDocumentCommand\text{m}{\ifmmode\mbox{#1}\else#1\fi} +% Fix a 'feature' +\makeatletter +\renewcommand \verbatim@font {\normalfont \ttfamily} +\makeatother +\providecommand\url[1]{\texttt{#1}} \begin{document} @@ -52,105 +63,74 @@ \section{Introduction} -This document is an introduction to writing classes and packages for -\LaTeX{}, with special attention given to upgrading existing -\LaTeX~2.09 packages to \LaTeXe{}. The latter subject is also -covered in an article by Johannes Braams published in TUGboat~15.3. - -\subsection{Writing classes and packages for \LaTeXe} - -\LaTeX{} is a document preparation system that enables the document -writer to concentrate on the contents of their text, without bothering -too much about the formatting of it. For example, chapters are -indicated by |\chapter{<title>}| rather than by selecting 18pt bold. - -The file that contains the information about how to turn logical -structure (like `|\chapter|') into formatting (like `18pt bold ragged -right') is a \emph{document class}. In addition, some features (such -as colour or included graphics) are independent of the document class -and these are contained in \emph{packages}. +\LaTeXe{} was released in 1994 and added a number of then-new concepts to +\LaTeX{}. For package and class authors, these are described in +\texttt{clsguide-historic}, which has largely remained unchanged. Since then, +the \LaTeX{} team have worked on a number of ideas, firstly a programming +language for \LaTeX{} (L3 programming layer) and then a range of tools for +authors which build on that language. Here, we describe the current, stable set +of tools provided by the \LaTeX{} kernel for package and class developers. We +assume familiarity with general \LaTeX{} usage as a document author, and that +the material here is read in conjunction with \texttt{usrguide}, which provides +information for general \LaTeX{} users on up-to-date approaches to creating +commands, etc. -One of the largest differences between \LaTeX~2.09 and \LaTeXe{} is in -the commands used to write packages and classes. In \LaTeX~2.09, -there was very little support for writing |.sty| files, and so writers -had to resort to using low-level commands. +\section{Writing classes and packages} +\label{Sec:writing} -\LaTeXe{} provides high-level commands for structuring packages. -It is also much easier to build classes and packages on top of each -other, for example writing a local technical report class |cetechr| -(for the Chemical Engineering department) based on |article|. +This section covers some general points concerned with writing +\LaTeX{} classes and packages. -\subsection{Overview} +\subsection{Is it a class or a package?} +\label{Sec:classorpkg} -This document contains an overview of how to write classes and -packages for \LaTeX{}. It does \emph{not} introduce all of the -commands necessary to write packages: these can be found in either -\emph{\LaTeXbook} or \emph{\LaTeXcomp}. But it does describe the new -commands for structuring classes and packages. +The first thing to do when you want to put some new \LaTeX{} commands +in a file is to decide whether it should be a \emph{document class} or a +\emph{package}. The rule of thumb is: +\begin{quote} + If the commands could be used with any document class, then make + them a package; and if not, then make them a class. +\end{quote} -\begin{description} +There are two major types of class: those like |article|, |report| or +|letter|, which are free-standing; and those which are extensions or +variations of other classes---for example, the |proc| document class, +which is built on the |article| document class. -\item[Section~\ref{Sec:general}] contains some general advice about - writing classes and packages. It describes the difference between - classes and packages, the command naming conventions, the use of - |doc| and |docstrip|, how \TeX's primitive file and box commands - interact with \LaTeX{}. It also contains some hints about general - \LaTeX{} style. +Thus, a company might have a local |ownlet| class for printing letters +with their own headed note-paper. Such a class would build on top of +the existing |letter| class but it cannot be used with any other +document class, so we have |ownlet.cls| rather than |ownlet.sty|. -\item[Section~\ref{Sec:structure}] describes the structure of classes - and packages. This includes building classes and packages on top of - other classes and packages, declaring options and declaring - commands. It also contains example classes. +The |graphics| package, in contrast, provides commands for including +images into a \LaTeX{} document. Since these commands can be used +with any document class, we have |graphics.sty| rather than +|graphics.cls|. -\item[Section~\ref{Sec:commands}] lists the new class and package - commands. +\subsection{Using `docstrip' and `doc'} - \item[Section~\ref{Sec:upgrade}] gives detailed advice on how to - upgrade existing \LaTeX~2.09 classes and packages to \LaTeXe{}. +If you are going to write a large class or package for \LaTeX{} then +you should consider using the |doc| software which comes with +\LaTeX{}. +\LaTeX{} classes and packages written using this can be +processed in two ways: they can be run through \LaTeX{}, to produce +documentation; and they can be processed with |docstrip|, to produce +the |.cls| or |.sty| file. -\end{description} +The |doc| software can automatically generate indexes of definitions, +indexes of command use, and change-log lists. It is very useful for +maintaining and documenting large \TeX{} sources. -\subsection{Further information} - -For a general introduction to \LaTeX{}, including the new features of -\LaTeXe{}, you should read \emph{\LaTeXbook} -by Leslie Lamport~\cite{A-W:LLa94}. - -A more detailed description of the new features of \LaTeX, including an -overview of more than 200 packages and nearly 1000 ready to run examples, is -to be found in \emph{\LaTeXcomp\ second edition} by Frank Mittelbach and -Michel Goossens~\cite{A-W:MG2004}. - -The \LaTeX{} system is based on \TeX{}, which is -described in \emph{The \TeX book} by Donald E.~Knuth~\cite{A-W:DEK91}. - -There are a number of documentation files which accompany every copy -of \LaTeX{}. A copy of \emph{\LaTeX{} News} will come out with each -six-monthly release of \LaTeX{}, and is found in the files -|ltnews*.tex|. The author's guide \emph{\usrguide} describes the new -\LaTeX{} document features; it is in |usrguide.tex|. The guide -\emph{\fntguide} describes the \LaTeX{} font selection scheme for -class- and package-writers; it is in |fntguide.tex|. Configuring -\LaTeX{} is covered by the guide \emph{\cfgguide} in -\texttt{cfgguide.tex} whilst the philosophy behind our policy on -modifying \LaTeX{} is described in \emph{\modguide} in -\texttt{modguide.tex}. - -The documented source code (from the files used to produce the kernel -format via |latex.ltx|) is now available as -\emph{The \LaTeXe\ Sources}. -This very large document also includes an index of -\LaTeX{} commands. It can be typeset from the \LaTeX{} file -|source2e.tex| in the |base| directory, using the source files and -the class file |ltxdoc.cls| from this directory. - -For more information about \TeX{} and \LaTeX{}, please contact your -local \TeX{} Users Group, or the international \TeX{} Users Group. -Addresses and other details can be found at: -\begin{quote}\small\label{addrs} - \texttt{http://www.tug.org/lugs.html} -\end{quote} +The documented sources of the \LaTeX{} kernel itself, and of the +standard classes, etc., are |doc| documents; they are in the |.dtx| +files in the distribution. You can, in fact, typeset the source code +of the kernel as one long document, complete with index, by running +\LaTeX{} on |source2e.tex|. Typesetting these documents uses the +class file |ltxdoc.cls|. +For more information on |doc| and |docstrip|, consult the files +|docstrip.dtx|, |doc.dtx|, and \emph{\LaTeXcomp}. For examples of its +use, look at the |.dtx| files. \subsection{Policy on standard classes} @@ -182,89 +162,10 @@ packages that can be used to enhance these classes. So your first thought when you consider such a deficiency will, we hope, be ``what can I do to improve this?'' -Similar considerations apply to those parts of the kernel that are -implementing design decisions, many of which should be left to the -class file but are not in the current system. We realise that in such -cases it is much more difficult for you to rectify the problem -yourself but it is also the case that making such changes in the -kernel would probably be a major project for us; therefore such -enhancements will have to wait for \LaTeX3. - -\section{Writing classes and packages} -\label{Sec:writing} - -This section covers some general points concerned with writing -\LaTeX{} classes and packages. - - -\subsection{Old versions} - -If you are upgrading an existing \LaTeX~2.09 style file then we -recommend freezing the 2.09 version and no longer maintaining it. -Experience with the various dialects of \LaTeX{} which existed in the -early 1990's suggests that maintaining packages for different versions -of \LaTeX{} is almost impossible. It will, of course, be necessary -for some organisations to maintain both versions in parallel for some -time but this is not essential for those packages and classes -supported by individuals: they should support only the new standard -\LaTeXe{}, not obsolete versions of \LaTeX{}. - - -\subsection{Using `docstrip' and `doc'} - -If you are going to write a large class or package for \LaTeX{} then -you should consider using the |doc| software which comes with -\LaTeX{}. -\LaTeX{} classes and packages written using this can be -processed in two ways: they can be run through \LaTeX{}, to produce -documentation; and they can be processed with |docstrip|, to produce -the |.cls| or |.sty| file. - -The |doc| software can automatically generate indexes of definitions, -indexes of command use, and change-log lists. It is very useful for -maintaining and documenting large \TeX{} sources. - -The documented sources of the \LaTeX{} kernel itself, and of the -standard classes, etc, are |doc| documents; they are in the |.dtx| -files in the distribution. You can, in fact, typeset the source code -of the kernel as one long document, complete with index, by running -\LaTeX{} on |source2e.tex|. Typesetting these documents uses the -class file |ltxdoc.cls|. - -For more information on |doc| and |docstrip|, consult the files -|docstrip.dtx|, |doc.dtx|, and \emph{\LaTeXcomp}. For examples of its -use, look at the |.dtx| files. - -\subsection{Is it a class or a package?} -\label{Sec:classorpkg} - -The first thing to do when you want to put some new \LaTeX{} commands -in a file is to decide whether it should be a \emph{document class} or a -\emph{package}. The rule of thumb is: -\begin{quote} - If the commands could be used with any document class, then make - them a package; and if not, then make them a class. -\end{quote} - -There are two major types of class: those like |article|, |report| or -|letter|, which are free-standing; and those which are extensions or -variations of other classes---for example, the |proc| document class, -which is built on the |article| document class. - -Thus, a company might have a local |ownlet| class for printing letters -with their own headed note-paper. Such a class would build on top of -the existing |letter| class but it cannot be used with any other -document class, so we have |ownlet.cls| rather than |ownlet.sty|. - -The |graphics| package, in contrast, provides commands for including -images into a \LaTeX{} document. Since these commands can be used -with any document class, we have |graphics.sty| rather than -|graphics.cls|. - - \subsection{Command names} -\LaTeX{} has three types of command. +Prior to the introduction of the L3~programming layer described in the next +section, \LaTeX{} had three types of command. There are the author commands, such as |\section|, |\emph| and |\times|: most of these have short names, all in lower case. @@ -289,117 +190,97 @@ However, this rule of thumb is still useful: if a command has |@| in its name then it is not part of the supported \LaTeX{} language---and its behaviour may change in future releases! If a command is mixed-case, or is described in \emph{\LaTeXbook}, then you can rely on -future releases of \LaTeXe{} supporting the command. - -\subsection{Box commands and colour} -\label{Sec:colour} - -Even if you do not intend to use colour in your own documents, by -taking note of the points in this section you can ensure that your -class or package is compatible with the |color| package. This may -benefit people using your class or package who have access to colour -printers. - -The simplest way to ensure `colour safety' is to always use \LaTeX{} -box commands rather than \TeX{} primitives, that is use |\sbox| rather -than |\setbox|, |\mbox| rather than |\hbox| and |\parbox| or -the |minipage| environment rather than |\vbox|. -The \LaTeX{} box commands have new options which mean that they are now -as powerful as the \TeX{} primitives. - -As an example of what can go wrong, consider that in -|{\ttfamily <text>}| -the font is restored just \emph{before} the |}|, whereas in the -similar looking construction -|{\color{green} <text>}| -the colour is restored just \emph{after} the final |}|. Normally this -distinction does not matter at all; but consider a primitive \TeX{} -box assignment such as: +future releases of \LaTeX{} supporting the command. + +\subsection{Programming support} + +As noted in the introduction, the \LaTeX{} kernel today loads dedicated support +from programming, here referred to as the L3 programming layer but also often +called \pkg{expl3}. Details of the general approach taken by the L3 +programming layer are given in the document \texttt{expl3}, while a reference +for all current code interfaces is available as \texttt{interface3}. This layer +contains two types of command: a documented set of commands making up the API +and a large number of private internal commands. The latter all start with two +underscores and should not be used outside of the code module which defines +them. This more structured approach means that using the L3 programming layer +does not suffer from the somewhat fluid situation mentioned above with +`\texttt{@} commands'. + +We do not cover the detail of using the L3 programming layer here. A good +introduction to the approach is provided at +\url{https://www.alanshawn.com/latex3-tutorial/}. + +\subsection{Box commands and color} +\label{Sec:color} + +Even if you do not intend to use color in your own documents, by taking note of +the points in this section you can ensure that your class or package is +compatible with the |color| package. This may benefit people using your class +or package and wish to use color. + +The simplest way to ensure `color safety' is to always use \LaTeX{} box +commands rather than \TeX{} primitives, that is use |\sbox| rather than +|\setbox|, |\mbox| rather than |\hbox| and |\parbox| or the |minipage| +environment rather than |\vbox|. The \LaTeX{} box commands have new options +which mean that they are now as powerful as the \TeX{} primitives. + +As an example of what can go wrong, consider that in |{\ttfamily <text>}| the +font is restored just \emph{before} the |}|, whereas in the similar looking +construction |{\color{green} <text>}| the color is restored just \emph{after} +the final |}|. Normally this distinction does not matter at all; but consider a +primitive \TeX{} box assignment such as: \begin{verbatim} \setbox0=\hbox{\color{green} <text>} \end{verbatim} -Now the colour-restore occurs after the |}| and so is \emph{not} -stored in the box. Exactly what bad effects this can have depends on -how colour is implemented: it can range from getting the wrong -colours in the rest of the document, to causing errors in the -dvi-driver used to print the document. - -Also of interest is the command |\normalcolor|. This is -normally just |\relax| (i.e., does nothing) -but you can use it rather like |\normalfont| to -set regions of the page such as captions or section headings to the -`main document colour'. - - -\subsection{Defining text and math characters} -\label{Sec:chars} - -Because \LaTeXe{} supports different encodings, definitions of commands -for producing symbols, accents, composite glyphs, etc.\ must be -defined using the commands provided for this purpose and described in -\emph{\fntguide}. This part of the system is still under development -so such tasks should be undertaken with great caution. - -Also, |\DeclareRobustCommand| should be used for encoding-independent -commands of this type. - -Note that it is no longer possible to refer to the math font set-up -outside math mode: for example, neither |\textfont 1| nor -|\scriptfont 2| are guaranteed to be defined in other modes. +Now the color-restore occurs after the |}| and so is \emph{not} stored in the +box. Exactly what bad effects this can have depends on how color is +implemented: it can range from getting the wrong colors in the rest of the +document, to causing errors in the dvi-driver used to print the document. +Also of interest is the command |\normalcolor|. This is normally just |\relax| +(i.e., does nothing) but you can use it rather like |\normalfont| to set +regions of the page such as captions or section headings to the `main document +color'. \subsection{General style} \label{Sec:general} -The new system provides many commands designed to help you produce -well-structured class and package files that are both robust and -portable. This section outlines some ways to make intelligent use of -these. +\LaTeX{} provides many commands designed to help you produce well-structured +class and package files that are both robust and portable. This section +outlines some ways to make intelligent use of these. \subsubsection{Loading other files} \label{Sec:loading} -\NEWdescription{1995/12/01} \LaTeX{} provides these commands: \begin{verbatim} \LoadClass \LoadClassWithOptions \RequirePackage \RequirePackageWithOptions \end{verbatim} -for using classes or packages inside other classes or packages. We -recommend strongly that you use them, rather than the primitive -|\input| command, for a number of reasons. +for using classes or packages inside other classes or packages. We recommend +strongly that you use them, rather than the primitive |\input| command, for a +number of reasons. -Files loaded with |\input <filename>| will not be listed in the -|\listfiles| list. +Files loaded with |\input <filename>| will not be listed in the |\listfiles| +list. -If a package is always loaded with |\RequirePackage...| or |\usepackage| -then, even if its loading is requested several times, it will be -loaded only once. By contrast, if it is loaded with |\input| then it -can be loaded more than once; such an extra loading may waste time and -memory and it may produce strange results. +If a package is always loaded with |\RequirePackage...| or |\usepackage| then, +even if its loading is requested several times, it will be loaded only once. By +contrast, if it is loaded with |\input| then it can be loaded more than once; +such an extra loading may waste time and memory and it may produce strange +results. -If a package provides option-processing then, again, strange results -are possible if the package is |\input| rather than loaded by means of +If a package provides option-processing then, again, strange results are +possible if the package is |\input| rather than loaded by means of |\usepackage| or |\RequirePackage...|. -If the package |foo.sty| loads the package |baz.sty| by use of -|\input baz.sty| then the user will get a warning: +If the package |foo.sty| loads the package |baz.sty| by use of |\input baz.sty| +then the user will get a warning: \begin{verbatim} LaTeX Warning: You have requested package `foo', but the package provides `baz'. \end{verbatim} -Thus, for several reasons, using |\input| to load packages is not a -good idea. - -Unfortunately, if you are upgrading the file |myclass.sty| to a class -file then you have to make sure that any old files which contain -|\input myclass.sty| still work. - -This was also true for the standard classes (|article|, |book| and -|report|), since a lot of existing \LaTeX~2.09 document styles contain -|\input article.sty|. The approach which we use to solve this is -to provide minimal files |article.sty|, |book.sty| and |report.sty|, -which simply load the appropriate class files. +Thus, for several reasons, using |\input| to load packages is not a good idea. For example, |article.sty| contains just the following lines: \begin{verbatim} @@ -407,93 +288,72 @@ For example, |article.sty| contains just the following lines: \@obsoletefile{article.cls}{article.sty} \LoadClass{article} \end{verbatim} -You may wish to do the same or, if you think that it is safe to do so, -you may decide to just remove |myclass.sty|. +You may wish to do the same or, if you think that it is safe to do so, you may +decide to just remove |myclass.sty|. \subsubsection{Make it robust} We consider it good practice, when writing packages and classes, to use \LaTeX{} commands as much as possible. -Thus, instead of using |\def...| we recommend using one of -|\newcommand|, |\renewcommand| or |\providecommand|; |\CheckCommand| is -also useful. Doing this makes -it less likely that you will inadvertently redefine a command, giving -unexpected results. +Thus, instead of using |\def...| we recommend using one of |\newcommand|, +|\renewcommand| or |\providecommand| for programming and for defining document +interfaces |\NewDocumentCommand|, etc. (see \texttt{usrguide} for details of +these commands). -When you define an environment, use |\newenvironment| or -|\renewenvironment| instead |\def\foo{...}| and |\def\endfoo{...}|. +When you define an environment, use |\NewDocumentEnvironment|, etc., (or +|\newenvironment|, etc., for simple cases) instead of using |\def\foo{...}| and +|\def\endfoo{...}|. -If you need to set or change the value of a \m{dimen} or \m{skip} -register, use |\setlength|. +If you need to set or change the value of a \m{dimen} or \m{skip} register, use +|\setlength|. -To manipulate boxes, use \LaTeX{} commands such as |\sbox|, -|\mbox| and |\parbox| rather than |\setbox|, |\hbox| and |\vbox|. +To manipulate boxes, use \LaTeX{} commands such as |\sbox|, |\mbox| and +|\parbox| rather than |\setbox|, |\hbox| and |\vbox|. -Use |\PackageError|, |\PackageWarning| or |\PackageInfo| (or the -equivalent class commands) rather than |\@latexerr|, |\@warning| or -|\wlog|. - -It is still possible to declare options by defining |\ds@<option>| and -calling |\@options|; but we recommend the |\DeclareOption| and -|\ProcessOptions| commands instead. These are more powerful and use -less memory. So rather than using: -\begin{verbatim} - \def\ds@draft{\overfullrule 5pt} - \@options -\end{verbatim} -you should use: -\begin{verbatim} - \DeclareOption{draft}{\setlength{\overfullrule}{5pt}} - \ProcessOptions\relax -\end{verbatim} +Use |\PackageError|, |\PackageWarning| or |\PackageInfo| (or the equivalent +class commands) rather than |\@latexerr|, |\@warning| or |\wlog|. -The advantage of this kind of practice is that your code is more -readable and, more important, that it is less likely to break when -used with future versions of \LaTeX{}. +The advantage of this kind of practice is that your code is more readable and +accessible to other experienced \LaTeX{} programmers. \subsubsection{Make it portable} -It is also sensible to make your files are as portable as possible. To -ensure this; they should contain only visible 7-bit text; and the -filenames should contain at most eight characters (plus the three -letter extension). Also, of course, it \textbf{must not} have the -same name as a file in the standard \LaTeX{} distribution, however -similar its contents may be to one of these files. +It is also sensible to make your files are as portable as possible. To ensure +this, files must not have the same name as a file in the standard \LaTeX{} +distribution, however similar its contents may be to one of these files. It is +also still lower risk to stick to file names which use only the ASCII range: +whilst \LaTeX{} works natively with UTF-8, the same cannot be said with +certainty for all tools. For the same reason, avoid spaces in file names. -It is also useful if local classes or packages have a common prefix, -for example the University of Nowhere classes might begin with |unw|. -This helps to avoid every University having its own thesis class, all -called |thesis.cls|. +It is also useful if local classes or packages have a common prefix, for +example the University of Nowhere classes might begin with |unw|. This helps to +avoid every University having its own thesis class, all called |thesis.cls|. If you rely on some features of the \LaTeX{} kernel, or on a package, please specify the release-date you need. For example, the package -error commands were introduced in the June 1994 release so, if you use +error commands were introduced in the June 2022 release so, if you use them then you should put: \begin{verbatim} - \NeedsTeXFormat{LaTeX2e}[1994/06/01] + \NeedsTeXFormat{LaTeX2e}[2022-06-01] \end{verbatim} \subsubsection{Useful hooks} -Some packages and document styles had to redefine the command -|\document| or |\enddocument| to achieve their goal. This is no -longer necessary. You can now use the `hooks' |\AtBeginDocument| and -|\AtEndDocument| (see Section~\ref{Sec:delays}). Again, using these -hooks makes it less likely that your code breaks with future versions -of \LaTeX{}. It also makes it more likely that your package can work -together with someone else's. - -\NEWdescription{1996/12/01} -However, note that code in the |\AtBeginDocument| hook is part of the -preamble. Thus there are restrictions on what can be put there; in -particular, no typesetting can be done. +It is sometimes necessary for a package to arrange for code to be +executed at the start or end of the preamble, at the end of the document +or at the start of every use of an environment. This can be carried +out by using hooks. As a document author, you will likely be familiar with +|\AtBeginDocument|, a wrapper around the more powerful command |\AddToHook|. +The \LaTeX{} kernel provides a large number of dedicated hooks (applying in +a pre-defined location) and generic hooks (applying to arbitrary commands): +the interface for using these is described in \texttt{lthooks} . There are +also hooks to apply to files, described in \texttt{ltfilehooks}. \section{The structure of a class or package} \label{Sec:structure} -\LaTeXe{} classes and packages have more structure than \LaTeX~2.09 -style files did. The outline of a class or package file is: +The outline of a class or package file is: \begin{description} \item[Identification] The file says that it is a \LaTeXe{} package or class, and gives a short description of itself. @@ -517,7 +377,7 @@ Package files do this as follows: For example: \begin{verbatim} \NeedsTeXFormat{LaTeX2e} - \ProvidesPackage{latexsym}[1994/06/01 Standard LaTeX package] + \ProvidesPackage{latexsym}[1998-08-17 Standard LaTeX package] \end{verbatim} Class files do this as follows: \begin{verbatim} @@ -527,40 +387,30 @@ Class files do this as follows: For example: \begin{verbatim} \NeedsTeXFormat{LaTeX2e} - \ProvidesClass{article}[1994/06/01 Standard LaTeX class] -\end{verbatim} -\NEWdescription{1998/06/19} -The \m{date} should be given in the form `\textsc{yyyy/mm/dd}' and -must be present if the optional argument is used (this is also true -for the |\NeedsTeXFormat| command). -Any derivation from this syntax will result in low-level \TeX{} -errors---the commands expect a valid syntax to speed up the daily -usage of the package or class and make no provision for the case that -the developer made a mistake! - -This date is checked whenever a user specifies a date in their -|\documentclass| or |\usepackage| command. For example, if you wrote: -\begin{verbatim} - \documentclass{article}[1995/12/23] -\end{verbatim} -then users at a different location -would get a warning that their copy of |article| was out of -date. - -The description of a class is displayed when the class is used. The -description of a package is put into the log file. These descriptions -are also displayed by the |\listfiles| command. The phrase -\texttt{Standard LaTeX} \textbf{must not} be used in the identification -banner of any file other than those in the standard \LaTeX{} -distribution. + \ProvidesClass{article}[2022-06-01 Standard LaTeX class] +\end{verbatim} +The \m{date} should be given in the form `\textsc{yyyy-mm-dd}' and must be +present if the optional argument is used (this is also true for the +|\NeedsTeXFormat| command). Any derivation from this syntax will result in +low-level \TeX{} errors---the commands expect a valid syntax to speed up the +daily usage of the package or class and make no provision for the case that the +developer made a mistake! +This date is checked whenever a user specifies a date in their |\documentclass| +or |\usepackage| command. For example, if you wrote: +\begin{verbatim} + \documentclass{article}[2022-06-01] +\end{verbatim} +then users at a different location would get a warning that their copy of +|article| was out of date. -\subsection{Using classes and packages} +The description of a class is displayed when the class is used. The description +of a package is put into the log file. These descriptions are also displayed by +the |\listfiles| command. The phrase \texttt{Standard LaTeX} \textbf{must not} +be used in the identification banner of any file other than those in the +standard \LaTeX{} distribution. -The first major difference between \LaTeX~2.09 style files and -\LaTeXe{} packages and classes is that \LaTeXe{} supports -\emph{modularity}, in the sense of building files from small -building-blocks rather than using large single files. +\subsection{Using classes and packages} A \LaTeX{} package or class can load a package as follows: \begin{verbatim} @@ -568,13 +418,12 @@ A \LaTeX{} package or class can load a package as follows: \end{verbatim} For example: \begin{verbatim} - \RequirePackage{ifthen}[1994/06/01] + \RequirePackage{ifthen}[2022-06-01] \end{verbatim} -This command has the same syntax as the author command |\usepackage|. -It allows packages or classes to use features provided by other -packages. For example, by loading the |ifthen| package, a package -writer can use the `if\dots then\dots else\dots' commands provided -by that package. +This command has the same syntax as the author command |\usepackage|. It allows +packages or classes to use features provided by other packages. For example, by +loading the |ifthen| package, a package writer can use the `if\dots then\dots +else\dots' commands provided by that package. A \LaTeX{} class can load one other class as follows: \begin{verbatim} @@ -584,13 +433,12 @@ For example: \begin{verbatim} \LoadClass[twocolumn]{article} \end{verbatim} -This command has the same syntax as the author command |\documentclass|. -It allows classes to be based on the syntax and appearance of another -class. For example, by loading the |article| class, a class writer -only has to change the bits of |article| they don't like, rather than -writing a new class from scratch. +This command has the same syntax as the author command |\documentclass|. It +allows classes to be based on the syntax and appearance of another class. For +example, by loading the |article| class, a class writer only has to change the +bits of |article| they don't like, rather than writing a new class from +scratch. -\NEWfeature{1995/12/01} The following commands can be used in the common case that you want to simply load a class or package file with exactly those options that are being used by the current class. @@ -606,14 +454,20 @@ For example: \subsection{Declaring options} -\NEWdescription{1998/12/01} -The other major difference between \LaTeX~2.09 styles and \LaTeXe{} -packages and classes is in option handling. Packages and classes can -now declare options and these can be specified by authors; for -example, the |twocolumn| option is declared by the |article| class. -Note that the name of an option should contain only those characters -allowed in a `\LaTeX{} name'; in particular it must not contain any -control sequences. +Packages and classes can declare options and these can be specified by authors; +for example, the |twocolumn| option is declared by the |article| class. Note +that the name of an option should contain only those characters allowed in a +`\LaTeX{} name'; in particular it must not contain any control sequences. + +\LaTeX{} supports two methods for creating options: a key--value system and a +`simple text' approach. The key--value system is recommended for new classes +and packages, and is more flexible in handling of option classes than the +simple text approach. Both option methods use the same basic structure within +the \LaTeX{} source: declaration of options first then processing options in a +second step. Both also allow options to be passed on to other packages or an +underlying class. As the `classical' simple text approach is conceptually more +straight-forward to illustrate, it is used here to show the general structure: +see Section~\ref{Sec:opt:keyval} for full details of the key--value approach. An option is declared as follows: \begin{verbatim} @@ -624,63 +478,58 @@ to the |graphics| package is implemented as: \begin{verbatim} \DeclareOption{dvips}{\input{dvips.def}} \end{verbatim} -This means that when an author writes |\usepackage[dvips]{graphics}|, -the file |dvips.def| is loaded. As another example, the |a4paper| -option is declared in the |article| class to set the |\paperheight| -and |\paperwidth| lengths: +This means that when an author writes |\usepackage[dvips]{graphics}|, the file +|dvips.def| is loaded. As another example, the |a4paper| option is declared in +the |article| class to set the |\paperheight| and |\paperwidth| lengths: \begin{verbatim} \DeclareOption{a4paper}{% \setlength{\paperheight}{297mm}% \setlength{\paperwidth}{210mm}% } \end{verbatim} -Sometimes a user will request an option which the class -or package has not explicitly declared. By default this will produce -a warning (for classes) or error (for packages); this behaviour -can be altered as follows: +Sometimes a user will request an option which the class or package has not +explicitly declared. By default this will produce a warning (for classes) or +error (for packages); this behaviour can be altered as follows: \begin{verbatim} \DeclareOption*{<code>} \end{verbatim} -For example, to make the package |fred| produce a warning rather than -an error for unknown options, you could specify: +For example, to make the package |fred| produce a warning rather than an error +for unknown options, you could specify: \begin{verbatim} \DeclareOption*{% \PackageWarning{fred}{Unknown option `\CurrentOption'}% } \end{verbatim} -Then, if an author writes |\usepackage[foo]{fred}|, they will get a -warning \texttt{Package fred Warning: Unknown option `foo'.} As -another example, the |fontenc| package tries to load a file -|<ENC>enc.def| whenever the \m{ENC} option is used. This -can be done by writing: +Then, if an author writes |\usepackage[foo]{fred}|, they will get a warning +\texttt{Package fred Warning: Unknown option `foo'.} As another example, the +|fontenc| package tries to load a file |<ENC>enc.def| whenever the \m{ENC} +option is used. This can be done by writing: \begin{verbatim} \DeclareOption*{% \input{\CurrentOption enc.def}% } \end{verbatim} -\NEWdescription{1998/12/01} -It is possible to pass options on to another package or class, using -the command |\PassOptionsToPackage| or |\PassOptionsToClass| (note -that this is a specialised operation that works only for option -names). For example, to pass every unknown option on to the |article| -class, you can use: + +It is possible to pass options on to another package or class, using the +command |\PassOptionsToPackage| or |\PassOptionsToClass| (note that this is a +specialised operation that works only for option names): see +Section~\ref{Sec:opmove}. For example, to pass every unknown option on to the +|article| class, you can use: \begin{verbatim} \DeclareOption*{% \PassOptionsToClass{\CurrentOption}{article}% } \end{verbatim} -If you do this then you should make sure you load the class at some -later point, otherwise the options will never be processed! +If you do this then you should make sure you load the class at some later +point, otherwise the options will never be processed! -So far, we have explained only how to declare options, not how to -execute them. To process the options with which the file was called, -you should use: +So far, we have explained only how to declare options, not how to execute them. +To process the options with which the file was called, you should use: \begin{verbatim} \ProcessOptions\relax \end{verbatim} -This executes the \m{code} for each option that was both specified and -declared (see Section~\ref{Sec:commands.options} for details of how -this is done). +This executes the \m{code} for each option that was both specified and declared +(see Section~\ref{Sec:commands.options} for details of how this is done). For example, if the |jane| package file contains: \begin{verbatim} @@ -689,8 +538,8 @@ For example, if the |jane| package file contains: \DeclareOption*{\typeout{What's \CurrentOption?}} \ProcessOptions\relax \end{verbatim} -and an author writes |\usepackage[foo,bar]{jane}|, then they will see -the messages \texttt{Saw foo.} and \texttt{What's bar?} +and an author writes |\usepackage[foo,bar]{jane}|, then they will see the +messages \texttt{Saw foo.} and \texttt{What's bar?} \subsection{A minimal class file} @@ -698,9 +547,6 @@ Most of the work of a class or package is in defining new commands, or changing the appearance of documents. This is done in the body of the package, using commands such as |\newcommand| or |\setlength|. -\LaTeXe{} provides several new commands to help class and package -writers; these are described in detail in Section~\ref{Sec:commands}. - There are four things that every class file \emph{must} contain: these are a definition of |\normalsize|, values for |\textwidth| and |\textheight| and a specification for page-numbering. So a minimal @@ -708,7 +554,7 @@ document class file\footnote {This class is now in the standard distribution, as \texttt{minimal.cls}.} looks like this: \begin{verbatim} \NeedsTeXFormat{LaTeX2e} - \ProvidesClass{minimal}[1995/10/30 Standard LaTeX minimal class] + \ProvidesClass{minimal}[2022-06-01 Standard LaTeX minimal class] \renewcommand{\normalsize}{\fontsize{10pt}{12pt}\selectfont} \setlength{\textwidth}{6.5in} \setlength{\textheight}{8in} @@ -728,18 +574,17 @@ class, although a real class would need more structure. The class begins by announcing itself as |neplet.cls|. \begin{verbatim} \NeedsTeXFormat{LaTeX2e} - \ProvidesClass{neplet}[1995/04/01 NonExistent Press letter class] + \ProvidesClass{neplet}[2022-06-01 NonExistent Press letter class] \end{verbatim} -Then this next bit passes any options on to the |letter| class, which -is loaded with the |a4paper| option. +Then this next bit passes any options on to the |letter| class, which is loaded +with the |a4paper| option. \begin{verbatim} \DeclareOption*{\PassOptionsToClass{\CurrentOption}{letter}} \ProcessOptions\relax \LoadClass[a4paper]{letter} \end{verbatim} -In order to use the company letter head, it redefines the -|firstpage| page style: this is the page style that is used on -the first page of letters. +In order to use the company letter head, it redefines the |firstpage| page +style: this is the page style that is used on the first page of letters. \begin{verbatim} \renewcommand{\ps@firstpage}{% \renewcommand{\@oddhead}{<letterhead goes here>}% @@ -751,17 +596,16 @@ And that's it! \subsection{Example: a newsletter class} A simple newsletter can be typeset with \LaTeX{}, using a variant of the -|article| class. -The class begins by announcing itself as |smplnews.cls|. +|article| class. The class begins by announcing itself as |smplnews.cls|. \begin{verbatim} \NeedsTeXFormat{LaTeX2e} - \ProvidesClass{smplnews}[1995/04/01 The Simple News newsletter class] + \ProvidesClass{smplnews}[2022-06-01 The Simple News newsletter class] \newcommand{\headlinecolor}{\normalcolor} \end{verbatim} -It passes most specified options on to the |article| class: apart from -the |onecolumn| option, which is switched off, and the |green| option, -which sets the headline in green. +It passes most specified options on to the |article| class: apart from the +|onecolumn| option, which is switched off, and the |green| option, which sets +the headline in green. \begin{verbatim} \DeclareOption{onecolumn}{\OptionNotUsed} \DeclareOption{green}{\renewcommand{\headlinecolor}{\color{green}}} @@ -774,14 +618,14 @@ It then loads the class |article| with the option |twocolumn|. \begin{verbatim} \LoadClass[twocolumn]{article} \end{verbatim} -Since the newsletter is to be printed in colour, it now loads the -|color| package. The class does not specify a device driver option -since this should be specified by the user of the |smplnews| class. +Since the newsletter is to be printed in colour, it now loads the |color| +package. The class does not specify a device driver option since this should be +specified by the user of the |smplnews| class. \begin{verbatim} \RequirePackage{color} \end{verbatim} -The class then redefines |\maketitle| to produce the title in 72pt -Helvetica bold oblique, in the appropriate colour. +The class then redefines |\maketitle| to produce the title in 72\,pt Helvetica +bold oblique, in the appropriate colour. \begin{verbatim} \renewcommand{\maketitle}{% \twocolumn[% @@ -807,90 +651,91 @@ It also sets the three essential things. \setlength{\textwidth}{17.5cm} \setlength{\textheight}{25cm} \end{verbatim} -In practice, a class would need more than this: it would provide -commands for issue numbers, authors of articles, page styles and so -on; but this skeleton gives a start. The |ltnews| class file is not -much more complex than this one. +In practice, a class would need more than this: it would provide commands for +issue numbers, authors of articles, page styles and so on; but this skeleton +gives a start. The |ltnews| class file is not much more complex than this one. \section{Commands for class and package writers} \label{Sec:commands} -This section describes briefly each of the new commands for class and -package writers. To find out about other aspects of the new system, +This section describes briefly each of the commands for class and package +writers. To find out about other aspects of the system, you should also read \emph{\LaTeXbook}, \emph{\LaTeXcomp} and \emph{\usrguide}. \subsection{Identification} -The first group of commands discussed here are those used -to identify your class or package file. +The first group of commands discussed here are those used to identify your +class or package file. \begin{decl} |\NeedsTeXFormat| \arg{format-name} \oarg{release-date} \end{decl} -This command tells \TeX{} that this file should be processed using a -format with name \m{format-name}. You can use the optional argument -\m{release-date} to further specify the earliest release date of the -format that is needed. When the release date of the format is older -than the one specified a warning will be generated. The standard -\m{format-name} is \texttt{LaTeX2e}. The date, if present, must be in -the form \textsc{yyyy/mm/dd}. +This command tells \TeX{} that this file should be processed using a format +with name \m{format-name}. You can use the optional argument \m{release-date} +to further specify the earliest release date of the format that is needed. When +the release date of the format is older than the one specified a warning will +be generated. The standard \m{format-name} is \texttt{LaTeX2e}. The date, if +present, must be in the form \textsc{yyyy-mm-dd}. Example: \begin{verbatim} - \NeedsTeXFormat{LaTeX2e}[1994/06/01] + \NeedsTeXFormat{LaTeX2e}[2022-06-01] \end{verbatim} +People often don't know what date to put here. For the kernel, you can find out +the right one by consulting |changes.txt| and select the release date of a new +feature you are interested in. This is slightly different for packages as they +are released throughout the year: you will need to consult their change +history. \begin{decl} |\ProvidesClass| \arg{class-name} \oarg{release-info} \\ |\ProvidesPackage| \arg{package-name} \oarg{release-info} \end{decl} -This declares that the current file contains the definitions for the -document class \m{class-name} or package \m{package-name}. +This declares that the current file contains the definitions for the document +class \m{class-name} or package \m{package-name}. The optional \m{release-info}, if used, must contain: \begin{itemize} - \item the release date of - this version of the file, in the form \textsc{yyyy/mm/dd}; + \item the release date of this version of the file, in the form + \textsc{yyyy-mm-dd}; \item optionally followed by a space and a short description, possibly including a version number. \end{itemize} -The above syntax must be followed exactly so that this information -can be used by |\LoadClass| or |\documentclass| (for classes) or -|\RequirePackage| or |\usepackage| (for packages) to test that the -release is not too old. +The above syntax must be followed exactly so that this information can be used +by |\LoadClass| or |\documentclass| (for classes) or |\RequirePackage| or +|\usepackage| (for packages) to test that the release is not too old. -The whole of this \m{release-info} information is displayed by -|\listfiles| and should therefore not be too long. +The whole of this \m{release-info} information is displayed by |\listfiles| and +should therefore not be too long. Example: \begin{verbatim} - \ProvidesClass{article}[1994/06/01 v1.0 Standard LaTeX class] - \ProvidesPackage{ifthen}[1994/06/01 v1.0 Standard LaTeX package] + \ProvidesClass{article}[2022-06-01 v1.0 Standard LaTeX class] + \ProvidesPackage{ifthen}[2022-06-01 v1.0 Standard LaTeX package] \end{verbatim} \begin{decl} |\ProvidesFile| \arg{file-name} \oarg{release-info} \end{decl} This is similar to the two previous commands except that here the full -filename, including the extension, must be given. It is used for -declaring any files other than main class and package files. +filename, including the extension, must be given. It is used for declaring any +files other than main class and package files. Example: \begin{verbatim} - \ProvidesFile{T1enc.def}[1994/06/01 v1.0 Standard LaTeX file] + \ProvidesFile{T1enc.def}[2022-06-01 v1.0 Standard LaTeX file] \end{verbatim} -Note that the phrase \texttt{Standard LaTeX} \textbf{must not} be used -in the identification banner of any file other than those in the -standard \LaTeX{} distribution. +Note that the phrase \texttt{Standard LaTeX} \textbf{must not} be used in the +identification banner of any file other than those in the standard \LaTeX{} +distribution. \subsection{Loading files} \label{Sec:loadf} -\NEWfeature{1995/12/01} -This group of commands can be used to create your own document class or -package by building on existing classes or packages. +This group of commands can be used to create your own document class or package +by building on existing classes or packages. \begin{decl} |\RequirePackage| \oarg{options-list} \arg{package-name} \oarg{release-info}\\ @@ -899,13 +744,11 @@ package by building on existing classes or packages. \end{decl} Packages and classes should use these commands to load other packages. -The use of |\RequirePackage| is the same as the author command -|\usepackage|. - +The use of |\RequirePackage| is the same as the author command |\usepackage|. Examples: \begin{verbatim} - \RequirePackage{ifthen}[1994/06/01] - \RequirePackageWithOptions{graphics}[1995/12/01] + \RequirePackage{ifthen}[2022-06-01] + \RequirePackageWithOptions{graphics}[2022-06-01] \end{verbatim} \begin{decl} @@ -914,107 +757,153 @@ Examples: |\LoadClassWithOptions| \arg{class-name} \oarg{release-info} \end{decl} -\NEWfeature{1995/12/01} -These commands are for use \emph{only} in class files, they cannot be -used in packages files; -they can be used at most once within a class file. +These commands are for use \emph{only} in class files, they cannot be used in +packages files; they can be used at most once within a class file. -The use of |\LoadClass| is the same as -the use of |\documentclass| to load a class file. +The use of |\LoadClass| is the same as the use of |\documentclass| to load a +class file. Examples: \begin{verbatim} - \LoadClass{article}[1994/06/01] - \LoadClassWithOptions{article}[1995/12/01] + \LoadClass{article}[2022-06-01] + \LoadClassWithOptions{article}[2022-06-01] \end{verbatim} -\NEWfeature{1995/12/01} -The two |WithOptions| versions simply load the class (or package) file -with exactly those options that are being used by the current file -(class or package). See below, in \ref{Sec:opmove}, for further -discussion of their use. - +The two |WithOptions| versions simply load the class (or package) file with +exactly those options that are being used by the current file (class or +package). See below, in \ref{Sec:opmove}, for further discussion of their use. -\subsection{Option declaration} -\label{Sec:commands.options.dec} +\subsection{Delaying code} +\label{Sec:delays} -\NEWdescription{1998/12/01} -The following commands deal with the declaration and handling of -options to document classes and packages. Every option name must be a -`\LaTeX{} name'. +As noted earlier, a sophisticated hook system is available and described in +\texttt{lthooks}. Here, we document a small set of convenient short names for +common hooks. -There are some commands designed especially for use within the -\m{code} argument of these commands (see below). +These first two commands are also intended primarily for use within the +\m{code} argument of |\DeclareOption| or |\DeclareOption*|. \begin{decl} - |\DeclareOption| \arg{option-name} \arg{code} + |\AtEndOfClass| \arg{code}\\ + |\AtEndOfPackage| \arg{code} \end{decl} -This makes \m{option-name} a `declared option' of the class or package -in which it is put. - -The \m{code} argument contains the code to be executed if that option -is specified for the class or package; it can contain any valid -\LaTeXe{} construct. +These commands declare \m{code} that is saved away internally and then executed +after processing the whole of the current class or package file. -Example: -\begin{verbatim} - \DeclareOption{twoside}{\@twosidetrue} -\end{verbatim} +Repeated use of these commands is permitted: the code in the arguments is +stored (and later executed) in the order of their declarations. \begin{decl} - |\DeclareOption*| \arg{code} + |\AtBeginDocument| \arg{code}\\ + |\AtEndDocument| \arg{code} \end{decl} -This declares the \m{code} to be executed for every option which is -specified for, but otherwise not explicitly declared by, the class or -package; this code is called the `default option code' and it can -contain any valid \LaTeXe{} construct. +These commands declare \m{code} to be saved internally and executed while +\LaTeX{} is executing |\begin{document}| or |\end{document}|. -If a class file contains no |\DeclareOption*| then, by default, all -specified but undeclared options for that class will be silently -passed to all packages (as will the specified and declared options for -that class). +The \m{code} specified in the argument to |\AtBeginDocument| is executed near +the end of the |\begin{document}| code, \emph{after} the font selection tables +have been set up. It is therefore a useful place to put code which needs to be +executed after everything has been prepared for typesetting and when the normal +font for the document is the current font. -If a package file contains no |\DeclareOption*| then, by default, each -specified but undeclared option for that package will produce an error. +The |\AtBeginDocument| hook should not be used for code that does any +typesetting since the typeset result would be unpredictable. +The \m{code} specified in the argument to |\AtEndDocument| is executed at the +beginning of the |\end{document}| code, \emph{before} the final page is +finished and before any leftover floating environments are processed. If some +of the \m{code} is to be executed after these two processes, you should include +a |\clearpage| at the appropriate point in \m{code}. -\subsection{Commands within option code} -\label{Sec:within.code} +Repeated use of these commands is permitted: the code in the arguments is +stored (and later executed) in the order of their declarations. + +\subsection{Creating and using keyval options} +\label{Sec:opt:keyval} -These two commands can be used only within the \m{code} argument of -either |\DeclareOption| or |\DeclareOption*|. Other commands commonly -used within these arguments can be found in the next few subsections. +As with any key--value input, using key--value pairs as package or class +options has two parts: creating the key options and setting (using) them. +Options created in this way \emph{may} be used after package loading as general +key--value settings: this will depend on the nature of the underlying code. \begin{decl} - |\CurrentOption| + |\DeclareKeys| \oarg{family} \arg{declarations} \end{decl} -This expands to the name of the current option. +This command creates a series of options from a comma-separated +\m{declarations} list. Each entry in this list is a key--value pair, with the +\m{key} having one or more \m{properties}. A small number of `basic' +\m{properties} are described below. The full range of properties, provided by +\texttt{l3keys}, can also be used for more powerful processing. See +\texttt{interface3} for the full details. + +The basic properties provided here are +\begin{itemize} + \item \texttt{.code} --- execute arbitrary code + \item \texttt{.if} --- sets a \TeX{} |\if...| switch + \item \texttt{.ifnot} --- sets an inverted \TeX{} |\if...| switch + \item \texttt{.store} --- stores a value in a macro + \item \texttt{.usage} -- defines whether the option can be given only + when loading (\texttt{load}), in the preamble (\texttt{preamble}) or + has no limitation on scope (\texttt{general}) +\end{itemize} +The part of the \meta{key} before the \m{property} is the \m{name}, with the +\m{value} working with the \m{property} to define the behaviour of the option. + +For example, with +\begin{verbatim} +\DeclareKeys[mypkg] + { + draft.if = @mypkg@draft , + draft.usage = preamble , + name.store = \@mypkg@name , + name.usage = load , + second-name.store = \@mypkg@other@name + } +\end{verbatim} +three options would be created. The option \texttt{draft} can be given anywhere +in the preamble, and will set a switch called |\if@mypkg@draft|. The option +\texttt{name} can only be given during package loading, and will save whatever +value it is given in |\@mypkg@name|. Finally, the option \texttt{second-name} +can be given anywhere, and will save its value in |\@mypkg@other@name|. + +Keys created \emph{before} the use of |\ProcessKeyOptions| act as package +options. \begin{decl} - |\OptionNotUsed| + |\DeclareUnknownKeyHandler| \oarg{family} \arg{code} \end{decl} -This causes the current option to -be added to the list of `unused options'. +The command |\DeclareUnknownKeyHandler| may be used to define the behavior when +an undefined key is encountered. The \m{code} will receive the unknown key name +as |#1| and the value as |#2|. These can then be processed as appropriate, +e.g.~by forwarding to another package. -\NEWfeature{1995/06/01} - You can now include hash marks (\texttt{\#}) within these \m{code} - arguments without special treatment (formerly, it had been - necessary to double them). +\begin{decl} + |\ProcessKeyOptions| \oarg{family} +\end{decl} +The |\ProcessKeyOptions| function is used to check the current option list +against the keys defined for \m{family}. Global (class) options and local +(package) options are checked when this function is called in a package. -\subsection{Moving options around} +\begin{decl} + |\SetKeys| \oarg{family} \arg{keyvals} +\end{decl} +Sets (applies) the explicit list of \m{keyvals} for the \m{family}: if the +latter is not given, the value of |\@currname| is used. This command may be used +within a package to set options before or after using |\ProcessKeyOptions|. + +\subsection{Passing options around} \label{Sec:opmove} -These two commands are also very useful within the \m{code} argument -of |\DeclareOption| or |\DeclareOption*|: +These two commands are also very useful within the \m{code} argument of +options. \begin{decl} |\PassOptionsToPackage| \arg{options-list} \arg{package-name}\\ |\PassOptionsToClass| \arg{options-list} \arg{class-name} \end{decl} -The command |\PassOptionsToPackage| passes the option names in -\m{options-list} to package \m{package-name}. -This means that it adds the \m{option-list} to the -list of options used by any future |\RequirePackage| or |\usepackage| -command for package \m{package-name}. +The command |\PassOptionsToPackage| passes the option names in \m{options-list} +to package \m{package-name}. This means that it adds the \m{option-list} to the +list of options used by any future |\RequirePackage| or |\usepackage| command +for package \m{package-name}. Example: \begin{verbatim} @@ -1026,24 +915,22 @@ is the same as: \RequirePackage[foo,bar,baz]{fred} \end{verbatim} -Similarly, |\PassOptionsToClass| may be used in a class file to pass -options to another class to be loaded with |\LoadClass|. +Similarly, |\PassOptionsToClass| may be used in a class file to pass options to +another class to be loaded with |\LoadClass|. -\NEWdescription{1995/12/01} -The effects and use of these two commands should be contrasted with -those of the following two (documented above, in \ref{Sec:loadf}): +The effects and use of these two commands should be contrasted with those of +the following two (documented above, in \ref{Sec:loadf}): \begin{verbatim} \LoadClassWithOptions \RequirePackageWithOptions \end{verbatim} -The command |\RequirePackageWithOptions| is similar to -|\RequirePackage|, but it always loads the required package with -exactly the same option list as that being used by the current class -or package, rather than with any option explicitly supplied or passed -on by |\PassOptionsToPackage|. +The command |\RequirePackageWithOptions| is similar to |\RequirePackage|, but +it always loads the required package with exactly the same option list as that +being used by the current class or package, rather than with any option +explicitly supplied or passed on by |\PassOptionsToPackage|. -The main purpose of |\LoadClassWithOptions| is to allow one class to -simply build on another, for example: +The main purpose of |\LoadClassWithOptions| is to allow one class to simply +build on another, for example: \begin{verbatim} \LoadClassWithOptions{article} \end{verbatim} @@ -1053,12 +940,11 @@ This should be compared with the slightly different construction \ProcessOptions\relax \LoadClass{article} \end{verbatim} -As used above, the effects are more or less the same, but the first is -a lot less to type; also the |\LoadClassWithOptions| method runs -slightly quicker. +As used above, the effects are more or less the same, but the first is a lot +less to type; also the |\LoadClassWithOptions| method runs slightly quicker. -If, however, the class declares options of its own then -the two constructions are different. Compare, for example: +If, however, the class declares options of its own then the two constructions +are different. Compare, for example: \begin{verbatim} \DeclareOption{landscape}{\@landscapetrue} \ProcessOptions\relax @@ -1071,255 +957,56 @@ with: \ProcessOptions\relax \LoadClass{article} \end{verbatim} -In the first example, the \textsf{article} class will be loaded with -option |landscape| precisely when the current class is called with -this option. By contrast, in the second example it will never be -called with option \texttt{landscape} as in that case \textsf{article} -is passed options only by the default option handler, but this handler -is not used for |landscape| because that option is explicitly -declared. - -\subsection{Delaying code} -\label{Sec:delays} - -These first two commands are also intended primarily for use within -the \m{code} argument of |\DeclareOption| or |\DeclareOption*|. - -\begin{decl} - |\AtEndOfClass| \arg{code}\\ - |\AtEndOfPackage| \arg{code} -\end{decl} -These commands declare \m{code} that is saved away internally and then -executed after processing the whole of the current class or package -file. - -Repeated use of these commands is permitted: the code in the -arguments is stored (and later executed) in the order of their -declarations. - -\begin{decl} - |\AtBeginDocument| \arg{code}\\ - |\AtEndDocument| \arg{code} -\end{decl} -These commands declare \m{code} to be saved internally and executed -while \LaTeX{} is executing |\begin{document}| or |\end{document}|. - -The \m{code} specified in the argument to |\AtBeginDocument| is -executed near the end of the |\begin{document}| code, \emph{after} the -font selection tables have been set up. It is therefore a useful -place to put code which needs to be executed after everything has been -prepared for typesetting and when the normal font for the document is -the current font. - -\NEWdescription{1995/12/01} -The |\AtBeginDocument| hook should not be used for code that does any -typesetting since the typeset result would be unpredictable. - -The \m{code} specified in the argument to |\AtEndDocument| is -executed at the beginning of the |\end{document}| code, -\emph{before} the final page is finished and before any leftover -floating environments are processed. If some of the \m{code} is to be -executed after these two processes, you should include a |\clearpage| -at the appropriate point in \m{code}. - -Repeated use of these commands is permitted: the code in the -arguments is stored (and later executed) in the order of their -declarations. - -\begin{decl}[1994/12/01] - |\AtBeginDvi| \arg{specials} -\end{decl} -These commands save in a box register things which are written to the -|.dvi| file at the beginning of the `shipout' of the first page of the -document. - -This should not be used for anything that will add any typeset -material to the |.dvi| file. - -Repeated use of this command is permitted. - - -\subsection{Option processing} -\label{Sec:commands.options} - -\begin{decl} - |\ProcessOptions| -\end{decl} -This command executes the \m{code} for each selected option. - -We shall first describe how |\ProcessOptions| works in a package file, -and then how this differs in a class file. - -To understand in detail what |\ProcessOptions| does in a package file, -you have to know the difference between \emph{local} and \emph{global} -options. -\begin{itemize} -\item \textbf{Local options} are those which have been explicitly - specified for this particular package in the \m{options} argument of - any of these: -\begin{quote} - |\PassOptionsToPackage{<options>}| \ |\usepackage[<options>]|\\ - |\RequirePackage[<options>]| -\end{quote} -\item \textbf{Global options} are any other options that are specified - by the author in the \m{options} argument of - |\documentclass[<options>]|. -\end{itemize} -For example, suppose that a document begins: -\begin{verbatim} - \documentclass[german,twocolumn]{article} - \usepackage{gerhardt} -\end{verbatim} -whilst package |gerhardt| calls package |fred| with: -\begin{verbatim} - \PassOptionsToPackage{german,dvips,a4paper}{fred} - \RequirePackage[errorshow]{fred} -\end{verbatim} -then: -\begin{itemize} -\item |fred|'s local options are |german|, |dvips|, |a4paper| - and |errorshow|; -\item |fred|'s only global option is |twocolumn|. -\end{itemize} - -When |\ProcessOptions| is called, the following happen. -\begin{itemize} -\item \emph{First}, for each option so far declared in |fred.sty| - by |\DeclareOption|, it looks to see if that option is either a - global or a local option for |fred|: if it is then the corresponding - code is executed. - - This is done in the order in which these options - were declared in |fred.sty|. -\item \emph{Then}, for each remaining \emph{local} option, the command - |\ds@<option>| is executed if it has been defined somewhere (other - than by a |\DeclareOption|); otherwise, the `default option code' is - executed. If no default option code has been declared then an error - message is produced. - - This is done in the order in which these - options were specified. -\end{itemize} -Throughout this process, the system ensures that the code declared for -an option is executed at most once. - -Returning to the example, if |fred.sty| contains: -\begin{verbatim} - \DeclareOption{dvips}{\typeout{DVIPS}} - \DeclareOption{german}{\typeout{GERMAN}} - \DeclareOption{french}{\typeout{FRENCH}} - \DeclareOption*{\PackageWarning{fred}{Unknown `\CurrentOption'}} - \ProcessOptions\relax -\end{verbatim} -then the result of processing this document will be: -\begin{verbatim} - DVIPS - GERMAN - Package fred Warning: Unknown `a4paper'. - Package fred Warning: Unknown `errorshow'. -\end{verbatim} -Note the following: - -\begin{itemize} -\item the code for the |dvips| option is executed before that for the - |german| option, because that is the order in which they are declared - in |fred.sty|; -\item the code for the |german| option is executed only once, when the - declared options are being processed; -\item the |a4paper| and |errorshow| options produce the warning from - the code declared by |\DeclareOption*| (in the order in which they - were specified), whilst the |twocolumn| option does not: this is - because |twocolumn| is a global option. -\end{itemize} - -In a class file, |\ProcessOptions| works in the same way, except -that: \emph{all} options are local; and the default value for -|\DeclareOption*| is |\OptionNotUsed| rather than an error. - -\NEWdescription{1995/12/01} -Note that, because |\ProcessOptions| has a |*|-form, it is wise to -follow the non-star form with |\relax|, as in the previous examples, -since this prevents unnecessary look ahead and possibly misleading -error messages being issued. - -\begin{decl} - |\ProcessOptions*| \\ - |\@options| -\end{decl} -This is like |\ProcessOptions| but it executes the options in the -order specified in the calling commands, rather than in the order of -declaration in the class or package. For a package this means that the -global options are processed first. - -The |\@options| command from \LaTeX~2.09 has been made equivalent to -this in order to ease the task of updating old document styles to -\LaTeXe{} class files. - -\begin{decl} - |\ExecuteOptions| \arg{options-list} -\end{decl} - -For each option in the \m{options-list}, in order, -this command simply executes the command -|\ds@<option>| (if this command is not defined, then that option is -silently ignored). - -It can be used to provide a `default option list' just before -|\ProcessOptions|. For example, suppose that in a class file you want -to set up the default design to be: two-sided printing; 11pt fonts; -in two columns. Then it could specify: -\begin{verbatim} - \ExecuteOptions{11pt,twoside,twocolumn} -\end{verbatim} - +In the first example, the \textsf{article} class will be loaded with option +|landscape| precisely when the current class is called with this option. By +contrast, in the second example it will never be called with option |landscape| +as in that case \textsf{article} is passed options only by the default option +handler, but this handler is not used for |landscape| because that option is +explicitly declared. \subsection{Safe file commands} -These commands deal with file input; they ensure that the non-existence -of a requested file can be handled in a user-friendly way. +These commands deal with file input; they ensure that the non-existence of a +requested file can be handled in a user-friendly way. \begin{decl} |\IfFileExists| \arg{file-name} \arg{true} \arg{false} \end{decl} -If the file exists then the code specified in \m{true} is -executed. +If the file exists then the code specified in \m{true} is executed. -If the file does not exist then the code specified in \m{false} is -executed. +If the file does not exist then the code specified in \m{false} is executed. This command does \emph{not} input the file. \begin{decl} |\InputIfFileExists| \arg{file-name} \arg{true} \arg{false} \end{decl} -This inputs the file \m{file-name} if it exists and, immediately -before the input, the code specified in \m{true} is executed. +This inputs the file \m{file-name} if it exists and, immediately before the +input, the code specified in \m{true} is executed. -If the file does not exist then the code specified in \m{false} is -executed. +If the file does not exist then the code specified in \m{false} is executed. It is implemented using |\IfFileExists|. - \subsection{Reporting errors, etc} -These commands should be used by third party classes and packages to -report errors, or to provide information to authors. +These commands should be used by third party classes and packages to report +errors, or to provide information to authors. \begin{decl} |\ClassError| \arg{class-name} \arg{error-text} \arg{help-text}\\ |\PackageError| \arg{package-name} \arg{error-text} \arg{help-text} \end{decl} -These produce an error message. The \m{error-text} is displayed and the -|?| error prompt is shown. If the user types |h|, they will be shown -the \m{help-text}. +These produce an error message. The \m{error-text} is displayed and the |?| +error prompt is shown. If the user types |h|, they will be shown the +\m{help-text}. -Within the \m{error-text} and \m{help-text}: |\protect| can be used to -stop a command from expanding; |\MessageBreak| causes a line-break; -and |\space| prints a space. +Within the \m{error-text} and \m{help-text}: |\protect| can be used to stop a +command from expanding; |\MessageBreak| causes a line-break; and |\space| +prints a space. -Note that the \m{error-text} will have a full stop added to it, so do -not put one into the argument. +Note that the \m{error-text} will have a full stop added to it, so do not put +one into the argument. For example: \begin{verbatim} @@ -1354,96 +1041,22 @@ If the user types |h|, this will be shown: |\ClassInfo| \arg{class-name} \arg{info-text}\\ |\PackageInfo| \arg{package-name} \arg{info-text} \end{decl} -The four |Warning| commands are similar to the error commands, except -that they produce only a warning on the screen, with no error prompt. +The four |Warning| commands are similar to the error commands, except that they +produce only a warning on the screen, with no error prompt. -The first two, |Warning| versions, also show the line number where the -warning occurred, whilst the second two, |WarningNoLine| versions, do -not. +The first two, |Warning| versions, also show the line number where the warning +occurred, whilst the second two, |WarningNoLine| versions, do not. -The two |Info| commands are similar except that they log the -information only in the transcript file, including the line number. -There are no |NoLine| versions of these two. +The two |Info| commands are similar except that they log the information only +in the transcript file, including the line number. There are no |NoLine| +versions of these two. -Within the \m{warning-text} and \m{info-text}: |\protect| can be used to -stop a command from expanding; |\MessageBreak| causes a line-break; -and |\space| prints a space. -Also, these should not end with a full stop as one is +Within the \m{warning-text} and \m{info-text}: |\protect| can be used to stop a +command from expanding; |\MessageBreak| causes a line-break; and |\space| +prints a space. Also, these should not end with a full stop as one is automatically added. - -\subsection{Defining commands} -\label{Sec:commands.define} - -\LaTeXe{} provides some extra methods of (re)defining commands that are -intended for use in class and package files. - -\NEWfeature{1994/12/01} -The \texttt{*}-forms of these commands should be used to define -commands that are not, in \TeX{} terms, long. This can be useful for -error-trapping with commands whose arguments are not intended to -contain whole paragraphs of text. - -\begin{decl} - |\DeclareRobustCommand| \arg{cmd} \oarg{num} \oarg{default} - \arg{definition}\\ - |\DeclareRobustCommand*| \arg{cmd} \oarg{num} \oarg{default} - \arg{definition} -\end{decl} -This command takes the same arguments as |\newcommand| but it declares -a robust command, even if some code within the \m{definition} is -fragile. You can use this command to define new robust commands, or -to redefine existing commands and make them robust. A log is put into -the transcript file if a command is redefined. - -For example, if |\seq| is defined as follows: -\begin{verbatim} - \DeclareRobustCommand{\seq}[2][n]{% - \ifmmode - #1_{1}\ldots#1_{#2}% - \else - \PackageWarning{fred}{You can't use \protect\seq\space in text}% - \fi - } -\end{verbatim} -Then the command |\seq| can be used in moving arguments, even though -|\ifmmode| cannot, for example: -\begin{verbatim} - \section{Stuff about sequences $\seq{x}$} -\end{verbatim} - -Note also that there is no need to put a |\relax| before the -|\ifmmode| at the beginning of the definition; this is because the -protection given by this |\relax| against expansion at the wrong time -will be provided internally. - -\begin{decl} - |\CheckCommand| \arg{cmd} \oarg{num} \oarg{default} - \arg{definition}\\ - |\CheckCommand*| \arg{cmd} \oarg{num} \oarg{default} - \arg{definition} -\end{decl} -This takes the same arguments as |\newcommand| but, rather than define -\m{cmd}, it just checks that the current definition of \m{cmd} is -exactly as given by \m{definition}. An error is raised if these -definitions differ. - -This command is useful for checking the state of the system before -your package starts altering the definitions of commands. It allows -you to check, in particular, that no other package has redefined the -same command. - -\subsection{Moving arguments} - -\NEWdescription{1994/12/01} -The setting of protect whilst processing (i.e.~moving) moving arguments -has been reimplemented, as has the method of writing information from -the |.aux| file to other files such as the |.toc| file. Details can -be found in the file |ltdefns.dtx|. - -We hope that these changes will not affect many packages. - -\section{Miscellaneous commands, etc} +\section{Miscellaneous commands, etc.} \label{Sec:commands.misc} \subsection{Layout parameters} @@ -1452,78 +1065,25 @@ We hope that these changes will not affect many packages. |\paperheight|\\ |\paperwidth| \end{decl} -These two parameters are usually set by the class to be the size of -the paper being used. This should be actual paper size, unlike -|\textwidth| and |\textheight| which are the size of the main text -body within the margins. - +These two parameters are usually set by the class to be the size of the paper +being used. This should be actual paper size, unlike |\textwidth| and +|\textheight| which are the size of the main text body within the margins. \subsection{Case changing} \label{sec:case} \begin{decl} |\MakeUppercase| \arg{text} \\ - |\MakeLowercase| \arg{text} + |\MakeLowercase| \arg{text} \\ + |\MakeTitlecase| \arg{text} \end{decl} -\NEWfeature{1995/06/01} -\TeX{} provides two primitives |\uppercase| and |\lowercase| for -changing the case of text. These are sometimes used in document -classes, for example to set information in running heads in all -capitals. - -Unfortunately, these \TeX{} primitives do not change the case of -characters accessed by commands like |\ae| or |\aa|. To overcome this -problem, \LaTeX{} provides two new commands |\MakeUppercase| and -|\MakeLowercase| to do this. - -For example: -\begin{quotation} -\begin{tabular}{rl} - |\uppercase{aBcD\ae\AA\ss\OE}| & \uppercase{aBcD\ae\AA\ss\OE}\\ - |\lowercase{aBcD\ae\AA\ss\OE}| & \lowercase{aBcD\ae\AA\ss\OE}\\ - |\MakeUppercase{aBcD\ae\AA\ss\OE}| & - \MakeUppercase{aBcD\ae\AA\ss\OE}\\ - |\MakeLowercase{aBcD\ae\AA\ss\OE}| & \MakeLowercase{aBcD\ae\AA\ss\OE} -\end{tabular} -\end{quotation} - -The commands |\MakeUppercase| and |\MakeLowercase| themselves are -robust, but they have moving arguments. - -The commands use the \TeX{} primitives |\uppercase| and |\lowercase|, -and so have a number of unexpected `features'. In particular, they -change the case of everything (except characters in the names of -control-sequences) in their text argument: this includes mathematics, -environment names, and label names. - -For example: -\begin{verbatim} - \MakeUppercase{$x+y$ in \ref{foo}} -\end{verbatim} -produces $X+Y$ and the warning: -\begin{verbatim} - LaTeX Warning: Reference `FOO' on page ... undefined on ... -\end{verbatim} -In the long run, we would like to use all-caps fonts rather than any -command like |\MakeUppercase| but this is not possible at the moment -because such fonts do not exist. - -\NEWdescription{1995/12/01} -In order that upper/lower-casing will work reasonably well, and in -order to provide any correct hyphenation, \LaTeXe{} \emph{must} use, -throughout a document, the same fixed table for changing case. -The table used is designed for the font encoding |T1|; this works well -with the standard \TeX{} fonts for all Latin alphabets but will cause -problems when using other alphabets. - -\subsection{The `openany' option in the `book' class} - -\NEWdescription{1996/06/01} -The |openany| option allows chapter and similar openings to -occur on left hand pages. Previously this option affected only -|\chapter| and |\backmatter|. It now also affects -|\part|, |\frontmatter| and |\mainmatter|. +As described in \texttt{usrguide}, case changing for text should be carried out +using the commands |\MakeUppercase|, |\MakeLowercase| and +|\MakeTitlecase|. If you need to change the case of programmatic material, the +team strongly suggest using the L3 programming layer commands in the +\texttt{str} module. If you do not wish to do this, you should use the \TeX{} +|\uppercase| and |\lowercase| primitives \emph{in this situation only}. \subsection{Better user-defined math display environments} @@ -1531,11 +1091,8 @@ occur on left hand pages. Previously this option affected only |\ignorespacesafterend| \end{decl} -\NEWfeature{1996/12/01} -\NEWdescription{2003/12/01} -Suppose that you want to define an environment for displaying text -that is numbered as an equation. A straightforward way to do this is -as follows: +Suppose that you want to define an environment for displaying text that is +numbered as an equation. A straightforward way to do this is as follows: \begin{verbatim} \newenvironment{texteqn} {\begin{equation} @@ -1543,13 +1100,13 @@ as follows: {\end{minipage} \end{equation}} \end{verbatim} -However, if you have tried this then you will probably have noticed -that it does not work perfectly when used in the middle of a paragraph -because an inter-word space appears at the beginning of the first -line after the environment. +However, if you have tried this then you will probably have noticed that it +does not work perfectly when used in the middle of a paragraph because an +inter-word space appears at the beginning of the first line after the +environment. -There is now an extra command (with a very long name) available that -you can use to avoid this problem; it should be inserted as shown here: +You can avoid this problem using |\ignorespacesafterend|; it should be +inserted as shown here: \begin{verbatim} \newenvironment{texteqn} {\begin{equation} @@ -1567,312 +1124,298 @@ This command may also have other uses. |\normalsfcodes| \end{decl} -\NEWfeature{1997/06/01} This command should be used to restore the normal settings of the parameters that affect spacing between words, sentences, etc. -An important use of this feature is to correct a problem, reported by -Donald Arseneau, that punctuation in page headers has always (in all -known \TeX{} formats) been potentially wrong whenever a page break -happens while a local setting of the space codes is in effect. These -space codes are changed by, for example, the command -\verb|\frenchspacing|) and the \textsf{verbatim} environment. - -It is normally given the correct definition automatically in -|\begin{document}| and so need not be explicitly set; however, if it -is explicitly made nonempty in a class file then automatic -default setting will be over-ridden. - - -\section{Upgrading \LaTeX~2.09 classes and packages} -\label{Sec:upgrade} - -This section describes the changes you may need to make when you -upgrade an existing \LaTeX{} style to a package or class but we shall -start in optimistic mode. - -Many existing style files will run with \LaTeXe{} without any -modification to the file itself. When everything is running OK, -please put a note in the newly created package or class file to record -that it runs with the new standard \LaTeX{}; then distribute it to -your users. - -\subsection{Try it first!} -\label{Sec:try-it} - -The first thing you should do is to test your style in `compatibility -mode'. The only change you need to make in order to do this is, -possibly, to change the extension of the file to |.cls|: you should -make this change only if your file was used as a main document style. -Now, without any other modifications, run \LaTeXe{} on a document that -uses your file. This assumes that you have a suitable collection of -files that tests all the functionality provided by your style file. -(If you haven't, now is the time to make one!) - -You now need to change the test document files so that they are -\LaTeXe{} documents: see \emph{\usrguide} for details of how to do -this and then try them again. You have now tried the test documents -in both \LaTeXe{} native mode and \LaTeX~2.09 compatibility mode. - -\subsection{Troubleshooting} -\label{Sec:trouble} - -If your file does not work with \LaTeXe{}, there are two likely -reasons. +An important use of this feature is to correct a problem, reported by Donald +Arseneau, that punctuation in page headers has always (in all known \TeX{} +formats) been potentially wrong whenever a page break happens while a local +setting of the space codes is in effect. These space codes are changed by, for +example, the command \verb|\frenchspacing|) and the \textsf{verbatim} +environment. + +It is normally given the correct definition automatically in |\begin{document}| +and so need not be explicitly set; however, if it is explicitly made non-empty +in a class file then automatic default setting will be over-ridden. + +\subsection{Querying localisation} + +Localisation information is needed to customise a range of outputs. The +\LaTeX{} kernel does not itself manage localisation, which is well-served by +the bundles \pkg{babel} and \pkg{polyglossia}. To allow the kernel and other +packages to access the current localisation information provided by \pkg{babel} +or \pkg{polyglossia}, the command \cs{BCPdata} is defined by the kernel. The +initial kernel definition expands to tag parts for \texttt{en-US}, as the +kernel does not track localisation but does start out with a broadly US~English +setup. However, if \pkg{babel} or \pkg{polyglossia} are loaded, it is redefined +expand to the BCP-47 information from the appropriate package. The supported +arguments are the BCP-47 tag breakdowns: \begin{itemize} -\item \LaTeX{} now has a robust, well-defined designer's interface for - selecting fonts, which is very different from the \LaTeX~2.09 - internals. -\item Your style file may have used some \LaTeX~2.09 internal commands - which have changed, or which have been removed. + \item \texttt{tag} The full BCP-47 tag (e.g.~\texttt{en-US}) + \item \texttt{language} (e.g.,~\texttt{de}) + \item \texttt{region} (e.g.,~\texttt{AT}) + \item \texttt{script} (e.g.,~\texttt{Latn}) + \item \texttt{variant} (e.g.,~\texttt{1901}) + \item \texttt{extension.t} (transformation, e.g.,~\texttt{en-t-ja}) + \item \texttt{extension.u} (additional locale + information, e.g.,~\texttt{ar-u-nu-latn}) + \item \texttt{extension.x} (private use area, e.g.,~\texttt{la-x-classic}) \end{itemize} +The information for the \emph{main} language for a document is be provided +if these are prefixed by \texttt{main.}, e.g.~\texttt{main.language} will +expand to the main language even if another language is currently active. -When you are debugging your file, you will probably need more -information than is normally displayed by \LaTeXe. This is achieved -by resetting the counter |errorcontextlines| from its default value of -$-1$ to a much higher value, e.g.~999. - -\subsection{Accommodating compatibility mode} - -Sometimes an existing collection of \LaTeX~2.09 documents makes it -inconvenient or impossible to abandon the old commands entirely. -If this is the case, then it is possible to accommodate both conventions -by making special provision for documents processed in compatibility -mode. +In addition to the tag breakdown, the following semantic arguments are +supported +\begin{itemize} + \item \texttt{casing} The tag for case changing, e.g.~\texttt{el-x-iota} + could be selected rather than \texttt{el} to select a capital adscript + iota on uppercasing an \emph{ypogegrammeni} +\end{itemize} -\begin{decl} -|\if@compatibility| -\end{decl} -This switch is set when a document begins with |\documentstyle| rather -than |\documentclass|. Appropriate code can be supplied for either -condition, as follows: +For example, the case changing command \cs{MakeUppercase} is (conceptually) +defined as \begin{verbatim} - \if@compatibility - <code emulating LaTeX 2.09 behavior> - \else - <code suitable for LaTeX2e> - \fi +\ExpandArgs{e}\MakeUppercaseAux{\BCPdata{casing}}{#1} \end{verbatim} +where |#1| is the user input and the first argument to +\cs{MakeUppercaseAux} takes two arguments, the locale and input text. + +\section{Commands superseded for new material} +A small number of commands were introduced as part of \LaTeXe{} in the +mid-1990s, are widely used but have been superseded by more modern methods. +These are covered here as they are likely to be encountered routinely in +existing classes and packages. -\subsection{Font commands} +\subsection{Defining commands} -Some font and size commands are now defined by the document class -rather than by the \LaTeX{} kernel. If you are upgrading a -\LaTeX~2.09 document style to a class that does not load one of the -standard classes, then you will probably need to add definitions for -these commands. +The \texttt{*}-forms of these commands should be used to define +commands that are not, in \TeX{} terms, long. This can be useful for +error-trapping with commands whose arguments are not intended to +contain whole paragraphs of text. \begin{decl} - |\rm| |\sf| |\tt| |\bf| |\it| |\sl| |\sc| + |\DeclareRobustCommand| \arg{cmd} \oarg{num} \oarg{default} + \arg{definition}\\ + |\DeclareRobustCommand*| \arg{cmd} \oarg{num} \oarg{default} + \arg{definition} \end{decl} -None of these short-form font selection commands are defined in the -\LaTeXe{} kernel. They are defined by all the standard class files. - -If you want to define them in your class file, there are several -reasonable ways to do this. - -One possible definition is: -\begin{verbatim} - \newcommand{\rm}{\rmfamily} - ... - \newcommand{\sc}{\scshape} -\end{verbatim} -This would make the font commands orthogonal; for example -|{\bf\it text}| would produce bold italic, thus: \textbf{\textit{text}}. -It will also make them produce an error if used in math mode. +This command takes the same arguments as |\newcommand| but it declares a robust +command, even if some code within the \m{definition} is fragile. You can use +this command to define new robust commands, or to redefine existing commands +and make them robust. A log is put into the transcript file if a command is +redefined. -Another possible definition is: +For example, if |\seq| is defined as follows: \begin{verbatim} - \DeclareOldFontCommand{\rm}{\rmfamily}{\mathrm} - ... - \DeclareOldFontCommand{\sc}{\scshape}{\mathsc} + \DeclareRobustCommand{\seq}[2][n]{% + \ifmmode + #1_{1}\ldots#1_{#2}% + \else + \PackageWarning{fred}{You can't use \protect\seq\space in text}% + \fi + } \end{verbatim} -This will make |\rm| act like |\rmfamily| in text mode (see above) and -it will make |\rm| select the |\mathrm| math alphabet in math mode. - -Thus |${\rm math} = X + 1$| will produce `${\rm math} = X + 1$'. - -If you do not want font selection to be orthogonal then you can -follow the standard classes and define: +Then the command |\seq| can be used in moving arguments, even though +|\ifmmode| cannot, for example: \begin{verbatim} - \DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm} - ... - \DeclareOldFontCommand{\sc}{\normalfont\scshape}{\mathsc} + \section{Stuff about sequences $\seq{x}$} \end{verbatim} -This means, for example, that |{\bf\it text}| will produce medium -weight (rather than bold) italic, thus: \textit{text}. -\begin{decl} - |\normalsize| \\ - |\@normalsize| -\end{decl} -The command |\@normalsize| is retained for compatibility with -\LaTeX~2.09 packages which may have used its value; but redefining it -in a class file will have no effect since it is always reset to have -the same meaning as |\normalsize|. - -This means that classes \emph{must} now redefine |\normalsize| rather -than redefining |\@normalsize|; for example (a rather incomplete one): -\begin{verbatim} - \renewcommand{\normalsize}{\fontsize{10}{12}\selectfont} -\end{verbatim} -Note that |\normalsize| is defined by the \LaTeX{} kernel to be an -error message. +Note also that there is no need to put a |\relax| before the |\ifmmode| at the +beginning of the definition; this is because the protection given by this +|\relax| against expansion at the wrong time will be provided internally. \begin{decl} - |\tiny| |\footnotesize| |\small| |\large|\\ - |\Large| |\LARGE| |\huge| |\Huge| + |\CheckCommand| \arg{cmd} \oarg{num} \oarg{default} + \arg{definition}\\ + |\CheckCommand*| \arg{cmd} \oarg{num} \oarg{default} + \arg{definition} \end{decl} -None of these other `standard' size-changing commands are defined in -the kernel: each needs to be defined in a class file if you need it. -They are all defined by the standard classes. - -This means you should use |\renewcommand| for |\normalsize| and -|\newcommand| for the other size-changing commands. - +This takes the same arguments as |\newcommand| but, rather than define \m{cmd}, +it just checks that the current definition of \m{cmd} is exactly as given by +\m{definition}. An error is raised if these definitions differ. -\subsection{Obsolete commands} +This command is useful for checking the state of the system before your package +starts altering the definitions of commands. It allows you to check, in +particular, that no other package has redefined the same command. -Some packages will not work with \LaTeXe{}, normally because they relied -on an internal \LaTeX{} command which was never supported and has now -changed, or been removed. - -In many cases there will now be a robust, high-level means of -achieving what previously required low-level commands. Please consult -Section~\ref{Sec:commands} to see if you can now use the \LaTeXe{} -class and package writers commands. - -Also, of course, if your package or class redefined any of the kernel -commands (i.e.~those defined in the files |latex.tex|, |slitex.tex|, -|lfonts.tex|, |sfonts.tex|) then you will need to check it very -carefully against the new kernel in case the implementation has -changed or the command no longer exists in the \LaTeX2e{} kernel. +\subsection{Option declaration} +\label{Sec:commands.options.dec} -Too many of the internal commands of \LaTeX~2.09 have been -re-implemented or removed to be able to list them all here. You must -check any that you have used or changed. +The following commands deal with the declaration and handling of options to +document classes and packages using a classical `simple text' approach. Every +option name must be a `\LaTeX{} name'. -We shall, however, list some of the more important commands which are -no longer supported. +There are some commands designed especially for use within the \m{code} +argument of these commands (see below). \begin{decl} - |\tenrm| |\elvrm| |\twlrm| \dots\\ - |\tenbf| |\elvbf| |\twlbf| \dots\\ - |\tensf| |\elvsf| |\twlsf| \dots\\ - \qquad$\vdots$ + |\DeclareOption| \arg{option-name} \arg{code} \end{decl} -The (approximately) seventy internal commands of this form are no longer -defined. If your class or package uses them then \emph{please} -replace them with new font commands described in \emph{\fntguide}. +This makes \m{option-name} a `declared option' of the class or package in which +it is put. + +The \m{code} argument contains the code to be executed if that option is +specified for the class or package; it can contain any valid \LaTeXe{} +construct. -For example, the command |\twlsf| should be replaced by: +Example: \begin{verbatim} - \fontsize{12}{14}\normalfont\sffamily\selectfont + \DeclareOption{twoside}{\@twosidetrue} \end{verbatim} -Another possibility is to use the |rawfonts| package, described in -\emph{\usrguide}. - -Also, remember that many of the fonts preloaded by \LaTeX~2.09 -are no longer preloaded. - \begin{decl} - |\vpt| |\vipt| |\viipt| \dots + |\DeclareOption*| \arg{code} \end{decl} -These were the internal size-selecting commands in \LaTeX~2.09. -(They can still be used in \LaTeX~2.09 compatibility mode.) -Please use the command |\fontsize| instead: see \emph{\fntguide} for -details. +This declares the \m{code} to be executed for every option which is specified +for, but otherwise not explicitly declared by, the class or package; this code +is called the `default option code' and it can contain any valid \LaTeXe{} +construct. -For example, |\vpt| should be replaced by: -\begin{verbatim} - \fontsize{5}{6}\normalfont\selectfont -\end{verbatim} +If a class file contains no |\DeclareOption*| then, by default, all specified +but undeclared options for that class will be silently passed to all packages +(as will the specified and declared options for that class). + +If a package file contains no |\DeclareOption*| then, by default, each +specified but undeclared option for that package will produce an error. + +\subsection{Commands within option code} +\label{Sec:within.code} + +These two commands can be used only within the \m{code} argument of either +|\DeclareOption| or |\DeclareOption*|. Other commands commonly used within +these arguments can be found in the next few subsections. \begin{decl} - |\prm|, |\pbf|, |\ppounds|, |\pLaTeX| \dots + |\CurrentOption| \end{decl} -\LaTeX~2.09 used several commands beginning with |\p| in order to -provide `protected' commands. For example, |\LaTeX| was defined to be -|\protect\pLaTeX|, and |\pLaTeX| was defined to produce the \LaTeX{} -logo. This made |\LaTeX| robust, even though |\pLaTeX| was not. - -These commands have now been reimplemented using -|\DeclareRobustCommand| -(described in Section~\ref{Sec:commands.define}). -If your package redefined one of the |\p|-commands then you must -remove the redefinition and use |\DeclareRobustCommand| to redefine the -non-|\p| command. +This expands to the name of the current option. \begin{decl} -|\footheight|\\ -|\@maxsep|\\ -|\@dblmaxsep| + |\OptionNotUsed| \end{decl} -These parameters are not used by \LaTeXe{} so they have been removed, -except in \LaTeX~2.09 compatibility mode. Classes should no longer -set them. - -\begin{thebibliography}{1} +This causes the current option to be added to the list of `unused options'. -\bibitem{A-W:DEK91} -Donald~E. Knuth. -\newblock {\em The \TeX book}. -\newblock Addison-Wesley, Reading, Massachusetts, 1986. -\newblock Revised to cover \TeX3, 1991. - -\bibitem{A-W:LLa94} -Leslie Lamport. -\newblock {\em {\LaTeX:} A Document Preparation System}. -\newblock Addison-Wesley, Reading, Massachusetts, second edition, 1994. +\subsection{Option processing} +\label{Sec:commands.options} -\bibitem{A-W:MG2004} -Frank Mittelbach and Michel Goossens. -\newblock {\em The {\LaTeX} Companion second edition}. -\newblock With Johannes Braams, David Carlisle, and Chris Rowley. -\newblock Addison-Wesley, Reading, Massachusetts, 2004. +\begin{decl} + |\ProcessOptions| +\end{decl} +This command executes the \m{code} for each selected option. -\end{thebibliography} +We shall first describe how |\ProcessOptions| works in a package file, and then +how this differs in a class file. -\newpage -\thispagestyle{empty} +To understand in detail what |\ProcessOptions| does in a package file, you have +to know the difference between \emph{local} and \emph{global} options. +\begin{itemize} +\item \textbf{Local options} are those which have been explicitly + specified for this particular package in the \m{options} argument of + any of these: +\begin{quote} + |\PassOptionsToPackage{<options>}| \ |\usepackage[<options>]|\\ + |\RequirePackage[<options>]| +\end{quote} +\item \textbf{Global options} are any other options that are specified + by the author in the \m{options} argument of + |\documentclass[<options>]|. +\end{itemize} +For example, suppose that a document begins: +\begin{verbatim} + \documentclass[german,twocolumn]{article} + \usepackage{gerhardt} +\end{verbatim} +whilst package |gerhardt| calls package |fred| with: +\begin{verbatim} + \PassOptionsToPackage{german,dvips,a4paper}{fred} + \RequirePackage[errorshow]{fred} +\end{verbatim} +then: +\begin{itemize} +\item |fred|'s local options are |german|, |dvips|, |a4paper| + and |errorshow|; +\item |fred|'s only global option is |twocolumn|. +\end{itemize} -\section*{\LaTeXe{} Summary sheet: updating old styles} +When |\ProcessOptions| is called, the following happen. +\begin{itemize} +\item \emph{First}, for each option so far declared in |fred.sty| + by |\DeclareOption|, it looks to see if that option is either a + global or a local option for |fred|: if it is then the corresponding + code is executed. -Section references below are to \emph{\clsguide}. + This is done in the order in which these options + were declared in |fred.sty|. +\item \emph{Then}, for each remaining \emph{local} option, the command + |\ds@<option>| is executed if it has been defined somewhere (other + than by a |\DeclareOption|); otherwise, the `default option code' is + executed. If no default option code has been declared then an error + message is produced. -\begin{enumerate} + This is done in the order in which these + options were specified. +\end{itemize} +Throughout this process, the system ensures that the code declared for +an option is executed at most once. -\item Should it become a class or a package? - See Section~\ref{Sec:classorpkg} for how to answer this question. +Returning to the example, if |fred.sty| contains: +\begin{verbatim} + \DeclareOption{dvips}{\typeout{DVIPS}} + \DeclareOption{german}{\typeout{GERMAN}} + \DeclareOption{french}{\typeout{FRENCH}} + \DeclareOption*{\PackageWarning{fred}{Unknown `\CurrentOption'}} + \ProcessOptions\relax +\end{verbatim} +then the result of processing this document will be: +\begin{verbatim} + DVIPS + GERMAN + Package fred Warning: Unknown `a4paper'. + Package fred Warning: Unknown `errorshow'. +\end{verbatim} +Note the following: -\item If it uses another style file, then you will need to obtain an - updated version of this other file. Look at Section~\ref{Sec:loading} - for information on how to load other class and package files. +\begin{itemize} +\item the code for the |dvips| option is executed before that for the + |german| option, because that is the order in which they are declared + in |fred.sty|; +\item the code for the |german| option is executed only once, when the + declared options are being processed; +\item the |a4paper| and |errorshow| options produce the warning from + the code declared by |\DeclareOption*| (in the order in which they + were specified), whilst the |twocolumn| option does not: this is + because |twocolumn| is a global option. +\end{itemize} -\item Try it: see Section~\ref{Sec:try-it}. +In a class file, |\ProcessOptions| works in the same way, except that: +\emph{all} options are local; and the default value for |\DeclareOption*| is +|\OptionNotUsed| rather than an error. -\item It worked? Excellent, but there are probably still some things - you should change in order to make your file into a well-structured - \LaTeXe{} file that is both robust and portable. So you should now - read Section~\ref{Sec:writing}, especially~\ref{Sec:general}. You - will also find some useful examples in Section~\ref{Sec:structure}. +Note that, because |\ProcessOptions| has a |*|-form, it is wise to follow the +non-star form with |\relax|, as in the previous examples, since this prevents +unnecessary look ahead and possibly misleading error messages being issued. - If your file sets up new fonts, font-changing commands or symbols, - you should also read \emph{\fntguide}. +\begin{decl} + |\ProcessOptions*| +\end{decl} +This is like |\ProcessOptions| but it executes the options in the order +specified in the calling commands, rather than in the order of declaration in +the class or package. For a package this means that the global options are +processed first. -\item It did not work? There are three possibilities here: - \begin{itemize} - \item error messages are produced whilst reading your file; - \item error messages are produced whilst processing test documents; - \item there are no errors but the output is not as it should be. - \end{itemize} - Don't forget to check carefully for this last possibility. +\begin{decl} + |\ExecuteOptions| \arg{options-list} +\end{decl} - If you have got to this stage then you will need to read - Section~\ref{Sec:upgrade} to find the solutions that will make your - file work. -\end{enumerate} +It can be used to provide a `default option list' just before +|\ProcessOptions|. For example, suppose that in a class file you want to set up +the default design to be: two-sided printing; 11pt fonts; in two columns. Then +it could specify: +\begin{verbatim} + \ExecuteOptions{11pt,twoside,twocolumn} +\end{verbatim} \end{document} diff --git a/macros/latex/base/cmextra.ins b/macros/latex/base/cmextra.ins index a2befb3aef..0fa45183fc 100644 --- a/macros/latex/base/cmextra.ins +++ b/macros/latex/base/cmextra.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/cmfonts.fdd b/macros/latex/base/cmfonts.fdd index 477085eaef..af898e47b2 100644 --- a/macros/latex/base/cmfonts.fdd +++ b/macros/latex/base/cmfonts.fdd @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -67,7 +67,7 @@ %<*driver, > \ProvidesFile{cmfonts.drv} %</driver, > - [2022/07/10 v2.5l Standard LaTeX font definitions] + [2023/04/13 v2.5m Standard LaTeX font definitions] % %<*driver> \documentclass{ltxdoc} @@ -1048,8 +1048,10 @@ % \end{macrocode} % % \changes{v2.5j}{2019/12/16}{Provide substitutions for cmtt/bx/sl} +% \changes{v2.5m}{2023/04/13}{Add missing substitution for U/cmtt/bx/sl} % \begin{macrocode} %<+OT1cmtt>\DeclareFontShape{OT1}{cmtt}{bx}{sl} +%<+Ucmtt>\DeclareFontShape{U}{cmtt}{bx}{sl} %<-nowarn> {<->sub*cmtt/m/n}{} %<+nowarn> {<->ssub*cmtt/m/n}{} %<+OT1cmtt>\DeclareFontShape{OT1}{cmtt}{bx}{ui} diff --git a/macros/latex/base/cmfonts.ins b/macros/latex/base/cmfonts.ins index 55af4759c5..af5ac7e5f8 100644 --- a/macros/latex/base/cmfonts.ins +++ b/macros/latex/base/cmfonts.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/cmfonts.pdf b/macros/latex/base/cmfonts.pdf Binary files differindex 01bd9f1fa2..e81f13eb78 100644 --- a/macros/latex/base/cmfonts.pdf +++ b/macros/latex/base/cmfonts.pdf diff --git a/macros/latex/base/cyrguide.pdf b/macros/latex/base/cyrguide.pdf Binary files differindex 6339438a02..2efa4eee4d 100644 --- a/macros/latex/base/cyrguide.pdf +++ b/macros/latex/base/cyrguide.pdf diff --git a/macros/latex/base/cyrguide.tex b/macros/latex/base/cyrguide.tex index 7304a586e4..394cd59e20 100644 --- a/macros/latex/base/cyrguide.tex +++ b/macros/latex/base/cyrguide.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -34,7 +34,7 @@ \author{\copyright~Copyright 1998--1999,\\ Vladimir Volovich, Werner Lemberg and \LaTeX\ Project Team.\\ All rights reserved.% - \footnote{This file may distributed and/or modified under the + \footnote{This file 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. See the source \texttt{cyrguide.tex} for full details.}% diff --git a/macros/latex/base/doc-code.pdf b/macros/latex/base/doc-code.pdf Binary files differindex 3b0c7bc965..9c17bbb77c 100644 --- a/macros/latex/base/doc-code.pdf +++ b/macros/latex/base/doc-code.pdf diff --git a/macros/latex/base/doc.dtx b/macros/latex/base/doc.dtx index d137038d63..75e04cc299 100644 --- a/macros/latex/base/doc.dtx +++ b/macros/latex/base/doc.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment % -% Copyright 1993-2022 -% The LaTeX3 Project and any individual authors listed elsewhere +% Copyright (C) 1993-2023 +% The LaTeX Project and any individual authors listed elsewhere % in this file. % % This file is part of the LaTeX base system. @@ -45,7 +45,7 @@ %<+package> %<+package>\ProvidesPackage{doc} %<+shortvrb>\ProvidesPackage{shortvrb} -%<+package|shortvrb> [2022/07/03 v3.0k +%<+package|shortvrb> [2022/11/13 v3.0m %<+package|shortvrb> Standard LaTeX documentation package V3 (FMi)] %\catcode`\<=12 % @@ -82,6 +82,8 @@ % \changes{v1.9a}{1993/12/02}{Upgrade for LaTeX2e} % \changes{v1.9d}{1993/12/20}{Protected changes entry.} % \changes{v1.0p}{1994/05/21}{Use new error commands} +% \changes{v3.0m}{2022/11/13}{Redefinitions of \cs{verb} removed as +% no longer needed (gh/953)} % % % \hyphenation{make-index} @@ -1208,7 +1210,7 @@ % not to exceed this limit when describing the change. The actual % entry consists of the \meta{version}, the |\actualchar|, the current % macro name, a colon, the |\levelchar|, and, finally, the \meta{text}. -% The result is a glossaryentry for the \meta{version}, with the name of +% The result is a glossary entry for the \meta{version}, with the name of % the current macro as subitem. Outside the |macro| environment, the % text |\generalname| is used instead of the macro name. When % referring to macros in change descriptions it is conventional to use @@ -1216,6 +1218,13 @@ % and using up valuable characters in the entry with old \prg{makeindex} % versions. % +% Note that in the history listing, the entry is shown with the page number +% that corresponds to its place in the source, e.g., general changes put at the +% very beginning of the file will show up with page number ``1'', change entries +% placed elsewhere might have different numbers (not necessarily always +% very useful unless you are careful). +% +% % \changes{v1.7a}{1992/02/26}{Description of \cs{RecordChanges} etc. % added % to interface section.} \DescribeInterfaceMacro\RecordChanges To cause the @@ -1824,8 +1833,8 @@ % July 1989. % \bibitem{art:docstrip} \textsc{Frank Mittelbach, Denys Duchier and % Johannes Braams}. -% \newblock \texttt{docstrip.dtx} (to appear). -% \newblock The file is part of the DOC package. +% \newblock \texttt{docstrip.dtx}. +% \newblock The file is part of core \LaTeX{}. % \bibitem{book:Raspe} \textsc{R. E. Raspe} (*1737, \dag 1797). % \newblock Baron Münchhausens narrative of his marvelous % travels and campaigns in Russia. @@ -2686,12 +2695,16 @@ % first lines are copied literally from \texttt{latex.tex}. % \changes{v1.7i}{1992/07/12}{Added \cs{@@par} to clear possible % \cs{parshape}.} +% \changes{v3.0m}{2022/11/13}{Redefinitions of \cs{@verbatim} changed +% to match the kernel definition (gh/953)} % \begin{macrocode} -\def\@verbatim{\trivlist \item[]\if@minipage\else\vskip\parskip\fi - \leftskip\@totalleftmargin\rightskip\z@ - \parindent\z@\parfillskip\@flushglue\parskip\z@ - \@@par - \@tempswafalse +\def\@verbatim{\trivlist \item\relax + \if@minipage\else\vskip\parskip\fi + \leftskip\@totalleftmargin\rightskip\z@ + \parindent\z@\parfillskip\@flushglue\parskip\z@ + \language\l@nohyphenation + \@@par + \@tempswafalse % \end{macrocode} % |\@verbatim| sets |^^M|, the end of line character, to % be equal to |\par|. This control sequence is redefined @@ -2699,8 +2712,13 @@ % \changes{v1.7c}{1992/03/24}{Added \cs{interlinepenalty} to % \cs{par} from verbatim.sty} % \begin{macrocode} - \def\par{\if@tempswa\hbox{}\fi\@tempswatrue\@@par - \penalty\interlinepenalty + \def\par{% + \if@tempswa + \leavevmode \null \@@par\penalty\interlinepenalty + \else + \@tempswatrue + \ifhmode\@@par\penalty\interlinepenalty\fi + \fi % \end{macrocode} % We add a control sequence |\check@percent| to the definition % of |\par| whose task it is to check for a percent character. @@ -2713,9 +2731,10 @@ % \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX verbatim, % which handles more ligatures.} % \begin{macrocode} - \obeylines - \let\do\do@noligs \verbatim@nolig@list - \let\do\@makeother \dospecials} + \let\do\@makeother \dospecials + \obeylines \verbatim@font \@noligs + \everypar \expandafter{\the\everypar \unpenalty}% +} % \end{macrocode} % \end{macro} % @@ -2744,83 +2763,12 @@ % \end{macrocode} % \end{macro} % -% \begin{imacro}{\verb} -% \changes{v1.7a}{1992/02/27}{Now warns about newlines (from -% newdoc with `@noligs added).} -% \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX \cs{verb}} -% We re-define |\verb| to check for newlines in its argument since a -% missing delimiter is difficult to detect in \DOC{} source. -% The code is the same as in \texttt{latex.tex} of September 19, 1993. -% Perhaps there should be a font-changing -% hook rather than just using |\ttfamily|, but if so it probably should be -% different from |\MacroFont| since that normally includes |\small| -% and would look wrong inline. -% \changes{v1.7a}{1992/02/28}{Added math mode check (from verbatim.sty)} -% \begin{macrocode} -\def\verb{\relax\ifmmode\hbox\else\leavevmode\null\fi - \bgroup \let\do\do@noligs \verbatim@nolig@list - \ttfamily \verb@eol@error \let\do\@makeother \dospecials - \@ifstar{\@sverb}{\@vobeyspaces \frenchspacing \@sverb}} -% \end{macrocode} -% \end{imacro} -% -% \begin{macro}{\verb@balance@group} -% \begin{macro}{\verb@egroup} -% \begin{macro}{\verb@eol@error} -% \changes{v1.8b}{1993/09/21}{Renamed \cs{verb@err} to -% \cs{verb@eol@error}, as in new LaTeX verbatim.} -% \begin{macrocode} -\let\verb@balance@group\@empty -% \end{macrocode} -% -% \begin{macrocode} -\def\verb@egroup{\global\let\verb@balance@group\@empty\egroup} -% \end{macrocode} -% -% \begin{macrocode} -\begingroup - \obeylines% - \gdef\verb@eol@error{\obeylines% - \def^^M{\verb@egroup\@latex@error{% - \noexpand\verb command ended by end of line}\@ehc}}% -\endgroup -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@sverb} -% \changes{v1.7a}{1992/02/27}{Added for \cs{verb} change.} -% \changes{v1.7a}{1992/02/28}{Now same as in verbatim.sty.} -% \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX verbatim, -% which has better error trapping.} -% See \cite{art:verbatim} for commentary. -% \changes{v2.1j}{2019/11/03}{Use the kernel definition, no change needed (gh/205)} -% \begin{macrocode} -%\def\@sverb#1{% -% \catcode`#1\active \lccode`\~`#1% -% \gdef\verb@balance@group{\verb@egroup -% \@latex@error{Illegal use of \noexpand\verb command}\@ehc}% -% \aftergroup\verb@balance@group -% \lowercase{\let~\verb@egroup}} -% \end{macrocode} -% \end{macro} -% % -% \begin{macro}{\verbatim@nolig@list} -% \begin{macro}{\do@noligs} -% These macros replace the old |\@noligs| mechanism by an -% extensible version to allow more ligatures to be added. -% \begin{macrocode} -\def\verbatim@nolig@list{\do\`\do\<\do\>\do\,\do\'\do\-} -\def\do@noligs#1{% - \catcode`#1\active - \begingroup - \lccode`\~=`#1\relax - \lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1}}} -% \end{macrocode} -% \end{macro} -% \end{macro} +% In the early versions of the package it also redefined \cs{verb} +% because that didn't include the useful test for \enquote{newline} in +% the verbatim text. This is nowadays part of \LaTeX{} so we do not +% redefine it any longer (the original code is still kept in the file +% after \cs{endinput} to keep the long history intact). % % \begin{tcounter}{\macro@cnt} % \label{page:macro} The \env{macro} environment is implemented as @@ -3147,9 +3095,6 @@ % % \begin{macro}{\short@macro} % -% \fmi{this needs cleaning up too, the results in the index are -% currently wrong for cases like `\cs{ }' and the like.} -% % \changes{v1.5c}{1989/04/27}{Corrected bad bug by putting the % scan@allowedfalse macro before printing % the argument.} @@ -3164,17 +3109,14 @@ % done by the |\ifnot@excluded| macro which assumes that the % macro name is saved in |\macro@namepart|. The character % mustn't be stored with a special category code or exclusion from -% the index won't work, so we employ the case-changing trick used -% elsewhere. Since the argument might be an active character, -% |\string| is used to normalize it. +% the index won't work, so we we use \cs{string} to normalize it +% the same way it is done in \cs{DoNotIndex}, i.e. everything ends up catcode 12 +% except for the space character. % \changes{v2.0e}{1998/12/28}{Correctly use the case-changing trick.} +% \changes{v3.0l}{2022/11/03}{No longer using the case-changing trick.} % \begin{macrocode} -\begingroup -\catcode`\&=12 -\gdef\short@macro#1{\begingroup - \uccode`\&=\expandafter`\string#1% - \uppercase{\def\x{\def\macro@namepart{&}}}% - \expandafter\endgroup\x +\def\short@macro#1{% + \edef\macro@namepart{\string#1}% % \end{macrocode} % Any indexing is then delegated to % |\maybe@index@short@macro|. Depending on the actual character seen, @@ -3197,7 +3139,6 @@ % cross-referencing is globally disabled. % \begin{macrocode} \scan@allowedtrue } -\endgroup % \end{macrocode} % \end{macro} % @@ -3441,7 +3382,6 @@ \def \ShowIndexingState { \__doc_trace:x{Show~ doc~ indexing~ state:} \seq_show:N \l__doc_donotindex_seq -% \tl_analysis_show:N\l__doc_donotindex_seq \prop_show:N \g__doc_idxtype_prop } % \end{macrocode} @@ -3637,10 +3577,12 @@ % \begin{macro}{\maybe@index@short@macro} % \begin{macro}{\__doc_maybe_index_short:o} % Single character macros are handled similarly but there the -% indexing is done by \cs{SpecialShortIndex}. +% indexing is done by \cs{SpecialShortIndex} and it is simpler +% because we know that the argument contains a string token not letters. +% \changes{v3.0l}{2022/11/03}{We know the argument expands to a single string token} % \begin{macrocode} \cs_new:Npn \__doc_maybe_index_short:o #1 { - \exp_args:Nf \__doc_maybe_index_aux:nN { \tl_to_str:o {#1} } + \exp_args:No \__doc_maybe_index_aux:nN #1 \SpecialShortIndex } \cs_set_eq:NN \maybe@index@short@macro \__doc_maybe_index_short:o @@ -3715,7 +3657,12 @@ {\cs_to_str:N \^^M } {\def\reserved@a{ \string \space \actualchar } \def\reserved@b { \space } \let\reserved@c \@empty } - { } {\def\reserved@a{ \string \space \actualchar } +% \end{macrocode} +% With the fix for +% \verb*=\ = we now have to look for a real space to handle that command sequence. +% \changes{v3.0l}{2022/11/03}{look for the right token} +% \begin{macrocode} + { ~ } {\def\reserved@a{ \string \space \actualchar } \def\reserved@b { \space } \let\reserved@c \@empty } {\c_left_brace_str} { \def\reserved@a{ \bgroup \actualchar } @@ -6256,6 +6203,89 @@ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \endinput +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +% \section{Code no longer used} +% +% \begin{imacro}{\verb} +% \changes{v1.7a}{1992/02/27}{Now warns about newlines (from +% newdoc with `@noligs added).} +% \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX \cs{verb}} +% We re-define |\verb| to check for newlines in its argument since a +% missing delimiter is difficult to detect in \DOC{} source. +% The code is the same as in \texttt{latex.tex} of September 19, 1993. +% Perhaps there should be a font-changing +% hook rather than just using |\ttfamily|, but if so it probably should be +% different from |\MacroFont| since that normally includes |\small| +% and would look wrong inline. +% \changes{v1.7a}{1992/02/28}{Added math mode check (from verbatim.sty)} +% \begin{macrocode} +%\def\verb{\relax\ifmmode\hbox\else\leavevmode\null\fi +% \bgroup \let\do\do@noligs \verbatim@nolig@list +% \ttfamily \verb@eol@error \let\do\@makeother \dospecials +% \@ifstar{\@sverb}{\@vobeyspaces \frenchspacing \@sverb}} +% \end{macrocode} +% \end{imacro} +% +% \begin{macro}{\verb@balance@group} +% \begin{macro}{\verb@egroup} +% \begin{macro}{\verb@eol@error} +% \changes{v1.8b}{1993/09/21}{Renamed \cs{verb@err} to +% \cs{verb@eol@error}, as in new LaTeX verbatim.} +% \begin{macrocode} +%\let\verb@balance@group\@empty +% \end{macrocode} +% +% \begin{macrocode} +%\def\verb@egroup{\global\let\verb@balance@group\@empty\egroup} +% \end{macrocode} +% +% \begin{macrocode} +%\begingroup +% \obeylines% +% \gdef\verb@eol@error{\obeylines% +% \def^^M{\verb@egroup\@latex@error{% +% \noexpand\verb command ended by end of line}\@ehc}}% +%\endgroup +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@sverb} +% \changes{v1.7a}{1992/02/27}{Added for \cs{verb} change.} +% \changes{v1.7a}{1992/02/28}{Now same as in verbatim.sty.} +% \changes{v1.8b}{1993/09/21}{Changed to conform to new LaTeX verbatim, +% which has better error trapping.} +% See \cite{art:verbatim} for commentary. +% \changes{v2.1j}{2019/11/03}{Use the kernel definition, no change needed (gh/205)} +% \begin{macrocode} +%\def\@sverb#1{% +% \catcode`#1\active \lccode`\~`#1% +% \gdef\verb@balance@group{\verb@egroup +% \@latex@error{Illegal use of \noexpand\verb command}\@ehc}% +% \aftergroup\verb@balance@group +% \lowercase{\let~\verb@egroup}} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\verbatim@nolig@list} +% \begin{macro}{\do@noligs} +% These macros replace the old |\@noligs| mechanism by an +% extensible version to allow more ligatures to be added. +% \begin{macrocode} +%\def\verbatim@nolig@list{\do\`\do\<\do\>\do\,\do\'\do\-} +%\def\do@noligs#1{% +% \catcode`#1\active +% \begingroup +% \lccode`\~`#1\relax +% \lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1}}} +% \end{macrocode} +% \end{macro} +% \end{macro} + ^^A Needed for emacs ^^A diff --git a/macros/latex/base/doc.pdf b/macros/latex/base/doc.pdf Binary files differindex 75e804a9c9..8c86a55630 100644 --- a/macros/latex/base/doc.pdf +++ b/macros/latex/base/doc.pdf diff --git a/macros/latex/base/docstrip.dtx b/macros/latex/base/docstrip.dtx index de20073c48..be373499e6 100644 --- a/macros/latex/base/docstrip.dtx +++ b/macros/latex/base/docstrip.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/docstrip.ins b/macros/latex/base/docstrip.ins index e2187594a4..79d4c429dd 100644 --- a/macros/latex/base/docstrip.ins +++ b/macros/latex/base/docstrip.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -52,7 +52,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/docstrip.pdf b/macros/latex/base/docstrip.pdf Binary files differindex 83739ec6b3..7b09dba511 100644 --- a/macros/latex/base/docstrip.pdf +++ b/macros/latex/base/docstrip.pdf diff --git a/macros/latex/base/ec.ins b/macros/latex/base/ec.ins index 47823e7edf..15a7c3848c 100644 --- a/macros/latex/base/ec.ins +++ b/macros/latex/base/ec.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/encguide.pdf b/macros/latex/base/encguide.pdf Binary files differindex 5ddc6f4fc9..c2da6210d8 100644 --- a/macros/latex/base/encguide.pdf +++ b/macros/latex/base/encguide.pdf diff --git a/macros/latex/base/encguide.tex b/macros/latex/base/encguide.tex index 3c95cf30cc..1a0978267e 100644 --- a/macros/latex/base/encguide.tex +++ b/macros/latex/base/encguide.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/exscale.dtx b/macros/latex/base/exscale.dtx index bc884c4db0..89890a4198 100644 --- a/macros/latex/base/exscale.dtx +++ b/macros/latex/base/exscale.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/exscale.ins b/macros/latex/base/exscale.ins index d202aad7cf..ae75460ee5 100644 --- a/macros/latex/base/exscale.ins +++ b/macros/latex/base/exscale.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/exscale.pdf b/macros/latex/base/exscale.pdf Binary files differindex 30af0ff0a7..d9bad62abf 100644 --- a/macros/latex/base/exscale.pdf +++ b/macros/latex/base/exscale.pdf diff --git a/macros/latex/base/fix-cm.dtx b/macros/latex/base/fix-cm.dtx index 5f8983ed34..9e39cd192b 100644 --- a/macros/latex/base/fix-cm.dtx +++ b/macros/latex/base/fix-cm.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/fix-cm.ins b/macros/latex/base/fix-cm.ins index b688cd66cf..68c6792412 100644 --- a/macros/latex/base/fix-cm.ins +++ b/macros/latex/base/fix-cm.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/fix-cm.pdf b/macros/latex/base/fix-cm.pdf Binary files differindex 5d8487c2ea..21479fe3cb 100644 --- a/macros/latex/base/fix-cm.pdf +++ b/macros/latex/base/fix-cm.pdf diff --git a/macros/latex/base/fntguide.pdf b/macros/latex/base/fntguide.pdf Binary files differindex d4c88762f4..b7570a411e 100644 --- a/macros/latex/base/fntguide.pdf +++ b/macros/latex/base/fntguide.pdf diff --git a/macros/latex/base/fntguide.tex b/macros/latex/base/fntguide.tex index 65467339f1..619cc907b2 100644 --- a/macros/latex/base/fntguide.tex +++ b/macros/latex/base/fntguide.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. @@ -42,17 +42,17 @@ \title{\LaTeXe{} font selection} -\author{\copyright~Copyright 1995--2022, \LaTeX\ Project +\author{\copyright~Copyright 1995--2023, \LaTeX\ Project Team.\thanks{Thanks to Arash Esbati for documenting the newer NFSS features of 2020}\\ All rights reserved.% - \footnote{This file may distributed and/or modified under the + \footnote{This file 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. See the source \texttt{fntguide.tex} for full details.}% } -\date{August 2022} +\date{May 2023} \begin{document} @@ -299,8 +299,6 @@ e.g., ``demi-bold'' is normally just another name for ``semi-bold'', so should get |sb| assigned, etc. -\newpage - \NEWdescription{2020/02/02} The most common values for the font shape are: \begin{center} @@ -325,7 +323,7 @@ A less common value for font shape is: \end{minipage} \end{center} and there is also |ui| for upright italic, i.e., an italic shape but -artifically turned upright. This is sometimes useful and available in +artificially turned upright. This is sometimes useful and available in some fonts. @@ -404,8 +402,6 @@ turned into \TeX{} font names. This is described in Section~\ref{Sec:install}. -\newpage - \subsection{Selection commands} @@ -955,7 +951,6 @@ Example: \DeclareMathSymbol{\alphld}{\mathalpha}{AMSb}{"0C} \end{verbatim} -\newpage \begin{decl} |\DeclareMathDelimiter| \arg{cmd} \arg{type} @@ -1382,7 +1377,7 @@ the `cmr' family). from this subsection. \NEWdescription{2019/07/10} -As an exception it may also contain a |\DeclareFontsubstitution| +As an exception it may also contain a |\DeclareFontSubstitution| declaration (described in \ref{sec:encoding-defaults}) to specify how font substitution for this encoding should be handled. In that case it is important that the values used point to a font that is guaranteed to @@ -1431,6 +1426,8 @@ executed whenever a math alphabet with this encoding is called. It also saves the value of \m{encoding} in the macro |\LastDeclaredEncoding|. +\newpage + Example: \begin{verbatim} \DeclareFontEncoding{OT1}{}{} @@ -1496,6 +1493,8 @@ For example, the definition of |\ss| in the |OT1| encoding is: It does not produce an error if the command has already been defined but logs the redefinition in the transcript file. +\newpage + \begin{decl} |\DeclareTextAccent| \arg{cmd} \arg{encoding} \arg{slot} \end{decl} @@ -1611,6 +1610,8 @@ defined with |\DeclareTextSymbol|. For more examples of these definitions, see |ltoutenc.dtx|. +\newpage + \begin{decl}[1994/12/01] |\ProvideTextCommandDefault| \arg{cmd} \arg{definition} \end{decl} @@ -2440,8 +2441,6 @@ become unavailable in the different sub-encodings. Again, the numbers are the slots in the |TS1| encoding, |acc| indicates a `constructed' accent. -\newpage - \begin{table}[!tbp] diff --git a/macros/latex/base/fontdef.dtx b/macros/latex/base/fontdef.dtx index 06af8feefd..5e88e55079 100644 --- a/macros/latex/base/fontdef.dtx +++ b/macros/latex/base/fontdef.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/format.ins b/macros/latex/base/format.ins index 369f01a7c5..74cd78ff4a 100644 --- a/macros/latex/base/format.ins +++ b/macros/latex/base/format.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. @@ -88,7 +88,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 2015-2022 +Copyright (C) 2015-2023 The LaTeX Project and any individual authors listed elsewhere in this file. @@ -123,7 +123,7 @@ extension .ins) which are part of the distribution. This is a generated file. -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/graphpap.dtx b/macros/latex/base/graphpap.dtx index 78bb688f83..6b7bc8b822 100644 --- a/macros/latex/base/graphpap.dtx +++ b/macros/latex/base/graphpap.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/graphpap.ins b/macros/latex/base/graphpap.ins index d82cbd6670..43ba83aae3 100644 --- a/macros/latex/base/graphpap.ins +++ b/macros/latex/base/graphpap.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/graphpap.pdf b/macros/latex/base/graphpap.pdf Binary files differindex d2385fa786..2460d68872 100644 --- a/macros/latex/base/graphpap.pdf +++ b/macros/latex/base/graphpap.pdf diff --git a/macros/latex/base/idx.tex b/macros/latex/base/idx.tex index bc0dd71021..04c8ef6959 100644 --- a/macros/latex/base/idx.tex +++ b/macros/latex/base/idx.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ifthen.dtx b/macros/latex/base/ifthen.dtx index d36042990d..aefc4a7666 100644 --- a/macros/latex/base/ifthen.dtx +++ b/macros/latex/base/ifthen.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ifthen.ins b/macros/latex/base/ifthen.ins index 88047e94f0..697a4a38b3 100644 --- a/macros/latex/base/ifthen.ins +++ b/macros/latex/base/ifthen.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/ifthen.pdf b/macros/latex/base/ifthen.pdf Binary files differindex 4802103db4..7437721f4d 100644 --- a/macros/latex/base/ifthen.pdf +++ b/macros/latex/base/ifthen.pdf diff --git a/macros/latex/base/inputenc.dtx b/macros/latex/base/inputenc.dtx index e056f8ffd7..02956a8c07 100644 --- a/macros/latex/base/inputenc.dtx +++ b/macros/latex/base/inputenc.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/inputenc.ins b/macros/latex/base/inputenc.ins index adacf9efce..3857827070 100644 --- a/macros/latex/base/inputenc.ins +++ b/macros/latex/base/inputenc.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/inputenc.pdf b/macros/latex/base/inputenc.pdf Binary files differindex 1ea351b1e7..4a7f1190f1 100644 --- a/macros/latex/base/inputenc.pdf +++ b/macros/latex/base/inputenc.pdf diff --git a/macros/latex/base/lablst.tex b/macros/latex/base/lablst.tex index 0821b0e4f0..b0a3ac1ab6 100644 --- a/macros/latex/base/lablst.tex +++ b/macros/latex/base/lablst.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/lamport-manual.pdf b/macros/latex/base/lamport-manual.pdf Binary files differindex 2d2e7d4f47..bf804f21a0 100644 --- a/macros/latex/base/lamport-manual.pdf +++ b/macros/latex/base/lamport-manual.pdf diff --git a/macros/latex/base/latex209.dtx b/macros/latex/base/latex209.dtx index 768f7237a5..b84564bb55 100644 --- a/macros/latex/base/latex209.dtx +++ b/macros/latex/base/latex209.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/latex209.ins b/macros/latex/base/latex209.ins index f530347a3c..0c90fa36ea 100644 --- a/macros/latex/base/latex209.ins +++ b/macros/latex/base/latex209.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/latexrelease.dtx b/macros/latex/base/latexrelease.dtx index 294007553d..4abde253e1 100644 --- a/macros/latex/base/latexrelease.dtx +++ b/macros/latex/base/latexrelease.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -40,7 +40,7 @@ %<*latexrelease> % \fi % \ProvidesFile{latexrelease.dtx} - [2022/02/28 v1.0o LaTeX release emulation and tests + [2022/11/14 v1.0p LaTeX release emulation and tests (including releases up to \latexreleaseversion)] % \iffalse %</latexrelease> @@ -746,8 +746,12 @@ of this package available from CTAN} % % Finally, redirect the error thrown by \cs{NewHook} to nowhere so it % can be safely reused (the hook isn't redeclared if it already exists). +% The same happens for \cs{NewMarkClass}. +% \changes{v1.0p}{2022/11/14} +% {Silence \cs{NewMarkClass} in rollback (gh/955)} % \begin{macrocode} \msg_redirect_name:nnn { hooks } { exists } { none } +\msg_redirect_name:nnn { mark } { class-already-defined }{ none } % \end{macrocode} % % Now a one-off for |ltcmd.dtx|: we need to make \cs{NewDocumentCommand} @@ -799,9 +803,12 @@ of this package available from CTAN} \tl_clear:N \l_@@_restores_tl % \end{macrocode} % -% And restore the hook error message. +% And restore the silenced error messages. +% \changes{v1.0p}{2022/11/14} +% {Unsilence \cs{NewMarkClass} error message after rollback (gh/955)} % \begin{macrocode} \msg_redirect_name:nnn { hooks } { exists } { } +\msg_redirect_name:nnn { mark } { class-already-defined } { } % \end{macrocode} % % \begin{macrocode} diff --git a/macros/latex/base/latexrelease.ins b/macros/latex/base/latexrelease.ins index b5e97a9479..61315f8e07 100644 --- a/macros/latex/base/latexrelease.ins +++ b/macros/latex/base/latexrelease.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/latexrelease.pdf b/macros/latex/base/latexrelease.pdf Binary files differindex 9ab51faa3b..e4217ba088 100644 --- a/macros/latex/base/latexrelease.pdf +++ b/macros/latex/base/latexrelease.pdf diff --git a/macros/latex/base/latexsym.dtx b/macros/latex/base/latexsym.dtx index 62fb097c0d..e4e1559e27 100644 --- a/macros/latex/base/latexsym.dtx +++ b/macros/latex/base/latexsym.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/latexsym.ins b/macros/latex/base/latexsym.ins index 468afddd67..12d658bca9 100644 --- a/macros/latex/base/latexsym.ins +++ b/macros/latex/base/latexsym.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. @@ -87,7 +87,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/latexsym.pdf b/macros/latex/base/latexsym.pdf Binary files differindex 8546f14f7d..aeb945867d 100644 --- a/macros/latex/base/latexsym.pdf +++ b/macros/latex/base/latexsym.pdf diff --git a/macros/latex/base/lb2.err b/macros/latex/base/lb2.err index 46958ae3a5..d2ea742f82 100644 --- a/macros/latex/base/lb2.err +++ b/macros/latex/base/lb2.err @@ -363,10 +363,15 @@ Bafög-Ausgabe (Softcover) die inhaltlich identisch ist: ) \end{verbatim} - \begin{list}{}{\setlength\leftmargin{0cm}\setlength\rightmargin{3cm}} \item[] +Beide Ausgaben sind nur noch antiquarisch erhältlich. Das englische +Original "`The \LaTeX{} Companion"' existiert in der dritten Ausgabe +(Erscheinungsdatum Mai 2023). + +\item[] + Diese Errata-Datei (\texttt{\jobname.err}) ist Teil der \LaTeX-Distribution und die neuste Version findet man auf der \LaTeX{} Project Webseite unter diff --git a/macros/latex/base/lb2.pdf b/macros/latex/base/lb2.pdf Binary files differindex c8f32233af..9913fca20c 100644 --- a/macros/latex/base/lb2.pdf +++ b/macros/latex/base/lb2.pdf diff --git a/macros/latex/base/letter.dtx b/macros/latex/base/letter.dtx index 4052c260c8..3e3c36d3d0 100644 --- a/macros/latex/base/letter.dtx +++ b/macros/latex/base/letter.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/letter.ins b/macros/latex/base/letter.ins index c078dc59ce..c522f39e59 100644 --- a/macros/latex/base/letter.ins +++ b/macros/latex/base/letter.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/letter.pdf b/macros/latex/base/letter.pdf Binary files differindex 51e1f40c55..b456935de8 100644 --- a/macros/latex/base/letter.pdf +++ b/macros/latex/base/letter.pdf diff --git a/macros/latex/base/lgc2.err b/macros/latex/base/lgc2.err index 45b440a7f4..cb1a382348 100644 --- a/macros/latex/base/lgc2.err +++ b/macros/latex/base/lgc2.err @@ -330,6 +330,26 @@ ) \end{verbatim} +Reprinted by Lehmanns in 2022: + +\begin{verbatim} +@book(Lehmanns:GMRRV2022, + author = {Michel Goossens and Frank Mittelbach and Sebastian Rahtz + and Denis Roegel and Herbert Vo{\ss}}, + title = {The {\LaTeX} Graphics Companion}, + edition = 2, + series = {Tools and Techniques for Computer Typesetting}, + publisher = {Lehmanns Media}, + address = {Köln}, + year = {2022}, + isbn = {978-3-96543-303-8 (softcover), 978-3-96543-299-4 (ebook)}, + originalyear = {2007}, + pagenums = {976}, + bibliography = {yes}, + index = {yes}, +) +\end{verbatim} + \begin{list}{}{\setlength\leftmargin{0cm}\setlength\rightmargin{3cm}} \item[] @@ -378,7 +398,7 @@ Good luck! Contest period ends & Winner \\[4pt] 2008/05 & Milan Vujtek & 16 suggestions\\ 2010/05 & & \\ -\ldots & contest no longer open +\ldots & -- contest no longer open -- \end{tabular} \end{center} \end{list} diff --git a/macros/latex/base/lgc2.pdf b/macros/latex/base/lgc2.pdf Binary files differindex 43ab034d38..339f3c46a3 100644 --- a/macros/latex/base/lgc2.pdf +++ b/macros/latex/base/lgc2.pdf diff --git a/macros/latex/base/lppl.pdf b/macros/latex/base/lppl.pdf Binary files differindex 81e00214b6..196e23d5cb 100644 --- a/macros/latex/base/lppl.pdf +++ b/macros/latex/base/lppl.pdf diff --git a/macros/latex/base/ltalloc.dtx b/macros/latex/base/ltalloc.dtx index 4530d4b07b..c3498fb9c7 100644 --- a/macros/latex/base/ltalloc.dtx +++ b/macros/latex/base/ltalloc.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltbibl.dtx b/macros/latex/base/ltbibl.dtx index 4c219657b8..8e34ca685a 100644 --- a/macros/latex/base/ltbibl.dtx +++ b/macros/latex/base/ltbibl.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltboxes.dtx b/macros/latex/base/ltboxes.dtx index b82f5bdb8e..ff1717caa9 100644 --- a/macros/latex/base/ltboxes.dtx +++ b/macros/latex/base/ltboxes.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltclass.dtx b/macros/latex/base/ltclass.dtx index a525b6f573..bb52148508 100644 --- a/macros/latex/base/ltclass.dtx +++ b/macros/latex/base/ltclass.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltclass.dtx} - [2022/10/22 v1.5e LaTeX Kernel (Class & Package Interface)] + [2023/04/14 v1.5h LaTeX Kernel (Class & Package Interface)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltclass.dtx} @@ -324,6 +324,7 @@ % % \DescribeMacro\IfPackageAtLeastTF % \DescribeMacro\IfClassAtLeastTF +% \DescribeMacro\IfFileAtLeastTF % \DescribeMacro\@ifpackagelater % \DescribeMacro\@ifclasslater % \changes{v1.1i}{2013/07/07}{Correctly describe how the date in @@ -890,12 +891,14 @@ % % \begin{macro}{\IfPackageAtLeastTF} % \begin{macro}{\IfClassAtLeastTF} +% \begin{macro}{\IfFileAtLeastTF} % \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)} % \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}} +% \changes{v1.5g}{2023/03/28}{Added \cs{IfFileAtLeastTF} (gh/1015)} % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> @@ -904,6 +907,7 @@ \def\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} \let\IfPackageAtLeastTF\@ifpackagelater \let\IfClassAtLeastTF\@ifclasslater +\def\IfFileAtLeastTF#1{\expandafter\@ifl@t@r\csname ver@#1\endcsname} % \end{macrocode} % For rollback pretend it was available since the beginning of dawn. % \begin{macrocode} @@ -914,12 +918,14 @@ %<latexrelease>\def\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} %<latexrelease>\let\IfPackageAtLeastTF\@ifpackagelater %<latexrelease>\let\IfClassAtLeastTF\@ifclasslater +%<latexrelease>\def\IfFileAtLeastTF#1{\expandafter\@ifl@t@r\csname ver@#1\endcsname} %<latexrelease>\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}{\@ifl@ter} % \changes{v1.4e}{2021/07/19}{Drop \cs{@onlypreamble}} @@ -2133,13 +2139,28 @@ % {Reset \cs{CurrentOption}} % \changes{v1.3d}{2019/10/18}{Initialize \cs{...-h@@k} only when loading % the package or class (gh/198)} +% \changes{v1.5h}{2023/04/14}{Define \cs{load@onefilewithoptions} when +% in \pkg{latexrelease} (gh/992)} % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> %<latexrelease>\IncludeInRelease{2020/10/01}% %<latexrelease> {\@onefilewithoptions}{Hooks and unused options issue}% +% \end{macrocode} +% +% Here this macro is called \cs{@onefilewithoptions}, but further +% ahead in this file it is renamed to \cs{load@onefilewithoptions}, +% and \cs{@onefilewithoptions} becomes a wrapper around this, used for +% bookkeeping when rolling back. Therefore, when in +% \pkg{latexrelease}, we need to define \cs{load@onefilewithoptions} +% instead, thus the extra guarded \cs{def} line below: +% \begin{macrocode} +%<*2ekernel> \def\@onefilewithoptions#1[#2][#3]#4{% +%</2ekernel> +%<latexrelease>\def\load@onefilewithoptions#1[#2][#3]#4{% % \end{macrocode} +% % We have to sanitise file names, so that something like % \begin{verbatim} % \usepackage{some/local/path/array} @@ -2813,6 +2834,7 @@ % unknown option. % \changes{v1.3h}{2020/01/28}{Allow spaces in option string and display % only unknown options not the whole option list (gh/256)} +% \changes{v1.5f}{2022/11/16}{Introduce key 'nowarn' on filecontents (gh/958)} % \begin{macrocode} \def\filec@ntents@opt[#1]{% \edef\@fortmp{\zap@space#1 \@empty}% @@ -2821,7 +2843,7 @@ \csname filec@ntents@\reserved@a\endcsname \else \@latex@error{Unknown filecontents option \reserved@a}% - {Valid options are force (or overwrite), nosearch, noheader}% + {Valid options are force (or overwrite), nosearch, noheader, nowarn}% \fi}% \filec@ntents } @@ -2849,6 +2871,18 @@ \let\filec@ntents@checkdir\@empty \def\filec@ntents@where{exists on the system} % \end{macrocode} +% Option \texttt{nowarn} does not show any warning on the terminal +% but still writes it to the \texttt{.log}. +% \changes{v1.5f}{2022/11/16}{Introduce key 'nowarn' on filecontents (gh/958)} +% \begin{macrocode} +\def\filec@ntents@nowarn{% + \let\filec@ntents@warning\@latex@note@no@line +} +% \end{macrocode} +% By default we show terminal warnings. +% \begin{macrocode} +\let\filec@ntents@warning\@latex@warning@no@line +% \end{macrocode} % % \begin{macrocode} \begingroup% @@ -2925,6 +2959,8 @@ % on the terminal. % \changes{v1.3g}{2020/01/27}{Fix typo in error message} % \changes{v1.3j}{2020/02/20}{Fix missing quotes around file name (gh/284)} +% \changes{v1.5f}{2022/11/16}{Introduce key 'nowarn' on filecontents (gh/958)} +% \changes{v1.5f}{2022/11/16}{Do not show "current dir" in message (gh/917)} % \begin{macrocode} \ch@ck7\reserved@c\write\relax% \if@filesw% % Foul ... trying to overwrite \jobname! @@ -2932,8 +2968,8 @@ write to the file you are reading from!\MessageBreak% Data is written to screen instead.}% \else% - \@latex@warning@no@line% - {Writing or overwriting file `\@currdir\@curr@file'}% + \filec@ntents@warning% + {Writing or overwriting file `\@curr@file'}% \immediate\openout\reserved@c\q@curr@file\relax% \fi% \fi% diff --git a/macros/latex/base/ltcmd.dtx b/macros/latex/base/ltcmd.dtx index 14d6756f5c..d6322ff3ee 100644 --- a/macros/latex/base/ltcmd.dtx +++ b/macros/latex/base/ltcmd.dtx @@ -1,8 +1,8 @@ % \iffalse meta-comment % % Copyright (C) 1999 Frank Mittelbach, Chris Rowley, David Carlisle -% Copyright (C) 2004-2008 Frank Mittelbach, The LaTeX3 Project -% Copyright (C) 2009-2022 +% Copyright (C) 2004-2008 Frank Mittelbach, The LaTeX Project +% Copyright (C) 2009-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -34,8 +34,8 @@ %%% From File: ltcmd.dtx % % \begin{macrocode} -\def\ltcmdversion{v1.1a} -\def\ltcmddate{2022-08-16} +\def\ltcmdversion{v1.1e} +\def\ltcmddate{2023-05-26} % \end{macrocode} % %<*driver> @@ -725,6 +725,9 @@ { \@@_environment_or_command: } } % \end{macrocode} +% +% \changes{v1.1e}{2023/05/26} +% {Use simpler variant \cs{cs_generate_from_arg_count:NNno}} % To construct \cs{@@_tmp:w}, first go through the arguments % found and the corresponding defaults, building a token list with % |{#|\meta{arg number}|}| for arguments found in the input (whose @@ -738,10 +741,10 @@ \int_zero:N \l_@@_current_arg_int \@@_tl_mapthread_function:NNN \l_@@_args_tl \l_@@_defaults_tl \@@_defaults_def:nn - \cs_generate_from_arg_count:NNVo \@@_tmp:w \cs_set:Npn + \cs_generate_from_arg_count:NNno \@@_tmp:w \cs_set:Npn \l_@@_current_arg_int \l_@@_tmpa_tl } -\cs_generate_variant:Nn \cs_generate_from_arg_count:NNnn { NNVo } +\cs_generate_variant:Nn \cs_generate_from_arg_count:NNnn { NNno } \cs_new_protected:Npn \@@_defaults_def:nn { \int_incr:N \l_@@_current_arg_int @@ -2123,8 +2126,8 @@ % and possibly another auxiliary % \cs{\meta{cmd}\textvisiblespace\textvisiblespace}, if the command % has both long and short arguments. Then, its signature also has -% several specific bits that are unique to that command; this is in contrast to -% non-expandable commands, which use a common set of parsing functions. +% several specific bits that are unique to that command; this is in contrast +% to non-expandable commands, which use a common set of parsing functions. % % We start by copying the basics, then call % \cs{@@_copy_expandable_signature:NnNNNNnnn} to parse the signature @@ -2132,7 +2135,24 @@ % then we call \cs{@@_copy_expandable:NnNNNNnnn} that will copy the % top-level definition of the command, with the proper internal % renames. +% % \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_copy:NN}% +%<latexrelease> {Support~\NewCommandCopy~in~ltcmd} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \changes{v1.1c}{2023/03/12} +% {Distinguish (non-expandable) document commands starting with +% \cs{@@_start_expandable:nNNNNn}} +% There's one variant: a command begins with \cs{@@_start_expandable:nNNNNn} +% may still be un-expandable/protected if it's defined by +% \cs{NewDocumentCommand} and friends, with empty or only m-type arguments. +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_copy_expandable:nnNN}% +%<latexrelease> {Distinguish~non-expandable~document~commands} \cs_new_protected:Npn \@@_copy_expandable:nnNN #1 #2 #3 #4 { \cs_set_eq:cc { #1 ~ code } { #2 ~ code } @@ -2140,9 +2160,36 @@ \@@_set_eq_if_exist:cc { #1 ~ \c_space_tl } { #2 ~ \c_space_tl } \@@_set_eq_if_exist:cc { #1 ~ defaults } { #2 ~ defaults } \exp_after:wN \@@_copy_expandable_signature:NnNNNNnnn #4 {#1} {#2} - \cs_set_nopar:Npx #3 + \token_if_protected_macro:NTF #4 + { \cs_set_protected_nopar:Npx }{ \cs_set_nopar:Npx } + #3 { \exp_after:wN \@@_copy_expandable:NnNNNNnnn #4 {#1} {#2} } } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_copy_expandable:nnNN}% +%<latexrelease> {Support~\NewCommandCopy~in~ltcmd} +%<latexrelease>\cs_new_protected:Npn \@@_copy_expandable:nnNN #1 #2 #3 #4 +%<latexrelease> { +%<latexrelease> \cs_set_eq:cc { #1 ~ code } { #2 ~ code } +%<latexrelease> \@@_set_eq_if_exist:cc { #1 ~ } { #2 ~ } +%<latexrelease> \@@_set_eq_if_exist:cc { #1 ~ \c_space_tl } { #2 ~ \c_space_tl } +%<latexrelease> \@@_set_eq_if_exist:cc { #1 ~ defaults } { #2 ~ defaults } +%<latexrelease> \exp_after:wN \@@_copy_expandable_signature:NnNNNNnnn #4 {#1} {#2} +%<latexrelease> \cs_set_nopar:Npx #3 +%<latexrelease> { \exp_after:wN \@@_copy_expandable:NnNNNNnnn #4 {#1} {#2} } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_copy_expandable:nnNN}% +%<latexrelease> {Support~\NewCommandCopy~in~ltcmd} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_copy:NN (part 2)}% +%<latexrelease> {Support~\NewCommandCopy~in~ltcmd} +% \end{macrocode} +% +% \begin{macrocode} \cs_new:Npn \@@_copy_expandable:NnNNNNnnn #1 #2 #3 #4 #5 #6 #7 #8 #9 { \exp_not:N #1 \exp_not:n { {#2} } @@ -2355,7 +2402,7 @@ % worth it. % \begin{macrocode} %<latexrelease>\EndIncludeInRelease -%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_copy:NN}% +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_copy:NN (part 2)}% %<latexrelease> {Support~\NewCommandCopy~in~ltcmd} %<latexrelease>\EndIncludeInRelease % \end{macrocode} @@ -2401,21 +2448,64 @@ % \@@_show_command:NnNNwN, % \@@_show_expandable:N, % \@@_show_expandable:NnNNNNnN, -% \@@_show_command_aux:nNNn, +% \@@_show_command_aux:NnNNn, % \@@_show_environment:N, +% \@@_show:x, % } % These commands just expand the command once to reveal its innards, % then pass the type of command, the control sequence, the signature, -% and the code macro to \cs{@@_show_command_aux:nNNn}. +% and the code macro to \cs{@@_show_command_aux:NnNNn}. % \begin{macrocode} \cs_new_protected:Npn \@@_show_command:N #1 { \exp_after:wN \@@_show_command:NnNNwN #1 \q_@@ #1 } \cs_new_protected:Npn \@@_show_command:NnNNwN #1 #2 #3 #4 #5 \q_@@ #6 - { \@@_show_command_aux:nNNn { document~command } #6 #4 {#2} } + { + \@@_show_command_aux:NnNNn \tl_show:x + { document~command } #6 #4 {#2} + } \cs_new_protected:Npn \@@_show_expandable:N #1 { \exp_after:wN \@@_show_expandable:NnNNNNnN #1 #1 } +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_show:N}% +%<latexrelease> {Support~\ShowCommand~in~ltcmd} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \changes{v1.1c}{2023/03/12} +% {Distinguish (non-expandable) document commands starting with +% \cs{@@_start_expandable:nNNNNn}} +% There's one variant: a command begins with \cs{@@_start_expandable:nNNNNn} +% may still be un-expandable/protected if it's defined by +% \cs{NewDocumentCommand} and friends, with empty or only m-type arguments. +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_show_expandable:NnNNNNnN}% +%<latexrelease> {Distinguish~non-expandable~document~commands} \cs_new_protected:Npn \@@_show_expandable:NnNNNNnN #1 #2 #3 #4 #5 #6 #7 #8 - { \@@_show_command_aux:nNNn { expandable~document~command } #8 #5 {#2} } + { + \exp_args:NNe \@@_show_command_aux:NnNNn \tl_show:x + { \token_if_protected_macro:NF #8 { expandable~ } document~command } + #8 #5 {#2} + } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_show_expandable:NnNNNNnN}% +%<latexrelease> {Support~\ShowCommand~in~ltcmd} +%<latexrelease>\cs_new_protected:Npn \@@_show_expandable:NnNNNNnN #1 #2 #3 #4 #5 #6 #7 #8 +%<latexrelease> { +%<latexrelease> \@@_show_command_aux:NnNNn \tl_show:x +%<latexrelease> { expandable~document~command } #8 #5 {#2} +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_show_expandable:NnNNNNnN}% +%<latexrelease> {Support~\ShowCommand~in~ltcmd} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_show:N (part 2)}% +%<latexrelease> {Support~\ShowCommand~in~ltcmd} % \end{macrocode} % % Now just print everything in the required format. The auxiliary @@ -2423,27 +2513,31 @@ % \cs{l_@@_tmpa_tl}, so we ust use that here: % \changes{v1.0j}{2021/13/31} % {Make \cs{ShowCommand} stop for interaction} +% \changes{v1.1b}{2022/11/30} +% {Don't stop for the \cs{begin} part of an environment} % \begin{macrocode} -\cs_new_protected:Npn \@@_show_command_aux:nNNn #1 #2 #3 #4 +\cs_new_protected:Npn \@@_show_command_aux:NnNNn #1 #2 #3 #4 #5 { - \@@_split_signature:n {#4} - \tl_show:x + \@@_split_signature:n {#5} + #1 { - \token_to_str:N #2 = #1: \iow_newline: + \token_to_str:N #3 = #2: \iow_newline: \tl_use:N \l_@@_tmpa_tl - -> \cs_replacement_spec:N #3 + -> \cs_replacement_spec:N #4 } } % \end{macrocode} % % We can reuse most of the above to show an environment, except that % we need to ensure that the proper \cs[no-index]{environment~\ldots} -% are passed to \cs{@@_show_command_aux:nNNn}. Additionally, when +% are passed to \cs{@@_show_command_aux:NnNNn}. Additionally, when % |\ShowCommand\foo| is used (if |foo| is an environment), we show % |\endfoo| as well, and when |\ShowCommand\endfoo| is used, change % that to |\ShowCommand\foo| and do the same. % \changes{v1.0j}{2021/13/31} % {Make \cs{ShowCommand} stop for interaction} +% \changes{v1.1b}{2022/11/30} +% {Don't stop for the \cs{begin} part of an environment} % \begin{macrocode} \cs_new_protected:Npn \@@_show_environment:N #1 { @@ -2459,12 +2553,14 @@ { \use:x { - \@@_show_command_aux:nNNn { document~environment } + \@@_show_command_aux:NnNNn \@@_show:x { document~environment } { \exp_not:N \begin {#3} } \exp_not:c { environment~ #3 ~ code } {#2} } } +\cs_new_protected:Npn \@@_show:x #1 + { \iow_term:x { > ~ #1 . \iow_newline: } } \cs_new_protected:Npn \@@_show_environment_end:N #1 { \exp_args:NNx \@@_check_end:Nn \l_@@_tmpa_tl { \cs_to_str:N #1 } @@ -2473,10 +2569,15 @@ % \end{macrocode} % % And, of course, add \cs{__kernel_cmd_if_xparse:NTF} and -% \cs{@@_show:N} to \cs{@showcommandlisthook}: +% \cs{@@_show:N} to \cs{@showcommandlisthook} and to +% \cs{@showenvironmentlisthook} (\cs{@@_show:N} takes care of the +% environment case as well, so both entries are identical): +% \changes{v1.1b}{2022-11-29}{Add \cs{@showenvironmentlisthook}} % \begin{macrocode} \tl_gput_right:Nn \@showcommandlisthook { { \__kernel_cmd_if_xparse:NTF \@@_show:N } } +\tl_gput_right:Nn \@showenvironmentlisthook + { { \__kernel_cmd_if_xparse:NTF \@@_show:N } } % \end{macrocode} % \end{macro} % @@ -2657,7 +2758,7 @@ % \begin{macrocode} %<latexrelease>\EndIncludeInRelease % -%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_show:N}% +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_show:N (part 2)}% %<latexrelease> {Support~\ShowCommand~in~ltcmd} %<latexrelease>\EndIncludeInRelease % \end{macrocode} @@ -3200,6 +3301,10 @@ % \begin{macro}{\@@_grab_v_long:w} % \begin{macro}{\@@_grab_v_aux:w} % \begin{macro}{\@@_grab_v_group_end:} +% Firstly, it is necessary to change \cs{tex_endlinechar:D} so that +% newlines in different catcode regimes (e.g., \cs{ExplSyntaxOn}) are +% not misinterpreted as spaces. +% \changes{v1.1d}{2023/04/13}{Set \cs{tex_endlinechar:D} earlier (gh/876).} % The opening delimiter is the first non-space token, and is never % read verbatim. This is required by consistency with the case where % the preceding argument was optional and absent: then \TeX{} has @@ -3233,6 +3338,7 @@ \tl_set:Nn \l_@@_signature_tl {#1} \group_begin: \tex_escapechar:D = 92 \scan_stop: + \tex_endlinechar:D = `\^^M \scan_stop: \tl_clear:N \l_@@_v_arg_tl \peek_remove_spaces:n { @@ -3250,8 +3356,8 @@ } \cs_new_protected:Npn \@@_grab_v_group_end: { - \exp_args:NNNo - \group_end: + \exp_args:NNNo + \group_end: \tl_set:Nn \l_@@_v_arg_tl { \l_@@_v_arg_tl } } % \end{macrocode} @@ -3396,7 +3502,6 @@ { \cs_set_eq:NN \do \char_set_catcode_other:N \dospecials - \tex_endlinechar:D = `\^^M \scan_stop: \bool_if:NTF \l_@@_long_bool { \char_set_catcode_other:n { \tex_endlinechar:D } } { \char_set_catcode_parameter:n { \tex_endlinechar:D } } diff --git a/macros/latex/base/ltcmdhooks-code.pdf b/macros/latex/base/ltcmdhooks-code.pdf Binary files differindex 83670e4463..499194f3d6 100644 --- a/macros/latex/base/ltcmdhooks-code.pdf +++ b/macros/latex/base/ltcmdhooks-code.pdf diff --git a/macros/latex/base/ltcmdhooks-doc.pdf b/macros/latex/base/ltcmdhooks-doc.pdf Binary files differindex fa4ca35a07..51320b388e 100644 --- a/macros/latex/base/ltcmdhooks-doc.pdf +++ b/macros/latex/base/ltcmdhooks-doc.pdf diff --git a/macros/latex/base/ltcmdhooks.dtx b/macros/latex/base/ltcmdhooks.dtx index ccb5a35a71..27907af679 100644 --- a/macros/latex/base/ltcmdhooks.dtx +++ b/macros/latex/base/ltcmdhooks.dtx @@ -1,7 +1,8 @@ % \iffalse meta-comment % -%% File: ltcmdhooks.dtx (C) Copyright 2020-2021 -%% Frank Mittelbach, Phelype Oleinik, LaTeX Team +%% File: ltcmdhooks.dtx +%% Copyright (C) 2020-2023 +%% Frank Mittelbach, Phelype Oleinik, The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -13,8 +14,8 @@ % %%% From File: ltcmdhooks.dtx % -\def\ltcmdhooksversion{v1.0f} -\def\ltcmdhooksdate{2021/10/20} +\def\ltcmdhooksversion{v1.0h} +\def\ltcmdhooksdate{2023/05/21} % % % @@ -51,20 +52,32 @@ % % This file implements generic hooks for (arbitrary) commands. % In theory every command \tn[no-index]{\meta{name}} offers now two -% associated hooks to which code can be added using \tn{AddToHook} -% or \tn{AddToHookNext}.\footnote{In practice this is not supported +% associated hooks to which code can be added using +% \tn{AddToHook},\!\footnote{In this documentation, when something is +% being said about \tn{AddToHook}, the same will be valid for +% \tn{AddToHookWithArguments}, unless that particular paragraph is +% highlighting the differences between both. The same is true for +% the other hook-related functions and their +% \texttt{\ldots WithArguments} counterparts.} +% \tn{AddToHookNext}, \tn{AddToHookWithArguments}, and +% \tn{AddToHookNextWithArguments}.\footnote{In practice this is not +% supported % for all types of commands, see section~\ref{sec:look-ahead} for % the restrictions that apply and what happens if one tries to use -% this with commands for which this is not supported.} These are +% this with commands for which this is not supported.} These are: % \begin{description} % \item[\hook{cmd/\meta{name}/before}] % -% This hook is executed at the very start of the command -% execution after its arguments (if any) are parsed. The hook -% \meta{code} is wrapped in the command inside a call to -% \cs{UseHook}|{cmd/|\meta{name}|/before}|, so the arguments -% passed to the command are \emph{not} available in the hook -% \meta{code}. +% This hook is executed at the very start of the command, right +% after its arguments (if any) are parsed. The hook \meta{code} +% runs in the command inside a call to \cs{UseHookWithArguments}. +% Any code added to this hook using \tn{AddToHookWithArguments} +% or \tn{AddToHookNextWithArguments} can access the command's +% arguments using |#1|, |#2|, etc., up to the number of arguments +% of the command. If \tn{AddToHook} or \tn{AddToHookNext} are +% used, the arguments cannot be accessed (see the \pkg{lthooks} +% documentation\footnote{\texttt{texdoc lthooks-doc}} on hooks +% with arguments). % % \item[\hook{cmd/\meta{name}/after}] % @@ -74,9 +87,12 @@ % \end{description} % % The hooks are not physically present before -% \verb=\begin{document}= (i.e., using a command in the preamble -% will never execute them) and if nobody has declared any code for -% them, then they are not added to the command code ever. For +% \verb=\begin{document}=\footnote{More specifically, they are +% inserted in the commands after the \hook{begindocument} hook, so +% they are also not present while \LaTeX{} is reading the +% \texttt{.aux} file.} (i.e., using a command in the preamble +% will never execute the hook) and if nobody has declared any code +% for them, then they are not added to the command code ever. For % example, if we have the following definition %\begin{verbatim} % \newcommand\foo[2]{Code #1 for #2!} @@ -90,23 +106,27 @@ %\end{verbatim} % then, after |\begin{document}| the definition of \cs[no-index]{foo} will be: %\begin{verbatim} -% \renewcommand\foo[2]{\UseHook{cmd/foo/before}Code #1 for #2!} +% \renewcommand\foo[2]{% +% \UseHookWithArguments{cmd/foo/before}{2}{#1}{#2}% +% Code #1 for #2!} %\end{verbatim} % and similarly \verb=\AddToHook{cmd/foo/after}{<after code>}= % alters the definition to %\begin{verbatim} -% \renewcommand\foo[2]{Code #1 for #2!\UseHook{cmd/foo/after}} +% \renewcommand\foo[2]{% +% Code #1 for #2!% +% \UseHookWithArguments{cmd/foo/after}{2}{#1}{#2}} %\end{verbatim} % % In other words, the mechanism is similar to what \pkg{etoolbox} % offers with \tn{pretocmd} and \tn{apptocmd} with the important -% differences +% differences % \begin{itemize} % \item % % that code can be prepended or appended (i.e., added to the % hooks) even if the command itself is not defined, because the -% defining package has not yet been loaded +% defining package has not yet been loaded; % % \item % @@ -197,6 +217,7 @@ % % % \section{Package Author Interface} +% \label{sec:pkg-author} % % The \hook{cmd} hooks are, by default, available for all commands % that can be patched to add the hooks. For some commands, however, @@ -206,9 +227,10 @@ % % If you are a package author and you want to add the hooks to your % own commands in the proper position you can define the command and -% manually add the \cs{UseHook} calls inside the command in the proper -% positions, and manually define the hooks with \cs{NewHook} or -% \cs{NewReversedHook}. When the hooks are explicitly defined, +% manually add the \cs{UseHookWithArguments} calls inside the command in +% the proper positions, and manually define the hooks with +% \cs{NewHookWithArguments} or \cs{NewReversedHookWithArguments}. +% When the hooks are explicitly defined, % patching is not attempted so you can make sure your command works % properly. For example, an (admittedly not really useful) command % that typesets its contents in a framed box with width optionally @@ -230,26 +252,27 @@ % \begin{verbatim} % \newcommand\fancybox{\@ifnextchar({\@fancybox}{\@fancybox(5cm)}} % \def\@fancybox(#1)#2{\fbox{% -% \UseHook{cmd/fancybox/before}% -% \parbox{#1}{#2}% -% \UseHook{cmd/fancybox/after}}} -% \NewHook{cmd/fancybox/before} -% \NewReversedHook{cmd/fancybox/after} +% \UseHookWithArguments{cmd/fancybox/before}{2}{#1}{#2}% +% \parbox{#1}{#2}% +% \UseHookWithArguments{cmd/fancybox/after}{2}{#1}{#2}}} +% \NewHookWithArguments{cmd/fancybox/before}{2} +% \NewReversedHookWithArguments{cmd/fancybox/after}{2} % \end{verbatim} % then the hooks will be executed where they should and no patching % will be attempted. It is important that the hooks are declared with -% \cs{NewHook} or \cs{NewReversedHook}, otherwise the command hook +% \cs{NewHookWithArguments} or \cs{NewReversedHookWithArguments}, +% otherwise the command hook % code will try to patch the command. Note also that the call to -% |\UseHook{cmd/fancybox/before}| does not need to be in the -% definition of \cs[no-index]{fancybox}, but anywhere it makes sense +% |\UseHookWithArguments{cmd/fancybox/before}| does not need to be in +% the definition of \cs[no-index]{fancybox}, but anywhere it makes sense % to insert it (in this case in the internal % \cs[no-index]{@fancybox}). % % Alternatively, if for whatever reason your command does not support % the generic hooks provided here, you can disable a hook with -% \cs{DisableHook}\footnote{Please use \cs{DisableHook} if at all, only -% on hooks that you \enquote{own}, i.e., for commands that your -% package or class defines and not second guess +% \cs{DisableGenericHook}\footnote{Please use \cs{DisableGenericHook} if +% at all, only on hooks that you \enquote{own}, i.e., for commands +% your package or class defines and not second guess % whether or not hooks of other packages should get disabled!}, so % that when someone tries to add code to it they will get an error. % Or if you don't want the error, you can simply declare the hook with @@ -270,6 +293,55 @@ % If you do that then both hooks automatically work and are patched % into the right places. % +% \subsection{Arguments and redefining commands} +% \label{sec:redef-warn} +% +% The code in \pkg{ltcmdhooks} does its best to find out how many +% arguments a given command has, and to insert the appropriate call to +% \cs{UseHookWithArguments}, so that the arguments seen by the hook are +% exactly those grabbed by the command (the hook, after all, is a macro +% call, so the arguments have to be placed in the right order, or they +% won't match). +% +% When using the package writer interface, as discussed in +% section~\ref{sec:pkg-author}, to change the position of the hooks in +% your commands, you are also free to change how the hook code in your +% command sees its arguments. When a \hook{cmd} hook is declared with +% \cs{NewHook} (or \cs{NewHookWithArguments} or other variations of +% that), it loses its \enquote{generic} nature and works as a regular +% hook. This means that you may choose to declare it without +% arguments regardless if the command takes arguments or not, or +% declare it with arguments, even if the command takes none. +% +% However, this flexibility should not be abused. When using a +% nonstandard configuration for the hook arguments, think reasonably: +% a user will expect that the argument \verb|#1| in the hook corresponds +% to the argument's first argument, and so on. Any other configuration +% is likely to cause confusion and, if used, will have to be well +% documented. +% +% This flexibility, however, allows you to \enquote{correct} the +% arguments for the hooks. For example, \LaTeX's \cs{refstepcounter} +% has a single argument, the name of the counter. The \pkg{cleveref} +% package adds an optional argument to \cs{refstepcounter}, making the +% name of the counter argument \verb|#2|. If the author of +% \pkg{cleveref} wanted, for whatever reason, to add hooks to +% \cs{refstepcounter}, to preserve compatibility he could write +% something along the lines of: +% \begin{verbatim} +% \NewHookWithArguments{cmd/refstepcounter/before}{1} +% \renewcommand\refstepcounter[2][<default>]{% +% \UseHookWithArguments{cmd/refstepcounter/before}{1}{#2}% +% <code for \refstepcounter>} +% \end{verbatim} +% so that the mandatory argument, which is arg \verb|#2| in the +% definition, would still be seen as \verb|#1| in the hook code. +% +% Another possibility would be to place the optional argument as the +% second argument for the hook, so that people looking for it would be +% able to use it. In either case, it would have to be well documented +% to cause as little confusion as possible. +% % \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } % % @@ -366,10 +438,13 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\c_@@_hash_tl} -% A constant token list that contains two parameter tokens. +% \begin{macro}{\c_@@_hash_tl,\c_@@_hashes_tl} +% Two constant token lists that contain one and two parameter tokens. +% \changes{v1.0g}{2023/04/06} +% {Rename to \cs{c_@@_hashes_tl} and add \cs{c_@@_hash_tl} (hook-args).} % \begin{macrocode} -\tl_const:Nn \c_@@_hash_tl { # # } +\tl_const:Nn \c_@@_hash_tl { # } +\tl_const:Nn \c_@@_hashes_tl { # # } % \end{macrocode} % \end{macro} % @@ -702,7 +777,7 @@ % % \changes{v1.0f}{2021/10/20} % {Correct patching by expansion+redefinition when the macro -% contains a parameter tokens (gh/697).} +% contains a parameter token (gh/697).} % Patching with expansion+redefinition is trickier than it looks like % at first glance. Suppose the simple definition: % \begin{verbatim} @@ -756,6 +831,8 @@ % parameter token, so that this case can be handled like the previous % one. % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_patch_expand_redefine:NNnn} +%<latexrelease> {cmd~hooks~with~args} \cs_new_protected:Npn \@@_patch_expand_redefine:NNnn #1 #2 #3 #4 { \@@_patch_debug:x { ++~command~can~be~patched~without~rescanning } @@ -779,14 +856,14 @@ % should be identical to the \meta{parameter text} used when % originally defining that macro. % \item[\cs{l_@@_replace_text_tl}] will contain braced pairs of -% \cs{c_@@_hash_tl}\meta{num} to feed to the macro when expanded. +% \cs{c_@@_hashes_tl}\meta{num} to feed to the macro when expanded. % This token list as well as the previous will have the first item % surrounded by |[|\ldots|]| in the case of an optional argument. % \end{description} % -% The use of \cs{c_@@_hash_tl} here is to differentiate actual +% The use of \cs{c_@@_hashes_tl} here is to differentiate actual % parameters in the macro from parameter tokens in the original -% definition of the macro. Later on, \cs{c_@@_hash_tl} is either +% definition of the macro. Later on, \cs{c_@@_hashes_tl} is either % replaced by actual parameter tokens, or expanded into them. % \begin{macrocode} \int_compare:nNnTF { \l_@@_patch_num_args_int } > { \c_zero_int } @@ -795,7 +872,7 @@ % We'll first check if the command has any parameter token in its % definition (feeding it empty arguments), and set \cs{@@_exp_not:n} % accordingly. \cs{@@_exp_not:n} will be used later to either leave -% \cs{c_@@_hash_tl} or expand it, and also to remember the result of +% \cs{c_@@_hashes_tl} or expand it, and also to remember the result of % \cs{@@_if_has_hash:nTF} to avoid testing twice (the test can be % rather slow). % \begin{macrocode} @@ -814,20 +891,22 @@ % \end{macrocode} % Here we'll conditionally add |[|\ldots|]| around the first % parameter: +% \changes{v1.0g}{2023/04/06} +% {Rename to \cs{c_@@_hashes_tl} (hook-args).} % \begin{macrocode} \bool_if:NTF #1 - { \@@_tmp:w \tl_set:Nx { [ \c_@@_hash_tl 1 ] } } - { \@@_tmp:w \tl_set:Nx { { \c_@@_hash_tl 1 } } } + { \@@_tmp:w \tl_set:Nx { [ \c_@@_hashes_tl 1 ] } } + { \@@_tmp:w \tl_set:Nx { { \c_@@_hashes_tl 1 } } } % \end{macrocode} % Then, for every parameter from the second, just add it normally: % \begin{macrocode} \int_step_inline:nnn { 2 } { \l_@@_patch_num_args_int } - { \@@_tmp:w \tl_put_right:Nx { { \c_@@_hash_tl ##1 } } } + { \@@_tmp:w \tl_put_right:Nx { { \c_@@_hashes_tl ##1 } } } % \end{macrocode} % Now, if the command has any parameter token in its definition % (then \cs{@@_exp_not:n} is \cs{exp_not:n}), call % \cs{@@_double_hashes:n} to double them, and replace every -% \cs{c_@@_hash_tl} by |#|: +% \cs{c_@@_hashes_tl} by |#|: % \begin{macrocode} \tl_set:Nx \l_@@_replace_text_tl { \exp_not:N #2 \exp_not:V \l_@@_replace_text_tl } @@ -875,22 +954,110 @@ { \exp_not:N \@@_make_prefixes:w \cs_prefix_spec:N #2 / / } } % \end{macrocode} -% Finally, call \cs{@@_redefine_with_hooks:Nnnn} with the macro being +% Here we redefine the hook to have the right number of arguments. +% Disabling the hook, undefining the \verb|parameter| token list then +% calling \cs{@@_make_usable:nn} are enough to redefine the hook to +% the extent we want. Code stored in the hook and other metadata +% about it are not lost in the process. +% \changes{v1.0h}{2023/05/21} +% {Changes to allow support arguments in cmd hooks (cmd-args).} +% \begin{macrocode} + \@@_disable:n { cmd / #3 / #4 } + \cs_undefine:c { c_@@_cmd / #3 / #4_parameter_tl } + \@@_make_usable:nn { cmd / #3 / #4 } { \l_@@_patch_num_args_int } +% \end{macrocode} +% Now call \cs{@@_redefine_with_hooks:Nnnn} with the macro being % redefined in |#1|, then \cs{UseHook}|{cmd/<name>/before}| in |#2| or % \cs{UseHook}|{cmd/<name>/after}| in |#3| (one is always empty), and % in |#4| the \meta{replacement text} of the macro. % \begin{macrocode} - \use:x + \use:e { \@@_redefine_with_hooks:Nnnn \exp_not:N #2 \str_if_eq:nnTF {#4} { after } { \use_ii_i:nn } { \use:nn } - { { \@@_exp_not:NN \exp_not:N \UseHook { cmd / #3 / #4 } } } + { { + \@@_exp_not:NN \exp_not:N \UseHookWithArguments + { cmd / #3 / #4 } { \int_use:N \l_@@_patch_num_args_int } + \@@_braced_parameter:n { cmd / #3 / #4 } + } } { { } } { \@@_exp_not:NN \exp_not:V \l_@@_replace_text_tl } } +% \end{macrocode} +% Finally, update the hook code. +% \begin{macrocode} + \@@_update_hook_code:n { cmd / #3 / #4 } } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/06/01}{\@@_patch_expand_redefine:NNnn} +%<latexrelease> {cmd~hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_patch_expand_redefine:NNnn #1 #2 #3 #4 +%<latexrelease> { +%<latexrelease> \@@_patch_debug:x { ++~command~can~be~patched~without~rescanning } +%<latexrelease> \int_set:Nn \l_@@_patch_num_args_int +%<latexrelease> { +%<latexrelease> \exp_args:Nf \str_count:n { \cs_argument_spec:N #2 } / 2 +%<latexrelease> \bool_if:NT #1 { -1 } +%<latexrelease> } +%<latexrelease> \int_compare:nNnTF { \l_@@_patch_num_args_int } > { \c_zero_int } +%<latexrelease> { +%<latexrelease> \tl_set:Nx \l_@@_tmpa_tl { \bool_if:NTF #1 { [ ] } { { } } } +%<latexrelease> \int_step_inline:nnn { 2 } { \l_@@_patch_num_args_int } +%<latexrelease> { \tl_put_right:Nn \l_@@_tmpa_tl { { } } } +%<latexrelease> \exp_args:NNo \exp_args:No \@@_if_has_hash:nTF +%<latexrelease> { \exp_after:wN #2 \l_@@_tmpa_tl } +%<latexrelease> { \cs_set_eq:NN \@@_exp_not:n \exp_not:n } +%<latexrelease> { \cs_set_eq:NN \@@_exp_not:n \use:n } +%<latexrelease> \cs_set_protected:Npn \@@_tmp:w ##1 ##2 +%<latexrelease> { +%<latexrelease> ##1 \l_@@_param_text_tl { \use:n ##2 } +%<latexrelease> ##1 \l_@@_replace_text_tl { \@@_exp_not:n {##2} } +%<latexrelease> } +%<latexrelease> \bool_if:NTF #1 +%<latexrelease> { \@@_tmp:w \tl_set:Nx { [ \c_@@_hash_tl 1 ] } } +%<latexrelease> { \@@_tmp:w \tl_set:Nx { { \c_@@_hash_tl 1 } } } +%<latexrelease> \int_step_inline:nnn { 2 } { \l_@@_patch_num_args_int } +%<latexrelease> { \@@_tmp:w \tl_put_right:Nx { { \c_@@_hash_tl ##1 } } } +%<latexrelease> \tl_set:Nx \l_@@_replace_text_tl +%<latexrelease> { \exp_not:N #2 \exp_not:V \l_@@_replace_text_tl } +%<latexrelease> \tl_set:Nx \l_@@_replace_text_tl +%<latexrelease> { +%<latexrelease> \token_if_eq_meaning:NNTF \@@_exp_not:n \exp_not:n +%<latexrelease> { \exp_args:NNV \exp_args:No \@@_double_hashes:n } +%<latexrelease> { \exp_args:NV \exp_not:o } +%<latexrelease> \l_@@_replace_text_tl +%<latexrelease> } +%<latexrelease> \cs_set_eq:NN \@@_def_cmd:w \tex_gdef:D +%<latexrelease> \cs_set_eq:NN \@@_exp_not:NN \prg_do_nothing: +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \tl_clear:N \l_@@_param_text_tl +%<latexrelease> \tl_set_eq:NN \l_@@_replace_text_tl #2 +%<latexrelease> \cs_set_eq:NN \@@_def_cmd:w \tex_xdef:D +%<latexrelease> \cs_set:Npn \@@_exp_not:NN ##1 { \exp_not:N ##1 \exp_not:N } +%<latexrelease> } +%<latexrelease> \group_begin: +%<latexrelease> \int_set:Nn \tex_escapechar:D { `\/ } +%<latexrelease> \use:x +%<latexrelease> { +%<latexrelease> \group_end: +%<latexrelease> \tl_set:Nx \exp_not:N \l_@@_patch_prefixes_tl +%<latexrelease> { \exp_not:N \@@_make_prefixes:w \cs_prefix_spec:N #2 / / } +%<latexrelease> } +%<latexrelease> \use:x +%<latexrelease> { +%<latexrelease> \@@_redefine_with_hooks:Nnnn \exp_not:N #2 +%<latexrelease> \str_if_eq:nnTF {#4} { after } +%<latexrelease> { \use_ii_i:nn } +%<latexrelease> { \use:nn } +%<latexrelease> { { \@@_exp_not:NN \exp_not:N \UseHook { cmd / #3 / #4 } } } +%<latexrelease> { { } } +%<latexrelease> { \@@_exp_not:NN \exp_not:V \l_@@_replace_text_tl } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % % Now that all the needed tools are ready, without further ado we'll @@ -973,7 +1140,7 @@ % } % \cs{@@_double_hashes:n} loops through the token list |#1| and % duplicates any catcode~6 token, and expands tokens \cs{ifx}-equal to -% \cs{c_@@_hash_tl}, and leaves all other tokens \cs{notexpanded} with +% \cs{c_@@_hashes_tl}, and leaves all other tokens \cs{notexpanded} with % \cs{exp_not:N}. Unfortunately pairs of explicit catcode~1 and % catcode~2 character tokens are normalised to |{|$_1$ and |}|$_1$ % because it's not feasible to expandably detect the character code @@ -1000,26 +1167,32 @@ % \end{macrocode} % % \cs{@@_double_hashes_output:N} checks for the end of the token list, -% then checks if the token is \cs{c_@@_hash_tl}, and if so just leaves +% then checks if the token is \cs{c_@@_hashes_tl}, and if so just leaves % it. +% \changes{v1.0g}{2023/04/06} +% {Add case for \cs{c_@@_hashes_tl} (hook-args).} % \begin{macrocode} \cs_new:Npn \@@_double_hashes_output:N #1 { \if_meaning:w \q_@@_recursion_tail #1 \@@_double_hashes_stop:w \fi: - \if_meaning:w \c_@@_hash_tl #1 + \if:w ? + \if_meaning:w \c_@@_hash_tl #1 ! \fi: + \if_meaning:w \c_@@_hashes_tl #1 ! \fi: + ? + \else: % \end{macrocode} % (this \cs{use_i:nnnn} uses \cs{fi:} and consumes \cs{use:n}, the % whole \cs{if_catcode:w} block, and the \cs{exp_not:N}, leaving just -% |#1| which is \cs{c_@@_hash_tl}.) +% |#1| which is \cs{c_@@_hashes_tl}.) % \begin{macrocode} \use_i:nnnn \fi: \use:n { % \end{macrocode} -% If |#1| is not \cs{c_@@_hash_tl}, then check if its catcode is~6, +% If |#1| is not \cs{c_@@_hashes_tl}, then check if its catcode is~6, % and if so, leave it doubled in \cs{exp_not:n} and consume the % following |\exp_not:N #1|. % \begin{macrocode} @@ -1080,10 +1253,10 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_retokenize_patch:Nnn #1 #2 #3 { - \@@_patch_debug:x { ..~command~can~only~be~patched~by~rescanning } \str_if_eq:eeTF { \cs_argument_spec:N #1 } { } { \@@_patch_expand_redefine:NNnn \c_false_bool #1 {#2} {#3} } { + \@@_patch_debug:x { ..~command~can~only~be~patched~by~rescanning } % \end{macrocode} % % Otherwise, we start the actual patching by retokenization job. The @@ -1144,6 +1317,8 @@ % \cs{@@_cmd_if_scanable:NnTF} and \cs{@@_patch_retokenize:Nnnn} if % the former returns \meta{true}, plus some debug messages. % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_try_patch_with_catcodes:Nnnnw} +%<latexrelease> {cmd~hooks~with~args} \cs_new_protected:Npn \@@_try_patch_with_catcodes:Nnnnw #1 #2 #3 #4 { \quark_if_recursion_tail_stop_do:nn {#4} { \use:n } @@ -1152,7 +1327,7 @@ { \@@_patch_debug:x { ++~macro~can~be~retokenized~cleanly } \@@_patch_debug:x { ==~retokenizing~macro~now } - \@@_patch_retokenize:Nnnn #1 {#2} {#3} {#4} + \@@_patch_retokenize:Nnnn #1 { cmd / #2 / #3 } {#3} {#4} \use_i_delimit_by_q_recursion_stop:nw \use_none:n } { @@ -1160,6 +1335,26 @@ \@@_try_patch_with_catcodes:Nnnnw #1 {#2} {#3} } } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/06/01}{\@@_try_patch_with_catcodes:Nnnnw} +%<latexrelease> {cmd~hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_try_patch_with_catcodes:Nnnnw #1 #2 #3 #4 +%<latexrelease> { +%<latexrelease> \quark_if_recursion_tail_stop_do:nn {#4} { \use:n } +%<latexrelease> \@@_patch_debug:x { ++~trying~to~patch~by~retokenization } +%<latexrelease> \@@_cmd_if_scanable:NnTF {#1} {#4} +%<latexrelease> { +%<latexrelease> \@@_patch_debug:x { ++~macro~can~be~retokenized~cleanly } +%<latexrelease> \@@_patch_debug:x { ==~retokenizing~macro~now } +%<latexrelease> \@@_patch_retokenize:Nnnn #1 {#2} {#3} {#4} +%<latexrelease> \use_i_delimit_by_q_recursion_stop:nw \use_none:n +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \@@_patch_debug:x { --~macro~cannot~be~retokenized~cleanly } +%<latexrelease> \@@_try_patch_with_catcodes:Nnnnw #1 {#2} {#3} +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -1267,15 +1462,86 @@ % \end{macro} % % +% \begin{macro}{\@@_guess_arg_count:NN} +% \begin{macro}{\@@_guess_arg_count:wN} +% \begin{macro}{\@@_guess_arg_count:nw} +% Looks at the parameter text of a macro, and counts the parameters +% by looking at the number after a \verb|#|, and checking if they are +% sequential. This macro assumes that all parameters are marked with +% hashes, and not other characters, and that there is no +% \enquote{trick parameter}. +% \changes{v1.0h}{2023/05/21} +% {Macro added (cmd-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_guess_arg_count:NN} +%<latexrelease> {cmd~hooks~with~args} +\cs_new_protected:Npn \@@_guess_arg_count:NN #1 + { + \exp_after:wN \@@_guess_arg_count:wN + \token_to_meaning:N #1 \s_@@_mark + } +\exp_last_unbraced:NNNNo +\cs_new_protected:Npx \@@_guess_arg_count:wN + #1 { \tl_to_str:n { macro: } } #2 \s_@@_mark #3 + { + \int_set:Nn #3 + { + \exp_not:N \@@_guess_arg_count:nw { 0 } #2 + \c_hash_str 0 \s_@@_mark + } + } +\use:e + { \cs_new:Npn \exp_not:N \@@_guess_arg_count:nw #1 #2 \c_hash_str #3 } + { + \int_compare:nNnTF { #1 + 1 } = {#3} + { \@@_guess_arg_count:nw {#3} } + { #1 \@@_use_none_delimit_by_s_mark:w } + } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/06/01}{\@@_guess_arg_count:NN} +%<latexrelease> {cmd~hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_guess_arg_count:NN +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% % % \begin{macro}{\@@_patch_retokenize:Nnnn} % Then, if \cs{@@_cmd_if_scanable:NnTF} returned true, we can go on % and patch the command. % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_patch_retokenize:Nnnn} +%<latexrelease> {cmd~hooks~with~args} \cs_new_protected:Npn \@@_patch_retokenize:Nnnn #1 #2 #3 #4 { +% Here, when patching by retokenization, we can only guess the number +% of arguments of the macro. +% \changes{v1.0h}{2023/05/21} +% {Changes to allow support arguments in cmd hooks (cmd-args).} +% \begin{macrocode} + \@@_guess_arg_count:NN #1 \l_@@_patch_num_args_int % \end{macrocode} -% Start off by making some things \tn{relax} to avoid lots of +% +% Then we redefine the hook to have the right number of arguments. +% Disabling the hook, undefining the \verb|parameter| token list then +% calling \cs{@@_make_usable:nn} are enough to redefine the hook to +% the extent we want. Code stored in the hook and other metadata +% about it are not lost in the process. +% \begin{macrocode} + \@@_disable:n {#2} + \cs_undefine:c { c_@@_#2_parameter_tl } + \@@_make_usable:nn {#2} { \l_@@_patch_num_args_int } + \tl_set:Ne \l_@@_tmpa_tl + { \exp_args:Ne \tl_to_str:n { \@@_braced_parameter:n {#2} } } + \use:x + { + \str_replace_all:Nnn \exp_not:N \l_@@_tmpa_tl + { #### } { \c_hash_str } + } +% \end{macrocode} +% Then, make make some things \tn{relax} to avoid lots of % \tn{noexpand} below. % \begin{macrocode} \cs_set_eq:NN \kerneltmpDoNotUse \scan_stop: @@ -1301,10 +1567,18 @@ ####1 \def \kerneltmpDoNotUse ####2 { \str_if_eq:nnT {#3} { before } - { \token_to_str:N \UseHook { cmd / #2 / #3 } } + { + \token_to_str:N \UseHookWithArguments {#2} + { \int_use:N \l_@@_patch_num_args_int } + \l_@@_tmpa_tl + } ####3 \str_if_eq:nnT {#3} { after } - { \token_to_str:N \UseHook { cmd / #2 / #3 } } + { + \token_to_str:N \UseHookWithArguments {#2} + { \int_use:N \l_@@_patch_num_args_int } + \l_@@_tmpa_tl + } } } % \end{macrocode} @@ -1328,7 +1602,39 @@ % {Make patching of commands a global operation (gh/674)} % \begin{macrocode} \cs_gset_eq:NN #1 \kerneltmpDoNotUse +% \end{macrocode} +% Finally, update the hook code. +% \begin{macrocode} + \@@_update_hook_code:n {#2} } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/06/01}{\@@_patch_retokenize:Nnnn} +%<latexrelease> {cmd~hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_patch_retokenize:Nnnn #1 #2 #3 #4 +%<latexrelease> { +%<latexrelease> \cs_set_eq:NN \kerneltmpDoNotUse \scan_stop: +%<latexrelease> \cs_set_eq:NN \@@_tmp:w \scan_stop: +%<latexrelease> \use:x +%<latexrelease> { +%<latexrelease> \cs_set:Npn \@@_tmp:w +%<latexrelease> ####1 \tl_to_str:n { macro: } ####2 -> ####3 \s_@@_mark +%<latexrelease> { +%<latexrelease> ####1 \def \kerneltmpDoNotUse ####2 +%<latexrelease> { +%<latexrelease> \str_if_eq:nnT {#3} { before } +%<latexrelease> { \token_to_str:N \UseHook { cmd / #2 / #3 } } +%<latexrelease> ####3 +%<latexrelease> \str_if_eq:nnT {#3} { after } +%<latexrelease> { \token_to_str:N \UseHook { cmd / #2 / #3 } } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> \tl_set:Nx \exp_not:N \l_@@_tmpa_tl +%<latexrelease> { \exp_not:N \@@_tmp:w \token_to_meaning:N #1 \s_@@_mark } +%<latexrelease> } +%<latexrelease> \tl_rescan:nV { #4 \@@_patch_required_catcodes: } \l_@@_tmpa_tl +%<latexrelease> \cs_gset_eq:NN #1 \kerneltmpDoNotUse +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % diff --git a/macros/latex/base/ltcntrl.dtx b/macros/latex/base/ltcntrl.dtx index 5ebe256c75..52dcdbf983 100644 --- a/macros/latex/base/ltcntrl.dtx +++ b/macros/latex/base/ltcntrl.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltcounts.dtx b/macros/latex/base/ltcounts.dtx index ffe2265ac3..69025fa479 100644 --- a/macros/latex/base/ltcounts.dtx +++ b/macros/latex/base/ltcounts.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltdefns.dtx b/macros/latex/base/ltdefns.dtx index bd820e7cf2..209c4e0fba 100644 --- a/macros/latex/base/ltdefns.dtx +++ b/macros/latex/base/ltdefns.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltdefns.dtx} - [2022/05/22 v1.5r LaTeX Kernel (definition commands)] + [2022/11/24 v1.5s LaTeX Kernel (definition commands)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltdefns.dtx} @@ -784,7 +784,9 @@ % not take arguments. (but may contain |\par|s) % % Make sure that an attempt to define a `graf' or `group' environment -% fails. +% fails by temporarily letting the undefined \verb=\...= (begin code) to +% the definition of \verb=\end...= and as a result we get an error if that +% has a definition. % \begin{macrocode} \long\def\@newenv#1#2#3#4{% \@ifundefined{#1}% @@ -1641,6 +1643,7 @@ % \end{macrocode} % % \begin{macro}{\declare@commandcopy} +% \begin{macro}{\declare@commandcopy@do} % 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 @@ -1650,11 +1653,14 @@ \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}}} + {\declare@commandcopy@do{#3}{#4}}} +\long\def\declare@commandcopy@do#1#2{% + \robust@command@act + \@declarecommandcopylisthook#2% + \declare@commandcopy@let{#1#2}} % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}{\@declarecommandcopylisthook} % The initial definition of \cs{@declarecommandcopylisthook} contains the @@ -1694,6 +1700,64 @@ % \end{macro} % % +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2023-06-01}{\DeclareEnvironmentCopy} +%<latexrelease> {Add \NewEnvironmentCopy, \RenewEnvironmentCopy, and \DeclareEnvironmentCopy}% +%<*2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macro}{\NewEnvironmentCopy} +% \begin{macro}{\RenewEnvironmentCopy} +% \begin{macro}{\DeclareEnvironmentCopy} +% If \verb=\#1= or \verb=\end#1= already exist one gets an error +% message talking about the problematical command (not the +% environment). +% The remainder of the \LaTeX{} run is probably badly +% broken and it is unlikely that continuing it gives +% reasonable results. +% \changes{v1.5s}{2022/11/24}{Add \cs{NewEnvironmentCopy}, +% \cs{RenewEnvironmentCopy}, and \cs{DeclareEnvironmentCopy} (gh/963)} +% \begin{macrocode} +\def\NewEnvironmentCopy{% + \declare@environmentcopy + {\@firstofone}% + {\@firstoftwo\@notdefinable}} +\def\RenewEnvironmentCopy{% + \declare@environmentcopy + {\@latex@error{Environment \reserved@a\space undefined}\@ehc + \@firstofone}% + {\@firstofone}} +\def\DeclareEnvironmentCopy{% + \declare@environmentcopy + {\@firstofone}% + {\@firstofone}} +\long\def\declare@environmentcopy#1#2#3#4{% + \edef\reserved@a{\@ifundefined{#3}{end#3}{#3}}% + \@ifundefined\reserved@a + {\def\reserved@a{#3}#1}% + {\def\reserved@a{#3}#2}% + {\ExpandArgs{cc}\declare@commandcopy@do{#3}{#4}% + \ExpandArgs{cc}\declare@commandcopy@do{end#3}{end#4}}} +% \end{macrocode} +% +% Now the rollback code. +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000-00-00}{\DeclareEnvironmentCopy} +%<latexrelease> {Undefine \NewEnvironmentCopy, \RenewEnvironmentCopy, and \DeclareEnvironmentCopy}% +%<latexrelease>\let\NewEnvironmentCopy\@undefined +%<latexrelease>\let\RenewEnvironmentCopy\@undefined +%<latexrelease>\let\DeclareEnvironmentCopy\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% % \subsubsection{Showing robust commands} % % \begin{macro}{\ShowCommand} @@ -1747,7 +1811,6 @@ % \end{macrocode} % \end{macro} % -% % \begin{macrocode} %</2ekernel> %<latexrelease>\IncludeInRelease{2020-10-01}{\@if@DeclareRobustCommand} @@ -1836,6 +1899,7 @@ % % \begin{macro}{\@show@DeclareRobustCommand} % \begin{macro}{\show@kernel@robust@command} +% \begin{macro}{\@show@macro} % 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. @@ -1863,12 +1927,14 @@ \robust@command@chk@safe#1% {\@if@newcommand#1% {\@show@newcommand}% - {\show}}% - {\show}% + {\@show@macro}}% + {\@show@macro}% #1} +\let\@show@macro\show % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \end{macro} % @@ -1931,7 +1997,7 @@ \typeout{->\@expl@cs@replacement@spec@@N#1.^^J}% \expandafter\@show@newcommand@aux \csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname - \expandafter{#1}} + \expandafter{#1}\@show@tokens} % \end{macrocode} % % For a macro defined with, say, |\newcommand\foo[1][opt]{bar}|, it will @@ -1946,20 +2012,28 @@ % \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{% +\long\def\@show@newcommand@aux#1#2#3{% \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}} + #3{default \string##1=\expandafter\detokenize\@gobblethree#2.^^J% + \@expl@cs@argument@spec@@N#1->\@expl@cs@replacement@spec@@N#1}} % \end{macrocode} % \end{macro} % \end{macro} % +% \begin{macro}{\@show@tokens} +% This macro prints the contents of the token list (macro) |#1| using +% \cs{showtokens}. The \cs{expandafter} gymnastics ensures that +% \cs{showtokens} itself, and the internals of this macro aren't +% showed in the context lines. +% \begin{macrocode} +\long\def\@show@tokens#1{% + \edef\reserved@a{#1}% + \showtokens\expandafter + \expandafter\expandafter{\expandafter\reserved@a}} +% \end{macrocode} +% \end{macro} +% % Now the rollback code. % \begin{macrocode} %</2ekernel|latexrelease> @@ -1985,6 +2059,124 @@ % \end{macro} % % +% \subsubsection{Showing environments} +% +% \begin{macro}{\ShowEnvironment} +% \changes{v1.5s}{2022/11/24}{Added \cs{ShowEnvironment}} +% +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2023-06-01}{\ShowEnvironment} +%<latexrelease> {Add \ShowEnvironment}% +%<*2ekernel|latexrelease> +% \end{macrocode} +% +% \cs{ShowEnvironment} is quite similar to \cs{ShowCommand}. We will +% pass the environment \meta{env} around as the macro +% \cs[no-index]{env}, because \cs{robust@command@act} expects a single +% token. +% \begin{macrocode} +\def\ShowEnvironment#1{% + \expandafter\@show@environment\csname #1\endcsname} +\long\def\@show@environment#1{% + \robust@command@act + \@showenvironmentlisthook#1% + \@show@normalenv#1} +% \end{macrocode} +% +% \begin{macro}{\@showenvironmentlisthook} +% This is similar to \cs{@showcommandlisthook}, but uses the dedicated +% versions for environments. +% \begin{macrocode} +\def\@showenvironmentlisthook{% + {\@if@DeclareRobustCommand \@show@DeclareRobustCommand@env}% + {\@if@newcommand \@show@newcommand@env}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@show@newcommand@env} +% \begin{macro}{\@show@DeclareRobustCommand@env} +% These are similar to the command versions below, except they say +% \enquote{environment} and call \cs{@show@environment@end} to print +% the \cs{end} part. +% \begin{macrocode} +\long\def\@show@newcommand@env#1{% + \@show@environment@begin#1% + \expandafter\@show@newcommand@aux + \csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname + \expandafter{#1}\@show@typeout + \@show@environment@end#1} +\long\def\@show@DeclareRobustCommand@env#1{% + \@show@environment@begin#1% + \begingroup + \let\@show@tokens\@show@typeout + \let\@show@macro\@show@nonstop + \expandafter\show@kernel@robust@command + \csname\@expl@cs@to@str@@N#1 \endcsname + \endgroup + \@show@environment@end#1} +\long\def\@show@environment@begin#1{% + \typeout{> \string\begin{\@expl@cs@to@str@@N#1}=environment:}% + \typeout{\@expl@cs@argument@spec@@N#1->% + \@expl@cs@replacement@spec@@N#1.^^J}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@show@normalenv} +% \begin{macro}{\@show@environment@end} +% A \enquote{normal} environment is straightforward. +% \cs{@show@environment@end} needs to check if the \cs{end} part is +% defined and show it accordingly, otherwise the output would show +% gibberish. +% \begin{macrocode} +\long\def\@show@normalenv#1{% + \@show@environment@begin#1% + \@show@environment@end#1} +\long\def\@show@environment@end#1{% + \expandafter\@show@environment@end@aux + \csname end\@expl@cs@to@str@@N#1\endcsname#1} +\long\def\@show@environment@end@aux#1#2{% + \@show@tokens{\string\end{\@expl@cs@to@str@@N#2}% + \ifx\relax#1=undefined% + \else:^^J\@expl@cs@argument@spec@@N#1->% + \@expl@cs@replacement@spec@@N#1% + \fi}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@show@nonstop} +% \begin{macro}{\@show@typeout} +% And here some auxiliaries: +% \begin{description} +% \item[\cs{@show@nonstop}] same output as \cs{show}, but doesn't +% stop for interaction; +% \item[\cs{@show@typeout}] same output as \cs{showtokens}, but +% doesn't stop for interaction. +% \end{description} +% \begin{macrocode} +\def\@show@nonstop#1{% + \typeout{> \string#1=\@expl@cs@prefix@spec@@N#1macro:^^J% + \@expl@cs@argument@spec@@N#1->\@expl@cs@replacement@spec@@N#1.}} +\def\@show@typeout#1{\typeout{> #1.^^J}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% Now the rollback code. +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000-00-00}{\ShowEnvironment} +%<latexrelease> {Undefine \ShowEnvironment}% +%<latexrelease>\let\ShowEnvironment\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% +% % \subsection{Internal defining commands} % % These commands are used internally to define other \LaTeX{} diff --git a/macros/latex/base/ltdirchk.dtx b/macros/latex/base/ltdirchk.dtx index 16a2ed9e68..6e02929754 100644 --- a/macros/latex/base/ltdirchk.dtx +++ b/macros/latex/base/ltdirchk.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/lterror.dtx b/macros/latex/base/lterror.dtx index b302a9a74c..77672168ce 100644 --- a/macros/latex/base/lterror.dtx +++ b/macros/latex/base/lterror.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltexpl.dtx b/macros/latex/base/ltexpl.dtx index aab189bec2..92e6de52cb 100644 --- a/macros/latex/base/ltexpl.dtx +++ b/macros/latex/base/ltexpl.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2019-2022 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltfilehook-code.pdf b/macros/latex/base/ltfilehook-code.pdf Binary files differindex fbaf7f0502..e52041c425 100644 --- a/macros/latex/base/ltfilehook-code.pdf +++ b/macros/latex/base/ltfilehook-code.pdf diff --git a/macros/latex/base/ltfilehook-doc.pdf b/macros/latex/base/ltfilehook-doc.pdf Binary files differindex bb38e6a544..392b3c05af 100644 --- a/macros/latex/base/ltfilehook-doc.pdf +++ b/macros/latex/base/ltfilehook-doc.pdf diff --git a/macros/latex/base/ltfilehook.dtx b/macros/latex/base/ltfilehook.dtx index c8503de891..e10a5416e5 100644 --- a/macros/latex/base/ltfilehook.dtx +++ b/macros/latex/base/ltfilehook.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment % -% Copyright (C) 2020-2022 -% Frank Mittelbach, Phelype Oleinik & LaTeX Team +% Copyright (C) 2020-2023 +% Frank Mittelbach, Phelype Oleinik and The LaTeX Project % % This file is part of the LaTeX base system. % ------------------------------------------- @@ -31,8 +31,8 @@ %%% From File: ltfilehook.dtx % % \begin{macrocode} -\providecommand\ltfilehookversion{v1.0n} -\providecommand\ltfilehookdate{2022/08/18} +\providecommand\ltfilehookversion{v1.0o} +\providecommand\ltfilehookdate{2023/04/02} % \end{macrocode} % %<*driver> @@ -1229,8 +1229,10 @@ % This auxiliary compares \cs{\meta{filename}} with % \cs{csname\cs{endcsname}} to check if the empty |.tex| file was % requested. +% \changes{v1.0o}{2023/04/02} +% {Make \cs{@set@curr@file@aux} \cs{long} gh/942} % \begin{macrocode} -\def\@set@curr@file@aux#1{% +\long\def\@set@curr@file@aux#1{% \expandafter\ifx\csname\endcsname#1% .tex\else\string#1\fi} % \end{macrocode} diff --git a/macros/latex/base/ltfiles.dtx b/macros/latex/base/ltfiles.dtx index d99dfdcd48..3bac7ea0b2 100644 --- a/macros/latex/base/ltfiles.dtx +++ b/macros/latex/base/ltfiles.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltfiles.dtx} - [2022/05/27 v1.2r LaTeX Kernel (File Handling)] + [2023/05/17 v1.2t LaTeX Kernel (File Handling)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltfiles.dtx} @@ -417,6 +417,16 @@ \ignorespaces} % \end{macrocode} % +% Provide a global definition for \cs{do} as well, so that it is +% already defined in the preamble and not late as +% \verb=\begin{document}= overwriting some definition given by the +% unsuspecting user in the preamble. +% \changes{v1.2s}{2023/01/05}{\cs{do} now with default definition in +% the kernel (gh/975)} +% \begin{macrocode} +\let\do\noexpand +% \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} @@ -1192,6 +1202,9 @@ % \changes{v1.0t}{1995/05/25}{(CAR) added \cs{long}} % \changes{v1.2d}{2019/10/26}{quote on openin} % \changes{v1.2k}{2021/03/12}{Allow unbalanced conditionals (gh/530)} +% \changes{v1.2t}{2023/05/15}{Use \pkg{expl3} file existence test} +% \begin{macro}{\IfFileExists@} +% \changes{v1.2t}{2023/05/15}{Macro added} % Argument |#1| is |\@curr@file| so catcode 12 string with no quotes. % % The original definition picked up arguments |#2| and |#3| in a @@ -1201,23 +1214,35 @@ % \cs{secondoftwo}. However, that changes how |#| is interpreted % and so we can't do that nowaways without invalidating a lot of % code. Therefore the somewhat curious construction near the end. +% +% Earlier versions used |\openin| here, but this led to two +% code paths, one in \pkg{expl3} and one here. To avoid that, +% and as the \pkg{expl3} approach works by expansion, we use +% that here. As we need the file name to include the path, +% the actual \pkg{expl3} function used is not the file existence +% test! % \begin{macrocode} %</2ekernel> %<*2ekernel|latexrelease> -%<latexrelease>\IncludeInRelease{2021/06/01}% -%<latexrelease> {\IfFileExists@}{manage unbalanced conditionals} +%<latexrelease>\IncludeInRelease{2023/05/01}% +%<latexrelease> {\IfFileExists@}{IfFileExists} \long\def \IfFileExists@#1#2#3{% - \openin\@inputcheck"#1" % - \ifeof\@inputcheck - \ifx\input@path\@undefined - \let\reserved@a\@secondoftwo + \edef\@filef@und{\IfFileExists@@{#1}}% +% \end{macrocode} +% The \pkg{expl3} function regards an empty argument as nothing at all, +% but the \LaTeXe{} convention is that this is equal to the special +% \texttt{.tex} file. +% \begin{macrocode} + \ifx\@filef@und\@empty + \if\relax\detokenize{#1}\relax + \let\reserved@a\@firstoftwo + \def\@filef@und{".tex" }% \else - \def\reserved@a{\@iffileonpath{#1}}% + \let\reserved@a\@secondoftwo \fi \else - \closein\@inputcheck - \edef\@filef@und{"#1" }% \let\reserved@a\@firstoftwo + \edef\@filef@und{"\@filef@und" }% \fi % \end{macrocode} % This is just there so that any |#| inside |#2| or |#3| needs @@ -1226,10 +1251,35 @@ \expandafter\def\expandafter\reserved@a \expandafter{\reserved@a{#2}{#3}}% \reserved@a} +\ExplSyntaxOn +\cs_new_eq:NN \IfFileExists@@ \file_full_name:n +\ExplSyntaxOff %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/06/01}% +%<latexrelease> {\IfFileExists@}{IfFileExists} +%<latexrelease> +%<latexrelease>\long\def \IfFileExists@#1#2#3{% +%<latexrelease> \openin\@inputcheck"#1" % +%<latexrelease> \ifeof\@inputcheck +%<latexrelease> \ifx\input@path\@undefined +%<latexrelease> \let\reserved@a\@secondoftwo +%<latexrelease> \else +%<latexrelease> \def\reserved@a{\@iffileonpath{#1}}% +%<latexrelease> \fi +%<latexrelease> \else +%<latexrelease> \closein\@inputcheck +%<latexrelease> \edef\@filef@und{"#1" }% +%<latexrelease> \let\reserved@a\@firstoftwo +%<latexrelease> \fi +%<latexrelease> \expandafter\def\expandafter\reserved@a +%<latexrelease> \expandafter{\reserved@a{#2}{#3}}% +%<latexrelease>\reserved@a} +%<latexrelease>\let\IfFileExists@@\@undefined +%<latexrelease>\EndIncludeInRelease +%<latexrelease> %<latexrelease>\IncludeInRelease{2019/10/01}% -%<latexrelease> {\IfFileExists@}{manage unbalanced conditionals} +%<latexrelease> {\IfFileExists@}{IfFileExists} %<latexrelease> %<latexrelease>\long\def \IfFileExists@#1#2#3{% %<latexrelease> \openin\@inputcheck"#1" % @@ -1247,7 +1297,7 @@ %<latexrelease> \reserved@a} %<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{0000/00/00}% -%<latexrelease> {\IfFileExists@}{manage unbalanced conditionals} +%<latexrelease> {\IfFileExists@}{IfFileExists} %<latexrelease> %<latexrelease>\let\IfFileExists@\@undefined %<latexrelease> @@ -1256,7 +1306,7 @@ %<*2ekernel> % \end{macrocode} % \end{macro} -% +% \end{macro} % % % diff --git a/macros/latex/base/ltfinal.dtx b/macros/latex/base/ltfinal.dtx index a19ffa8305..2652f6ce44 100644 --- a/macros/latex/base/ltfinal.dtx +++ b/macros/latex/base/ltfinal.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltfinal.dtx} - [2022/11/30 v2.2y LaTeX Kernel (Final Settings)] + [2023/05/30 v2.3c LaTeX Kernel (Final Settings)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltfinal.dtx} @@ -1062,6 +1062,24 @@ \fi % End of reset block for 8-bit engines % \end{macrocode} % +% \begin{macro}{\BCPdata} +% \changes{v2.3a}{2023/04/16}{Command added} +% A stub for use by \pkg{babel}, \pkg{polyglossia}, etc. +% \begin{macrocode} +\ExplSyntaxOn +\newcommand*\BCPdata[1]{ + \str_case:nn {#1} + { + { language } { en } + { region } { US } + { script } { Latn } + { tag } { en-US } + } +} +\ExplSyntaxOff +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\MakeUppercase} % \begin{macro}{\MakeLowercase} % \begin{macro}{\MakeTitlecase} @@ -1069,6 +1087,9 @@ % \begin{macro}{\AddToNoCaseChangeList} % \begin{macro}{\CaseSwitch} % \begin{macro}{\DeclareCaseChangeEquivalent} +% \begin{macro}{\DeclareLowercaseMapping} +% \begin{macro}{\DeclareTitlecaseMapping} +% \begin{macro}{\DeclareUppercaseMapping} % \begin{macro}{\@uclclist} % % @@ -1088,6 +1109,7 @@ % \changes{v2.2x}{2022/10/26}{Introduce optional argument for case-changing commands} % \changes{v2.2x}{2022/10/26}{Make case changing commands language-aware} % \changes{v2.2x}{2022/10/26}{Auto-detect \pkg{babel} locale} +% \changes{v2.3a}{2023/04/11}{Use new generic mechanism to detect locale} % Wrappers around the L3 case changing functions. % |\protected| to make them mostly safe as replacements for |uppercase| % and |\lowercase|. @@ -1121,33 +1143,24 @@ { \cs_set_nopar:Npn \reserved@a { } \tl_if_blank:nTF {#2} - { \@@text@case@aux@ } - { \keys_set:nn { __kernel } {#2} } - \use:c { text_ #1 case:Vn } \reserved@a {#3} - } -\cs_new_protected:Npn \@@text@case@aux@ { } -\tl_gput_right:Nn \@kernel@after@begindocument - { - \@ifpackageloaded { babel } { - \@ifpackagelater { babel } { 2020-01-15 } + \str_set:Nx \reserved@a + { \BCPdata { casing } } + \str_if_empty:NT \reserved@a { - \cs_gset_protected:Npn \@@text@case@aux@ - { - \str_set:Nx \reserved@a - { \localeinfo* { tag.bcp47 } } - } + \str_set:Nx \reserved@a + { \BCPdata { language } } } - { } } - { } + { \keys_set:nn { __kernel } {#2} } + \use:c { text_ #1 case:Vn } \reserved@a {#3} } -\exp_args_generate:n { cnx } % \end{macrocode} % The odd use of \emph{three} spaces here is needed as \pkg{ltcmd} uses the % name with one and two spaces to give a `friendly' error message for a runaway % argument: that means we can't use it here. % \begin{macrocode} +\exp_args_generate:n { cnx } \cs_set_protected:Npn \reserved@a #1 { \cs_generate_variant:cn { text_ \str_lowercase:n {#1} case:nn } { V } @@ -1161,36 +1174,35 @@ \reserved@a { Title } % \end{macrocode} % \changes{v2.2y}{2022/11/30}{Set \cs{oe}/\cs{OE} equal to act as a marker for \pkg{babel}} +% \changes{v2.2z}{2023/03/28}{Use groups for gh/1021} % Currently, \pkg{babel} uses the equivalence of \cs{oe} and \cs{OE} to force casing of % some material, most notably in \cs{today}. To enable that to work, we have to set those % commands equal even though the current case changing code does not work using this % approach. % \begin{macrocode} \cs_new_protected:cpn { MakeLowercase \c_space_tl \c_space_tl \c_space_tl } [#1] #2 - { - \let \kernel@saved@OE \OE + {{ \let \OE \oe \@@text@case@aux { lower } {#1} {#2} - \let \OE \kernel@saved@OE - } + }} \cs_new_protected:cpn { MakeUppercase \c_space_tl \c_space_tl \c_space_tl } [#1] #2 - { - \let \kernel@saved@oe \oe + {{ \let \oe \OE \@@text@case@aux { upper } {#1} {#2} - \let \oe \kernel@saved@oe - } + }} \cs_new_protected:cpn { MakeTitlecase \c_space_tl \c_space_tl \c_space_tl } [#1] #2 - { - \let \kernel@saved@oe \oe + {{ \let \oe \OE \@@text@case@aux { title } {#1} {#2} - \let \oe \kernel@saved@oe - } + }} % \end{macrocode} % % \changes{v2.2u}{2022/06/02}{Add \cs{NoCaseChange}} % \changes{v2.2u}{2022/06/30}{Add \cs{AddToNoCaseChangeList}} +% \changes{v2.3b}{2023/04/19}{Add \cs{DeclareLowercaseMapping}, +% \cs{DeclareTitlecaseMapping} and \cs{DeclareUppercaseMapping}} +% \changes{v2.3c}{2023/05/30}{Fix a typo in implementation of +% \cs{DeclareLowercaseMapping}, etc.} % |\NoCaseChange| protects its argument from the case change functions. % % |\AddToNoCaseChangeList| Allows new commands to protect their arguments, eg @@ -1204,6 +1216,27 @@ \cs_new_eq:NN \CaseSwitch \text_case_switch:nnnn \cs_new_eq:NN \DeclareCaseChangeEquivalent \text_declare_case_equivalent:Nn +\NewDocumentCommand \DeclareLowercaseMapping { o m m } + { + \IfNoValueTF {#1} + { \text_declare_lowercase_mapping:nn } + { \text_declare_lowercase_mapping:nnn {#1} } + {#2} {#3} + } +\NewDocumentCommand \DeclareTitlecaseMapping { o m m } + { + \IfNoValueTF {#1} + { \text_declare_titlecase_mapping:nn } + { \text_declare_titlecase_mapping:nnn {#1} } + {#2} {#3} + } +\NewDocumentCommand \DeclareUppercaseMapping { o m m } + { + \IfNoValueTF {#1} + { \text_declare_uppercase_mapping:nn } + { \text_declare_uppercase_mapping:nnn {#1} } + {#2} {#3} + } \ExplSyntaxOff % \end{macrocode} % @@ -1222,6 +1255,9 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % \changes{v1.0h}{1994/05/13}{Added output enc stuff} % \changes{v1.0i}{1994/05/16}{moved output enc stuff to lfonts} diff --git a/macros/latex/base/ltfloat.dtx b/macros/latex/base/ltfloat.dtx index 8b5b92759a..7247824548 100644 --- a/macros/latex/base/ltfloat.dtx +++ b/macros/latex/base/ltfloat.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltfntcmd.dtx b/macros/latex/base/ltfntcmd.dtx index 64064abcb5..bb6dbfe75c 100644 --- a/macros/latex/base/ltfntcmd.dtx +++ b/macros/latex/base/ltfntcmd.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltfssaxes.dtx b/macros/latex/base/ltfssaxes.dtx index 843e8b544c..9e68b38654 100644 --- a/macros/latex/base/ltfssaxes.dtx +++ b/macros/latex/base/ltfssaxes.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2019-2022 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltfssbas.dtx b/macros/latex/base/ltfssbas.dtx index cc43622a4b..fda3d1ca4b 100644 --- a/macros/latex/base/ltfssbas.dtx +++ b/macros/latex/base/ltfssbas.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -35,7 +35,7 @@ % % \ProvidesFile{ltfssbas.dtx} - [2022/07/04 v3.2k LaTeX Kernel (NFSS Basic Macros)] + [2023/04/01 v3.2l LaTeX Kernel (NFSS Basic Macros)] % \iffalse \documentclass{ltxdoc} \begin{document} @@ -1050,11 +1050,22 @@ % {\cs{def} $\to$ \cs{edef} for \cs{math@version}.} % \changes{v1.2g}{1990/02/16}{\cs{@nomath} added.} % \changes{v2.1a}{1994/01/17}{New math font setup} +% \changes{v3.2l}{2023/04/01}{Reset frozen mathversion gh/1028} % \begin{macrocode} \DeclareRobustCommand\mathversion[1] {\@nomath\mathversion \expandafter\ifx\csname mv@#1\endcsname\relax \@latex@error{Math version `#1' is not defined}\@eha\else +% \end{macrocode} +% If there has been a frozen math version reset locally. See GH 1028. +% \begin{macrocode} + \ifcsname mv@\math@version @frozen\endcsname + \expandafter\let + \csname mv@\math@version @frozen\expandafter\endcsname + \csname mv@\math@version\endcsname + \fi +% \end{macrocode} +% \begin{macrocode} \edef\math@version{#1}% % \end{macrocode} % We need to force a math font setup both now and at the point diff --git a/macros/latex/base/ltfsscmp.dtx b/macros/latex/base/ltfsscmp.dtx index 09f43a0d94..7bdfe2fd3e 100644 --- a/macros/latex/base/ltfsscmp.dtx +++ b/macros/latex/base/ltfsscmp.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltfssdcl.dtx b/macros/latex/base/ltfssdcl.dtx index 49041605e9..c3a743d249 100644 --- a/macros/latex/base/ltfssdcl.dtx +++ b/macros/latex/base/ltfssdcl.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltfssini.dtx b/macros/latex/base/ltfssini.dtx index 12e3b6289b..7b43f0228b 100644 --- a/macros/latex/base/ltfssini.dtx +++ b/macros/latex/base/ltfssini.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltfsstrc.dtx b/macros/latex/base/ltfsstrc.dtx index 699fd2c594..be0e6c68cf 100644 --- a/macros/latex/base/ltfsstrc.dtx +++ b/macros/latex/base/ltfsstrc.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/lthooks-code.pdf b/macros/latex/base/lthooks-code.pdf Binary files differindex eac5817e79..88b163641f 100644 --- a/macros/latex/base/lthooks-code.pdf +++ b/macros/latex/base/lthooks-code.pdf diff --git a/macros/latex/base/lthooks-doc.pdf b/macros/latex/base/lthooks-doc.pdf Binary files differindex 69ab35fb5a..d47c52c4ad 100644 --- a/macros/latex/base/lthooks-doc.pdf +++ b/macros/latex/base/lthooks-doc.pdf diff --git a/macros/latex/base/lthooks.dtx b/macros/latex/base/lthooks.dtx index cfa1454775..3807d25c44 100644 --- a/macros/latex/base/lthooks.dtx +++ b/macros/latex/base/lthooks.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment % -% Copyright (C) 2020-2022 -% Frank Mittelbach, Phelype Oleinik & LaTeX Team +% Copyright (C) 2020-2023 +% Frank Mittelbach, Phelype Oleinik, The LaTeX Project % % This file is part of the LaTeX base system. % ------------------------------------------- @@ -31,8 +31,8 @@ %%% From File: lthooks.dtx % % \begin{macrocode} -\def\lthooksversion{v1.0v} -\def\lthooksdate{2022/06/15} +\def\lthooksversion{v1.1e} +\def\lthooksdate{2023/06/06} % \end{macrocode} % %<*driver> @@ -148,7 +148,6 @@ % 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} @@ -156,7 +155,45 @@ % 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 \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}{\NewHookWithArguments} +% \begin{syntax} +% \cs{NewHookWithArguments} \Arg{hook} \Arg{number} +% \end{syntax} +% Creates a new \meta{hook} whose code takes \meta{number} arguments, +% and otherwise works exactly like \cs{NewHook}. +% Section~\ref{sec:hook-args} explains hooks with arguments. +% +% 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}{\NewReversedHookWithArguments} +% \begin{syntax} +% \cs{NewReversedHookWithArguments} \Arg{hook} \Arg{number} +% \end{syntax} +% Like \cs{NewReversedHook}, but creates a hook whose code takes +% \meta{number} arguments. +% Section~\ref{sec:hook-args} explains hooks with arguments. +% +% 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}{\NewMirroredHookPairWithArguments} +% \begin{syntax} +% \cs{NewMirroredHookPairWithArguments} \Arg{hook-1} \Arg{hook-2} \Arg{number} +% \end{syntax} +% A shorthand for +% \cs{NewHookWithArguments}\Arg{hook-1}\Arg{number}\\ +% \cs{NewReversedHookWithArguments}\Arg{hook-2}\Arg{number}. +% Section~\ref{sec:hook-args} explains hooks with arguments. +% +% The \meta{hook} can be specified using the dot-syntax to denote % the current package name. See section~\ref{sec:default-label}. % \end{function} % @@ -173,9 +210,9 @@ % \begin{syntax} % \cs{DisableGenericHook} \Arg{hook} % \end{syntax} -% After this declaration\footnotemark{} the \meta{hook} is no longer usable: Any -% attempt to add further code to it will result in an error and any -% use, e.g., via \cs{UseHook}, will simply do nothing. +% After this declaration\footnotemark{} the \meta{hook} is no longer +% usable: Any further attempt to add code to it will result in an +% error and any use, e.g., via \cs{UseHook}, will simply do nothing. % % This is intended to be used with generic command hooks (see % \texttt{ltcmdhooks-doc}) as depending on the definition of the @@ -215,7 +252,7 @@ % \begin{syntax} % \cs{UseHook} \Arg{hook} % \end{syntax} -% Execute the hook code inside a command or environment. +% Execute the code stored in the \meta{hook}. % % 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 @@ -227,14 +264,30 @@ % A leading |.| is treated literally. % \end{function} % +% \begin{function}{\UseHookWithArguments} +% \begin{syntax} +% \cs{UseHookWithArguments} \Arg{hook} \Arg{number} \Arg{arg_1} \ldots \Arg{arg_n} +% \end{syntax} +% Execute the code stored in the \meta{hook} and pass the arguments +% \Arg{arg_1} through \Arg{arg_n} to the \meta{hook}. Otherwise, it +% works exactly like \cs{UseHook}. +% The \meta{number} should be the number of arguments declared for +% the hook. If the hook is not declared, this command does nothing +% and it will remove \meta{number} items from the input. +% Section~\ref{sec:hook-args} explains hooks with arguments. +% +% 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[no-index]{\meta{addto-cmd}} command (e.g., +% \verb=\end{document}=. From that point onwards, adding to the hook +% through a defined \cs[no-index]{\meta{addto-cmd}} command (e.g., % \cs{AddToHook} or \cs{AtBeginDocument}, etc.\@) would have no % effect (as would the use of such a command inside the hook code % itself). It is therefore customary to redefine @@ -250,15 +303,30 @@ % section~\ref{sec:default-label} for details. % % Using \cs{UseOneTimeHook} several times with the same -% \Arg{hook} means that it only executes the first time it is used. +% \Arg{hook} means that it only executes the first time it is used. % For example, if it is used in a command that can be called several times -% then the hook executes during only the \emph{first} invocation of that +% then the hook executes during only the \emph{first} invocation of that % command; this allows its use as an \enquote{initialization hook}. % % Mixing \cs{UseHook} and \cs{UseOneTimeHook} for the same % \Arg{hook} should be avoided, but if this is done then neither will execute % after the first \cs{UseOneTimeHook}. +% \end{function} % +% \begin{function}{\UseOneTimeHookWithArguments} +% \begin{syntax} +% \cs{UseOneTimeHookWithArguments} \Arg{hook} \Arg{number} \Arg{arg_1} \ldots \Arg{arg_n} +% \end{syntax} +% Works exactly like \cs{UseOneTimeHook}, but passes arguments +% \Arg{arg_1} through \Arg{arg_n} to the \meta{hook}. +% The \meta{number} should be the number of arguments declared for +% the hook. If the hook is not declared, this command does nothing +% and it will remove \meta{number} items from the input. +% +% It should be noted that after a one-time hook is used, it is no +% longer possible to use \cs{AddToHookWithArguments} or similar with +% that hook. \cs{AddToHook} continues to work as normal. +% Section~\ref{sec:hook-args} explains hooks with arguments. % \end{function} % % @@ -294,6 +362,34 @@ % See section~\ref{sec:default-label}. % \end{function} % +% \begin{function}{\AddToHookWithArguments} +% \begin{syntax} +% \cs{AddToHookWithArguments} \Arg{hook}\oarg{label}\Arg{code} +% \end{syntax} +% Works exactly like \cs{AddToHook}, except that the \meta{code} can +% access the arguments passed to the hook using \verb|#1|, \verb|#2|, +% \ldots, \verb|#n| (up to the number of arguments declared for the +% hook). If the \meta{code} should contain \emph{parameter tokens} +% (\verb|#|) that are not supposed to be understood as the arguments +% of the hook, such tokens should be doubled. For example, with +% \cs{AddToHook} one can write: +%\begin{verbatim} +% \AddToHook{myhook}{\def\foo#1{Hello, #1!}} +%\end{verbatim} +% but to achieve the same with \cs{AddToHookWithArguments}, one should +% write: +%\begin{verbatim} +% \AddToHookWithArguments{myhook}{\def\foo##1{Hello, ##1!}} +%\end{verbatim} +% because in the latter case, \verb|#1| refers to the first argument +% of the hook \hook{myhook}. +% Section~\ref{sec:hook-args} explains hooks with arguments. +% +% 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} @@ -403,6 +499,19 @@ % \end{function}\footnotetext{There is % no mechanism to reorder such code chunks (or delete them).} % +% \begin{function}{\AddToHookNextWithArguments} +% \begin{syntax} +% \cs{AddToHookNextWithArguments} \Arg{hook}\Arg{code} +% \end{syntax} +% Works exactly like \cs{AddToHookNext}, but the \meta{code} can +% contain references to the arguments of the \meta{hook} as described +% for \cs{AddToHookWithArguments} above. +% Section~\ref{sec:hook-args} explains hooks with arguments. +% +% 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}{\ClearHookNext} @@ -511,10 +620,10 @@ % 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 +% the code in logical parts, but still use the main package name as the % \meta{label}, then the \meta{default label} can be set using -% \cs{SetDefaultHookLabel} or -% \cs{PushDefaultHookLabel}\verb={..}=\,\ldots\cs{PopDefaultHookLabel}. +% \cs{PushDefaultHookLabel}\verb={...}=\,\ldots\cs{PopDefaultHookLabel} +% or \cs{SetDefaultHookLabel}\verb={...}=. % % \begin{function}{\PushDefaultHookLabel,\PopDefaultHookLabel} % \begin{syntax} @@ -906,8 +1015,11 @@ % 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{function}{ +% \hook_new:n, +% \hook_new_reversed:n, +% \hook_new_pair:nn +% } % \begin{syntax} % \cs{hook_new:n} \Arg{hook} % \cs{hook_new_reversed:n} \Arg{hook} @@ -923,6 +1035,27 @@ % the current package name. See section~\ref{sec:default-label}. % \end{function} % +% \begin{function}{ +% \hook_new_with_args:nn, +% \hook_new_reversed_with_args:nn, +% \hook_new_pair_with_args:nnn +% } +% \begin{syntax} +% \cs{hook_new_with_args:nn} \Arg{hook} \Arg{number} +% \cs{hook_new_reversed_with_args:nn} \Arg{hook} \Arg{number} +% \cs{hook_new_pair_with_args:nnn} \Arg{hook-1} \Arg{hook-2} \Arg{number} +% \end{syntax} +% Creates a new \meta{hook} with normal or reverse ordering of code +% chunks, that takes \meta{number} arguments from the input stream +% when it is used. \cs{hook_new_pair_with_args: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_disable_generic:n} @@ -958,37 +1091,62 @@ % % % -% \begin{function}{\hook_use:n} +% \begin{function}{\hook_use:n,\hook_use:nnw} % \begin{syntax} % \cs{hook_use:n} \Arg{hook} +% \cs{hook_use:nnw} \Arg{hook} \Arg{number} \Arg{arg_1} \ldots \Arg{arg_n} % \end{syntax} % Executes the \Arg{hook} code followed (if set up) by the code for next % invocation only, then empties that next invocation code. +% \cs{hook_use:nnw} should be used for hooks declared with arguments, +% and should be followed by as many brace groups as the declared +% number of arguments. +% The \meta{number} should be the number of arguments declared for +% the hook. If the hook is not declared, this command does nothing +% and it will remove \meta{number} items from the input. % % 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{function}{\hook_use_once:n,\hook_use_once:nnw} % \begin{syntax} % \cs{hook_use_once:n} \Arg{hook} +% \cs{hook_use_once:nnw} \Arg{hook} \Arg{number} \Arg{arg_1} \ldots \Arg{arg_n} % \end{syntax} % Changes the \Arg{hook} status so that from now on any addition to % the hook code is executed immediately. Then execute any % \Arg{hook} code already set up. +% \cs{hook_use_once:nnw} should be used for hooks declared with arguments, +% and should be followed by as many brace groups as the declared +% number of arguments. +% The \meta{number} should be the number of arguments declared for +% the hook. If the hook is not declared, this command does nothing +% and it will remove \meta{number} items from the input. % % 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{function}{ +% \hook_gput_code:nnn, +% \hook_gput_code_with_args:nnn +% } % \begin{syntax} % \cs{hook_gput_code:nnn} \Arg{hook} \Arg{label} \Arg{code} +% \cs{hook_gput_code_with_args:nnn} \Arg{hook} \Arg{label} \Arg{code} % \end{syntax} % Adds a chunk of \meta{code} to the \meta{hook} labeled % \meta{label}. If the label already exists the \meta{code} is % appended to the already existing code. % +% If \cs{hook_gput_code_with_args:nnn} is used, the \meta{code} +% can access the arguments passed to \cs{hook_use:nnw} +% (or~\cs{hook_use_once:nnw}) with \verb|#1|, \verb|#2|, \ldots, +% \verb|#n| (up to the number of arguments declared for the hook). +% In that case, if an actual parameter token should be added to the +% code, it should be doubled. +% % 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 @@ -999,18 +1157,26 @@ % See section~\ref{sec:default-label}. % \end{function} % -% \begin{function} -% {\hook_gput_next_code:nn} +% \begin{function}{ +% \hook_gput_next_code:nn, +% \hook_gput_next_code_with_args: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. % +% If \cs{hook_gput_next_code_with_args:nn} is used, the \meta{code} +% can access the arguments passed to \cs{hook_use:nnw} +% (or~\cs{hook_use_once:nnw}) with \verb|#1|, \verb|#2|, \ldots, +% \verb|#n| (up to the number of arguments declared for the hook). +% In that case, if an actual parameter token should be added to the +% code, it should be doubled. +% % 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}. % @@ -1019,8 +1185,7 @@ % \end{function} % % -% \begin{function} -% {\hook_gclear_next_code:n} +% \begin{function}{\hook_gclear_next_code:n} % \begin{syntax} % \cs{hook_gclear_next_code:n} \Arg{hook} % \end{syntax} @@ -1240,7 +1405,7 @@ % \begin{itshape}\begin{color}{blue} ... % \end{itshape}\end{color} %\end{verbatim} -% and an error message that \verb=\begin{color}= ended by +% and an error message saying that \verb=\begin{color}= was 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 @@ -1377,9 +1542,9 @@ % you typically do not know what kind of variable parts may come up % in real documents. % -% For example, \pkg{babel} may want to provide hooks such as -% \hook{babel/\meta{language}/afterextras}. Language support in -% \pkg{babel} is often done through external language +% For example, \pkg{babel} provides hooks such as +% \hook{babel/\meta{language}/afterextras}. However, language +% support in \pkg{babel} is often done through external language % packages. Thus doing the activation for all languages inside the % core \pkg{babel} code is not a viable approach. Instead it needs % to be done by each language package (or by the user who wants to @@ -1396,6 +1561,125 @@ % conciderably. % % +% \subsection{Hooks with arguments} +% \label{sec:hook-args} +% +% Sometimes it is necessary to pass contextual information to a hook, +% and, for one reason or another, it is not feasible to store such +% information in macros. To serve this purpose, hooks can be +% declared with arguments, so that the programmer can pass along the +% data necessary for the code in the hook to function properly. +% +% A hook with arguments works mostly like a regular hook, and most +% commands that work for regular hooks, also work for hooks that take +% arguments. The differences are when the hook is declared +% (\cs{NewHookWithArguments} is used instead of \cs{NewHook}), then +% code can be added with both \cs{AddToHook} and +% \cs{AddToHookWithArguments}, and when the hook is used +% (\cs{UseHookWithArguments} instead of \cs{UseHook}). +% +% \medskip +% +% A hook with arguments must be declared as such (before it is first +% used, as all regular hooks) using +% \cs{NewHookWithArguments}\Arg{hook}\Arg{number}. All code added to +% that hook can then use \verb|#1| to access the first argument, +% \verb|#2| to access the second, and so forth up to the number of +% arguments declared. However, it is still possible to add code with +% references to the arguments of a hook that was not yet declared +% (we will discuss that later). At their core, hooks are macros, so +% \TeX's limit of 9~arguments applies, and a low-level \TeX{} error +% is raised if you try to reference an argument number that doesn't +% exist. +% +% \medskip +% +% To use a hook with arguments, just write +% \cs{UseHookWithArguments}\Arg{hook}\Arg{number} followed by a +% braced list of the arguments. For example, if the hook \hook{test} +% takes three arguments, write: +%\begin{verbatim} +% \UseHookWithArguments{test}{3}{arg-1}{arg-2}{arg-3} +%\end{verbatim} +% then, in the \meta{code} of the hook, all instances of \verb|#1| +% will be replaced by \verb|arg-1|, \verb|#2| by \verb|arg-2| and so +% on. If, at the point of usage, the programmer provides more +% arguments than the hook is declared to take, the excess arguments +% are simply ignored by the hook. Behaviour is +% unpredictable\footnote +% {The hook \emph{will} take the declared number of arguments, and +% what will happen depends on what was grabbed, and what the hook +% code does with its arguments.} +% if too few arguments are provided. If the hook isn't declared, +% \meta{number} arguments are removed from the input stream. +% +% \medskip +% +% Adding code to a hook with arguments can be done with +% \cs{AddToHookWithArguments} as well as with the regular +% \cs{AddToHook}, to achieve different outcomes. The main difference +% when it comes to adding code to a hook, in this case, is firstly +% the possibility of accessing a hook's arguments, of course, and +% second, how parameter tokens (\verb|#|$_6$) are treated. +% +% Using \cs{AddToHook} in a hook that takes arguments will work as it +% does for all other hooks. This allows a package developer to add +% arguments to a hook that otherwise had none without having to worry +% about compatibility. This means that, for example: +%\begin{verbatim} +% \AddToHook{test}{\def\foo#1{Hello, #1!}} +%\end{verbatim} +% will define the same macro \cs[no-index]{foo} regardless if the +% hook \hook{test} takes arguments or not. +% +% Using \cs{AddToHookWithArguments} allows the \meta{code} added to +% access the arguments of the hook with \verb|#1|, \verb|#2|, and so +% forth, up to the number of the arguments declared in the hook. +% This means that if one wants to add a \verb|#|$_6$ to the +% \meta{code} that token must be doubled in the input. The same +% definition from above, using \cs{AddToHookWithArguments}, needs to +% be rewritten: +%\begin{verbatim} +% \AddToHookWithArguments{test}{\def\foo##1{Hello, ##1!}} +%\end{verbatim} +% +% Extending the above example to use the hook arguments, we could +% rewrite something like (now from declaration to usage, to get the +% whole picture): +%\begin{verbatim} +% \NewHookWithArguments{test}{1} +% \AddToHookWithArguments{test}{% +% \typeout{Defining foo with "#1"} +% \def\foo##1{Hello, ##1! Some text after: #1}% +% } +% \UseHook{test}{Howdy!} +% \ShowCommand\foo +%\end{verbatim} +% Running the code above prints in the terminal: +%\begin{verbatim} +% Defining foo with "Howdy!" +% > \foo=macro: +% #1->Hello, #1! Some text after: Howdy!. +%\end{verbatim} +% Note how \verb|##1| in the call to \cs{AddToHookWithArguments} +% became \verb|#1|, and the \verb|#1| was replaced by the argument +% passed to the hook. Should the hook be used again, with a +% different argument, the definition would naturally change. +% +% \bigskip +% +% It is possible to add code referencing a hook's arguments before +% such hook is declared and the number of hooks is fixed. However, +% if some code is added to the hook, that references more arguments +% than will be declared for the hook, there will be a low-level +% \TeX{} error about an \enquote{Illegal parameter number} at the +% time the hook is declared, which will be hard to track down because +% at that point \TeX{} can't know whence the offending code came +% from. Thus it is important that package writers explicitly +% document how many arguments (if any) each hook can take, so users +% of those packages know how many arguments can be referenced, and +% equally important, what each argument means. +% % \subsection{Private \LaTeX{} kernel hooks} % % There are a few places where it is absolutely essential for @@ -1461,7 +1745,7 @@ % package/class name if called inside such a file % (see section~\ref{sec:default-label}). % -% This way one can add further code to the hook using +% This way one can add 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 another package's code. When using the @@ -1746,10 +2030,10 @@ % % \subsection{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 +% \LaTeXe{} has always provided \cs{AtEndDocument} to add code to the +% \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 +% 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. @@ -2095,13 +2379,37 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int]{\tl_gremove_once:Nx,\tl_show:x,\tl_log:x} +% \begin{macro}{\c_@@_empty_tl} +% \begin{macro}{\c_@@_nine_parameters_tl} +% An empty token list, and one containing nine parameters. +% \changes{v1.1a}{2023/04/06} +% {Add auxiliary token lists (hook-args).} +% \begin{macrocode} +\tl_const:Nn \c_@@_empty_tl { } +\tl_const:Nn \c_@@_nine_parameters_tl { #1#2#3#4#5#6#7#8#9 } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int]{ +% \tl_gremove_once:Nx, +% \tl_show:x, +% \tl_log:x, +% \tl_set:Ne, +% \cs_replacement_spec:c, +% \prop_put:Nne, +% \str_count:e +% } % Some variants of \pkg{expl3} functions. % \fmiinline{should probably be moved to expl3} % \begin{macrocode} \cs_generate_variant:Nn \tl_gremove_once:Nn { Nx } \cs_generate_variant:Nn \tl_show:n { x } \cs_generate_variant:Nn \tl_log:n { x } +\cs_generate_variant:Nn \tl_set:Nn { Ne } +\cs_generate_variant:Nn \cs_replacement_spec:N { c } +\cs_generate_variant:Nn \prop_put:Nnn { Nne } +\cs_generate_variant:Nn \str_count:n { e } % \end{macrocode} % \end{macro} % @@ -2112,15 +2420,20 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_clean_to_scan:w} +% \begin{macro}{ +% \@@_use_none_delimit_by_s_mark:w, +% \@@_use_i_delimit_by_s_mark:nw +% } % Removes tokens until the next \cs{s_@@_mark}. +% \changes{v1.1a}{2023/04/06} +% {Use standard naming scheme (hook-args).} % \begin{macrocode} -\cs_new:Npn \@@_clean_to_scan:w #1 \s_@@_mark { } +\cs_new:Npn \@@_use_none_delimit_by_s_mark:w #1 \s_@@_mark { } +\cs_new:Npn \@@_use_i_delimit_by_s_mark:nw #1 #2 \s_@@_mark {#1} % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_tl_set:Nn,\@@_tl_set:Nx, -% \@@_tl_set:cn,\@@_tl_set:cx} +% \begin{macro}{\@@_tl_set:cn} % Private copies of a few \pkg{expl3} functions. \pkg{l3debug} will % only add debugging to the public names, not to these copies, so we % don't have to use \cs{debug_suspend:} and \cs{debug_resume:} @@ -2130,44 +2443,43 @@ % copied because in \pkg{expl3} they use % \cs[no-index]{__kernel_tl_(g)set:Nx}, which is also patched by % \pkg{l3debug}. -% \changes{v1.0h}{2021/01/07}{Manually define some \pkg{l3tl} commands +% \changes{v1.0h}{2021/01/07}{Manually define some \pkg{l3tl} commands % to work around \pkg{expl3} changes} +% \changes{v1.1a}{2023/04/06} +% {Clean-up unused variants (hook-args).} % \begin{macrocode} -\cs_new_protected:Npn \@@_tl_set:Nn #1#2 - { \cs_set_nopar:Npx #1 { \__kernel_exp_not:w {#2} } } -\cs_new_protected:Npn \@@_tl_set:Nx #1#2 - { \cs_set_nopar:Npx #1 {#2} } -\cs_generate_variant:Nn \@@_tl_set:Nn { c } -\cs_generate_variant:Nn \@@_tl_set:Nx { c } +\cs_new_protected:Npn \@@_tl_set:cn #1#2 + { \cs_set_nopar:cpx {#1} { \__kernel_exp_not:w {#2} } } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_tl_gset:Nn,\@@_tl_gset:No,\@@_tl_gset:Nx, +% \begin{macro}{\@@_tl_gset:Nn,\@@_tl_gset:Nx, % \@@_tl_gset:cn,\@@_tl_gset:co,\@@_tl_gset:cx} % Same as above. % \begin{macrocode} \cs_new_protected:Npn \@@_tl_gset:Nn #1#2 { \cs_gset_nopar:Npx #1 { \__kernel_exp_not:w {#2} } } -\cs_new_protected:Npn \@@_tl_gset:No #1#2 - { \cs_gset_nopar:Npx #1 { \__kernel_exp_not:w \exp_after:wN {#2} } } \cs_new_protected:Npn \@@_tl_gset:Nx #1#2 { \cs_gset_nopar:Npx #1 {#2} } -\cs_generate_variant:Nn \@@_tl_gset:Nn { c } -\cs_generate_variant:Nn \@@_tl_gset:No { c } +\cs_generate_variant:Nn \@@_tl_gset:Nn { c, co } \cs_generate_variant:Nn \@@_tl_gset:Nx { c } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_tl_gput_right:Nn,\@@_tl_gput_right:No,\@@_tl_gput_right:cn} +% \begin{macro}{ +% \@@_tl_gput_right:Nn, +% \@@_tl_gput_right:Ne, +% \@@_tl_gput_right:cn, +% } % Same as above. % \begin{macrocode} \cs_new_protected:Npn \@@_tl_gput_right:Nn #1#2 { \@@_tl_gset:Nx #1 { \__kernel_exp_not:w \exp_after:wN { #1 #2 } } } -\cs_generate_variant:Nn \@@_tl_gput_right:Nn { No, cn } +\cs_generate_variant:Nn \@@_tl_gput_right:Nn { Ne, cn } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_tl_gput_left:Nn,\@@_tl_gput_left:No} +% \begin{macro}{\@@_tl_gput_left:Nn} % Same as above. % \begin{macrocode} \cs_new_protected:Npn \@@_tl_gput_left:Nn #1#2 @@ -2175,7 +2487,6 @@ \@@_tl_gset:Nx #1 { \__kernel_exp_not:w {#2} \__kernel_exp_not:w \exp_after:wN {#1} } } -\cs_generate_variant:Nn \@@_tl_gput_left:Nn { No } % \end{macrocode} % \end{macro} % @@ -2202,7 +2513,11 @@ % % \DescribeMacro{\g_@@_\meta{hook}_code_prop} % \DescribeMacro{\@@\textvisiblespace\meta{hook}} +% \DescribeMacro{\g_@@_\meta{hook}_reversed_tl} +% \DescribeMacro{\g_@@_\meta{hook}_declared_tl} +% \DescribeMacro{\g_@@_\meta{hook}_parameter_tl} % \DescribeMacro{\@@_next\textvisiblespace\meta{hook}} +% \DescribeMacro{\@@_toplevel\textvisiblespace\meta{hook}} % Hooks have a name (called \meta{hook} in the description below) % and for each hook we have to % provide a number of data structures. These are @@ -2232,12 +2547,17 @@ % so that it can be identified. The |-| character is used because % $\meta{reversed}1$ is $+1$ for normal hooks and $-1$ for reversed % ones. - +% % \item[{\cs[no-index]{g_@@_\meta{hook}_declared_tl}}] This token -% list serves as marker for the hook being officially declared. Its +% list serves as a marker for the hook being officially declared. Its % existence is tested to raise an error in case another declaration % is attempted. % +% \item[{\cs[no-index]{c_@@_\meta{hook}_parameter_tl}}] This token +% list stores the parameter text for a declared hook (its existence +% almost completely intersects the token list above), which is used +% for managing hooks with arguments. +% % \item[\cs{@@_toplevel\textvisiblespace\meta{hook}}] This token list stores the code % inserted in the hook from the user's document, in the |top-level| % label. This label is special, and doesn't participate in sorting. @@ -2367,45 +2687,92 @@ % \subsubsection{Setting hooks up} % % -% \begin{macro}{\hook_new:n,\@@_new:n} +% \begin{macro}{ +% \hook_new:n, +% \hook_new_with_args:nn +% } +% \begin{macro}{@@_new:nn} % The \cs{hook_new:n} declaration declares a new hook and expects % the hook \meta{name} as its argument, e.g., % \hook{begindocument}. +% \changes{v1.1a}{2023/04/06} +% {Add \cs{hook_new_with_args:nn} (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_new_with_args:nn} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \hook_new:n #1 - { \@@_normalize_hook_args:Nn \@@_new:n {#1} } + { \@@_normalize_hook_args:Nn \@@_new:nn {#1} { 0 } } +\cs_new_protected:Npn \hook_new_with_args:nn #1 #2 + { \@@_normalize_hook_args:Nn \@@_new:nn {#1} {#2} } % \end{macrocode} % % \begin{macrocode} -\cs_new_protected:Npn \@@_new:n #1 +\cs_new_protected:Npn \@@_new:nn #1 #2 { % \end{macrocode} % We check if the hook was already \emph{explicitly} declared with % \cs{hook_new:n}, and if it already exists we complain, otherwise set % the \enquote{created} flag for the hook so that it errors next time % \cs{hook_new:n} is used. +% \changes{v1.1d}{2023/05/21} +% {Changes to allow support arguments in cmd hooks (cmd-args).} % \begin{macrocode} \@@_if_declared:nTF {#1} { \msg_error:nnn { hooks } { exists } {#1} } { \tl_new:c { g_@@_#1_declared_tl } - \@@_make_usable:n {#1} + \cs_undefine:c { @@~#1 } + \cs_undefine:c { c_@@_#1_parameter_tl } + \@@_make_usable:nn {#1} {#2} +% \end{macrocode} +% In case there is already code in a hook, but it's undeclared, run +% \cs{@@_update_hook_code:n} to make it ready to be executed (see test +% \texttt{lthooks-034}). +% \changes{v1.1a}{2023/04/06} +% {Update hook code after declaring.} +% \begin{macrocode} + \@@_update_hook_code:n {#1} } } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_new_with_args:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \hook_new:n #1 +%<latexrelease> { \@@_normalize_hook_args:Nn \@@_new:n {#1} } +%<latexrelease>\cs_undefine:N \@@_new:nn +%<latexrelease>\cs_gset_protected:Npn \@@_new:n #1 +%<latexrelease> { +%<latexrelease> \@@_if_declared:nTF {#1} +%<latexrelease> { \msg_error:nnn { hooks } { exists } {#1} } +%<latexrelease> { +%<latexrelease> \tl_new:c { g_@@_#1_declared_tl } +%<latexrelease> \@@_make_usable:n {#1} +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\cs_gset_protected:Npn \hook_new_with_args:nn #1 { } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % % % -% \begin{macro}{\@@_make_usable:n} +% \begin{macro}{\@@_make_usable:nn} % % This initializes all hook data structures for the hook but if % used on its own doesn't mark the hook as declared (as % \cs{hook_new:n} does, so a later \cs{hook_new:n} on that hook will % not result in an error. This command is internally used by -% \cs{hook_gput_code:n} when adding code to a generic hook. +% \cs{hook_gput_code:nnn} when adding code to a generic hook. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} -\cs_new_protected:Npn \@@_make_usable:n #1 +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_make_usable:nn} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_make_usable:nn #1 #2 { % \end{macrocode} % Now we check if the hook's data structure can be safely created @@ -2414,29 +2781,70 @@ % allocate the necessary data structures for the new hook, % otherwise just do nothing. % \begin{macrocode} - \tl_if_exist:cF { @@~#1 } + \@@_if_usable:nF {#1} { \seq_gput_right:Nn \g_@@_all_seq {#1} % \end{macrocode} +% Here we'll define the \cs[no-index]{c_@@_\meta{hook}_parameter_tl} +% to hold a run of parameters up to the number of arguments of the +% hook (\verb|#2|). +% \begin{macrocode} + \__kernel_cs_parm_from_arg_count:nnF + { \tl_const:cn { c_@@_#1_parameter_tl } } {#2} + { + \msg_error:nnnn { hooks } { too-many-args } {#1} {#2} + \tl_const:cx { c_@@_#1_parameter_tl } + { \exp_not:V \c_@@_nine_parameters_tl } + } +% \end{macrocode} +% After that, use \cs{@@_normalise_cs_args:nn} to correct the number +% of parameters of the macros +% \cs[no-index]{@@_toplevel\textvisiblespace\meta{hook}} and +% \cs[no-index]{@@_next\textvisiblespace\meta{hook}}. We need to be +% able to add +% code with arguments to a hook without prior knowledge of the number +% of arguments of that hook, so \pkg{lthooks} assumes~9 until the +% hook is properly declared and the number of arguments is known. +% \cs{@@_normalise_cs_args:nn} does the normalisation by using the +% \cs[no-index]{c_@@_\meta{hook}_parameter_tl} defined just above. +% \begin{macrocode} + \@@_normalise_cs_args:nn { _toplevel } {#1} + \@@_normalise_cs_args:nn { _next } {#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 } + \@@_code_gset:nn {#1} { } % \end{macrocode} % Now ensure that the base data structure for the hook exists: % \begin{macrocode} \@@_init_structure:n {#1} % \end{macrocode} +% The call to \cs{@@_normalise_code_pool:n} will correct any improper +% reference to arguments that don't exist in the hook, raising a +% low-level \TeX{} error and doubling the offending parameter tokens. +% It has to be done after \cs{@@_init_structure:n} because it +% operates on \cs[no-index]{g_@@_\meta{hook}_code_prop}. +% \begin{macrocode} + \@@_normalise_code_pool: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. +% These are defined conditionally, in case \cs{@@_make_usable:nn} +% is being used to redefine a hook. +% \changes{v1.1d}{2023/05/21} +% {Changes to allow support arguments in cmd hooks (cmd-args).} % \begin{macrocode} - \clist_new:c { g_@@_#1_labels_clist } + \clist_if_exist:cF { g_@@_#1_labels_clist } + { + \clist_new:c { g_@@_#1_labels_clist } % \end{macrocode} % Some hooks should reverse the default order of code chunks. To % signal this we have a token list which is empty for normal hooks % and contains a \verb=-= for reversed hooks. % \begin{macrocode} - \tl_new:c { g_@@_#1_reversed_tl } + \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}, @@ -2454,9 +2862,28 @@ \@@_include_legacy_code_chunk:n {#1} } } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} -% \end{macro} % +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_make_usable:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_make_usable:nn +%<latexrelease>\cs_gset_protected:Npn \@@_make_usable:n #1 +%<latexrelease> { +%<latexrelease> \tl_if_exist:cF { @@~#1 } +%<latexrelease> { +%<latexrelease> \seq_gput_right:Nn \g_@@_all_seq {#1} +%<latexrelease> \tl_new:c { @@~#1 } +%<latexrelease> \@@_init_structure:n {#1} +%<latexrelease> \clist_new:c { g_@@_#1_labels_clist } +%<latexrelease> \tl_new:c { g_@@_#1_reversed_tl } +%<latexrelease> \@@_include_legacy_code_chunk:n {#1} +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} % % % \begin{macro}{\@@_init_structure:n} @@ -2472,49 +2899,124 @@ % \cs{@@_init_structure:n} the first time anything is added to it. % Initializing a hook just with \cs{@@_init_structure:n} will not % make it usable with \cs{hook_use:n}. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_init_structure:n} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \@@_init_structure:n #1 { \@@_if_structure_exist:nF {#1} { \prop_new:c { g_@@_#1_code_prop } - \tl_new:c { @@_toplevel~#1 } - \tl_new:c { @@_next~#1 } + \@@_toplevel_gset:nn {#1} { } + \@@_next_gset:nn {#1} { } } } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} -% \end{macro} -% % +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_init_structure:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_init_structure:n #1 +%<latexrelease> { +%<latexrelease> \@@_if_structure_exist:nF {#1} +%<latexrelease> { +%<latexrelease> \prop_new:c { g_@@_#1_code_prop } +%<latexrelease> \tl_new:c { @@_toplevel~#1 } +%<latexrelease> \tl_new:c { @@_next~#1 } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} % -% \begin{macro}{\hook_new_reversed:n,\@@_new_reversed:n} +% \begin{macro}{ +% \hook_new_reversed:n, +% \hook_new_reversed_with_args:nn +% } +% \begin{macro}{\@@_new_reversed:nn} % % Declare a new hook. The default ordering of code chunks is % reversed, signaled by setting the token list to a minus sign. +% \changes{v1.1a}{2023/04/06} +% {Add \cs{hook_new_reversed_with_args:nn} (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_new_reversed_with_args:nn} +%<latexrelease> {Hooks~with~args} \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 + { \@@_normalize_hook_args:Nn \@@_new_reversed:nn {#1} { 0 } } +\cs_new_protected:Npn \hook_new_reversed_with_args:nn #1 #2 + { \@@_normalize_hook_args:Nn \@@_new_reversed:nn {#1} {#2} } +\cs_new_protected:Npn \@@_new_reversed:nn #1 #2 { - \@@_new:n {#1} + \@@_if_declared:nTF {#1} + { \msg_error:nnn { hooks } { exists } {#1} } + { + \@@_new:nn {#1} {#2} + \tl_gset:cn { g_@@_#1_reversed_tl } { - } + } + } +%<latexrelease>\EndIncludeInRelease % \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 } { - } - } +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_new_reversed_with_args:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \hook_new_reversed:n #1 +%<latexrelease> { \@@_normalize_hook_args:Nn \@@_new_reversed:n {#1} } +%<latexrelease>\cs_undefine:N \@@_new_reversed:nn +%<latexrelease>\cs_gset_protected:Npn \@@_new_reversed:n #1 +%<latexrelease> { +%<latexrelease> \@@_new:n {#1} +%<latexrelease> \tl_gset:cn { g_@@_#1_reversed_tl } { - } +%<latexrelease> } +%<latexrelease>\cs_undefine:N \@@_new_reversed:nn +%<latexrelease>\cs_gset_protected:Npn \hook_new_reversed_with_args:nn #1 #2 { } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} +% \end{macro} % -% -% -% -% \begin{macro}{\hook_new_pair:nn} +% \begin{macro}{\hook_new_pair:nn,\hook_new_pair_with_args:nnn} % A shorthand for declaring a normal and a (matching) reversed hook in one go. +% \changes{v1.1a}{2023/04/06} +% {Add \cs{hook_new_pair_with_args:nnn} (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_new_pair_with_args:nnn} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \hook_new_pair:nn #1#2 - { \hook_new:n {#1} \hook_new_reversed:n {#2} } + { \@@_normalize_hook_args:Nnn \@@_new_pair:nnn {#1} {#2} { 0 } } +\cs_new_protected:Npn \hook_new_pair_with_args:nnn #1#2#3 + { \@@_normalize_hook_args:Nnn \@@_new_pair:nnn {#1} {#2} {#3} } +\cs_new_protected:Npn \@@_new_pair:nnn #1 #2 #3 + { + \@@_if_declared:nTF {#1} + { \msg_error:nnn { hooks } { exists } {#1} } + { + \@@_if_declared:nTF {#2} + { \msg_error:nnn { hooks } { exists } {#2} } + { + \@@_new:nn {#1} {#3} + \@@_new_reversed:nn {#2} {#3} + } + } + } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_new_pair_with_args:nnn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \hook_new_pair:nn #1#2 +%<latexrelease> { +%<latexrelease> \hook_new:n {#1} +%<latexrelease> \hook_new_reversed:n {#2} +%<latexrelease> } +%<latexrelease>\cs_gset_protected:Npn \hook_new_pair_with_args:nnn #1#2#3 +%<latexrelease> { } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -2531,6 +3033,8 @@ % \textbf{Warning: this support will vanish in future releases!} % \end{quote} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_include_legacy_code_chunk:n} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \@@_include_legacy_code_chunk:n #1 { % \end{macrocode} @@ -2538,15 +3042,27 @@ % 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} +% Here we set \cs{@@_replacing_args_false:} because no legacy code +% will reference hook arguments. +% \changes{v1.1b}{2023/04/16} +% {\cs{@@_replacing_args_false:} in +% \cs{@@_include_legacy_code_chunk:n}.} +% \begin{macrocode} + \@@_replacing_args_false: + \use:e + { + \@@_hook_gput_code_do:nnn {#1} { legacy } + { \exp_not:v { @#1hook } } + } + \@@_replacing_args_reset: % \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. @@ -2555,6 +3071,22 @@ } } } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_include_legacy_code_chunk:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_include_legacy_code_chunk:n #1 +%<latexrelease> { +%<latexrelease> \tl_if_exist:cT { @#1hook } +%<latexrelease> { +%<latexrelease> \tl_if_empty:cF { @#1hook } +%<latexrelease> { +%<latexrelease> \exp_args:Nnnv \@@_hook_gput_code_do:nnn +%<latexrelease> {#1} { legacy } { @#1hook } +%<latexrelease> \@@_tl_gclear:c { @#1hook } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -2579,8 +3111,8 @@ % if the hook is disabled. % % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/06/01}% -%<latexrelease> {\hook_disable_generic:n}{Disable~hooks} +%<latexrelease>\IncludeInRelease{2021/06/01}{\hook_disable_generic:n} +%<latexrelease> {Disable~hooks} % \end{macrocode} % % \begin{macrocode} @@ -2595,7 +3127,7 @@ { \bool_lazy_and:nnTF { \tl_if_exist_p:c { g_@@_#1_declared_tl } } - { ! \tl_if_exist_p:c { @@~#1 } } + { ! \cs_if_exist_p:c { @@~#1 } } { \prg_return_true: } { \prg_return_false: } } @@ -2603,8 +3135,8 @@ % \end{macrocode} % % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2020/10/01} -%<latexrelease> {\hook_disable_generic:n}{Disable~hooks} +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_disable_generic:n} +%<latexrelease> {Disable~hooks} %<latexrelease> %<latexrelease>\cs_new_protected:Npn \hook_disable_generic:n #1 {} %<latexrelease> @@ -2619,9 +3151,11 @@ % The \cs{hook_activate_generic:n} declaration declares a new hook if it % wasn't declared already, in which case it only checks that the % already existing hook is not a reversed hook. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/06/01}% -%<latexrelease> {\hook_activate_generic:n}{Providing~hooks} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_activate_generic:n} +%<latexrelease> {Providing~hooks} % \end{macrocode} % % \begin{macrocode} @@ -2646,7 +3180,7 @@ \@@_if_declared:nF {#1} { \tl_new:c { g_@@_#1_declared_tl } - \@@_make_usable:n {#1} + \@@_make_usable:nn {#1} { 0 } \tl_gset:cx { g_@@_#1_reversed_tl } { \@@_if_generic_reversed:nT {#1} { - } } % \end{macrocode} @@ -2660,22 +3194,41 @@ } } % \end{macrocode} -% \end{macro} -% \end{macro} % % \begin{macrocode} %<latexrelease>\EndIncludeInRelease % \end{macrocode} % % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2020/10/01} -%<latexrelease> {\hook_activate_generic:n}{Providing~hooks} -%<latexrelease> -%<latexrelease>\cs_new_protected:Npn \hook_activate_generic:n #1 {} -%<latexrelease> +%<latexrelease>\IncludeInRelease{2021/06/01}{\hook_activate_generic:n} +%<latexrelease> {Providing~hooks} +%<latexrelease>\cs_gset_protected:Npn \@@_activate_generic:nn #1 #2 +%<latexrelease> { +%<latexrelease> \@@_if_disabled:nTF {#1} +%<latexrelease> { \msg_warning:nnn { hooks } { activate-disabled } {#1} } +%<latexrelease> { +%<latexrelease> \@@_if_declared:nF {#1} +%<latexrelease> { +%<latexrelease> \tl_new:c { g_@@_#1_declared_tl } +%<latexrelease> \@@_make_usable:n {#1} +%<latexrelease> \tl_gset:cx { g_@@_#1_reversed_tl } +%<latexrelease> { \@@_if_generic_reversed:nT {#1} { - } } +%<latexrelease> \@@_update_hook_code:n {#1} +%<latexrelease> } +%<latexrelease> } +%<latexrelease> } %<latexrelease>\EndIncludeInRelease % \end{macrocode} % +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_activate_generic:n} +%<latexrelease> {Providing~hooks} +%<latexrelease>\cs_gset_protected:Npn \hook_activate_generic:n #1 { } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% \end{macro} +% % % \subsection{Parsing a label} % @@ -2965,63 +3518,109 @@ % % \subsection{Adding or removing hook code} % -% \begin{macro}{\hook_gput_code:nnn} -% \begin{macro}{\@@_gput_code:nnn,\@@_hook_gput_code_do:nnn} +% \begin{macro}{\hook_gput_code:nnn,\hook_gput_code_with_args:nnn} +% \begin{macro}{ +% \@@_gput_code:nnn, +% \@@_gput_code_store:nnn, +% \@@_hook_gput_code_do:nnn, +% \@@_prop_gput_labeled_cleanup:nnn, +% \@@_prop_gput_labeled_do:Nnnn +% } % % 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}. % \changes{v1.0o}{2021/07/22}{Do not queue removals (gh/625)} +% \changes{v1.1a}{2023/04/06} +% {Add \cs{hook_gput_code_with_args:nnn} (hook-args).} % \begin{macrocode} -\cs_new_protected:Npn \hook_gput_code:nnn #1 #2 - { \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} } +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_gput_code_with_args:nnn} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \hook_gput_code:nnn #1 #2 #3 + { + \@@_replacing_args_false: + \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} {#3} + \@@_replacing_args_reset: + } +\cs_new_protected:Npn \hook_gput_code_with_args:nnn #1 #2 #3 + { + \@@_replacing_args_true: + \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} {#3} + \@@_replacing_args_reset: + } % \end{macrocode} % +% If \cs{AddToHookWithArguments} was used, do some sanity checking, +% and if it's not possible to use arguments at this point, fall back +% to regular \cs{AddToHook} by using \cs{@@_replacing_args_false:}. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} \cs_new_protected:Npn \@@_gput_code:nnn #1 #2 #3 { + \@@_chk_args_allowed:nn {#1} { AddToHook } % \end{macrocode} -% First check if the code should be executed immediately, rather than +% Then check if the code should be executed immediately, rather than % stored: % \changes{v1.0r}{2021/09/06}{Use dedicated conditional (gh/606)} % \begin{macrocode} \@@_if_execute_immediately:nTF {#1} - {#3} { % \end{macrocode} +% \cs{AddToHookWithArguments} can't be used on one-time hooks (that +% were already used). +% \begin{macrocode} + \@@_if_replacing_args:TF + { + \msg_error:nnnn { hooks } { one-time-args } + {#1} { AddToHook } + } + { } + \use:n + } + { \@@_gput_code_store:nnn {#1} {#2} } + {#3} + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_gput_code_store:nnn #1 #2 #3 + { +% \end{macrocode} % Then check if the hook is usable. % \begin{macrocode} - \@@_if_usable:nTF {#1} + \@@_if_usable:nTF {#1} % \end{macrocode} % If so we simply add (or append) the new code to the property list % holding different chunks for the hook. At \verb=\begin{document}= % this is then sorted into a token list for fast execution. % \begin{macrocode} - { - \@@_hook_gput_code_do:nnn {#1} {#2} {#3} + { + \@@_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} - } + \@@_update_hook_code:n {#1} + } % \end{macrocode} % % If the hook is not usable, before giving up, check if it's not % disabled and otherwise try to declare it as a generic hook, if its % name matches one of the valid patterns. % \begin{macrocode} - { - \@@_if_disabled:nTF {#1} - { \msg_error:nnn { hooks } { hook-disabled } {#1} } - { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} } - } + { + \@@_if_disabled:nTF {#1} + { \msg_error:nnn { hooks } { hook-disabled } {#1} } + { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} } } } % \end{macrocode} % % This macro will unconditionally add a chunk of code to the given hook. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} \cs_new_protected:Npn \@@_hook_gput_code_do:nnn #1 #2 #3 { @@ -3046,31 +3645,161 @@ \str_if_eq:eeTF { top-level } { \@@_currname_or_default: } { % \end{macrocode} -% If the hook's basic structure does not exist, we need to declare it -% with \cs{@@_init_structure:n}. +% If the hook's basic structure does not exist, we need to declare it +% with \cs{@@_init_structure:n}. % \begin{macrocode} \@@_init_structure:n {#1} - \@@_tl_gput_right:cn { @@_toplevel~#1 } {#3} +% \end{macrocode} +% Then append to the \verb|_toplevel| container for the hook. +% \begin{macrocode} + \@@_cs_gput_right:nnn { _toplevel } {#1} {#3} } { \msg_error:nnn { hooks } { misused-top-level } {#1} } } { - \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl +% \end{macrocode} +% When adding to the code pool, we have to double hashes if +% \cs{AddToHook} was used (\verb|replacing_args| is false), so that +% later it is turned into a single parameter token, rather than a +% parameter to the hook macro. +% \begin{macrocode} + \exp_args:Nx \@@_prop_gput_labeled_cleanup:nnn { - \prop_gput:cno { g_@@_#1_code_prop } {#2} - { \l_@@_return_tl #3 } + \@@_if_replacing_args:TF + { \exp_not:n } + { \@@_double_hashes:n } + {#3} } - { \prop_gput:cnn { g_@@_#1_code_prop } {#2} {#3} } + {#1} {#2} } } % \end{macrocode} +% +% Adds code to a hook's code pool. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +\cs_new_protected:Npn \@@_prop_gput_labeled_cleanup:nnn #1 #2 #3 + { + \tl_set:Nn \l_@@_return_tl {#1} + \@@_if_replacing_args:TF + { + \@@_if_usable:nT {#2} + { + \@@_set_normalise_fn:nn {#2} + { Invalid~code~added~\msg_line_context: } + \@@_normalise_fn:nn {#3} {#1} + \prop_get:NnN \l_@@_work_prop {#3} \l_@@_return_tl + } + } + { } + \exp_args:NcV \@@_prop_gput_labeled_do:Nnn + { g_@@_#2_code_prop } \l_@@_return_tl {#3} + } +\cs_new_protected:Npn \@@_prop_gput_labeled_do:Nnn #1 #2 #3 + { + \prop_get:NnNTF #1 {#3} \l_@@_return_tl + { \prop_gput:Nno #1 {#3} { \l_@@_return_tl #2 } } + { \prop_gput:Nnn #1 {#3} {#2} } + } +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_gput_code:nnn} +%<latexrelease> {Providing~hooks} +%<latexrelease>\cs_gset_protected:Npn \hook_gput_code:nnn #1 #2 +%<latexrelease> { \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} } +%<latexrelease>\cs_gset_protected:Npn \@@_gput_code:nnn #1 #2 #3 +%<latexrelease> { +%<latexrelease> \@@_if_execute_immediately:nTF {#1} +%<latexrelease> {#3} +%<latexrelease> { +%<latexrelease> \@@_if_usable:nTF {#1} +%<latexrelease> { +%<latexrelease> \@@_hook_gput_code_do:nnn {#1} {#2} {#3} +%<latexrelease> \@@_update_hook_code:n {#1} +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \@@_if_disabled:nTF {#1} +%<latexrelease> { \msg_error:nnn { hooks } { hook-disabled } {#1} } +%<latexrelease> { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\cs_gset_protected:Npn \@@_hook_gput_code_do:nnn #1 #2 #3 +%<latexrelease> { +%<latexrelease> \@@_debug:n{\iow_term:x{****~ Add~ to~ +%<latexrelease> \@@_if_usable:nF {#1} { undeclared~ } +%<latexrelease> hook~ #1~ (#2) +%<latexrelease> \on@line\space <-~ \tl_to_str:n{#3}} } +%<latexrelease> \str_if_eq:nnTF {#2} { top-level } +%<latexrelease> { +%<latexrelease> \str_if_eq:eeTF { top-level } { \@@_currname_or_default: } +%<latexrelease> { +%<latexrelease> \@@_init_structure:n {#1} +%<latexrelease> \@@_tl_gput_right:cn { @@_toplevel~#1 } {#3} +%<latexrelease> } +%<latexrelease> { \msg_error:nnn { hooks } { misused-top-level } {#1} } +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl +%<latexrelease> { +%<latexrelease> \prop_gput:cno { g_@@_#1_code_prop } {#2} +%<latexrelease> { \l_@@_return_tl #3 } +%<latexrelease> } +%<latexrelease> { \prop_gput:cnn { g_@@_#1_code_prop } {#2} {#3} } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\cs_gset_protected:Npn \hook_gput_code_with_args:nnn #1#2#3 { } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} % \end{macro} +% +% \begin{macro}{\@@_chk_args_allowed:nn} +% This macro checks if it is possible to add code with references to +% a hook's arguments for hook \verb|#1|. It only does something if +% the function being run is \verb|replacing_args|. This macro will +% error if the hook is declared and takes no arguments, then it will +% set \cs{@@_replacing_args_false:} so that the macro which called it +% will add the code normally. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_chk_args_allowed:nn} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_chk_args_allowed:nn #1 #2 + { + \@@_if_replacing_args:TF + { + \@@_if_declared:nT {#1} + { \tl_if_empty:cT { c_@@_#1_parameter_tl } { \use_ii:nn } } + \use_none:n + { + \msg_error:nnnn { hooks } { without-args } {#1} {#2} + \@@_replacing_args_false: + } + } + { } + } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_chk_args_allowed:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_chk_args_allowed:nn +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} % \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. +% An implicitly declared hook doesn't have arguments (in principle), +% so use \cs{c_false_bool} here. % \begin{macrocode} \cs_new_protected:Npn \@@_gput_undeclared_hook:nnn #1 #2 #3 { @@ -3098,24 +3827,43 @@ % \cs{hook_gput_next_code:nn} if the generic hook was declared, or % to \cs{@@_gput_next_do:nn} otherwise. % \changes{v1.0p}{2021/08/25}{Standardise generic hook names (gh/648)} +% \changes{v1.1d}{2023/05/21} +% {Changes to allow support arguments in cmd hooks (cmd-args).} % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_declaring_generic_hook:nnn} -%<latexrelease> {Standardise~generic~hook~names} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_try_declaring_generic_hook:nnn} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \@@_try_declaring_generic_hook:nnn #1 { \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1} - \hook_gput_code:nnn + \@@_gput_code:nnn \@@_gput_undeclared_hook:nnn {#1} } \cs_new_protected:Npn \@@_try_declaring_generic_next_hook:nn #1 { \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1} - \hook_gput_next_code:nn + \@@_gput_next_code:nn \@@_gput_next_do:nn {#1} } %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_declaring_generic_hook:nnn} +%<latexrelease> {Standardise~generic~hook~names} +%<latexrelease>\cs_gset_protected:Npn \@@_try_declaring_generic_hook:nnn #1 +%<latexrelease> { +%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1} +%<latexrelease> \hook_gput_code:nnn +%<latexrelease> \@@_gput_undeclared_hook:nnn +%<latexrelease> {#1} +%<latexrelease> } +%<latexrelease>\cs_gset_protected:Npn \@@_try_declaring_generic_next_hook:nn #1 +%<latexrelease> { +%<latexrelease> \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1} +%<latexrelease> \hook_gput_next_code:nn +%<latexrelease> \@@_gput_next_do:nn +%<latexrelease> {#1} +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{2020/10/01}{\@@_try_declaring_generic_hook:nnn} %<latexrelease> {Standardise~generic~hook~names} %<latexrelease>\cs_new_protected:Npn \@@_try_declaring_generic_hook:nnn #1 @@ -3170,9 +3918,11 @@ % \end{macro} % % \begin{macro}[TF]{\@@_try_declaring_generic_hook:wn} +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_declaring_generic_hook:wn}% -%<latexrelease> {Standardise~generic~hook~names} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_try_declaring_generic_hook:wn} +%<latexrelease> {Hooks~with~args} \prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn #1 / #2 / #3 / #4 \scan_stop: #5 { TF } { @@ -3188,18 +3938,25 @@ % For some commands this will not be possible, in which case % \cs{@@_patch_cmd_or_delay:Nnn} (defined in \texttt{ltcmdhooks}) % will generate an appropriate error message. +% \changes{v1.1d}{2023/05/21} +% {Changes to allow support arguments in cmd hooks (cmd-args).} % \begin{macrocode} \str_if_eq:nnT {#1} { cmd } - { \@@_try_put_cmd_hook:n {#5} } + { + \@@_try_put_cmd_hook:n {#5} + \@@_make_usable:nn {#5} { 9 } + \use_none:nnn + } % \end{macrocode} % % Declare the hook always even if it can't really be used (error % message generated elsewhere). % -% Here we use \cs{@@_make_usable:n}, so that a \cs{hook_new:n} is still -% possible later. +% Here we use \cs{@@_make_usable:nn}, so that a \cs{hook_new:n} is +% still possible later. Generic hooks (except \hook{cmd} hooks) take +% no arguments, so use zero as the second argument. % \begin{macrocode} - \@@_make_usable:n {#5} + \@@_make_usable:nn {#5} { 0 } } \@@_if_generic_reversed:nT {#5} { \tl_gset:cn { g_@@_#5_reversed_tl } { - } } @@ -3285,6 +4042,37 @@ % \end{macro} % % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_try_declaring_generic_hook:wn} +%<latexrelease> {Standardise~generic~hook~names} +%<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn +%<latexrelease> #1 / #2 / #3 / #4 \scan_stop: #5 { TF } +%<latexrelease> { +%<latexrelease> \@@_if_generic:nTF {#5} +%<latexrelease> { +%<latexrelease> \@@_if_usable:nF {#5} +%<latexrelease> { +%<latexrelease> \str_if_eq:nnT {#1} { cmd } +%<latexrelease> { \@@_try_put_cmd_hook:n {#5} } +%<latexrelease> \@@_make_usable:n {#5} +%<latexrelease> } +%<latexrelease> \@@_if_generic_reversed:nT {#5} +%<latexrelease> { \tl_gset:cn { g_@@_#5_reversed_tl } { - } } +%<latexrelease> \prg_return_true: +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \@@_if_deprecated_generic:nTF {#5} +%<latexrelease> { +%<latexrelease> \@@_deprecated_generic_warn:n {#5} +%<latexrelease> \exp_after:wN \@@_declare_deprecated_generic:NNn +%<latexrelease> \exp:w % \exp_end: +%<latexrelease> } +%<latexrelease> { \prg_return_false: } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} %<latexrelease>\IncludeInRelease{2021/06/01}{\@@_try_declaring_generic_hook:wn} %<latexrelease> {Support~cmd~hooks} %<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn @@ -3316,7 +4104,7 @@ % \end{macrocode} % % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_try_declaring_generic_hook:wn}% +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_try_declaring_generic_hook:wn} %<latexrelease> {Support~cmd~hooks} %<latexrelease>\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn %<latexrelease> #1 / #2 / #3 / #4 \scan_stop: #5 { TF } @@ -3338,7 +4126,6 @@ %<latexrelease> { \prg_return_false: } %<latexrelease> } %<latexrelease> } -%<latexrelease> %<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} @@ -3350,24 +4137,10 @@ % |file/foo.tex/before|). If it is a file-specific hook, then it % executes the \meta{true} branch, otherwise \meta{false}. % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_if_file_hook:w}% +%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_if_file_hook:w} %<latexrelease> {Standardise~generic~hook~names} -\prg_new_conditional:Npnn \@@_if_file_hook:w - #1 / #2 \s_@@_mark #3 { TF } - { - \@@_if_generic:nTF {#3} - { - \str_if_eq:nnTF {#1} { file } - { \prg_return_true: } - { \prg_return_false: } - } - { \prg_return_false: } - } %<latexrelease>\EndIncludeInRelease -% \end{macrocode} -% -% \begin{macrocode} -%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_if_file_hook:w}% +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_if_file_hook:w} %<latexrelease> {Standardise~generic~hook~names} %<latexrelease>\prg_new_conditional:Npnn \@@_if_file_hook:w %<latexrelease> #1 / #2 / #3 \s_@@_mark { TF } @@ -3394,7 +4167,7 @@ % \begin{macro}[EXP]{\@@_strip_double_slash:n,\@@_strip_double_slash:w} % % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_file_hook_normalize:n}% +%<latexrelease>\IncludeInRelease{2021/11/15}{\@@_file_hook_normalize:n} %<latexrelease> {Standardise~generic~hook~names} %<latexrelease>\EndIncludeInRelease % \end{macrocode} @@ -3406,7 +4179,7 @@ % like \verb|\def\input@path{{./mypath/}}|, in which case a hook would % have to be \verb|\AddToHook{file/./mypath//file.tex/after}|. % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_file_hook_normalize:n}% +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_file_hook_normalize:n} %<latexrelease> {Standardise~generic~hook~names} %<latexrelease>\cs_new:Npn \@@_file_hook_normalize:n #1 %<latexrelease> { \@@_strip_double_slash:n {#1} } @@ -3453,7 +4226,7 @@ % The generic hooks used when loading a file % \end{description} % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/11/15}{\c_@@_generics_prop}% +%<latexrelease>\IncludeInRelease{2021/11/15}{\c_@@_generics_prop} %<latexrelease> {Standardise~generic~hook~names} \clist_map_inline:nn { cmd , env , file , package , class , include } { @@ -3482,7 +4255,7 @@ % \end{macrocode} % % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_generics_prop}% +%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_generics_prop} %<latexrelease> {Standardise~generic~hook~names} %<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_prop %<latexrelease> {cmd=,env=,file=,package=,class=,include=} @@ -3496,13 +4269,13 @@ % The following generic hooks are supposed to use reverse ordering % (the |ii| and |iii| names are kept for the deprecation cycle): % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/11/15}{\c_@@_generics_reversed_ii_prop}% +%<latexrelease>\IncludeInRelease{2021/11/15}{\c_@@_generics_reversed_ii_prop} %<latexrelease> {Standardise~generic~hook~names} %<latexrelease>\EndIncludeInRelease % \end{macrocode} % % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_generics_reversed_ii_prop}% +%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_generics_reversed_ii_prop} %<latexrelease> {Standardise~generic~hook~names} %<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_reversed_ii_prop {after=,end=} %<latexrelease>\prop_const_from_keyval:Nn \c_@@_generics_reversed_iii_prop {after=} @@ -3511,13 +4284,46 @@ % \end{macrocode} % \end{macro} % +% +% \begin{macro}{ +% \c_@@_parameter_cmd/./before_tl,\c_@@_parameter_cmd/./after_tl, +% } +% Token lists defining the number of arguments for a given type of +% generic hook. +% \changes{v1.1d}{2023/05/21} +% {Token lists added (cmd-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\c_@@_parameter_cmd/./before_tl} +%<latexrelease> {Hooks~with~args} +% \end{macrocode} +% +% \hook{cmd} hooks are declared with 9 arguments because they have a +% variable number of arguments (depending on the command they are +% attached to), so we use the maximum here. +% \begin{macrocode} +\tl_const:cn { c_@@_parameter_cmd/./before_tl } { #1#2#3#4#5#6#7#8#9 } +\tl_const:cn { c_@@_parameter_cmd/./after_tl } { #1#2#3#4#5#6#7#8#9 } +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_parameter_cmd/./before_tl} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\EndIncludeInRelease +% \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. % \changes{v1.0o}{2021/07/22}{Do not queue removals (gh/625)} +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_gremove_code:nn} +%<latexrelease> {Hooks~with~args} \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 @@ -3542,8 +4348,8 @@ \str_if_eq:nnTF {#2} {*} { \prop_gclear:c { g_@@_#1_code_prop } - \@@_tl_gclear:c { @@_toplevel~#1 } - \@@_tl_gclear:c { @@_next~#1 } + \@@_toplevel_gset:nn {#1} { } + \@@_next_gset:nn {#1} { } } { % \end{macrocode} @@ -3551,7 +4357,7 @@ % there is under the same label. % \begin{macrocode} \str_if_eq:nnTF {#2} { top-level } - { \@@_tl_gclear:c { @@_toplevel~#1 } } + { \@@_toplevel_gset:nn {#1} { } } { \prop_gpop:cnNF { g_@@_#1_code_prop } {#2} \l_@@_return_tl { \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} } @@ -3576,14 +4382,568 @@ { \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} } } } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_gremove_code:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_new_protected:Npn \@@_gremove_code:nn #1 #2 +%<latexrelease> { +%<latexrelease> \@@_if_structure_exist:nTF {#1} +%<latexrelease> { +%<latexrelease> \str_if_eq:nnTF {#2} {*} +%<latexrelease> { +%<latexrelease> \prop_gclear:c { g_@@_#1_code_prop } +%<latexrelease> \@@_tl_gclear:c { @@_toplevel~#1 } +%<latexrelease> \@@_tl_gclear:c { @@_next~#1 } +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \str_if_eq:nnTF {#2} { top-level } +%<latexrelease> { \@@_tl_gclear:c { @@_toplevel~#1 } } +%<latexrelease> { +%<latexrelease> \prop_gpop:cnNF { g_@@_#1_code_prop } {#2} \l_@@_return_tl +%<latexrelease> { \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> \@@_if_usable:nT {#1} +%<latexrelease> { \@@_update_hook_code:n {#1} } +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \@@_if_deprecated_generic:nTF {#1} +%<latexrelease> { +%<latexrelease> \@@_deprecated_generic_warn:n {#1} +%<latexrelease> \@@_do_deprecated_generic:Nn \@@_gremove_code:nn {#1} {#2} +%<latexrelease> } +%<latexrelease> { \msg_warning:nnnn { hooks } { cannot-remove } {#1} {#2} } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_cs_gput_right:nnn} +% \begin{macro}{\@@_cs_gput_right_fast:nnn,\@@_cs_gput_right_slow:nnn} +% \begin{macro}{\@@_code_gset_auxi:nnnn,\@@_code_gset_auxi:eeen} +% This macro is used to append code to the \verb|toplevel| and +% \verb|next| token lists, trating them correctly depending on their +% number of arguments, and depending if the code being added should +% have parameter tokens understood as parameters, or doubled to be +% stored as parameter tokens. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \changes{v1.1e}{2023/06/06} +% {Short-circuit when the hook is declared without args (gh1078).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_cs_gput_right:nnn} +%<latexrelease> {Hooks~with~args} +% \end{macrocode} +% +% Check if the current hook is declared and takes no arguments. In +% this case, we short-circuit and use the simpler and much faster +% approach that doesn't require hash-doubling. +% \begin{macrocode} +\cs_new_protected:Npn \@@_cs_gput_right:nnn #1 #2 + { + \if:w T + \@@_if_declared:nF {#2} { F } + \tl_if_empty:cF { c_@@_#2_parameter_tl } { F } + T + \exp_after:wN \@@_cs_gput_right_fast:nnn + \else: + \exp_after:wN \@@_cs_gput_right_slow:nnn + \fi: + {#1} {#2} + } +\cs_new_protected:Npn \@@_cs_gput_right_fast:nnn #1 #2 #3 + { \cs_gset:cpx { @@#1~#2 } { \exp_not:v { @@#1~#2 } \exp_not:n {#3} } } +\cs_new_protected:Npn \@@_cs_gput_right_slow:nnn #1 #2 #3 + { +% \end{macrocode} +% The auxiliary \cs{@@_code_gset_auxi:eeen} just does the assignment +% at the end. Its first argument is the parameter text of the macro, +% which is chosen here depending if +% \cs[no-index]{c_@@_\meta{hook}_parameter_tl} exists, if the hook is +% declared, and if it's a generic hook. +% \begin{macrocode} + \cs_if_exist:cF { @@#1~#2 } + { \@@_code_gset_aux:nnn {#1} {#2} { } } + \@@_code_gset_auxi:eeen + { + \@@_if_declared:nTF {#2} + { \tl_use:c { c_@@_#2_parameter_tl } } + { + \@@_if_generic:nTF {#2} + { \@@_generic_parameter:n {#2} } + { \c_@@_nine_parameters_tl } + } + } +% \end{macrocode} +% Here we take the existing code in the macro, expand it with as many +% arguments as it takes, then double the hashes so the code can be +% reused. \pho{Maybe can be improved. The case of adding to an empty +% cs can be optimised by quickly checking \cs{cs_replacement_spec}.} +% \begin{macrocode} + { + \exp_args:NNo \exp_args:No \@@_double_hashes:n + { + \cs:w @@#1~#2 \exp_last_unbraced:Ne \cs_end: + { \@@_braced_cs_parameter:n { @@#1~#2 } } + } + } +% \end{macrocode} +% Now the new code: if we are replacing arguments, then hashes are +% left untouched, otherwise they are doubled. +% \begin{macrocode} + { + \@@_if_replacing_args:TF + { \exp_not:n } + { \@@_double_hashes:n } + {#3} + } +% \end{macrocode} +% And finally, the csname which we'll define with all the above. +% \begin{macrocode} + { @@#1~#2 } + } +% \end{macrocode} +% +% And as promised, the auxiliary that does the definition. +% \begin{macrocode} +\cs_new_protected:Npn \@@_code_gset_auxi:nnnn #1 #2 #3 #4 + { \cs_gset:cpn {#4} #1 { #2 #3 } } +\cs_generate_variant:Nn \@@_code_gset_auxi:nnnn { eeen } +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_cs_gput_right:nnn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_cs_gput_right:nnn +%<latexrelease>\cs_undefine:N \@@_cs_gput_right_fast:nnn +%<latexrelease>\cs_undefine:N \@@_cs_gput_right_slow:nnn +%<latexrelease>\cs_undefine:N \@@_code_gset_auxi:nnnn +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} +% +% \begin{macro}{ +% \@@_code_gset:nn,\@@_code_gset:ne, +% \@@_toplevel_gset:nn, +% \@@_next_gset:nn, +% \@@_code_gset_aux:nnn +% } +% These macros define +% \cs[no-index]{@@\meta{type}\textvisiblespace\meta{hook}} (with +% \meta{type} being \verb|_next|, \verb|_toplevel|, or empty) with the +% given code and the parameters stored in +% \cs[no-index]{c_@@_\meta{hook}_parameter_tl} (or none, if that +% doesn't exist). +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_code_gset:nn} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_code_gset:nn + { \@@_code_gset_aux:nnn { } } +\cs_new_protected:Npn \@@_toplevel_gset:nn + { \@@_code_gset_aux:nnn { _toplevel } } +\cs_new_protected:Npn \@@_next_gset:nn + { \@@_code_gset_aux:nnn { _next } } +\cs_new_protected:Npn \@@_code_gset_aux:nnn #1 #2 #3 + { + \cs_gset:cpn { @@#1~#2 \exp_last_unbraced:Ne } + { \@@_parameter:n {#2} } + {#3} + } +\cs_generate_variant:Nn \@@_code_gset:nn { ne } +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_code_gset:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_code_gset:nn +%<latexrelease>\cs_undefine:N \@@_toplevel_gset:nn +%<latexrelease>\cs_undefine:N \@@_next_gset:nn +%<latexrelease>\cs_undefine:N \@@_code_gset_aux:nnn +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_normalise_cs_args:nn} +% This macro normalises the parameters of the macros +% \cs[no-index]{@@\meta{type}\textvisiblespace\meta{hook}} to take the +% right number of arguments after a hook is declared. At this point +% we know \cs[no-index]{c_@@_\meta{hook}_parameter_tl} exists, so use +% that to count the arguments and use that as \meta{parameter text} +% for the newly (re)defined macro. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_normalise_cs_args:nn} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_normalise_cs_args:nn #1 #2 + { + \cs_if_exist:cT { @@#1~#2 } + { + \@@_code_gset_auxi:eeen + { \tl_use:c { c_@@_#2_parameter_tl } } + { + \exp_args:NNo \exp_args:No \@@_double_hashes:n + { + \cs:w @@#1~#2 \exp_last_unbraced:Ne \cs_end: + { \@@_braced_cs_parameter:n { @@#1~#2 } } + } + } + { } + { @@#1~#2 } + } + } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_normalise_cs_args:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_normalise_cs_args:nn +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_normalise_code_pool:n} +% \begin{macro}{\@@_set_normalise_fn:nn} +% This one's a bit of a hack. It takes a hook, and iterates over its +% code pool (\cs[no-index]{g_@@_\meta{hook}_code_prop}), redefining +% each code label to use only valid arguments. This is used when, for +% example, a code is added referencing arguments \verb|#1| and +% \verb|#2|, but the hook has only \verb|#1|. In this example, every +% reference to \verb|#2| is changed to \verb|##2|. This is done +% because otherwise \TeX{} will throw a low-level error every time +% some change happens to the hook (code is added, a rule is set, etc), +% which can get quite repetitive for no good reason. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_normalise_code_pool:n} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_normalise_code_pool:n #1 + { +% \end{macrocode} +% First, call \cs{@@_set_normalise_fn:nn} with the hook name to set +% everything up, then we'll loop over the +% hook's code pool applying the normalisation above. After that's +% done, copy the temporary property list back to the hook's. +% \begin{macrocode} + \@@_set_normalise_fn:nn {#1} { Offending~label:~'##1' } + \prop_clear:N \l_@@_work_prop + \prop_map_function:cN { g_@@_#1_code_prop } \@@_normalise_fn:nn + \prop_gset_eq:cN { g_@@_#1_code_prop } \l_@@_work_prop + } +% \end{macrocode} +% +% The sole purpose of this function is to define +% \cs{@@_normalise_fn:nn}, which will then do the correcting of the +% code being added to the hook. +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_normalise_fn:nn #1 #2 + { +% \end{macrocode} +% To start, we define two auxiliary token lists. +% \cs[no-index]{l_@@_tmpb_tl} contains: +%\begin{verbatim} +% {\c__hook_hashes_tl 1} +% {\c__hook_hashes_tl 2} +% ... +% {\c__hook_hashes_tl 9} +%\end{verbatim} +% \begin{macrocode} + \cs_set:Npn \@@_tmp:w ##1##2##3##4##5##6##7##8##9 { } + \tl_set:Ne \l_@@_tmpb_tl + { \@@_braced_cs_parameter:n { @@_tmp:w } } + \group_begin: + \@@_tl_set:cn { c_@@_hash_tl } { \exp_not:N \c_@@_hashes_tl } + \use:e + { + \group_end: + \tl_set:Nn \exp_not:N \l_@@_tmpb_tl { \l_@@_tmpb_tl } + } +% \end{macrocode} +% And \cs[no-index]{l_@@_tmpa_tl} contains: +%\begin{verbatim} +% {\c__hook_hash_tl 1} +% {\c__hook_hash_tl 2} +% ... +% {\c__hook_hash_tl <n>} +%\end{verbatim} +% with \meta{n} being the number of arguments declared for the hook. +% \begin{macrocode} + \exp_last_unbraced:NNf + \cs_set:Npn \@@_tmp:w { \@@_parameter:n {#1} } { } + \tl_set:Ne \l_@@_tmpa_tl { \@@_braced_cs_parameter:n { @@_tmp:w } } +% \end{macrocode} +% Now this function does the fun part. It is meant to be used with +% \cs{prop_map_function:NN}, taking a label name in \verb|##1| and the +% code stored in that label in \verb|##2|. +% \begin{macrocode} + \cs_gset_protected:Npx \@@_normalise_fn:nn ##1 ##2 + { +% \end{macrocode} +% Here we'll define two auxiliary macros: the first one throws an +% error when it detects an invalid argument reference. It piggybacks +% on \TeX's low-level \enquote{Illegal parameter number} error, but it +% defines a weirdly-named control sequence so that the error comes out +% nicely formatted. For example, if the label \enquote{badpkg} adds +% some code that references argument \verb|#3| in the hook +% \enquote{foo}, which takes only two arguments, the error will be: +%\begin{verbatim} +% ! Illegal parameter number in definition of hook 'foo'. +% (hooks) Offending label: 'badpkg'. +% <to be read again> +% 3 +%\end{verbatim} +% At the point of this definition, the error is raised if the code +% happens to reference an invalid argument. If it was possible to +% detect that this definition raised no error, the next step would be +% unnecessary. We'll do all this in a group so this weird definition +% doesn't leak out, and set \cs{tex_escapechar:D} to $-1$ so this hack +% shows up extra nice in the case of an error. +% \begin{macrocode} + \group_begin: + \int_set:Nn \tex_escapechar:D { -1 } + \cs_set:cpn + { + hook~'#1'. ^^J + (hooks) \prg_replicate:nn { 13 } { ~ } + #2 % more message text + } + \exp_not:v { c_@@_#1_parameter_tl } + {##2} + \group_end: +% \end{macrocode} +% This next macro, with a much less fabulous name, takes always nine +% arguments, and it just transfers the code \verb|##2| under the label +% \verb|##1| to the temporary property list. The first \meta{n} +% arguments are taken from \cs[no-index]{l_@@_tmpa_tl}, and the other +% $9-\meta{n}$ taken from \cs[no-index]{l_@@_tmpb_tl} (which contains +% twice as many \verb|#| tokens as the former). Then, +% \cs{@@_double_hashes:n} is used to double non-argument hashes, and +% expand the \cs{c_@@_hash_tl} and \cs{c_@@_hashes_tl} to the actual +% parameter tokens. +% \begin{macrocode} + \cs_set:Npn \exp_not:N \@@_tmp:w + \exp_not:V \c_@@_nine_parameters_tl + { + \prop_put:Nne \exp_not:N \l_@@_work_prop + {##1} { \exp_not:N \@@_double_hashes:n {##2} } + } +% \end{macrocode} +% This next macro, with a much less fabulous name, takes always nine +% arguments, and it just transfers the code \verb|##2| under the label +% \verb|##1| to the temporary property list. The first \meta{n} +% arguments are taken from \cs[no-index]{l_@@_tmpa_tl}, and the other +% $9-\meta{n}$ taken from \cs[no-index]{l_@@_tmpb_tl} (which contains +% twice as many \verb|#| tokens as the former). Then, +% \cs{@@_double_hashes:n} is used to double non-argument hashes, and +% expand the \cs{c_@@_hash_tl} and \cs{c_@@_hashes_tl} to the actual +% parameter tokens. +% \begin{macrocode} + \exp_not:N \@@_tmp:w + \exp_not:V \l_@@_tmpa_tl + \exp_args:No \exp_not:o + { \exp_after:wN \@@_tmp:w \l_@@_tmpb_tl } + } + } +\cs_new_eq:NN \@@_normalise_fn:nn ? +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_normalise_code_pool:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_normalise_code_pool:n +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF]{\@@_cs_if_empty:c} +% Check if the expansion of a control sequence is empty by looking at +% its replacement text. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_cs_if_empty:c} +%<latexrelease> {Hooks~with~args} +\prg_new_conditional:Npnn \@@_cs_if_empty:c #1 { p, T, F, TF } + { + \if:w \scan_stop: \@@_replacement_spec:c {#1} \scan_stop: + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_new:Npn \@@_replacement_spec:c #1 + { + \exp_args:Nc \token_if_macro:NT {#1} + { \cs_replacement_spec:c {#1} } + } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_cs_if_empty:c} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_cs_if_empty:c +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_braced_cs_parameter:n} +% \begin{macro}{\@@_braced_hidden_loop:w} +% \begin{macro}{\@@_cs_parameter_count:N} +% \begin{macro}{\@@_cs_parameter_count:w,\@@_cs_end:w} +% Looks at the \meta{parameter text} of a control sequence, and +% returns a run of \enquote{hidden} braced parameters for that macro. +% This works as long as the macros take a simple run of zero to nine +% arguments. The parameters are \enquote{hidden} because the +% parameter tokens are returned inside \cs{c_@@_hash_tl} instead of +% explicitly, so that \cs{@@_double_hashes:n} won't touch these. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_braced_cs_parameter:n} +%<latexrelease> {Hooks~with~args} +\cs_new:Npn \@@_braced_cs_parameter:n #1 + { + \exp_last_unbraced:Ne \@@_braced_hidden_loop:w + { \exp_args:Nc \@@_cs_parameter_count:N {#1} } ? \s_@@_mark + } +\cs_new:Npn \@@_braced_hidden_loop:w #1 + { + \if:w ? #1 + \@@_use_i_delimit_by_s_mark:nw + \fi: + { \exp_not:N \c_@@_hash_tl #1 } + \@@_braced_hidden_loop:w + } +\cs_new:Npn \@@_cs_parameter_count:N #1 + { + \exp_last_unbraced:Nf \@@_cs_parameter_count:w + { \token_if_macro:NT #1 { \cs_parameter_spec:N #1 } } + ? \@@_cs_end:w ? \@@_cs_end:w ? \@@_cs_end:w + ? \@@_cs_end:w ? \@@_cs_end:w ? \@@_cs_end:w + ? \@@_cs_end:w ? \@@_cs_end:w ? \@@_cs_end:w + \s_@@_mark + } +\cs_new:Npn \@@_cs_parameter_count:w #1#2 #3#4 #5#6 #7#8 + { #2 #4 #6 #8 \@@_cs_parameter_count:w } +\cs_new:Npn \@@_cs_end:w #1 \s_@@_mark { } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% This function can't be undefined when rolling back because it's used +% at the end of this module to adequate the hook data structures to +% previous versions. +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_braced_cs_parameter:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_braced_parameter:n} +% \begin{macro}{\@@_braced_real_loop:w} +% This one is used in simpler cases, where no special handling of +% hashes is required. This is used only inside +% \cs{@@_initialize_hook_code:n}, so it assumes +% \cs[no-index]{c_@@_\meta{hook}_parameter_tl} is defined, but should +% work otherwise. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_braced_parameter:n} +%<latexrelease> {Hooks~with~args} +\cs_new:Npn \@@_braced_parameter:n #1 + { + \if_case:w + \int_eval:n + { \exp_args:Nv \str_count:n { c_@@_#1_parameter_tl } / 3 } + \exp_stop_f: + \or: {##1} + \or: {##1} {##2} + \or: {##1} {##2} {##3} + \or: {##1} {##2} {##3} {##4} + \or: {##1} {##2} {##3} {##4} {##5} + \or: {##1} {##2} {##3} {##4} {##5} {##6} + \or: {##1} {##2} {##3} {##4} {##5} {##6} {##7} + \or: {##1} {##2} {##3} {##4} {##5} {##6} {##7} {##8} + \or: {##1} {##2} {##3} {##4} {##5} {##6} {##7} {##8} {##9} + \else: + \msg_expandable_error:nnn { latex2e } { should-not-happen } + { Invalid~parameter~spec. } + \fi: + } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_braced_parameter:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_braced_parameter:n +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parameter:n} +% This is just a shortcut to \verb|e|- or \verb|f|-expand to the +% \meta{parameter text} of the hook. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_parameter:n} +%<latexrelease> {Hooks~with~args} +\cs_new:Npn \@@_parameter:n #1 + { + \cs:w c_@@_ + \tl_if_exist:cTF { c_@@_#1_parameter_tl } + { #1_parameter } { empty } + _tl \cs_end: + } +\cs_new:Npn \@@_generic_parameter:n #1 + { \@@_generic_parameter:w #1 / / / \s_@@_mark } +\cs_new:Npn \@@_generic_parameter:w #1 / #2 / #3 / #4 \s_@@_mark + { + \cs_if_exist_use:cF { c_@@_parameter_#1/./#3_tl } + { \c_@@_empty_tl } + } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_parameter:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_parameter:n +%<latexrelease>\cs_undefine:N \@@_generic_parameter:n +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Setting rules for hooks code} % % \begin{macro}{ % \g_@@_??_code_prop, % \@@~??, % \g_@@_??_reversed_tl, +% \c_@@_??_parameter_tl, % } % % Initially these variables simply used an empty ``label'' name (not @@ -3597,11 +4957,11 @@ % lot, the code should be fast, so this is not done with \texttt{c} % expansion in the code later on. % -% \cs{@@\textvisiblespace??} isn't used, but it has to be defined to trick -% the code into thinking that \texttt{??} is actually a hook. +% \cs{@@\textvisiblespace??} isn't used, but it has to be defined to +% trick the code into thinking that \texttt{??} is actually a hook. % \begin{macrocode} -\prop_new:c {g_@@_??_code_prop} -\prop_new:c {@@~??} +\prop_new:c { g_@@_??_code_prop } +\prop_new:c { @@~?? } % \end{macrocode} % % Default rules are always given in normal ordering (never in @@ -3610,11 +4970,23 @@ % \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} +\tl_new:c { g_@@_??_reversed_tl } % \end{macrocode} -% \end{macro} % -% \subsection{Setting rules for hooks code} +% The parameter text for the \enquote{default} hook is empty. +% \changes{v1.1a}{2023/04/06} +% {Token list added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\c_@@_??_parameter_tl} +%<latexrelease> {Hooks~with~args} +\tl_const:cn { c_@@_??_parameter_tl } { } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\c_@@_??_parameter_tl} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:c { c_@@_??_parameter_tl } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} % % \begin{macro}{\hook_gset_rule:nnnn} % \begin{macro}{\@@_gset_rule:nnnn} @@ -3645,13 +5017,13 @@ \@@_deprecated_generic_warn:n {#1} \@@_do_deprecated_generic:Nn \@@_gset_rule:nnnn {#1} {#2} {#3} {#4} - \@@_clean_to_scan:w + \@@_use_none_delimit_by_s_mark:w } \@@_if_execute_immediately:nT {#1} { \msg_error:nnnnnn { hooks } { rule-too-late } {#1} {#2} {#3} {#4} - \@@_clean_to_scan:w + \@@_use_none_delimit_by_s_mark:w } % \end{macrocode} % First we ensure the basic data structure of the hook exists: @@ -3840,44 +5212,82 @@ % \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. +% in the right order. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} -\cs_new_protected:Npn \@@_initialize_all: { +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_initialize_all:} +%<latexrelease> {Hooks~with~args} +\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 + \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. +% of them. Here we have to determine if the hook has arguments so +% that auxiliaries know what to do with hashes. We look at +% \cs[no-index]{c_@@_\meta{hook}_parameter_tl}, if it has any +% parameters, and set \verb|replacing_args| accordingly. % \begin{macrocode} - \@@_debug:n { \prop_gclear:N \g_@@_used_prop } - \seq_map_inline:Nn \g_@@_all_seq + \@@_debug:n { \prop_gclear:N \g_@@_used_prop } + \seq_map_inline:Nn \g_@@_all_seq { + \tl_if_empty:cTF { c_@@_##1_parameter_tl } + { \@@_replacing_args_false: } + { \@@_replacing_args_true: } \@@_update_hook_code:n {##1} + \@@_replacing_args_reset: } % \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}~ } - } - } + \@@_debug:n + { + \iow_term:x { ^^J All~initialized~(non-empty)~hooks: } + \prop_map_inline:Nn \g_@@_used_prop + { + \iow_term:x + { ^^J ~ ##1 ~ -> ~ \cs_replacement_spec:c { @@~##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 -} + \@@_post_initialization_defs: + } +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_initialize_all:} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_initialize_all: +%<latexrelease> { +%<latexrelease> \cs_gset_eq:NN \@@_update_hook_code:n \@@_initialize_hook_code:n +%<latexrelease> \@@_debug:n { \prop_gclear:N \g_@@_used_prop } +%<latexrelease> \seq_map_inline:Nn \g_@@_all_seq +%<latexrelease> { \@@_update_hook_code:n {##1} } +%<latexrelease> \@@_debug:n +%<latexrelease> { +%<latexrelease> \iow_term:x{^^JAll~ initialized~ (non-empty)~ hooks:} +%<latexrelease> \prop_map_inline:Nn \g_@@_used_prop +%<latexrelease> { +%<latexrelease> \iow_term:x +%<latexrelease> { ^^J ~ ##1 ~ -> ~ \cs_replacement_spec:c { @@~##1 } ~ } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> \cs_gset_eq:NN \hook_use:n \@@_use_initialized:n +%<latexrelease> \cs_gset_eq:NN \@@_preamble_hook:n \use_none:n +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -3887,7 +5297,11 @@ % 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. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_initialize_hook_code:n} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \@@_initialize_hook_code:n #1 { \@@_debug:n @@ -3915,10 +5329,15 @@ { \prop_if_empty:cTF { g_@@_#1_code_prop } { - \@@_tl_gset:co { @@~#1 } + \@@_code_gset:ne {#1} { - \cs:w @@_toplevel~#1 \exp_after:wN \cs_end: - \cs:w @@_next~#1 \cs_end: +% \end{macrocode} +% The hook may take arguments, so we add a run of braced parameters +% after the \verb|_next| and \verb|_toplevel| macros, so that the +% arguments passed to the hook are forwarded to them. +% \begin{macrocode} + \exp_not:c { @@_toplevel~#1 } \@@_braced_parameter:n {#1} + \exp_not:c { @@_next~#1 } \@@_braced_parameter:n {#1} } } { @@ -3958,6 +5377,42 @@ } } } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_initialize_hook_code:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_initialize_hook_code:n #1 +%<latexrelease> { +%<latexrelease> \@@_debug:n +%<latexrelease> { \iow_term:x { ^^J Update~code~for~hook~'#1' \on@line :^^J } } +%<latexrelease> \@@_include_legacy_code_chunk:n {#1} +%<latexrelease> \@@_if_usable:nT {#1} +%<latexrelease> { +%<latexrelease> \prop_if_empty:cTF { g_@@_#1_code_prop } +%<latexrelease> { +%<latexrelease> \@@_tl_gset:co { @@~#1 } +%<latexrelease> { +%<latexrelease> \cs:w @@_toplevel~#1 \exp_after:wN \cs_end: +%<latexrelease> \cs:w @@_next~#1 \cs_end: +%<latexrelease> } +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \@@_if_reversed:nTF {#1} +%<latexrelease> { \cs_set_eq:NN \@@_tl_gput:Nn \@@_tl_gput_left:Nn +%<latexrelease> \cs_set_eq:NN \@@_clist_gput:NV \clist_gput_left:NV } +%<latexrelease> { \cs_set_eq:NN \@@_tl_gput:Nn \@@_tl_gput_right:Nn +%<latexrelease> \cs_set_eq:NN \@@_clist_gput:NV \clist_gput_right:NV } +%<latexrelease> \prop_set_eq:Nc \l_@@_work_prop { g_@@_#1_code_prop } +%<latexrelease> \@@_initialize_single:ccn +%<latexrelease> { @@~#1 } { g_@@_#1_labels_clist } {#1} +%<latexrelease> \@@_debug:n +%<latexrelease> { \exp_args:NNx \prop_gput:Nnn \g_@@_used_prop {#1} { } } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -4034,7 +5489,12 @@ % ^^A #1 <- \@@~#1 % ^^A #2 <- \g_@@_#1_labels_clist % ^^A #3 <- #1 +% +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_initialize_single:NNn} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \@@_initialize_single:NNn #1#2#3 { % \end{macrocode} @@ -4181,15 +5641,103 @@ % time execution (\verb=#3=). These should normally be empty. The % |top-level| code is added with \cs{@@_tl_gput:Nn} as that might % change for a reversed hook (then |top-level| is the very first code -% chunk added). The |next| code is always added last. -% \begin{macrocode} - \exp_args:NNo \@@_tl_gput:Nn #1 { \cs:w @@_toplevel~#3 \cs_end: } - \@@_tl_gput_right:No #1 { \cs:w @@_next~#3 \cs_end: } +% chunk added). The |next| code is always added last (to the right). +% The hook may take arguments, so we add a run of braced parameters +% after the \verb|_next| and \verb|_toplevel| macros, so that the +% arguments passed to the hook are forwarded to them. +% \begin{macrocode} + \exp_args:NNe \@@_tl_gput:Nn #1 + { \exp_not:c { @@_toplevel~#3 } \@@_braced_parameter:n {#3} } + \@@_tl_gput_right:Ne #1 + { \exp_not:c { @@_next~#3 } \@@_braced_parameter:n {#3} } + \use:e + { + \cs_gset:cpn { @@~#3 } \use:c { c_@@_#3_parameter_tl } + { \exp_not:V #1 } + } } % \end{macrocode} % % \begin{macrocode} \cs_generate_variant:Nn \@@_initialize_single:NNn { cc } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_initialize_single:NNn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_new_protected:Npn \@@_initialize_single:NNn #1#2#3 +%<latexrelease> { +%<latexrelease> \seq_clear:N \l_@@_labels_seq +%<latexrelease> \int_zero:N \l_@@_labels_int +%<latexrelease> \tl_set:Nn \l_@@_cur_hook_tl {#3} +%<latexrelease> \prop_map_inline:Nn \l_@@_work_prop +%<latexrelease> { +%<latexrelease> \int_incr:N \l_@@_labels_int +%<latexrelease> \seq_put_right:Nn \l_@@_labels_seq {##1} +%<latexrelease> \@@_tl_set:cn { \@@_tl_csname:n {##1} } { 0 } +%<latexrelease> \seq_clear_new:c { \@@_seq_csname:n {##1} } +%<latexrelease> } +%<latexrelease> \prop_map_inline:Nn \l_@@_work_prop +%<latexrelease> { +%<latexrelease> \prop_map_inline:Nn \l_@@_work_prop +%<latexrelease> { +%<latexrelease> \@@_if_label_case:nnnnn {##1} {####1} +%<latexrelease> { \prop_map_break: } +%<latexrelease> { \@@_apply_label_pair:nnn {##1} {####1} } +%<latexrelease> { \@@_apply_label_pair:nnn {####1} {##1} } +%<latexrelease> {#3} +%<latexrelease> } +%<latexrelease> } +%<latexrelease> \@@_debug:n { \@@_debug_label_data:N \l_@@_work_prop } +%<latexrelease> \tl_set:Nn \l_@@_rear_tl { 0 } +%<latexrelease> \tl_set:cn { \@@_tl_csname:n { 0 } } { 0 } +%<latexrelease> \seq_map_inline:Nn \l_@@_labels_seq +%<latexrelease> { +%<latexrelease> \int_compare:nNnT { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0 +%<latexrelease> { +%<latexrelease> \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } }{##1} +%<latexrelease> \tl_set:Nn \l_@@_rear_tl {##1} +%<latexrelease> } +%<latexrelease> } +%<latexrelease> \tl_set_eq:Nc \l_@@_front_tl { \@@_tl_csname:n { 0 } } +%<latexrelease> \@@_tl_gclear:N #1 +%<latexrelease> \clist_gclear:N #2 +%<latexrelease> \bool_while_do:nn { ! \str_if_eq_p:Vn \l_@@_front_tl { 0 } } +%<latexrelease> { +%<latexrelease> \int_decr:N \l_@@_labels_int +%<latexrelease> \prop_get:NVN \l_@@_work_prop \l_@@_front_tl \l_@@_return_tl +%<latexrelease> \exp_args:NNV \@@_tl_gput:Nn #1 \l_@@_return_tl +%<latexrelease> \@@_clist_gput:NV #2 \l_@@_front_tl +%<latexrelease> \@@_debug:n{ \iow_term:x{Handled~ code~ for~ \l_@@_front_tl} } +%<latexrelease> \seq_map_inline:cn { \@@_seq_csname:n { \l_@@_front_tl } } +%<latexrelease> { +%<latexrelease> \tl_set:cx { \@@_tl_csname:n {##1} } +%<latexrelease> { \int_eval:n +%<latexrelease> { \cs:w \@@_tl_csname:n {##1} \cs_end: - 1 } +%<latexrelease> } +%<latexrelease> \int_compare:nNnT +%<latexrelease> { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0 +%<latexrelease> { +%<latexrelease> \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } } {##1} +%<latexrelease> \tl_set:Nn \l_@@_rear_tl {##1} +%<latexrelease> } +%<latexrelease> } +%<latexrelease> \tl_set_eq:Nc \l_@@_front_tl +%<latexrelease> { \@@_tl_csname:n { \l_@@_front_tl } } +%<latexrelease> } +%<latexrelease> \int_compare:nNnF \l_@@_labels_int = 0 +%<latexrelease> { +%<latexrelease> \iow_term:x{====================} +%<latexrelease> \iow_term:x{Error:~ label~ rules~ are~ incompatible:} +%<latexrelease> \@@_debug_label_data:N \l_@@_work_prop +%<latexrelease> \iow_term:x{====================} +%<latexrelease> } +%<latexrelease> \exp_args:NNo \@@_tl_gput:Nn #1 { \cs:w @@_toplevel~#3 \cs_end: } +%<latexrelease> \@@_tl_gput_right:No #1 { \cs:w @@_next~#3 \cs_end: } +%<latexrelease> } +%<latexrelease>\cs_generate_variant:Nn \@@_tl_gput_right:Nn { No } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -4444,7 +5992,11 @@ { \@@_log_cmd:x { >~\@spaces #1 } } % \end{macrocode} % +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_log:nN} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \@@_log:nN #1 #2 { \@@_if_deprecated_generic:nT {#1} @@ -4455,7 +6007,20 @@ } \@@_preamble_hook:n {#1} \@@_log_cmd:x - { ^^J ->~The~ \@@_if_generic:nT {#1} { generic~ } hook~'#1': } + { + ^^J ->~The~ + \@@_if_generic:nT {#1} { generic~ } + hook~'#1' + \@@_if_disabled:nF {#1} + { + \exp_args:Nf \@@_print_args:nn {#1} + { + \int_eval:n + { \str_count:e { \@@_parameter:n {#1} } / 3 } + } + } + : + } % \end{macrocode} % % \begin{macrocode} @@ -4471,7 +6036,12 @@ { \@@_log_line_indent:x { --- } } { \prop_map_inline:cn { g_@@_#1_code_prop } - { \@@_log_line_indent:x { ##1~->~\tl_to_str:n {##2} } } + { + \exp_after:wN \cs_set:Npn \exp_after:wN \@@_tmp:w + \c_@@_nine_parameters_tl {##2} + \@@_log_line_indent:x + { ##1~->~\cs_replacement_spec:N \@@_tmp:w } + } } % \end{macrocode} % @@ -4485,9 +6055,9 @@ } \@@_log_line_indent:x { - \tl_if_empty:cTF { @@_toplevel~#1 } + \@@_cs_if_empty:cTF { @@_toplevel~#1 } { --- } - { -> ~ \exp_args:Nv \tl_to_str:n { @@_toplevel~#1 } } + { -> ~ \cs_replacement_spec:c { @@_toplevel~#1 } } } % \end{macrocode} % @@ -4495,7 +6065,7 @@ \@@_log_line:x { Extra~code~for~next~invocation: } \@@_log_line_indent:x { - \tl_if_empty:cTF { @@_next~#1 } + \@@_cs_if_empty:cTF { @@_next~#1 } { --- } % \end{macrocode} % @@ -4503,7 +6073,10 @@ % 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 } } + { + -> ~ \exp_last_unbraced:Nf \@@_log_next_code:w + { \cs_replacement_spec:c { @@_next~#1 } } + } } % \end{macrocode} % @@ -4549,7 +6122,7 @@ \@spaces \clist_if_empty:cTF { g_@@_#1_labels_clist } { --- } - { \clist_use:cn {g_@@_#1_labels_clist} { ,~ } } + { \clist_use:cn { g_@@_#1_labels_clist } { ,~ } } } } { @@ -4563,15 +6136,139 @@ } } } +%<latexrelease>\EndIncludeInRelease +% +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_log:nN} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_new_protected:Npn \@@_log:nN #1 #2 +%<latexrelease> { +%<latexrelease> \@@_if_deprecated_generic:nT {#1} +%<latexrelease> { +%<latexrelease> \@@_deprecated_generic_warn:n {#1} +%<latexrelease> \@@_do_deprecated_generic:Nn \@@_log:nN {#1} #2 +%<latexrelease> \exp_after:wN \use_none:nnnnnnnnn \use_none:nnnnn +%<latexrelease> } +%<latexrelease> \@@_preamble_hook:n {#1} +%<latexrelease> \@@_log_cmd:x +%<latexrelease> { ^^J ->~The~ \@@_if_generic:nT {#1} { generic~ } hook~'#1': } +%<latexrelease> \@@_if_usable:nF {#1} +%<latexrelease> { \@@_log_line:x { The~hook~is~not~declared. } } +%<latexrelease> \@@_if_disabled:nT {#1} +%<latexrelease> { \@@_log_line:x { The~hook~is~disabled. } } +%<latexrelease> \hook_if_empty:nTF {#1} +%<latexrelease> { #2 { The~hook~is~empty } } +%<latexrelease> { +%<latexrelease> \@@_log_line:x { Code~chunks: } +%<latexrelease> \prop_if_empty:cTF { g_@@_#1_code_prop } +%<latexrelease> { \@@_log_line_indent:x { --- } } +%<latexrelease> { +%<latexrelease> \prop_map_inline:cn { g_@@_#1_code_prop } +%<latexrelease> { \@@_log_line_indent:x { ##1~->~\tl_to_str:n {##2} } } +%<latexrelease> } +%<latexrelease> \@@_log_line:x +%<latexrelease> { +%<latexrelease> Document-level~(top-level)~code +%<latexrelease> \@@_if_usable:nT {#1} +%<latexrelease> { ~(executed~\@@_if_reversed:nTF {#1} {first} {last} ) } : +%<latexrelease> } +%<latexrelease> \@@_log_line_indent:x +%<latexrelease> { +%<latexrelease> \tl_if_empty:cTF { @@_toplevel~#1 } +%<latexrelease> { --- } +%<latexrelease> { -> ~ \exp_args:Nv \tl_to_str:n { @@_toplevel~#1 } } +%<latexrelease> } +%<latexrelease> \@@_log_line:x { Extra~code~for~next~invocation: } +%<latexrelease> \@@_log_line_indent:x +%<latexrelease> { +%<latexrelease> \tl_if_empty:cTF { @@_next~#1 } +%<latexrelease> { --- } +%<latexrelease> { ->~ \exp_args:Nv \@@_log_next_code:n { @@_next~#1 } } +%<latexrelease> } +%<latexrelease> \@@_log_line:x { Rules: } +%<latexrelease> \bool_set_true:N \l_@@_tmpa_bool +%<latexrelease> \@@_list_rules:nn {#1} +%<latexrelease> { +%<latexrelease> \bool_set_false:N \l_@@_tmpa_bool +%<latexrelease> \@@_log_line_indent:x +%<latexrelease> { +%<latexrelease> ##2~ with~ +%<latexrelease> \str_if_eq:nnT {##3} {??} { default~ } +%<latexrelease> relation~ ##1 +%<latexrelease> } +%<latexrelease> } +%<latexrelease> \bool_if:NT \l_@@_tmpa_bool +%<latexrelease> { \@@_log_line_indent:x { --- } } +%<latexrelease> \bool_lazy_and:nnTF +%<latexrelease> { \@@_if_usable_p:n {#1} } +%<latexrelease> { ! \hook_if_empty_p:n {#1} } +%<latexrelease> { +%<latexrelease> \@@_log_line:x +%<latexrelease> { +%<latexrelease> Execution~order +%<latexrelease> \bool_if:NTF \l_@@_tmpa_bool +%<latexrelease> { \@@_if_reversed:nT {#1} { ~(after~reversal) } } +%<latexrelease> { ~(after~ +%<latexrelease> \@@_if_reversed:nT {#1} { reversal~and~ } +%<latexrelease> applying~rules) +%<latexrelease> } : +%<latexrelease> } +%<latexrelease> #2 % \tl_show:n +%<latexrelease> { +%<latexrelease> \@spaces +%<latexrelease> \clist_if_empty:cTF { g_@@_#1_labels_clist } +%<latexrelease> { --- } +%<latexrelease> { \clist_use:cn { g_@@_#1_labels_clist } { ,~ } } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> { +%<latexrelease> \@@_log_line:x { Execution~order: } +%<latexrelease> #2 +%<latexrelease> { +%<latexrelease> \@spaces Not~set~because~the~hook~ \@@_if_usable:nTF {#1} +%<latexrelease> { code~pool~is~empty } +%<latexrelease> { is~\@@_if_disabled:nTF {#1} {disabled} {undeclared} } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \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. +% \cs{AddToHookNext} we have to remove the string +% \cs{@@_clear_next:n}\Arg{hook}, so the simplest is to use a macro +% delimited by a \verb|}|$_12$. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_log_next_code:n} +%<latexrelease> {Hooks~with~args} +\exp_last_unbraced:NNNNo +\cs_new:Npn \@@_log_next_code:w #1 \c_right_brace_str { } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_log_next_code:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset:Npn \@@_log_next_code:n #1 +%<latexrelease> { \exp_args:No \tl_to_str:n { \use_none:nn #1 } } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_print_args:n} +% Pretty-prints the number of arguments of a hook. % \begin{macrocode} -\cs_new:Npn \@@_log_next_code:n #1 - { \exp_args:No \tl_to_str:n { \use_none:nn #1 } } +\cs_new:Npn \@@_print_args:nn #1 #2 + { + \int_compare:nNnT {#2} > { 0 } + { + \@@_if_declared:nT {#1} { \use_none:nnn } + \@@_if_cmd_hook:nT {#1} + { \use_i:nnn { ~ (unknown ~ } } + \use:n { ~ (#2 ~ } + argument \int_compare:nNnT {#2} > { 1 } { s } ) + } + } % \end{macrocode} % \end{macro} % @@ -4656,15 +6353,34 @@ % \subsection{Specifying code for next invocation} % % \begin{macro}{\hook_gput_next_code:nn} +% \changes{v1.1a}{2023/04/06} +% {Add \cs{hook_gput_next_code_with_args:nn} (hook-args).} % \begin{macrocode} -\cs_new_protected:Npn \hook_gput_next_code:nn #1 - { \@@_normalize_hook_args:Nn \@@_gput_next_code:nn {#1} } +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_gput_next_code:nn} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \hook_gput_next_code:nn #1 #2 + { + \@@_replacing_args_false: + \@@_normalize_hook_args:Nn \@@_gput_next_code:nn {#1} {#2} + \@@_replacing_args_reset: + } +\cs_new_protected:Npn \hook_gput_next_code_with_args:nn #1 #2 + { + \@@_replacing_args_true: + \@@_normalize_hook_args:Nn \@@_gput_next_code:nn {#1} {#2} + \@@_replacing_args_reset: + } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_gput_next_code:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \hook_gput_next_code:nn #1 +%<latexrelease> { \@@_normalize_hook_args:Nn \@@_gput_next_code:nn {#1} } +%<latexrelease>\cs_gset_protected:Npn \hook_gput_next_code_with_args:nn #1 #2 { } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_gput_next_code:nn, -% \@@_gput_next_do:nn, -% \@@_gput_next_do:Nnn} +% \begin{macro}{\@@_gput_next_code:nn} % \begin{macrocode} \cs_new_protected:Npn \@@_gput_next_code:nn #1 #2 { @@ -4672,20 +6388,17 @@ { \msg_error:nnn { hooks } { hook-disabled } {#1} } { \@@_if_structure_exist:nTF {#1} - { \@@_gput_next_do:nn {#1} {#2} } - { \@@_try_declaring_generic_next_hook:nn {#1} {#2} } + { \@@_gput_next_do:nn } + { \@@_try_declaring_generic_next_hook:nn } + {#1} {#2} } } % \end{macrocode} +% \end{macro} % -% \begin{macrocode} -\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 +% \begin{macro}{\@@_gput_next_do:nn} +% Start by sanity-checking with \cs{@@_chk_args_allowed:nn}. +% Then 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 @@ -4694,38 +6407,74 @@ % 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. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} +% \changes{v1.1c}{2023/04/19} +% {Initialise hook structure when adding 'next' code (gh/1052).} % \begin{macrocode} -\cs_new_protected:Npn \@@_gput_next_do:Nnn #1 #2 +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_gput_next_do:nn} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_gput_next_do:nn #1 { - \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 + \@@_init_structure:n {#1} + \@@_chk_args_allowed:nn {#1} { AddToHookNext } + \@@_cs_if_empty:cT { @@~#1 } + { \@@_update_hook_code:n {#1} } + \@@_cs_if_empty:cT { @@_next~#1 } + { \@@_next_gset:nn {#1} { \@@_clear_next:n {#1} } } + \@@_cs_gput_right:nnn { _next } {#1} } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_gput_next_do:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_gput_next_do:nn #1 +%<latexrelease> { +%<latexrelease> \exp_args:Nc \@@_gput_next_do:Nnn +%<latexrelease> { @@_next~#1 } {#1} +%<latexrelease> } +%<latexrelease>\cs_gset_protected:Npn \@@_gput_next_do:Nnn #1 #2 +%<latexrelease> { +%<latexrelease> \tl_if_empty:cT { @@~#2 } +%<latexrelease> { \@@_update_hook_code:n {#2} } +%<latexrelease> \tl_if_empty:NT #1 +%<latexrelease> { \@@_tl_gset:Nn #1 { \@@_clear_next:n {#2} } } +%<latexrelease> \@@_tl_gput_right:Nn #1 +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % -% -% -% \begin{macro}{\hook_gclear_next_code:n,\@@_clear_next:n} +% \begin{macro}{\hook_gclear_next_code:n} % Discard anything set up for next invocation of the hook. % \changes{v1.0o}{2021/07/27}{Macro made public} % \begin{macrocode} \cs_new_protected:Npn \hook_gclear_next_code:n #1 { \@@_normalize_hook_args:Nn \@@_clear_next:n {#1} } -\cs_new_protected:Npn \@@_clear_next:n #1 - { \cs_gset_eq:cN { @@_next~#1 } \c_empty_tl } % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_clear_next:n} +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_clear_next:n} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_clear_next:n #1 + { \@@_next_gset:nn {#1} { } } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_clear_next:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_clear_next:n #1 +%<latexrelease> { \cs_gset_eq:cN { @@_next~#1 } \c_empty_tl } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \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 @@ -4750,24 +6499,50 @@ % \verb=\csname ...\endcsname= construct \cs{tl_if_exist:c} is % careful to avoid this. % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/11/15}{\hook_use:n} -%<latexrelease> {Standardise~generic~hook~names} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_use:n} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \hook_use:n #1 { - \tl_if_exist:cT { @@~#1 } - { - \@@_preamble_hook:n {#1} - \cs:w @@~#1 \cs_end: - } + \@@_preamble_hook:n {#1} + \@@_use_initialized:n {#1} } \cs_new:Npn \@@_use_initialized:n #1 { \if_cs_exist:w @@~#1 \cs_end: - \cs:w @@~#1 \exp_after:wN \cs_end: + \cs:w @@~#1 \use_i:nn \fi: + \use_none:n + \cs_end: } \cs_new_protected:Npn \@@_preamble_hook:n #1 - { \@@_initialize_hook_code:n {#1} } + { + \if_cs_exist:w @@~#1 \cs_end: + \@@_initialize_hook_code:n {#1} + \fi: + } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2021/11/15}{\hook_use:n} +%<latexrelease> {Standardise~generic~hook~names} +%<latexrelease>\cs_new_protected:Npn \hook_use:n #1 +%<latexrelease> { +%<latexrelease> \tl_if_exist:cT { @@~#1 } +%<latexrelease> { +%<latexrelease> \@@_preamble_hook:n {#1} +%<latexrelease> \cs:w @@~#1 \cs_end: +%<latexrelease> } +%<latexrelease> } +%<latexrelease>\cs_new:Npn \@@_use_initialized:n #1 +%<latexrelease> { +%<latexrelease> \if_cs_exist:w @@~#1 \cs_end: +%<latexrelease> \cs:w @@~#1 \exp_after:wN \cs_end: +%<latexrelease> \fi: +%<latexrelease> } +%<latexrelease>\cs_new_protected:Npn \@@_preamble_hook:n #1 +%<latexrelease> { \@@_initialize_hook_code:n {#1} } +%<latexrelease>\cs_new:Npn \hook_use:nnw #1 { } %<latexrelease>\EndIncludeInRelease % \end{macrocode} % @@ -4799,13 +6574,69 @@ %<latexrelease>\cs_new_protected:Npn \@@_preamble_hook:n #1 %<latexrelease> { \@@_initialize_hook_code:n {#1} } %<latexrelease>\cs_new_eq:NN \@@_use_end: \cs_end: +%<latexrelease>\cs_new:Npn \hook_use:nnw #1 { } %<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% +% +% \begin{macro}{\hook_use:nnw} +% \begin{macro}[EXP]{\@@_use_initialized:nnw} +% \changes{v1.1a}{2023/04/06} +% {Add \cs{hook_use:nnw} (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_use:nnw} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \hook_use:nnw #1 + { + \@@_preamble_hook:n {#1} + \@@_use_initialized:nnw {#1} + } +\cs_new:Npn \@@_use_initialized:nnw #1 #2 + { + \cs:w + \if_cs_exist:w @@~#1 \cs_end: + @@~#1 + \else: + use_none: \prg_replicate:nn {#2} { n } + \fi: + \cs_end: + } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_use:nnw} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset:Npn \hook_use:nnw #1 #2 +%<latexrelease> { \use:c { use_none: \prg_replicate:nn {#2} { n } } } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\@@_post_initialization_defs:} +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_post_initialization_defs:} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_post_initialization_defs: + { + \cs_gset_eq:NN \hook_use:n \@@_use_initialized:n + \cs_gset_eq:NN \hook_use:nnw \@@_use_initialized:nnw + \cs_gset_eq:NN \@@_preamble_hook:n \use_none:n + \cs_gset_eq:NN \@@_post_initialization_defs: \prg_do_nothing: + } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_post_initialization_defs:} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_post_initialization_defs: +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} % \end{macro} % +% % \begin{macro}[EXP]{\@@_use:wn} % \begin{macro}{\@@_try_file_hook:n,\@@_if_usable_use:n} % \cs{@@_use:wn} does a quick check to test if the current hook is a @@ -4861,8 +6692,7 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\hook_use_once:n} -% \begin{macro}{\@@_use_once:n} +% \begin{macro}{\hook_use_once:n,\hook_use_once:nnw} % For hooks that can and should be used only once we have a special % use command that further inhibits the hook from getting more code % added to it. This has the effect that any @@ -4874,20 +6704,80 @@ % documented to not trim spaces. % % \changes{v1.0r}{2021/09/06}{Clean up after \cs{UseOneTimeHook} (gh/606)} +% \changes{v1.1a}{2023/04/06} +% {Add \cs{hook_use_once:nnw} (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_use_once:nnw} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \hook_use_once:n #1 { \@@_if_execute_immediately:nF {#1} - { \@@_normalize_hook_args:Nn \@@_use_once:n { \use:n {#1} } } + { \@@_normalize_hook_args:Nn \@@_use_once:nn { \use:n {#1} } { 0 } } } -\cs_new_protected:Npn \@@_use_once:n #1 +\cs_new_protected:Npn \hook_use_once:nnw #1 #2 + { + \@@_if_execute_immediately:nF {#1} + { \@@_normalize_hook_args:Nn \@@_use_once:nn { \use:n {#1} } {#2} } + } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_use_once:nnw} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \hook_use_once:n #1 +%<latexrelease> { +%<latexrelease> \@@_if_execute_immediately:nF {#1} +%<latexrelease> { \@@_normalize_hook_args:Nn \@@_use_once:n { \use:n {#1} } } +%<latexrelease> } +%<latexrelease>\cs_gset:Npn \hook_use_once:nnw #1 #2 +%<latexrelease> { \use:c { use_none: \prg_replicate:nn {#2} { n } } } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macro}{\@@_use_once:nn} +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_use_once:nn} +%<latexrelease> {Hooks~with~args} +\cs_new_protected:Npn \@@_use_once:nn #1 #2 { \@@_preamble_hook:n {#1} \@@_use_once_set:n {#1} - \@@_use_initialized:n {#1} - \@@_use_once_clear:n {#1} +% \end{macrocode} +% When a hook has arguments, the call to \cs{@@_use_initialized:n}, +% should be the very last thing to happen, otherwise the arguments +% grabbed will be wrong. So, to clean up after the hook we need to +% cheat a bit and sneak the cleanup code at the end of the hook, +% along with the next execution code. +% \begin{macrocode} + \@@_replacing_args_false: + \@@_cs_gput_right:nnn { _next } {#1} { \@@_use_once_clear:n {#1} } + \@@_replacing_args_reset: + \@@_if_usable:nTF {#1} + { \@@_use_initialized:n {#1} } + { + \int_compare:nNnT {#2} > { 0 } + { \use:c { use_none: \prg_replicate:nn {#2} { n } } } + } } +%<latexrelease>\EndIncludeInRelease +% +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_use_once:nn} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_gset_protected:Npn \@@_use_once:n #1 +%<latexrelease> { +%<latexrelease> \@@_preamble_hook:n {#1} +%<latexrelease> \@@_use_once_set:n {#1} +%<latexrelease> \@@_use_initialized:n {#1} +%<latexrelease> \@@_use_once_clear:n {#1} +%<latexrelease> } +%<latexrelease>\cs_undefine:N \@@_use_once:nn +%<latexrelease>\EndIncludeInRelease % \end{macrocode} +% \end{macro} % % \begin{macro}{\@@_use_once_set:n} % \begin{macro}{\@@_use_once_clear:n} @@ -4900,43 +6790,60 @@ % \cs{hook_use_once:n} will expand to nothing. % \changes{v1.0r}{2021/09/06}{Clean up after \cs{UseOneTimeHook} (gh/606)} % \changes{v1.0u}{2022/05/13}{Check if prop exists to avoid l3debug error} +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_use_once_clear:n} +%<latexrelease> {Hooks~with~args} \cs_new_protected:Npn \@@_use_once_set:n #1 { \@@_tl_gset:cn { g_@@_#1_reversed_tl } { I } } \cs_new_protected:Npn \@@_use_once_clear:n #1 { - \@@_tl_gclear:c { @@~#1 } - \@@_tl_gclear:c { @@_next~#1 } - \@@_tl_gclear:c { @@_toplevel~#1 } + \@@_code_gset:nn {#1} { } + \@@_next_gset:nn {#1} { } + \@@_toplevel_gset:nn {#1} { } \prop_gclear_new:c { g_@@_#1_code_prop } } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_use_once_clear:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_new_protected:Npn \@@_use_once_clear:n #1 +%<latexrelease> { +%<latexrelease> \@@_tl_gclear:c { @@~#1 } +%<latexrelease> \@@_tl_gclear:c { @@_next~#1 } +%<latexrelease> \@@_tl_gclear:c { @@_toplevel~#1 } +%<latexrelease> \prop_gclear_new:c { g_@@_#1_code_prop } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} -% \end{macro} -% \end{macro} % \end{macro} % \end{macro} % % \begin{macro}[pTF]{\@@_if_execute_immediately:n} -% To check whether the code being added should be executed immediately (that -% is, if the hook is a one-time hook), we check if it's usable (it -% can't be one-time if it was not already usable), then we check that +% To check whether the code being added should be executed immediately +% (that is, if the hook is a one-time hook), we check if % \cs[no-index]{g_@@_\meta{hook}_reversed_tl} is |I|. The gymnastics % around \cs{if:w} is there to allow the |reversed| token list to be % empty. % \changes{v1.0r}{2021/09/06}{Macro added (gh/606)} +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} % \begin{macrocode} \prg_new_conditional:Npnn \@@_if_execute_immediately:n #1 { T, F, TF } { - \@@_if_usable:nTF {#1} - { - \exp_after:wN \@@_clean_to_scan:w - \if:w I \cs:w g_@@_#1_reversed_tl \cs_end: - \s_@@_mark \prg_return_true: - \else: - \s_@@_mark \prg_return_false: + \exp_after:wN \@@_use_none_delimit_by_s_mark:w + \if:w I + \if_cs_exist:w g_@@_#1_reversed_tl \cs_end: + \cs:w g_@@_#1_reversed_tl \exp_after:wN \cs_end: \fi: - } - { \prg_return_false: } + X + \s_@@_mark \prg_return_true: + \else: + \s_@@_mark \prg_return_false: + \fi: } % \end{macrocode} % \end{macro} @@ -4963,30 +6870,57 @@ % % All other states can only be queried with internal tests as the % different states are irrelevant for package code. - +% % \begin{macro}[pTF]{\hook_if_empty:n} % Test if a hook is empty (that is, no code was added to that hook). % A \meta{hook} being empty means that all three of its % \cs{g_@@_\meta{hook}_code_prop}, its % \cs{@@_toplevel\textvisiblespace\meta{hook}} and its % \cs{@@_next\textvisiblespace\meta{hook}} are empty. +% \changes{v1.1a}{2023/04/06} +% {Changes to add hook arguments (hook-args).} +% \changes{v1.1c}{2023/04/19} +% {Simpler and faster version (gh/1052).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\hook_if_empty:n} +%<latexrelease> {Hooks~with~args} \prg_new_conditional:Npnn \hook_if_empty:n #1 { p , T , F , TF } { - \@@_if_structure_exist:nTF {#1} - { - \bool_lazy_and:nnTF - { \prop_if_empty_p:c { g_@@_#1_code_prop } } - { - \bool_lazy_and_p:nn - { \tl_if_empty_p:c { @@_toplevel~#1 } } - { \tl_if_empty_p:c { @@_next~#1 } } - } - { \prg_return_true: } - { \prg_return_false: } - } - { \prg_return_true: } + \if:w + T + \prop_if_exist:cT { g_@@_#1_code_prop } + { \prop_if_empty:cF { g_@@_#1_code_prop } { F } } + \@@_cs_if_empty:cF { @@_toplevel~#1 } { F } + \@@_cs_if_empty:cF { @@_next~#1 } { F } + T + \prg_return_true: + \else: + \prg_return_false: + \fi: } +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\hook_if_empty:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\prg_new_conditional:Npnn \hook_if_empty:n #1 { p , T , F , TF } +%<latexrelease> { +%<latexrelease> \@@_if_structure_exist:nTF {#1} +%<latexrelease> { +%<latexrelease> \bool_lazy_and:nnTF +%<latexrelease> { \prop_if_empty_p:c { g_@@_#1_code_prop } } +%<latexrelease> { +%<latexrelease> \bool_lazy_and_p:nn +%<latexrelease> { \tl_if_empty_p:c { @@_toplevel~#1 } } +%<latexrelease> { \tl_if_empty_p:c { @@_next~#1 } } +%<latexrelease> } +%<latexrelease> { \prg_return_true: } +%<latexrelease> { \prg_return_false: } +%<latexrelease> } +%<latexrelease> { \prg_return_true: } +%<latexrelease> } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -4994,15 +6928,15 @@ % \begin{macro}[pTF]{\@@_if_usable:n} % A hook is usable if the % token list that stores the sorted code for that hook, -% \cs[no-index]{@@~\meta{hook}}, exists. The property list -% \cs[no-index]{g_@@_\meta{hook}_code_prop} cannot be used here +% \cs[no-index]{@@\textvisiblespace\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 \@@_if_usable:n #1 { p , T , F , TF } { - \tl_if_exist:cTF { @@~#1 } + \cs_if_exist:cTF { @@~#1 } { \prg_return_true: } { \prg_return_false: } } @@ -5046,7 +6980,7 @@ % \begin{macrocode} \prg_new_conditional:Npnn \@@_if_reversed:n #1 { p , T , F , TF } { - \exp_after:wN \@@_clean_to_scan:w + \exp_after:wN \@@_use_none_delimit_by_s_mark:w \if:w - \cs:w g_@@_#1_reversed_tl \cs_end: \s_@@_mark \prg_return_true: \else: @@ -5086,6 +7020,37 @@ % \end{macro} % \end{macro} % +% \begin{macro}[pTF]{\@@_if_cmd_hook:n} +% \begin{macro}[pTF]{\@@_if_cmd_hook:w} +% An internal conditional that checks if a given hook is a valid +% generic \hook{cmd} hook. +% \changes{v1.1d}{2023/05/21} +% {Changes to allow support arguments in cmd hooks (cmd-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\@@_if_cmd_hook:n} +%<latexrelease> {Hooks~with~args} +\prg_new_conditional:Npnn \@@_if_cmd_hook:n #1 { T } + { \@@_if_cmd_hook:w #1 / / / \s_@@_mark } +\cs_new:Npn \@@_if_cmd_hook:w #1 / #2 / #3 / #4 \s_@@_mark + { + \if:w Y + \str_if_eq:nnF {#1} { cmd } { N } + \tl_if_exist:cF { c_@@_generic_#1/./#3_tl } { N } + Y + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\@@_if_cmd_hook:n} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_undefine:N \@@_if_cmd_hook:nT +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}[pTF]{\@@_if_generic_reversed:n} % An internal conditional that checks if a name belongs to a generic % reversed hook. @@ -5103,6 +7068,50 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[EXP]{\@@_if_replacing_args:TF} +% \begin{macro}[EXP]{\@@_misused_if_replacing_args:nn} +% \begin{macro}{\@@_replacing_args_true:} +% \begin{macro}{\@@_replacing_args_false:} +% \begin{macro}{\@@_replacing_args_reset:} +% \begin{macro}{\g_@@_replacing_stack_seq} +% An internal conditional that checks if the code being added to the +% hook contains arguments. +% \changes{v1.1a}{2023/04/06} +% {Macro added (hook-args).} +% \begin{macrocode} +\seq_new:N \g_@@_replacing_stack_seq +\cs_new:Npn \@@_misused_if_replacing_args:nn #1 #2 + { + \msg_expandable_error:nnn { latex2e } { should-not-happen } + { Misused~\@@_if_replacing_args:. } + } +\cs_new:Npn \@@_if_replacing_args:TF + { \@@_misused_if_replacing_args:nn } +\cs_new_protected:Npn \@@_replacing_args_true: + { + \seq_gpush:No \g_@@_replacing_stack_seq + { \@@_if_replacing_args:TF } + \cs_set:Npn \@@_if_replacing_args:TF { \use_i:nn } + } +\cs_new_protected:Npn \@@_replacing_args_false: + { + \seq_gpush:No \g_@@_replacing_stack_seq + { \@@_if_replacing_args:TF } + \cs_set:Npn \@@_if_replacing_args:TF { \use_ii:nn } + } +\cs_new_protected:Npn \@@_replacing_args_reset: + { + \seq_gpop:NN \g_@@_replacing_stack_seq \l_@@_return_tl + \cs_gset_eq:NN \@@_if_replacing_args:TF \l_@@_return_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \subsection{Messages} % % Hook errors are LaTeX kernel errors: @@ -5137,6 +7146,55 @@ Please~ use~ a~ different~ name~ for~ your~ hook.} % \end{macrocode} % +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{too-many-args} +%<latexrelease> {Hooks~with~args} +% \end{macrocode} +% +% \changes{v1.1a}{2023/04/06} +% {Messages 'too-many-args', 'without-args' and 'one-time-args' added (hook-args).} +% \begin{macrocode} +\msg_new:nnnn { hooks } { too-many-args } + { Too~many~arguments~for~hook~'#1'. } + { + You~tried~to~declare~a~hook~with~#2~arguments,~but~a~ + hook~can~only~have~up~to~nine.~LaTeX~will~define~this~ + hook~with~nine~arguments. + } +% \end{macrocode} +% +% \begin{macrocode} +\msg_new:nnnn { hooks } { without-args } + { Hook~'#1'~has~no~arguments. } + { + You~tried~to~use~\iow_char:N\\#2WithArguments~ + on~a~hook~that~takes~no~arguments.\\ + Check~the~usage~of~the~hook~or~use~\iow_char:N\\#2~instead.\\ + \\ + LaTeX~will~use~\iow_char:N\\#2. + } +% \end{macrocode} +% +% \begin{macrocode} +\msg_new:nnnn { hooks } { one-time-args } + { You~can't~have~arguments~in~used~one-time~hook~'#1'. } + { + You~tried~to~use~\iow_char:N\\#2WithArguments~ + on~a~one-time~hook~that~has~already~been~used.~ + You~have~to~add~the~code~before~the~hook~is~used,~ + or~add~the~code~without~arguments~using~\iow_char:N\\#2~instead.\\ + \\ + LaTeX~will~use~\iow_char:N\\#2. + } +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{too-many-args} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\EndIncludeInRelease +% \end{macrocode} +% % % \begin{macrocode} \msg_new:nnnn { hooks } { hook-disabled } @@ -5278,17 +7336,49 @@ % \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} } +\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}{ +% \NewHookWithArguments, +% \NewReversedHookWithArguments, +% \NewMirroredHookPairWithArguments +% } +% Declaring new hooks with arguments\ldots +% \changes{v1.1a}{2023/04/06} +% {Add \cs{NewHookWithArguments} (hook-args).} +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\NewHookWithArguments} +%<latexrelease> {Hooks~with~args} +\NewDocumentCommand \NewHookWithArguments { mm } + { \hook_new_with_args:nn {#1} {#2} } +\NewDocumentCommand \NewReversedHookWithArguments { mm } + { \hook_new_reversed_with_args:nn {#1} {#2} } +\NewDocumentCommand \NewMirroredHookPairWithArguments { mmm } + { \hook_new_pair_with_args:nnn {#1} {#2} {#3} } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2023/06/01}{\NewHookWithArguments} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_new_protected:Npn \NewHookWithArguments #1 #2 { } +%<latexrelease>\cs_new_protected:Npn \NewReversedHookWithArguments #1 #2 { } +%<latexrelease>\cs_new_protected:Npn \NewMirroredHookPairWithArguments #1 #2 #3 { } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % % % % \begin{macrocode} -%<latexrelease>\IncludeInRelease{2021/06/01}% -%<latexrelease> {\hook_activate_generic:n}{Providing~hooks} +%<latexrelease>\IncludeInRelease{2021/06/01}{\ActivateGenericHook} +%<latexrelease> {Providing~hooks} % \end{macrocode} % % \begin{macro}{\ActivateGenericHook} @@ -5296,7 +7386,8 @@ % \changes{v1.0m}{2021/04/29}{Add \cs{ProvideHook} etc.} % \changes{v1.0o}{2021/08/02}{Change name} % \begin{macrocode} -\NewDocumentCommand \ActivateGenericHook { m }{ \hook_activate_generic:n {#1} } +\NewDocumentCommand \ActivateGenericHook { m } + { \hook_activate_generic:n {#1} } % \end{macrocode} % \end{macro} % @@ -5304,32 +7395,57 @@ % Disabling a generic hook. % \changes{v1.0o}{2021/08/02}{Change name} % \begin{macrocode} -\NewDocumentCommand \DisableGenericHook { m }{ \hook_disable_generic:n {#1} } +\NewDocumentCommand \DisableGenericHook { m } + { \hook_disable_generic:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macrocode} %<latexrelease>\EndIncludeInRelease -%<latexrelease>\IncludeInRelease{2020/10/01} -%<latexrelease> {\hook_activate_generic:n}{Providing~hooks} -%<latexrelease> -%<latexrelease>\def \ActivateGenericHook#1{} -%<latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\IncludeInRelease{2020/10/01}{\ActivateGenericHook} +%<latexrelease> {Providing~hooks} +%<latexrelease>\def \ActivateGenericHook #1 { } +%<latexrelease>\def \DisableGenericHook #1 { } %<latexrelease>\EndIncludeInRelease % \end{macrocode} % % -% \begin{macro}{\AddToHook} +% \begin{macro}{\AddToHook,\AddToHookWithArguments} +% \changes{v1.1a}{2023/04/06} +% {Add \cs{AddToHookWithArguments} (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\AddToHookWithArguments} +%<latexrelease> {Hooks~with~args} \NewDocumentCommand \AddToHook { m o +m } { \hook_gput_code:nnn {#1} {#2} {#3} } +\NewDocumentCommand \AddToHookWithArguments { m o +m } + { \hook_gput_code_with_args:nnn {#1} {#2} {#3} } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\AddToHookWithArguments} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_new_protected:Npn \AddToHookWithArguments #1 #2 #3 { } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % -% \begin{macro}{\AddToHookNext} +% \begin{macro}{\AddToHookNext,\AddToHookNextWithArguments} +% \changes{v1.1a}{2023/04/06} +% {Add \cs{AddToHookNextWithArguments} (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\AddToHookNextWithArguments} +%<latexrelease> {Hooks~with~args} \NewDocumentCommand \AddToHookNext { m +m } { \hook_gput_next_code:nn {#1} {#2} } +\NewDocumentCommand \AddToHookNextWithArguments { m +m } + { \hook_gput_next_code_with_args:nn {#1} {#2} } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\AddToHookNextWithArguments} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_new_protected:Npn \AddToHookNextWithArguments #1 #2 { } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -5396,12 +7512,29 @@ % % % -% \begin{macro}{\UseHook,\UseOneTimeHook} +% \begin{macro}{ +% \UseHook, +% \UseOneTimeHook, +% \UseHookWithArguments, +% \UseOneTimeHookWithArguments, +% } % Avoid the overhead of \pkg{xparse} and its protection that we % don't want here (since the hook should vanish without trace if empty)! +% \changes{v1.1a}{2023/04/06} +% {Add \cs{UseHookWithArguments} (hook-args).} % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01}{\UseHookWithArguments} +%<latexrelease> {Hooks~with~args} \cs_new:Npn \UseHook { \hook_use:n } \cs_new:Npn \UseOneTimeHook { \hook_use_once:n } +\cs_new:Npn \UseHookWithArguments { \hook_use:nnw } +\cs_new:Npn \UseOneTimeHookWithArguments { \hook_use_once:nnw } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2020/10/01}{\UseHookWithArguments} +%<latexrelease> {Hooks~with~args} +%<latexrelease>\cs_new:Npn \UseHookWithArguments #1 #2 { } +%<latexrelease>\cs_new:Npn \UseOneTimeHookWithArguments #1 #2 { } +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % @@ -5462,7 +7595,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\IfHookExistsTF} +% \begin{macro}[EXP,int]{\IfHookExistsTF} % Marked for removal and no longer documented in the doc section! % \phoinline{\cs{IfHookExistsTF} is used in \texttt{jlreq.cls}, % \texttt{pxatbegshi.sty}, \texttt{pxeverysel.sty}, @@ -5484,7 +7617,7 @@ % \changes{v1.0p}{2021/08/20}{Added deprecation warnings for % old generic hook commands (gh/638)} % -% \begin{macro}{ +% \begin{macro}[int]{ % \hook_disable:n, % \hook_provide:n, % \hook_provide_reversed:n, @@ -5529,7 +7662,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{ +% \begin{macro}[int]{ % \DisableHook, % \ProvideHook, % \ProvideReversedHook, @@ -5596,8 +7729,10 @@ %<@@=> % \end{macrocode} % -% \begin{macro}{\@expl@@@initialize@all@@, -% \@expl@@@hook@curr@name@pop@@} +% \begin{macro}[int]{ +% \@expl@@@initialize@all@@, +% \@expl@@@hook@curr@name@pop@@ +% } % % \InternalDetectionOff % \begin{macrocode} @@ -5620,8 +7755,8 @@ % to be for \cs{AddToHook} vice versa (gh/401)} % \begin{macrocode} % -%<latexrelease>\IncludeInRelease{0000/00/00}% -%<latexrelease> {lthooks}{The~hook~management}% +%<latexrelease>\IncludeInRelease{0000/00/00}{lthooks} +%<latexrelease> {The~hook~management}% %<latexrelease> %<latexrelease>\def \NewHook#1{} %<latexrelease>\def \NewReversedHook#1{} @@ -5656,10 +7791,56 @@ %<latexrelease>\long\def \IfHookEmptyTF #1#2#3{#2} %<latexrelease> %<latexrelease>\EndModuleRelease +% \end{macrocode} +% +% \begin{macrocode} +%<@@=hook> +% \end{macrocode} +% +% \changes{v1.1a}{2023/04/06} +% {Add dedicated rollback code to revert data structures (hook-args).} +% \begin{macrocode} +%<latexrelease>\cs:w @@_rollback_tidying: \cs_end: +%<latexrelease>\bool_lazy_and:nnT +%<latexrelease> { \int_compare_p:nNn { \sourceLaTeXdate } > { 20230600 } } +%<latexrelease> { \int_compare_p:nNn { \requestedLaTeXdate } < { 20230601 } } +%<latexrelease> { +%<latexrelease> \cs_gset_protected:Npn \@@_rollback_tidying: +%<latexrelease> { +%<latexrelease> \@latex@error { Rollback~code~executed~twice } +%<latexrelease> { +%<latexrelease> Something~went~wrong~(unless~this~was~ +%<latexrelease> done~on~purpose~in~a~testing~environment). +%<latexrelease> } +%<latexrelease> \use_none:nnnn +%<latexrelease> } +%<latexrelease> \cs_set:Npn \@@_tmp:w #1 #2 +%<latexrelease> { +%<latexrelease> \@@_tl_gset:cx { @@#1~#2 } +%<latexrelease> { +%<latexrelease> \exp_args:No \exp_not:o +%<latexrelease> { +%<latexrelease> \cs:w @@#1~#2 \exp_last_unbraced:Ne \cs_end: +%<latexrelease> { \@@_braced_cs_parameter:n { @@#1~#2 } } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> } +%<latexrelease> \seq_map_inline:Nn \g_@@_all_seq +%<latexrelease> { +%<latexrelease> \exp_after:wN \cs_gset_nopar:Npn +%<latexrelease> \cs:w g_@@_#1_code_prop \exp_args:NNo \exp_args:No +%<latexrelease> \cs_end: { \cs:w g_@@_#1_code_prop \cs_end: } +%<latexrelease> \@@_tmp:w { _toplevel } {#1} +%<latexrelease> \@@_tmp:w { _next } {#1} +%<latexrelease> } +%<latexrelease> } \ExplSyntaxOff %</2ekernel|latexrelease> % \end{macrocode} % +% \begin{macrocode} +%<@@=> +% \end{macrocode} % % \Finale % diff --git a/macros/latex/base/lthyphen.dtx b/macros/latex/base/lthyphen.dtx index b7cede1175..88d30c9cca 100644 --- a/macros/latex/base/lthyphen.dtx +++ b/macros/latex/base/lthyphen.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltidxglo.dtx b/macros/latex/base/ltidxglo.dtx index 395fe83975..a2dc6b873e 100644 --- a/macros/latex/base/ltidxglo.dtx +++ b/macros/latex/base/ltidxglo.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltkeys.dtx b/macros/latex/base/ltkeys.dtx index edf12f7cb2..80c36d5cd9 100644 --- a/macros/latex/base/ltkeys.dtx +++ b/macros/latex/base/ltkeys.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2021-2022 +% Copyright (C) 2021-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltlength.dtx b/macros/latex/base/ltlength.dtx index f979dd4e23..10e4b671c8 100644 --- a/macros/latex/base/ltlength.dtx +++ b/macros/latex/base/ltlength.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltlists.dtx b/macros/latex/base/ltlists.dtx index d0413dad08..d43df93a54 100644 --- a/macros/latex/base/ltlists.dtx +++ b/macros/latex/base/ltlists.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -31,7 +31,7 @@ %<*driver> % \fi \ProvidesFile{ltlists.dtx} - [2020/12/05 v1.0t LaTeX Kernel (List Environments)] + [2023/05/17 v1.0t LaTeX Kernel (List Environments)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltlists.dtx} @@ -68,7 +68,6 @@ % \begin{quote} % |\list|\marg{LABEL}\marg{COMMANDS} ... |\endlist| % \end{quote} -% % which can be invoked by the user as the list environment. The LABEL % argument specifies item labeling. COMMANDS contains commands for % changing the horizontal and vertical spacing parameters. @@ -187,7 +186,7 @@ % |\hsize|. % % Here are the parameters of a list that can be set by commands in -% the |\list|'s COMMANDS argument. These parameters are all TeX +% the |\list|'s COMMANDS argument. These parameters are all \TeX{} % skips or dimensions (defined by |\newskip| or |\newdimen|), so the % usual \TeX\ or \LaTeX\ commands can be used to set them. The % commands will be executed in vmode if and only if the |\list| was @@ -228,7 +227,7 @@ % label. % \item[\cs{labelwidth}:] nominal width of box that contains the label. % If the natural width of the -% label $< =$ \cs{labelwidth}, +% label $\leq$ \cs{labelwidth}, % then the label is flushed right inside a box % of width \cs{labelwidth} (with an \cs{hfil}). % Otherwise, diff --git a/macros/latex/base/ltlogos.dtx b/macros/latex/base/ltlogos.dtx index 56453f73db..7589cf36e1 100644 --- a/macros/latex/base/ltlogos.dtx +++ b/macros/latex/base/ltlogos.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltluatex.dtx b/macros/latex/base/ltluatex.dtx index 6c66a96be0..135cb63009 100644 --- a/macros/latex/base/ltluatex.dtx +++ b/macros/latex/base/ltluatex.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2015-2022 +% Copyright (C) 2015-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -28,7 +28,7 @@ \ProvidesFile{ltluatex.dtx} %</driver> %<*tex> -[2022/10/03 v1.2a +[2023/01/19 v1.2b %</tex> %<plain> LuaTeX support for plain TeX (core) %<*tex> @@ -968,10 +968,10 @@ local luatexbase = luatexbase % % Some Lua best practice: use local versions of functions where possible. % \changes{v1.1u}{2021/08/11}{Define missing local function} +% \changes{v1.2b}{2023/01/19}{Remove unused local variable tex_setattribute} % \begin{macrocode} local string_gsub = string.gsub local tex_count = tex.count -local tex_setattribute = tex.setattribute local tex_setcount = tex.setcount local texio_write_nl = texio.write_nl local flush_list = node.flush_list diff --git a/macros/latex/base/ltluatex.pdf b/macros/latex/base/ltluatex.pdf Binary files differindex f53e9a5b13..8b854be87e 100644 --- a/macros/latex/base/ltluatex.pdf +++ b/macros/latex/base/ltluatex.pdf diff --git a/macros/latex/base/ltmarks-code.pdf b/macros/latex/base/ltmarks-code.pdf Binary files differindex 7c88582032..9fc96a45bd 100644 --- a/macros/latex/base/ltmarks-code.pdf +++ b/macros/latex/base/ltmarks-code.pdf diff --git a/macros/latex/base/ltmarks-doc.pdf b/macros/latex/base/ltmarks-doc.pdf Binary files differindex 0aad6985bc..86c684dc7a 100644 --- a/macros/latex/base/ltmarks-doc.pdf +++ b/macros/latex/base/ltmarks-doc.pdf diff --git a/macros/latex/base/ltmarks.dtx b/macros/latex/base/ltmarks.dtx index 3dc4b493ac..677534dd27 100644 --- a/macros/latex/base/ltmarks.dtx +++ b/macros/latex/base/ltmarks.dtx @@ -1,7 +1,8 @@ % \iffalse meta-comment % -%% File: ltmarks.dtx (C) Copyright 2022 -% Frank Mittelbach, LaTeX Team +%% File: ltmarks.dtx +%% Copyright (C) 2022-2023 +%% Frank Mittelbach, The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this diff --git a/macros/latex/base/ltmath.dtx b/macros/latex/base/ltmath.dtx index 60394460f5..3b1518dd2e 100644 --- a/macros/latex/base/ltmath.dtx +++ b/macros/latex/base/ltmath.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -38,7 +38,7 @@ %<*driver> % \fi \ProvidesFile{ltmath.dtx} - [2022/09/07 v1.2m LaTeX Kernel (Math Setup)] + [2023/05/13 v1.2n LaTeX Kernel (Math Setup)] % \iffalse %</driver> % @@ -1132,9 +1132,29 @@ \fi % \end{macrocode} % +% \begin{macro}{\eqno} +% \begin{macro}{\leqno} +% \changes{v1.2n}{2023/05/13}{add \cs{ignorespaces} gh/1059} +% Ensure the (deprecated) \verb|$$..\eqno 1 $$| ignores spaces. % \begin{macrocode} %</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2023/06/01}% +%<latexrelease> {\eqno}{add ignorespaces to eqno}% +\let\@kernel@eqno\eqno +\let\@kernel@leqno\leqno +\protected\def\eqno{\@kernel@eqno\aftergroup\ignorespaces} +\protected\def\leqno{\@kernel@leqno\aftergroup\ignorespaces} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\eqno}{add ignorespaces to eqno}% +%<latexrelease>\let\eqno\@kernel@eqno +%<latexrelease>\let\leqno\@kernel@leqno +%<latexrelease>\EndIncludeInRelease % \end{macrocode} +% \end{macro} +% \end{macro} % % % @@ -1322,6 +1342,5 @@ % \end{environment} % % -% % \Finale % diff --git a/macros/latex/base/ltmeta.dtx b/macros/latex/base/ltmeta.dtx index 31c5d8dbee..daaa71626b 100644 --- a/macros/latex/base/ltmeta.dtx +++ b/macros/latex/base/ltmeta.dtx @@ -1,7 +1,8 @@ % \iffalse meta-comment % -%% File: ltmeta.dtx (C) Copyright 2021, 2022 -% Frank Mittelbach, LaTeX Team +%% File: ltmeta.dtx +%% Copyright (C) 2021-2023 +%% Frank Mittelbach, The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this diff --git a/macros/latex/base/ltmiscen.dtx b/macros/latex/base/ltmiscen.dtx index b7b2bf5e31..801d1e6862 100644 --- a/macros/latex/base/ltmiscen.dtx +++ b/macros/latex/base/ltmiscen.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltmiscen.dtx} - [2021/06/05 v1.1z LaTeX Kernel (Misc. Environments)] + [2022/11/06 v1.2a LaTeX Kernel (Misc. Environments)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltmiscen.dtx} @@ -270,9 +270,17 @@ % 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}} +% \changes{v1.2a}{2022/11/06}{Repeat release info at the end (gh/944)} % \begin{macrocode} \AddToHook{enddocument/info}[kernel/filelist]{\@dofilelist} \AddToHook{enddocument/info}[kernel/warnings]{\@enddocument@kernel@warnings} +\AddToHook{enddocument/info}[kernel/release]{% + \let\show@release@info\wlog + \show@release@info{ ***********}% + \the\LaTeXReleaseInfo + \show@release@info{ ***********}} + +\DeclareHookRule{enddocument/info}{kernel/release}{before}{kernel/filelist} \DeclareHookRule{enddocument/info}{kernel/filelist}{before}{kernel/warnings} % \end{macrocode} % \end{macro} diff --git a/macros/latex/base/ltnews.cls b/macros/latex/base/ltnews.cls index 9271b56f1c..45ee3664d1 100644 --- a/macros/latex/base/ltnews.cls +++ b/macros/latex/base/ltnews.cls @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 1993-2020 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -41,7 +41,7 @@ \NeedsTeXFormat{LaTeX2e} -\ProvidesClass{ltnews}[2017/12/13 v1.06 Standard LaTeX class] +\ProvidesClass{ltnews}[2023/05/28 v1.08 Standard LaTeX class] % The configuration file, used for passing options. @@ -429,6 +429,30 @@ \newcommand{\@year}{\ClassError{ltnews} {No \protect\publicationyear~given}\@eha} +\newcommand{\publicationday}{\renewcommand{\@day}} +\newcommand{\@day}{01} % most releases happen on 1st of a month + +\newcommand{\publicationdate}{% + % support draft ltnews, \publicationyear{2023 --- DRAFT ...} + \expandafter\@gobblenonyear\@year\@nil + -\@julianmonthtonum\@month-\two@digits\@day} + +\newcommand{\@julianmonthtonum}[1]{\@nameuse{@juliantonum#1}} +\def\@juliantonumJanuary {01} +\def\@juliantonumFebruary {02} +\def\@juliantonumMarch {03} +\def\@juliantonumApril {04} +\def\@juliantonumMay {05} +\def\@juliantonumJune {06} +\def\@juliantonumJuly {07} +\def\@juliantonumAugust {08} +\def\@juliantonumSeptember{09} +\def\@juliantonumOctober {10} +\def\@juliantonumNovember {11} +\def\@juliantonumDecember {12} + +\long\def\@gobblenonyear#1#2#3#4#5\@nil{#1#2#3#4} + \newcommand{\publicationissue}{\renewcommand{\@issue}} \newcommand{\@issue}{\ClassError{ltnews} {No \protect\publicationissue~given}\@eha} @@ -449,7 +473,8 @@ \twocolumn[{% \parbox[t][7\baselineskip]{\textwidth}{% \@titlefont\@title\\[\medskipamount] - \normalfont\normalsize\issuename~\@issue, \@month~\@year + \normalfont\normalsize\issuename~\@issue, + \@month~\@year~(\LaTeX\ release \publicationdate)% }% }]% \thispagestyle{titlepage} @@ -494,6 +519,17 @@ {1sp}{\@subheadingfont}% } + +% suggestion by Karl Berry (not integrated (yet)) + +\newcommand{\ltnewssectformat}{% + \@headingfont + \frenchspacing + \raggedright + \hyphenpenalty=10000 + \exhyphenpenalty=10000 +} + % No section numbers. \setcounter{secnumdepth}{0} diff --git a/macros/latex/base/ltnews.pdf b/macros/latex/base/ltnews.pdf Binary files differindex 5a52a33471..5ecb14ad3e 100644 --- a/macros/latex/base/ltnews.pdf +++ b/macros/latex/base/ltnews.pdf diff --git a/macros/latex/base/ltnews.tex b/macros/latex/base/ltnews.tex index 8d45f77cda..d239fc274f 100644 --- a/macros/latex/base/ltnews.tex +++ b/macros/latex/base/ltnews.tex @@ -1,7 +1,7 @@ % \iffalse meta-comment % % Copyright (C) 2006, 2009, 2011, 2014 Heiko Oberdiek -% Copyright (C) 2014-2022 +% Copyright (C) 2014-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -40,7 +40,7 @@ \ProvidesFile{ltnews.tex}% [2022/06/10 v1.4e Master file for ltnews*.tex (LaTeX Project)] -\providecommand*{\lastissue}{36} +\providecommand*{\lastissue}{37} \InputIfFileExists{ltnews-lastissue.cfg}{}{} @@ -113,22 +113,11 @@ \renewcommand{\@evenfoot}{\@indiciafont\@indicia\hfill --\thepage}% } -\newcommand*{\MonthJanuary}{01} -\newcommand*{\MonthFebruary}{02} -\newcommand*{\MonthMarch}{03} -\newcommand*{\MonthApril}{04} -\newcommand*{\MonthMay}{05} -\newcommand*{\MonthJune}{06} -\newcommand*{\MonthJuly}{07} -\newcommand*{\MonthAugust}{08} -\newcommand*{\MonthSeptember}{09} -\newcommand*{\MonthOctober}{10} -\newcommand*{\MonthNovember}{11} -\newcommand*{\MonthDecember}{12} \newcommand*{\printissue}{% Issue % \texorpdfstring{\number\value{issue}}{\theissue}, % - \texorpdfstring{\@month\space\@year}{\@year/\@nameuse{Month\@month}}% + \texorpdfstring{\@month\space\@year\space(\publicationdate)} + {\@year/\@julianmonthtonum{\@month}}% } \let\l@part\l@section \let\l@section\l@subsection @@ -303,6 +292,7 @@ \loop \ifnum\value{issue}<\lastissue \stepcounter{issue}% + \publicationday{01}% \input{ltnews\theissue}% \repeat \stepcounter{issue}% diff --git a/macros/latex/base/ltnews01.pdf b/macros/latex/base/ltnews01.pdf Binary files differindex 46f89cea3b..670facd8c6 100644 --- a/macros/latex/base/ltnews01.pdf +++ b/macros/latex/base/ltnews01.pdf diff --git a/macros/latex/base/ltnews01.tex b/macros/latex/base/ltnews01.tex index 08ac57d27d..55c6b20dd6 100644 --- a/macros/latex/base/ltnews01.tex +++ b/macros/latex/base/ltnews01.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews02.pdf b/macros/latex/base/ltnews02.pdf Binary files differindex bbe1c4ebd1..458c10709a 100644 --- a/macros/latex/base/ltnews02.pdf +++ b/macros/latex/base/ltnews02.pdf diff --git a/macros/latex/base/ltnews02.tex b/macros/latex/base/ltnews02.tex index 1d875dcd03..58856fe97b 100644 --- a/macros/latex/base/ltnews02.tex +++ b/macros/latex/base/ltnews02.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews03.pdf b/macros/latex/base/ltnews03.pdf Binary files differindex 58a9a40d0b..54deb688dd 100644 --- a/macros/latex/base/ltnews03.pdf +++ b/macros/latex/base/ltnews03.pdf diff --git a/macros/latex/base/ltnews03.tex b/macros/latex/base/ltnews03.tex index 93f0963426..96a5bec428 100644 --- a/macros/latex/base/ltnews03.tex +++ b/macros/latex/base/ltnews03.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews04.pdf b/macros/latex/base/ltnews04.pdf Binary files differindex 5236b48dd8..37a344bc9d 100644 --- a/macros/latex/base/ltnews04.pdf +++ b/macros/latex/base/ltnews04.pdf diff --git a/macros/latex/base/ltnews04.tex b/macros/latex/base/ltnews04.tex index 527024fa18..ab49d7ade3 100644 --- a/macros/latex/base/ltnews04.tex +++ b/macros/latex/base/ltnews04.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews05.pdf b/macros/latex/base/ltnews05.pdf Binary files differindex 82c03a4c12..f84999681e 100644 --- a/macros/latex/base/ltnews05.pdf +++ b/macros/latex/base/ltnews05.pdf diff --git a/macros/latex/base/ltnews05.tex b/macros/latex/base/ltnews05.tex index d13f469dd6..cdfe8bc072 100644 --- a/macros/latex/base/ltnews05.tex +++ b/macros/latex/base/ltnews05.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews06.pdf b/macros/latex/base/ltnews06.pdf Binary files differindex 0b8753998e..d5b2c509a7 100644 --- a/macros/latex/base/ltnews06.pdf +++ b/macros/latex/base/ltnews06.pdf diff --git a/macros/latex/base/ltnews06.tex b/macros/latex/base/ltnews06.tex index ac32eab8d1..3d5cadb745 100644 --- a/macros/latex/base/ltnews06.tex +++ b/macros/latex/base/ltnews06.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews07.pdf b/macros/latex/base/ltnews07.pdf Binary files differindex b8aad35370..bca35e9904 100644 --- a/macros/latex/base/ltnews07.pdf +++ b/macros/latex/base/ltnews07.pdf diff --git a/macros/latex/base/ltnews07.tex b/macros/latex/base/ltnews07.tex index 56cfd76661..43cf204fed 100644 --- a/macros/latex/base/ltnews07.tex +++ b/macros/latex/base/ltnews07.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews08.pdf b/macros/latex/base/ltnews08.pdf Binary files differindex c3d9b6b848..157e8f2c3d 100644 --- a/macros/latex/base/ltnews08.pdf +++ b/macros/latex/base/ltnews08.pdf diff --git a/macros/latex/base/ltnews08.tex b/macros/latex/base/ltnews08.tex index 68cd1247e6..f1386a5332 100644 --- a/macros/latex/base/ltnews08.tex +++ b/macros/latex/base/ltnews08.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews09.pdf b/macros/latex/base/ltnews09.pdf Binary files differindex 92fb1771a0..543a2c8795 100644 --- a/macros/latex/base/ltnews09.pdf +++ b/macros/latex/base/ltnews09.pdf diff --git a/macros/latex/base/ltnews09.tex b/macros/latex/base/ltnews09.tex index af14a53e34..26eccedd1e 100644 --- a/macros/latex/base/ltnews09.tex +++ b/macros/latex/base/ltnews09.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews10.pdf b/macros/latex/base/ltnews10.pdf Binary files differindex f87a2bd4e2..7dc732ba41 100644 --- a/macros/latex/base/ltnews10.pdf +++ b/macros/latex/base/ltnews10.pdf diff --git a/macros/latex/base/ltnews10.tex b/macros/latex/base/ltnews10.tex index c6a77e6e36..b011eacf7e 100644 --- a/macros/latex/base/ltnews10.tex +++ b/macros/latex/base/ltnews10.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews11.pdf b/macros/latex/base/ltnews11.pdf Binary files differindex 8a9605348b..c07bf4681b 100644 --- a/macros/latex/base/ltnews11.pdf +++ b/macros/latex/base/ltnews11.pdf diff --git a/macros/latex/base/ltnews11.tex b/macros/latex/base/ltnews11.tex index b4f6d19910..07dbd64240 100644 --- a/macros/latex/base/ltnews11.tex +++ b/macros/latex/base/ltnews11.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews12.pdf b/macros/latex/base/ltnews12.pdf Binary files differindex b74dc492f6..f848096ed0 100644 --- a/macros/latex/base/ltnews12.pdf +++ b/macros/latex/base/ltnews12.pdf diff --git a/macros/latex/base/ltnews12.tex b/macros/latex/base/ltnews12.tex index b7a01bc208..38ea9122a0 100644 --- a/macros/latex/base/ltnews12.tex +++ b/macros/latex/base/ltnews12.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews13.pdf b/macros/latex/base/ltnews13.pdf Binary files differindex 014faa5e5f..d511573394 100644 --- a/macros/latex/base/ltnews13.pdf +++ b/macros/latex/base/ltnews13.pdf diff --git a/macros/latex/base/ltnews13.tex b/macros/latex/base/ltnews13.tex index 0cbbe49a5d..e489b4ff27 100644 --- a/macros/latex/base/ltnews13.tex +++ b/macros/latex/base/ltnews13.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews14.pdf b/macros/latex/base/ltnews14.pdf Binary files differindex 40972a5a43..debb104763 100644 --- a/macros/latex/base/ltnews14.pdf +++ b/macros/latex/base/ltnews14.pdf diff --git a/macros/latex/base/ltnews14.tex b/macros/latex/base/ltnews14.tex index b5fa7cb019..44cc44647e 100644 --- a/macros/latex/base/ltnews14.tex +++ b/macros/latex/base/ltnews14.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews15.pdf b/macros/latex/base/ltnews15.pdf Binary files differindex 3fd5dce4aa..9e2432ea99 100644 --- a/macros/latex/base/ltnews15.pdf +++ b/macros/latex/base/ltnews15.pdf diff --git a/macros/latex/base/ltnews15.tex b/macros/latex/base/ltnews15.tex index 3b1ea3f89c..b95801dd6e 100644 --- a/macros/latex/base/ltnews15.tex +++ b/macros/latex/base/ltnews15.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews16.pdf b/macros/latex/base/ltnews16.pdf Binary files differindex 5fc21f98ee..612c1bd5f2 100644 --- a/macros/latex/base/ltnews16.pdf +++ b/macros/latex/base/ltnews16.pdf diff --git a/macros/latex/base/ltnews16.tex b/macros/latex/base/ltnews16.tex index 7f7183ac0e..7edf8a7f53 100644 --- a/macros/latex/base/ltnews16.tex +++ b/macros/latex/base/ltnews16.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews17.pdf b/macros/latex/base/ltnews17.pdf Binary files differindex 9806abea05..e8325346a0 100644 --- a/macros/latex/base/ltnews17.pdf +++ b/macros/latex/base/ltnews17.pdf diff --git a/macros/latex/base/ltnews17.tex b/macros/latex/base/ltnews17.tex index 4dab20f53f..e18e4660eb 100644 --- a/macros/latex/base/ltnews17.tex +++ b/macros/latex/base/ltnews17.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews18.pdf b/macros/latex/base/ltnews18.pdf Binary files differindex b3628bab08..641dc18d2e 100644 --- a/macros/latex/base/ltnews18.pdf +++ b/macros/latex/base/ltnews18.pdf diff --git a/macros/latex/base/ltnews18.tex b/macros/latex/base/ltnews18.tex index 04491760b2..8c70621534 100644 --- a/macros/latex/base/ltnews18.tex +++ b/macros/latex/base/ltnews18.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews19.pdf b/macros/latex/base/ltnews19.pdf Binary files differindex d6ac262c05..2bf99f3954 100644 --- a/macros/latex/base/ltnews19.pdf +++ b/macros/latex/base/ltnews19.pdf diff --git a/macros/latex/base/ltnews19.tex b/macros/latex/base/ltnews19.tex index 43d388b29b..7e9492a8f2 100644 --- a/macros/latex/base/ltnews19.tex +++ b/macros/latex/base/ltnews19.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -36,6 +36,7 @@ \usepackage{lmodern,url} +\publicationday{24} \publicationmonth{September} \publicationyear{2009} diff --git a/macros/latex/base/ltnews20.pdf b/macros/latex/base/ltnews20.pdf Binary files differindex 54544a702f..6382f7b26f 100644 --- a/macros/latex/base/ltnews20.pdf +++ b/macros/latex/base/ltnews20.pdf diff --git a/macros/latex/base/ltnews20.tex b/macros/latex/base/ltnews20.tex index 89d166b49c..b233f92dc4 100644 --- a/macros/latex/base/ltnews20.tex +++ b/macros/latex/base/ltnews20.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 1993--2019 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -36,6 +36,7 @@ \usepackage{lmodern,url} +\publicationday{27} \publicationmonth{June} \publicationyear{2011} diff --git a/macros/latex/base/ltnews21.pdf b/macros/latex/base/ltnews21.pdf Binary files differindex 69332e0e04..c6b0913181 100644 --- a/macros/latex/base/ltnews21.pdf +++ b/macros/latex/base/ltnews21.pdf diff --git a/macros/latex/base/ltnews21.tex b/macros/latex/base/ltnews21.tex index 7b363447d9..a48cd0b199 100644 --- a/macros/latex/base/ltnews21.tex +++ b/macros/latex/base/ltnews21.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2019 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews22.pdf b/macros/latex/base/ltnews22.pdf Binary files differindex 429820ea50..4ca923a557 100644 --- a/macros/latex/base/ltnews22.pdf +++ b/macros/latex/base/ltnews22.pdf diff --git a/macros/latex/base/ltnews22.tex b/macros/latex/base/ltnews22.tex index 8d1c91acfa..dfc2e2326a 100644 --- a/macros/latex/base/ltnews22.tex +++ b/macros/latex/base/ltnews22.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2015-2022 +% Copyright (C) 2015-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews23.pdf b/macros/latex/base/ltnews23.pdf Binary files differindex 86bcb55ada..b3b97d9071 100644 --- a/macros/latex/base/ltnews23.pdf +++ b/macros/latex/base/ltnews23.pdf diff --git a/macros/latex/base/ltnews23.tex b/macros/latex/base/ltnews23.tex index 29241766ca..ee75a6463e 100644 --- a/macros/latex/base/ltnews23.tex +++ b/macros/latex/base/ltnews23.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2015-2022 +% Copyright (C) 2015-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews24.pdf b/macros/latex/base/ltnews24.pdf Binary files differindex 30ddd82eba..0555a29b8c 100644 --- a/macros/latex/base/ltnews24.pdf +++ b/macros/latex/base/ltnews24.pdf diff --git a/macros/latex/base/ltnews24.tex b/macros/latex/base/ltnews24.tex index 13d2fc8519..6a50ef902c 100644 --- a/macros/latex/base/ltnews24.tex +++ b/macros/latex/base/ltnews24.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2015-2022 +% Copyright (C) 2015-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews25.pdf b/macros/latex/base/ltnews25.pdf Binary files differindex 0e2c3fa717..17c09e30d9 100644 --- a/macros/latex/base/ltnews25.pdf +++ b/macros/latex/base/ltnews25.pdf diff --git a/macros/latex/base/ltnews25.tex b/macros/latex/base/ltnews25.tex index 5a9f480718..0676220a2e 100644 --- a/macros/latex/base/ltnews25.tex +++ b/macros/latex/base/ltnews25.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2016-2022 +% Copyright (C) 2016-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews26.pdf b/macros/latex/base/ltnews26.pdf Binary files differindex 0e31e2c482..64a5a94b8a 100644 --- a/macros/latex/base/ltnews26.pdf +++ b/macros/latex/base/ltnews26.pdf diff --git a/macros/latex/base/ltnews26.tex b/macros/latex/base/ltnews26.tex index 94b4c4818b..9fbb6716b1 100644 --- a/macros/latex/base/ltnews26.tex +++ b/macros/latex/base/ltnews26.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2017-2022 +% Copyright (C) 2017-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews27.pdf b/macros/latex/base/ltnews27.pdf Binary files differindex 260f2b6ebd..0db3aec237 100644 --- a/macros/latex/base/ltnews27.pdf +++ b/macros/latex/base/ltnews27.pdf diff --git a/macros/latex/base/ltnews27.tex b/macros/latex/base/ltnews27.tex index 03c8c04205..917bf1cc10 100644 --- a/macros/latex/base/ltnews27.tex +++ b/macros/latex/base/ltnews27.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2017-2022 +% Copyright (C) 2017-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -35,6 +35,7 @@ \usepackage{lmodern,url,hologo} +\publicationday{15} \publicationmonth{April} \publicationyear{2017} diff --git a/macros/latex/base/ltnews28.pdf b/macros/latex/base/ltnews28.pdf Binary files differindex a20223db92..e1bdb5e1b5 100644 --- a/macros/latex/base/ltnews28.pdf +++ b/macros/latex/base/ltnews28.pdf diff --git a/macros/latex/base/ltnews28.tex b/macros/latex/base/ltnews28.tex index 28bfe0577c..3c3b92da97 100644 --- a/macros/latex/base/ltnews28.tex +++ b/macros/latex/base/ltnews28.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2017-2022 +% Copyright (C) 2017-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews29.pdf b/macros/latex/base/ltnews29.pdf Binary files differindex 95619ddaff..609c139590 100644 --- a/macros/latex/base/ltnews29.pdf +++ b/macros/latex/base/ltnews29.pdf diff --git a/macros/latex/base/ltnews29.tex b/macros/latex/base/ltnews29.tex index c06d4de347..999836b01d 100644 --- a/macros/latex/base/ltnews29.tex +++ b/macros/latex/base/ltnews29.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2018-2022 +% Copyright (C) 2018-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews30.pdf b/macros/latex/base/ltnews30.pdf Binary files differindex d45d527caa..fbd9a3af3d 100644 --- a/macros/latex/base/ltnews30.pdf +++ b/macros/latex/base/ltnews30.pdf diff --git a/macros/latex/base/ltnews30.tex b/macros/latex/base/ltnews30.tex index 74d7659512..8183f7eabb 100644 --- a/macros/latex/base/ltnews30.tex +++ b/macros/latex/base/ltnews30.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2019 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews31.pdf b/macros/latex/base/ltnews31.pdf Binary files differindex f88b776066..bb9c2e3e45 100644 --- a/macros/latex/base/ltnews31.pdf +++ b/macros/latex/base/ltnews31.pdf diff --git a/macros/latex/base/ltnews31.tex b/macros/latex/base/ltnews31.tex index 8bb6e638b5..44bf494142 100644 --- a/macros/latex/base/ltnews31.tex +++ b/macros/latex/base/ltnews31.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2019-2020 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -119,6 +119,7 @@ \fi %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\publicationday{02} \publicationmonth{February} \publicationyear{2020} diff --git a/macros/latex/base/ltnews32.pdf b/macros/latex/base/ltnews32.pdf Binary files differindex f6298a7cfb..6c99b2cf6d 100644 --- a/macros/latex/base/ltnews32.pdf +++ b/macros/latex/base/ltnews32.pdf diff --git a/macros/latex/base/ltnews32.tex b/macros/latex/base/ltnews32.tex index 28f3bf88b4..c64cd97958 100644 --- a/macros/latex/base/ltnews32.tex +++ b/macros/latex/base/ltnews32.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2019-2020 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews33.pdf b/macros/latex/base/ltnews33.pdf Binary files differindex b5132f035e..9372bf0ec1 100644 --- a/macros/latex/base/ltnews33.pdf +++ b/macros/latex/base/ltnews33.pdf diff --git a/macros/latex/base/ltnews33.tex b/macros/latex/base/ltnews33.tex index 39af4f1b72..0b98a707ba 100644 --- a/macros/latex/base/ltnews33.tex +++ b/macros/latex/base/ltnews33.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2019-2021 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltnews34.pdf b/macros/latex/base/ltnews34.pdf Binary files differindex 8962193f72..481e449690 100644 --- a/macros/latex/base/ltnews34.pdf +++ b/macros/latex/base/ltnews34.pdf diff --git a/macros/latex/base/ltnews34.tex b/macros/latex/base/ltnews34.tex index 04d1c25bc7..d3a9202b56 100644 --- a/macros/latex/base/ltnews34.tex +++ b/macros/latex/base/ltnews34.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2019-2021 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -116,6 +116,7 @@ \providecommand\tubcommand[1]{} \tubcommand{\input{tubltmac}} +\publicationday{15} \publicationmonth{November} \publicationyear{2021} diff --git a/macros/latex/base/ltnews35.pdf b/macros/latex/base/ltnews35.pdf Binary files differindex e044273d06..1eda06fb70 100644 --- a/macros/latex/base/ltnews35.pdf +++ b/macros/latex/base/ltnews35.pdf diff --git a/macros/latex/base/ltnews35.tex b/macros/latex/base/ltnews35.tex index 0230ef6e58..8d49bf1984 100644 --- a/macros/latex/base/ltnews35.tex +++ b/macros/latex/base/ltnews35.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2021-2022 +% Copyright (C) 2021-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -322,7 +322,6 @@ has been refined, such that \ProcessKeyOptions \end{verbatim} will now automatically pick up the package name as the key \emph{family}, -%unless explicitly given as an optional argument. unless explicitly given as an optional argument: \begin{verbatim} \ProcessKeyOptions[family] @@ -378,9 +377,7 @@ syntax are described in \file{usrguide3.pdf}. The command \cs{fpeval} offers a rich syntax allowing for extensive calculations, whereas the other three commands are essentially thin wrappers for \cs{numexpr}, \cs{dimexpr}, and \cs{glueexpr} \Dash therefore inheriting some syntax -%peculiars and limitations in expressiveness. peculiarities and limitations in expressiveness. -% \newcommand\calulateheight[1]{% \begin{verbatim} \newcommand\calculateheight[1]{% \setlength\textheight{\dimeval{\topskip @@ -698,7 +695,7 @@ Source files containing \textlangle\ or \textrangle\ directly written as Unicode codepoints U+2329 and U+232A no longer break when the source file gets normalized under Unicode normalization rules. % -\githubissue{gh/714} +\githubissue{714} @@ -907,7 +904,6 @@ For details and further examples, see \file{mathcolor.pdf}. \subsection{Fix locating files with \cs{graphicspath}} -% If a call to \cs{includegraphics} asked for a file (say, \file{image}) without extension, and if both \file{A/image.pdf} and \file{B/image.tex} @@ -953,22 +949,10 @@ internal syntax errors due to premature expansion. \emph{\LaTeX{} Tagged PDF \Dash A blueprint for a large project}.\\ \url{https://latex-project.org/publications/indexbyyear/2020/} -%\bibitem{35:source2e} -% \emph{\LaTeX{} documentation on the \LaTeX{} Project Website}.\\ -% \url{https://latex-project.org/help/documentation/} - -%\bibitem{35:ltnews31} \LaTeX{} Project Team: -% \emph{\LaTeXe{} news 31}.\\ -% \url{https://latex-project.org/news/latex2e-news/ltnews31.pdf} - \bibitem{35:ltnews32} \LaTeX{} Project Team: \emph{\LaTeXe{} news 32}.\\ \url{https://latex-project.org/news/latex2e-news/ltnews32.pdf} -%\bibitem{35:ltnews33} \LaTeX{} Project Team: -% \emph{\LaTeXe{} news 33}.\\ -% \url{https://latex-project.org/news/latex2e-news/ltnews33.pdf} - \bibitem{35:ltnews34} \LaTeX{} Project Team: \emph{\LaTeXe{} news 34}.\\ \url{https://latex-project.org/news/latex2e-news/ltnews34.pdf} diff --git a/macros/latex/base/ltnews36.pdf b/macros/latex/base/ltnews36.pdf Binary files differindex fbbd2036d0..7113dbcce4 100644 --- a/macros/latex/base/ltnews36.pdf +++ b/macros/latex/base/ltnews36.pdf diff --git a/macros/latex/base/ltnews36.tex b/macros/latex/base/ltnews36.tex index d6df801db2..5dee958747 100644 --- a/macros/latex/base/ltnews36.tex +++ b/macros/latex/base/ltnews36.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2021-2022 +% Copyright (C) 2021-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -262,10 +262,11 @@ will give the expected result: {\fontfamily{cmr} \bfseries \textsc{\textsl{Bold Slanted Small Caps}}; \textsc{\textit{Bold Italic Small Caps}}}. -Given that the Computer Modern fonts in \texttt{T1} do not have real italic small caps but only -slanted small caps, the latter is substituted for the former, which is -why above both work but you see no difference between the two (and in the log you get a -substitution warning for the \cs{textit}\cs{textsc} shape combination). +Given that the Computer Modern fonts in \texttt{T1} do not have real +italic small caps but only slanted small caps, the latter is +substituted for the former. This is why both work in the above, but +there is no difference between the two (and you get a substitution +warning for the \cs{textit}\cs{textsc} shape combination). % \githubissue{782} diff --git a/macros/latex/base/ltnews37.pdf b/macros/latex/base/ltnews37.pdf Binary files differnew file mode 100644 index 0000000000..b0f6947d8d --- /dev/null +++ b/macros/latex/base/ltnews37.pdf diff --git a/macros/latex/base/ltnews37.tex b/macros/latex/base/ltnews37.tex new file mode 100644 index 0000000000..5527975c54 --- /dev/null +++ b/macros/latex/base/ltnews37.tex @@ -0,0 +1,848 @@ +% \iffalse meta-comment +% +% Copyright (C) 2021-2023 +% The LaTeX Project and any individual authors listed elsewhere +% in this file. +% +% This file is part of the LaTeX base system. +% -—————————————— +% +% It may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3c +% of this license or (at your option) any later version. +% The latest version of this license is in +% https://www.latex-project.org/lppl.txt +% and version 1.3c or later is part of all distributions of LaTeX +% version 2008 or later. +% +% This file has the LPPL maintenance status "maintained". +% +% The list of all files belonging to the LaTeX base distribution is +% given in the file `manifest.txt'. See also `legal.txt' for additional +% information. +% +% The list of derived (unpacked) files belonging to the distribution +% and covered by LPPL is defined by the unpacking scripts (with +% extension .ins) which are part of the distribution. +% +% \fi +% Filename: ltnews37.tex +% +% This is issue 37 of LaTeX News. + +\NeedsTeXFormat{LaTeX2e}[2020-02-02] + +\documentclass{ltnews} + +%% Maybe needed only for Chris' inadequate system: +\providecommand\Dash {\unskip \textemdash} + +%% NOTE: Chris' preferred hyphens! +%%\showhyphens{parameters} +%% \hyphenation{because parameters parameter} + +\usepackage[T1]{fontenc} + +\usepackage{lmodern,url,hologo} + +\usepackage{csquotes} +\usepackage{multicol} +\usepackage{color} + +\providecommand\hook[1]{\texttt{#1}} + +\providecommand\meta[1]{$\langle$\textrm{\itshape#1}$\rangle$} +\providecommand\option[1]{\texttt{#1}} +\providecommand\env[1]{\texttt{#1}} +\providecommand\Arg[1]{\texttt\{\meta{#1}\texttt\}} + + +\providecommand\eTeX{\hologo{eTeX}} +\providecommand\XeTeX{\hologo{XeTeX}} +\providecommand\LuaTeX{\hologo{LuaTeX}} +\providecommand\pdfTeX{\hologo{pdfTeX}} +\providecommand\MiKTeX{\hologo{MiKTeX}} +\providecommand\CTAN{\textsc{ctan}} +\providecommand\TL{\TeX\,Live} +\providecommand\githubissue[2][]{\ifhmode\unskip\fi + \quad\penalty500\strut\nobreak\hfill + \mbox{\small\slshape(% + \href{https://github.com/latex3/latex2e/issues/\getfirstgithubissue#2 \relax}% + {github issue#1 #2}% + )}% + \par\smallskip} +%% But Chris has to mostly disable \href for his TEXPAD app: +%% \def\href #1{} % Only For Chris' deficient TeX engine + +% simple solution right now (just link to the first issue if there are more) +\def\getfirstgithubissue#1 #2\relax{#1} + +\providecommand\sxissue[1]{\ifhmode\unskip + \else + % githubissue preceding + \vskip-\smallskipamount + \vskip-\parskip + \fi + \quad\penalty500\strut\nobreak\hfill + \mbox{\small\slshape(\url{https://tex.stackexchange.com/#1})}\par} + +\providecommand\gnatsissue[2]{\ifhmode\unskip\fi + \quad\penalty500\strut\nobreak\hfill + \mbox{\small\slshape(% + \href{https://www.latex-project.org/cgi-bin/ltxbugs2html?pr=#1\%2F\getfirstgithubissue#2 \relax}% + {gnats issue #1/#2}% + )}% + \par} + +\let\cls\pkg +\providecommand\env[1]{\texttt{#1}} +\providecommand\acro[1]{\textsc{#1}} + +\vbadness=1400 % accept slightly empty columns + + +\makeatletter +% maybe not the greatest design but normally we wouldn't have subsubsections +\renewcommand{\subsubsection}{% + \@startsection {subsubsection}{2}{0pt}{1.5ex \@plus 1ex \@minus .2ex}% + {-1em}{\@subheadingfont\colonize}% +} +\providecommand\colonize[1]{#1:} +\makeatother + +\let\finalvspace\vspace % for document layout fixes + +% Undo ltnews's \verbatim@font with active < and > +% (we have meta variables in verbatim, so keep it.) +%\makeatletter +%\def\verbatim@font{% +% \normalsize\ttfamily} +%\makeatother + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\providecommand\tubcommand[1]{} +\tubcommand{\input{tubltmac}} + +% \publicationday{01} % change this if it's not released on 1st of a month +\publicationmonth{June} +%\publicationyear{2023 --- DRAFT version for upcoming release} +\publicationyear{2023} + +\publicationissue{37} + +\begin{document} + +\tubcommand{\addtolength\textheight{4.1pc}} % only for TUB + +\maketitle +{\hyphenpenalty=10000 \exhyphenpenalty=10000 \spaceskip=3.33pt \hbadness=10000 +\tableofcontents} + +\setlength\rightskip{0pt plus 3em} + +% for ltnews37, squeeze to five pages. +\tubcommand{\fontsize{9.6}{12}\selectfont} + + +\medskip + + +%\section{Introduction} + + +\section{New functionality offered as part of the + \enquote{\LaTeX{} Tagged PDF} project} + +We have now enabled new automatic tagging functionality for additional +\LaTeX{} elements, among them most display environments, standard +sectioning commands, content, figure and table listings, floats and graphics and +bibliographies. This can +be activated through +\begin{verbatim} +\DocumentMetadata{testphase=phase-III} +\end{verbatim} +At this point in time tagging support is only available for a +restricted set of documents, i.e., those that use one of the basic +document classes (\texttt{article}, \texttt{report}, and +\texttt{book}) and only use commands and environments described in +Lamport's \LaTeX{} manual. + +Using other document classes or adding additional packages in the +preamble may work (or may partially work) but at this stage it is not +very likely, at least not for packages or classes that excessively +alter internals of \LaTeX{}. + +Also note that there are still several environments and commands +described in the \LaTeX{} manual that do not have tagging support yet, +notably tabulars, \texttt{tabbing}, the various math environment and a +few others. They will get this support as part of \texttt{phase-III}, +but some of them will be delayed until after the June release. + +A prototype for math tagging (including support for the \pkg{amsmath} +environments) is already available, but it is mainly intended for +experimentation and feedback and the resulting tagging is by no means +the way we envision it to be eventually. If you would like to try it out use +the following line: +\begin{verbatim} +\DocumentMetadata{testphase={phase-III,math}} +\end{verbatim} +Note that the math tagging code at this point in time will clash with +packages that redefine the \texttt{\$} character (which then may lead to strange +errors) and that packages that use math mode for non-mathematical +constructs may result in surprising output as far as tagging is +concerned. Feedback on which packages fail with the code in one or +another way would be appreciated. + +The \texttt{latex-lab} bundle contains various +(still untagged) documentation files about the new code that can +be accessed with \verb|texdoc -l latex-lab|. + +Feedback is welcome! +Please use \url{https://github.com/latex3/latex2e/discussions/1010}. + + + +\section{New or improved commands} + +\subsection{Extending hooks to take arguments} + +Hooks have always been containers for code whose outcome was entirely +dependent on the contents of the hook alone. If any type of contextual +information had to be passed to the hook, it had to be done by setting +some variable before the hook so that the code in the hook could use +that. But this is somewhat hard to keep track of, clumsy to implement, +and it required the programmer to have some kind of \enquote{hook before +the hook} to do that setup. + +To make things a bit easier, \pkg{lthooks} was enhanced to support hooks +with arguments. Hooks can now be declared and used with arguments, then +the code added to these hooks can reference the hook's arguments using +\verb|#1|, \verb|#2|, etc., so now hooks can behave more like macros +than like \emph{token lists} (using \pkg{expl3} terminology). Regular +argument-less hooks continue to work exactly like they did before: this +extension is completely compatible with older documents and packages. + +\AddToHook{cmd/verbatim@font/after}[hack]{\small} +To declare a hook with arguments, use +\begin{verbatim} +\NewHookWithArguments {<hook>} {<num-args>} +\end{verbatim} +then, similarly, to use the code in the hook, supposing a hook declared +with 2 arguments, write +\begin{verbatim} +\UseHookWithArguments {<hook>} {2} {<arg1>} {<arg2>} +\end{verbatim} + +Or, if you want to add some code to a hook that takes arguments, write +\begin{verbatim} +\AddToHookWithArguments {<hook>} [<label>] {<code>} +\end{verbatim} +exactly like you would for regular hooks, except that the \meta{code} +can use the arguments by referencing \verb|#1|, \verb|#2|, etc. In this +case, if you want to add an actual parameter token (\verb|#|) to the +\meta{code}, you have to double it, as usual. +\RemoveFromHook{cmd/verbatim@font/after}[hack] + +Additionally, if you want to add \enquote{regular} code to a hook with +arguments, you can still use \cs{AddToHook} --- in that case \verb|#| +tokens are \emph{not} doubled. This means that a package author can +decide to add arguments to an existing hook without worrying about +compatibility: \cs{AddToHook} will do the right thing and will not +mistakenly reference the newly added arguments. + +The commands \cs{NewReversedHookWithArguments}, \cs +{NewMirroredHookPairWithArguments}, \cs +{AddToHookNextWithArguments}, \cs{UseOneTimeHookWithArguments}, and +the \pkg{expl3} counterparts of the commands discussed in this section +were also added. The complete documentation can be found in the +\pkg{lthooks} documentation \cite{37:lthooks-doc}. + +\subsubsection{Generic \texttt{cmd} hooks with arguments} + +Along with the possibility of passing arguments to a regular hook as +discussed above, generic \hook{cmd} hooks can now access the arguments +of the command they are patched into, using the interface described in +the previous section. + +For example, if you were to add some code to the \cs{title} command +using hooks, you could access the actual title given in the argument. +Thus, to write the title of the document in the terminal you +could use: +\begin{verbatim} + \AddToHookWithArguments{cmd/title/before} + {\typeout{Document title: #1}} +\end{verbatim} + +As with regular hooks, code added to a \hook{cmd} hook using +\cs{AddToHook} will not be able to access the command's arguments. This +means that, as with regular hooks, this change is completely backwards +compatible, so previous usages of \hook{cmd} hooks will work exactly as +they did before. + +\subsection{Providing copy and show functions for environments} + +To copy a command definition we introduced \cs{NewCommandCopy} in +2022. This even allows you to copy commands that consist of several internal +components, such as robust commands or those with a complex signature. +To do the same with environments, e.g., to define the environment +\env{myitemize} to be equivalent to \env{itemize}, you can now write +\begin{verbatim} + \NewEnvironmentCopy{myitemize}{itemize} +\end{verbatim} +There are also \cs{Renew...}\ and \cs{Declare...}, which may be useful +depending on the circumstances. + +In addition, we offer a \cs{ShowEnvironment} command, which displays the +\cs{begin} and \cs{end} code of the environment passed as an +argument. E.g., \verb=\ShowEnvironment{center}= results in the +following output: +\begin{verbatim} + >> \begin{center}=environment: + >> ->>\trivlist \centering \item \relax . + <<recently read>> } + l. ...\ShowEnvironment{center} + >> \end{center}: + >> ->>\endtrivlist . + <<recently read>> } + l. ...\ShowEnvironment{center} +\end{verbatim} +% +\githubissue{963} + +\subsection{\cs{IfFileAtLeastTF}} + +The 2020-10-01 \LaTeX{} release introduced the CamelCase tests +\cs{IfClassAtLeastTF} and \cs{IfPackageAtLeastTF} for checking class +and package dates. We have now added \cs{IfFileAtLeastTF} to allow the +same to happen for generic files which contain a \cs{ProvidesFile} +line. +% +\githubissue{1015} + +\subsection{\cs{DeclareLowercaseMapping}, \cs{DeclareTitlecaseMapping} + and \cs{DeclareUppercaseMapping}\texorpdfstring{\raggedright}{}} + +The move from a case-changing approach using \cs{lccode} and \cs{uccode} data +to one where information is stored by a kernel-managed structure left a gap in +the ability of the user to \emph{tune} the case changing outcomes. This has now +been addressed by the addition of three commands +\begin{itemize}\tubcommand{\setlength{\parskip}{0pt}}% + \item \cs{DeclareLowercaseMapping} + \item \cs{DeclareTitlecaseMapping} + \item \cs{DeclareUppercaseMapping} +\end{itemize} +which can be used to customise the outcome for codepoints. This can be applied +generally or to a specific locale (see also the next section). A small number +of pre-defined customisations have been set up in the kernel where the outcomes +for \pdfTeX{} should be different for those from Unicode engines. For +example +\begin{verbatim} + \DeclareUppercaseMapping{"01F0}{\v{J}} +\end{verbatim} +allows \v{J} to be produced in 8-bit engines: without this customisation, +an error would occur as there is no pre-composed \v{J} in Unicode. More detail +is given in \texttt{usrguide}. +% +\githubissue{1033} + +\subsection{\cs{BCPdata}} + +Improvements in the Unicode handling for case changing have highlighted that +the kernel has not to-date been locale-aware. The packages \pkg{babel} and +\pkg{polyglossia} provide comprehensive locale support, but did not have +an agreed unified interface to pass that information back to other code. +Following discussion with the maintainers of those two bundles, the kernel +now defines \cs{BCPdata} as a stub (so it is always defined), and \pkg{babel} +and \pkg{polyglossia} will redefine it to provide the locale data. An agreed +set of keywords mean that \cs{BCPdata} can be queried in a structured way +by both the kernel and any other \enquote{consumer} packages. +% +\githubissue{1035} + +\subsection{Improve \cs{samepage}} + +The \cs{samepage} declaration sets various parameters to +\texttt{10000} to prevent undesired page breaks. The +\cs{predisplaypenalty} parameter has already by default a value of +\texttt{10000}, and to save space in the past it was therefore not +explicitly set. However, there are a few classes that change the +parameter and as result the user might experience a page break in +front of a display formula within the scope of \cs{samepage} when +using such classes. This has now been corrected and +\cs{predisplaypenalty} is also explicitly set to \texttt{10000}. +% +\githubissue{1022} + +\subsection{Groups in \cs{MakeUppercase}} +% +Prior to 2022, \cs{MakeUppercase} and \cs{MakeLowercase} used a brace +group around their argument so providing a scope for any declarations +within the argument. This grouping has been restored (also +for \cs{MakeTitlecase}), although the underlying L3 text case commands do +not use grouping. +% +\githubissue{1021} + +\subsection{Extension of the \cs{label} command} + +Previously, in standard \LaTeX{}, the \cs{label} command wrote a \cs{newlabel} declaration into +the \texttt{.aux} file and stored two values in +the second argument of this \cs{newlabel} command: +\cs{@currentlabel}, which normally contains the state of the current +counter and \cs{thepage} for the current page number. + +The packages \pkg{hyperref} and +\pkg{nameref} then patched the \cs{label} command to store five values instead. +In addition to the above they saved \cs{@currentlabelname}, which normally contains the +current title text and can be retrieved with \cs{nameref}, and +\cs{@currentHref}, which is the name of the destination needed to create an +active link. The fifth argument was only used if external +references were loaded with the \pkg{xr-hyper} package. + +Starting with this release, the number of values stored in \cs{newlabel} has been unified. +\cs{label} now writes a +\cs{newlabel} command that always contains five values in the second argument (each in a brace group): +\cs{@currentlabel}, \cs{thepage}, \cs{@currentlabelname}, +\cs{@currentHref}, and \cs{@kernel@reserved@label@data} (which is reserved for the kernel). + +Additionally, a hook with the name \texttt{label} has been +added. It takes one argument: the label string. +Code added to the hook can refer to this argument with~\verb+#1+. +The hook is executed directly before the \cs{label} command writes to the \texttt{.aux} file +but \emph{after} the \cs{@bsphack} command has done its spacing magic, and it is located \emph{inside} a group; thus, its code only affects the write operation. + +\section{Code improvements} + +\subsection{Performance in checking file existence} + +The addition of hooks, etc., to file operations had a side effect of making +multiple checks that the file existed. In larger documents using +many files, these file system operations caused non-trivial performance +impact. We now cache the existence of files, such that these repeated filesystem +calls are avoided. + +\subsection{\pkg{doc}: Handle \texttt{\textbackslash\textvisiblespace} correctly in the index} + +Due to some problems in the code it wasn't possible to prevent +\verb*=\ = from showing up in the index\Dash \verb=\DoNotIndex{\ }=, etc.\ had no effect. This has now been corrected. +% +\githubissue{943} + + +\subsection{\pkg{doc}: Support the \pkg{upquote} package} + +The default quote and backquote characters in typewriter fonts are +typographical quotes, e.g., the input +\begin{verbatim} + \verb/`prog 'my input'`/ +\end{verbatim} + is rendered as \verb/`prog 'my input'`/ and not as +% +\begingroup % code to mimic upquote.sty +\catcode`'=\active +\catcode``=\active +\makeatletter +\g@addto@macro\@noligs + {\let'\textquotesingle + \let`\textasciigrave + \ifx\encodingdefault\upquote@OTone + \ifx\ttdefault\upquote@cmtt + \def'{\char13 }% + \def`{\char18 }% + \fi\fi} +\endgroup +% +\verb/`prog 'my input'`/ as preferred by many programmers. + +This can be adjusted, for example, with the \pkg{upquote} package, +which results in the second output. However, for historical reasons +\pkg{doc} had its own definition of \cs{verb} and \env{verbatim} and +as a consequence the two packages did not cooperate. This has now +been fixed and loading \pkg{upquote} together with \pkg{doc} has the +desired effect. +% +\githubissue{953} + + +\subsection{Default definition for \cs{do}} + +The command \cs{do} with its nice public name is in reality an +internal command inherited from plain \TeX{} for list +processing. However, it only got a definition when +\verb=\begin{document}= was executed, with a result that a user +definition in the preamble was unconditionally overwritten at this +point. To properly alert the user that this command is not freely +available we now make a definition in the format, so that +\cs{newcommand} and friends produce a proper error message instead of +allowing a definition that doesn't last. +% +\githubissue{975} + + + + +\subsection{New key for \env{filecontents}} + +The \env{filecontents} environment warns on the terminal if a file +gets overwritten even if that is intentional, +e.g., when you write a temporary file over and over again. To make +the warning less noisy in this case we added a new \texttt{nowarn} key +that redirects the overwriting warning to the transcript file. We +think that some record of the action is still required to help with +debugging, thus it is not completely silenced. The warning that +nothing gets written, because the file already exists (and the +\texttt{force} key was not used), is not altered and still shows up on +the terminal. +% +\githubissue{958} + + +\subsection{A further hook for shipping out pages} + +Since October 2020 the shipout process offers a number of hooks to +adjust what is happening before, during, and after the +\cs{shipout}. For example, with the \hook{shipout/before} hook, packages +can reset code they have altered (e.g., \cs{catcode}s during +verbatim-like processing) and with \hook{shipout/background} and +\hook{shipout/foreground} material can be added to the pages. +Details are given in \cite{37:ltshipout-doc}. + +However, still +missing was a hook that allows a package writer to manipulate the +completed page (with foreground and background attached) just before +the actual shipout happens. +For this we now provide the additional hook \hook{shipout}. One +use case (sometimes needed in print production) is to mirror the +whole page via \cs{reflectbox} including all the extra data that may +have been added into the fore- or background. +% +\githubissue{920} + + + +\subsection{Displaying release information in the \texttt{.log}} + +\LaTeX{} displays its release information at the very beginning of the +\LaTeX{} run on the terminal, and also writes it to the transcript file +if that is already opened at this point. While this is normally true, +it is not the case if the \LaTeX{} run was started passing additional +\TeX{} code on the command line, e.g., +\begin{verbatim} +pdflatex '\PassOptionsToClass{11pt}{article} + \input{myarticle}' +\end{verbatim} +In this case the release information is displayed when +\cs{PassOptionsToClass} is processed but the transcript file is only +opened when the output file name is known, i.e., after \cs{input} has +been seen, and as a result the release information is only shown on +the terminal. + +To account for this scenario, we now repeat the release information +also at the very end of the transcript file where we can be sure that +it is open and ready to receive material. +% +\githubissue{944} + + + + + +\section{Bug fixes} + +\subsection{Incompatibility between \pkg{doc} and \pkg{unicode-math}} + +The \pkg{unicode-math} package alters the catcode of \verb=|= but does +not adjust its value for use in \pkg{doc}, with the result that +\enquote{or} modules, i.e., $\langle A | B \rangle$ are displayed in a +strange way. This is now fixed with some firstaid code that will +eventually be moved into \pkg{unicode-math}. +% +\githubissue{820} + + +\subsection{A fix for \cs{hspace}} + +The change to \cs{hspace}, done in 2020 to make it \pkg{calc}-aware, +had the unfortunate side effect that starting a paragraph with +\cs{hspace} would result in the execution of \cs{everypar} inside a +group (i.e., any local changes would immediately be revoked, breaking, +for example, \pkg{wrapfig} in that special situation). +% +This got fixed with the 2022-11 PL1 hotfix, so was already corrected in +the previous release, but is only now documented in the newsletter. +% +\githubissue{967} + +\subsection{Ensure that \cs{cs} is defined in \cls{ltxdoc}} + +The class \cls{ltxdoc} defined the command \cs{cs} to typeset a +command name with a backslash in front. This definition was moved to +the \pkg{doc} package itself. This meant that it was suddenly missing +when reverting to the old \pkg{doc} package implementation via the +class option \texttt{doc2}. This has now been corrected. +% +\githubissue{981} + + + +\subsection{Improve spacing at top of \env{minipages}} + +A list and several other document elements add some vertical space in +front of them. However this should not happen at the beginning of a +box (such as a \env{minipage}) and normally it doesn't, because +\TeX{} automatically drops such space at the start of a vertical +list. However, if there is some invisible material, such as a +\cs{color} command, a \pkg{hyperref} anchor, a \cs{write} or +other such items, then the list is no longer empty and \TeX{} no longer +drops the vertical space. + +With the new paragraph handling introduced in 2021 it is now finally +possible to detect and avoid this problem and apply appropriate +counter measures so that from now on the spacing will always be +correct. +% +\githubissue{989} + + +\subsection{A fix for \cs{NewCommandCopy} and \cs{ShowCommand}} + +When copying and showing definitions of (non-expandable) document commands +(a.k.a.\ commands defined by \cs{NewDocumentCommand} and friends) containing empty +or only \texttt{m}-type arguments, these commands were wrongly recognized as +expandable ones. +This is fixed in the present \LaTeX{} release. +% +\githubissue{1009} + +\subsection{Corrections for switching math version} +Some internal code improvements improve support for switching math version +when nested within an outer math expression. +This will improve \cs{boldsymbol} and \cs{bm} and similar commands. +% +\githubissue{1028} + +\subsection{Allow par as a filename} +\verb|\input{par}| or \verb|\includegraphics{par}| could give spurious +errors. This has been fixed by making an internal command \cs{long}. +% +\githubissue{942} + +\subsection{Correct setting of \cs{endlinechar} in \texttt{+v} arguments} +In the particular case of a document command with a \texttt{+v}-type +argument used inside \cs{ExplSyntaxOn}\texttt{/Off}, newlines would be +misinterpreted as spaces because the value of \cs{endlinechar} was +set too late. This has been fixed, and now newlines are correctly +translated to ``\verb|the character ^^M|''. +% +\githubissue{876} + +\subsection{Correct handling of hooks with only `next' code} +When \cs{AddToHookNext} was used on a not-yet-declared hook, that hook +would be incorrectly identified as empty by \cs{ShowHook}. Also, if +that hook was later declared, that `next' code would not be executed. +This has been fixed by correctly initializing the hook structure when +\cs{AddToHookNext} is used. +% +\githubissue{1052} + +\subsection{Ignoring space after \texttt{\$\$}} +Space is normally ignored after a closing \texttt{\$\$}, +but internal \LaTeX{} font handling code could interfere if +\cs{eqno} was used. \cs{eqno} and \cs{leqno} have been redefined +to add \cs{ignorespaces} after the math group. +% +\githubissue{1059} + +\section{Documentation improvements} + +\subsection{Updates to the guides} + +When \LaTeXe{} was released, the team provided documentation for both document +authors and package/class developers in the two files \texttt{usrguide} and +\texttt{clsguide}. Over time, the team have augmented these documents as new +methods have been added to the kernel. However, they retained their structure +as assuming familiarity with \LaTeX{}~2.09. This meant that for new users, +there was material which is no longer relevant, and less clarity than desirable +regarding the approaches that are recommended today. + +The two files have now been (partially) re-written, with the versions available +previously now frozen as \texttt{usrguide-historic} and \texttt{clsguide-historic}. +More material has been carried forward in the class/package guide than in the +user guide, but both are worth a re-read by experienced \LaTeX{} users. + + + +\subsection{Displaying the exact release dates for \LaTeX{}} + +In some situations it is necessary to find out the exact release dates +for older versions of the \LaTeX{} format, for example, when you need +to use different code in a package depending on the availability of a +certain feature and you therefore want to use +\cs{IfFormatAtLeastTF}\texttt\{\meta{date}\texttt\} or the +rather horrible construction \verb/\@ifl@t@r\fmtversion{/\meta{date}\texttt\}, +if you +want to cater for formats that are older than 2020. + +Or you know that your package is definitely not going to work with a +format before a certain \meta{date}, in which case you could use +\verb/\NeedsTeXFormat{LaTeX2e}[/\meta{date}\texttt] to ensure that +users are alerted if their format is too old. + +The big problem is knowing the exact \meta{date} to put into such +commands; in the past, that was not that easy to find. You could have +looked in the file \file{changes.txt}, but that is hidden somewhere +in your installation and if you try +\verb/texdoc -l changes.txt/ you get more than thirty results and the %* +right file is by no means the first. + +Yukai Chou (\textsf{@muzimuzhi}) kindly provided a patch for this, so that we now have +the exact dates for each \LaTeX{} format listed in an easy to remember +place: in \file{ltnews.pdf} and that file conveniently also contains all major +features and changes to \LaTeX{} over the years\Dash one of which is +most likely the reason you need the \meta{date} in the first +place. + +The date is now given in parentheses in the newsletter title, thus this +newsletter tells you that on +% +\makeatletter +\mbox{\expandafter\@gobblenonyear\@year\@nil + -\@julianmonthtonum\@month-\two@digits\@day} +\makeatother +% +the command +\cs{NewEnvironmentCopy}, a new \texttt{shipout} hook, etc.\ was made +available. And looking into \file{ltnews.pdf} you can now easily find +out that the \LaTeX3 programming layer was added on 2020-02-02 +(because the date was so nice) and not on the first of the month. +% +\githubissue{982} + +\subsection{Fresh from the press:\ \enquote{The \LaTeX{} Companion, third~edition} is now in print} + +The third edition of \emph{The \LaTeX{} Companion} is now +available. This is the result of five years of careful work and we hope +that it will provide our readers with all the information they need to +successfully navigate the \LaTeX{} ecosystem and efficiently produce +beautiful documents. + +Since the publication of the last edition (2004), a lot has happened in +the \LaTeX{} world and thus a complete rewrite was necessary. All +chapters have been thoroughly revised, and in many cases significantly +extended, to describe new important functionality and features. More +than 5,000 add-on packages have been analyzed in detail, out of which +roughly 10\% have been chosen for inclusion in \emph{The \LaTeX{} +Companion}. All important aspects of these packages are described to +provide the user once again with a satisfying one-stop–shop experience +for the decade to come. + +To cover what we thought worth describing today, the book nearly +doubled in size. The print edition is therefore produced as a +two-volume set and sold as a bundle. Both volumes come as hardcover +with ribbons to easily mark pages in the book. + +To give you an idea of what is covered in the third edition you can +find some excerpts at +\begin{quote} +\url{https://www.latex-project.org/news/2023/03/17/TLC3} +\end{quote} + +The edition is also available as an eBook (Parts~I and~II combined) +consisting of PDF and ePub format, without DRM\@. Finally, the publisher +offers the combination of the printed books and the digital versions at +a very attractive price not available anywhere else. + +%% bb -- add reference to TUGboat review here + + +%\section{Changes to packages in the \pkg{amsmath} category} + +%\section{Changes to packages in the \pkg{graphics} category} + +\section{Changes to packages in the \pkg{tools} category} + + +\subsection{\pkg{multicol}: Better support for CJK languages} + +The default minimum depth of each column in a \env{multicols} +corresponds to the depth of a \enquote{p} in the current font. This +helps to get some uniformity if rules are used between the columns and +makes sense for Latin-based languages. Until now it was hard-wired, +but for CJK (Chinese/Japanese/Korean) languages it is better to use a zero depth, because there +all characters have the same height and depth. And even with +Latin-based languages one might want to use the depth of a \cs{strut} +or that of a parenthesis. So we now offer a way to adjust this while +maintaining backward compatibility: redefine +\cs{multicolmindepthstring} to hold whatever you want to get measured +for its depth (the width is not relevant). +% +\githubissue{698} + + +\subsection{\pkg{multicol}: Fix handling of nested environments} + +If \env{multicols} environments have been nested into each other (the +inner one boxed) it could fail if the boxed environment appeared near a +page break. The problem was that the output routine was called while +the \cs{hsize} was still altered to fit the column width of the inner +\env{multicols} --- thereby messing up the placement of columns of the +page. This has now been fixed. +% +\githubissue{1002} + + + +%\medskip + +\begin{thebibliography}{9} + +%\fontsize{9.3}{11.3}\selectfont + +\bibitem{37:ltshipout-doc} Frank Mittelbach, \LaTeX{}~Project~Team: + \emph{The~\texttt{\upshape ltshipout} documentation}.\\ + Run \texttt{texdoc} \texttt{ltshipout-doc} to view. + +\bibitem{37:lthooks-doc} Frank Mittelbach, Phelype Oleinik, \LaTeX{}~Project~Team: + \emph{\LaTeX's hook management}.\\ + Run \texttt{texdoc} \texttt{lthooks-doc} to view. + +%\bibitem{37:blueprint} Frank Mittelbach and Chris Rowley: +% \emph{\LaTeX{} Tagged PDF \Dash A blueprint for a large project}.\\ +% \url{https://latex-project.org/publications/indexbyyear/2020/} + +%\bibitem{37:source2e} +% \emph{\LaTeX{} documentation on the \LaTeX{} Project Website}.\\ +% \url{https://latex-project.org/help/documentation/} + +%\bibitem{37:Lamport} +%Leslie Lamport. +%\newblock {\LaTeX}: {A} Document Preparation System: User's Guide and Reference +% Manual. +%\newblock \mbox{Addison}-Wesley, Reading, MA, USA, 2nd edition, 1994. +%\newblock ISBN 0-201-52983-1. +%\newblock Reprinted with corrections in 1996. +% +%\bibitem{37:ltnews32} \LaTeX{} Project Team: +% \emph{\LaTeXe{} news 32}.\\ +% \url{https://latex-project.org/news/latex2e-news/ltnews32.pdf} +% +%\bibitem{37:ltnews34} \LaTeX{} Project Team: +% \emph{\LaTeXe{} news 34}.\\ +% \url{https://latex-project.org/news/latex2e-news/ltnews34.pdf} +% +%\bibitem{37:ltnews35} \LaTeX{} Project Team: +% \emph{\LaTeXe{} news 35}.\\ +% \url{https://latex-project.org/news/latex2e-news/ltnews35.pdf} +% +%\bibitem{37:fntguide} \LaTeX{} Project Team: +% \emph{\LaTeXe{} font selection}.\\ +% \url{https://latex-project.org/help/documentation/} +% +%\bibitem{37:ltfilehook-doc} Frank Mittelbach, Phelype Oleinik, \LaTeX{}~Project~Team: +% \emph{The \texttt{\upshape ltfilehook} documentation}.\\ +% Run \texttt{texdoc} \texttt{ltfilehook-doc} to view. +\end{thebibliography} + + + +\end{document} diff --git a/macros/latex/base/ltoutenc.dtx b/macros/latex/base/ltoutenc.dtx index 4dac4e1548..1d257805a4 100644 --- a/macros/latex/base/ltoutenc.dtx +++ b/macros/latex/base/ltoutenc.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltoutenc.ins b/macros/latex/base/ltoutenc.ins index 8ff0f02608..2f0c39517f 100644 --- a/macros/latex/base/ltoutenc.ins +++ b/macros/latex/base/ltoutenc.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/ltoutput.dtx b/macros/latex/base/ltoutput.dtx index 1cbc7ab0b1..18388b1cc6 100644 --- a/macros/latex/base/ltoutput.dtx +++ b/macros/latex/base/ltoutput.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -37,7 +37,7 @@ %<*driver> % \fi \ProvidesFile{ltoutput.dtx} - [2022/08/20 v1.4j LaTeX Kernel (Output Routine)] + [2023/05/26 v1.4j LaTeX Kernel (Output Routine)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltoutput.dtx} @@ -3005,9 +3005,6 @@ % % There is also an |\addpenalty\interlinepenalty| above. % -% Since in 2e |\samepage| is no longer supported, these could be -% removed. -% % Although it is best to use |\addvspace| in case two h floats come % together, this makes other spacing more difficult to adjust; whereas % if a user specifies two h floats together then they can more easily @@ -3227,9 +3224,6 @@ % % There is also an |\addpenalty\interlinepenalty| above. % -% Since in 2e |\samepage| is no longer supported, these could be -% removed. -% % Although it is best to use |\addvspace| in case two h floats come % together, this makes other spacing more difficult to adjust; whereas % if a user specifies two h floats together then they can more easily diff --git a/macros/latex/base/ltpage.dtx b/macros/latex/base/ltpage.dtx index 1d514fc7c7..1a6586d067 100644 --- a/macros/latex/base/ltpage.dtx +++ b/macros/latex/base/ltpage.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltpageno.dtx b/macros/latex/base/ltpageno.dtx index 8142639633..6c02d0fa7f 100644 --- a/macros/latex/base/ltpageno.dtx +++ b/macros/latex/base/ltpageno.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltpar.dtx b/macros/latex/base/ltpar.dtx index 50ff57183c..31d863610b 100644 --- a/macros/latex/base/ltpar.dtx +++ b/macros/latex/base/ltpar.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltpara-code.pdf b/macros/latex/base/ltpara-code.pdf Binary files differindex 2ad8d90eab..4ca5193aa2 100644 --- a/macros/latex/base/ltpara-code.pdf +++ b/macros/latex/base/ltpara-code.pdf diff --git a/macros/latex/base/ltpara-doc.pdf b/macros/latex/base/ltpara-doc.pdf Binary files differindex 31ac4d0714..1f47fc92db 100644 --- a/macros/latex/base/ltpara-doc.pdf +++ b/macros/latex/base/ltpara-doc.pdf diff --git a/macros/latex/base/ltpara.dtx b/macros/latex/base/ltpara.dtx index 9296f2b2cd..9c1a95ee61 100644 --- a/macros/latex/base/ltpara.dtx +++ b/macros/latex/base/ltpara.dtx @@ -1,7 +1,8 @@ % \iffalse meta-comment % -%% File: ltpara.dtx (C) Copyright 2020-2021 -% Frank Mittelbach, LaTeX Team +%% File: ltpara.dtx +%% Copyright (C) 2020-2023 +%% Frank Mittelbach, The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -14,8 +15,8 @@ %%% From File: ltpara.dtx % % \begin{macrocode} -\def\ltparaversion{v1.0k} -\def\ltparadate{2022/05/13} +\def\ltparaversion{v1.0l} +\def\ltparadate{2023/01/30} % \end{macrocode} %<*driver> \documentclass{l3doc} @@ -729,6 +730,8 @@ % for error recovery and so altering \cs{tex_everypar:D} all the % time should be a tiny bit faster. % \begin{macrocode} +%<latexrelease>\IncludeInRelease{2023/06/01} +%<latexrelease> {\g_@@_standard_everypar_tl}{minipage~ fix} \tl_new:N \g_@@_standard_everypar_tl % \end{macrocode} % Here is now its definition: @@ -769,7 +772,28 @@ % \begin{macrocode} \group_begin: \tex_everypar:D {} - \skip_zero:N \tex_parskip:D +% \end{macrocode} +% There has been a long-standing problem with \LaTeX's minipages in +% that invisible material at the beginning of a minipage (such as a +% \cs{color} setting) would result in \cs{parskip} being added in +% front of the first paragraph---something that is not done by +% \TeX{} if a vertical list is completely empty. As this is +% happening on a very low-level in the engine it wasn't really +% possible to find out if this \cs{parskip} was added or if a space +% we see in front of the current point is legitimate. However, with +% the new paragraph handling we are in a better position: while we +% still don't know if there is such a space or not, we do know +% if we have just created an empty paragraph. Thus, if we now set +% \cs{parskip} to \texttt{-}\cs{parskip} the two will cancel each other +% if present and if the first was ignored because the vertical list +% was empty, then the second will be ignored too because it is +% still empty. Of course, we don't want to cancel always but only +% at the start of a minipage and that is signaled with the +% \texttt{@minipage} switch. +% \changes{v1.0l}{2023/01/30}{Backout \cs{parskip} at top of minipage (gh/989)} +% \begin{macrocode} + \skip_set:Nn \tex_parskip:D + { \if@minipage -\tex_parskip:D \else: \c_zero_skip \fi: } \tex_noindent:D \group_end: % \end{macrocode} @@ -800,6 +824,43 @@ \@@_handle_indent: % \the \everypar % <--- done differently below } +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2021/06/01} +%<latexrelease> {\g_@@_standard_everypar_tl}{minipage~ fix} +%<latexrelease> +%<latexrelease>\tl_gset:Nn \g_@@_standard_everypar_tl { +%<latexrelease> \box_gset_to_last:N \g_para_indent_box +%<latexrelease> \group_begin: +%<latexrelease> \tex_par:D +%<latexrelease> \group_end: +%<latexrelease> \tex_everypar:D { \msg_error:nnnn { hooks }{ para-mode }{before}{vertical} } +%<latexrelease> \@kernel@before@para@before +%<latexrelease> \hook_use:n {para/before} +%<latexrelease> \group_begin: +%<latexrelease> \tex_everypar:D {} +%<latexrelease> \skip_zero:N \tex_parskip:D +%<latexrelease> \tex_noindent:D +%<latexrelease> \group_end: +%<latexrelease> \tex_everypar:D{\g_@@_standard_everypar_tl} +%<latexrelease> \@kernel@before@para@begin +%<latexrelease> \hook_use:n {para/begin} +%<latexrelease> \if_mode_horizontal: \else: +%<latexrelease> \msg_error:nnnn { hooks }{ para-mode }{begin}{vertical} \fi: +%<latexrelease> \@@_handle_indent: +%<latexrelease>} +% \end{macrocode} +% We also have to add the \cs{everypar} toks register at the +% end. In case of rollback this is already allocated and we have to +% find out the correct number (hope this is correctly done) +% \begin{macrocode} +%<latexrelease>\cs_set:Npn \@@_tmp:w #1#2#3#4#5 { } +%<latexrelease>\tl_gput_right:Nx \g_@@_standard_everypar_tl { +%<latexrelease> \exp_not:N \the +%<latexrelease> \exp_not:N \toks +%<latexrelease> \exp_after:wN \@@_tmp:w \token_to_meaning:N \everypar +%<latexrelease> \c_space_tl +%<latexrelease>} +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % diff --git a/macros/latex/base/ltpictur.dtx b/macros/latex/base/ltpictur.dtx index 453ec6149e..926fd5c692 100644 --- a/macros/latex/base/ltpictur.dtx +++ b/macros/latex/base/ltpictur.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltplain.dtx b/macros/latex/base/ltplain.dtx index ee1cf0a161..89e5017300 100644 --- a/macros/latex/base/ltplain.dtx +++ b/macros/latex/base/ltplain.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltplain.dtx} - [2022/01/25 v2.3h LaTeX Kernel (Plain TeX)] + [2023/04/15 v2.3i LaTeX Kernel (Plain TeX)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltplain.dtx} @@ -660,6 +660,10 @@ \def\extrafloats#1{% \ifnum#1>\z@ \count@\numexpr\float@count-1\relax +% \end{macrocode} +% \changes{v2.3i}{2023/04/15}{Protect box 255 in lualatex gh/1041} +% \begin{macrocode} + \ifnum\count@<266 \ch@ck0\m@ne\insert\fi \ch@ck0\count@\count \ch@ck1\count@\dimen \ch@ck2\count@\skip @@ -668,8 +672,12 @@ \global\expandafter\e@alloc@chardef \csname bx@\the\float@count\endcsname\float@count \@cons\@freelist{\csname bx@\the\float@count\endcsname}% -\expandafter -\extrafloats\expandafter{\numexpr#1-1\relax}% +% \end{macrocode} +% \changes{v2.3i}{2023/04/15}{unwind numexpr and ifnum nesting} +% \begin{macrocode} +\expandafter\extrafloats\expandafter{\the\numexpr#1-1\expandafter}% +% \end{macrocode} +% \begin{macrocode} \fi}% % \end{macrocode} % @@ -880,7 +888,6 @@ % but the code is commented out if no special value needs to be set. % INITEX makes all parameters zero except where noted. % -% \begin{oldcomments} % \begin{macrocode} \pretolerance=100 \tolerance=200 % INITEX sets this to 10000 @@ -897,10 +904,14 @@ \brokenpenalty=100 \predisplaypenalty=10000 % \end{macrocode} +% +% \begin{macrocode} % \postdisplaypenalty=0 % \interlinepenalty=0 % \floatingpenalty=0, set during \insert % \outputpenalty=0, set before TeX enters \output +% \end{macrocode} +% % \begin{macrocode} \doublehyphendemerits=10000 \finalhyphendemerits=5000 @@ -971,6 +982,8 @@ % \begin{macrocode} \uchyph=1 % \end{macrocode} +% +% \begin{macrocode} % \lefthyphenmin=2 \righthyphenmin=3 set below % \globaldefs=0 % \maxdeadcycles=25 % INITEX does this @@ -978,21 +991,29 @@ % \fam=0 % \mag=1000 % INITEX does this % \escapechar=`\\ % INITEX does this +% \end{macrocode} +% % \begin{macrocode} \defaulthyphenchar=`\- \defaultskewchar=-1 % \end{macrocode} +% +% \begin{macrocode} % \endlinechar=`\^^M % INITEX does this % \newlinechar=-1 \LaTeX\ sets this in ltdefns.dtx. +% \end{macrocode} +% % \begin{macrocode} \delimiterfactor=901 % \end{macrocode} +% +% \begin{macrocode} % \time=now % TeX does this at beginning of job % \day=now % TeX does this at beginning of job % \month=now % TeX does this at beginning of job % \year=now % TeX does this at beginning of job +% \end{macrocode} % -% \end{oldcomments} % In \LaTeX{} we don't want box information in the transcript % unless we do a full tracing. % \changes{v1.0g}{1994/04/28}{Turn off overfull box tracing in log} @@ -1012,26 +1033,36 @@ \boxmaxdepth=\maxdimen % \end{macrocode} % -% \begin{oldcomments} +% \begin{macrocode} % \lineskiplimit=0pt, changed by \normalbaselines +% \end{macrocode} +% % \begin{macrocode} \delimitershortfall=5pt \nulldelimiterspace=1.2pt \scriptspace=0.5pt % \end{macrocode} +% +% \begin{macrocode} % \mathsurround=0pt % \predisplaysize=0pt, set before TeX enters $$ % \displaywidth=0pt, set before TeX enters $$ % \displayindent=0pt, set before TeX enters $$ +% \end{macrocode} +% % \begin{macrocode} \parindent=20pt % \end{macrocode} +% +% \begin{macrocode} % \hangindent=0pt, zeroed by TeX after each paragraph % \hoffset=0pt % \voffset=0pt % % \baselineskip=0pt, changed by \normalbaselines % \lineskip=0pt, changed by \normalbaselines +% \end{macrocode} +% % \begin{macrocode} \parskip=0pt plus 1pt \abovedisplayskip=12pt plus 3pt minus 9pt @@ -1039,19 +1070,26 @@ \belowdisplayskip=12pt plus 3pt minus 9pt \belowdisplayshortskip=7pt plus 3pt minus 4pt % \end{macrocode} +% +% \begin{macrocode} % \leftskip=0pt % \rightskip=0pt +% \end{macrocode} +% % \begin{macrocode} \topskip=10pt \splittopskip=10pt % \end{macrocode} +% +% \begin{macrocode} % \tabskip=0pt % \spaceskip=0pt % \xspaceskip=0pt +% \end{macrocode} +% % \begin{macrocode} \parfillskip=0pt plus 1fil % \end{macrocode} -% \end{oldcomments} % % % \begin{macro}{\normalbaselineskip} @@ -1215,7 +1253,7 @@ \gdef\obeylines{\catcode`\^^M\active% \let^^M\obeyedline% % \end{macrocode} -% +% % The next line ending the definition is rather curious and it took % me awhile to understand why rollback fails. The problem is the % following: if \texttt{latexrelease} is used, then blocks of diff --git a/macros/latex/base/ltsect.dtx b/macros/latex/base/ltsect.dtx index 71ab1ee89d..5a03fd4977 100644 --- a/macros/latex/base/ltsect.dtx +++ b/macros/latex/base/ltsect.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltshipout-code.pdf b/macros/latex/base/ltshipout-code.pdf Binary files differindex efc6444c48..6209463f89 100644 --- a/macros/latex/base/ltshipout-code.pdf +++ b/macros/latex/base/ltshipout-code.pdf diff --git a/macros/latex/base/ltshipout-doc.pdf b/macros/latex/base/ltshipout-doc.pdf Binary files differindex a2d210dda0..86bd577603 100644 --- a/macros/latex/base/ltshipout-doc.pdf +++ b/macros/latex/base/ltshipout-doc.pdf diff --git a/macros/latex/base/ltshipout.dtx b/macros/latex/base/ltshipout.dtx index ae29c1acad..b19814a6fd 100644 --- a/macros/latex/base/ltshipout.dtx +++ b/macros/latex/base/ltshipout.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment %% -%% Copyright (C) 2020-2022 -%% Frank Mittelbach, LaTeX Team +%% Copyright (C) 2020-2023 +%% Frank Mittelbach, The LaTeX Project %% % % This file is part of the LaTeX base system. @@ -32,8 +32,8 @@ %%% From File: ltshipout.dtx % % \begin{macrocode} -\providecommand\ltshipoutversion{v1.0m} -\providecommand\ltshipoutdate{2022/08/26} +\providecommand\ltshipoutversion{v1.0n} +\providecommand\ltshipoutdate{2022/11/08} % \end{macrocode} % %<*driver> @@ -75,7 +75,7 @@ % \providecommand\pkg[1]{\texttt{#1}} % % -% \title{The \texttt{ltshipout} package\thanks{This package has version +% \title{The \texttt{ltshipout} documentation\thanks{This file has version % \ltshipoutversion\ dated \ltshipoutdate, \copyright\ \LaTeX\ % Project.}} % @@ -241,6 +241,18 @@ % 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}] +% This hook is executed after foreground and/or background +% material has been added, i.e., just in front of the actual +% shipout operation. Its purpose is to allow manipulation of the +% finalized box (stored in \cs{ShipoutBox}) with the extra +% material also in place (which is not yet the case in +% \hook{shipout/before}). +% +% It cannot be used to cancel the shipout operation via +% \cs{DiscardShipoutBox} (that has +% to happen in \hook{shipout/before}, if desired! +% % % \item[\hook{shipout/firstpage}] % @@ -296,7 +308,7 @@ % actual shipout. It is even run if there was a % \cs{DiscardShipoutBox} request in the document. % -% The other hooks (except \hook{shipout/after}) are added inside +% The other hooks (except \hook{shipout} and \hook{shipout/after}) are added inside % hboxes to the box being shipped out in the following order: % \begin{center} % \begin{tabular}{ll} @@ -307,9 +319,13 @@ % \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 +% If any of the hooks has no code then the corresponding box is % added at that point. % +% Once the (page) box has got the above extra content it can +% again be manipulated using the \hook{shipout} hook and then +% is shipped out for real. +% % Once the (page) box has been shipped out the \hook{shipout/after} % hook is called (while you are still inside the output routine). It % is not called if the shipout box was discarded. @@ -381,13 +397,16 @@ % % \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.} +% that contains it --- not done (yet)} +% +% \cs{DiscardShipoutBox} cannot be used in any of the \hook{shipout/...} +% hooks other than \hook{shipout/before}. % \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}, +% add code to the hooks \hook{shipout/before}, \hook{shipout}, % \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 @@ -401,7 +420,9 @@ % % \begin{variable}{pre_shipout_filter} % Under Lua\TeX{} the \texttt{pre\_shipout\_filter} Lua callback is -% provided which gets called immediately before the shipout primitive gets invoked. +% provided which gets called directly after the +% \hook{shipout} hook, immediately before the shipout +% primitive gets invoked. % The signature is % \begin{verbatim} % function(<node> head) @@ -1014,15 +1035,20 @@ \_@@_add_foreground_box:n { \UseHook{shipout/lastpage} \@kernel@after@shipout@lastpage } - \bool_gset_true:N \g_@@_lastpage_handled_bool % \end{macrocode} % We record that we have handled the \hook{shipout/lastpage} hook % but only if we really did. % \changes{v1.0m}{2022/05/08}{Handle case where shipout/lastpage is % run too early (gh/813)} % \begin{macrocode} + \bool_gset_true:N \g_@@_lastpage_handled_bool } } +% \end{macrocode} +% +% \changes{v1.0n}{2022/11/08}{Add shipout hook (gh/920)} +% \begin{macrocode} + \hook_use:n {shipout} \@@_finalize_box: % \end{macrocode} % Finally we run the actual \TeX{} primitive for shipout. As that will @@ -1116,13 +1142,14 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{shipout/before,shipout/after, +% \begin{macro}{shipout/before,shipout,shipout/after, % shipout/foreground,shipout/background, -% shipout/firstpage, -% shipout/lastpage} +% shipout/firstpage,shipout/lastpage} % Declaring all hooks for the shipout code. +% \changes{v1.0n}{2022/11/08}{Add shipout hook (gh/920)} % \begin{macrocode} \hook_new:n{shipout/before} +\hook_new:n{shipout} \hook_new:n{shipout/after} \hook_new:n{shipout/foreground} \hook_new:n{shipout/background} diff --git a/macros/latex/base/ltspace.dtx b/macros/latex/base/ltspace.dtx index 30bda278fb..a77314b1bd 100644 --- a/macros/latex/base/ltspace.dtx +++ b/macros/latex/base/ltspace.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -32,7 +32,7 @@ %<*driver> % \fi \ProvidesFile{ltspace.dtx} - [2022/11/28 v1.3o LaTeX Kernel (spacing)] + [2023/05/26 v1.3p LaTeX Kernel (spacing)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltspace.dtx} @@ -94,6 +94,7 @@ % inhibits page breaking most places by setting the % following penalties to 10000:\\ % |\interlinepenalty|\\ +% |\predisplaypenalty|\\ % |\postdisplaypenalty|\\ % |\interdisplaylinepenalty|\\ % |\@beginparpenalty|\\ @@ -308,8 +309,10 @@ % \end{macro} % % \begin{macro}{\samepage} +% \changes{v1.3p}{2023/03/22}{Add \cs{predisplaypenalty} setting (gh/1022)} % \begin{macrocode} \DeclareRobustCommand\samepage{\interlinepenalty\@M + \predisplaypenalty\@M \postdisplaypenalty\@M \interdisplaylinepenalty\@M \@beginparpenalty\@M diff --git a/macros/latex/base/lttab.dtx b/macros/latex/base/lttab.dtx index e32153f31c..e76325d82b 100644 --- a/macros/latex/base/lttab.dtx +++ b/macros/latex/base/lttab.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/lttextcomp.dtx b/macros/latex/base/lttextcomp.dtx index 8f5ec0d200..3602e0a6b0 100644 --- a/macros/latex/base/lttextcomp.dtx +++ b/macros/latex/base/lttextcomp.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2019-2022 +% Copyright (C) 2019-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltthm.dtx b/macros/latex/base/ltthm.dtx index d0d04d9669..b321c7ac2b 100644 --- a/macros/latex/base/ltthm.dtx +++ b/macros/latex/base/ltthm.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltvers.dtx b/macros/latex/base/ltvers.dtx index 24308589f1..de3c022755 100644 --- a/macros/latex/base/ltvers.dtx +++ b/macros/latex/base/ltvers.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltvers.dtx} - [2022/02/28 v1.1i LaTeX Kernel (Version Info)] + [2022/11/06 v1.1j LaTeX Kernel (Version Info)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltvers.dtx} @@ -112,10 +112,10 @@ %</2ekernel> %<latexrelease>\edef\latexreleaseversion %<*2ekernel|latexrelease> - {2022-11-01} + {2023-06-01} %</2ekernel|latexrelease> %<*2ekernel> -\def\patch@level{1} +\def\patch@level{0} % \end{macrocode} % % \begin{macro}{\development@branch@name} @@ -178,20 +178,33 @@ % by a loader (\texttt{.ini} file)} % \changes{v1.0v}{2015/08/23}{Allow negative patchlevel for pre-release} % \changes{v1.1e}{2020/01/31}{Allow for upcoming format as pre-release 0} +% \changes{v1.1j}{2022/11/06}{Repeat release info at the end (gh/944)} +% +% We store release info in the toks \cs{LaTeXReleaseInfo} to be +% used in \cs{everyjob} but also when \verb=\end{document}= is +% executed. +% Instead of using \cs{typeout} we use \cs{show@release@info} so +% that we can write to the log only by changing that to \cs{wlog}. +% \begin{macrocode} +\newtoks\LaTeXReleaseInfo +\everyjob\expandafter{\the\everyjob\the\LaTeXReleaseInfo} +\let\show@release@info\typeout +% \end{macrocode} +% % \begin{macrocode} \ifnum0\ifnum\patch@level=0 \ifx\development@branch@name\@empty 1\fi\fi>0 % - \everyjob\expandafter{\the\everyjob - \typeout{\fmtname\space <\fmtversion>}} + \LaTeXReleaseInfo\expandafter{\the\LaTeXReleaseInfo + \show@release@info{\fmtname\space <\fmtversion>}} \immediate \write16{\fmtname \space<\fmtversion>} \else\ifnum\patch@level>0 - \everyjob\expandafter{\the\everyjob - \typeout{\fmtname\space <\fmtversion> patch level \patch@level}} + \LaTeXReleaseInfo\expandafter{\the\LaTeXReleaseInfo + \show@release@info{\fmtname\space <\fmtversion> patch level \patch@level}} \immediate \write16{\fmtname\space <\fmtversion> patch level \patch@level} \else - \everyjob\expandafter{\the\everyjob - \typeout{\fmtname\space <\fmtversion> + \LaTeXReleaseInfo\expandafter{\the\LaTeXReleaseInfo + \show@release@info{\fmtname\space <\fmtversion> pre-release-\number-\patch@level\space \ifx\development@branch@name\@undefined \else \ifx\development@branch@name\@empty \else diff --git a/macros/latex/base/ltx3info.pdf b/macros/latex/base/ltx3info.pdf Binary files differindex 368f3162ad..1756ab795e 100644 --- a/macros/latex/base/ltx3info.pdf +++ b/macros/latex/base/ltx3info.pdf diff --git a/macros/latex/base/ltx3info.tex b/macros/latex/base/ltx3info.tex index 13231da818..096fa2db9a 100644 --- a/macros/latex/base/ltx3info.tex +++ b/macros/latex/base/ltx3info.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltxcheck.tex b/macros/latex/base/ltxcheck.tex index 7f4b925b79..d219d2ebc2 100644 --- a/macros/latex/base/ltxcheck.tex +++ b/macros/latex/base/ltxcheck.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltxdoc.dtx b/macros/latex/base/ltxdoc.dtx index 6863349be3..e147c9d22f 100644 --- a/macros/latex/base/ltxdoc.dtx +++ b/macros/latex/base/ltxdoc.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -30,7 +30,7 @@ % %<class>\NeedsTeXFormat{LaTeX2e} %<class>\ProvidesClass{ltxdoc} -%<class> [2022/06/22 v2.1i Standard LaTeX documentation class] +%<class> [2023/03/28 v2.1j Standard LaTeX documentation class] % %<*driver> \documentclass{ltxdoc} @@ -182,9 +182,13 @@ % % Support rolling back \pkg{doc} to version 2: % \changes{v2.1e}{2022/05/27}{Support rolling back doc to version 2} +% \changes{v2.1j}{2023/03/28}{Define \cs{cs} if doc is rolled back to v2 (gh/981)} % \begin{macrocode} \let\ltxdoc@doc@version\@empty % use current version by default -\DeclareOption{doc2}{\def\ltxdoc@doc@version{=v2}} +\DeclareOption{doc2}{% + \def\ltxdoc@doc@version{=v2}% + \DeclareRobustCommand\cs[1]{\texttt{\bslash #1}}% +} % \end{macrocode} % % \begin{macrocode} @@ -670,8 +674,10 @@ Bug reports can be opened (category \texttt{#1}) at\\% % kernel sources. % % -% Copyright 2006, 2007, 2011 Heiko Oberdiek -% Copyright 2014-2021 The LaTeX Project +% Copyright 2006, 2007, 2011 +% Heiko Oberdiek +% Copyright (C) 2014-2023 +% The LaTeX Project % \ProvidesFile{ltxdoc.cfg}% diff --git a/macros/latex/base/ltxdoc.pdf b/macros/latex/base/ltxdoc.pdf Binary files differindex aae8871c68..e3c23c97ec 100644 --- a/macros/latex/base/ltxdoc.pdf +++ b/macros/latex/base/ltxdoc.pdf diff --git a/macros/latex/base/ltxguide.cls b/macros/latex/base/ltxguide.cls index b743fd9cda..778f7e993e 100644 --- a/macros/latex/base/ltxguide.cls +++ b/macros/latex/base/ltxguide.cls @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 1993-2019 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/ltxref.dtx b/macros/latex/base/ltxref.dtx index 596eb2fd74..0f842e4312 100644 --- a/macros/latex/base/ltxref.dtx +++ b/macros/latex/base/ltxref.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -33,7 +33,7 @@ %<*driver> % \fi \ProvidesFile{ltxref.dtx} - [2022/04/12 v1.1p LaTeX Kernel (Cross Referencing)] + [2023/05/16 v1.1q LaTeX Kernel (Cross Referencing)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltxref.dtx} @@ -93,6 +93,15 @@ % to align with the use of \pkg{hyperref}. Without \pkg{hyperref} (or some % other package using the starred form) the star is simply ignored. % +% Note: starting with 2023-06-01 |\label| stores also the current value +% of |\@currentlabelname| which should typically contain a (sanitized) title. +% (A reference command |\nameref| is provided by the \pkg{nameref} package.) +% |\label| also stores |\@currentHref| which if set should refer to a target name +% for links. This value is set and used by \pkg{hyperref}. Unlike the other values +% |\@currentHref| should be set globally. A fifth value |\@kernel@reserved@label@data| +% is reserved for the kernel to allow future extensions of the cross-reference +% system. +% % % \MaybeStop{} % @@ -108,7 +117,8 @@ % incremented by the command \refstepcounter{CNT} , which sets % \@currentlabel == {CNT}{eval(\p@cnt\theCNT)}. The command % \label{FOO} then writes the following on file \@auxout : -% \newlabel{FOO}{{eval(\@currentlabel)}{eval(\thepage)}} +% \newlabel{FOO}{{eval(\@currentlabel)}{eval(\thepage)}% +% {eval(\@currentlabelname)}{eval(\@currentHref)}{eval(\@kernel@reserved@label@data)}} % % \ref{FOO} == % BEGIN @@ -228,6 +238,10 @@ % % RmS 93/09/08: Added setting of refundefined switch. % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2023/06/01}% +%<latexrelease> {\@kernel@sref}{store five arguments}% \def\@setref#1#2#3{% \ifx#1\relax \protect\G@refundefinedtrue @@ -235,19 +249,53 @@ \@latex@warning{Reference `#3' on page \thepage \space undefined}% \else - \expandafter#2#1\null + \expandafter#2#1\@empty\@empty\@empty\null \fi} % \end{macrocode} % \begin{macrocode} -%</2ekernel> -%<*2ekernel|latexrelease> +\long\def\@firstoffive#1#2#3#4#5{#1} +\long\def\@secondoffive#1#2#3#4#5{#2} +\def\@kernel@sref#1{\expandafter\@setref\csname r@#1\endcsname\@firstoffive{#1}} +\def\@kernel@spageref#1{\expandafter\@setref\csname r@#1\endcsname + \@secondoffive{#1}} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{2022/06/01}% +%<latexrelease> {\@kernel@sref}{store five arguments}% +%<latexrelease>\def\@setref#1#2#3{% +%<latexrelease> \ifx#1\relax +%<latexrelease> \protect\G@refundefinedtrue +%<latexrelease> \nfss@text{\reset@font\bfseries ??}% +%<latexrelease> \@latex@warning{Reference `#3' on page \thepage \space +%<latexrelease> undefined}% +%<latexrelease> \else +%<latexrelease> \expandafter#2#1\null +%<latexrelease> \fi} +%<latexrelease>\let\@firstoffive\undefined +%<latexrelease>\let\@secondoffive\undefined +%<latexrelease>\def\@kernel@sref#1{\expandafter\@setref\csname r@#1\endcsname\@firstoftwo{#1}} +%<latexrelease>\def\@kernel@spageref#1{\expandafter\@setref\csname r@#1\endcsname +%<latexrelease> \@secondoftwo{#1}} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@kernel@sref}{store five arguments}% +%<latexrelease>\def\@setref#1#2#3{% +%<latexrelease> \ifx#1\relax +%<latexrelease> \protect\G@refundefinedtrue +%<latexrelease> \nfss@text{\reset@font\bfseries ??}% +%<latexrelease> \@latex@warning{Reference `#3' on page \thepage \space +%<latexrelease> undefined}% +%<latexrelease> \else +%<latexrelease> \expandafter#2#1\null +%<latexrelease> \fi} +%<latexrelease>\let\@firstoffive\undefined +%<latexrelease>\let\@secondoffive\undefined +%<latexrelease>\let\@kernel@sref\undefined +%<latexrelease>\let\@kernel@spageref\undefined +%<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{2022/06/01}% %<latexrelease> {\ref}{Add starred reference commands}% % \end{macrocode} % \begin{macrocode} -\def\@kernel@sref#1{\expandafter\@setref\csname r@#1\endcsname\@firstoftwo{#1}} -\def\@kernel@spageref#1{\expandafter\@setref\csname r@#1\endcsname - \@secondoftwo{#1}} \let\@kernel@ref\@kernel@sref \let\@kernel@pageref\@kernel@spageref \NewDocumentCommand\ref{s} @@ -334,6 +382,8 @@ % \begin{macro}{\label} % \changes{v1.1d}{1994/11/04}{(ASAJ)Added \cs{protected@write}} % \changes{v1.1d}{1994/11/04}{(ASAJ)Added \cs{protected@edef}} +% \changes{v1.1q}{2023/05/12}{(UFi)extended to store five arguments} +% \changes{v1.1q}{2023/05/12}{(UFi)added a hook with argument} % The commands |\label| and |\refstepcounter| have been changed to % allow |\protect|'ed commands to work properly. For example, %\begin{verbatim} @@ -343,16 +393,27 @@ % to something like |\foo{4.d}|. Change made 20 Jul 88. % % \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2023/06/01}% +%<latexrelease> {\label}{store five label arguments}% +\providecommand\@currentlabelname{} +\providecommand\@currentHref{} +\providecommand\@kernel@reserved@label@data{} +\NewHookWithArguments{label}{1} \def\label#1{\@bsphack + \begingroup + \UseHookWithArguments{label}{1}{#1}% \protected@write\@auxout{}% - {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}% + {\string\newlabel{#1}{{\@currentlabel}{\thepage}% + {\@currentlabelname}{\@currentHref}{\@kernel@reserved@label@data}}}% + \endgroup \@esphack} +%<latexrelease>\EndIncludeInRelease % \end{macrocode} % \end{macro} % % \begin{macrocode} -%</2ekernel> -%<*2ekernel|latexrelease> %<latexrelease>\IncludeInRelease{2022/06/01}% %<latexrelease> {\Ref}{Add starred version}% % \end{macrocode} @@ -432,6 +493,16 @@ % \begin{macrocode} %</2ekernel|latexrelease> %<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\label}{store five label arguments}% +%<latexrelease>\let\@currenttitle\@undefined +%<latexrelease>\let\@currenttarget\@undefined +%<latexrelease>\let\@kernel@currentdata\@undefined +%<latexrelease>\def\label#1{\@bsphack +%<latexrelease> \protected@write\@auxout{}% +%<latexrelease> {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}% +%<latexrelease> \@esphack} +%<latexrelease>\EndIncludeInRelease %<latexrelease>\IncludeInRelease{2020/10/01}% %<latexrelease> {\Ref}{Add starred version}% %<latexrelease>\def\@currentcounter{} diff --git a/macros/latex/base/makeindx.dtx b/macros/latex/base/makeindx.dtx index fb6c474659..b91d3a6c44 100644 --- a/macros/latex/base/makeindx.dtx +++ b/macros/latex/base/makeindx.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/makeindx.ins b/macros/latex/base/makeindx.ins index 0fe55ed039..1c5f6edcb9 100644 --- a/macros/latex/base/makeindx.ins +++ b/macros/latex/base/makeindx.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/makeindx.pdf b/macros/latex/base/makeindx.pdf Binary files differindex 139accd18f..677cf80b00 100644 --- a/macros/latex/base/makeindx.pdf +++ b/macros/latex/base/makeindx.pdf diff --git a/macros/latex/base/manifest.txt b/macros/latex/base/manifest.txt index d63945fa0e..22791a2494 100644 --- a/macros/latex/base/manifest.txt +++ b/macros/latex/base/manifest.txt @@ -27,7 +27,8 @@ % sample2e.tex -- Sample LaTeX input file. % small2e.tex -- Small sample LaTeX input file. % -% clsguide.tex -- How to write class files. +% clsguide.tex -- How to write class files. +% clsguide-historic.tex -- How to write class files with a focus on moving from 2.09. % cfgguide.tex -- Guide to using `.cfg' files to configure LaTeX. % cyrguide.tex -- Guide to using cyrillic languages in LaTeX. % encguide.tex -- Guide to font encodings. @@ -71,12 +72,15 @@ % ltnews33.tex -- What was new in the release dated 2021/06. % ltnews34.tex -- What was new in the release dated 2021/11. % ltnews35.tex -- What was new in the release dated 2022/06. +% ltnews36.tex -- What was new in the release dated 2022/11. +% ltnews37.tex -- What was new in the release dated 2023/06. % % ltx3info.tex -- Information about the LaTeX3 project. % % lamport-manual.err -- Errata for the LaTeX Manual book, second edition. % tlc2.err -- Errata for the LaTeX Companion, second edition. +% tlc3.err -- Errata for the LaTeX Companion, third edition. % lb2.err -- Errata for the LaTeX-Begleiter, 2te erw. Auflage (German). % lgc2.err -- Errata for the LaTeX Graphics Companion, second edition. % webcomp.err -- Errata for the LaTeX Web Companion. diff --git a/macros/latex/base/minimal.cls b/macros/latex/base/minimal.cls index 9024a23bca..89c233c30f 100644 --- a/macros/latex/base/minimal.cls +++ b/macros/latex/base/minimal.cls @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 1993-2019 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/modguide.pdf b/macros/latex/base/modguide.pdf Binary files differindex f74e0c15f7..92c662c2f3 100644 --- a/macros/latex/base/modguide.pdf +++ b/macros/latex/base/modguide.pdf diff --git a/macros/latex/base/modguide.tex b/macros/latex/base/modguide.tex index 3474d8a5fc..332b609ab3 100644 --- a/macros/latex/base/modguide.tex +++ b/macros/latex/base/modguide.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -42,7 +42,7 @@ \author{\copyright~Copyright 1995, \LaTeX\ Project Team.\\ All rights reserved.% - \footnote{This file may distributed and/or modified under the + \footnote{This file 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. See the source texttt{modguide.tex} for full details.}% diff --git a/macros/latex/base/newdc.ins b/macros/latex/base/newdc.ins index eeec6479eb..277e8ea21f 100644 --- a/macros/latex/base/newdc.ins +++ b/macros/latex/base/newdc.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/newlfont.dtx b/macros/latex/base/newlfont.dtx index 86c0d47ab6..0b35eddd80 100644 --- a/macros/latex/base/newlfont.dtx +++ b/macros/latex/base/newlfont.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/nfssfont.dtx b/macros/latex/base/nfssfont.dtx index 51d7834aa3..556ce5f76d 100644 --- a/macros/latex/base/nfssfont.dtx +++ b/macros/latex/base/nfssfont.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/nfssfont.ins b/macros/latex/base/nfssfont.ins index a181c61972..21a13f70a8 100644 --- a/macros/latex/base/nfssfont.ins +++ b/macros/latex/base/nfssfont.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/nfssfont.pdf b/macros/latex/base/nfssfont.pdf Binary files differindex 4b657e0f39..d08548d0eb 100644 --- a/macros/latex/base/nfssfont.pdf +++ b/macros/latex/base/nfssfont.pdf diff --git a/macros/latex/base/olddc.ins b/macros/latex/base/olddc.ins index 707fb207e6..320b3a4b0e 100644 --- a/macros/latex/base/olddc.ins +++ b/macros/latex/base/olddc.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/oldlfont.dtx b/macros/latex/base/oldlfont.dtx index b7c9abc3eb..33ae5e6fd9 100644 --- a/macros/latex/base/oldlfont.dtx +++ b/macros/latex/base/oldlfont.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/preload.dtx b/macros/latex/base/preload.dtx index 3b75df38fd..d26bdaa9ed 100644 --- a/macros/latex/base/preload.dtx +++ b/macros/latex/base/preload.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/proc.dtx b/macros/latex/base/proc.dtx index 135c67bc0b..bbbf71162f 100644 --- a/macros/latex/base/proc.dtx +++ b/macros/latex/base/proc.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/proc.ins b/macros/latex/base/proc.ins index 16f60195e5..056816e99e 100644 --- a/macros/latex/base/proc.ins +++ b/macros/latex/base/proc.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/proc.pdf b/macros/latex/base/proc.pdf Binary files differindex c99e5989d7..8f28a58bdc 100644 --- a/macros/latex/base/proc.pdf +++ b/macros/latex/base/proc.pdf diff --git a/macros/latex/base/slides.dtx b/macros/latex/base/slides.dtx index 5ea9e58d9c..a918c337dd 100644 --- a/macros/latex/base/slides.dtx +++ b/macros/latex/base/slides.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/slides.ins b/macros/latex/base/slides.ins index 8c9862c2d5..3acb556b96 100644 --- a/macros/latex/base/slides.ins +++ b/macros/latex/base/slides.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. @@ -96,7 +96,7 @@ extension .ins) which are part of the distribution. This is a generated file. -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. @@ -138,7 +138,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/slides.pdf b/macros/latex/base/slides.pdf Binary files differindex cf5f4f9794..f294fcc6a6 100644 --- a/macros/latex/base/slides.pdf +++ b/macros/latex/base/slides.pdf diff --git a/macros/latex/base/slifonts.fdd b/macros/latex/base/slifonts.fdd index ec8b802596..5b66975095 100644 --- a/macros/latex/base/slifonts.fdd +++ b/macros/latex/base/slifonts.fdd @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 1993-2019 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/slifonts.pdf b/macros/latex/base/slifonts.pdf Binary files differindex 49fcdd0ada..4598e87180 100644 --- a/macros/latex/base/slifonts.pdf +++ b/macros/latex/base/slifonts.pdf diff --git a/macros/latex/base/source2e.pdf b/macros/latex/base/source2e.pdf Binary files differindex b837332107..2aa83c3624 100644 --- a/macros/latex/base/source2e.pdf +++ b/macros/latex/base/source2e.pdf diff --git a/macros/latex/base/source2e.tex b/macros/latex/base/source2e.tex index 797304e8d6..873daebb4d 100644 --- a/macros/latex/base/source2e.tex +++ b/macros/latex/base/source2e.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/syntonly.dtx b/macros/latex/base/syntonly.dtx index ae4d4cd1f8..2b0049b696 100644 --- a/macros/latex/base/syntonly.dtx +++ b/macros/latex/base/syntonly.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/syntonly.ins b/macros/latex/base/syntonly.ins index 5812ef2fd6..8ccaf254d1 100644 --- a/macros/latex/base/syntonly.ins +++ b/macros/latex/base/syntonly.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/syntonly.pdf b/macros/latex/base/syntonly.pdf Binary files differindex 6c9ca64273..9d15389b26 100644 --- a/macros/latex/base/syntonly.pdf +++ b/macros/latex/base/syntonly.pdf diff --git a/macros/latex/base/testpage.tex b/macros/latex/base/testpage.tex index e199a2bb71..7eae6c142c 100644 --- a/macros/latex/base/testpage.tex +++ b/macros/latex/base/testpage.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/tlc2.err b/macros/latex/base/tlc2.err index 8925a8bee1..5b01ff0513 100644 --- a/macros/latex/base/tlc2.err +++ b/macros/latex/base/tlc2.err @@ -1,4 +1,4 @@ -\newcommand\erratafiledate{2022-01-03} +\newcommand\erratafiledate{2023-01-08} \def\comando#1{\texttt{\string#1}} @@ -359,7 +359,7 @@ you own by changing the configuration in the file \texttt{\jobname.cfg}. \end{center} Any mistake found and reported is a gain for all readers of our book. -For this reason Addison-Wesley and the authors offer a prize (for 6 +For this reason Addison-Wesley and the authors offer a prize (for 5 periods) to the eligible person who finds the largest number of bugs during that period (in case of a draw a random choice will be made between all those with the largest number of findings). @@ -385,7 +385,7 @@ Contest period ends & Winner \\[4pt] 2005/10 & Daniel Alonso i Alemany & 13 suggestions\\ 2006/04 & Michael Schutte & 2 suggestions\\ 2008/05 & Brooks Moses & 1 suggestion \\ -\ldots & -- final draw eventually -- + & -- final draw was 2008/05 -- \end{tabular} \end{center} \end{list} @@ -2185,6 +2185,8 @@ Change: ``The unaccented ASCII Latin letters and Arabic |\dag| and |\ddag| are |\mathord|s not |\mathbin| as claimed in table 8.13. + Frank: This is actually correct nowadays (maybe it wasn't in 2008) + \seriouserroronpage{529}{table 8.12, l.3}{JGr}{2004/06/10}{2} \verb=\mathring{x}= is missing its accent. @@ -2202,6 +2204,9 @@ Change: ``The unaccented ASCII Latin letters and Arabic aren't (as claimed in legend) synonyms of |\dagger| and |\ddagger| respectively. + Frank: This is actually correct nowadays (maybe it wasn't in 2008) + + \erroronpage{531}{table 8.15}{BMo/FMi}{2004/05/21}{2} The commands starting with |\var...| are only partially in blue to indicate their relationship with those commands missing the ``var'' in their @@ -2236,10 +2241,6 @@ Change: ``The unaccented ASCII Latin letters and Arabic Various deviations from alphabetical sort order of the table entries. -\erroronpage{553}{para 3, l.1}{EOl}{2022/01/02}{} - Missing letter: ``sup\u{p}ressing'' - - \iffalse % more blue align stuff \erroronpage{534}{page}{FMi}{2004/04/23}{} Printing problem: blue color not properly aligned (horizontally). @@ -2332,6 +2333,10 @@ Plural: ``Clearly, 8 bits \u{are} not sufficient\ldots'' respectively %(ref: TB 14-3-252-259) +\erroronpage{553}{para 3, l.1}{EOl}{2022/01/02}{} + Missing letter: ``sup\u{p}ressing'' + + \seriouserroronpage{553}{para 4}{UFi}{2004/06/03}{2} Replace with: ``Another popular shorthand is |"-|, which indicates a diff --git a/macros/latex/base/tlc2.pdf b/macros/latex/base/tlc2.pdf Binary files differindex e82f587b19..3d93429fbc 100644 --- a/macros/latex/base/tlc2.pdf +++ b/macros/latex/base/tlc2.pdf diff --git a/macros/latex/base/tlc3.err b/macros/latex/base/tlc3.err new file mode 100644 index 0000000000..b7e2c1c0fd --- /dev/null +++ b/macros/latex/base/tlc3.err @@ -0,0 +1,848 @@ +\newcommand\erratafiledate{2023-05-30} + +\def\comando#1{\texttt{\string#1}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% To produce a printed version of this errata file run this file through +% LaTeX. It will unpack a small class file (if not already present) and +% a configuration file with the extension .cfg. You might want to modify +% the setting in this configuration file to print only a partial errata +% suitable for your printed revision of this book, see details in the +% .cfg file. +% +% The current version of this file can be found at: +% +% https://www.latex-project.org/help/books/ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\begin{filecontents}{ttcterrata.cls} +%% +%% Copyright (C) 1997-2021 Frank Mittelbach +%% This class file is licensed under LPPL latest version; +%% see https://www.latex-project.org/lppl +% +% +% It sets up a few commands used to format the errata entries for books in the +% Addison-Wesley Series: +% +% Tools and Techniques for Computer Typesetting +% +% hence the name. However, anybody who likes to use it is free to apply it for +% errata files of other books. +% +% Changes: +% +% v1.0a - changed name from errata.cls to ttcterrata.cls +% v1.0b - added \arraybackslash +% v1.0c - and took it out again and used \tabularnewline instead + +\ProvidesClass{ttcterrata} + [2021/08/03 v1.0c Mini class for errata files; subject to change (FMi)] + +\LoadClass{article} + +\setcounter{secnumdepth}{-1} +\addtolength\textwidth{5cm} +\addtolength\oddsidemargin{-3cm} + +\addtolength\textheight{36pt} + +\RequirePackage{shortvrb} +\MakeShortVerb{\|} + +\RequirePackage{array,longtable} +\RequirePackage{multicol} + + +\newcommand\erratagetnumber{} +\def\erratagetnumber#1/#2/#3\erratagetnumber{#1#2#3} + + +\newcommand\gobbleerrata{% + \setbox\@tempboxa\vbox\bgroup + \let\endgobble\egroup + \let\hideamp\relax + \let\\\relax + \let\tabularnewline\relax + \let\par\@@par} + +\newcommand*\hideamp{&} + +\let\endgobble\relax + + +\newcommand\erratastartdate{} +\newcommand\myprinting{1} + + +\newcommand\doweprint[2]{% + \ifnum \myprinting < \if!#2!1000 \else \ifx s#2 1000\else#2 \fi\fi + \ifnum \expandafter\erratagetnumber\erratastartdate\erratagetnumber < + \erratagetnumber#1\erratagetnumber \relax + \@tempswatrue + \else + \@tempswafalse + \fi + \else + \@tempswafalse + \fi +} + + + +\newcommand\includedentries{entries after = \erratastartdate} +\newcommand\printedentries{between \erratastartdate\space and} + +\newcommand\showallerrors{% + \renewcommand\includedentries{all errata entries}% + \renewcommand\printedentries{up to} + \renewcommand\doweprint[2]{\@tempswatrue}} + + +\newcommand\displayrevisionfix[2]{% + \if!#2!\textbf{#1}\else\textit{#1}\rlap{\textsuperscript{#2}}\fi} + +\newcommand\norevisionnumbers{% + \renewcommand\displayrevisionfix[2]{\textbf{##1}}} + +\IfFileExists{\jobname.cfg} + { + \input{\jobname.cfg} + \typeout{***************************************************} + \typeout{*} + \typeout{* Configuration file for \jobname.err found } + \typeout{*} + \typeout{***************************************************} + \AtEndDocument{ + \typeout{***************************************************} + \typeout{*} + \typeout{* If you wish to generate an errata listing} + \typeout{* containing only errors found after a certain revision} + \typeout{* and/or only errors found after a certain date} + \typeout{* modify the information stored in \jobname.cfg} + \typeout{*} + \typeout{* Current settings are:} + \typeout{*} + \typeout{* \@spaces printing of your book = \myprinting} + \typeout{* \@spaces include \includedentries} + \typeout{*} + \typeout{***************************************************} + }} + {} + +%% \erroronpage <page> <line info> <contributor> <date> <fixed in revision> + +\newcommand\erroronpage[5]{% + \endgobble + \doweprint{#4}{#5}% + \if@tempswa + \typeout{Typesetting entry #1 #2 #3 #4}% + \else + \typeout{Ignoring entry #1 #2 #3 #4}% + \expandafter\gobbleerrata + \fi + \hideamp \tabularnewline + \displayrevisionfix{#1}{#5} + \hideamp #2 \hideamp (\textsf{#3}) \hideamp +} + +\newcommand\seriouserroronpage[5]{% + \endgobble + \doweprint{#4}{#5}% + \if@tempswa + \typeout{Typesetting entry #1 #2 #3 #4}% + \else + \typeout{Ignoring entry #1 #2 #3 #4}% + \expandafter\gobbleerrata + \fi + \hideamp \tabularnewline + \fbox{\bfseries !!}\hfill + \displayrevisionfix{#1}{#5} + \hideamp #2 \hideamp (\textsf{#3}) \hideamp +} + +\newcommand\CHAPTER[1]{\endgobble + &\tabularnewline[4pt]% + \multicolumn{4}{l}{\framebox[10cm][l]{\textbf{\normalsize\strut#1}}} \tabularnewline} + +\newenvironment{erratalist} + {\begin{longtable}{r>{\raggedright}p{2cm}l>{\raggedright}p{10cm}l}} + {\endgobble\end{longtable}} + +\newcommand\erratatitle[2] + {\begin{center}\LARGE\bfseries + Errata list for #1\\[5pt](\myprinting.\ printing)\\[10pt] + \small Includes all entries found \printedentries\space #2\\ + (For other periods/print runs reprocess this document + with different config settings) + \end{center}% + \markright{Errata for #1 (\printedentries\space #2)}% + \thispagestyle{plain}% + \vspace{20pt}} + +\pagestyle{myheadings} + +\AtBeginDocument{\small} + +\setlength\parindent{0pt} +\setlength\parskip{2pt} + +\newcommand\contributor[2]{\makebox[1cm][l]{\sffamily#1} #2\par} + +% some special shortcuts overwriting existing commands: + +\let\u\underline +\renewcommand\>{$\to$} + +%%% some code suggested by Thorsten Hansen to count the number of +%%% contributions by individuals (will work only if we do not get +%%% too many :-) + +\def\count@contributors#1/#2/#3\@nil{ + \@ifundefined{c@#1}{\newcounter{#1}}{}\stepcounter{#1}% +%%% also count secondary: +%%% \@ifundefined{c@#2}{\newcounter{#2}}{}\stepcounter{#2}% +} + +\renewcommand\erroronpage[5]{% + \count@contributors#3/secondary/\@nil + \endgobble + \doweprint{#4}{#5}% + \if@tempswa + \typeout{Typesetting entry #1 #2 #3 #4}% + \else + \typeout{Ignoring entry #1 #2 #3 #4}% + \expandafter\gobbleerrata + \fi + \hideamp \tabularnewline + \displayrevisionfix{#1}{#5} + \hideamp #2 \hideamp (\textsf{#3}) \hideamp +} + +\renewcommand\seriouserroronpage[5]{% + \count@contributors#3/secondary/\@nil + \endgobble + \doweprint{#4}{#5}% + \if@tempswa + \typeout{Typesetting entry #1 #2 #3 #4}% + \else + \typeout{Ignoring entry #1 #2 #3 #4}% + \expandafter\gobbleerrata + \fi + \hideamp \tabularnewline + \fbox{\bfseries !!}\hfill + \displayrevisionfix{#1}{#5} + \hideamp #2 \hideamp (\textsf{#3}) \hideamp +} + +\renewcommand\contributor[2]{\makebox[1cm][l]{% + \sffamily#1} #2\@ifundefined{c@#1}{}{ (\arabic{#1})}\par} + +\end{filecontents} + + +\begin{filecontents}{\jobname.cfg} +% +% +% Configuration file for the errata listing of +% +% The LaTeX Companion, Third Edition, Parts I & II +% +% +% \erratastartdate +% +% Specifies the date from which on errata entries should be listed. +% +% The format is YYYY/MM/DD. +% +% The default below ensures that all entries for a particular +% printing are typeset. +% + +\renewcommand\erratastartdate{2023/04/01} + + +% +% \myprinting +% +% Specifies which (revised) printing you own. For example, if you +% have the second printing set this to 2 so that errors already +% corrected in that printing will not appear in your errata +% listing. +% +% The default below ensures that all entries relevant to the x-th +% printing are typeset. +% +% + +\renewcommand\myprinting{1} + +% +% \norevisionnumbers +% +% Specifies that all page numbers in the errata are shown in the same +% format (bold face) irregardless of whether or not they are fixed +% in some revision. The default is to print corrected errors in +% italic and add the revision number as a superscript. + +% +% \showallerrors +% +% With this command you tell the program that all errata entries are +% supposed to be generated. This makes \myprinting and +% \erratastartdate basically obsolete so this isn't turned on by +% default. +% +% +\endinput +\end{filecontents} + + +\documentclass{ttcterrata}[2005/11/10] % we want new class + +\usepackage[T1]{fontenc} +\let\u\underline % shortcut for this file +\newcommand\meta[1]{$\langle$\textit{#1\/}$\rangle$} + +\usepackage{textcomp} + +\usepackage{url} + +\begin{document} + +\erratatitle{The \LaTeX{} Companion, Third Edition, Parts I \& II}{\erratafiledate} + + +\begin{verbatim} +@book(A-W:MF:2023, + author = {Frank Mittelbach and Ulrike Fischer}, + title = {The {\LaTeX} Companion}, + edition = 3, + note = {With contributions by Javier Bezos, Johannes Braams, and Joseph Wright}, + series = {Tools and Techniques for Computer Typesetting}, + publisher = {Addison-Wesley}, + address = {Boston, Massachusetts}, + year = 2023, + pagenums = {976 (Part I) and 1008 (Part II)}, + bibliography = {yes}, + index = {yes}, + isbn = {978-0-13-816648-9}, +) +\end{verbatim} + + +\begin{list}{}{\setlength\leftmargin{0cm}\setlength\rightmargin{3cm}} +\item[] + +This file (\texttt{\jobname.err}) can be found as part of the \LaTeX{} +distribution and its latest version is maintained on the \LaTeX{} +project site at \texttt{https://www.latex-project.org/help/books/\jobname.err} +where you will also find extracts of the book. + +The first column in the table shows the page number of the errata +entry. Superscript numbers in the first column refer to the printed +revision in which this entry was corrected (\textit{s} indicates a +correction in the sources only). The second +column gives the precise location (negative line or paragraph numbers +are counted from the bottom of the page). The third column shows the +first finder of the problem. + +You can customize this list to only show errata related to the printing +you own by changing the configuration in the file \texttt{\jobname.cfg}. + +\begin{center} + \Large \bfseries To Err is Human --- Bug Contest +\end{center} + +Any mistake found and reported is a gain for all readers of our book. +For this reason Addison-Wesley and the authors offer a prize (for 5 +periods) to the eligible person who finds the largest +number of bugs during that period (in case of a draw a random choice +will be made between all those with the largest number of findings). +A person can receive at most one prize, ever; errors found by any of +the authors do not count. + +Each prize is a free choice of any single computing book found on the +Addison-Wesley/Pearson web site: +\texttt{https://www.informit.com} (that +is, no boxed sets or multiple volume offers). + + +As usual, the authors and publisher reserve the right to make various +decisions such as whether a reported feature is an error for +competitive purposes or whether similar features count as a single or +multiple errors. --- +Good luck! + +\begin{center} +\begin{tabular}{clr} +Contest period ends & Winner \\[4pt] +2023/?? & & ??? suggestions\\ +\end{tabular} +\end{center} + + +Due to its size the third edition of \textit{The \LaTeX{} Companion} is printed +as a two-volume set. The digital version, however, is provided as a +single PDF or ePub. This means that a small fraction of the digital +content differs from that of the printed version: there is only a +single font matter, a single bibliography, and a single index, whereas +in the printed books these are separated out. However, all versions share the main +matter (down to the page numbering) so most of the errata applies to +all versions, but a few only to the digital and some only to the +printed version. Thus, we end up with three separate lists. + + +\end{list} + +%\newpage + + +%<-------------------------- + +\newcommand\BibTeX{\textsc{Bib}\TeX} +\newcommand\cs[1]{\texttt{\textbackslash #1}} +\newcommand\env[1]{\texttt{#1}} +\newcommand\pkg[1]{\textsf{#1}} + +\section*{Errata for the print version (not applicable to the digital version)} + +The printed books differ from the digital version in that the +bibliography is split across both volumes (with a few repeats) and that +the font matter of each volume has its own table of contents and list +of figures and tables. Therefore these parts have different page +numbers and you will see similar errata entries for both print and +digital differing only in that respect. + +\begin{erratalist} + +\CHAPTER{Front matter (Part I)} + +\erroronpage{I-ix\ldots I-xvi}{}{FMi}{2023/04/04}{s} +Dot leaders have been changed on all sections. + +\erroronpage{I-xvii}{chapter head}{FMi}{2023/04/04}{s} +formulas \> \u{F}ormulas + +\erroronpage{I-xvii}{chapter head}{FMi}{2023/04/04}{s} +documents \> \u{D}ocuments + +\erroronpage{I-xvii}{chapter head}{FMi}{2023/04/04}{s} +beyond \> \u{B}eyond + +\erroronpage{I-xx\ldots I-xxi}{}{FMi}{2023/04/04}{s} +Dot leaders have been changed on all sections. + +\CHAPTER{Bibliography (Part I)} + +\erroronpage{I-783}{[55], l.-2}{FMi}{2023/04/04}{s} +all \> \u{them} all + +\erroronpage{I-785}{[73], l.-2}{kb/bb}{2023/04/04}{s} +the go-forward way for \LaTeX-coding \> \\ +the way for \LaTeX{} coding going forward + +\erroronpage{I-786}{[87], l.2}{kb/bb}{2023/04/04}{s} +p. \> pp. + +\erroronpage{I-786}{[88], l.2}{kb/bb}{2023/04/04}{s} +p. \> pp. + +\erroronpage{I-787}{[92], l.2}{kb/bb}{2023/04/04}{s} +Add: Vancouver, 1999 + +\erroronpage{I-788}{[100], l.3}{kb/bb}{2023/04/04}{s} +Publishing \> Publishing\u{,} + +\erroronpage{I-790}{[122], l.1}{kb/bb}{2023/04/04}{s} +In \u{ACM editor} ``Proceedings \> In ``\u{PODC'01: }Proceedings + +\erroronpage{I-790}{[122], l.1}{kb/bb}{2023/04/04}{s} +In \u{Unicode Consortium, editor} \> In + + +\CHAPTER{Front matter (Part II)} + +\erroronpage{II-x\ldots II-xxviii}{}{FMi}{2023/04/04}{s} +Dot leaders have been changed on all sections. + +\erroronpage{II-xiv}{heading}{bb/FMi}{2023/04/04}{s} +Multiple alignments: \env{align} \u{and \env{flalign}} +\>\\ +Multiple alignments: \env{align}\u{, \env{flalign}, and \env{alignat}} + +\erroronpage{II-xv}{chapter head}{FMi}{2023/04/04}{s} +formulas \> \u{F}ormulas + +\erroronpage{II-xvi}{chapter head}{FMi}{2023/04/04}{s} +documents \> \u{D}ocuments + +\erroronpage{II-xxi}{chapter head}{FMi}{2023/04/04}{s} +beyond \> \u{B}eyond + + + +\CHAPTER{Bibliography (Part II)} + +\erroronpage{II-799}{[43], l.-2}{FMi}{2023/04/04}{s} +all \> \u{them} all + +\erroronpage{II-801}{[62], l.-2}{kb/bb}{2023/04/04}{s} +the go-forward way for \LaTeX-coding \>\\ +the way for \LaTeX{} coding going forward + +\erroronpage{II-802}{[71], l.2}{kb/bb}{2023/04/04}{s} +p. \> pp. + +\erroronpage{II-802}{[72], l.2}{kb/bb}{2023/04/04}{s} +p. \> pp. + +\erroronpage{II-803}{[80], l.3}{kb/bb}{2023/04/04}{s} +Publishing \> Publishing\u{,} + + + + +\end{erratalist} + + +%<-------------------------- + +\section*{Errata for the digital version (not applicable to the print version)} + +All known errors to the digital version have already been incorporated in the product as distributed. + +%\begin{erratalist} +% +%\CHAPTER{General} +% +%\CHAPTER{Front matter} +% +%\end{erratalist} + + +%<-------------------------- + + +\section*{Errata common to the print and digital versions} + +The main matter is identical (also in page numbers) in the print and +the digital versions. Therefore most errata entries appear in this +section. + +\begin{erratalist} + + +\CHAPTER{General} + +\erroronpage{}{}{FMi}{2023/04/04}{s} +Some corrections result in index changes. These are not tracked here; +the index is always fully regenerated for new printings. + +\CHAPTER{Chapter 1 --- Introduction} + +\erroronpage{I-5}{para 4, l.4}{kb}{2023/04/04}{s} +\u{of} the bugs \> \u{with} the bugs +\\ Already corrected in the digital version. + + +\erroronpage{I-5}{para 5, l.5}{kb}{2023/04/04}{s} +not least \> \u{but} not least +\\ Already corrected in the digital version. + + +\CHAPTER{Chapter 2 --- The Structure of a \LaTeX{} Document} + +\erroronpage{I-34}{l.-1}{FMi}{2023/04/04}{s} +Moved first line of page 35 to 34. +\\ Already corrected in the digital version. + +\erroronpage{I-35}{l.1}{FMi}{2023/04/04}{s} +Moved first line of page 35 to 34. +\\ Already corrected in the digital version. + +\erroronpage{I-113}{listing}{FMi}{2023/05/14}{s} +Situation is the same in the 2023 distributions; listing output updated. +\\ Already corrected in the digital version. + + +\CHAPTER{Chapter 3 --- Basic Formatting Tools -- Paragraph \ldots} + + +\CHAPTER{Chapter 4 --- Basic Formatting Tools -- Larger \ldots} + + +\CHAPTER{Chapter 5 --- The Layout of the Page} + + +\CHAPTER{Chapter 6 --- Tabular Material} + + +\CHAPTER{Chapter 7 --- Mastering Floats} + + +\CHAPTER{Chapter 8 --- Graphics Generation and Manipulation} + +\erroronpage{I-619}{para -2, l.2}{FMi}{2023/05/30}{s} +in \u{light blue} \> in \u{red} + +\erroronpage{I-619}{exa 8-4-7}{FMi}{2023/05/30}{s} +The example uses \verb*/left color=red!20/ but this is not really +visible if the red is turned into some gray value in the book (which +is then made even lighter through \texttt{!20}). So it is better to +start from full red, i.e., \> \verb*/left color=red/ instead. +\\ Already corrected in the digital version. + +\CHAPTER{Chapter 9 --- Font Selection and Encodings} + +\erroronpage{I-669}{exa 9-3-11}{FMi}{2023/04/04}{s} +Changed line breaks in example. + +\erroronpage{I-708}{listing}{FMi}{2023/05/14}{s} +Situation is the same in the 2023 distributions; listing output updated. +\\ Already corrected in the digital version. + + +\CHAPTER{Chapter 10 --- Text and Symbol Fonts} + +\erroronpage{II-114}{table 10.89}{FMi}{2023/04/04}{s} +Added missing \texttt{U+00Fx} line. +There was a bug in code generating it. +\\ Already corrected in the digital version. + +\erroronpage{II-117}{table 10.92}{FMi}{2023/04/04}{s} +Added missing \texttt{U+00Fx} line. +There was a bug in code generating it. +\\ Already corrected in the digital version. + +\erroronpage{II-121}{table 10.96}{FMi}{2023/04/04}{s} +Added missing \texttt{U+00Fx} line. +There was a bug in code generating it. +\\ Already corrected in the digital version. + +\erroronpage{II-122}{table 10.98}{FMi}{2023/04/04}{s} +Added missing \texttt{U+00Fx} line. +There was a bug in code generating it. +\\ Already corrected in the digital version. + +\erroronpage{II-122}{table 10.99}{FMi}{2023/04/04}{s} +Added missing \texttt{U+00Fx} line. +There was a bug in code generating it. +\\ Already corrected in the digital version. + +\erroronpage{II-123}{table 10.100}{FMi}{2023/04/04}{s} +Added missing \texttt{U+00Fx} line. +There was a bug in code generating it. +\\ Already corrected in the digital version. + +\erroronpage{II-124}{table 10.103}{FMi}{2023/04/04}{s} +Added missing \texttt{U+00Fx} line. +There was a bug in code generating it. +\\ Already corrected in the digital version. + + + +\CHAPTER{Chapter 11 --- Higher Mathematics} + +\erroronpage{II-127}{para 1, l.5}{bb/FMi}{2023/04/04}{s} +\u{The} American Mathematical Society (AMS) \u{provides} a major +package, \pkg{amsmath}, which \u{makes} \ldots +\>\\ +\u{In the early nineties the} American Mathematical Society (AMS) +\u{provided} a major package, \pkg{amsmath}, which \u{made} \ldots +\\ Already corrected in the digital version. + +\erroronpage{II-129}{para -3, l.1}{bb/FMi}{2023/04/04}{s} +The principal documentation for these packages +\>\\ +The principal documentation for these \u{two} packages +\\ Already corrected in the digital version. + + +\erroronpage{II-129}{para -1, l.3}{bb}{2023/04/04}{s} +\u{lot} additions \> \u{many} additions +\\ Already corrected in the digital version. + + +\erroronpage{II-132}{table 11.1}{bb/FMi}{2023/04/04}{s} +Also mention \env{alignat}, \env{alignat*}, and \env{alignedat}. +\\ Already corrected in the digital version. + +\erroronpage{II-133}{para 4,l.2}{bb/FMi}{2023/04/04}{s} +Add: + +Furthermore, they move the equation tag out of the way if it would +otherwise overprint the formula. +\\ Already corrected in the digital version. + +\erroronpage{II-138}{heading}{bb/FMi}{2023/04/04}{s} +Multiple alignments: \env{align} \u{and \env{flalign}} +\> +Multiple alignments: \env{align}\u{, \env{flalign}, and \env{alignat}} +\\ Already corrected in the digital version. + +\erroronpage{II-138}{}{FMi}{2023/04/04}{s} +Moved para from 139 to end of this page. +\\ Already corrected in the digital version. + +\erroronpage{II-139}{para 1}{FMi}{2023/04/04}{s} +Moved para back to page 138. +\\ Already corrected in the digital version. + +\erroronpage{II-139}{bottom}{FMi}{2023/04/04}{s} +Add: + +Sometimes it is more convenient to explicitly specify all the +horizontal spacing yourself within the formula. For this you can use +an \env{alignat} environment. It differs from \env{align} in two ways: you have to +specify the number of \texttt{rl} pairs as an argument to the environment and +it does not add any spaces between the pairs, e.g., +\begin{verbatim} +\begin{alignat}{3} x &= y &\qquad X &= Y &\qquad a &= b+c \\ ... +\end{verbatim} +As usual, equation numbers can be altered with \cs{tag} or suppressed with \cs{notag}. +\\ Already corrected in the digital version. + + +\erroronpage{II-140}{para 1, l.2}{bb/FMi}{2023/04/04}{s} +Add: + +Do not forget to reset \cs{minalignsep} if you change it in this manner. +\\ Already corrected in the digital version. + +\erroronpage{II-140}{para 2, l.4}{bb/FMi}{2023/04/04}{s} +Add: + +You can think of them as subsidiary environments that can be used +within any of the display environments discussed so far (below we use +them inside equation). +\\ Already corrected in the digital version. + +\erroronpage{II-140}{para -1}{FMi}{2023/04/04}{s} +Paragraph moved to page 141. +\\ Already corrected in the digital version. + +\erroronpage{II-141}{}{FMi}{2023/04/04}{s} +One paragraph moved over from page 140. +\\ Already corrected in the digital version. + +\erroronpage{II-144}{para 2, l.-3}{FMi}{2023/04/04}{s} +the issue \> the \u{spacing} issue +\\ Already corrected in the digital version. + +\erroronpage{II-145}{para 2, l.1}{bb/FMi}{2023/04/04}{s} +Add: + +Another problem is that an empty line introduces an unwanted break +point in front of the display, thus \cs{predisplaypenalty} is no +longer honored. +\\ Already corrected in the digital version. + + +\CHAPTER{Chapter 12 --- Fonts in Formulas} + +\erroronpage{II-225}{heading}{FMi}{2023/04/04}{s} +Chapter title not properly capitalized. +\\ Already corrected in the digital version. + +\erroronpage{II-261}{para 3, l.3}{FMi}{2023/05/26}{s} +Yoda spoke it seems: \ldots \u{and compare we should} \> +\ldots \u{and you should compare} +\\ Already corrected in the digital version. + + +\CHAPTER{Chapter 13 --- Localizing Documents} + +\erroronpage{II-297}{heading}{FMi}{2023/04/04}{s} +Chapter title not properly capitalized. +\\ Already corrected in the digital version. + + +\CHAPTER{Chapter 14 --- Index Generation} + + +\CHAPTER{Chapter 15 --- Bibliography Generation} + +\erroronpage{II-435}{code}{FMi}{2023/05/26}{s} +\verb=\textcolor{See= \> \verb=\textcolor{blue}{See= +\\ Already corrected in the digital version. + + + +\CHAPTER{Chapter 16 --- Managing Citations} + + +\CHAPTER{Chapter 17 --- \LaTeX{} Package Documentation Tools} + + +\CHAPTER{Appendix A --- \LaTeX{} Overview for Preamble, \ldots} + + +\CHAPTER{Appendix B --- Tracing and Resolving Problems} + + +\CHAPTER{Appendix C --- Going Beyond} + +\erroronpage{II-297}{heading}{FMi}{2023/04/04}{s} +Appendix title not properly capitalized. +\\ Already corrected in the digital version. + +\CHAPTER{Biographies} + +\CHAPTER{Production Notes} + +\end{erratalist} + + + + + +\setcounter{collectmore}{3} + +\begin{multicols}{3}[Thanks to all who have found errors or + omissions. Listed are the people who found an errata entry first.] +\contributor{bb}{Barbara Beeton} +\contributor{FMi}{Frank Mittelbach} +\contributor{kb}{Karl Berry} +\end{multicols} + + +Other people have sent us corrections for errors already found. +Thanks to all of you! + +If you find further errors please report them to one of the authors, e.g., +\begin{quote}\ttfamily + frank.mittelbach@latex-project.org +\end{quote} +preferably in a form usable directly in this file, i.e., +\begin{flushleft} +|\erroronpage{|\textit{page-number}|}{|\textit{line-identification}|}{|% + \textit{your-initials}|}{|\textit{date}|}{}| \\ + \hspace*{2em}\textit{description of the erratum} +\end{flushleft} +Here is an example: +\begin{verbatim} +\erroronpage{5}{para 3, l.1}{FMi}{2023/06/21}{} + \u{LaTeX} \> \u{\LaTeX} +\end{verbatim} +\verb=\u= underlines a text fragment and \verb=\>= produces \>. +\end{document} + + + + +\seriouserroronpage{general}{}{FMi}{2004/06/12}{} + + To help you in assessing this errata document we have placed + exclamation marks in front of each entry that we consider essential + for correctly understanding the book contents. + +\erroronpage{general}{}{FMi}{2004/05/14}{} + + Due to the printing process there may be small alignment problems + between blue and black text on some pages. These can vary from book + to book depending on how the paper was handled between print + runs---such is the analog nature of printing on a press. + diff --git a/macros/latex/base/tlc3.pdf b/macros/latex/base/tlc3.pdf Binary files differnew file mode 100644 index 0000000000..83605eb82f --- /dev/null +++ b/macros/latex/base/tlc3.pdf diff --git a/macros/latex/base/tulm.fdd b/macros/latex/base/tulm.fdd index 243cbe30cc..c8dd8b95fc 100644 --- a/macros/latex/base/tulm.fdd +++ b/macros/latex/base/tulm.fdd @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright 2016-2021 +% Copyright (C) 2016-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/tulm.ins b/macros/latex/base/tulm.ins index a50060b201..85970a5133 100644 --- a/macros/latex/base/tulm.ins +++ b/macros/latex/base/tulm.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 2016-2022 +%% Copyright (C) 2016-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -48,7 +48,7 @@ reports for it can be opened at https://latex-project.org/bugs.html (but please observe conditions on bug reports sent to that address!) -Copyright (C) 2016-2022 +Copyright (C) 2016-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/base/tulm.pdf b/macros/latex/base/tulm.pdf Binary files differindex 990eba766b..d1bf3b1a88 100644 --- a/macros/latex/base/tulm.pdf +++ b/macros/latex/base/tulm.pdf diff --git a/macros/latex/base/unpack.ins b/macros/latex/base/unpack.ins index 21ba62a33a..5baa2b5447 100644 --- a/macros/latex/base/unpack.ins +++ b/macros/latex/base/unpack.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% diff --git a/macros/latex/base/usrguide-historic.pdf b/macros/latex/base/usrguide-historic.pdf Binary files differindex ba663260c9..629e70e7bd 100644 --- a/macros/latex/base/usrguide-historic.pdf +++ b/macros/latex/base/usrguide-historic.pdf diff --git a/macros/latex/base/usrguide-historic.tex b/macros/latex/base/usrguide-historic.tex index ce35aaa77c..40865a2be9 100644 --- a/macros/latex/base/usrguide-historic.tex +++ b/macros/latex/base/usrguide-historic.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -36,7 +36,7 @@ \author{\copyright~Copyright 1995--2022, \LaTeX\ Project Team.\\ All rights reserved.% - \footnote{This file may distributed and/or modified under the + \footnote{This file 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. See the source \texttt{usrguide.tex} for full details.}% diff --git a/macros/latex/base/usrguide.pdf b/macros/latex/base/usrguide.pdf Binary files differindex 3bcdae3035..c9d445ae8a 100644 --- a/macros/latex/base/usrguide.pdf +++ b/macros/latex/base/usrguide.pdf diff --git a/macros/latex/base/usrguide.tex b/macros/latex/base/usrguide.tex index 32e12a1397..42d5e401f8 100644 --- a/macros/latex/base/usrguide.tex +++ b/macros/latex/base/usrguide.tex @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2020-2022 +% Copyright (C) 2020-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % @@ -32,17 +32,18 @@ \usepackage[T1]{fontenc} % needed for \textbackslash in tt \usepackage{csquotes} +\usepackage{url} \title{\LaTeX\ for authors --- current version} -\author{\copyright~Copyright 2020-2022, \LaTeX\ Project Team.\\ +\author{\copyright~Copyright 2020-2023, \LaTeX\ Project Team.\\ All rights reserved.% - \footnote{This file may distributed and/or modified under the + \footnote{This file 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. See the source \texttt{usrguide.tex} for full details.}% } -\date{2022-07-05} +\date{2023-05-23} \NewDocumentCommand\cs{m}{\texttt{\textbackslash\detokenize{#1}}} \NewDocumentCommand\marg{m}{\arg{#1}} @@ -340,6 +341,12 @@ in \pkg{amsmath} environments, which in the terms here would be defined as \NewDocumentCommand\\{!s !o}{ ... } \end{verbatim} +Also notable when using optional arguments in the last position is that \TeX{} +will necessarily look ahead for the argument opening token. This means that +the value of |\inputlineno| will be `out by one' if such a trailing optional +argument is \emph{not} present and the command ends a line; it will be one +greater than the line number containing the last mandatory argument. + \subsection{`Embellishments'} \label{sec:cmd:embellishment} @@ -636,7 +643,19 @@ processed argument can be further processed using a mapping function If only a single character \meta{token} is used for the split, any category code $13$ (active) character matching the \meta{token} will be replaced before the split takes place. -Spaces are trimmed at each end of each item parsed. +Spaces are trimmed at each end of each item parsed. Exactly one set +of braces will be stripped if an entire item is surrounded by them, +i.e.~the following inputs and outputs result (each separte item as +a brace group). +\begin{verbatim} +a ==> {a} +{a} ==> {a} +{a}b ==> {{a}b} +a,b ==> {a}{b} +{a},b ==> {a}{b} +a,{b} ==> {a}{b} +a,{b}c ==> {a}{{b}c} +\end{verbatim} \begin{decl} |\ProcessList| \arg{list} \arg{function} @@ -716,7 +735,7 @@ put that code at the end of the \meta{start code}. Nevertheless this Environments that use this feature can be nested. -\subsection{Fully-expandable document commands} +\subsection{Fully-expandable document commands\label{sec:ltcmd:expandable}} Document commands created using \cs{NewDocumentCommand}, etc.\@, are normally created so that they do not expand unexpectedly. This is done using engine @@ -724,7 +743,7 @@ features, so is more powerful than \LaTeXe{}'s \cs{protect} mechanism. There are \emph{very rare} occasion when it may be useful to create functions using a expansion-only grabber. This imposes a number of restrictions on the nature of the arguments accepted by a function, and the code it implements. -This facility should only be used when \emph{absolutely necessary}. +This facility should only be used when \emph{necessary}. \begin{decl} |\NewExpandableDocumentCommand| \arg{cmd} \arg{arg spec} \arg{code} \\ @@ -755,6 +774,25 @@ available: in the standard version. \end{itemize} +\subsection{Commands at the start of tabular cells} + +Creating commands that are used at the start of tabular cells imposes +some restrictions on the underlying implementation. The standard \LaTeX{} +tabular environments (\texttt{tabular}, etc.) use a mechanism which requires +that any command wrapping \cs{multicolumn} or similar must be +`expandable'. This is \emph{not} the case for commands created using +\cs{NewDocumentCommand}, etc., which as detailed in +Section~\ref{sec:ltcmd:expandable} use an engine feature which prevents +such `expansion'. Therefore, to create such wrappers for use at the start +of tabular cells, you must use \cs{NewExpandableDocumentCommand}, for example +\begin{verbatim} +\NewExpandableDocumentCommand\MyMultiCol{m}{\multicolumn{3}{c}{#1}} +\begin{tabular}{lcr} +a & b & c \\ +\MyMultiCol{stuff} \\ +\end{tabular} +\end{verbatim} + \subsection{Details about argument delimiters} In normal (non-expandable) commands, the delimited types look for the @@ -844,28 +882,28 @@ The argument specifications for document commands and environments are available for examination and use. \begin{decl} - |\GetDocumentCommandArgSpec| \arg{function} \\ + |\GetDocumentCommandArgSpec| \arg{cmd} \\ |\GetDocumentEnvironmentArgSpec| \arg{environment} \end{decl} These functions transfer the current argument specification for the -requested \meta{function} or \meta{environment} into the token list -variable \cs{ArgumentSpecification}. If the \meta{function} or +requested \meta{cmd} or \meta{environment} into the token list +variable \cs{ArgumentSpecification}. If the \meta{cmd} or \meta{environment} has no known argument specification then an error is issued. The assignment to \cs{ArgumentSpecification} is local to the current \TeX{} group. \begin{decl} - |\ShowDocumentCommandArgSpec| \arg{function} \\ + |\ShowDocumentCommandArgSpec| \arg{cmd} \\ |\ShowDocumentEnvironmentArgSpec| \arg{environment} \end{decl} These functions show the current argument specification for the -requested \meta{function} or \meta{environment} at the terminal. If -the \meta{function} or \meta{environment} has no known argument +requested \meta{cmd} or \meta{environment} at the terminal. If +the \meta{cmd} or \meta{environment} has no known argument specification then an error is issued. -\section{Copying and showing (robust) commands} +\section{Copying and showing (robust) commands and environments} If you want to (slightly) alter an existing command you may want to save the current definition under a new name and then use that in a @@ -911,9 +949,6 @@ token but need \enquote{constructing}, you can use \cs{ExpandArgs} as explained in Section~\ref{sec:preconstructing-csnames}. - - - \begin{decl} |\ShowCommand| \arg{cmd} \end{decl} @@ -926,6 +961,26 @@ also the actual payload code and in case of commands declared with \cs{NewDocumentCommand}, etc.\ it also gives you detailed information about the argument signature. +\begin{decl} + |\NewEnvironmentCopy| \arg{env} \arg{existing-env} \\ + |\RenewEnvironmentCopy| \arg{env} \arg{existing-env} \\ + |\DeclareEnvironmentCopy| \arg{env} \arg{existing-env} +\end{decl} + +This copies the definition for environment \meta{existing-env} to +\meta{env} (both the beginning and end code), i.e., it is simply +applying \cs{NewCommandCopy} twice to the internal commands that +define an environment, i.e., \cs{}\meta{env} and \cs{end}\meta{env}. +The differences between \cs{New...}, \cs{Renew...}, and +\cs{Declare...} are the usual ones. + +\begin{decl} + |\ShowEnvironment| \arg{env} +\end{decl} +This displays the meaning of the begin end end code for environment \meta{env}. + + + \section[Preconstructing command names \\ (or otherwise expanding arguments)] {Preconstructing command names (or otherwise expanding arguments)} @@ -1132,11 +1187,11 @@ therefore shows the same syntax peculiars as discussed above. Nevertheless, in practice they are usually sufficient. For example \begin{verbatim} -\newcommand\calulateheight[1]{% +\newcommand\calculateheight[1]{% \setlength\textheight{\dimeval{\topskip+\baselineskip*\inteval{#1-1}}}} \end{verbatim} sets the \cs{textheight} to the appropriate value if a page should -hold a specific number of text lines. Thus after |\calulateheight{40}| +hold a specific number of text lines. Thus after |\calculateheight{40}| it is set to \dimeval{\topskip+\baselineskip*\inteval{40-1}}, given the values \cs{topskip} (\dimeval{\topskip}) and \cs{baselineskip} (\dimeval{\baselineskip}) in the current document. @@ -1199,8 +1254,35 @@ cases \item Lowercasing \item Titlecasing (only applies for the start of the input) \end{itemize} + The command \cs{DeclareCaseChangeEquivalent} provides a way to substitute a command by an alternative version when it is found inside a case changing -situation. +situation. There are three commands for customising the case changing of +codepoints +\begin{decl} + |\DeclareLowercaseMapping| \oarg{locale} \arg{codepoint} \arg{output} \\ + |\DeclareTitlecaseMapping| \oarg{locale} \arg{codepoint} \arg{output} \\ + |\DeclareUppercaseMapping| \oarg{locale} \arg{codepoint} \arg{output} +\end{decl} +All three take a \meta{codepoint} (as an integer expression) and will +result in the \meta{output} being produced under the appropriate case changing +operation. The optional \meta{locale} can be given if the mapping should only +apply to a specific one: this is given in BCP-47 format +(\url{https://en.wikipedia.org/wiki/IETF_language_tag}). For example, +the kernel customises the mapping for U+01F0 (\v{j}) when uppercasing in +8-bit engines: +\begin{quotation} + |\DeclareUppercaseMapping{"01F0}{\v{J}}| +\end{quotation} +as there is no pre-composed \v{J} character, and this is problematic if +the engine does not support Unicode natively. Similarly, to set a locale +\texttt{xx} to behave in the same way as Turkish and retain the difference +between dotted- and dotless-i, one could use for example +\begin{quotation} + |\DeclareLowercaseMapping[xx]{"0049}{\i}|\\ + |\DeclareLowercaseMapping[xx]{"0130}{i}|\\ + |\DeclareUppercaseMapping[xx]{"0069}{\.{I}}|\\ + |\DeclareUppercaseMapping[xx]{"0131}{I}| +\end{quotation} \end{document} diff --git a/macros/latex/base/utf8ienc.dtx b/macros/latex/base/utf8ienc.dtx index a2b25fd3ab..f1623ee0e6 100644 --- a/macros/latex/base/utf8ienc.dtx +++ b/macros/latex/base/utf8ienc.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % The LaTeX Project and any individual authors listed elsewhere % in this file. % diff --git a/macros/latex/base/utf8ienc.pdf b/macros/latex/base/utf8ienc.pdf Binary files differindex 5ada2a0c2f..0ebe463aa7 100644 --- a/macros/latex/base/utf8ienc.pdf +++ b/macros/latex/base/utf8ienc.pdf diff --git a/macros/latex/base/webcomp.pdf b/macros/latex/base/webcomp.pdf Binary files differindex 18aaaf71db..67c9d3aa62 100644 --- a/macros/latex/base/webcomp.pdf +++ b/macros/latex/base/webcomp.pdf diff --git a/macros/latex/required/amsmath/README.md b/macros/latex/required/amsmath/README.md index 1bc1702484..267418fc5c 100644 --- a/macros/latex/required/amsmath/README.md +++ b/macros/latex/required/amsmath/README.md @@ -1,7 +1,7 @@ The amsmath bundle for LaTeX ============================ -Release 2022-06-01 +Release 2023-06-01 Overview -------- @@ -77,5 +77,5 @@ version 1.3c or later. ----- <p>Copyright (C) 2001-2004, 2007, 2008, 2010, 2011, 2013 American Mathematical Society. <br /> -<p>Copyright (C) 2016-2022 The LaTeX Project and American Mathematical Society. <br /> +<p>Copyright (C) 2016-2023 The LaTeX Project and American Mathematical Society. <br /> diff --git a/macros/latex/required/amsmath/amsbsy.ins b/macros/latex/required/amsmath/amsbsy.ins index c35a72dad6..62b4e9a67c 100644 --- a/macros/latex/required/amsmath/amsbsy.ins +++ b/macros/latex/required/amsmath/amsbsy.ins @@ -26,7 +26,7 @@ \preamble Copyright (C) 1995, 1999 American Mathematical Society. -Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsbsy.pdf b/macros/latex/required/amsmath/amsbsy.pdf Binary files differindex e85825b6f9..fd67fc9cfa 100644 --- a/macros/latex/required/amsmath/amsbsy.pdf +++ b/macros/latex/required/amsmath/amsbsy.pdf diff --git a/macros/latex/required/amsmath/amscd.dtx b/macros/latex/required/amsmath/amscd.dtx index 1ed5be6b67..85475708cc 100644 --- a/macros/latex/required/amsmath/amscd.dtx +++ b/macros/latex/required/amsmath/amscd.dtx @@ -2,7 +2,7 @@ % \iffalse meta-comment % % Copyright (C) 1995, 1999 American Mathematical Society. -% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amscd.ins b/macros/latex/required/amsmath/amscd.ins index 5ecf051583..56aedca375 100644 --- a/macros/latex/required/amsmath/amscd.ins +++ b/macros/latex/required/amsmath/amscd.ins @@ -1,6 +1,6 @@ %% %% Copyright (C) 2010 American Mathematical Society. -%% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3c @@ -25,7 +25,7 @@ \preamble Copyright (C) 1995, 1999 American Mathematical Society. -Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amscd.pdf b/macros/latex/required/amsmath/amscd.pdf Binary files differindex c0ecd2961b..823a98bdd7 100644 --- a/macros/latex/required/amsmath/amscd.pdf +++ b/macros/latex/required/amsmath/amscd.pdf diff --git a/macros/latex/required/amsmath/amsgen.dtx b/macros/latex/required/amsmath/amsgen.dtx index 0493940071..6c4aefed67 100644 --- a/macros/latex/required/amsmath/amsgen.dtx +++ b/macros/latex/required/amsmath/amsgen.dtx @@ -2,7 +2,7 @@ % \iffalse meta-comment % % Copyright (C) 1995, 1999 American Mathematical Society. -% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsgen.ins b/macros/latex/required/amsmath/amsgen.ins index 7d845e61cf..faef4aa275 100644 --- a/macros/latex/required/amsmath/amsgen.ins +++ b/macros/latex/required/amsmath/amsgen.ins @@ -25,7 +25,7 @@ \preamble Copyright (C) 1995, 1999 American Mathematical Society. -Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsgen.pdf b/macros/latex/required/amsmath/amsgen.pdf Binary files differindex 014feb8d2a..2fd862962b 100644 --- a/macros/latex/required/amsmath/amsgen.pdf +++ b/macros/latex/required/amsmath/amsgen.pdf diff --git a/macros/latex/required/amsmath/amsldoc.pdf b/macros/latex/required/amsmath/amsldoc.pdf Binary files differindex dd7061eac5..f9f7824c1f 100644 --- a/macros/latex/required/amsmath/amsldoc.pdf +++ b/macros/latex/required/amsmath/amsldoc.pdf diff --git a/macros/latex/required/amsmath/amsldoc.tex b/macros/latex/required/amsmath/amsldoc.tex index 4a8230e39f..5c4b9e0d89 100644 --- a/macros/latex/required/amsmath/amsldoc.tex +++ b/macros/latex/required/amsmath/amsldoc.tex @@ -1,6 +1,6 @@ % % Copyright (C) 1995, 2000, 2013 American Mathematical Society. -% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsmath.dtx b/macros/latex/required/amsmath/amsmath.dtx index 34d17b65f0..bf8aa418df 100644 --- a/macros/latex/required/amsmath/amsmath.dtx +++ b/macros/latex/required/amsmath/amsmath.dtx @@ -2,7 +2,7 @@ % \iffalse meta-comment % % Copyright (C) 1995, 2000, 2013 American Mathematical Society. -% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c @@ -86,7 +86,7 @@ Bug reports can be opened (category \texttt{#1}) at\\% % \end{macrocode} % % \begin{macrocode} -\ProvidesPackage{amsmath}[2022/04/08 v2.17n AMS math features] +\ProvidesPackage{amsmath}[2023/05/13 v2.17o AMS math features] % \end{macrocode} % % \section{Catcode defenses} @@ -6261,9 +6261,10 @@ Cannot use `split' here;\MessageBreak trying to recover with `aligned'}% % Standard \latex/ provides three environments for one-line equations: % \cn{[}\cn{]}, \env{equation}, and \env{displaymath}. We add % \env{equation*} as a synonym for \env{displaymath}. +% \changes{v2.17o}{2023/05/13}{Do not error if \cs{eqno} not primitive (gh/1059)} % \begin{macrocode} -\@saveprimitive\leqno\@@leqno -\@saveprimitive\eqno\@@eqno +\let\@@eqno\eqno +\let\@@leqno\leqno \def\eqno{\@@eqno\let\eqno\relax\let\leqno\relax} \def\leqno{\@@leqno\let\leqno\relax\let\eqno\relax} % diff --git a/macros/latex/required/amsmath/amsmath.ins b/macros/latex/required/amsmath/amsmath.ins index 82876ffc5d..f92839f959 100644 --- a/macros/latex/required/amsmath/amsmath.ins +++ b/macros/latex/required/amsmath/amsmath.ins @@ -1,6 +1,6 @@ %% %% Copyright (C) 2010 American Mathematical Society. -%% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3c @@ -25,7 +25,7 @@ \preamble Copyright (C) 1995, 1999, 2000, 2013 American Mathematical Society. -Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsmath.pdf b/macros/latex/required/amsmath/amsmath.pdf Binary files differindex 806926ebc0..43358382aa 100644 --- a/macros/latex/required/amsmath/amsmath.pdf +++ b/macros/latex/required/amsmath/amsmath.pdf diff --git a/macros/latex/required/amsmath/amsopn.dtx b/macros/latex/required/amsmath/amsopn.dtx index 110a5fa8be..b089749c17 100644 --- a/macros/latex/required/amsmath/amsopn.dtx +++ b/macros/latex/required/amsmath/amsopn.dtx @@ -2,7 +2,7 @@ % \iffalse meta-comment % % Copyright (C) 1995, 1999 American Mathematical Society. -% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsopn.ins b/macros/latex/required/amsmath/amsopn.ins index 8a57404c1e..859e3d7e5a 100644 --- a/macros/latex/required/amsmath/amsopn.ins +++ b/macros/latex/required/amsmath/amsopn.ins @@ -1,6 +1,6 @@ %% %% Copyright (C) 2010 American Mathematical Society. -%% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3c @@ -25,7 +25,7 @@ \preamble Copyright (C) 1995, 1999 American Mathematical Society. -Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsopn.pdf b/macros/latex/required/amsmath/amsopn.pdf Binary files differindex 0c1f60fd38..afe2d02c11 100644 --- a/macros/latex/required/amsmath/amsopn.pdf +++ b/macros/latex/required/amsmath/amsopn.pdf diff --git a/macros/latex/required/amsmath/amstext.dtx b/macros/latex/required/amsmath/amstext.dtx index 7498040214..a4bc541d34 100644 --- a/macros/latex/required/amsmath/amstext.dtx +++ b/macros/latex/required/amsmath/amstext.dtx @@ -2,7 +2,7 @@ % \iffalse meta-comment % % Copyright (C) 1995, 1999 American Mathematical Society. -% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amstext.ins b/macros/latex/required/amsmath/amstext.ins index 3ba3000eb8..11ed56cc3c 100644 --- a/macros/latex/required/amsmath/amstext.ins +++ b/macros/latex/required/amsmath/amstext.ins @@ -1,6 +1,6 @@ %% %% Copyright (C) 2010 American Mathematical Society. -%% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3c @@ -25,7 +25,7 @@ \preamble Copyright (C) 1995, 1999 American Mathematical Society. -Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amstext.pdf b/macros/latex/required/amsmath/amstext.pdf Binary files differindex bc92eb847d..6af69a0585 100644 --- a/macros/latex/required/amsmath/amstext.pdf +++ b/macros/latex/required/amsmath/amstext.pdf diff --git a/macros/latex/required/amsmath/amsxtra.dtx b/macros/latex/required/amsmath/amsxtra.dtx index c2bc4bbd26..a1f2c6686c 100644 --- a/macros/latex/required/amsmath/amsxtra.dtx +++ b/macros/latex/required/amsmath/amsxtra.dtx @@ -2,7 +2,7 @@ % \iffalse meta-comment % % Copyright (C) 1995, 1999 American Mathematical Society. -% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsxtra.ins b/macros/latex/required/amsmath/amsxtra.ins index 70f50c6bcb..4707222513 100644 --- a/macros/latex/required/amsmath/amsxtra.ins +++ b/macros/latex/required/amsmath/amsxtra.ins @@ -1,6 +1,6 @@ %% %% Copyright (C) 2010 American Mathematical Society. -%% Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +%% Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3c @@ -25,7 +25,7 @@ \preamble Copyright (C) 1995, 1999 American Mathematical Society. -Copyright (C) 2016-2022 LaTeX Project and American Mathematical Society. +Copyright (C) 2016-2023 LaTeX Project and American Mathematical Society. This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c diff --git a/macros/latex/required/amsmath/amsxtra.pdf b/macros/latex/required/amsmath/amsxtra.pdf Binary files differindex 6074bb822e..da423751ec 100644 --- a/macros/latex/required/amsmath/amsxtra.pdf +++ b/macros/latex/required/amsmath/amsxtra.pdf diff --git a/macros/latex/required/amsmath/changes.txt b/macros/latex/required/amsmath/changes.txt index 83d6c6e3a1..149da6b425 100644 --- a/macros/latex/required/amsmath/changes.txt +++ b/macros/latex/required/amsmath/changes.txt @@ -3,6 +3,14 @@ All changes above are only part of the development branch for the next release. ================================================================================ ######################### +# 2023-06-01 Release +######################### + +2023-05-13 David Carlisle <David.Carlisle@latex-project.org> + + * amsmath.dtx: Adjust the definition of \@@eqno (gh/1059) + +######################### # 2022-06-01 Release ######################### diff --git a/macros/latex/required/amsmath/subeqn.pdf b/macros/latex/required/amsmath/subeqn.pdf Binary files differindex 28c721c6f2..ecd2007fc4 100644 --- a/macros/latex/required/amsmath/subeqn.pdf +++ b/macros/latex/required/amsmath/subeqn.pdf diff --git a/macros/latex/required/amsmath/technote.pdf b/macros/latex/required/amsmath/technote.pdf Binary files differindex 6a8c594364..737227c298 100644 --- a/macros/latex/required/amsmath/technote.pdf +++ b/macros/latex/required/amsmath/technote.pdf diff --git a/macros/latex/required/amsmath/testmath.pdf b/macros/latex/required/amsmath/testmath.pdf Binary files differindex 8aef17f9ef..3fe7a82152 100644 --- a/macros/latex/required/amsmath/testmath.pdf +++ b/macros/latex/required/amsmath/testmath.pdf diff --git a/macros/latex/required/firstaid/changes.txt b/macros/latex/required/firstaid/changes.txt index 3c6cb992c8..e326957807 100644 --- a/macros/latex/required/firstaid/changes.txt +++ b/macros/latex/required/firstaid/changes.txt @@ -1,3 +1,24 @@ +2023-05-20 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * latex2e-first-aid-for-external-files.dtx: removed temporary fix for + GitHub issue 591, unneeded now and it breaks for luatex the fix for gh 989 + (minipage/list spacing) + +2022-12-06 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * latex2e-first-aid-for-external-files.dtx (subsection{the crop package first aid}): + A first aid for crop after changes to \rlap and \stockwidth/\stockheight + +2022-11-28 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * latex2e-first-aid-for-external-files.dtx (subsection{the songs package first aid}): + A first aid for songs after a change to \obeylines + +2022-11-04 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * latex2e-first-aid-for-external-files.dtx (subsection{The unicode-math package first aid}): + A first aid for unicode-math used together with the doc package. + 2022-10-27 Joseph Wright <Joseph.Wright@latex-project.org> * latex2e-first-aid-for-external-files.dtx: diff --git a/macros/latex/required/firstaid/latex2e-first-aid-for-external-files.dtx b/macros/latex/required/firstaid/latex2e-first-aid-for-external-files.dtx index 9bc4969b2c..90958ed777 100644 --- a/macros/latex/required/firstaid/latex2e-first-aid-for-external-files.dtx +++ b/macros/latex/required/firstaid/latex2e-first-aid-for-external-files.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: latex2e-first-aid-for-external-files.dtx (C) Copyright 2020-2022 +%% File: latex2e-first-aid-for-external-files.dtx (C) Copyright 2020-2023 %% %% The LaTeX Project and any individual authors listed elsewhere %% in this file. @@ -65,7 +65,7 @@ % % For that reason, it is put into a separate bundle so that we can % update it easily without requiring the CTAN maintainers to -% install a new full LaTeX system just because we take out (or add) +% install a new full \LaTeX{} system just because we take out (or add) % a fix for a package here. % % In the best case scenario the file documented here should be @@ -111,8 +111,8 @@ % \end{macrocode} % % \begin{macrocode} -\def\LaTeXFirstAidDate{2022/10/29} -\def\LaTeXFirstAidVersion{v1.0u} +\def\LaTeXFirstAidDate{2023/05/20} +\def\LaTeXFirstAidVersion{v1.0z} % \end{macrocode} % % \begin{macrocode} @@ -353,6 +353,20 @@ % \end{macrocode} % % +% \subsection{The \pkg{unicode-math} package first aid} +% +% If \pkg{unicode-math} is used together with \pkg{doc} there is a +% problem because it changes the mathcodes without adjusting the +% use in \pkg{doc} that assume standard settings. Could be fixed on +% either side, but as \pkg{unicode-math} is derivating from the +% standard, the right place is probably a fix in this package. For +% now we do it here. See github/820. +% \begin{macrocode} +\AddToHook{package/unicode-math/after}{% + \AddToHook{cmd/mod@math@codes/after}{\mathcode`\|=28796 }} +% \end{macrocode} +% +% % % % \subsection{The \pkg{pgfpages} and \pkg{pgfmorepages} first aid} @@ -411,13 +425,62 @@ \AddToHook{file/babel.sty/before}[firstaid]{\def\BabelCaseHack{}} % \end{macrocode} % -% \begin{macrocode} -%</kernel> -% \end{macrocode} % +% \subsection{The \pkg{songs} package first aid} % +% The songs package uses \cs{obeylines} and redefines \cs{par} for special effect. +% this no longer works in \LaTeX{} 2022-06-01 (gh issue 367). The following +% fixes at least one failure. +% \begin{macrocode} +\AddToHook{file/songs.sty/after}[firstaid]{% + \FirstAidNeededT{songs}{sty}{2018/09/12 v3.1 Songs package}% + {% + \renewcommand\SB@obeylines{% + \let\obeyedline\SB@par% + \obeylines% + \let\@par\SB@@par% + }}% +} +% \end{macrocode} % +% \subsection{The \pkg{crop} package first aid} % +% The crop packages fails currently due to two \LaTeX{} changes: +% It doesn't know that \cs{stockheight} and \cs{stockwidth} +% are now defined, and doesn't take into account that \cs{rlap} +% is robust (https://github.com/rrthomas/crop/issues/2). +% The first is addressed by setting the dimension if they are zero or +% negative. For the second we locally change the meaning of \cs{protect} +% +% \begin{macrocode} +\AddToHook{file/crop.sty/after}[firstaid]{% + \FirstAidNeededT{crop}{sty}{2017/11/19 1.10 crop marks (mf)}% + {% + \ifdim\stockwidth > 0pt \else \stockwidth\paperwidth \fi + \ifdim\stockheight > 0pt \else \stockheight\paperheight \fi + \renewcommand*\CROP@genreflect[1]{% + \leavevmode + \dimen0\CROP@horigin + \kern2\dimen0 + \begingroup + \set@typeset@protect %change protect + \reflectbox{% + \hb@xt@\paperwidth{% + \vbox to\paperheight{% + #1% + \vss + }% + \hss + }% + }% + \endgroup + } + }% +} +% \end{macrocode} +% \begin{macrocode} +%</kernel> +% \end{macrocode} % % \subsection{The \pkg{everysel} package first aid} % @@ -612,63 +675,6 @@ % \end{macrocode} % % -% \subsection[Temporary fixes for the kernel (until the next -% patch-level release)] -% {Temporary fixes for the kernel \\ -% (until the next patch-level release)} -% -% This fixes GitHub issue 591. It is only needed in Lua\TeX\ and replaces just one -% instance of \cs{tex\_par:D} with the following version which removes -% other nodes in the current list first. -% \begin{macrocode} -\ExplSyntaxOn -\sys_if_engine_luatex:T - { - \newluafunction \g__para_end_empty_par_id_int - \exp_args:Nx \everyjob { - \exp_not:V \everyjob - \exp_not:N \lua_now:n { - local~texnest, flush_list, par_token = tex.nest, node.flush_list, token.create'tex_par:D'~ - lua.get_functions_table()[\int_use:N \g__para_end_empty_par_id_int] = function() - local~nest_level = texnest.top~ - local~cur_head = nest_level.head~ - flush_list(cur_head.next) - nest_level.tail, cur_head.next = cur_head, nil~ - token.put_next(par_token) - end - } - } - \protected \luadef \__para_end_empty_par: \g__para_end_empty_par_id_int - \group_begin: - \cs_set:Npn \__para_extract_everypar:w #1 \the \toks #2 \s_stop - { - \tl_gset:Nn \g__para_standard_everypar_tl { - \box_gset_to_last:N \g_para_indent_box - \group_begin: - \__para_end_empty_par: - \group_end: - \tex_everypar:D { \msg_error:nnnn { hooks }{ para-mode }{before}{vertical} } - \@kernel@before@para@before - \hook_use:n {para/before} - \group_begin: - \tex_everypar:D {} - \skip_zero:N \tex_parskip:D - \tex_noindent:D - \group_end: - \tex_everypar:D{\g__para_standard_everypar_tl} - \@kernel@before@para@begin - \hook_use:n {para/begin} - \if_mode_horizontal: \else: - \msg_error:nnnn { hooks }{ para-mode }{begin}{vertical} \fi: - \__para_handle_indent: - \the \toks #2 - } - } - \exp_last_unbraced:No \__para_extract_everypar:w \g__para_standard_everypar_tl \s_stop - \group_end: - } -\ExplSyntaxOff -% \end{macrocode} % % % \begin{macrocode} diff --git a/macros/latex/required/firstaid/latex2e-first-aid-for-external-files.pdf b/macros/latex/required/firstaid/latex2e-first-aid-for-external-files.pdf Binary files differindex 6523046f58..14434f3755 100644 --- a/macros/latex/required/firstaid/latex2e-first-aid-for-external-files.pdf +++ b/macros/latex/required/firstaid/latex2e-first-aid-for-external-files.pdf diff --git a/macros/latex/required/latex-lab/README.md b/macros/latex/required/latex-lab/README.md index 7f1a275794..dbb1e72f42 100644 --- a/macros/latex/required/latex-lab/README.md +++ b/macros/latex/required/latex-lab/README.md @@ -1,6 +1,6 @@ # LaTeX laboratory -Release 2022-11-01 +Release 2023-06-01 ## Overview @@ -38,5 +38,5 @@ The license is LPPL 1.3c. This README file is -Copyright (C) 2021-2022 +Copyright (C) 2021-2023 The LaTeX Project diff --git a/macros/latex/required/latex-lab/TODOS-unsorted.md b/macros/latex/required/latex-lab/TODOS-unsorted.md new file mode 100644 index 0000000000..1e2771ae67 --- /dev/null +++ b/macros/latex/required/latex-lab/TODOS-unsorted.md @@ -0,0 +1,33 @@ + +# A number of todos (unsorted and incomplete) + + +## Code extensions / cleanup + +### theorem-like envs + + - this can currently only handle the simple version from LaTeX2e + - it is missing a proper set of templates + - it is missing extensions to support different styles (a la amsmath and the like) + + +## Missing basic support + + - `\textbf` should probably mapt to `<Strong>` + - `\emph` should probably map to `<Em>` + + - Logos such as `\TeX` and `\LaTeX` should produce proper ActualText + + + + +## Package Support + +### csquotes + + - we can't really grab TeX's basic quotes, e.g. + ``` + some quotes around ``text'' here +``` + at least not easily, but we can support `\enquote` and the like + diff --git a/macros/latex/required/latex-lab/blocks-code.pdf b/macros/latex/required/latex-lab/blocks-code.pdf Binary files differnew file mode 100644 index 0000000000..efd9930bfe --- /dev/null +++ b/macros/latex/required/latex-lab/blocks-code.pdf diff --git a/macros/latex/required/latex-lab/blocks-code.tex b/macros/latex/required/latex-lab/blocks-code.tex new file mode 100644 index 0000000000..f71342d6f5 --- /dev/null +++ b/macros/latex/required/latex-lab/blocks-code.tex @@ -0,0 +1,4 @@ +% this will typeset documentation + code + +\AtBeginDocument{\AlsoImplementation} +\input{latex-lab-block-tagging.dtx} diff --git a/macros/latex/required/latex-lab/blocks-doc.pdf b/macros/latex/required/latex-lab/blocks-doc.pdf Binary files differnew file mode 100644 index 0000000000..4bbad5d393 --- /dev/null +++ b/macros/latex/required/latex-lab/blocks-doc.pdf diff --git a/macros/latex/required/latex-lab/blocks-doc.tex b/macros/latex/required/latex-lab/blocks-doc.tex new file mode 100644 index 0000000000..39a93479a1 --- /dev/null +++ b/macros/latex/required/latex-lab/blocks-doc.tex @@ -0,0 +1,4 @@ +% this will typeset documentation + code + +\AtBeginDocument{\OnlyDescription} +\input{latex-lab-block-tagging.dtx} diff --git a/macros/latex/required/latex-lab/changes.txt b/macros/latex/required/latex-lab/changes.txt index b4b4df9811..7e76d74996 100644 --- a/macros/latex/required/latex-lab/changes.txt +++ b/macros/latex/required/latex-lab/changes.txt @@ -1,3 +1,86 @@ +2023-06-07 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * latex-lab-block-tagging.dtx corrected tagging of caption + * new latex-lab-firstaid.dtx with adaptions to external packages + * latex-lab-float.dtx: declare variable + * latex-lab-toc-hyperref-changes: use hooks with arguments + * latex-lab-toc-kernel-changes: use hooks with arguments + * latex-lab-sec.dtx: provide \pdfgentounicode with lualatex + +2023-05-20 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * renamed latex-lab-sec-tagging -> latex-lab-sec for consistency + + +2023-05-19 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * new latex-lab-bib.dtx: + tagging support for cite and bibliography with standard LaTeX and natbib + * small corrections/adaptions in latex-lab-sec-tagging and latex-lab-toc-tagging + +2023-05-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * new latex-lab-floats.dtx: + tagging support for float environments + * new latex-lab-graphic.dtx + tagging support for includegraphics and picture environment + * new latex-lab-minipage.dtx + tagging support for minipage and parbox + +2023-05-16 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * latex-lab-block-tagging.dtx (subsubsection{Verbatim instances}): + verbatim environments get their own block instances so that they can receive + special formatting instructions. + This also fixes a bug that we forgot to set par-skip to 0pt by default (tagpdf/74) + + (paragraph{Helper commands for verbatim}): + The \legacyverbatimsetup command needs to execute \@@par inside a group, because + we need to preserve any outer setup to \parshape (tagpdf/79) + +2023-04-09 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * latex-lab-sec-tagging.dtx: + don't load extra glyphtounicode if \pdfglyphtounicode is not defined. + +2023-04-09 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * latex-lab-footnotes.dtx: + made \footnote and \footnotetext long + + +2023-03-08 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * latex-lab-block-tagging.dtx: + Added the support for tagging display blocks and corresponding environments + such as lists, quotes, verbatim, theorem-like envs, ... + +2023-03-07 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * tagpdf updated + * improved glyphtounicode support for luatex and math + * adapted toc and sec tagging code to new two-level paragraph handling + and block tagging code + +2023-02-16 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * latex-lab-sec-tagging.dtx: first, simple tagging of sectioning commands + * latex-lab-toc-tagging-functions.dtx, latex-lab-toc-kernel-changes.dtx, + latex-lab-toc-kernel-changes.dtx: Tagging of table of contents and similar + lists + * tagpdf and pdfmanagement updated in texmf tree. + + +2023-02-04 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * latex-lab-footnotes.dtx: improve tagging of footnotes + +2022-12-11 Joseph Wright <Joseph.Wright@latex-project.org> + + * latex-lab-mathcapture.dtx + New file to implement grabbing of math mode context + +2022-04-11 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * documentmeta-support.dtx: + updated documentation + * moved output patches from pdfresources to latex-lab-new-or-1 + * reorganized new-or: number subfiles as new-or-1, new-or-2 and load all with new-or. + 2022-07-22 Frank Mittelbach <Frank.Mittelbach@latex-project.org> * latex-lab-footnotes.dtx (subsection{Document-level commands}): diff --git a/macros/latex/required/latex-lab/documentmetadata-support-code.pdf b/macros/latex/required/latex-lab/documentmetadata-support-code.pdf Binary files differindex 2e999dd268..bf0d11a71a 100644 --- a/macros/latex/required/latex-lab/documentmetadata-support-code.pdf +++ b/macros/latex/required/latex-lab/documentmetadata-support-code.pdf diff --git a/macros/latex/required/latex-lab/documentmetadata-support-doc.pdf b/macros/latex/required/latex-lab/documentmetadata-support-doc.pdf Binary files differindex ac5c23a86a..ce81773be5 100644 --- a/macros/latex/required/latex-lab/documentmetadata-support-doc.pdf +++ b/macros/latex/required/latex-lab/documentmetadata-support-doc.pdf diff --git a/macros/latex/required/latex-lab/documentmetadata-support.dtx b/macros/latex/required/latex-lab/documentmetadata-support.dtx index 23053a484a..0dccdd87cb 100644 --- a/macros/latex/required/latex-lab/documentmetadata-support.dtx +++ b/macros/latex/required/latex-lab/documentmetadata-support.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment % %% File: documentmetadata-support.dtx -% Copyright (C) 2021-2022 The LaTeX Project +% Copyright (C) 2021-2023 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -18,8 +18,8 @@ % for those people who are interested or want to report an issue. % % \begin{macrocode} -\def\documentmetadatasupportversion{1.0b} -\def\documentmetadatasupportdate{2022-14-04} +\def\documentmetadatasupportversion{1.0d} +\def\documentmetadatasupportdate{2023-06-07} % \end{macrocode} % % @@ -64,13 +64,19 @@ % While the underlying functionality is still under % development (e.g., further keys will be added over time and keys % marked temporary may vanish again) the code for -% \cs{DocumentMetadata} is place in a separate bundle, so that it +% \cs{DocumentMetadata} is placed in a separate bundle, so that it % is easier to update it without the need to build a full \LaTeX{} % release. Over time the functionality will move fully into the % kernel. +% +% \cs{DocumentMetadata} also loads and activates +% the new PDF management code from \pkg{pdfmanagement-testphase}. +% As this forces the loading of the \pkg{l3backend} files, a backend +% that can't be detected automatically like |dvipdfmx|, +% must be set in the first \cs{DocumentMetadata}. % % From a process perspective \cs{DocumentMetadata} loads the -% \pkg{pdfmanagement} code the first time it is called and then +% \pkg{pdfmanagement-testphase} code the first time it is called and then % redefines itself to only manage key/value pairs in case it is % called more than once. In particular, this means that a document % without a \cs{DocumentMetadata} declaration has no code available @@ -84,10 +90,12 @@ % % % Currently the following keys are implemented for \cs{DocumentMetadata}: +% \DescribeMkey{backend} % \DescribeMkey{colorprofiles} % \DescribeMkey{debug} % \DescribeMkey{lang} % \DescribeMkey{pdfstandard} +% \DescribeMkey{xmp} % \DescribeMkey{pdfversion} % \DescribeMkey{testphase} % \DescribeMkey{uncompress} @@ -110,15 +118,36 @@ % \item[\texttt{pdfstandard}] Choice key to set the pdf standard. % Currently |A-1b|, |A-2a|, |A-2b|, |A-2u|, |A-3a|, |A-3b|, |A-3u| and |A-4| are accepted as % values. The casing is irrelevant, |a-1b| works too. -% The underlying code to ensure the requirements (as far as they -% can be ensured) is still incomplete, but a color profile is included and the -% \texttt{/OutputIntent} is set. The |u| variants for example do not force unicode, -% but they will pass the information to hyperref and hyperxmp. The |a| variants -% do \emph{not} enforce (or even test) a tagged pdf yet. The |A-4| support is -% currently incomplete. +% Note that using these +% key doesn't mean that the document actually follows the standard. \LaTeX{} +% can neither ensure nor check all requirements of a standard, and not everything +% it can do theoretically has already been implemented. +% When setting an A-standard a color profile is included and the +% \texttt{/OutputIntent} is set and javascript action in hyperref are suppressed. +% The |u| variants do not enforce unicode, +% but they will pass the information to hyperref. The |a| variants +% do \emph{not} enforce (or even test) a tagged pdf yet. +% +% Starting with version 0.95s of \pkg{pdfmanagement-testphase} +% it is also possible to use the values +% |X-4|, |X-4p|, |X-5g|, |X-5n|, |X-5pg|, |X-6|, |X-6n|, |X-6p|, |UA-1| for +% a PDF/X and PDF/UA standard. These keys currently set \emph{only} the relevant +% XMP-metadata. In version 0.95z support for |UA-2| has been added but +% note that |UA-2| hasn't been released yet. It should be used only together +% with pdf version 2.0. +% +% |pdfstandard| can be used more than once to set overlapping standards, e.g:\\ +% |pdfstandard=A-2b,pdfstandard=X-4,pdfstandard=UA-1| +% +% If XMP-metadata are added (see the following key \texttt{xmp} +% the needed conformance marker for the standards are set. +% % More information can be found in the documentation -% of \pkg{l3pdfmeta}. +% of \pkg{l3pdfmeta}. % +% \item[\texttt{xmp}] A boolean, if set to false no XMP metadata are added to the PDF. +% The initial value is true. Details are described in the documentation of \pkg{l3pdfmeta}. +% % \item[\texttt{colorprofiles}] This allows to load icc-colorprofiles. Details % are described in the documentation of \pkg{l3pdfmeta}. % @@ -132,11 +161,28 @@ % |\tagpdfsetup{activate,interwordspace}|. This phase % is frozen. % \item[\texttt{phase-II}] -% This is the current development phase. -% Currently it differs from \texttt{phase-I} only in one point: It will +% It differs from \texttt{phase-I} only in one point: It will % additionally activate tagging of paragraphs with % |\tagpdfsetup{paratagging}|. In the upcoming months it will % also enable automatic tagging of other basic document elements. +% \item[\texttt{phase-III}] +% This is the current development phase. +% It differs from \texttt{phase-II} \emph{a lot}: It will +% load new code for the tagging of lists, sectioning commands, +% table of contents and similar lists, graphics, minipages and floats. +% As it redefines many internals it is currently restricted to the use of +% standard classes (article, report, and book) +% and it supports only a limited number of add-on packages. +% \item[\texttt{new-or-1}] This patches a few commands related +% to the output routine. The patches are needed for the tagging +% of paragraphs, for the tagging of header and footer and +% to allow the PDF management to insert code which avoids that +% links happening at page breaks spills into the header and footer. +% This code is automatically loaded if the \texttt{testphase} values +% \texttt{phase-I}, \texttt{phase-II} or \texttt{new-or} are used.% +% \item[\texttt{new-or}] This loads more changes to the output routine required for the +% tagging. It is not compatible with every class! The code is also loaded by the +% \texttt{phase-II} value. % \end{description} % The |testphase| key can only be used in the first \cs{DocumentMetadata}. % @@ -151,6 +197,10 @@ % \item[\texttt{firstaidoff}] This accepts a comma lists of keywords and disables the patches % related to them. More information can be found in the documentation of % \pkg{pdfmanagement-firstaid}. +% \item[\texttt{xmp-export}] This will export the XMP-metadata to a file \verb+\jobname.xmpi+. +% with \texttt{debug=\{xmp-export=filename\}} the file name can be changed. +% More information can be found in the documentation of \pkg{l3pdfmeta} of the \pkg{pdfmanagement-testphase} +% bundle. % \end{description} % \end{description} % diff --git a/macros/latex/required/latex-lab/glyphtounicode-cmex.tex b/macros/latex/required/latex-lab/glyphtounicode-cmex.tex new file mode 100644 index 0000000000..2b5c1d979d --- /dev/null +++ b/macros/latex/required/latex-lab/glyphtounicode-cmex.tex @@ -0,0 +1,141 @@ +% A subset of glyhtounicode-cmr.tex +% +% Copyright (c) 2008, Han The Thanh <thanh@river-valley.org> +% Copyright (c) 2014, Peter Selinger <selinger@mathstat.dal.ca> +% Copyright (c) 2018, Ross Moore <ross.moore@mq.edu.au> +% + +%% Glyphs from the cmex fonts: + +\pdfglyphtounicode{angbracketleftBig}{27E8 FE02} +\pdfglyphtounicode{angbracketleftBigg}{27E8 FE04} +\pdfglyphtounicode{angbracketleftbig}{27E8 FE01} +\pdfglyphtounicode{angbracketleftbigg}{27E8 FE03} +\pdfglyphtounicode{angbracketrightBig}{27E9 FE02} +\pdfglyphtounicode{angbracketrightBigg}{27E9 FE04} +\pdfglyphtounicode{angbracketrightbig}{27E9 FE01} +\pdfglyphtounicode{angbracketrightbigg}{27E9 FE03} +\pdfglyphtounicode{arrowbt}{2193} +\pdfglyphtounicode{arrowdblbt}{21D3} +\pdfglyphtounicode{arrowdbltp}{21D1} +\pdfglyphtounicode{arrowhookleft}{21AA} +\pdfglyphtounicode{arrowhookright}{21A9} +\pdfglyphtounicode{arrowtp}{2191} +\pdfglyphtounicode{arrowvertex}{23D0} +\pdfglyphtounicode{arrowvertexdbl}{20E6}% was {ED12}% PUA +\pdfglyphtounicode{backslashBig}{005C FE02} +\pdfglyphtounicode{backslashBigg}{005C FE04} +\pdfglyphtounicode{backslashbig}{005C FE01} +\pdfglyphtounicode{backslashbigg}{005C FE03} +\pdfglyphtounicode{braceex}{23AA} +\pdfglyphtounicode{bracehtipdownleft}{23DF}% was {ED17}% PUA +\pdfglyphtounicode{bracehtipdownright}{23DF}% was {ED18}% PUA +\pdfglyphtounicode{bracehtipupleft}{23DE}% was {ED19}% PUA +\pdfglyphtounicode{bracehtipupright}{23DE}% was {ED1A}% PUA +\pdfglyphtounicode{braceleftBig}{007B FE02} +\pdfglyphtounicode{braceleftBigg}{007B FE04} +\pdfglyphtounicode{braceleftbig}{007B FE01} +\pdfglyphtounicode{braceleftbigg}{007B FE03} +\pdfglyphtounicode{braceleftbt}{23A9} +\pdfglyphtounicode{braceleftmid}{23A8} +\pdfglyphtounicode{bracelefttp}{23A7} +\pdfglyphtounicode{bracerightBig}{007D FE02} +\pdfglyphtounicode{bracerightBigg}{007D FE04} +\pdfglyphtounicode{bracerightbig}{007D FE01} +\pdfglyphtounicode{bracerightbigg}{007D FE03} +\pdfglyphtounicode{bracerightbt}{23AD} +\pdfglyphtounicode{bracerightmid}{23AC} +\pdfglyphtounicode{bracerighttp}{23AB} +\pdfglyphtounicode{bracketleftBig}{005B FE02} +\pdfglyphtounicode{bracketleftBigg}{005B FE04} +\pdfglyphtounicode{bracketleftbig}{005B FE01} +\pdfglyphtounicode{bracketleftbigg}{005B FE03} +\pdfglyphtounicode{bracketleftbt}{23A3} +\pdfglyphtounicode{bracketleftex}{23A2} +\pdfglyphtounicode{bracketlefttp}{23A1} +\pdfglyphtounicode{bracketrightBig}{005D FE02} +\pdfglyphtounicode{bracketrightBigg}{005D FE04} +\pdfglyphtounicode{bracketrightbig}{005D FE01} +\pdfglyphtounicode{bracketrightbigg}{005D FE03} +\pdfglyphtounicode{bracketrightbt}{23A6} +\pdfglyphtounicode{bracketrightex}{23A5} +\pdfglyphtounicode{bracketrighttp}{23A4} +\pdfglyphtounicode{ceilingleftBig}{2308 FE02} +\pdfglyphtounicode{ceilingleftBigg}{2308 FE04} +\pdfglyphtounicode{ceilingleftbig}{2308 FE01} +\pdfglyphtounicode{ceilingleftbigg}{2308 FE03} +\pdfglyphtounicode{ceilingrightBig}{2309 FE02} +\pdfglyphtounicode{ceilingrightBigg}{2309 FE04} +\pdfglyphtounicode{ceilingrightbig}{2309 FE01} +\pdfglyphtounicode{ceilingrightbigg}{2309 FE03} +\pdfglyphtounicode{circledotdisplay}{2A00 FE02} +\pdfglyphtounicode{circledottext}{2A00 FE01} +\pdfglyphtounicode{circlemultiplydisplay}{2A02 FE02} +\pdfglyphtounicode{circlemultiplytext}{2A02 FE01} +\pdfglyphtounicode{circleplusdisplay}{2A01 FE02} +\pdfglyphtounicode{circleplustext}{2A01 FE01} +\pdfglyphtounicode{contintegraldisplay}{222E FE02} +\pdfglyphtounicode{contintegraltext}{222E FE01} +\pdfglyphtounicode{coproductdisplay}{2210 FE02} +\pdfglyphtounicode{coproducttext}{2210 FE01} +\pdfglyphtounicode{floorleftBig}{230A FE02} +\pdfglyphtounicode{floorleftBigg}{230A FE04} +\pdfglyphtounicode{floorleftbig}{230A FE01} +\pdfglyphtounicode{floorleftbigg}{230A FE03} +\pdfglyphtounicode{floorrightBig}{230B FE02} +\pdfglyphtounicode{floorrightBigg}{230B FE04} +\pdfglyphtounicode{floorrightbig}{230B FE01} +\pdfglyphtounicode{floorrightbigg}{230B FE03} +\pdfglyphtounicode{hatwide}{02C6 FE01} +\pdfglyphtounicode{hatwider}{02C6 FE02} +\pdfglyphtounicode{hatwidest}{02C6 FE03} +\pdfglyphtounicode{integraldisplay}{222B FE02} +\pdfglyphtounicode{integraltext}{222B FE01} +\pdfglyphtounicode{intersectiondisplay}{22C2 FE02} +\pdfglyphtounicode{intersectiontext}{22C2 FE01} +\pdfglyphtounicode{logicalanddisplay}{22C0 FE02} +\pdfglyphtounicode{logicalandtext}{22C0 FE01} +\pdfglyphtounicode{logicalordisplay}{22C1 FE02} +\pdfglyphtounicode{logicalortext}{22C1 FE01} +\pdfglyphtounicode{mapsto}{21A6} +\pdfglyphtounicode{parenleftBig}{0028 FE02} +\pdfglyphtounicode{parenleftBigg}{0028 FE04} +\pdfglyphtounicode{parenleftbig}{0028 FE01} +\pdfglyphtounicode{parenleftbigg}{0028 FE03} +\pdfglyphtounicode{parenleftbt}{239D} +\pdfglyphtounicode{parenleftex}{239C} +\pdfglyphtounicode{parenlefttp}{239B} +\pdfglyphtounicode{parenrightBig}{0029 FE02} +\pdfglyphtounicode{parenrightBigg}{0029 FE04} +\pdfglyphtounicode{parenrightbig}{0029 FE01} +\pdfglyphtounicode{parenrightbigg}{0029 FE03} +\pdfglyphtounicode{parenrightbt}{23A0} +\pdfglyphtounicode{parenrightex}{239F} +\pdfglyphtounicode{parenrighttp}{239E} +\pdfglyphtounicode{productdisplay}{220F FE02} +\pdfglyphtounicode{producttext}{220F FE01} +\pdfglyphtounicode{radicalBig}{221A FE02} +\pdfglyphtounicode{radicalBigg}{221A FE04} +\pdfglyphtounicode{radicalbig}{221A FE01} +\pdfglyphtounicode{radicalbigg}{221A FE03} +\pdfglyphtounicode{radicalbt}{23B7}% was {221A} +\pdfglyphtounicode{radicaltp}{231C}% was {ED6A}% PUA +\pdfglyphtounicode{radicalvertex}{20D3}% was {ED6B}% PUA +\pdfglyphtounicode{slashBig}{002F FE02} +\pdfglyphtounicode{slashBigg}{002F FE04} +\pdfglyphtounicode{slashbig}{002F FE01} +\pdfglyphtounicode{slashbigg}{002F FE03} +\pdfglyphtounicode{summationdisplay}{2211 FE02} +\pdfglyphtounicode{summationtext}{2211 FE01} +\pdfglyphtounicode{tie}{2040} +\pdfglyphtounicode{tildewide}{02DC FE01} +\pdfglyphtounicode{tildewider}{02DC FE02} +\pdfglyphtounicode{tildewidest}{02DC FE03} +\pdfglyphtounicode{uniondisplay}{22C3 FE02} +\pdfglyphtounicode{unionmultidisplay}{2A04 FE02} +\pdfglyphtounicode{unionmultitext}{2A04 FE01} +\pdfglyphtounicode{unionsqdisplay}{2A06 FE02} +\pdfglyphtounicode{unionsqtext}{2A06 FE01} +\pdfglyphtounicode{uniontext}{22C3 FE01} +\pdfglyphtounicode{vextenddouble}{20E6}% was {ED79}% PUA +\pdfglyphtounicode{vextendsingle}{20D3}%%% was {23D0} diff --git a/macros/latex/required/latex-lab/latex-lab-amsmath.dtx b/macros/latex/required/latex-lab/latex-lab-amsmath.dtx new file mode 100644 index 0000000000..e1f95730fa --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-amsmath.dtx @@ -0,0 +1,131 @@ +% \iffalse meta-comment +% +%% File: latex-lab-amsmath.dtx +% +% Copyright (C) 2022,2023 The LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-amsmath.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \texttt{latex-lab-amsmath} code\thanks{}} +% \author{\LaTeX{} Project} +% +% \maketitle +% +% \newcommand\fmi[1]{\begin{quote} TODO: \itshape #1\end{quote}} +% \newcommand\NEW[1]{\marginpar{\mbox{}\hfill\fbox{New: #1}}} +% \providecommand\class[1]{\texttt{#1.cls}} +% \providecommand\pkg[1]{\texttt{#1}} +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% This file implements adaptations to the \pkg{amsmath} package needed for +% the tagging project. +% +% \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } +% +% \section{The Implementation} +% +% \begin{macrocode} +%<@@=math> +% \end{macrocode} +% +% \begin{macrocode} +%<*kernel> +% \end{macrocode} +% +% \subsection{File declaration} +% \begin{macrocode} +\ProvidesFile{latex-lab-amsmath.ltx} + [2023-01-05 v0.1a amsmath adaptions] +% \end{macrocode} +% \subsection{Tagpdf support} +% To make the code independent from tagging being loaded and active +% we load the \pkg{tagpdf-base} package: +% +% \begin{macrocode} +\RequirePackage{tagpdf-base} +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOn +% \end{macrocode} +% +% \subsection{\cs{intertext}} +% The \cs{intertext} command errors with active tagging as it is processed twice +% which leads to duplicated structures. +% \begin{macrocode} +\AddToHook{package/amsmath/after} + { + \def\intertext@{% + \def\intertext##1{% + \ifvmode\else\\\@empty\fi + \noalign{% + \penalty\postdisplaypenalty\vskip\belowdisplayskip + \vbox{ +% \end{macrocode} +% Stop tagging when measuring: +% \begin{macrocode} + \ifmeasuring@\tag_stop:\fi + \normalbaselines + \ifdim\linewidth=\columnwidth + \else \parshape\@ne \@totalleftmargin \linewidth + \fi +% \end{macrocode} +% End the previous mc: +% \begin{macrocode} + \tag_mc_end_push: +% \end{macrocode} +% We are already in a par so we change now to Span: +% \begin{macrocode} + \tagpdfsetup{paratag=Span}% + \noindent\ignorespaces##1\par +% \end{macrocode} +% Restart the MC +% \begin{macrocode} + \tag_mc_begin_pop:n{}}% + \penalty\predisplaypenalty\vskip\abovedisplayskip% + }% + }} + } +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOff +% \end{macrocode} +% +% \begin{macrocode} +%</kernel> +% \end{macrocode} +% +% \Finale +% diff --git a/macros/latex/required/latex-lab/latex-lab-amsmath.pdf b/macros/latex/required/latex-lab/latex-lab-amsmath.pdf Binary files differnew file mode 100644 index 0000000000..9c53d2ba81 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-amsmath.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-bib.dtx b/macros/latex/required/latex-lab/latex-lab-bib.dtx new file mode 100644 index 0000000000..9a5ee81720 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-bib.dtx @@ -0,0 +1,406 @@ +% \iffalse meta-comment +% +%% File: latex-lab-bib.dtx (C) Copyright 2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-bib.dtx} +\end{document} +%</driver> +% +% \fi +% +% \title{The \textsf{latex-lab-bib} package\\ +% Changes and additions to the kernel related to tagging and links in citations and +% bibliography entries} +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{Version 0.81 2023-06-07} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \section{Introduction} +% +% The followings contains small changes to improve tagging of +% bibliography entries and citations. +% +% The tagging of the standard bibliography is actually quite straightforward: +% A bibliography is typically a list with a heading and the code which tags sectioning +% commands and lists handles that. +% +% There are here only two problems: +% +% \begin{itemize} +% \item The structure number of the \texttt{LI} element +% created by a \cs{bibitem} must be recorded somehow to allow to reference it in +% a \cs{cite}. +% \item \pkg{hyperref} redefines the item command and so breaks the list structure +% see \url{https://github.com/latex3/latex2e/discussions/1010#discussioncomment-5565418} +% \end{itemize} +% +% Both problems are rather easy to resolve, but it must be checked if other packages +% interfere again by redefining the commands. +% +% More difficult is the tagging of citation commands. Citations should be inside +% a Reference structure and contain a /Ref entry pointing to the relevant +% item in the bibliography. For simple citations like +% \enquote{[1]} or \enquote{Doody (2023)} this is easy, but it is not obvious how +% to handle combined citations like \enquote{Doody (2003,2018)} (or even compressed citations +% like \enquote{[1-3]}). The current implementation follows the links: whatever hyperref would +% link is set as the reference. +% +% There exist various packages which over the years tried to improve and extend +% the bibliography commands. We discuss here three: natbib, chapterbib and biblatex. +% +% \begin{description} +% \item[natbib] It is rather easy to support natbib: it has hooks for links and the tagging code +% can follow. Only a bit coordination with hyperref is needed to avoid that hyperref +% remove the tagging code again. +% +% \item[chapterbib] In standard LaTeX every bib entry has an unique label which points to the +% (mandatory and unique) bibliography and the target created by hyperref +% has the simple form \texttt{cite.}\meta{key}. +% If a package that support multiple bibliographies is used (e.g. chapterbib) +% this is no longer works: a bib entry \texttt{doody} +% can in one chapter get the label \enquote{[1]} +% and in the other \enquote{[5]} or even \enquote{Doo19} and naturally links +% should jump to the relevant chapter bibliography. chapterbib solves this +% by creating bib keys with a suffix: when reading the \texttt{.aux} files it will +% create the keys \texttt{doody@-1} and \texttt{doody@-2} where the number is related +% to the chapter/include, and in the document and in the document \verb+\cite{doody}+ +% will look for \texttt{doody@-1} and \texttt{doody@-2} depending on the number of the +% current include. For some unknown reason chapterbib uses two commands +% to handle the suffix: the command \cs{@extra@binfo} is written to the aux-files +% and used when processing the \cs{bibcite} commands, +% but in the document \cs{@extra@b@citeb} is used. Supporting this is +% straightforward: one only has to take care that the tagging code uses +% \cs{@extra@b@citeb} in the relevant places too. +% +% \item[biblatex] biblatex supports multiple bibliographies out-of-the-box. +% It numbers the link target by refsection and uses then the name +% \verb+\the\c@refsection @+\meta{key}. +% +% Printing a bibliography is not required, in this case you get an engine warning +% and links jump to the begin of the document: +% \begin{verbatim} +% name{cite.0@doody} has been referenced but does not exist +% \end{verbatim} +% +% Bibliographies can be printed more than once by refsection. To avoid duplicated +% target, biblatex stores the names of the targets in a list and if later +% it detects that a target name has already been used in a +% bibliography no new target is created for this item. This means a citation +% will normally jump to the first bibliography which shows the entry. +% +% The tagging code has to mimic this code. This means that it can't label every item, +% but has to test if this anchor is already known. +% \end{description} +% +% +% \section{Implementation} +% \begin{macrocode} +%<*package> +%<@@=tag> +% \end{macrocode} +% \begin{macrocode} +\ProvidesExplPackage {latex-lab-testphase-bib} {2023-05-18} {0.8} + {Code related to the tagging of bibliography and cite command} +% \end{macrocode} +% We need at least the block tagging code. +% \begin{macrocode} +\RequirePackage{latex-lab-testphase-block-tagging} +% \end{macrocode} +% +% At first we suppress the patches from hyperref. This will only work with the next +% hyperref! +% \begin{macrocode} +\def\hyper@nopatch@bib{} +% \end{macrocode} + +% \begin{macro}{\@extra@binfo,\@extra@b@citeb} +% These are taken from hyperref, they are for chapterbib compability (and also +% signal to chapterbib not to change the citation commands) +% \begin{macrocode} +\providecommand*\@extra@binfo{}% +\providecommand\@extra@b@citeb{} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_@@_bib_citekey_tl} +% We can't pass the cite key everywhere as argument so we store it: +% \begin{macrocode} +\tl_new:N\l_@@_bib_citekey_tl +% \end{macrocode} +% \end{variable} +% +%\subsection{Handling the bibliography} +% \begin{macro}{\@lbibitem} +% The item command if an optional argument is used. +% +% We only prepend some code. +% \begin{macrocode} +\AddToHookWithArguments{cmd/@lbibitem/before} + { +% \end{macrocode} +% we store the target name for the label. +% \begin{macrocode} + \tl_set:Nn\l_@@_bib_citekey_tl{#2} + } +% \end{macrocode} +% The target is added at the begin of the paragraph. We give that a label as +% it perhaps need to be removed by packages +% \begin{macrocode} +\AddToHookWithArguments{cmd/@lbibitem/before}[latex-lab-testphase-bib/target] + { + \AddToHookNext{para/begin} + { + \makebox[0pt][r]{\MakeLinkTarget*{cite.#2\@extra@b@citeb}\hspace{\leftmargin}} + } + } +% \end{macrocode} +% we make a copy to be able to reinstate the definition. This is e.g. +% currently needed with hyperref. +% \begin{macrocode} +\let\@kernel@copy@lbibitem\@lbibitem +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@bibitem} +% Similar for \cs{@bibitem}. +% TODO: If hyperref is loaded we will get a second target from the refstepcounter, +% but this is ignored for now. +% \begin{macrocode} +\AddToHookWithArguments{cmd/@bibitem/before} + { +% \end{macrocode} +% we store the target name for the label. +% \begin{macrocode} + \tl_set:Nn\l_@@_bib_citekey_tl{#1} + } +% \end{macrocode} +% +% The target is added at the begin of the paragraph. We give that a label as +% it perhaps need to be removed by packages +% \begin{macrocode} +\AddToHookWithArguments{cmd/@bibitem/before}[latex-lab-testphase-bib/target] + { + \AddToHookNext{para/begin} + { + \makebox[0pt][r]{\MakeLinkTarget*{cite.#1\@extra@b@citeb}\hspace{\leftmargin}} + } + } +% \end{macrocode} +% \begin{macrocode} +\let\@kernel@copy@bibitem\@bibitem +% \end{macrocode} +% \end{macro} +% +% TODO The LI-structure should set a label, we redefine the internal command locally for +% now, but perhaps this need a recipe? +% +% \begin{macrocode} +\AddToHook{env/thebibliography/begin} + { + \cs_set:Npn \__block_list_item_begin: + { + \tag_struct_begin:n + { + tag=\LItag, + label= cite.\l_@@_bib_citekey_tl\@extra@b@citeb + } + } + } +% \end{macrocode} +% +% \subsection{Handling citation commands} +% We redefine similar to hyperref the \cs{bibcite} command to inject link and +% structure. Even if it looks a bit odd it is now used for many years and so +% hopefully compatible with various packages. But differently to hyperref we use +% the new hooks with arguments. +% TODO: consider hook name. +% \begin{macrocode} +\NewMirroredHookPairWithArguments{bibcite/before}{bibcite/after}{2} +\def\bibcite#1#2{% + \@newl@bel{b}{#1\@extra@binfo}{% + \UseHookWithArguments{bibcite/before}{2}{#1}{#2} + #2 + \UseHookWithArguments{bibcite/after}{2}{#1}{#2} + }% + }% +\let\@kernel@copy@bibcite\bibcite +% \end{macrocode} +% Now we add the tagging structure. +% TODO: with the next tagpdf version it should no longer be +% needed to exand the ref key. +% \begin{macrocode} +\AddToHookWithArguments{bibcite/before} + { + \tag_mc_end_push: + \exp_args:Nx\tagstructbegin{tag=Reference,ref=cite.#1\@extra@b@citeb} + \tagmcbegin{} + } +\AddToHookWithArguments{bibcite/after}[tag] + { + \tag_mc_end: + \tagstructend + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% At last the code for hyperref, the link will be inside the reference, but +% this can be changed with a rule. +% \begin{macrocode} +\AddToHook{package/hyperref/after} + { + \AddToHookWithArguments{bibcite/before} + { + \hyper@linkstart{cite}{cite.#1\@extra@b@citeb} + } + \AddToHookWithArguments{bibcite/after}{\hyper@linkend} + } +% \end{macrocode} +% +% \subsection{Natbib and biblatex support} +% When hyperref is loaded, both natbib and biblatex use \cs{hyper@natlinkstart} +% and \cs{hyper@natlinkend} to handle the links. We can use the generic hooks to +% add the tagging code (and the link code from hyperref). +% We need in part different code for both systems: +% with biblatex we have to take care that only the first +% structure sets a label, and if +% hyperref is not loaded (or deactived) we will need additional code +% but this currently doesn't exist. +% We assume that no document loads both package -- that will probably break. +% \begin{macrocode} +\newcommand\hyper@natlinkstart[1]{} +\newcommand\hyper@natlinkend{} +% \end{macrocode} +% With natbib we need to change the hooks to avoid duplicated target as it sets +% the anchor too. We can not simply empty \cs{hyper@natanchorstart} as that is +% used by biblatex. +% \begin{macrocode} +\AddToHook{package/natbib/after} + { + \RemoveFromHook{cmd/@bibitem/before} [latex-lab-testphase-bib/target] + \RemoveFromHook{cmd/@lbibitem/before}[latex-lab-testphase-bib/target] + } +% \end{macrocode} +% This can be shared by both packages: it will work with natbib with and without hyperref. +% With biblatex it will work without hyperref as long as \cs{@extra@b@citeb} is empty +% \begin{macrocode} +\AddToHookWithArguments{cmd/hyper@natlinkstart/before} + { + \leavevmode + \tag_mc_end_push: + \exp_args:Nx\tag_struct_begin:n{tag=Reference,ref=cite.#1\@extra@b@citeb} + \tag_mc_begin:n{} + } +\AddToHook{cmd/hyper@natlinkend/after} + { + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} + } + +% \end{macrocode} +% if hyperref is loaded we have to revert its definition of the natbib hooks +% and add its code through the generic hooks. +% TODO: allow to suppress the natbib code in hyperref. +% +% \begin{macrocode} +\AddToHook{package/hyperref/after} + { + \renewcommand\hyper@natlinkstart[1]{} + \renewcommand\hyper@natlinkend{} + \AddToHookWithArguments{cmd/hyper@natlinkstart/before} + { + \Hy@backout{#1}% +% \end{macrocode} +% natbib passes the \cs{@extra@b@citeb} in the argument, and biblatex +% the refsection, so we only need to add the prefix \texttt{cite.}. +% \begin{macrocode} + \hyper@linkstart{cite}{cite.#1}% + \def\hyper@nat@current{#1} + } + \AddToHook{cmd/hyper@natlinkend/after} + { + \hyper@linkend + } + } + +% \end{macrocode} +% and now special biblatex code. The list item code has to test if the +% anchor is already known: +% \begin{macrocode} +\AddToHook{cmd/blx@bibinit/after} + { + \cs_set:Npn \__block_list_item_begin: + { + \xifinlist{\the\c@refsection @\abx@field@entrykey}{\blx@anchors} + { + \tag_struct_begin:n + { + tag=\LItag, + } + } + { + \tag_struct_begin:n + { + tag=\LItag, + label= cite.\the\c@refsection @\abx@field@entrykey + } + } + } + } +% \end{macrocode} +% biblatex without hyperref is currently not supported but we at least avoid that it +% errors: +% \begin{macrocode} +\AddToHook{package/biblatex/after} + { + \appto\blx@mknohyperref + { + \let\blx@anchors\@empty + \protected\def\blx@anchor{% + \xifinlist{\the\c@refsection @\abx@field@entrykey}{\blx@anchors} + {} + {\listxadd\blx@anchors{\the\c@refsection @\abx@field@entrykey}}}% + } + } +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{bib-latex-lab-testphase.ltx} + [2023-05-18 v0.8 code related to the tagging of bib and citations] + +\RequirePackage{latex-lab-testphase-bib} + +%</latex-lab> +% \end{macrocode} diff --git a/macros/latex/required/latex-lab/latex-lab-bib.pdf b/macros/latex/required/latex-lab/latex-lab-bib.pdf Binary files differnew file mode 100644 index 0000000000..99f4722dc2 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-bib.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-block-tagging.dtx b/macros/latex/required/latex-lab/latex-lab-block-tagging.dtx new file mode 100644 index 0000000000..63145d929e --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-block-tagging.dtx @@ -0,0 +1,4055 @@ +% \iffalse meta-comment +% +%% File: latex-lab-block-tagging.dtx (C) Copyright 2021-2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +%<*driver> +\documentclass{l3doc} +\usepackage{amstext} +\EnableCrossrefs +\CodelineIndex + +\usepackage{todonotes} + +\begin{document} + \DocInput{latex-lab-block-tagging.dtx} +\end{document} +%</driver> +% +% \fi +% + +\def\ltblocksversion{v0.8d} +\def\ltblocksdate{2023/06/07} + +% +% \title{Prototype reimplementation of \LaTeXe{}'s block environments using templates} +% \author{\LaTeX{} Project\thanks{Initial reimplementation of lists done by Bruno +% Le Floch, generalized second version with tagging support by Frank Mittelbach.}} +% \date{\ltblocksversion\ \ltblocksdate} +% +% \maketitle +% +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% \providecommand\struct[1]{\texttt{<#1>}} +% +% \NewDocElement[envlike, idxtype=objecttype, idxgroup=object types, +% printtype=\textit{objecttype}] {ObjectType}{objecttype} +% +% \NewDocElement[envlike, idxtype=template, idxgroup=templates, +% printtype=\textit{templ.}] {Template}{template} +% +% \NewDocElement[envlike, idxtype=instance, idxgroup=instances, +% printtype=\textit{inst.}] {Instance}{instance} +% +% +% \newcommand\valuefrom[1]{\textrm{value from }\texttt{#1}} +% \newcommand\key[1]{\texttt{#1}} +% +% +% \NewDocumentCommand\fmi{sO{}m} +% {\IfBooleanTF{#1}{\todo[inline,#2]{#3}}^^A +% {\todo[#2]{#3}}} +% +% \NewDocumentCommand\ufi{sO{}m} +% {\IfBooleanTF{#1}{\todo[inline,#2]{UFi:#3}}^^A +% {\todo[#2]{UFi:#3}}} +% \makeatletter +% \renewenvironment{TemplateInterfaceDescription}[1] +% { +% \subsubsection{The~object~type~`#1'} +% \begingroup +% \@beginparpenalty\@M +% \description +% \def\TemplateArgument##1##2{\item[Arg:~##1]##2\par} +% \def\TemplateSemantics +% { +% \enddescription\endgroup +% \subsubsection*{Semantics:} +% } +% } +% { +% \par\bigskip +% } +% \renewenvironment{TemplateDescription}[2] +% {\subsubsection{The \texttt{#1} template `#2'}^^A +% \paragraph*{Attributes:}^^A +% \begingroup +% \@beginparpenalty\@M +% \description +% \def\TemplateKey##1##2##3##4{^^A +% \item[\texttt{##1}~(\textit{\mdseries##2})]##3^^A +% \ifx\TemplateKey##4\TemplateKey\else +% \hfill\penalty500\hbox{}\hfill Default:~\texttt{##4}^^A +% \nobreak\hskip-\parfillskip\hskip0pt\relax +% \fi +% \par +% }^^A +% \def\TemplateSemantics{^^A +% \enddescription\endgroup +% \paragraph*{Semantics~\&~Comments:}^^A +% }^^A +% } +% { \par \bigskip } +% \makeatother +% +% +% \begin{abstract} +% \end{abstract} +% +% +% \tableofcontents +% \medskip +% +% +% \begin{documentation} +% +% +% +% \section{Introduction} +% +% The list implementation in \LaTeXe{} serves a dual purpose: it +% implements real lists such as \env{itemize} or \env{enumerate}, +% but it is also used as the basis for vertical blocks, i.e., to specify +% the vertical spacing and paragraph handling after such block, e.g., +% in environments like \env{center}, \env{quote}, \env{verbatim}, or in +% the theorem environments. They are all implemented as +% \enquote{trivial} lists with a single (hidden) item. +% +% While this was convenient to get a consistent layout using a single +% implementation it is not adequate if it comes to interpreting the +% structure of a document, because environments based on \env{trivlist} +% should not advertise themselves as being a \enquote{list} --- after all, +% from a semantic point of view they aren't lists. +% +% The approach taking here is therefore to offer separate object +% types: \xt{block} (horizontally or vertically oriented data that +% needs some handling at the start and the end), \xt{para} (that deals +% with different paragraph layouts), \xt{list} (that handles list +% related parameters, and \xt{item} (for item layouts and handling), to address +% the independent aspects and also offer the object type \xt{blockenv} +% that ties them together as necessary. +% +% For example, a \env{quote} environment would make use of a (display) +% \xt{block} and some \xt{para} handling while an standard +% \env{enumerate} would make use of a display \xt{block}, a \xt{list}, +% and an \xt{item} and \xt{para} instance. +% An inline list (like \env{enumerate*} from the \pkg{enumitem} +% package) would be using the same \xt{list} instance but a different +% (horizontally oriented) \xt{block}. +% +% +% \section{Object types and templates for blocks and lists} +% +% \subsection{Object types} +% +% \begin{TemplateInterfaceDescription}{block} +% \TemplateArgument{1}{key/value list to alter the default block parameters} +% \TemplateSemantics +% Handle the layout aspects of a block of data. In case of a +% \enquote{display} block (i.e., vertically oriented) the spacing +% and page breaking as well as the handling if the block starts a +% paragraph or ends one, that is, if text is immediately following +% the block without being separated by an empty line, then this +% text is considered to be in the same paragraph as the block. +% +% In case of a horizontally oriented block it covers any special +% handling at the start and end of the block, e.g, extra spacing, +% prohibitying or encuraging line breaks, and so forth. +% \end{TemplateInterfaceDescription} +% +% \begin{TemplateInterfaceDescription}{para} +% \TemplateArgument{1}{key/value list to alter the default item parameters} +% \TemplateSemantics +% Sets up paragraph-specific parameters for H\&J, e.g., to +% implement justification variations, the behavior of \verb=\\= +% etc. The instances are used in higher-level templates, e.g., in a +% \xt{block}. +% \end{TemplateInterfaceDescription} +% +% \begin{TemplateInterfaceDescription}{list} +% \TemplateArgument{1}{key/value list to alter the default item parameters} +% \TemplateSemantics +% Handle the aspects related to list design, e.g., the use and +% formatting of counters, etc. +% +% Note that this does not cover block-related aspects, i.e., a list +% instance could be used both for a display list or for an inline line. +% \end{TemplateInterfaceDescription} +% +% \begin{TemplateInterfaceDescription}{item} +% \TemplateArgument{1}{key/value list to alter the default item parameters} +% \TemplateSemantics +% A sub-type used as part of \xt{list} to easily cover alternative layout +% for list items. +% \end{TemplateInterfaceDescription} +% +% +% \begin{TemplateInterfaceDescription}{blockenv} +% \TemplateArgument{1}{key/value list to alter the default item parameters} +% \TemplateSemantics +% This object type is used to implement document-level +% environments. It defines a \xt{block} instance to handle the +% layout at the \enquote{edge} of the environment data, possibly +% some paragraph setup through a \xt{para} instance, potentially an +% \enquote{inner} instance for more complicated environments (such +% as lists), and possibly some additional setup code for certain +% environments. +% +% It also defines how the \xt{blockenv} behaves with respect to +% nesting, e.g., does it change when nested and if so how many +% levels of nesting are supported, etc. +% +% Finally, the object type defines how it appears in a tagged PDF +% document, what tag names are used, how they are rolemapped and +% whether it adds additional attributes, etc. +% \end{TemplateInterfaceDescription} +% +% +% +% \subsection{Templates} +% +% +% \begin{TemplateDescription}{blockenv}{display} +% +% \TemplateKey{env-name}{tokenlist} +% {Name of the environment used only in tracing}{} +% \TemplateKey{tag-name}{tokenlist} +% {Name of the tag in the PDF. If not explicitly given +% the name is defined by the \key{tagging-recipe}}{} +% \TemplateKey{tag-class}{tokenlist} +% {An explicit tag class attribute}{} +% \TemplateKey{tagging-recipe}{tokenlist} +% {Defines the way tagging is done. Currently the values +% \texttt{basic}, \texttt{standard}, and \texttt{list} +% are supported}{standard} +% \TemplateKey{level-increase}{boolean}{Does this \xt{blockenv} +% increase the block level if it is nested in an outer block?}{true} +% \TemplateKey{setup-code}{tokenlist} +% {Initial setup code. This is +% executed after legacy defaults (from \cs{@listi}, +% \cs{@listii}, etc.) are used but before the block instance is called}{} +% \TemplateKey{block-instance}{tokenlist}{Part of the name of the +% \xt{block} instance that is called. The full name has +% a \texttt{-}\meta{level} appended}{displayblock} +% \TemplateKey{para-instance}{tokenlist}{}{} +% \TemplateKey{inner-level-counter}{tokenlist}{Name of an existing (!) counter +% that is incremented and used to determine final name +% of the \key{inner-instance} or empty if always the +% same inner instance should be used}{} +% \TemplateKey{max-inner-levels}{tokenlist}{Maximum number of nested +% environments of this kind. Only relevant if there is a +% \key{inner-level-counter} specified}{4} +% \TemplateKey{inner-instance-type}{tokenlist}{Opject type of the +% inner instance}{list} +% \TemplateKey{inner-instance}{tokenlist}{Name of the inner instance +% (if any).}{} +% \TemplateKey{para-flattened}{boolean}{\emph{describe}}{false} +% \TemplateKey{final-code}{tokenlist}{Final setup code}{\cs{ignorespaces}} +% +% \TemplateSemantics +% +% This \xt{blockenv} template supports the legacy list setting that +% are found in many document classes in the macros \cs{@listi}, +% \cs{@listii}, up to \cs{@listvi}. It also uses the counter +% \cs{@listdepth} to track nesting of block, again mainly to +% support legacy setups (internally it gives it a more appropriate +% name but it remains accessible through the \LaTeXe{} name). +% +% +% It first checks that nothing is too deeply nested. +% If the level should increase then the increments the +% \cs{@listdepth} counter and +% calls the corresponding \cs{@list...} macro to update the legacy +% defaults. If \key{level-increase} is set to false this is bypassed. +% +% It then sets up the +% tagging via the \key{tagging-recipe} setting and executes any +% code in \key{setup-code}. +% +% Afterwards it calls the appropriate \xt{block} instance based on +% \key{block-instance} and current level, e.g., +% \texttt{displayblock-1}. Then it sets up paragraph parameters if +% a \key{para-instance} was specified (otherwise they stay as +% they are). +% +% If a \key{inner-instance} was specified this is called next, +% or more precisely: if no \key{inner-level-counter} was +% specified the instance \key{inner-instance} is +% called. +% +% Otherwise, the \key{inner-level-counter} is incremented and the +% instance with the name +% \key{inner-instance}\texttt{-}\key{inner-level-counter} is +% called. +% +% Finally, the \key{final-code} is executed (by default +% \cs{ignorespaces}). +% +% +% \end{TemplateDescription} +% +% The maximum number of \xt{blockenv}s that can be nested into each +% other is is restricted by the \LaTeX{} counter +% \texttt{maxblocklevels} with a default value of \texttt{6}. If this +% value is increased then it is necessary to provide additional +% instances, e.g., \texttt{displayblock-7}, etc. Decreasing is, of +% course, always possible, then some of the instances defined are not +% used and instead the user gets an error that there is too much +% nesting going on. +% +% If the key \key{level-increase} is set to \texttt{false} then such +% an environment doesn't alter the nesting level and therefore you can +% nest those environments as often as you like (a typical example +% would be \env{flushleft} anywhere in the nesting hierarchy, that +% would have no effect on hitting the boundary). +% +% +% \begin{TemplateDescription}{block}{display} +% +% \TemplateKey{heading}{tokenlist}{\emph{not really used yet}}{} +% \TemplateKey{beginsep}{skip}{}{\cs{topsep}} +% \TemplateKey{begin-par-skip}{skip}{}{\cs{partopsep}} +% \TemplateKey{par-skip}{skip}{}{\cs{parsep}} +% \TemplateKey{end-skip}{skip}{}{\valuefrom{beginsep}} +% \TemplateKey{end-par-skip}{skip}{}{\valuefrom{begin-par-skip}} +% \TemplateKey{beginpenalty}{integer}{}{\cs{@beginparpenalty}} +% \TemplateKey{endpenalty}{integer}{}{\cs{@endparpenalty}} +% \TemplateKey{leftmargin}{length}{}{\cs{leftmargin}} +% \TemplateKey{rightmargin}{length}{}{\cs{rightmargin}} +% \TemplateKey{parindent}{length}{}{\cs{listparindent}} +% +% \TemplateSemantics +% +% The idea of a \key{heading} key needs some further +% thoughts. Maybe instead the object type should accept a second +% argument and receive input for such a headding from the document +% level instead. +% +% The names of the keys need further thoughts and some +% decision. Right now it is a mixture of those with hyphens and +% those that match legacy register names (the way \pkg{enumitem} +% did its keys). +% +% Also \key{parindent} conflicts with \key{indent-width}! +% +% \end{TemplateDescription} +% +% +% \begin{TemplateDescription}{para}{std} +% +% \TemplateKey{indent-width}{length}{}{\cs{parindent}} +% \TemplateKey{start-skip}{skip}{}{0pt} +% \TemplateKey{left-skip}{skip}{}{0pt} +% \TemplateKey{right-skip}{skip}{}{0pt} +% \TemplateKey{end-skip}{skip}{}{\cs{@flushglue}} +% \TemplateKey{fixed-word-spaces}{boolean}{}{false} +% \TemplateKey{final-hyphen-demerits}{integer}{}{5000} +% \TemplateKey{cr-cmd}{tokenlist}{}{\cs{@normalcr}} +% \TemplateKey{para-class}{tokenlist}{}{justify} +% +% \TemplateSemantics +% +% +% \end{TemplateDescription} +% +% +% +% \begin{TemplateDescription}{list}{std} +% +% \TemplateKey{counter}{tokenlist} +% {Counter name to be used in a numbered list or empty, +% if the list is unnumbered}{} +% \TemplateKey{item-label}{tokenlist} +% {Label \enquote{string} for a fixed label or as +% generated from the current \key{counter} value}{} +% \TemplateKey{start}{integer} +% {Start value for the counter if the list is numbered, +% otherwise irrelevant}{1} +% \TemplateKey{resume}{boolean} +% {Should a numbered list be resumed from the last instance?}{false} +% \TemplateKey{item-instance}{instance} +% {Instance of type \texttt{item} to be used to format +% the label string}{basic} +% \TemplateKey{item-skip}{skip}{The space in front of an item in the +% list.\fmi{May need to be on a different template level}}{\cs{itemsep}} +% \TemplateKey{item-indent}{length}{Horizontal displacement of the item.}{0pt} +% \TemplateKey{item-penalty}{integer} +% {Penalty for breaking before an +% item (except the first)}{\cs{@itempenalty}} +% \TemplateKey{label-width}{length} +% {Width reserved for the formatted item label}{\cs{labelwidth}} +% \TemplateKey{label-sep}{length} +% {Horizontal separation between label and following text}{\cs{labelsep}} +% \TemplateKey{legacy-support}{boolean} +% {Is formatting the label via \cs{makelabel} supported?}{false} +% +% \TemplateSemantics +% +% +% \end{TemplateDescription} +% +% +% \begin{TemplateDescription}{item}{std} +% +% \TemplateKey{counter-label}{function{1}}{\emph{unused}}{\cs{arabic}\{\#1\}} +% \TemplateKey{counter-ref}{function{1}}{\emph{unused}}{\valuefrom{counter-label}} +% \TemplateKey{label-ref}{function{1}}{\emph{unused}}{\#1} +% \TemplateKey{label-autoref}{function{1}}{\emph{unused}}{item~\#1} +% \TemplateKey{label-format}{function{1}} +% {Formatting of the label, questionable the way it is used}{\#1} +% \TemplateKey{label-strut}{boolean}{Add a \cs{strut} to the label?}{false} +% \TemplateKey{label-align}{choice} +% {Supported values \texttt{left},\texttt{center}, +% \texttt{right}, and \texttt{parleft}. \emph{Only partly implemented}}{right} +% \TemplateKey{label-boxed}{boolean} +% {Should the label be boxed?}{true} +% \TemplateKey{next-line}{boolean}{}{false} +% \TemplateKey{text-font}{tokenlist}{\emph{unused}}{} +% \TemplateKey{compatibility}{boolean}{}{true} +% +% \TemplateSemantics +% +% This template is only rudimentary implemented at the moment. It +% probably needs other keys and the existing ones need a proper +% implementation. +% +% \end{TemplateDescription} +% +% +% \section{Tagging support} +% +% \subsection{Paragraph tags} +% +% Paragraphs in \LaTeX{} can be nested, e.g., you can have a paragraph +% containing a display quote, which in turn consists of more than one +% (sub)paragraph, followed by some more text which all belongs to the +% same outer paragraph. +% +% In the PDF model and in the HTML model that is not supported --- a +% limitation that conflicts with real live, given that such +% constructs are quite normal in spoken and written language. +% +% The approach we take to resolve this is to model such \enquote{big} +% paragraphs with a structure named \struct{text-unit} and use \struct{text} (rollmapped to \struct{P}) +% only for (portions of) the actual paragraph text in a way that the +% \struct{text}s are not nested. As a result we have for a simple +% paragraph the structures +% \begin{tabbing} +% \hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\= \kill +% \> \struct{text-unit}\\ +% \>\> \struct{text}\\ +% \>\>\> The paragraph text \ldots\\ +% \>\> \struct{/text}\\ +% \> \struct{/text-unit} +% \end{tabbing} +% The \struct{text-unit} structure is rollmapped to \struct{Part} or possibly to +% \struct{Div} so we get a valid PDF, but processors who care can identify +% the complete paragraphs by looking for \struct{text-unit} tags. +% +% In the case of an element, such as a display quote or a display list +% inside the paragraph, we then have +% \begin{tabbing} +% \hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\= \kill +% \> \struct{text-unit}\\ +% \>\> \struct{text}\\ +% \>\>\> The paragraph text before the display element \ldots\\ +% \>\> \struct{/text}\\ +% \>\> \struct{display element structure}\\ +% \>\>\> Content of the display structure possiblly involving inner \struct{text-unit} tags\\ +% \>\> \struct{/display element structure}\\ +% \>\> \struct{text}\\ +% \>\>\> \ldots{} continuing the outer paragraph text\\ +% \>\> \struct{/text}\\ +% \> \struct{/text-unit} +% \end{tabbing} +% In other words such a display block is always embedded in a +% \struct{text-unit} structure, possibly preceded by a \struct{text}\ldots\struct{/text} block +% and possibly followed by one, though both such blocks are optional. +% +% Thus an \env{itemize} environment that has some introductory text +% but no text immediately following the list +% would be tagged as follows: +% \begin{tabbing} +% \hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\= \kill +% \> \struct{text-unit}\\ +% \>\> \struct{text}\\ +% \>\>\> The intro text for the \env{itemize} environment \ldots\\ +% \>\> \struct{/text}\\ +% \>\> \struct{itemize}\\ +% \>\>\> \struct{LI}\\ +% \>\>\>\> \struct{Lbl} label \struct{/Lbl}\\ +% \>\>\>\> \struct{LBody}\\ +% \>\>\>\>\> The text of the first item involving \struct{text-unit} as necessary \ldots\\ +% \>\>\>\> \struct{/LBody}\\ +% \>\>\> \struct{/LI}\\ +% \>\>\> \struct{LI}\\ +% \>\>\>\> The second item \ldots{}\\ +% \>\>\> \struct{/LI}\\ +% \>\>\> \ldots{} further items \ldots\\ +% \>\> \struct{/itemize}\\ +% \> \struct{/text-unit} +% \end{tabbing} +% The \struct{itemize} is rollmapped to \struct{L}. +% +% For some display blocks, such as centered text, we use a simpler +% strategy. Such blocks still ensure that they are inside a \struct{text-unit} +% structure but their body uses simple \struct{text} blocks and not +% \struct{text-unit}\struct{text} inside, e.g., the input +% \begin{verbatim} +% This is a paragraph with some +% \begin{center} +% centered lines +% +% with a paragraph break between them +% \end{center} +% followed by some more text. +% \end{verbatim} +% will be tagged as follows: +% \begin{tabbing} +% \hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\=\hspace*{1em}\= \kill +% \> \struct{text-unit}\\ +% \>\> \struct{text}\\ +% \>\>\> This is a paragraph with some\\ +% \>\> \struct{/text}\\ +% \>\> \struct{text /O /Layout /TextAlign/Center}\\ +% \>\>\> centered lines\\ +% \>\> \struct{/text}\\ +% \>\> \struct{text /O /Layout /TextAlign/Center}\\ +% \>\>\> with a paragraph break between them\\ +% \>\> \struct{/text}\\ +% \>\> \struct{text}\\ +% \>\>\> followed by some more text.\\ +% \> \struct{/text-unit} +% \end{tabbing} +% +% +% \subsection{Tagging recipes} +% +% There are a number of different tagging recipes that implement +% different tagging approaches. They are selected through the +% \key{tagging-recipe} of the \xt{blockenv} template. Currently the +% following values are implemented: +% \begin{description} +% \item[\texttt{basic}] +% This recipe does the following: +% \begin{itemize} +% \item +% Ensure that the \xt{blockenv} is inside a \struct{text-unit} +% structure, if necessary, start one. +% \item +% If inside a \struct{text-unit}\struct{text}, then close the \struct{/text} but +% leave the \struct{text-unit} open. +% +% \item +% Text inside the body of the environment starts with +% \struct{text-unit}\struct{text} if \key{para-flattened} is set to \texttt{false}, +% otherwise just with \struct{text}. +% +% \item +% At the end of the environment close \struct{/text} and possibly an +% inner \struct{/text-unit} if open. +% +% \item +% Then look if the environment is followed by an empty line +% (\cs{par}). If so, close the outer \struct{/text-unit} and start any +% following text with \struct{text-unit}\struct{text}. Otherwise, +% don't and following text restarts with a just a \struct{text} (and no +% paragraph indentation) +% \end{itemize} +% +% +% \item[\texttt{standard}] +% This recipe is like the \texttt{basic} one as far as handling +% \struct{text-unit} and \struct{text} is concerned. In addition +% \begin{itemize} +% \item +% it starts an inner tagging structure (i.e., which is therefore a +% child of the outer \struct{text-unit}). +% \item +% By default this structure is a \struct{Figure} unless overwritten +% by the key \key{tag-name}. If that key is used, a suitable +% rollmap needs to be provided for the name given. +% \item +% At the end of the environment that inner structure is closed +% again so that we are back on the \struct{text-unit} level from the outside. +% \item +% Then the lookahead for an empty line is done as described previously. +% \end{itemize} +% +% +% +% \item[\texttt{list}] +% This recipe is like the \texttt{standard} one except that +% \begin{itemize} +% \item +% the inner structure is a list (\struct{L}). +% \item +% Furthermore everything is set up so that we have list items +% (\struct{LI}) with suitable substructures (\struct{Lbl} for the item +% labels and \struct{LBody} for the item bodies). +% \item +% If the key \key{tag-name} is specified, this is used as the tag +% name for the whole list instead of \struct{L}. Of course, it +% should then have a suitable rollmap. +% \item +% If the key \key{tag-class} is specified then this is used as the +% class attribute. Again, this requires a suitable setup on the outside. +% \item +% At the end of the environment the \struct{/LBody}, \struct{/LI}, and +% \struct{/L} (or the tag name used) are closed. +% \item +% Then the lookahead for an empty line is done as described previously. +% \end{itemize} +% +% +% \end{description} +% +% +% +% +% +% +% \end{documentation} +% +% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } +% +% +% +% \begin{implementation} +% +% \section{The Implementation} +% +% +% \begin{macrocode} +%<*package> +%<@@=block> +% \end{macrocode} +% +% +% \begin{macrocode} +\ProvidesPackage {latex-lab-testphase-block-tagging} + [\ltblocksdate\space \ltblocksversion\space + blockenv implementation] +% \end{macrocode} +% +% We make use of templates: +% \begin{macrocode} +\RequirePackage{xtemplate} +% \end{macrocode} +% Generell kernel changes, also loaded by the sec and toc code. +% \begin{macrocode} +\RequirePackage{latex-lab-kernel-changes} +% \end{macrocode} +% \begin{macrocode} +\ExplSyntaxOn +% \end{macrocode} +% +% \ufi{this variable(s) must be declared:} +% \begin{macrocode} +\tl_new:N \l_@@_item_align_tl +\tl_new:N\l_@@_legacy_env_params_tl +% \end{macrocode} + +% \subsection{Handling \cs{par} after the end of the list} +% +% An empty line (or a \cs{par}) after a list has semantic meaning as +% it defines whether then following text is logically within the same +% paragraph as the list (no empty line) or whether it starts a new +% paragraph and the paragraph containing the list ends at the end of +% the list (empty line after the list). +% This is handled by \LaTeX{} using a legacy flag called +% \texttt{@endpe} and set of commands inside the +% generic \cs{end} (calling \cs{@doendpe}) and as part of the list +% environments identifying themselves as \enquote{paragraph ending +% environments} (by setting this flag). +% +% For the reimplementation of the list environments including support +% of tagging we need to augment that mechanism slightly and add some +% kernel hook(s) to add the tagging code if needed. +% +% +% +% +% \begin{macro}{\@doendpe} +% The original \LaTeXe{} command is augmented to allow for tagging. +% \begin{macrocode} +\def\@doendpe{\@endpetrue + \def\par + { + \@restorepar + \clubpenalty\@clubpenalty +% \end{macrocode} +% At this point we add the tagging code that closes an open +% \struct{text-unit}, \struct{text} tag combination, +% if necessary: +% \begin{macrocode} + \__kernel_displayblock_doendpe: +% \end{macrocode} +% +% The standard \cs{par} command (\cs{par_end:}) acts on +% \texttt{@endpe} and attempts to close a still open \texttt{text-unit} +% and this would be wrong if it was already closed above. So we +% have to reset the switch to false first. +% \begin{macrocode} + \@endpefalse + \everypar{} + \par + } + \everypar{{\setbox\z@\lastbox} + \everypar{} + \@endpefalse + } +} +% \end{macrocode} +% +% By default we don't do any tagging: +% \begin{macrocode} +\cs_new_eq:NN \__kernel_displayblock_doendpe: \prg_do_nothing: +% \end{macrocode} +% The flag itself should be set globally not locally.\fmi{verify +% that this claim is actually correct!} +% \begin{macrocode} +\def\@endpetrue {\global\let\if@endpe\iftrue} +\def\@endpefalse{\global\let\if@endpe\iffalse} +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Object and template interfaces} +% +% +% \begin{objecttype}{blockenv, block, para, list, item} +% All object types expect a single +% key--value argument used to tweak template parameters specific to a +% given use in the document. This section is devoted to template +% interfaces, and the template code is covered later. +% \begin{macrocode} +\DeclareObjectType{blockenv}{1} +\DeclareObjectType{block}{1} +\DeclareObjectType{para}{1} +\DeclareObjectType{list}{1} +\DeclareObjectType{item}{1} +% \end{macrocode} +% \end{objecttype} +% +% +% +% \begin{template}{blockenv display} +% +% \begin{macrocode} +\DeclareTemplateInterface{blockenv}{display}{1} +{ + env-name : tokenlist , + tag-name : tokenlist , + tag-class : tokenlist , + tagging-recipe : tokenlist = standard, + level-increase : boolean = true , + setup-code : tokenlist , + block-instance : tokenlist = displayblock , + para-instance : tokenlist , + inner-level-counter : tokenlist, + max-inner-levels : tokenlist = 4, + inner-instance-type : tokenlist = list , + inner-instance : tokenlist , + para-flattened : boolean = false , + final-code : tokenlist = \ignorespaces , +} +% \end{macrocode} +% \end{template} +% +% +% \begin{template}{block display} +% +% \begin{macrocode} +\DeclareTemplateInterface{block}{display}{1} +{ + heading : tokenlist = , %?? + beginsep : skip = \topsep , + begin-par-skip : skip = \partopsep , + par-skip : skip = \parsep , + end-skip : skip = \KeyValue{beginsep} , % conflict with name below + end-par-skip : skip = \KeyValue{begin-par-skip} , + beginpenalty : integer = \UseName{@beginparpenalty} , + endpenalty : integer = \UseName{@endparpenalty} , + leftmargin : length = \leftmargin , + rightmargin : length = \rightmargin , + parindent : length = \listparindent , +% font : tokenlist % maybe add? (or more general for fonts and color) +} +% \end{macrocode} +% \end{template} +% +% +% \begin{template}{para std} +% +% \begin{macrocode} +\DeclareTemplateInterface{para}{std}{1} +{ + indent-width : length = \parindent , + start-skip : skip = 0pt , + left-skip : skip = 0pt , + right-skip : skip = 0pt , + end-skip : skip = \@flushglue , + fixed-word-spaces : boolean = false , + final-hyphen-demerits : integer = 5000 , + cr-cmd : tokenlist = \@normalcr , + para-class : tokenlist = justify , +} +% \end{macrocode} +% \end{template} +% +% +% \begin{template}{list std} +% +% \begin{macrocode} +\DeclareTemplateInterface{list}{std}{1} % optional +{ + counter : tokenlist = , + item-label : tokenlist = , + start : integer = 1 , + resume : boolean = false , + item-instance : instance{item} = basic , + item-skip : skip = \itemsep , + item-penalty : integer = \UseName{@itempenalty} , + item-indent : length = 0pt , % was \itemindent + label-width : length = \labelwidth , + label-sep : length = \labelsep , + legacy-support : boolean = false , +} +% \end{macrocode} +% \end{template} +% +% +% \begin{template}{item std} +% +% \begin{macrocode} +\DeclareTemplateInterface{item}{std}{1} + { + counter-label : function{1} = \arabic{#1} , + counter-ref : function{1} = \KeyValue{counter-label} , + label-ref : function{1} = #1 , + label-autoref : function{1} = item~#1 , + label-format : function{1} = #1 , + label-strut : boolean = false , + label-align : choice {left,center,right,parleft} = right , + label-boxed : boolean = true , + next-line : boolean = false , + text-font : tokenlist , + compatibility : boolean = true , + } +% \end{macrocode} +% \end{template} +% +% +% +% +% +% +% \subsection{Useful helper commands} +% +% This section collects \pkg{expl3} commands that will be useful. +% +% \begin{macro}{\@@_skip_set_to_last:N,\@@_skip_remove_last:} +% Set a skiip register to the value of an immediately preceding +% skip or zero if there was none +% \begin{macrocode} +\cs_new_protected:Npn \@@_skip_set_to_last:N #1 { + \skip_set:Nn #1 { \tex_lastskip:D } +} +% \end{macrocode} +% Remove a skip previous skip if it is directly in front (not +% allowed in unrestricted vertical mode). +% \begin{macrocode} +\cs_new_eq:NN \@@_skip_remove_last: \tex_unskip:D +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\tl_if_novalue:nTF} +% +% \begin{macrocode} +\cs_generate_variant:Nn \tl_if_novalue:nTF { o } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\tag_if_active:T} +% If tagging support is not loaded then we shouldn't try to execute +% any tagging related commands. Eventually this can go once the +% basic support is available in the kernel. +% \fmi{can vanish one day} +% \begin{macrocode} +\cs_if_exist:NF \tag_if_active:T + { \cs_new_eq:NN \tag_if_active:T \use_none:n } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Debugging} +% +% +% \begin{variable}{\g_@@_debug_bool} +% +% \begin{macrocode} +\bool_new:N \g_@@_debug_bool +% \end{macrocode} +% \end{variable} +% +% +% \begin{macro}{\@@_debug:n,\@@_debug_typeout:n} +% +% \begin{macrocode} +\cs_new_eq:NN \@@_debug:n \use_none:n +\cs_new_eq:NN \@@_debug_typeout:n \use_none:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\block_debug_on:,\block_debug_off:, +% \@@_debug_gset:} +% \begin{macrocode} +\cs_new_protected:Npn \block_debug_on: + { + \bool_gset_true:N \g_@@_debug_bool + \@@_debug_gset: + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \block_debug_off: + { + \bool_gset_false:N \g_@@_debug_bool + \@@_debug_gset: + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_debug_gset: + { + \cs_gset_protected:Npx \@@_debug:n ##1 + { \bool_if:NT \g_@@_debug_bool {##1} } + \cs_gset_protected:Npx \@@_debug_typeout:n ##1 + { \bool_if:NT \g_@@_debug_bool { \typeout{==>~ ##1} } } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\DebugBlocksOn,\DebugBlocksOff} +% +% \begin{macrocode} +\cs_new_protected:Npn \DebugBlocksOn { \block_debug_on: } +\cs_new_protected:Npn \DebugBlocksOff { \block_debug_off: } +% \end{macrocode} +% +% \begin{macrocode} +\DebugBlocksOff +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Implementation of the document-level block environments} +% +% Most such environments are pretty simple: they take an option +% argument and call a \texttt{blockenv} instance to do the work. At +% the end of environment we call \cs{endblockenv} to finish. +% +% +% \subsubsection{Displayblock environments} +% +% +% There are two basic block environment which are similar to +% \LaTeXe{}'s \env{trivlist} except that there aren't degenerated +% lists and thus have no hidden \cs{item} inside. +% +% +% \begin{environment}{displayblock} +% +% \begin{macrocode} +\NewDocumentEnvironment{displayblock}{ !O{} } + { \UseInstance{blockenv}{displayblock} {#1} } + { \endblockenv } +% \end{macrocode} +% \end{environment} +% +% +% +% +% \begin{environment}{displayblockflattened} +% +% \begin{macrocode} +\NewDocumentEnvironment{displayblockflattened}{ !O{} } + { \UseInstance{blockenv}{displayblockflattened} {#1} } + { \endblockenv } +% \end{macrocode} +% \end{environment} +% +% +% +% +% +% +% +% +% \begin{environment}{center,flushleft,flushright} +% +% \begin{macrocode} +\AddToHook{begindocument/before}{ + \RenewDocumentEnvironment{center} { !O{} } + { \UseInstance{blockenv}{center}{#1} } + { \endblockenv } +% \end{macrocode} +% +% \begin{macrocode} + \RenewDocumentEnvironment{flushright} { !O{} } + { \UseInstance{blockenv}{flushright}{#1} } + { \endblockenv } +% \end{macrocode} +% +% \begin{macrocode} + \RenewDocumentEnvironment{flushleft} { !O{} } + { \UseInstance{blockenv}{flushleft}{#1} } + { \endblockenv } +} +% \end{macrocode} +% +% +% \end{environment} +% +% +% +% +% \subsubsection{Display quote environments} +% +% +% \begin{environment}{quote,quotation} +% +% \begin{macrocode} +\AddToHook{begindocument/before}{ + \RenewDocumentEnvironment{quote}{ !O{} } + { \UseInstance{blockenv}{quote} {#1} } + { \endblockenv } +% \end{macrocode} +% +% \begin{macrocode} + \RenewDocumentEnvironment{quotation}{ !O{} } + { \UseInstance{blockenv}{quotation} {#1} } + { \endblockenv } +} +% \end{macrocode} +% \end{environment} +% +% +% +% +% +% +% \subsubsection{Verbatim environments} +% +% +% \begin{environment}{verbatim,verbatim*} +% +% \begin{macrocode} +\AddToHook{begindocument/before}{ + \RenewDocumentEnvironment{verbatim}{ !O{} } + { \UseInstance{blockenv}{verbatim} {#1} +% \end{macrocode} +% This is the part of the code where \env{verbatim} +% and\env{verbatim*} differ. +% \begin{macrocode} + \@setupverbinvisiblespace\frenchspacing\@vobeyspaces + \@xverbatim + } + { \endblockenv } +% \end{macrocode} +% +% \begin{macrocode} + \RenewDocumentEnvironment{verbatim*}{ !O{} } + { \UseInstance{blockenv}{verbatim} {#1} + \@setupverbvisiblespace\frenchspacing\@vobeyspaces + \@sxverbatim + } + { \endblockenv } +} +% \end{macrocode} +% \end{environment} +% +% +% +% \paragraph{Helper commands for verbatim} +% +% +% \begin{macro}{\legacyverbatimsetup} +% +% This code resembles the \LaTeXe{} verbatim implementation with a +% slight twist: in \LaTeXe{} each code line was a paragraph using +% \cs{leftskip}=\cs{@totalleftmargin}. This was possible because +% the whole environment was implemented as a trivlist. As this is +% no longer the case setting \cs{leftskip} would alter the layout +% of a surrounding list. So instead we need to make sure that the +% paragraph end is executed in a group so that any parshape setup +% is preserved. +% \begin{macrocode} +%<@@=> +\def\legacyverbatimsetup{% + \language\l@nohyphenation + \@tempswafalse + \def\par{% + \if@tempswa + \leavevmode \null {\@@par}\penalty\interlinepenalty + \else + \@tempswatrue + \ifhmode{\@@par}\penalty\interlinepenalty\fi + \fi}% + \let\do\@makeother \dospecials + \obeylines \verbatim@font \@noligs + \everypar \expandafter{\the\everypar \unpenalty}% +% \end{macrocode} +% +% \begin{macrocode} + \tl_set:Nn \l__tag_para_main_tag_tl {codeline} + \tagtool{paratag=Code}% oder faster: \tl_set:Nn\l__tag_para_tag_tl{Code} +} +%<@@=block> +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@setupverbinvisiblespace} +% In the \pdfTeX{} engine we need to use \cs{pdffakespace} chars +% for the invisible spaces. +% \begin{macrocode} +\newcommand\@setupverbinvisiblespace{} +\tag_if_active:T { + \bool_if:NF\g__tag_mode_lua_bool + { + \renewcommand\@setupverbinvisiblespace{\def\@xobeysp{\nobreakspace\pdffakespace}} + } +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsubsection{Standard list environments} +% +% +% \begin{environment}{itemize,enumerate,description} +% +% For the standard lists everything is managed by the blockenv instance. +% \begin{macrocode} +\AddToHook{begindocument/before}{ + \RenewDocumentEnvironment{itemize}{!O{}} + { \UseInstance{blockenv}{itemize} {#1} } + { \endblockenv } +% \end{macrocode} +% +% \begin{macrocode} + \RenewDocumentEnvironment{enumerate}{!O{}} + { \UseInstance{blockenv}{enumerate} {#1} } + { \endblockenv } +% \end{macrocode} +% +% \begin{macrocode} + \RenewDocumentEnvironment{description}{!O{}} + { \UseInstance{blockenv}{description} {#1} } + { \endblockenv } +} +% \end{macrocode} +% \end{environment} +% +% +% +% +% +% +% \begin{environment}{list} +% +% The legacy 2e list environment is more complicated as we have to get the +% extra arguments accounted for. +% \begin{macrocode} +\AddToHook{begindocument/before}{ + \RenewDocumentEnvironment{list}{O{} m m } + { +% \end{macrocode} +% We do this by storing them away and then call the list +% instance. Inside this instance the \texttt{setup-code} key +% contains \cs{legacylistsetupcode}, which makes use of the stored values. +% \begin{macrocode} + \tl_set:Nn \@itemlabel {#2} + \tl_set:Nn \l_@@_legacy_env_params_tl {#3} +% \end{macrocode} +% +% \begin{macrocode} + \UseInstance{blockenv}{list} {#1} + } + { \endblockenv } +} +% \end{macrocode} +% +% Again something that should probably elsewhere: the rolemapping. +% \begin{macrocode} +\tag_if_active:T { + \tagpdfsetup{add-new-tag={tag=list,role=L}} +} +% \end{macrocode} +% \end{environment} +% +% +% +% \begin{variable}{\l_@@_env_params_tl} +% Declare the variable for the parameter argument; \cs{@itemlabel} +% is already declared in \LaTeXe{}. +% \begin{macrocode} +\tl_new:N \l_@@_env_params_tl +% \end{macrocode} +% \end{variable} +% +% +% \begin{macro}{\legacylistsetupcode} +% +% And here is the extra code for use in the list instance setup +% inside the key \texttt{setup-code}. +% \begin{macrocode} +\cs_new:Npn \legacylistsetupcode { +% \end{macrocode} +% Reset values to defaults: +% \begin{macrocode} + \dim_zero:N \listparindent + \dim_zero:N \rightmargin + \dim_zero:N \itemindent +% \end{macrocode} +% +% By default a \env{list} environment is not numbered: +% \begin{macrocode} + \tl_set:Nn \@listctr {} + \legacy_if_set_false:n { @nmbrlist } % needed if lists are nested +% \end{macrocode} +% By default there is a simple definition for \cs{makelabel}. It can be +% overwritten in the second mandatory argument to the list +% environment (stored in \cs{l_@@_legacy_env_params_tl}) and +% is used if the instance sets the compatibility key to true. +% \begin{macrocode} + \let\makelabel\@mklab % TODO: customize +% \end{macrocode} +% Now we use the argument with parameter settings to update some or +% all of the above defaults: +% \begin{macrocode} + \l_@@_legacy_env_params_tl +% \end{macrocode} +% As we don't know much about this list we can only make a guess about +% the nature of the list and the setting of the tag name (default +% \texttt{list} rolemapped to \texttt{L}) and any tag attributes +% may have to be overwritten in the optional key/value argument. But we do have some hints to play with. +% \begin{macrocode} + \legacy_if:nTF { @nmbrlist } + { \tl_set:Nn \l__tag_L_attr_class_tl {enumerate} } % numbered list + { \tl_if_empty:NTF \@itemlabel + { \tl_set:Nn \l__tag_L_attr_class_tl {list} } % no label + { \tl_set:Nn \l__tag_L_attr_class_tl {itemize} } % unnumbered, unordered + } +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{environment}{trivlist} +% +% \begin{macrocode} +\AddToHook{begindocument/before}{ + \RenewDocumentEnvironment{trivlist}{ !O{} } + { \list[#1]{} + { + \dim_zero:N \leftmargin + \dim_zero:N \labelwidth + \cs_set_eq:NN \makelabel \use:n + } + } + { \endblockenv } +} +% \end{macrocode} +% \end{environment} +% +% +% \subsubsection{Theorem-like environments} +% +% Theorem-like environments are defined in \LaTeX{} with the help of +% \cs{newtheorem} declarations. Internally they used a list with a +% single item. Using lists was convenient back then, but in a tagged +% document you end up with a strange structure. We therefore alter the +% mechanism. +% +% +% \begin{macro}{\newtheorem} +% This is a slightly streamlined version of \cs{newtheorem}, but it +% still uses a lot of the 2e code for now. Eventually this will change. +% \begin{macrocode} +\RenewDocumentCommand \newtheorem { m O{#1} m o } +{ + \expandafter\@ifdefinable\csname #1\endcsname + { + \str_if_eq:nnTF{#1}{#2} + { + \@definecounter {#2} + \IfNoValueTF {#4} + { % @ynthm + \tl_gset:cx { the #2 } + { + \@thmcounter{#2} + } + } + { % @xnthm + \@newctr{#1}[#4] + \tl_gset:cx { the #2 } + { + \expandafter\noexpand\csname the#4\endcsname + \@thmcountersep + \@thmcounter{#2} + } + } + } + { % @othm + \@ifundefined{c@#2} + { \@nocounterr{#2} } + { + \tl_gset:cn { the #1 } + { \UseName { the #2 } } + } + } + \global\@namedef{#1} { \@thm{#2}{#3} } + \global\@namedef{end#1}{ \@endtheorem } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@begintheorem,\@opargbegintheorem} +% +% The \cs{@thm} command expands to either \cs{@beginthorem} or +% \cs{@opargbegintheorem}. For the moment we stick with this as it +% will help with the transion. But instead of using a +% \env{trivlist} we use a blockenv and some tagging for the title +% (as a Caption). +% We do not want potential tagging from \cs{textbf} here, +% so we use \cs{bfseries} to set the font. +% \begin{macrocode} +\def\@begintheorem#1#2{ + \UseInstance{blockenv}{theorem}{} + \tagpdfparaOff + \mode_leave_vertical: + \tag_struct_begin:n{tag=Caption} + \group_begin: + \bfseries + \tag_mc_begin:n {} + #1\ + \tag_mc_end: + \tag_struct_begin:n{tag=Lbl} + \tag_mc_begin:n {} + #2 + \tag_mc_end: + \tag_struct_end: + \group_end: + \tag_struct_end: + \tagpdfparaOn +% \end{macrocode} +% +% \begin{macrocode} + \@@_start_para_structure_unconditionally:n { \PARALABEL } +% \end{macrocode} +% +% \begin{macrocode} + \itshape + \hskip\labelsep + \ignorespaces +} +\def\@opargbegintheorem#1#2#3{ + \UseInstance{blockenv}{theorem}{} + \tagpdfparaOff + \mode_leave_vertical: + \tag_struct_begin:n{tag=Caption} + \group_begin: + \bfseries + \tag_mc_begin:n {} + #1\ + \tag_mc_end: + \tag_struct_begin:n{tag=Lbl} + \tag_mc_begin:n {} + #2 + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin:n {} + \ (#3) + \tag_mc_end: + \group_end: + \tag_struct_end: + \tagpdfparaOn +% \end{macrocode} +% +% \begin{macrocode} + \@@_start_para_structure_unconditionally:n { \PARALABEL } +% \end{macrocode} +% +% \begin{macrocode} + \itshape + \hskip\labelsep + \ignorespaces +} +% \end{macrocode} +% +% \begin{macrocode} +\def\@endtheorem{\endblockenv} +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% \subsection{Implementation of templates} +% +% +% \subsubsection{Implementation of blockenv templates \ldots} +% +% +% +% \begin{macro}{\g_block_nesting_depth_int} +% \LaTeXe{} already has a counter to record the nesting depth of +% blocks, but we want our own name because it isn't really tied to +% \enquote{lists} any more. However, \cs{@listdepth} is really part +% of the legacy interface (for example \env{minipage} alters it to +% point to a different counter) so that we are stuck with using at +% least indirectly for now and the following line makes this look +% like an L3 integer variable but internally expands to \cs{@listdepth}: +% \begin{macrocode} +\cs_new:Npn \g_block_nesting_depth_int { \@listdepth } % a fake int + % for now +% \end{macrocode} +% \end{macro} +% +% +% \begin{template}{blockenv display} +% +% \begin{macrocode} +\DeclareTemplateCode{blockenv}{display}{1} +{ + env-name = \l_@@_env_name_tl , + tag-name = \l_@@_tag_name_tl , + tag-class = \l_@@_tag_class_tl , + tagging-recipe = \l_@@_tagging_recipe_tl , + level-increase = \l_@@_level_incr_bool , + setup-code = \l_@@_setup_code_tl , + block-instance = \l_@@_block_instance_tl , + para-instance = \l_@@_para_instance_tl , + inner-level-counter = \l_@@_inner_level_counter_tl , + max-inner-levels = \l_@@_max_inner_levels_tl , + inner-instance-type = \l_@@_inner_instance_type_tl , + inner-instance = \l_@@_inner_instance_tl , + para-flattened = \l__tag_para_flattened_bool , + final-code = \l_@@_final_code_tl , +} +{ + \@@_debug_typeout:n{\l_@@_env_name_tl -env-start} +% + \tl_if_empty:nF {#1} { \SetTemplateKeys{blockenv}{display}{#1} } +% +% \end{macrocode} +% We need to know later if we haved nested blockenvs inside +% a flattened environment. Whenever we start a new blockenv we +% increment \cs{\l_@@_flattened_level_int} if it is already +% different from zero. If it is zero we increment it if flattening +% is requested. +% Thus a value of \texttt{0} means no flattening requested so far +% and \texttt{1} means this is the first blockenv requesting +% flattening. In either case we have to make sure that the blockenv +% is surrounded by a \texttt{text-unit} tag, while for any value above +% \texttt{1} we have to omit the \texttt{text-unit}. + % \begin{macrocode} + \int_compare:nNnTF \l_@@_flattened_level_int > 0 + { + \int_incr:N \l_@@_flattened_level_int + } + { + \bool_if:NT \l__tag_para_flattened_bool + { + \int_incr:N \l_@@_flattened_level_int + } + } +% + \tl_if_empty:NF \l_@@_inner_level_counter_tl + { + \int_compare:nNnTF \l_@@_inner_level_counter_tl > + { \l_@@_max_inner_levels_tl - 1 } + { \@toodeep } + { \int_incr:N \l_@@_inner_level_counter_tl } % not clean "o"? + } +% \end{macrocode} +% Legacy defaults are only roped in if the list level changes. For +% display blocks that remain on the same level the current values +% are kept. +% \begin{macrocode} + \bool_if:NT \l_@@_level_incr_bool + { + \int_compare:nNnTF \g_block_nesting_depth_int > + { \c@maxblocklevels - 1 } + { \@toodeep } + { + \int_gincr:N \g_block_nesting_depth_int +% \end{macrocode} +% If there are no legacy defaults for that level then the next line +% does nothing, i.e., the current values (from the last level +% become the defaults for the next. +% \begin{macrocode} + \use:c { @list \int_to_roman:n { \g_block_nesting_depth_int } } + } + } +% \end{macrocode} +% If we are doing tagging we load one of the available recipes for +% tagging, which alters various kernel hooks to add appropriate +% tagging structures. +% \begin{macrocode} + \tag_if_active:T { \use:c { @@_recipe_ \l_@@_tagging_recipe_tl : } } +% \end{macrocode} +% Then run the setup code if any is given in the instance. +% \begin{macrocode} + \l_@@_setup_code_tl +% \end{macrocode} +% Next call a block instance at the appropriate level passing it +% any key/value list provided in the optional argument (keys that +% are not recognized are ignored---currently with an +% error). +% \begin{macrocode} + \@@_debug_typeout:n{use~ instance:~ + \l_@@_block_instance_tl - \int_use:N \g_block_nesting_depth_int } + \UseInstance{block} + { \l_@@_block_instance_tl - \int_use:N + \g_block_nesting_depth_int } + {#1} +% \end{macrocode} +% After the block instance call the para and then inner (list) +% instance if either or both are +% specified (which may not be the case). +% \begin{macrocode} + \tl_if_empty:NF \l_@@_para_instance_tl + { + \@@_debug_typeout:n{use~ para~ instance:~ \l_@@_para_instance_tl } +% \end{macrocode} +% For now we don't offer to alter instance parameters here so we +% pass an empty argument. +% \begin{macrocode} + \UseInstance{para}{ \l_@@_para_instance_tl } {} + } +% \end{macrocode} +% In the inner instance may have its own levels or none depending +% on which the instance name differs. Again we pass it the optional +% key/value list. +% \begin{macrocode} + \tl_if_empty:NF \l_@@_inner_instance_tl + { + \@@_debug_typeout:n{use~ instance:~ \l_@@_inner_instance_tl + \tl_if_empty:NF \l_@@_inner_level_counter_tl + { - \int_use:N \l_@@_inner_level_counter_tl }} + \UseInstance{ \l_@@_inner_instance_type_tl } + { \l_@@_inner_instance_tl + \tl_if_empty:NF \l_@@_inner_level_counter_tl + { - \int_use:N \l_@@_inner_level_counter_tl } % not clean + % use "o"? + } + {#1} + } +% \end{macrocode} +% We finish off with \cs{l_@@_final_code_tl} which defaults to +% \cs{ignorespaces} so that spaces between \verb=\begin{...}= and +% the start of the text are ignored. +% \begin{macrocode} + \l_@@_final_code_tl +} +% \end{macrocode} +% \end{template} +% +% +% \begin{macro}{\l_@@_flattened_level_int} +% Count the levels of nested blockenvs starting with the first that +% is \enquote{flattened}. +% \begin{macrocode} +\int_new:N \l_@@_flattened_level_int +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\c@maxblocklevels} +% A counter to increase or decrease the number of supported +% level. If increased, one needs to suply additional level instances. +% \begin{macrocode} +\newcounter{maxblocklevels} +\setcounter{maxblocklevels}{6} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\endblockenv} +% The code executed when a blockenv ends is 99\% the same for all +% blockenvs (at least up to now). Small differences exist, though. They +% are accounted for first in the conditionals. +% +% We make this a public command so that new block environments can +% be set up without the need to resort to L3 layer +% programming.\fmi{name is bad} +% \begin{macrocode} +\cs_new:Npn \endblockenv { + \@@_debug_typeout:n{blockenv~ common~ ending \on@line} +% \end{macrocode} +% If this block was incrementing the level we have to decrement it +% now again: +% \begin{macrocode} + \bool_if:NT \l_@@_level_incr_bool + { \int_gdecr:N \g_block_nesting_depth_int } +% \end{macrocode} +% If this block was a list and there are still \cs{item} labels to +% be placed we move to horizontal mode to get them typeset. +% \begin{macrocode} + \legacy_if:nT { @inlabel } + { + \mode_leave_vertical: + \legacy_if_gset_false:n { @inlabel } + } +% \end{macrocode} +% In a pure ``displayblock'' scenario \texttt{@newlist} will be +% always false and the code bypassed, but we may have an outer list +% followed immediately by a displayblock (with the \cs{item} missing) +% \begin{macrocode} + \legacy_if:nT { @newlist } + { + \@noitemerr + \legacy_if_gset_false:n { @newlist } + } + \mode_if_horizontal:TF + { \@@_skip_remove_last: \@@_skip_remove_last: \par } + { \@inmatherr{\end{\@currenvir}} } +% \end{macrocode} +% Once we are back in vertical mode we can add the appropriate +% closing tagging structure(s), if we are doing tagging. +% \begin{macrocode} + \__kernel_displayblock_end: +% \end{macrocode} +% What to do in terms of vertical spacing in different situations +% is still somewhat open to debate, right now this is more or less +% implementing what \LaTeXe{} list environment have been +% doing.\fmi{some redesign/extensions here?} +% \begin{macrocode} +% \@@_debug_typeout:n{@noparlist = +% \legacy_if:nTF { @noparlist }{true}{false}} + \legacy_if:nF { @noparlist } + { + \@@_skip_set_to_last:N \l_tmpa_skip + \dim_compare:nNnT \l_tmpa_skip > \c_zero_dim + { + \skip_vertical:n { - \l_tmpa_skip } + \skip_vertical:n { \l_tmpa_skip + \parskip - \@outerparskip } + } + \addpenalty \@endparpenalty + \addvspace \l_@@_topsepadd_skip +% \end{macrocode} +% \LaTeXe{} triggered the paragraph handling after a list at this +% point here, i.e., only if the list didn't start a paragraph. One +% can make a case for that, but it can be somewhat surprising to +% the user and there is a good argument that even such a list could +% be followed expanatory text that is part of the same paragraph +% and doesn't start a new one.\fmi{decide which logic we want to +% use! If the old logic is used we need to close the text-unit +% ourselves in the true branch} +% \begin{macrocode} +% \legacy_if_gset_true:n { @endpe } + } +% \end{macrocode} +% So this is for now always done. Probably \cs{l_@@_topsepadd_skip} above +% should be added only if the paragraph ends here and not if it +% continues, so this need some further cleanup.\fmi{decide} + % \begin{macrocode} + \bool_if:NTF \l_@@_standalone_bool +% \end{macrocode} +% It is possible that \texttt{@endpe} is true because a +% displayblock has just ended before we end the standalone +% displayblock and in that casevthere is no outer +% \struct{text-unit} so we have to explicitly set \texttt{@endpe} +% back to false to prevent it from closing a structure later that +% isn't there. +% \begin{macrocode} + { \legacy_if_gset_false:n { @endpe } } + { \legacy_if_gset_true:n { @endpe } } +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\__kernel_displayblock_end:} +% The kernel hook for tagging at the end of the block. +% \begin{macrocode} +\cs_new:Npn \__kernel_displayblock_end: { + \@@_debug_typeout:n{\detokenize{__kernel_displayblock_end:}} +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\l_@@_standalone_bool} +% +% \begin{macrocode} +\bool_new:N \l_@@_standalone_bool +\bool_set_false:N \l_@@_standalone_bool +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% \subsubsection{Implementation of para templates \ldots} +% +% \begin{template}{para std} +% +% \begin{macrocode} +\DeclareTemplateCode{para}{std}{1} +{ + indent-width = \parindent , + start-skip = \l__par_start_skip , % name?? + left-skip = \leftskip , + right-skip = \rightskip , + end-skip = \parfillskip , + fixed-word-spaces = \l__par_fixed_word_spaces_bool , % name?? + final-hyphen-demerits = \finalhyphendemerits , + cr-cmd = \\ , + para-class = \l_tag_para_attr_class_tl , +} +{ + \tl_if_empty:nF {#1} { \SetTemplateKeys{para}{std}{#1} } + \skip_set:Nn \@rightskip \rightskip +} +% \end{macrocode} +% \end{template} +% +% +% +% +% +% \subsubsection{Implementation of block templates \ldots} +% +% +% +% +% +% \begin{template}{block display} +% +% \begin{macrocode} +\DeclareTemplateCode{block}{display}{1} +{ + heading = \l_@@_heading_tl , + beginsep = \topsep , + begin-par-skip = \partopsep , + par-skip = \parsep , + end-skip = \l_@@_botsep_skip , + end-par-skip = \l_@@_parbotsep_skip , + beginpenalty = \@beginparpenalty , + endpenalty = \@endparpenalty , + rightmargin = \rightmargin , + leftmargin = \leftmargin , + parindent = \listparindent , +} +{ + \tl_if_empty:nF {#1} { \SetTemplateKeys{block}{display}{#1} } +% \end{macrocode} +% \fmi{generalize heading usage (or drop?)} +% \begin{macrocode} + \tl_if_blank:oF \l_@@_heading_tl + { \mode_leave_vertical: \textbf{\l_@@_heading_tl} } % TODO customize +% \end{macrocode} +% The code largely follows the logic of \LaTeXe{}'s \env{trivlist} +% implementation as far as it applicable for the \enquote{display +% block} but coded using the L3 programming layer. However, we keep +% all the legacy variables (e.g., \texttt{@noskipsec}) if there is +% some chance that they are set in classes or packages. +% \begin{macrocode} + \legacy_if:nT { @noskipsec } { \mode_leave_vertical: } + \skip_set:Nn \l_@@_topsepadd_skip { \topsep } + \mode_if_vertical:TF + { + \skip_add:Nn \l_@@_topsepadd_skip { \partopsep } +% \end{macrocode} +% At this point it is safe to add tagging structure(s) so we have +% a kernel-owned hook here for tagging. This is used to possibly +% start a paragraph structure (to surround the block, for example, +% in case of lists) and possibly do some other preparation for +% tagging the block. +% \begin{macrocode} + \__kernel_displayblock_beginpar_vmode: + } + { +% \end{macrocode} +% If we are in horizontal mode then the displayblock has to return +% to vertical mode now (after removing any immediately preceding +% skip or kern. But before we actually issue the\cs{par} we execute +% a kernel hook in which we can add tagging code. This hook is +% \enquote{weird} because by default it does nothing, but if +% tagging is wanted it takes an argument and grabs the following +% \cs{par} in order to put tagging code before and after the \cs{par}. +% \begin{macrocode} + \@@_skip_remove_last: \@@_skip_remove_last: + \__kernel_displayblock_beginpar_hmode:w \par + } +% \end{macrocode} +% Now we are back to legacy list implementation \ldots +% \begin{macrocode} + \legacy_if:nTF { @inlabel } + { + \legacy_if_set_true:n { @noparitem } + \legacy_if_set_true:n { @noparlist } + } + { + \legacy_if:nT { @newlist } { \@noitemerr } + \legacy_if_set_false:n { @noparlist } + \skip_set_eq:NN \l_@@_effective_top_skip \l_@@_topsepadd_skip + } + \skip_add:Nn \l_@@_effective_top_skip { \parskip } +% \end{macrocode} +% Next lines set some paragraph defaults, this may get overwritten +% if there is a \key{para-instance} specified on the \xt{blockenv}. +% \begin{macrocode} + \skip_zero:N \leftskip + \skip_set_eq:NN \rightskip \@rightskip + \skip_set_eq:NN \parfillskip \@flushglue +% \end{macrocode} +% The next lines establish a parshape which is retained across +% paragraphs be executing \cs{para_end:} within a group and thus +% reestablishing the parshape for the next paragraph again. In case +% a list got started \cs{par} is ignored until we have seen an +% \cs{item} (or we have executed \cs{par} one thousand times. +% \begin{macrocode} + \int_zero:N \par@deathcycles + \@setpar + { + \legacy_if:nTF { @newlist } + { + \int_incr:N \par@deathcycles + \int_compare:nNnTF \par@deathcycles > { 1000 } + { \@noitemerr + { \para_end: } + } + } + { + { \para_end: } + } + } + \skip_set_eq:NN \@outerparskip \parskip + \skip_set_eq:NN \parskip \parsep + \dim_set_eq:NN \parindent \listparindent + \dim_add:Nn \linewidth { - \rightmargin - \leftmargin } + \dim_add:Nn \@totalleftmargin { \leftmargin } + \tex_parshape:D 1 ~ \@totalleftmargin \linewidth +% \end{macrocode} +% This is the point where we are ready to add the tagging structure +% for the block, e.g., an \verb=<L>=, a \verb=<Figure>= or some +% other structure. +% \begin{macrocode} + \__kernel_displayblock_begin: +% \end{macrocode} +% Finally, we have to output the vertical separation and penalty at +% the start of the block and make corrections for a change in +% \cs{parskip} and some other housekeeping, unless this block is inside a list and the list +% \cs{item} has not yet placed. In that case the vertical +% space and penalty us suppressed. This +% is controled through the legacy switches \texttt{@noparitem}, +% \texttt{minipage}, and \texttt{@nobreak}. +% \begin{macrocode} + \legacy_if:nTF { @noparitem } + { + \legacy_if_set_false:n { @noparitem } + \hbox_gset:Nn \g_@@_labels_box + { + \skip_horizontal:n { - \leftmargin } + \hbox_unpack_drop:N \g_@@_labels_box + \skip_horizontal:n { \leftmargin } + } +% \end{macrocode} +% \fmi{document 2e logic used here} +% \begin{macrocode} + \legacy_if:nF { @minipage } % Why this chunk of code? + { + \@@_skip_set_to_last:N \l_@@_tmpa_skip + \skip_vertical:n { - \l_@@_tmpa_skip } + \skip_vertical:n { \l_@@_tmpa_skip + \@outerparskip - \parskip } + } + } + { + \legacy_if:nTF { @nobreak } + { \addvspace{\skip_eval:n{\@outerparskip-\parskip}} } + { + \addpenalty \@beginparpenalty + \addvspace \l_@@_effective_top_skip + \addvspace{-\parskip} + } + } +} +% \end{macrocode} +% +% +% Extra keys to support enumitem conventions: +% \begin{macrocode} +\keys_define:nn { template/block/display } +{ + ,topsep .skip_set:N = \topsep + ,partopsep .skip_set:N = \partopsep + ,listparindent .skip_set:N = \listparindent +} +% \end{macrocode} +% \end{template} +% +% +% +% \begin{macro}{\__kernel_displayblock_begin:, +% \__kernel_displayblock_beginpar_hmode:w, +% \__kernel_displayblock_beginpar_vmode:} +% The internal kernel hooks for tagging. +% \begin{macrocode} +\cs_new:Npn \__kernel_displayblock_begin: { + \@@_debug_typeout:n{\detokenize{__kernel_displayblock_begin:}} +} +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Npn \__kernel_displayblock_beginpar_hmode:w { + \@@_debug_typeout:n{\detokenize{__kernel_displayblock_beginpar_hmode:w}} +} +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Npn \__kernel_displayblock_beginpar_vmode: { + \@@_debug_typeout:n{\detokenize{__kernel_displayblock_beginpar_vmode:}} +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsubsection{Implementation of list templates \ldots} +% +% +% +% \begin{macro}{\@itemlabel,\@listctr} +% Both \cs{@itemlabel} and \cs{@listctr} from the \LaTeXe{} list +% implementation are used (or set) by various packages. We +% therefore use them too, so that these packages have a fighting +% chance to work with the new tagging-aware implementation for +% \env{list}. +% \begin{macrocode} +\tl_new:N \@itemlabel % should have a top-level definition +\tl_new:N \@listctr % should have a top-level definition +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% \begin{template}{list std} +% +% This template implements numbered and unnumbered lists and can +% be combined with display blocks or with inline blocks. +% \begin{macrocode} +\DeclareTemplateCode{list}{std}{1} +{ + counter = \l_@@_counter_tl, + item-label = \l_@@_item_label_tl, + start = \l_@@_counter_start_int , + resume = \l_@@_resume_bool , + item-instance = \@@_item_instance:n , + item-skip = \itemsep , +% item-par-skip = \parsep , + item-penalty = \@itempenalty , + item-indent = \itemindent , + label-width = \labelwidth , + label-sep = \labelsep , + legacy-support = \l_@@_legacy_support_bool , % FMi questionable +} +{ + \@@_debug_typeout:n{template:list:std} +% + \tl_if_empty:nF {#1} { \SetTemplateKeys{list}{std}{#1} } +% \end{macrocode} +% Has this list a counter name defined in the instance? +% \begin{macrocode} + \tl_if_empty:NTF \l_@@_counter_tl + { +% \end{macrocode} +% If not we check if \cs{@listctr} has a non-empty value to be used +% for the list counter. +% +% We better test for blank not empty in case somebody had defined +% \cs{@listctr} using \cs{renewcommand} or \cs{cs_set:Npn}. +% \begin{macrocode} + \tl_if_blank:oF \@listctr + { +% \end{macrocode} +% In that case \texttt{@nmbrlist} should have been set too, for +% example, through \cs{usecounter}, so we do not set it +% explicitly. However, we check if we should resume a previous list. +% \begin{macrocode} + \bool_if:NF \l_@@_resume_bool + { + \int_gset:cn{ c@ \@listctr } + { \l_@@_counter_start_int - 1 } + } + } +% \end{macrocode} +% If \cs{@listctr} is not set then we have definitely an unnumbered list. +% \begin{macrocode} + { \@nmbrlistfalse } + } +% \end{macrocode} +% If a counter is set in the list instance we use that +% one. This should be the name of a \LaTeX{} counter that is +% already allocated externally---no runtime check is made for this: +% if it is not declared one will get \enquote{no such counter} +% error when the list is used. +% \begin{macrocode} + { + \@nmbrlisttrue + \tl_set_eq:NN \@listctr \l_@@_counter_tl + \bool_if:NF \l_@@_resume_bool + { + \int_gset:cn{ c@ \@listctr } + { \l_@@_counter_start_int - 1 } + } + } +% \end{macrocode} +% Does the current instance has an item label representation? This +% would be possible whether or not we have a numbered list. If yes, +% then we use this for \cs{@itemlabel}, otherwise we expect that +% \cs{@itemlabel} is provided from the outside, e.g., as part of +% the \env{list} environment argument. +% \begin{macrocode} + \tl_if_empty:NF \l_@@_item_label_tl + { + \tl_set_eq:NN \@itemlabel \l_@@_item_label_tl + } +% \end{macrocode} +% finally, we signal that we are at the start of a new list (which +% effects how the first \cs{item} is handled and how \cs{par} +% commands are interpreted. +% \begin{macrocode} + \legacy_if_gset_true:n { @newlist } +% \end{macrocode} +% +% \begin{macrocode} + \@@_debug_typeout:n{template:list:std~end} +} +% \end{macrocode} +% +% +% Extra keys to support enumitem conventions: +% \begin{macrocode} +\keys_define:nn { template/list/std } +{ + ,nosep .code:n = + \dim_zero:N \itemsep + \dim_zero:N \parsep + \dim_zero:N \topsep + \dim_zero:N \l_@@_botsep_skip + \dim_zero:N \l_@@_parbotsep_skip + ,midsep .skip_set:N = \topsep +} +% \end{macrocode} +% +% \end{template} +% +% +% \subsubsection{Implementation of \cs{item} template(s)} +% +% +% +% \begin{template}{item std} +% The item template has one hidden key \texttt{label} which is not available on the +% template for setting because it is only used to receive any +% optional data passed to the \cs{item} command. We therefore +% declare it with \cs{keys_define:nn} and ensure that the optional +% argument data to \cs{item} (if it is not a key/value list +% already) is passed to this \texttt{label} key. +% \begin{macrocode} +\keys_define:nn { template/item/std } + { label .tl_set:N = \l_@@_label_given_tl } +% \end{macrocode} +% +% \fmi{alignment is mostly wrong (test short medium and multiline +% labels)} +% \begin{macrocode} +\DeclareTemplateCode{item}{std}{1} + { + counter-label = \@@_counter_label:n , + counter-ref = \@@_counter_ref:n , +% \end{macrocode} +% \fmi{next set of key not yet used} +% \begin{macrocode} + label-ref = \@@_label_ref:n , + label-autoref = \@@_label_autoref:n , + label-format = \@@_label_format:n , + label-strut = \l_@@_label_strut_bool , + label-boxed = \l_@@_label_boxed_bool , + next-line = \l_@@_next_line_bool , + text-font = \l_@@_text_font_tl , + compatibility = \l_@@_item_compatibility_bool , +% \end{macrocode} +% This probably needs a different implementation (and needs completing)\fmi{complete} +% \begin{macrocode} + label-align = { + left = \tl_set:Nn \l_@@_item_align_tl { \relax \hss } , + center = \tl_set:Nn \l_@@_item_align_tl { \hss \hss } , + right = \tl_set:Nn \l_@@_item_align_tl { \hss \relax } , + parleft = \NOT_IMPLEMENTED , + } , + } +% \end{macrocode} +% Then typeset the label at its natural width by applying +% \cs{@@_make_label_box:n} to the label given or to a label constructed +% from the counter. If it is boxed and reasonably short, add padding to +% make it at least of size \tn{labelwidth}, then add another layer of +% box. This way, when we unpack it in \cs{g_@@_labels_box} it correctly +% remains boxed in those cases. Afterwards, in the \texttt{nextline} +% case add \tn{newline} if the label did not fit in the allotted space. +% \begin{macrocode} + { + \@@_debug_typeout:n{template:item:std} +% \end{macrocode} +% +% First deal with the key--value input, which in particular may +% provide a value for the label (the usual optional argument of +% \cs{item}). For this we set \cs{l_@@_label_given_tl} to +% \cs{c_novalue_tl} so that we can identify if an optional argument +% was given. +% \begin{macrocode} + \tl_set_eq:NN \l_@@_label_given_tl \c_novalue_tl + \tl_if_empty:nF{#1}{ \SetTemplateKeys{item}{std}{#1} } +% \end{macrocode} +% If no optional argument was given then \cs{l_@@_label_given_tl} +% is still equal to \cs{c_novalue_tl} and so we can distinuish +% that from \verb=\item[]=. +% +% \begin{macrocode} + \tl_if_novalue:oTF \l_@@_label_given_tl + { +% \end{macrocode} +% The rest of the code for this template needs work and is both +% incomplete and partly wrong.\fmi{fix} +% \begin{macrocode} + \tl_if_blank:oF \@listctr { \@kernel@refstepcounter \@listctr } + \bool_if:NTF \l_@@_item_compatibility_bool % not sure that conditional + % makes sense + { \@@_make_label_box:n { \MakeLinkTarget[\@listctr]{}\@itemlabel } } % TODO ? + { \@@_make_label_box:n { \MakeLinkTarget[\@listctr]{}\@@_counter_label:n { \@listctr } } } + } + { + \@@_debug_typeout:n{item~ with~ optional} + \@@_make_label_box:n { \l_@@_label_given_tl } } + \bool_if:nT + { + \l_@@_label_boxed_bool + && \dim_compare_p:n { \box_wd:N \l_@@_one_label_box <= \linewidth } % TODO: is \linewidth correct? + } + { + \dim_compare:nNnT + { \box_wd:N \l_@@_one_label_box } < \labelwidth + { + \hbox_set_to_wd:Nnn \l_@@_one_label_box { \labelwidth } + { + \exp_after:wN \use_i:nn \l_@@_item_align_tl +% \end{macrocode} +% FMi: \LaTeXe{} keeps the label boxed inside (not unboxed). This +% means that the content stays rigid and does not vary based on +% glue setting in the line with the label. +% There are cases where we do want the unboxed version (I think +% enumitem offers that in some cases too) but it should probably +% not the default. +% \begin{macrocode} +% \hbox_unpack_drop:N \l_@@_one_label_box %TODO: customize? + \box_use_drop:N \l_@@_one_label_box +% \end{macrocode} +% +% \begin{macrocode} + \exp_after:wN \use_ii:nn \l_@@_item_align_tl + } + } + \hbox_set:Nn \l_@@_one_label_box + { \box_use_drop:N \l_@@_one_label_box } + } + \dim_compare:nNnTF { \box_wd:N \l_@@_one_label_box } > \labelwidth + { \bool_set_true:N \l_@@_long_label_bool } + { \bool_set_false:N \l_@@_long_label_bool } + \hbox_gset:Nn \g_@@_labels_box + { + \hbox_unpack_drop:N \g_@@_labels_box + \skip_horizontal:n { \itemindent - \labelsep - \labelwidth } + \hbox_unpack_drop:N \l_@@_one_label_box + \skip_horizontal:n { \labelsep } + \bool_if:NT \l_@@_next_line_bool + { \bool_if:NT \l_@@_long_label_bool { \nobreak \hfil \break } } + % version of \newline inside an hbox that will be unpacked + } + % \skip_set_eq:NN \parsep \l_@@_item_parsep_skip TODO??? FMi + % what's that? + \dim_set_eq:NN \parindent \listparindent +% \end{macrocode} +% Placing the list label(s) is done when the paragraph for the +% \cs{item} is started, which executes \cs{@@_item_everypar:} +% inside \hook{para/begin}. By default this command does nothing, now we +% change it to attach the pending label or labels. +% \begin{macrocode} + \cs_set_eq:NN \@@_item_everypar: \@@_item_everypar_std: + } +% \end{macrocode} +% \end{template} +% +% +% +% +% \begin{variable}{\l_@@_one_label_box, \g_@@_labels_box} +% Each label is typeset in \cs{l_@@_one_label_box} to be measured. +% Once this is ready, it is put (boxed or unboxed) in +% \cs{g_@@_labels_box}, together with any pending labels (for the case +% where a list begins just after \tn{item}). This is an analogue of +% \LaTeXe{}'s \tn{@labels}, but it is always unboxed before use, to +% support both boxed and unboxed labels. +% \begin{macrocode} +\box_new:N \l_@@_one_label_box +\box_new:N \g_@@_labels_box +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_long_label_bool} +% Track whether the \cs{l_@@_one_label_box} is larger than +% \tn{labelwidth}. +% \begin{macrocode} +\bool_new:N \l_@@_long_label_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_make_label_box:n, \@@_label_format:x} +% Make one label, wrapped in \cs{@@_label_format:n}, with an +% appropriate \tn{strut} and possibly \tn{makelabel} in compatibility +% mode (used for the \env{list} environment). +% \begin{macrocode} +\cs_new_protected:Npn \@@_make_label_box:n #1 + { + \hbox_set:Nn \l_@@_one_label_box + { +% \end{macrocode} +% If we do tagging then the contents of this box may need to be +% wrapped into a structure, e.g., \verb=<Lbl>=. +% \begin{macrocode} + \__kernel_list_label_begin: +% \end{macrocode} +% +% \begin{macrocode} + \@@_label_format:n + { + \bool_if:NT \l_@@_label_strut_bool { \strut } + \bool_if:NTF \l_@@_legacy_support_bool + \makelabel + \use:n + {#1} + } +% \end{macrocode} +% And what gets opened also needs closing: +% \begin{macrocode} + \__kernel_list_label_end: + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\__kernel_list_label_begin:, +% \__kernel_list_label_end:} +% If we aren't doing tagging the kernel hooks do nothing. +% \begin{macrocode} +\cs_new_eq:NN \__kernel_list_label_begin: \prg_do_nothing: +\cs_new_eq:NN \__kernel_list_label_end: \prg_do_nothing: +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_item_everypar:, \@@_item_everypar_std:} +% The \cs{@@_item_everypar:} command is executed as part of \hook{para/begin} +% but most of the time does nothing, i.e., it has the following +% default definition. +% \begin{macrocode} +\cs_new_eq:NN \@@_item_everypar: \prg_do_nothing: +% \end{macrocode} +% +% \begin{macrocode} +\AddToHook{para/begin}[lists]{\@@_item_everypar:} +% \end{macrocode} +% +% Note that we have to make sure that the above code is executed +% after the hook chunk from \texttt{tagpdf} because the latter uses +% \texttt{@inlabel} to make a decision. +% +% By the end of the day both should probably move into the kernel +% hook instead! +% \begin{macrocode} +\DeclareHookRule{para/begin}{lists}{after}{tagpdf} +% \end{macrocode} +% +% +% What follows is the version that resets various legacy booleans and puts +% the label box in the right place and finally resets itself to do +% nothing next time. \cs{@@_item_everypar:} is set to this by the +% item template so that the next paragraph start runs the code below. +% \begin{macrocode} +\cs_new_protected:Npn \@@_item_everypar_std: { + \@@_debug_typeout:n{item~ everypar \on@line } + \legacy_if_set_false:n { @minipage } + \legacy_if_gset_false:n { @newlist } + \legacy_if:nT { @inlabel } + { + \legacy_if_gset_false:n { @inlabel } +% \end{macrocode} +% +% \begin{macrocode} + \box_if_empty:NT \g_para_indent_box { \kern - \itemindent } + \para_omit_indent: +% \end{macrocode} +% +% \begin{macrocode} + \box_use_drop:N \g_@@_labels_box +% \end{macrocode} +% After the labels are placed we start a paragraph structure (if +% appropriate). This is handled in the following kernel hook: +% \begin{macrocode} + \__kernel_list_label_after: +% \end{macrocode} +% +% \begin{macrocode} + \penalty \c_zero_int + } + \legacy_if:nTF { @nobreak } + { + \legacy_if_gset_false:n { @nobreak } + \int_set:Nn \clubpenalty { 10000 } + } + { + \int_set_eq:NN \clubpenalty \@clubpenalty +% \end{macrocode} +% Once the label(s) are typeset and we are past any special +% \texttt{@nobreak} handling we reset \cs{@@_item_everypar:} to do +% nothing. +% \begin{macrocode} + \cs_set_eq:NN \@@_item_everypar: \prg_do_nothing: + } +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\__kernel_list_label_after:} +% +% \begin{macrocode} +\cs_new_eq:NN \__kernel_list_label_after: \prg_do_nothing: +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_@@_tmpa_skip} +% \begin{macrocode} +\skip_new:N \l_@@_tmpa_skip +% \end{macrocode} +% \end{variable} +% +% +% +% +% +% +% +% \begin{variable}{\l_@@_topsepadd_skip, \l_@@_effective_top_skip} +% Variables equivalent to \LaTeXe{}'s \tn{@topsepadd} and \tn{@topsep}. +% Roughly equal to a mixture of \texttt{topsep}, \texttt{partopsep}, +% and various \texttt{parskip} at different nesting levels in lists. +% The code is really elaborate when \texttt{@inlabel} is true. +% \begin{macrocode} +\skip_new:N \l_@@_topsepadd_skip +\skip_new:N \l_@@_effective_top_skip +% \end{macrocode} +% \end{variable} +% +% +% +% +% +% +% +% +% +% +% +% \begin{macro}{\item} +% Here we already have all the building blocks. Complain in math +% mode. Distingusih between first item (do necessary tagging) and +% later items \cs{@@_inter_item:} to +% cleanly close what's before, then call \cs{@@_item_instance:n} (which +% calls \cs{UseInstance}\{item\}\marg{instance}) to prepare the +% upcoming item: it will be actually inserted only once some later +% material triggers \tn{everypar}. +% \begin{macrocode} +\AddToHook{begindocument/before}{ + \RenewDocumentCommand{\item}{ ={label}o } + { + \@inmatherr \item +% \end{macrocode} +% TODO: Test for being outside of a list needs updating! +% \begin{macrocode} + \tl_if_empty:oTF \@@_item_instance:n %%FMi? + { \msg_error:nnn { @@ } { item-in-nonlist } { \item[{#1}] } } + { + \legacy_if:nTF { @newlist } + { \__kernel_list_item_begin: } + { \@@_inter_item: } +% \end{macrocode} +% To avoid unnecessary key/val processing we make a quick check if +% there was an optional argument. +% \begin{macrocode} + \tl_if_novalue:nTF {#1} % avoids reparsing label={} + { \@@_item_instance:n { } } + { \@@_item_instance:n {#1} } +% \end{macrocode} +% Set the legacy switch that signals that we have a pending item label: +% \begin{macrocode} + \legacy_if_gset_true:n { @inlabel } + \ignorespaces + } + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_inter_item:} +% Between items. If the previous item had no content then we need to +% trigger \tn{everypar}. Otherwise we simply close the previous item +% with \tn{par} after removing some horizontal space. Between items, +% there is a penalty and some space. +% \begin{macrocode} +\cs_new_protected:Npn \@@_inter_item: { + \legacy_if:nT { @inlabel } + { \indent \par } % case of \item\item +% \end{macrocode} +% \cs{par} may have a strange definition and may not get us back to +% vertical mode in one go, so we better do not treat the next line +% as an else case to the above conditional (for now). +% \begin{macrocode} + \mode_if_horizontal:T { \@@_skip_remove_last: + \@@_skip_remove_last: \par } +% \end{macrocode} +% End any LI-tag, then start the next LI-tag (if doing tagging): +% \begin{macrocode} + \__kernel_list_item_end: + \__kernel_list_item_begin: +% \end{macrocode} +% +% \begin{macrocode} + \addpenalty \@itempenalty + \addvspace \itemsep +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\__kernel_list_item_begin:, +% \__kernel_list_item_end:} +% +% \begin{macrocode} +\cs_new_eq:NN \__kernel_list_item_begin: \prg_do_nothing: +\cs_new_eq:NN \__kernel_list_item_end: \prg_do_nothing: +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% +% +% \subsection{Tagging recipes} +% +% \begin{macro}{\@@_recipe_basic:} +% The \texttt{basic} recipe simply ensures that the block is inside +% a \texttt{text-unit} structure and if necessary starts one. When the +% block ends and is followed by a blank line the \texttt{text-unit} +% structure is closed too, otherwise it remains open and further +% text starts with just a \struct{text} structure. +% +% There is otherwise no inner structure so +% \cs{__kernel_displayblock_begin:} and +% \cs{__kernel_displayblock_end:} do nothing---blockenvs with inner +% structure use the \texttt{standard} or \texttt{list} recipe instead. +% \begin{macrocode} +\cs_new:Npn \@@_recipe_basic: { + \cs_set_eq:NN \__kernel_displayblock_beginpar_hmode:w + \@@_beginpar_hmode:N + \cs_set_eq:NN \__kernel_displayblock_beginpar_vmode: + \@@_beginpar_vmode: + \let \__kernel_displayblock_begin: \prg_do_nothing: + \let \__kernel_displayblock_end: \prg_do_nothing: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_recipe_standalone:} +% +% The \texttt{standalone} recipe produces a block that ensures that +% a previous \texttt{text-unit} ends and that after the block a new +% \texttt{text-unit} starts. +% \begin{macrocode} +\cs_new:Npn \@@_recipe_standalone: { + \cs_set_eq:NN \__kernel_displayblock_beginpar_hmode:w + \prg_do_nothing: + \cs_set_eq:NN \__kernel_displayblock_beginpar_vmode: + \prg_do_nothing: + \cs_set_eq:NN \__kernel_displayblock_begin: \@@_inner_begin: + \cs_set_eq:NN \__kernel_displayblock_end: \@@_inner_end: +% \end{macrocode} +% +% \begin{macrocode} + \bool_set_true:N \l_@@_standalone_bool +% \end{macrocode} +% +% \begin{macrocode} + \tl_if_empty:NTF \l_@@_tag_name_tl + { \tl_set:Nn \l_@@_tag_inner_tag_tl {Sect} } + { \tl_set_eq:NN \l_@@_tag_inner_tag_tl \l_@@_tag_name_tl } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_recipe_standard:} +% The \texttt{standard} recipe does the following: +% \begin{itemize} +% \item surround the block with a \texttt{text-unit}-structure if not already in a +% a \texttt{text-unit}. In the latter case end the +% MC and the \struct{text} but leave the \texttt{text-unit} open. +% +% If we are producing flattened paragraphs, just close any +% \struct{text} but do not open a \texttt{text-unit}. +% +% \item Then open an new (inner) structure (by default +% \texttt{Figure} but typically the one specified on the instance). +% \item At the end of the block close the the inner structure +% (\texttt{Figure} or explicit one) +% but leave the \texttt{text-unit} open to be either continued or closed due to a +% following \cs{par}. +% \end{itemize} +% \begin{macrocode} +\cs_new:Npn \@@_recipe_standard: +{ + \cs_set_eq:NN \__kernel_displayblock_beginpar_hmode:w + \@@_beginpar_hmode:N + \cs_set_eq:NN \__kernel_displayblock_beginpar_vmode: + \@@_beginpar_vmode: + \cs_set_eq:NN \__kernel_displayblock_begin: \@@_inner_begin: + \cs_set_eq:NN \__kernel_displayblock_end: \@@_inner_end: +% \end{macrocode} +% +% \begin{macrocode} + \tl_if_empty:NTF \l_@@_tag_name_tl + { \tl_set:Nn \l_@@_tag_inner_tag_tl {Figure} } + { \tl_set_eq:NN \l_@@_tag_inner_tag_tl \l_@@_tag_name_tl } +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\l_@@_tag_inner_tag_tl} +% \begin{macrocode} +\tl_new:N \l_@@_tag_inner_tag_tl +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_recipe_list:} +% The \texttt{list} recipe does the following. +% \begin{itemize} +% \item It opens a \struct{text-unit}-structure or keeps the current one open (only +% closing the MC). +% \item It then starts a new structure rollmapped to L-structure +% and arranges for handling list items, e.g., Li, Lbl and LBody +% structures. +% \item At the end it closes open list structures as needed but +% keeps the \struct{text-unit}-structure open to continue the paragraph after the +% list, if necessary. +% \end{itemize} +% \begin{macrocode} +\cs_new:Npn \@@_recipe_list: +{ + \cs_set_eq:NN \__kernel_displayblock_beginpar_hmode:w + \@@_beginpar_hmode:N + \cs_set_eq:NN \__kernel_displayblock_beginpar_vmode: + \@@_beginpar_vmode: + \cs_set_eq:NN \__kernel_displayblock_begin: \@@_list_begin: + \cs_set_eq:NN \__kernel_displayblock_end: \@@_list_end: +% \end{macrocode} +% The next two lines could be done globally, because they are only +% called if we do have \cs{item}s, i.e., if we are in a list. It is +% therefore also not necessary to reset them in other recipes +% (right now---this may change if we get more templates (like +% inline lists)). +% \begin{macrocode} + \cs_set_eq:NN \__kernel_list_item_begin: \@@_list_item_begin: + \cs_set_eq:NN \__kernel_list_item_end: \@@_list_item_end: +% \end{macrocode} +% Handle the tag name and attribute classess using the key values +% from the current list instance. +% \begin{macrocode} + \tl_if_empty:NTF \l_@@_tag_name_tl + { \tl_set:Nn \l__tag_L_tag_tl {L} } + { \tl_set_eq:NN \l__tag_L_tag_tl \l_@@_tag_name_tl } + \tl_if_empty:NTF \l_@@_tag_class_tl + { \tl_set:Nn \l__tag_L_attr_class_tl {} } + { \tl_set_eq:NN \l__tag_L_attr_class_tl \l_@@_tag_class_tl } +} +% \end{macrocode} +% \end{macro} + + + +% \subsection{Blockenv instances} +% +% +% \subsubsection{Basic instances} +% +% \begin{instance}{blockenv displayblock} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{displayblock}{display} +{ + env-name = displayblock, + tag-name = , + tag-class = , + tagging-recipe = standard, + inner-level-counter = , + level-increase = false, + setup-code = , + block-instance = displayblock , + inner-instance = , +} +% \end{macrocode} +% \end{instance} +% +% +% +% \begin{instance}{blockenv displayblockflattened} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{displayblockflattened}{display} +{ + env-name = displayblockflattened, + tag-name = , + tag-class = , + tagging-recipe = basic, + inner-level-counter = , + level-increase = false, + setup-code = , + block-instance = displayblock , + para-flattened = true , + inner-instance = , +} +% \end{macrocode} +% \end{instance} +% +% +% +% \begin{instance}{blockenv center} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{center}{display} +{ + env-name = center, + tag-name = , + tag-class = , + tagging-recipe = basic, + inner-level-counter = , + level-increase = false, + setup-code = , + block-instance = displayblock , + para-flattened = true , + para-instance = center , + inner-instance = , +} +% \end{macrocode} +% \end{instance} +% +% +% \begin{instance}{blockenv flushleft} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{flushleft}{display} +{ + env-name = flushleft, + tag-name = , + tag-class = , + tagging-recipe = basic, + inner-level-counter = , + level-increase = false, + setup-code = , + block-instance = displayblock , + para-flattened = true , + para-instance = raggedright , + inner-instance = , +} +% \end{macrocode} +% \end{instance} +% +% +% +% \begin{instance}{blockenv flushright} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{flushright}{display} +{ + env-name = flushleft, + tag-name = , + tag-class = , + tagging-recipe = basic, + inner-level-counter = , + level-increase = false, + setup-code = , + block-instance = displayblock , + para-flattened = true , + para-instance = raggedleft , + inner-instance = , +} +% \end{macrocode} +% \end{instance} +% +% +% +% \subsubsection{Blockquote instances} +% +% \begin{instance}{blockenv quotation} +% +% \begin{macrocode} +\tag_if_active:T { + \tagpdfsetup{add-new-tag={tag=quote,role=BlockQuote}} + \tagpdfsetup{add-new-tag={tag=quotation,role=BlockQuote}} +} +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{quotation}{display} +{ + env-name = quotation, + tag-name = quotation, + tag-class = , + tagging-recipe = standard, + inner-level-counter = , + level-increase = true, + setup-code = , + block-instance = quotationblock , + inner-instance = , +} +% \end{macrocode} +% \end{instance} +% +% +% +% \begin{instance}{blockenv quote} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{quote}{display} +{ + env-name = quote, + tag-name = quote, + tag-class = , + tagging-recipe = standard, + inner-level-counter = , + level-increase = true, + setup-code = , + block-instance = quoteblock , + inner-instance = , +} +% \end{macrocode} +% \end{instance} +% +% An alternative setup for quotations, using the displayblock instance and +% just overwrite a bit in the setup code.\fmi{I guess the setup +% code is still executed too early, have to check.} +% This would be less flexible but would ensure visual consistency, +% because the displayblock settings are used throughout. +% \begin{macrocode} +% \DeclareInstance{blockenv}{quotation}{display} +% { +% env-name = quotation, +% tag-name = , +% tag-class = , +% tagging-recipe = blockquote, +% inner-level-counter = , +% level-increase = true, +% setup-code = \setlength\rightmargin{\leftmargin} +% \setlength\parsep{1.5em} , +% block-instance = displayblock , +% inner-instance = , +% } +% \end{macrocode} +% +% \begin{macrocode} +% \DeclareInstance{blockenv}{quote}{display} +% { +% env-name = quote, +% tag-name = , +% tag-class = , +% tagging-recipe = blockquote, +% inner-level-counter = , +% level-increase = true, +% setup-code = \setlength\rightmargin{\leftmargin} , +% block-instance = displayblock , +% inner-instance = , +% } +% \end{macrocode} +% + +% +% \begin{macrocode} +\DeclareInstance{blockenv}{theorem}{display} +{ + env-name = theorem-like, + tag-name = theorem-like, + tag-class = , + tagging-recipe = standalone, + inner-level-counter = , + level-increase = false, + setup-code = , + block-instance = displayblock , +% inner-instance-type = innerblock , +% inner-instance = theorem, +} +% \end{macrocode} +% +% We use \struct{theorem-like} as the structure name and rollmap it +% to a \struct{Sect} because that can hold a \struct{Caption}. +% \begin{macrocode} +\tag_if_active:T { + \tagpdfsetup{add-new-tag={tag=theorem-like,role=Sect}} +} +% \end{macrocode} +% +% +% +% +% \subsubsection{Verbatim instances} +% +% \begin{instance}{blockenv verbatim} +% +% \begin{macrocode} +\tag_if_active:T { + \tagpdfsetup{add-new-tag={tag=verbatim,role=P}} + \tagpdfsetup{add-new-tag={tag=codeline,role=Sub}} +% \end{macrocode} +% Possible alternative for PDF 1.7: +% \begin{macrocode} +% \tagpdfsetup{add-new-tag={tag=verbatim,role=Div}} +% \tagpdfsetup{add-new-tag={tag=codeline,role=P}} +} +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{verbatim}{display} +{ + env-name = verbatim, + tag-name = verbatim, + tag-class = , + tagging-recipe = standard, + inner-level-counter = , + level-increase = false, + setup-code = , + block-instance = verbatimblock , + inner-instance = , + final-code = \legacyverbatimsetup , +} +% \end{macrocode} +% \end{instance} +% +% +% \subsubsection{Standard list instances} +% +% \begin{instance}{blockenv itemize} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{itemize}{display} +{ + env-name = itemize, + tag-name = itemize, + tag-class = itemize, + tagging-recipe = list, + inner-level-counter = \@itemdepth, + level-increase = true, + max-inner-levels = 4, + setup-code = , + block-instance = list , + inner-instance = itemize , +} +% \end{macrocode} +% \end{instance} +% +% +% \begin{instance}{blockenv enumerate} +% +% \begin{macrocode} +\DeclareInstance{blockenv}{enumerate}{display} +{ + env-name = enumerate, + tag-name = enumerate, + tag-class = enumerate, + tagging-recipe = list, + level-increase = true, + setup-code = , + block-instance = list , + inner-level-counter = \@enumdepth, + max-inner-levels = 4, + inner-instance = enum , +} +% \end{macrocode} +% \end{instance} +% +% +% \begin{instance}{blockenv description} +% +% \begin{macrocode} + +\DeclareInstance{blockenv}{description}{display} +{ + env-name = description, + tag-name = description, + tag-class = description, + tagging-recipe = list, + inner-level-counter = , + level-increase = true, + setup-code = , + block-instance = list , + inner-instance = description , +} +% \end{macrocode} +% \end{instance} +% +% +% \begin{instance}{blockenv list} +% The general (legacy) \env{list} environment does some of its +% setup in the \texttt{setup-code} key. +% \begin{macrocode} +\DeclareInstance{blockenv}{list}{display} +{ + env-name = list, + tag-name = list, + tag-class = , + tagging-recipe = list, + level-increase = true, + setup-code = \legacylistsetupcode , + block-instance = list , + inner-level-counter = , + inner-instance = legacy , +} +% \end{macrocode} +% \end{instance} +% +% +% +% +% \subsection{Block instances} +% +% \subsubsection{Displayblock instances} +% +% We provide 6 nesting levels (as in \LaTeXe{}). If you want to +% provide more you need to change the \texttt{maxblocklevels} +% counter, offer further \texttt{displayblock-xx} instances but +% also define further (legacy) \cs{list\meta{romannumeral}} commands +% for the defaults. If not, then the settings from the previous +% level are reused automatically---which may or may not be good enough). +% \begin{macrocode} +\setcounter{maxblocklevels}{6} +% \end{macrocode} +% +% \begin{instance}{block displayblock-0, +% block displayblock-1, +% block displayblock-2, +% block displayblock-3, +% block displayblock-4, +% block displayblock-5, +% block displayblock-6 } +% +% Here we need level zero as well in case a flattened displayblock +% (like the center env) it is used on top-level. +% \begin{macrocode} +\DeclareInstance{block}{displayblock-0}{display} + { + leftmargin = 0pt , + parindent = 0pt , + } +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstanceCopy{block}{displayblock-1}{displayblock-0} +\DeclareInstanceCopy{block}{displayblock-2}{displayblock-0} +\DeclareInstanceCopy{block}{displayblock-3}{displayblock-0} +\DeclareInstanceCopy{block}{displayblock-4}{displayblock-0} +\DeclareInstanceCopy{block}{displayblock-5}{displayblock-0} +\DeclareInstanceCopy{block}{displayblock-6}{displayblock-0} +% \end{macrocode} +% \end{instance} +% +% +% +% \subsubsection{Verbatim instances} +% +% Verbatim instances have there own levels so that one can specify +% specific indentations or vertical separations between line. +% +% \begin{instance}{block verbatimblock-0, +% block verbatimblock-1, +% block verbatimblock-2, +% block verbatimblock-3, +% block verbatimblock-4, +% block verbatimblock-5, +% block verbatimblock-6 } +% +% \begin{macrocode} +\DeclareInstance{block}{verbatimblock-0}{display} + { + leftmargin = 0pt , + parindent = 0pt , + par-skip = 0pt , + } +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstanceCopy{block}{verbatimblock-1}{verbatimblock-0} +\DeclareInstanceCopy{block}{verbatimblock-2}{verbatimblock-0} +\DeclareInstanceCopy{block}{verbatimblock-3}{verbatimblock-0} +\DeclareInstanceCopy{block}{verbatimblock-4}{verbatimblock-0} +\DeclareInstanceCopy{block}{verbatimblock-5}{verbatimblock-0} +\DeclareInstanceCopy{block}{verbatimblock-6}{verbatimblock-0} +% \end{macrocode} +% \end{instance} +% +% +% +% +% \subsubsection{Quote/quotationblock instances} +% +% Quote and quotation are not flattened, i.e., they change levels, +% thus they start with level 1 not 0. +% +% \begin{instance}{block quoteblock-1, +% block quoteblock-2, +% block quoteblock-3, +% block quoteblock-4, +% block quoteblock-5, +% block quoteblock-6 } +% Default layout is to indent equaly from both side. +% \begin{macrocode} +\DeclareInstance{block}{quoteblock-1}{display} + { rightmargin = \KeyValue{leftmargin} } +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstanceCopy{block}{quoteblock-2}{quoteblock-1} +\DeclareInstanceCopy{block}{quoteblock-3}{quoteblock-1} +\DeclareInstanceCopy{block}{quoteblock-4}{quoteblock-1} +\DeclareInstanceCopy{block}{quoteblock-5}{quoteblock-1} +\DeclareInstanceCopy{block}{quoteblock-6}{quoteblock-1} +% \end{macrocode} +% \end{instance} +% +% +% +% \begin{instance}{block quotationblock-1, +% block quotationblock-2, +% block quotationblock-3, +% block quotationblock-4, +% block quotationblock-5, +% block quotationblock-6 } +% Quotation additionally changes the parindent. +% \begin{macrocode} +\DeclareInstance{block}{quotationblock-1}{display} + { parindent = 1.5em , rightmargin = \KeyValue{leftmargin} } +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstanceCopy{block}{quotationblock-2}{quotationblock-1} +\DeclareInstanceCopy{block}{quotationblock-3}{quotationblock-1} +\DeclareInstanceCopy{block}{quotationblock-4}{quotationblock-1} +\DeclareInstanceCopy{block}{quotationblock-5}{quotationblock-1} +\DeclareInstanceCopy{block}{quotationblock-6}{quotationblock-1} +% \end{macrocode} +% \end{instance} +% +% +% \subsubsection{Block instances for the standard lists} +% +% \begin{instance}{block list-1, +% block list-2, +% block list-3, +% block list-4, +% block list-5, +% block list-6 } +% The block instances for the various list environments use the +% same underlying instance (well by default) and nothing nothing +% needs to be set up specifically (because that is already done in +% the legacy \cs{list\meta{romannumeral}} unless a +% different layout is wanted. +% \begin{macrocode} +\DeclareInstance{block}{list-1}{display}{ +% heading = , +% beginsep = \topsep , +% begin-par-skip = \partopsep , +% par-skip = \parsep , +% end-skip = \KeyValue{beginsep} , +% end-par-skip = \KeyValue{begin-par-skip} , +% beginpenalty = \UseName{@beginparpenalty} , +% endpenalty = \UseName{@endparpenalty} , +% leftmargin = \leftmargin , +% rightmargin = \rightmargin , +% parindent = \listparindent , +} +\DeclareInstance{block}{list-2}{display}{} +\DeclareInstance{block}{list-3}{display}{} +\DeclareInstance{block}{list-4}{display}{} +\DeclareInstance{block}{list-5}{display}{} +\DeclareInstance{block}{list-6}{display}{} +% \end{macrocode} +% \end{instance} +% +% +% +% \subsection{List instances for the standard lists} +% +% For all list instances we have to say what kind of label we want +% (\texttt{label-instance}) and how it should beformatted. +% +% \begin{instance}{list itemize-1, +% list itemize-2, +% list itemize-3, +% list itemize-4} +% For \env{itemize} environments this is all we need to do and we +% refer back to the external definitions rather than defining the +% \texttt{item-label} code in the instance to ensure that old +% documents still work. +% +% \begin{macrocode} +\DeclareInstance{list}{itemize-1}{std}{ item-label = \labelitemi } +\DeclareInstance{list}{itemize-2}{std}{ item-label = \labelitemii } +\DeclareInstance{list}{itemize-3}{std}{ item-label = \labelitemiii } +\DeclareInstance{list}{itemize-4}{std}{ item-label = \labelitemiv } +% \end{macrocode} +% \end{instance} +% +% +% +% \begin{instance}{list enumerate-1, +% list enumerate-2, +% list enumerate-3, +% list enumerate-4} +% \env{enumerate} environments are similar, except that we also +% have to say which counter to use on every level. +% \begin{macrocode} +\DeclareInstance{list}{enum-1}{std} + { item-label = \labelenumi , counter = enumi } +\DeclareInstance{list}{enum-2}{std} + { item-label = \labelenumii , counter = enumii } +\DeclareInstance{list}{enum-3}{std} + { item-label = \labelenumiii , counter = enumiii } +\DeclareInstance{list}{enum-4}{std} + { item-label = \labelenumiv , counter = enumiv } +% \end{macrocode} +% \end{instance} +% +% +% +% \begin{instance}{list legacy} +% For the legacy \env{list} environment there is only one instance +% which is reused on all levels. This is done this way one because +% the legacy \env{list} environment sets all its +% parameters through its arguments. So this instances shouldn't +% really be touched. It sets the \texttt{legacy-support} key to +% true, which means that the list code uses \cs{makelabel} for +% formatting the label +% \begin{macrocode} +\DeclareInstance{list}{legacy}{std} { + item-instance = basic , + legacy-support = true , +} +% \end{macrocode} +% \end{instance} +% +% +% \begin{instance}{list description} +% The \env{description} lists also use only a single list instance +% with only one key not using the default: +% \begin{macrocode} +\DeclareInstance{list}{description}{std} { item-instance = description } +% \end{macrocode} +% \end{instance} +% +% +% \subsection{Item instances} +% +% +% \begin{instance}{item basic, item description} +% There two item instances set up: \texttt{description} for use +% with the \env{description} environment and \texttt{basic} for use +% with all other lists (up to now). +% \begin{macrocode} +\DeclareInstance{item}{basic}{std} + { + label-align = right , + } +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstance{item}{description}{std} + { + label-format = \normalfont\bfseries #1 , + } +% \end{macrocode} +% \end{instance} +% +% +% +% \subsection{Para instances} +% +% \begin{macrocode} +\tag_if_active:T +{ + \tagpdfsetup + { + newattribute = {justify} {/O /Layout /TextAlign/Justify}, + newattribute = {center} {/O /Layout /TextAlign/Center}, + newattribute = {raggedright}{/O /Layout /TextAlign/Start}, + newattribute = {raggedleft} {/O /Layout /TextAlign/End}, + } +} +% \end{macrocode} +% +% \begin{instance}{para center} +% \begin{macrocode} +\DeclareInstance{para}{center}{std} +{ + indent-width = 0pt , + start-skip = 0pt , + left-skip = \@flushglue , + right-skip = \@flushglue , + end-skip = \z@skip , + final-hyphen-demerits = 0 , + cr-cmd = \@centercr , + para-class = center , +} +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstance{para}{raggedright}{std} +{ + indent-width = 0pt , + start-skip = 0pt , + left-skip = \z@skip , + right-skip = \@flushglue , + end-skip = \z@skip , + final-hyphen-demerits = 0 , + cr-cmd = \@centercr , + para-class = raggedright , +} +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstance{para}{raggedleft}{std} +{ + indent-width = 0pt , + start-skip = 0pt , + left-skip = \@flushglue , + right-skip = \z@skip , + end-skip = \z@skip , + final-hyphen-demerits = 0 , + cr-cmd = \@centercr , + para-class = raggedleft , +} +% \end{macrocode} +% +% \begin{macrocode} +\DeclareInstance{para}{justify}{std} +{ +% indent-width = 0pt , + start-skip = 0pt , + left-skip = \z@skip , + right-skip = \z@skip , + end-skip = \@flushglue , + final-hyphen-demerits = 5000 , + cr-cmd = \@normalcr , + para-class = justify , +} +% \end{macrocode} +% \end{instance} +% +% +% +% +% \begin{macrocode} +\DeclareRobustCommand\centering {\UseInstance{para}{center}{}} +\DeclareRobustCommand\raggedleft {\UseInstance{para}{raggedleft}{}} +\DeclareRobustCommand\raggedright{\UseInstance{para}{raggedright}{}} +\DeclareRobustCommand\justifying {\UseInstance{para}{justify}{}} + +\justifying +% \end{macrocode} +% +% +% +% +% +% \subsection{Tagging support} +% +% In this section we provide code to the various kernel hooks to support +% the tagging of the different displayblock environments. +% +% +% +% All of the following definitions should only be made if tagging +% is active! +% \begin{macrocode} +\tag_if_active:T { +% \end{macrocode} +% +% \begin{macro}{\@@_beginpar_vmode:} +% When a block starts out in vertical mode, i.e., is not yet part of +% a paragraph, we have to start a paragraph +% structure. However, this is not the case if we are already +% flattening paragraphs, thus in this case we do nothing. +% We also do nothing if \texttt{@endpe} is currently true, because +% that means we are right now just after the end of a +% \texttt{blockenv} and in the process of looking if we have to end +% the current \texttt{text-unit}, i.e., it is already open. +% \begin{macrocode} + \cs_set:Npn \@@_beginpar_vmode: { + \@@_debug_typeout:n + { @endpe = \legacy_if:nTF { @endpe }{true}{false} + \on@line } + \legacy_if:nTF { @endpe } + { + \legacy_if_gset_false:n { @endpe } + } +% \end{macrocode} +% We test for \texttt{<2} because the first flattened environment +% has to surround itself with a \texttt{text-unit}. Only any inner ones +% then have to avoid adding another \texttt{text-unit}. +% \begin{macrocode} + { + \int_compare:nNnT \l_@@_flattened_level_int < 2 + { + \int_gincr:N \g__tag_para_main_begin_int + \tagstructbegin{tag=\l__tag_para_main_tag_tl} + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_beginpar_hmode:N} +% If the block is already part of a part of a paragraph, i.e., when it has +% some text directly in front, then the first thing to +% do is to return to vertical mode. However, that should be done +% without inserting a paragraph end tag, so before calling \cs{par} +% to do its normal work, we disable paragraph tagging and +% restarting afterwards again. The argument to this config point +% simply gobbles the \cs{par} following it in the code above (which +% is used when there is no tagging going on. +% \begin{macrocode} + \cs_set:Npn \@@_beginpar_hmode:N #1 + { + \tag_mc_end: + \int_gincr:N \g__tag_para_end_int + \@@_debug_typeout:n{increment~ /P \on@line } + \bool_if:NT \l__tag_para_show_bool + { \tag_mc_begin:n{artifact} + \rlap{\color_select:n{red}\tiny\ \int_use:N\g__tag_para_end_int} + \tag_mc_end: + } + \tag_struct_end: + \tagpdfparaOff \par \tagpdfparaOn + } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\__kernel_displayblock_doendpe:} +% If a display block ends and is followed by a blank line we have to end the +% enclosing paragraph tagging structure. +% \begin{macrocode} +\cs_set:Npn \__kernel_displayblock_doendpe: { + \bool_if:NT \l__tag_para_bool + { +% \end{macrocode} +% Given that restoring \cs{par} through the legacy \LaTeXe{} method +% can take a few iterations (for example, in case of nested lists, +% e.g., \verb=...\end{itemize} \item ...\par= it can happen that +% \cs{__kernel_displayblock_doendpe:} is called while +% \texttt{@endpe} is already handled and then we should not attempt +% to close a \texttt{text-unit} structure. So we need to check for this. +% \begin{macrocode} + \legacy_if:nT { @endpe } + { +% \end{macrocode} +% If the display block currently ending was \enquote{flattened} +% (i.e., uses simplified paragraphs that are not tagged by a +% combination of \texttt{text-unit} followed by \struct{text}, but simply +% with a \struct{text}, +% then we don't have to do anything, because the \struct{text} is already closed. +% \begin{macrocode} + \@@_debug_typeout:n + { flattened= \bool_if:NTF + \l__tag_para_flattened_bool {true}{false} + \on@line } + \bool_if:NF \l__tag_para_flattened_bool + { + \@@_debug_typeout:n{Structure-end~ + \l__tag_para_main_tag_tl\space after~ displayblock \on@line } + \int_gincr:N \g__tag_para_main_end_int + \tag_struct_end: %text-unit + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{para/begin} +% +% Paragraph tagging is mainly done using the paragraph hooks (will +% get moved eventually). The default hook setting is not good +% enough when lists get suppported: we need to delay starting the +% paragraph tagging if we still have to place the list label. +% We therefore remove the existing hook data and replace it with an +% augmented version (this will get combined eventually). +% \begin{macrocode} +\RemoveFromHook{para/begin}[tagpdf] +% \end{macrocode} +% +% \begin{macrocode} +\AddToHook{para/begin}[tagpdf]{ + \bool_if:NT \l__tag_para_bool { +% \end{macrocode} +% if we are still waiting to typeset the list label we do nothing +% (the paragraph tagging then happens when the list is finally +% typeset). +% \begin{macrocode} + \legacy_if:nF { @inlabel } + { +% \end{macrocode} +% Otherwise, we start a \struct{text} tag structure but only if we are not +% starting a paragraph immediately \emph{after} a list, in which +% case we only start a new MC (because the \struct{text} tag is still open from +% before the list --- one of the reasons why lists are always put +% \enquote{inside} paragraphs. +% +% We do this in a separate command, because it is needed elsewhere too. +% \begin{macrocode} + \@@_start_para_structure:n { \PARALABEL } + } + } +} +% \end{macrocode} +% +% +% \begin{macro}{\@@_start_para_structure:n} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_start_para_structure:n #1 { + \@@_debug_typeout:n + { @endpe = \legacy_if:nTF { @endpe }{true}{false} + \on@line } + \legacy_if:nF { @endpe } + { + \bool_if:NF \l__tag_para_flattened_bool + { + \int_gincr:N \g__tag_para_main_begin_int + \tag_struct_begin:n{tag=\l__tag_para_main_tag_tl} + } + } + \int_gincr:N \g__tag_para_begin_int + \@@_debug_typeout:n{increment~ P \on@line } + \tag_struct_begin:n + { + tag=\l__tag_para_tag_tl + ,attribute-class=\l_tag_para_attr_class_tl + } + \__tag_check_para_begin_show:nn {green}{#1} + \tag_mc_begin:n {} +} +% \end{macrocode} +% The same code, but without testing \texttt{@endpe}. This is not +% needed in the standalong e case and wrong inside lists. +% \begin{macrocode} +\cs_new_protected:Npn \@@_start_para_structure_unconditionally:n #1 { + \bool_if:NF \l__tag_para_flattened_bool + { + \int_gincr:N \g__tag_para_main_begin_int + \tag_struct_begin:n{tag=\l__tag_para_main_tag_tl} + } + \int_gincr:N \g__tag_para_begin_int + \@@_debug_typeout:n{increment~ P \on@line } + \tag_struct_begin:n + { + tag=\l__tag_para_tag_tl + ,attribute-class=\l_tag_para_attr_class_tl + } + \__tag_check_para_begin_show:nn {green}{#1} + \tag_mc_begin:n {} +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macrocode} +\tag_if_active:T { +% \tagpdfsetup{add-new-tag={tag=text-unit,role=Part}} +} +% \end{macrocode} +% +% \begin{macrocode} +\RemoveFromHook{para/end}[tagpdf] +\AddToHook{para/end} + { + \bool_if:NT \l__tag_para_bool + { + \int_gincr:N \g__tag_para_end_int + \@@_debug_typeout:n{increment~ /P \on@line } + \tag_mc_end: + \__tag_check_para_end_show:nn {red}{} + \tag_struct_end: + \bool_if:NF \l__tag_para_flattened_bool + { + \int_gincr:N \g__tag_para_main_end_int + \tag_struct_end: + } + } + } +% \end{macrocode} +% +% \begin{macrocode} +\def\PARALABEL{NP-} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\para_end:} +% If we see a \cs{par} in vmode and a \texttt{text-unit} is still open +% we need to close that. For this we check if a request for +% \text{@endpe} was made (but the \cs{par} redefinition got lost +% due to (bad?) coding). +% \begin{macrocode} +\cs_set_protected:Npn \para_end: { + \scan_stop: + \mode_if_horizontal:TF { + \mode_if_inner:F { + \tex_unskip:D + \hook_use:n{para/end} + \@kernel@after@para@end + \mode_if_horizontal:TF { + \if_int_compare:w 11 = \tex_lastnodetype:D + \tex_hskip:D \c_zero_dim + \fi: + \tex_par:D + \hook_use:n{para/after} + \@kernel@after@para@after + } + { \msg_error:nnnn { hooks }{ para-mode }{end}{horizontal} } + } + } + { + \__kernel_endpe_vmode: % should do nothing if no tagging + \tex_par:D + } +} +\cs_set_eq:NN \par \para_end: +\cs_set_eq:NN \@@par \para_end: +\cs_set_eq:NN \endgraf \para_end: +% \end{macrocode} +% +% \begin{macrocode} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\begin} +% We need to do a little more than canceling \texttt{@endpe} now. +% \begin{macrocode} +\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}% + \@execute@begin@hook{#1}% + \csname #1\endcsname}}% + \@ignorefalse + \begingroup + \__kernel_endpe_vmode: + \reserved@a} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\__kernel_endpe_vmode:} +% Close an open \texttt{text-unit} if \texttt{@endpe} is true and we +% are in vmode. Used in \cs{para_end:} and \cs{begin}. +% \begin{macrocode} +\cs_new:Npn \__kernel_endpe_vmode: { + \if@endpe \ifvmode + \bool_if:NT \l__tag_para_bool + { + \bool_if:NF \l__tag_para_flattened_bool + { + \int_gincr:N \g__tag_para_main_end_int + \tag_struct_end: + } + \@endpefalse + } + \fi \fi +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\__kernel_list_label_after:} +% If starting the text-unit/text tags got delayed because of a pending label we +% have to do it after the label got typeset +% \begin{macrocode} +\cs_set:Npn \__kernel_list_label_after: { + \bool_if:NT \l__tag_para_bool + { + \@@_start_para_structure_unconditionally:n { LI- } + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_inner_begin:} +% Start a block that has an inner structure if it isn't also a list. +% \begin{macrocode} +\cs_new:Npn \@@_inner_begin: { + \tagstructbegin{tag=\l_@@_tag_inner_tag_tl} +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_inner_end:} +% End a block (which isn't also a list). +% \begin{macrocode} +\cs_new:Npn \@@_inner_end: { + \@@_debug_typeout:n{block-end \on@line} + \legacy_if:nT { @endpe } + { + \int_gincr:N \g__tag_para_main_end_int + \@@_debug_typeout:n{close~ /text-unit \on@line} + \tagstructend + } + \tagstructend % end inner structure +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% \subsubsection{List tags} +% +% +% \begin{macrocode} +\tl_new:N \l__tag_L_tag_tl +\tl_set:Nn \l__tag_L_tag_tl {L} + +\tl_new:N\l__tag_L_attr_class_tl +\tl_set:Nn \l__tag_L_attr_class_tl {list} +% \end{macrocode} +% +% \begin{macrocode} +\tag_if_active:T +{ + \tagpdfsetup + { + % default if unknown + newattribute = {list}{/O /List /ListNumbering/None}, + newattribute = {itemize}{/O /List /ListNumbering/Unordered}, + newattribute = {enumerate}{/O /List /ListNumbering/Ordered}, + newattribute = {description}{/O /List /ListNumbering/Description}, + } +} +% \end{macrocode} +% +% \begin{macrocode} +\def\LItag{LI} +% \end{macrocode} +% +% \begin{macro}{\@@_list_begin:} +% Start a list \ldots +% \begin{macrocode} +\cs_set:Npn \@@_list_begin: { + \tagstructbegin + { + tag=\l__tag_L_tag_tl + ,attribute-class=\l__tag_L_attr_class_tl + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_list_item_begin:} +% Start tagging a list item. +% \begin{macrocode} +\cs_set:Npn \@@_list_item_begin: { \tagstructbegin{tag=\LItag} } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\__kernel_list_label_begin:} +% A list label needs a \texttt{Lbl} structure tag and an MC. +% \begin{macrocode} +\cs_set:Npn \__kernel_list_label_begin: { +% +% FMi: this needs a different logic to decide when to make the label +% an artifact (after cleaning up the the \item code ), therefore +% disabled for now +% \tl_if_empty:oTF \@itemlabel +% { +% \tag_mc_begin:n {artifact} +% } +% { + \tagstructbegin{tag=Lbl} + \tagmcbegin{tag=Lbl} +% } +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\__kernel_list_label_end:} +% And when we are done with the label we have to close the MC and +% the \texttt{Lbl} structure. We then start the \texttt{LBody}. The +% material inside will be \enquote{paragraph} text and the tagging +% for that is handled by the normal para tagging. +% \begin{macrocode} +\cs_set:Npn \__kernel_list_label_end: { + \tagmcend % end mc-Lbl or artifact +% FMi: unconditionally for now +% \tl_if_empty:oF \@itemlabel + \tagstructend % end Lbl + \tagstructbegin{tag=\LBody} +} +\def\LBody{LBody} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_list_item_end:} +% When a list item ends we have to close \texttt{LBody} and +% \texttt{LI} but also a \struct{text} in the special case that the +% item material ends in a list (identifiable via \texttt{@endpe}). +% \begin{macrocode} +\cs_set:Npn \@@_list_item_end: { + \legacy_if:nT { @endpe } + { + \int_gincr:N \g__tag_para_main_end_int + \tagstructend % text-unit +% \@@_debug_typeout:n{Structure-end~ P~ at~ item-end \on@line } + } + \tagstructend \tagstructend % end LBody, LI +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_list_end:} +% Finally, at the list end we have to close the open +% \texttt{LBody}, \texttt{LI}, \texttt{L}, and possibly a +% \struct{text} if the last item ends with a list. +% \begin{macrocode} +\cs_set:Npn \@@_list_end: { + \legacy_if:nT { @endpe } + { + \int_gincr:N \g__tag_para_main_end_int + \tagstructend % text-unit + \@@_debug_typeout:n{Structure-end~ P~ at~ list-end \on@line } + } + \tagstructend\tagstructend % end LBody, LI + \tagstructend % end L +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% End of tagging related declarations. +% \begin{macrocode} +} +% \end{macrocode} +% +% +% +% +% +% +% +% +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% +% +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{block-tagging-latex-lab-testphase.ltx} + [\ltblocksdate\space \ltblocksversion\space + blockenv implementation] +\RequirePackage{latex-lab-testphase-block-tagging} +%</latex-lab> +% \end{macrocode} +% +% \end{implementation} +% +% +% \section{Documentation from first prototype implementations} +% +% +% \subsection{Open questions} +% \begin{itemize} +% \item Existing questions --- moved to issues --- +% \end{itemize} +% +% \subsection{Code cleanup} +% \begin{itemize} +% \item Actually implement what's announced. +% +% \item Encapsulate most uses of \cs[no-index]{legacy_if\dots} into +% commands with \texttt{expl3} syntax: we cannot rename these booleans +% for compatibility reasons but we can make the code cleaner +% nevertheless. --- made issue --- +% +% \item The \tn{topsep} and \tn{partopsep} business is tricky to +% reproduce exactly (see \tn{@topsepadd} and \tn{@topsep}) because of +% how it accumulates when lists are nested immediately. +% +% \end{itemize} +% +% +% +% \subsection{Tasks} +% \begin{itemize} +% +% \item Change author to LaTeX Team once it's nice enough to deserve +% that label. +% +% \item Reproducing exactly the standard layouts and examples in the +% \pkg{enumitem} documentation. +% +% \item Hooks, but do not duplicate those that already exist as +% environment hooks. Hence, mostly around items. +% +% \item Customization and interaction with LDB: +% \begin{itemize} +% \item Allow arbitrary nesting depth with automatically defined +% styles for labels, counters etc. +% \item Adapt everything to font size! (e.g. footnotes). +% \item How to model the inheritance from trivlist to list to +% enumerate? +% \end{itemize} +% +% \item Add key--value settings mimicking \pkg{enumitem}'s ability to +% set any four of five horizontal parameters and deduce the fifth by +% $\cs{leftmargin} + \cs{itemindent} = \cs{labelindent} + +% \cs{labelwidth} + \cs{labelsep}$. +% +% \item Provide good ways to customize how overlong labels are dealt with. +% +% \item Use the \texttt{.aux} file. +% \begin{itemize} +% \item Implement the \tn{ref} styles that \pkg{enumitem} provides. +% \item Reverse enumerations, important in publication lists and the +% like. Somehow avoid needing 3 compilations for references to +% reverse enumerations to settle? +% \item Ability to calculate \tn{labelwidth} from the label contents. +% Share calculated parameters between multiple environments (cf.\ +% \texttt{resume} option). +% \end{itemize} +% +% \item Related to grabbing the whole list environment, and input syntax +% variations: +% \begin{itemize} +% \item Other layouts: tabular (see \pkg{listliketab} vs +% \pkg{typed-checklist}), multicolumn and horizontally numbered (see +% \pkg{tasks}), inline lists, runin lists in the easy case where +% there is no intervening \tn{par}. +% \item Formatting the item text in a +% box or similar (requires grabbing the whole list). +% \item Filtering which items to show: hide certain items according to +% criteria (useful together with list reuse), see +% \pkg{typed-checklist}. +% \item Shorthands \tn{iitem} for automatic nested lists, or \cs{1}, +% \cs{2} etc from \pkg{outlines}. +% \item Support markdown input like \pkg{asciilist}. +% \end{itemize} +% +% \item Check interaction with \texttt{babel} options such as +% \texttt{french} or \texttt{accadian} (see FrenchItemizeSpacing) +% +% \item RTL and vertical typesetting. +% \end{itemize} +% +% \section{Plan of attack of first prototype} +% +% Typesetting list environments involves a rather large number of +% parameters. They can be affected by the context such as the total +% list nesting level, the nesting level of the given type of list, and +% the font size. An environment like \texttt{enumerate} has two main +% aspects. +% \begin{itemize} +% \item It has a certain layout in the page, with vertical and +% horizontal spacing around it. This type of layout is shared with +% environments such as \texttt{quote}, \texttt{flushright}, or +% \texttt{tabbing}. This common layout is implemented in \LaTeXe{} +% through \cs{trivlist} (or \cs{list}). +% \item It defines how each \cs{item} should be typeset: how to +% construct the label, in particular the \texttt{counter} name, and +% how to format the content of the item. +% \end{itemize} +% +% This suggests defining two object types, \xt{block} and \xt{item} +% covering these two aspects.\footnote{Possibly also \xt{endblock} to +% deal with decorations at the end?} While the \xt{item} type will +% perhaps have a single template, one could typeset a \xt{block} object +% in several ways, for instance the standard \LaTeXe{} way or a fancy +% colored box. +% +% The \xt{general} \xt{block} template should receive the following +% parameters. The \xt{plain} \xt{block} template is a restricted +% template that freezes all item-related parameters to dummy values +% (\texttt{counter}, \texttt{start}, \texttt{resume}, +% \texttt{label-width}, \texttt{label-sep} and all \texttt{item-*}). +% The \xt{list} \xt{block} template is a restricted template\footnote{A +% better approach could be to have a notion of inheritance for object +% types, so that we end up with two different \emph{object types}. Then +% we can implement other template for the list object type: \xt{table} +% for lists typeset as rows/columns of a table, \xt{inline} for lists +% typeset in horizontal mode within a paragraph, and \xt{runin} for +% run-in lists.} that omits the \texttt{heading} parameter and whose +% default for \texttt{item-instance} is non-empty. +% \begin{itemize} +% \item Structural parameters: the \texttt{heading} to place before, +% \texttt{counter} name, \texttt{start} value, whether to +% \texttt{resume} a previous list, and the \texttt{item-instance} (an +% \xt{item} instance) to use when typesetting items. +% \item Vertical spacing and penalties: \texttt{beginpenalty}, +% \texttt{beginsep}, \texttt{begin-par-skip}, \texttt{item-penalty}, +% \texttt{item-skip}, \texttt{item-par-skip}, \texttt{endpenalty}, +% \texttt{end-skip}, \texttt{end-par-skip}. +% \item Horizontal spacing: \texttt{rightmargin}, \texttt{leftmargin}, +% \texttt{parindent}, \texttt{item-indent}, \texttt{label-width}, +% \texttt{label-sep}. +% \end{itemize} +% A \docclass should edit these templates (or define restricted +% templates) to set up default values that depend on \tn{g_block_nesting_depth_int}, +% namely how many lists are nested overall.\footnote{Does +% \pkg{xtemplate} provide a way to specify default values that are only +% evaluated once an instance is used?} The document class should then +% set up an instance of these templates for each environment, with +% appropriate settings such as a \texttt{heading}, a suitable +% \texttt{item-instance}, or making \texttt{margin-right} equal to +% \texttt{margin-left} in a \texttt{quote} environment. +% +% The \xt{inline-list} \xt{block} template receives many fewer +% parameters. Note that \texttt{beginsep}, \texttt{item-skip}, +% \texttt{end-skip} are now \emph{horizontal} skips. +% \begin{itemize} +% \item Structural parameters: \texttt{counter}, \texttt{start}, +% \texttt{resume}, \texttt{item-instance}. +% \item Spacing and penalties: \texttt{beginpenalty}, +% \texttt{beginsep}, \texttt{item-penalty}, \texttt{item-skip}, +% \texttt{endpenalty}, \texttt{end-skip}. +% \item Horizontal spacing: \texttt{label-width}, \texttt{label-sep}. +% \end{itemize} +% +% The \xt{std} \xt{item} template should receive the following +% parameters. They depend on the type of list and its nesting level +% among lists of such type, but typically not on the total nesting +% level. +% \begin{itemize} +% \item Counter name (\texttt{counter}), shared with the parent +% \xt{list} \xt{block} template, but needed for incrementing. +% \item Label construction: a function \texttt{counter-label} that +% produces the label from the counter name, used if \tn{item} is given +% without argument. +% \item References: a function \texttt{counter-ref} for how the label +% should be referred to when it is constructed from the counter, +% \texttt{label-ref} and \texttt{label-autoref} used when \tn{item} +% has an optional argument. +% \item Label formatting: \texttt{label-format} function, +% \texttt{label-strut} boolean. +% \item Label alignment (\texttt{label-align}, \texttt{label-boxed}, +% \texttt{next-line}). +% \item Content parameters: \texttt{text-font}. +% \item A \texttt{compatibility} boolean that controls for instance +% whether \tn{makelabel} is used. +% \end{itemize} +% The \docclass should set up an instance such as \xt{enumiii} for each +% environment and nesting level.\footnote{This should be made easily +% extendible to deeper levels.} +% +% A given environment will adjust some nesting levels, then call the +% \xt{block} instance appropriate to the environment type, passing it +% the \xt{item} instance appropriate to the environment and depth. +% Additional context-dependence could be provided by \pkg{l3ldb}, but +% the main context-dependence should not rely on it for simplicity +% reasons and incidentally because \pkg{l3ldb} is not yet available. +% +% +% \Finale +% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\endinput diff --git a/macros/latex/required/latex-lab/latex-lab-block-tagging.pdf b/macros/latex/required/latex-lab/latex-lab-block-tagging.pdf Binary files differnew file mode 100644 index 0000000000..7b35aa4c7f --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-block-tagging.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-firstaid.dtx b/macros/latex/required/latex-lab/latex-lab-firstaid.dtx new file mode 100644 index 0000000000..8f474e6b12 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-firstaid.dtx @@ -0,0 +1,147 @@ +% \iffalse meta-comment +% +%% File: latex-lab-firstaid.dtx (C) Copyright 2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-firstaid.dtx} +\end{document} +%</driver> +% +% \fi +% +% \title{The \textsf{latex-lab-firstaid} package\\ +% Temporary patches to external packages} +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{Version 0.80 2023-06-04} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \section{Introduction} +% +% The followings contains small temporary changes to external packages to avoid +% errors with the new tagging code. +% +% Similar to the main firstaid package the goal is to remove the +% patches once the packages have been updated. + +% \section{Implementation} +% \begin{macrocode} +%<*package> +%<@@=tag> +% \end{macrocode} +% \begin{macrocode} +\ProvidesPackage {latex-lab-testphase-firstaid} [2023-06-04 v0.8 + Temporary patches to external packages need for the tagging project] +% \end{macrocode} + +% \subsection{blindtext} +% The blindtext package generates lists with nested \cs{loop} command. +% The inner loop introduces a group around the list which error when lists are tagged +% as \cs{@doendpe} is lost. +% \begin{macrocode} +\AddToHook{file/blindtext.sty/after}[latex-lab-firstaid]{% + \FirstAidNeededT{blindtext}{sty}{\blindfiledate\space\blindfileversion\space% + blindtext-Package}% + {% + \renewcommand{\blind@items}{% + \setcounter{blind@listcount}{1}% + \loop + \ifblind@optional + \ifblind@long + \item[\blindtext@countitem] \blindtext@text + \else + \item[\blindtext@count] \blindtext@item + \fi + \else % \blind@optionalfalse + \ifblind@long + \item \blindtext@text + \else + \item \blindtext@countitem + \fi + \fi % \ifblind@optional + {% + \loop + \ifnum\value{blindlistlevel}>\value{blindlist@level}% + \stepcounter{blind@levelcount}% + \blind@list[\value{blindlist}]\relax + \addtocounter{blind@levelcount}{-1}% + \setcounter{blind@listcount}{1}% + \repeat + \expandafter}\if@endpe\@doendpe\fi % <----------changed + \ifnum\value{blind@listcount}<\value{blindlist}% + \stepcounter{blind@listcount}% + \repeat + } + }% + } +% \end{macrocode} +% \subsection{ltugboat} +% ltugboat need only a redefinition of \cs{l@section} to add the hooks +% \begin{macrocode} +\AddToHook{file/ltugboat.cls/after} + { + \def\l@section#1#2{\addpenalty{\@secpenalty}% + \addvspace{\TBtocsectionspace}% + \@tempdima 1.5em + \begingroup + \parindent\z@ \rightskip\z@ % article style makes \rightskip > 0 + \parfillskip\z@ + \TBtocsectionfont + \leavevmode\advance\leftskip\@tempdima\hskip-\leftskip + \UseHookWithArguments{contentsline/text/before}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + \csname contentsline@text@1@format\endcsname{#1}% + \UseHookWithArguments{contentsline/text/after}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + \nobreak\hfil + \nobreak\hb@xt@\@pnumwidth{\hss + \UseHookWithArguments{contentsline/page/before}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + #2% + \UseHookWithArguments{contentsline/page/after}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + }\par + \endgroup} + } +% \end{macrocode} + +% \begin{macrocode} +%</package> +% \end{macrocode} +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{firstaid-latex-lab-testphase.ltx} + [2023-06-04 v0.8 Temporary patches to external packages need for the tagging project] + +\RequirePackage{latex-lab-testphase-firstaid} + +%</latex-lab> +% \end{macrocode} diff --git a/macros/latex/required/latex-lab/latex-lab-firstaid.pdf b/macros/latex/required/latex-lab/latex-lab-firstaid.pdf Binary files differnew file mode 100644 index 0000000000..e1f696499d --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-firstaid.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-float.dtx b/macros/latex/required/latex-lab/latex-lab-float.dtx new file mode 100644 index 0000000000..430b2aec96 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-float.dtx @@ -0,0 +1,494 @@ +% \iffalse meta-comment +% +%% File: latex-lab-float.dtx (C) Copyright 2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-float.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \textsf{latex-lab-floats} package\\ +% Tagging of floats } +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{v0.81 2023-06-07} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% \begin{documentation} +% \begin{abstract} +% The following code implements a first draft for the tagging of float +% environments +% \end{abstract} +% +% +% \section{Introduction} +% +% The code here handle the tagging of float environments. +% +% Figures (and tables) are in \LaTeX{} typically typeset in float environments. +% These are boxes which can \emph{float} away to special float areas on the pages, +% e.g., to the top or the bottom of a page or to special float pages. +% If the rules allow it they can also be placed in the main text stream (\enquote{here}). +% Floats can also be collected at the end of the document. +% In either case the order within each type of floats +% (e.g., figures, tables, algorithms, etc.) is preserved. +% +% A special type, called a H-float, (provided by the float package) +% is always placed in the main text stream and does not +% necessarly preserve the order with normal floats of the same type: It is basically +% a minipage with a caption. +% +% Floats typically contain a figure (or a table, etc.) and a caption, +% but more complex constructions with subfigures, +% copyright statements, sources or additional description are possible too. +% +% In the \LaTeX{} source a float is normally more or less at the place of +% the first call-out, but when preparing a document for print the code +% is sometimes moved to place floats in a more visually pleasing way. +% +% \section{Tagging} +% +% Floats (with the exception of H-floats) do not belong into the text stream, they +% are \enquote{consultation objects}: Readers must be able to choose if and when they read the float. +% Floats have captions, the PDF rules require that a \texttt{Caption} is the first or last +% structure in its parent structure. +% This poses some challenges on a good tagging. +% +% In PDF~2.0 there is the suitable \texttt{Aside} tag which hopefully will +% be handled correctly regarding the reading order once processor actually support +% PDF~2.0. But in PDF~1.7 we rolemap it to \texttt{Note} and this doesn't lead to +% a good reading order. The code therefore collect the float structures and moves +% them to a \texttt{Sect} the end of the document or the chapter +% (H-floats once they are handled will not be moved). +% +% To fulfill the requirement that a \texttt{Caption} should be at the begin or end, we always +% move it to the begin of the structure. If a float has two captions the author +% has to insert a command which splits the float in two. +% +% Subfigures and subcaptions are currently not handled, but will be implemented +% as simple \texttt{Part} with their own \texttt{Caption}. +% +% \section{Links} +% The code disable the caption patches from hyperref. It will add an anchor at the +% begin of the float or a split. It changes caption so that a link to a caption label +% will go to the begin of the float. +% +% \section{Tools} +% +% The code add two keys for the \cs{tagtool} command +% +% \begin{description} +% \item[flush-floats] This will flush out the collected floats sofar (currently +% table and figure. The value is a sectioning level, e.g. \texttt{section} or \texttt{chapter}, +% the floats will then inserted as a \texttt{Sect} of this level (all \texttt{Sect} of smaller or equal +% level are closed). The key then starts a new container for following floats. +% If no value is given, the \texttt{Sect} is at the document level. The code automatically +% flush all open floats at the end of the document. +% +% \item[split-float] This can be used inside a float if there are two captions. +% It will only work reasonably well if the content of the float parts are in a sensible order +% and can be separated by this command. More complex setups with tabulars will need more +% thoughts +% +% \end{description} +% +% +% \begin{macrocode} +%<@@=tag> +%<*package> +% \end{macrocode} +% \end{documentation} +% \begin{implementation} +% \section{Implementation} +% \begin{macrocode} +\ProvidesExplPackage {latex-lab-testphase-float} {2023-04-28} {0.8} + {Code related to the tagging of floats} +% \end{macrocode} +% \subsection{Variables} +% We rolemap to Aside, and float sections to Sect +% +% \begin{macrocode} +\tagpdfsetup{add-new-tag=float/Aside} +\tagpdfsetup{add-new-tag=figures/Sect} +\tagpdfsetup{add-new-tag=tables/Sect} +% \end{macrocode} +% +% \begin{variable}{ +% \g_@@_float_sect_prop, +% \g_@@_float_types_seq, +% \@current@float@struct +% } +% These variables will hold the structure number for the float container +% and the list of float types. Currently only figure and table are supported +% TODO: interface to declare new float types. +% \begin{macrocode} +\prop_new:N \g_@@_float_sect_prop +\seq_new:N \g_@@_float_types_seq +\seq_gput_right:Nn \g_@@_float_types_seq {figure} +\seq_gput_right:Nn \g_@@_float_types_seq {table} +\tl_new:N\@current@float@struct +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_@@_float_sect_bool} +% With this boolean float collection is switched on and off. +% Currently it is always on and set globally. +% TODO: think if an interface is needed. +% TODO: would a local variable make more sense? +% \begin{macrocode} +\bool_new:N \g_@@_float_sect_bool +\bool_gset_true:N \g_@@_float_sect_bool +% \end{macrocode} +% \end{variable} +% +% +%\subsection{Moving float structures} +% +% Currently it is for all float types or none. +% Probably we will need some more options here to select some float types. +% +% \begin{macro}{\@@_float_init_collect:} +% This initializes a container structure for every float type. +% It can be used more than once in a document, this allows to have e.g. +% chapter wise containers. +% \begin{macrocode} +\cs_new_protected:Npn\@@_float_init_collect: + { + \bool_if:NT\g_@@_float_sect_bool + { + \seq_map_inline:Nn\g_@@_float_types_seq + { + \tag_struct_begin:n{tag=##1s,stash} + \prop_gput:Nnx\g_@@_float_sect_prop {##1-struct}{\int_use:N\c@g__tag_struct_abs_int} + \tag_struct_end: + } + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_float_stop_sect:} +% This pushes out the floats. For every type is checks if there is actually +% a float of this type and then writes out the container structure. +% \begin{macrocode} +\cs_new_protected:Npn \@@_float_stop_sect: + { + \bool_if:NT\g_@@_float_sect_bool + { + \seq_map_inline:Nn\g_@@_float_types_seq + { + \prop_get:NnNT\g_@@_float_sect_prop{##1-used}\l_@@_tmpa_tl + { + \exp_args:Ne + \tag_struct_use_num:n{\prop_item:Nn\g_@@_float_sect_prop{##1-struct}} + \prop_gremove:Nn \g_@@_float_sect_prop{##1-used} + } + } + } + } +% \end{macrocode} +% \end{macro} + +% \begin{macro}{flush-floats} +% This is a key for \cs{tagtool} to flush out the collected floats. +% The value allows to set to which level the create Sect contains. +% So \texttt{section} will close all previous Sect until the section level +% and create a new section. +% \begin{macrocode} +\keys_define:nn { tag / tool} + { + flush-floats .code:n = + { + \keys_set:nn {tag / tool} {sec-stop=#1} + \@@_float_stop_sect: + \@@_float_init_collect: + }, + flush-float .default:n = Document + } +% \end{macrocode} +% \end{macro} +% We need at least one pair +% \begin{macrocode} +\AddToHook{begindocument/end}[latex-lab/float] + {\@@_float_init_collect:} +\AddToHook{tagpdf/finish/before}[latex-lab/float] + {\par\__tag_sec_end:n{-10}\@@_float_stop_sect:} +\DeclareHookRule{tagpdf/finish/before}{latex-lab/float}{before}{tagpdf} +% \end{macrocode} +% \subsection{Splitting floats} +% \begin{macro}{split-float} +% TODO: check if the target affect spacing!! +% \begin{macrocode} +\keys_define:nn { tag / tool} + { + split-float .code:n = + { + \@@_float_end: + \@@_float_begin: + \MakeLinkTarget[tagstructure]{g__tag_struct_abs_int} + } + } +% \end{macrocode} +% \end{macro} + +% \subsection{Patching} +% \begin{macro}{\@@_float_stop_par:,\@@_float_start_par:} +% if a float is in a par, we need commands to stop and restart the P-mc +% \begin{macrocode} +\cs_new_protected:Npn \@@_float_stop_par: + { + \tag_mc_end: + \bool_if:NF \g_@@_float_sect_bool + { + \tag_struct_end: + } + } +\cs_new_protected:Npn \@@_float_start_par: + { + \bool_if:NF \g_@@_float_sect_bool + { + \tag_struct_begin:n{tag=text}% + } + \tag_mc_begin:n{tag=P} + } + +% \end{macrocode} +% \end{macro} +% These commands are the main commands to start and end the float tagging. +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_float_begin: + {% +% \end{macrocode} +% We test if the float structure should be included directly or move to a dedicated section. +% \begin{macrocode} + \bool_if:NTF\g_@@_float_sect_bool + { + \exp_args:Ne + \tag_struct_begin:n{tag=float,parent=0\prop_item:No\g_@@_float_sect_prop{\@captype-struct}}% + \prop_gput:Nxx \g_@@_float_sect_prop {\@captype-used}{true} + } + { + \tag_struct_begin:n{tag=float} + } + \tl_set:Nx\@current@float@struct{\tag_get:n{struct_num}}% + \typeout{Float structure: \@current@float@struct} + } + +\cs_new_protected:Npn\@@_float_end:{\tag_struct_end:} %end Aside + +% \end{macrocode} +% This patches the main command \cs{@xfloat}. +% There is a : in the code, so we disable expl3 syntax +% \begin{macrocode} +\ExplSyntaxOff +\def\@xfloat #1[#2]{% + \@nodocument + \def \@captype {#1}% + \def \@fps {#2}% + \@onelevel@sanitize \@fps + \def \reserved@b {!}% + \ifx \reserved@b \@fps + \@fpsadddefault + \else + \ifx \@fps \@empty + \@fpsadddefault + \fi + \fi + \ifhmode + \@bsphack +% \end{macrocode} +% If the float is in hmode we have to interrupt the P +% \begin{macrocode} + \@nameuse{@@_float_stoppar:} %<---end P + \@floatpenalty -\@Mii + \else + \@floatpenalty-\@Miii + \fi + \ifinner + \@parmoderr\@floatpenalty\z@ + \else + \@next\@currbox\@freelist + {% + \@tempcnta \sixt@@@@n + \expandafter \@tfor \expandafter \reserved@a + \expandafter :\expandafter =\@fps + \do + {% + \if \reserved@a h% + \ifodd \@tempcnta + \else + \advance \@tempcnta \@ne + \fi + \else\if \reserved@a t% + \@setfpsbit \tw@ + \else\if \reserved@a b% + \@setfpsbit 4% + \else\if \reserved@a p% + \@setfpsbit 8% + \else\if \reserved@a !% + \ifnum \@tempcnta>15 + \advance\@tempcnta -\sixt@@@@n\relax + \fi + \else + \@latex@error{Unknown float option `\reserved@a'}% + {Option `\reserved@a' ignored and `p' used.}% + \@setfpsbit 8% + \fi\fi\fi\fi\fi + }% + \@tempcntb \csname ftype@\@captype \endcsname + \multiply \@tempcntb \@xxxii + \advance \@tempcnta \@tempcntb + \global \count\@currbox \@tempcnta + }% + \@fltovf + \fi +% \end{macrocode} +% This starts the structure for the float. +% \begin{macrocode} + \@nameuse{@@_float_begin:}% + \global \setbox\@currbox + \color@vbox + \normalcolor + \vbox \bgroup + \hsize\columnwidth + \@parboxrestore + \@floatboxreset +% \end{macrocode} +% We add a target for links. TODO: check that it doesn't affect spacing!! +% \begin{macrocode} + \MakeLinkTarget[tagstructure]{g__tag_struct_abs_int}% +}% +% \end{macrocode} +% The end code of the float ... +% \begin{macrocode} +\def\end@float{% + \@endfloatbox + \@nameuse{@@_float_end:}% + \ifnum\@floatpenalty <\z@ + \@largefloatcheck + \@cons\@currlist\@currbox + \ifnum\@floatpenalty <-\@Mii + \penalty -\@Miv + \@tempdima\prevdepth + \vbox{}% + \prevdepth\@tempdima + \penalty\@floatpenalty + \else + \vadjust{\penalty -\@Miv \vbox{}\penalty\@floatpenalty}\@Esphack + \@nameuse{@@_float_start_par:} %restart P safe here?? + \fi + \fi +} +\ExplSyntaxOn +% \end{macrocode} +% +% \subsection{Handling captions} +% +% To avoid that hyperref interferes we disable its patches: +% \begin{macrocode} +\def\hyper@nopatch@caption{} +% \end{macrocode} +% As we will use the structure number in the target, we need to provide a +% theH-representation. (Once the kernel will create +% theH-representation generally this will be provided automatically, as tagpdf uses +% \cs{newcounter}) +% \begin{macrocode} +\providecommand\theHg__tag_struct_abs_int{\int_use:N\c@g__tag_struct_abs_int} +% \end{macrocode} + +% \begin{macro}{\@makecaption} +% \cs{@makecaption} is defined by the classes so we overwrite it for now +% at begin document. +% \begin{macrocode} +\AddToHook{begindocument} + { + \long\def\@makecaption#1#2{% + \vskip\abovecaptionskip + \xdef\@currentHref{tagstructure.\@current@float@struct}% +% \end{macrocode} +% we don't want tagging when storing the caption for the singleline check +% \begin{macrocode} + \tag_stop:n{caption} + \sbox\@tempboxa{#1:~#2}% + \tag_start:n{caption} +% \end{macrocode} +% we stop paratagging. TODO: check +% \begin{macrocode} + \tagtool{para=false} + \tag_struct_begin:n{tag=Caption,parent=\@current@float@struct} +% \end{macrocode} +% move the caption to the begin of the float structure: +% \begin{macrocode} + \seq_gpop_right:cN {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl + \seq_gput_left:cV {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl + \ifdim \wd\@tempboxa >\hsize + \tag_struct_begin:n{tag=Lbl} + \tag_mc_begin:n{} + #1:~ + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin:n{} + #2\par + \tag_mc_end: + \else +% \end{macrocode} +% we don't reuse the box as it doesn't contain tagging, but set the text explicitly. +% \begin{macrocode} + \global \@minipagefalse + \hb@xt@\hsize{\hfil + \tag_struct_begin:n{tag=Lbl} + \tag_mc_begin:n{} + #1:~ + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin:n{} + #2\par + \tag_mc_end:\hfil}% + \fi + \tag_struct_end: %caption + \vskip\belowcaptionskip} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} + +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{float-latex-lab-testphase.ltx} + [2023-04-30 v0.8 code related to the tagging of floats] +\RequirePackage{latex-lab-testphase-float} +%</latex-lab> +% \end{macrocode} +% \end{implementation} diff --git a/macros/latex/required/latex-lab/latex-lab-float.pdf b/macros/latex/required/latex-lab/latex-lab-float.pdf Binary files differnew file mode 100644 index 0000000000..bdd5ef0169 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-float.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-footnotes.dtx b/macros/latex/required/latex-lab/latex-lab-footnotes.dtx index 6fe7ff6955..4c8c9b73a6 100644 --- a/macros/latex/required/latex-lab/latex-lab-footnotes.dtx +++ b/macros/latex/required/latex-lab/latex-lab-footnotes.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment % %% File: latex-lab-footnotes.dtx -% Copyright (C) 2022 The LaTeX Project +% Copyright (C) 2022-2023 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -53,19 +53,19 @@ % offering configurable methods for layout and functionality % adjustments that avoid overwriting each other when used in % classes as well as in packages (as far as possible --- obviously -% some adjustments are mutally exclusive). This is achieved by -% providing a a larger number of hooks (for areas where different +% some adjustments are mutually exclusive). This is achieved by +% providing a larger number of hooks (for areas where different % packages/classes can easily coexist with their adjustments) and a % number of configuration points to which only one class or package -% can write to successfully (in case of multiple changes the the +% can write to successfully (in case of multiple changes the % last one wins). The latter are for special functionality, e.g., % if footnote text is typeset as a single paragraph, it can't be configured % the same time to be typeset vertically with one footnote below % each other. % % The interfaces are set up to support tagged PDF, but in order -% for this to work, all packages altering the fontnote setup should -% use the inferfaces provided here and not do it through the +% for this to work, all packages altering the footnote setup should +% use the interfaces provided here and not do it through the % legacy methods (though there is some support for the latter as % well, but if will not work in a cases). % @@ -81,7 +81,7 @@ % that was used by most document classes, % but \cs{@makefntext} had to be defined in the class itself because % the format didn't provide a default. As a result you will find -% definitions for the latter in all document classes and defintions +% definitions for the latter in all document classes and definitions % for \cs{@makefnmark} only in very few. % % Furthermore, to enable special footnote layouts or provide @@ -114,7 +114,7 @@ % % In contrast the hooks are of interest to many classes to provide % their layout alterations in a way that it works smoothly with -% other packages handling aspects of foonote formatting. +% other packages handling aspects of footnote formatting. % % % \subsection{Formatting the mark in the main text} @@ -140,7 +140,7 @@ % % Executed at the very beginning of \cs{footnotemark}. Currently % there are two packages (\pkg{bibarts} and \pkg{chextras}) that -% prepend material at this point (not ncessarily correctly, e.g., +% prepend material at this point (not necessarily correctly, e.g., % they do not all check that they are in horizontal mode). % % This hook is paired with hook \hook{fnmark/after}. @@ -163,15 +163,15 @@ % \item[\hook{fnmark/begin}] % % This hook is executed directly in front of the typeset mark. -% This is the place where \pkg{hyperref} adds part of its code, -% i.e., after the \cs{nobreak} mentioned above. With a closer -% integration of \pkg{hyperref} this hook may not be necessary at -% all. +% This is the place where \pkg{hyperref} would have added +% part of its code, i.e., after the \cs{nobreak} mentioned above. +% With the integration of hyperlinks in the tagging code +% this hook may not be necessary at all. % % \item[\hook{fnmark/end}] % % This hook is executed directly after the typeset mark. It is -% used by \pkg{hyperref}, \pkg{memhfixc}, \pkg{scrlttr2}, and +% used by \pkg{memhfixc}, \pkg{scrlttr2}, and % \pkg{footmisc}. Used, for example, to implement support for % multiple marks in succession. % @@ -227,9 +227,9 @@ % \item[\cs{@footnotetext@cfgpointiii} (no argument)] % % By default this configuration point adds a strut to the -% footnote material. so that consecutive footnotes are properly +% footnote material so that consecutive footnotes are properly % spaced vertically. In some use cases this is not appropriate -% (e.g., when running all footnotes s a single paragraph) and so +% (e.g., when running all footnotes as a single paragraph) and so % this configuration point can cancel the action or do something % else instead. % @@ -261,17 +261,18 @@ % % If tagging is produced this configuration point is also % responsible for surrounding the mark with the appropriate tags -% marking the mark as an Lbl. It does this using the command \cs{tag@FELbl}. +% marking the mark as an Lbl. It does this using the command +% \cs{tag@FENoteLbl}. % % \item[\cs{@makefntext@cfgpointii} (1 argument)] % % This configuration point manages the formatting of the footnote -% text once the mark has been typeset. +% text once the mark has been typeset. % % If tagging is produced this configuration point is also % responsible for surrounding the mark with the appropriate tags % marking the mark as an MC of type FENote. It does this using -% the command \cs{tag@FENote}. +% the command \cs{tag@FENotetext}. % % \end{description} % @@ -335,7 +336,7 @@ % % At the very end of \cs{footnotetext} we execute the hook % \hook{fntext/after} which is a reversed hook paired with -% \hook{fntext/before}. Some packages, e.g., \pkg{linuex}, have +% \hook{fntext/before}. Some packages, e.g., \pkg{linguex}, have % code in that position. % % \end{description} @@ -346,7 +347,7 @@ % \subsubsection{Additional configuration possibilities} % % The formatting of the footnote mark in front of the footnote -% texts is influenced by the setting of the dimen parameter +% text is influenced by the setting of the dimen parameter % \cs{footnotemargin}. By default its value is 1.8em in the current % text font (or \texttt{-}\cs{maxdimen} when the para option is % chosen). The following rules apply: @@ -381,7 +382,247 @@ % \end{itemize} % % -% \section{Tagging support} +% \section{Tagging and hyperlinking support} +% +% Footnotes consist of a \emph{footnotemark} (short: mark) that is typically placed in the text +% as a superscript number like this\footnotemark[1], and a \emph{footnotetext} +% (short: note) that is placed at the bottom of the page. +% The \emph{footnotetext} normally repeats at the begin the mark as a visual clue. +% +% Tagging (and hyperlinking) has to connect the mark with the note. +% For the tagging code, we assume that every mark has exactly one associated note, +% and that every note is associated to at least one mark +% and can have more associated marks. +% +% The mark doesn't need to be visible, e.g. the typesetted +% mark\textsuperscript{1--3} denotes three marks, where the second is invisible. +% Tagging should produce here probably three \texttt{Lbl} structures +% (one without content), and an artifact for the range marker. +% If such a range is used, links can only point to the notes 1 and 3 and +% one has to suppress the linking for the second mark. +% This means that links and tagging are also related +% to the actual formatting of the footnote mark. +% In the following this problem is mostly ignored for now, but +% should not be forgotten and handled later. +% +% \subsection{Technical details for the tagging} +% +% The \emph{footnotemark} should create a \texttt{/Lbl} structure\footnote{to make it easier +% to identify the role we use \texttt{/footnotemark} which we rolemap to \texttt{/Lbl}} that should contain a \texttt{/Ref} entry pointing +% to the structure of the \emph{footnotetext}. +% +% The \emph{footnotetext} should create a \texttt{/FENote}\footnote{We tag it as \texttt{/footnote} and role map it.} +% structure with a \texttt{/Ref} +% entry pointing to the structures of \emph{all} marks related to the note. +% The mark at the begin of the +% note is in a \texttt{/Lbl}\footnote{We tag it as \texttt{/footnotelabel}.} +% structure but has to fulfil no special requirements. +% +% Structure objects and the underlying properties used by the tagging +% code are initialized when the structure is opened. This means that one can not +% directly add data to a future structure +% but as structure objects are written at the end of the document it is +% possible to update \texttt{/Ref} entries in an end document hook. +% +% +% So tagging has to solve two problems: +% \begin{itemize} +% \item the mark and the footnote text must be surrounded by the correct structure +% and marked content commands. This is not trivial +% as there are various layouts (bottom, marginpar, minipage) and the tagging +% from the automatic paratagging must be taken into account if one want to avoid +% faulty nesting. +% +% \item It must detect which marks are related to which notes +% so that it can setup the \texttt{/Ref} cross-references. +% \end{itemize} +% +% +% \subsection{Requirements for links} +% +% Links should go from the mark to the note. Sometimes it has been requested +% that links go back too, but as there +% can be more than one mark connected to a note it is not clear how to decide to which mark it should go. +% Using the keys from the PDF viewer to go back is normally better. +% +% Links are closely related to the references stored in the \texttt{/Ref} +% entry of a mark and so are handled in the code together with them. +% But there are subtle technical differences to take care of +% as links and destinations are whatsits and so must be created at the correct time. +% +% It should be possible to suppress the links both globally and locally.\footnote{ +% Currently hyperref only offers the option to suppress the +% footnote links globally +% with the option \texttt{hyperfootnotes=false}. To suppress them locally +% only the \texttt{NoHyper} environment is provided.} +% +% +% \subsection{The algorithmus to connect marks and notes} +% +% +% The connection is made by comparing the value of \cs{@thefnmark}. +% +% The standard mark commands (\cs{footnotemark} and \cs{footnote}) +% store the current value of \cs{@thefnmark} +% with their own structure number as a key in a property. +% +% A following \cs{footnotetext} compares its own \cs{@thefnmark} with the values in +% the prop. If there is a match it stores the structure numbers and removes the entries +% from the properties (so in a normal document the property will never contain more than +% a few entries). +% +% This works well as long as the \cs{footnotemark} commands are issued before the \cs{footnotetext} and +% as long as nothing unusual is done to \cs{@thefnmark}. +% It also works if a document uses more than one footnote series as long as they have distinct numbering +% systems, but in case a distinction is needed it is possible to define +% a new data structure and to switch locally to use this +% container. The following three commands are used for this. +% +% The default property uses the name \texttt{default} +% +% \begin{function}{\fnote_new:nn} +% \begin{syntax} +% \cs{fnote_new:nn}\Arg{name}\Arg{key/value option} +% \end{syntax} +% +% This commands set up the needed data structure. Currently this only +% consists of a property which is used to store and manage the mark values. +% There are no options yet. +% \end{function} +% +% \begin{function}{\fnote_mark_gput:nn,\fnote_mark_gput:no,\fnote_mark_gput:oo} +% \begin{syntax} +% \cs{fnote_mark_gput:nn}\Arg{mark}\Arg{footnote type name} +% \end{syntax} +% This command stores the current structure number as key and the \meta{mark} as +% value in the property associated with the \meta{footnote type name} +% \end{function} +% +% \begin{function}{\fnote_mark_gpop:nnN} +% \begin{syntax} +% \cs{fnote_mark_gpop:nnN}\Arg{mark}\Arg{footnote type name}\meta{sequence} +% \end{syntax} +% This command stores the keys/structure numbers whose value are \meta{mark} in the +% property associated with \meta{footnote type name} in the \meta{sequence} +% and then remove them from the property. The content of the sequence can then be +% used to create link targets and references. +% \end{function} +% +% +% \subsubsection{\cs{footref}} +% +% \cs{footref} use internally the same command to set the mark as \cs{footnotemark}, it only +% defines \cs{@thefnmark} differently. This \cs{@thefnmark} is not suitable for the method described +% above, as it contains a reference command it can't be used to match a note, also \cs{footref} can +% be used after the note has already been set. \cs{footref} disables therefore the automatic detection. +% +% Instead the \cs{label} command is (currently with the help of a hook from the \texttt{nameref} package) +% extended in the \cs{footnotetext} command to also store the structure number and \cs{footref} retrieves this +% number to setup the reference and the link. +% +% The structure related to the \cs{footref} is added to the end of the \texttt{/Ref} array of the note and so the +% \texttt{/Ref} array doesn't necessarly reflect the order of the marks in the document. It would probably +% be possible to change this, but it is not clear if it actually matters and so it worth the additional coding +% and processing. +% +% \subsubsection{\cs{footnotemark} after \cs{footnotetext}} +% +% The automatic detection doesn't work if a \cs{footnotemark} is issued after +% the \cs{footnotetext} it refers to. There will be no error, but neither the link nor +% the \texttt{/Ref} will connect both. +% +% The simple way to handle this is to use a label and \cs{footref}: +% +% \begin{verbatim} +% \footnotetext{\label{fn:a}text} ... \footref{fn:a} +% \end{verbatim} +% +% An alternative would be to extend the syntax of \cs{footnotemark} and +% \cs{footnotetext} to allow to add a label which can then be used. +% For example +% +% \begin{verbatim} +% \footnotetext[label=fn:a]{text} ... \footnotemark[label=fn:a] +% \end{verbatim} +% +% As both have already an optional argument, that requires the optional argument extension. +% +% +% \subsection{Links} +% +% The structure numbers detected for the \texttt{/Ref} are also used for links: +% even if tagging is not activated the tagging commands are defined through +% the \pkg{tagpdf-base} package +% and the structure commands increase the structure counter and this info can be used. +% +% A \cs{footnotetext} creates a bunch of destinations (in most cases this sums up to +% two destinations): one for every structure number in the \texttt{/Ref} (used as target +% by the mark commands) and one for the structure number of the footnotetest itself +% (used as target by \cs{footref}s commands). +% +% \subsection{Implementation details} +% +% \subsection{Handling the mark} +% +% The mark in the text is handled by redefining the kernel configuration point +% \cs{@kernel@process@makefnmark} to \cs{tag@FEMark}. +% It takes one argument, \cs{@makefnmark}, the command which formats the +% mark, and surrounds it by link and tagging commands. +% At the point where \cs{@kernel@process@makefnmark} is issued \cs{@thefnmark} has already been +% defined and can be used to setup the reference detections. +% +% +% \subsection{Handling the footnotetext} +% +% The main part is done by redefining \cs{@kernel@process@footnotetext}. This configuration point takes two arguments, \cs{@footnotetext@cfgpoint} (by default \verb+\insert\footins+) and as second argument lots of code related to typesetting the notemark and the footnote text with the actual content of the footnote text somewhere in the middle. +% +% The redefinition of \cs{@kernel@process@footnotetext} surrounds the content with the structure command +% and tries to detect to which mark the note is related. +% +% The actual typesetting of the note text is done +% by \cs{@makefntext}/\cs{fnote_makefntext:n}. In the new implementation this contains two configuration +% points, \cs{@makefntext@cfgpoint} and \cs{@makefntext@cfgpointii}. These are redefined to add the tagging commands around note mark and note text. +% +% \subsection{Footnotes in minipages} +% +% In minipages the \cs{footnote} command uses a special marker +% (small italic letters by default) and puts the +% footnote text at the bottom of the box. The \cs{footnotemark} +% command uses the standard footnote counter and marker (and so typically +% creates a superscript number). +% It is meant to be used with a \cs{footnotetext} \emph{outside} +% the minipage to create a footnote mark which refers to a footnote text +% at the bottom of the page. +% This means to repeat a footnote marker in a minipage you should use the \cs{footref} command. +% +% Tagging works quite similar to normal footnotes if the new definition is used +% and if the minipage code is changed to use the new configuration point. +% The main problem here is currently the tagging of the minipage itself. +% +% \section{TODOs} +% +% \begin{itemize} +% +% \item tagging destroys footnotes directly following the text with pdflatex. +% +% \item there is a dependency on nameref as it provides the hook in \cs{label} +% used by the \cs{footref} code. +% +% \item there is a dependency to etoolbox as we patch \cs{\@iiiminipage} +% +% \item Special formatting of footnote marks in the text, e.g. if ranges or commas are +% used require special care as they should normally mark up such text as artifacts and +% perhaps have to insert empty structures to represent an invisible mark. This must be coordinated +% with the relevant packages and classes. +% +% \item manyfoot doesn't work correctly and must be analyzed. +% +% \item Check if additional kernel configuration points are needed/possible +% to avoid the redefinitions of \cs{@makefntext@cfgpoint} and \cs{@makefntext@cfgpointii}. +% +% \item \pkg{memoir} is not supported at all and errors when the code tries to patch +% \cs{@makefntext}. +% \end{itemize} % % \emph{To be documented} % @@ -403,46 +644,171 @@ % \subsection{File declaration} % \begin{macrocode} \ProvidesFile{latex-lab-footnotes.ltx} - [2022-07-22 v0.6b changes to the footnote interfaces] + [2023-02-04 v0.7 changes to the footnote interfaces] % \end{macrocode} % +% \subsection{code not fully handled yet} % \begin{macrocode} - +% % latex.ltx +% not looked at yet +% \@mpfootnotetext is probably no longer needed, or only to support other +% classes and package. See below about the minipage code. +% +% \long\def\@mpfootnotetext#1{% +% \global\setbox\@mpfootins\vbox{% +% \unvbox\@mpfootins +% \reset@font\footnotesize +% \hsize\columnwidth +% \@parboxrestore +% \def\@currentcounter{mpfootnote}% +% \protected@edef\@currentlabel +% {\csname p@mpfootnote\endcsname\@thefnmark}% +% \color@begingroup +% \@makefntext{% +% \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% +% \par +% \color@endgroup}} +% ======== +% used by the minipage footnote code. +% +% \def\@mpfn{footnote} +% \def\thempfn{\thefootnote} +% ========= +% this perhaps need some configuration options. +% +%\def\@makefnmark{\hbox{\@textsuperscript{\normalfont\@thefnmark}}} +% +% ========= +%% alterations not covered: +% +% ./arabtex/afoot.sty --- too different (and probably too old) +% +% ===== +% alterations of footnotetext not covered: +% +% ./revtex4-1/revtex4-1.cls ./revtex/ltxutil.sty ./revtex/revtex4-2.cls ... (need analysis) +% ./bigfoot/bigfoot.sty +% +% memoir needs checking too +% +% ===== +% +% use of kerns to mark h-mode positions (unit sp) +% +% 1 = CJK +% 2 = CJK +% 3 = multiple footnotes (footmisc, koma, eledmac, tufte, memoir, +% parnotes, sidenotes) +% 3 = outer kern in letter spacing (letterspace) +% 3 = beginning of list (examdesign.cls) +% 4 = CJK pigin +% 5 = CJK ruby - % not looked at yet - -\long\def\@mpfootnotetext#1{% - \global\setbox\@mpfootins\vbox{% - \unvbox\@mpfootins - \reset@font\footnotesize - \hsize\columnwidth - \@parboxrestore - \def\@currentcounter{mpfootnote}% - \protected@edef\@currentlabel - {\csname p@mpfootnote\endcsname\@thefnmark}% - \color@begingroup - \@makefntext{% - \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% - \par - \color@endgroup}} - - -\def\@makefnmark{\hbox{\@textsuperscript{\normalfont\@thefnmark}}} - - - -\def\@mpfn{footnote} -\def\thempfn{\thefootnote} - - - +% 1-4 = polyglossia for korean +% +% \end{macrocode} %------------------------------------- - - +% \begin{macrocode} \ExplSyntaxOn +% \end{macrocode} +% \subsection{Temporary variables} +% \begin{macrocode} +\prop_new:N \l_@@_tmpa_prop +\tl_new:N \l_@@_tmpa_tl +% \end{macrocode} +% \subsection{Public variables} +% +% A footnote mark will store its structure number (key) and the +% expanded \cs{@thefnmark} in this prop so +% that a following note can retrieve this info +% if needed. It is possible to use more than one footnote series (type) +% if needed (if different footnotes/note use the same +% numbering system). +% If this command is changed an accompanying property must be created +% \begin{NOTE}{UF} +% TODO: interface to create the property.\\ +% TODO: check and decide about the name of the tl +% \end{NOTE} +% \begin{macro}{\l_fnote_type_tl} +% \begin{macrocode} +\tl_new:N \l_fnote_type_tl +\tl_set:Nn \l_fnote_type_tl {default} +% \end{macrocode} +% \end{macro} +% It must be possible to suppress the hyperlinking, both locally +% and globally. hyperref's hyperfootnotes option should set the boolean. +% \begin{macro}{\l_fnote_link_bool} +% \begin{macrocode} +\bool_new:N \l_fnote_link_bool +\bool_set_true:N \l_fnote_link_bool +% \end{macrocode} +% \end{macro} +% A hyperlink should have an changeable link type. This can +% be e.g. used to change the color or the border. +% \begin{macro}{\l_fnote_link_type_tl} +% \begin{macrocode} +\tl_new:N \l_fnote_link_type_tl +\tl_set:Nn \l_fnote_link_type_tl {link} +% \end{macrocode} +% \end{macro} +% +% \subsection{Internal variables} +% +% \begin{macro}{\l_@@_linktarget_tl} +% This command stores the name of a linktarget/destination +% when needed +% \begin{macrocode} +\tl_new:N \l_@@_linktarget_tl +% \end{macrocode} +% \end{macro} +% \begin{macro}{\l_@@_currentlabel_tl} +% This command is used to pass a label name around. +% \begin{macrocode} +\tl_new:N \l_@@_currentlabel_tl +% \end{macrocode} +% \end{macro} - +% \begin{macro}{\l_@@_currentrefs_seq} +% This sequence stores the list of reference of a note +% \begin{macrocode} +\seq_new:N \l_@@_currentrefs_seq +% \end{macrocode} +% \end{macro} +% +% The connection between the mark(s) in the text and the note +% is either deduced automatically or done through an label. +% The default is automatic, but we must be able to suppress it. For this we use a boolean. +% \begin{macro}{\l_@@_autodetect_bool} +% \begin{macrocode} +\bool_new:N \l_@@_autodetect_bool +\bool_set_true:N \l_@@_autodetect_bool +% \end{macrocode} +% \end{macro} +% This is used to pass the structure number of the note around, e.g. +% to a label inside the note. +% \begin{macrocode} +\tl_new:N \l_@@_currentstruct_tl +\tl_set:Nn \l_@@_currentstruct_tl {1} +% \end{macrocode} +% +% +% \subsection{Variants} +% +% \begin{macrocode} +\cs_generate_variant:Nn \ref_label:nn { Vn } +\cs_generate_variant:Nn \ref_value:nn { Vn } +\cs_generate_variant:Nn \prop_gput:Nnn {cxn} +\cs_generate_variant:Nn \hook_gput_code:nnn{nne} +\cs_generate_variant:Nn \tag_struct_use:n {e} +% \end{macrocode} +% +% \subsection{Updating \cs{@thefnmark}} +% \begin{macro}{\fnote_step_fnmark:nn} +% This command updates \cs{@thefnmark}. The first argument +% is an optional integer expression, the second a counter name. +% If the optional argument is not given it steps the counter. +% \begin{macrocode} \cs_new_protected:Npn \fnote_step_fnmark:nn #1#2 { \tl_if_novalue:nTF {#1} { @@ -463,7 +829,12 @@ \group_end: } } - +% \end{macrocode} +% \end{macro} +% \begin{macro}{\fnote_set_fnmark:nn} +% This is similar to the previous command, but it doesn't step the +% counter but use the current value. +% \begin{macrocode} \cs_new_protected:Npn \fnote_set_fnmark:nn #1#2 { \tl_if_novalue:nTF {#1} { @@ -476,25 +847,40 @@ \group_end: } } - -%------------------------------------- - -% the debugging code is just temp -\bool_new:N \g_fnote_debug_bool -\bool_gset_true:N \g_fnote_debug_bool % for now we have debugging turned on by default - -%------------------------------------- - - - +% \end{macrocode} +% \end{macro} +% +% \subsection{Hooks} +% +% Hooks in the footnotemark command. +% \begin{macrocode} \NewMirroredHookPair{fnmark/before}{fnmark/after} \NewHook{fnmark} \NewHook{fnmark/begin} \NewHook{fnmark/end} - - -\cs_new:Npn \@@_debug_footnotemark: { - \bool_if:NT \g_fnote_debug_bool +% \end{macrocode} +% Hooks in the footnotetext command +% \begin{macrocode} +\NewMirroredHookPair{fntext/before}{fntext/after} +\NewHook{fntext} +\NewHook{fntext/para} +\NewHook{fntext/begin} +\NewHook{fntext/end} +% \end{macrocode} +% +% \subsection{Debugging code} +% the debugging code is just temporary +% +% For now we have debugging turned on by default +% \begin{macrocode} +\bool_new:N \g_fnote_debug_bool +\bool_gset_true:N \g_fnote_debug_bool +% \end{macrocode} +% We log the hooks in the footnote mark command, but only once +% \begin{macrocode} +\cs_new_protected:Npn \@@_debug_footnotemark: + { + \bool_if:NT \g_fnote_debug_bool { \LogHook{fnmark/before} \LogHook{fnmark} @@ -503,9 +889,38 @@ \LogHook{fnmark/after} \cs_gset_eq:NN \@@_debug_footnotemark: \prg_do_nothing: } -} - - + } +% \end{macrocode} +% Similar for the footnotetext +% \begin{macrocode} +\cs_new_protected:Npn \@@_debug_footnotetext: + { + \bool_if:NT \g_fnote_debug_bool + { + \cs_log:N\@footnotetext@cfgpoint + \cs_log:N\@footnotetext@cfgpointii + \cs_log:N\@footnotetext@cfgpointiii + \cs_log:N\@footnotetext@cfgpointiv + \cs_log:N\@makefntext@cfgpoint + \cs_log:N\@makefntext@cfgpointii + \LogHook{fntext/before} + \LogHook{fntext} + \LogHook{fntext/para} + \LogHook{fntext/begin} + \LogHook{fntext/end} + \LogHook{fntext/after} +% \end{macrocode} +% Show the info only once (if at all). +% \begin{macrocode} + \cs_gset_eq:NN \@@_debug_footnotetext: \prg_do_nothing: + } + } +% \end{macrocode} +% +% \subsection{The new \cs{@footnotemark} command} +% \begin{macro}{\fnote_footnotemark:} +% This is the main command which will replace \cs{@footnotemark}. +% \begin{macrocode} \cs_new_protected:Npn \fnote_footnotemark: { \@@_debug_footnotemark: %------- @@ -535,17 +950,20 @@ % \end{macrocode} % If a footnote mark is placed by its own then it should finish by % executing \hook{fnmark/end}, resetting the space factor, and -% finishing with \hook{fnmark/after}. However, inf a complete +% finishing with \hook{fnmark/after}. However, in a complete % footnote these actions have to happen only after we have handled -% the footnote text (e.g., by placing it into an \cs{insert}. In +% the footnote text (e.g., by placing it into an \cs{insert}). In % such a situation \cs{_@@_footmark_finish:} below does nothing % and the action is carried out later. % \begin{macrocode} \@@_footnotemark_finish: } - - -\cs_new:Npn \@@_finish: { +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_finish:,\@@_footnotemark_finish:} +% \begin{macrocode} +\cs_new_protected:Npn \@@_finish: { % hyperref.sty % memhfixc.sty --- could move fnmark/after % scrlttr2.cls --- could vanish if footmisc uses a hook @@ -561,57 +979,30 @@ %------- } - \cs_new_eq:NN \@@_footnotemark_finish: \@@_finish: - - - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@kernel@process@makefnmark} % Not a public config point but the kernel hook to add tagging +% \begin{macrocode} \def \@kernel@process@makefnmark { } - - -% alterations not covered: +% \end{macrocode} +% \end{macro} % -% ./arabtex/afoot.sty --- too different (and probably too old) - - -% Provide the name \LaTeXe{} is used to. - +% \begin{macro}{\@footnotemark} +% At last provide the name \LaTeXe{} is used to. +% \begin{macrocode} \cs_set_eq:NN \@footnotemark \fnote_footnotemark: - - - -%------------------------------------- - -\NewMirroredHookPair{fntext/before}{fntext/after} -\NewHook{fntext} -\NewHook{fntext/para} -\NewHook{fntext/begin} -\NewHook{fntext/end} - - -\cs_new:Npn \@@_debug_footnotetext: { - \bool_if:NT \g_fnote_debug_bool - { - \cs_log:N\@footnotetext@cfgpoint - \cs_log:N\@footnotetext@cfgpointii - \cs_log:N\@footnotetext@cfgpointiii - \cs_log:N\@footnotetext@cfgpointiv - \cs_log:N\@makefntext@cfgpoint - \cs_log:N\@makefntext@cfgpointii - \LogHook{fntext/before} - \LogHook{fntext} - \LogHook{fntext/para} - \LogHook{fntext/begin} - \LogHook{fntext/end} - \LogHook{fntext/after} % \end{macrocode} -% Show the info only once (if at all). +% \end{macro} +% +% +% \subsection{The new \cs{@footnotetext} command} +% +% +% \begin{macro}{\fnote_footnotetext:n} % \begin{macrocode} - \cs_gset_eq:NN \@@_debug_footnotetext: \prg_do_nothing: - } - } - \cs_new_protected:Npn \fnote_footnotetext:n #1 { \@@_debug_footnotetext: %------- @@ -690,55 +1081,75 @@ \UseHook{fntext/after} %------- } - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@footnotetext@cfgpoint} % default for config point (1 arg) +% \begin{macrocode} \cs_new_protected:Npn \@footnotetext@cfgpoint { \insert\footins } - +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@footnotetext@cfgpointii} % default for config point (1 arg) +% \begin{macrocode} \cs_new_protected:Npn \@footnotetext@cfgpointii { \@makefntext } - - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@footnotetext@cfgpointiii} % default for config point (0 args) +% \begin{macrocode} \cs_new_protected:Npn \@footnotetext@cfgpointiii { \rule\z@\footnotesep } - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@footnotetext@cfgpointiv} % default for config point (0 args) +% \begin{macrocode} \cs_new_protected:Npn \@footnotetext@cfgpointiv { \@finalstrut\strutbox } - - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@kernel@process@footnotetext} % kernel hook for tagging (2 args) +% \begin{macrocode} \cs_new_protected:Npn \@kernel@process@footnotetext {} - +% \end{macrocode} +% \end{macro} +% % Provide the name \LaTeXe{} is used to and do this unconditionally % (no patching of class code if any). This means that if a class provides it own % definition that gets lost and if necessary needs to be handled -% with firstaid (or updating of the class. - -\AddToHook{begindocument}{ - \cs_set_eq:NN \@footnotetext \fnote_footnotetext:n -} - -% alterations not covered: +% with firstaid (or updating of the class). +% \begin{macrocode} +\AddToHook{begindocument} + { + \cs_set_eq:NN \@footnotetext \fnote_footnotetext:n + } +% \end{macrocode} % -% ./revtex4-1/revtex4-1.cls ./revtex/ltxutil.sty ./revtex/revtex4-2.cls ... (need analysis) -% ./bigfoot/bigfoot.sty - - - -% \footnotemargin is the logic implemented by footmisc. Perhaps we +% \subsection{The new \cs{@makefntext} command} +% +% \cs{footnotemargin} is the logic implemented by footmisc. Perhaps we % don't want to do this like that in the kernel but for now I have % used this interface unchanged. - - +% \begin{macrocode} \newdimen\footnotemargin \footnotemargin\maxdimen % no value given -\AtBeginDocument{ - \ifdim \footnotemargin=\maxdimen - \setlength\footnotemargin{1.8em} - \fi -} - +\AtBeginDocument + { + \ifdim \footnotemargin=\maxdimen + \setlength\footnotemargin{1.8em} + \fi + } +% \end{macrocode} +% \begin{macro}{\fnote_makefntext:n} +% \begin{macrocode} \cs_new_protected:Npn \fnote_makefntext:n #1 { % \end{macrocode} % Some classes in their redefinition for \cs{@makefntext} have @@ -765,36 +1176,45 @@ \@makefntext@cfgpointii { #1 } } - - - - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@makefntext@cfgpoint} % default for config point (1 arg) +% \begin{macrocode} \cs_new_protected:Npn \@makefntext@cfgpoint { \noindent } - +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@makefntext@cfgpointii} % default for config point (1 arg) +% \begin{macrocode} \cs_new_protected:Npn \@makefntext@cfgpointii #1 { #1 } % \end{macrocode} +% \end{macro} % +% \subsubsection{Making documents use the new \cs{@makefntext}} % +% If the definition for \cs{@makefntext} is that of the standard +% classes then replace it with \cs{fnote_makefntext:n}, otherwise +% try to patch the definition. % -% If the definition for \cs{@makefntext} is that of the standard -% classes then replace it with \cs{fnote_makefntext:n}, otherwise -% try to patch the definition. +% Here is the definition the way it is in +% \texttt{classes.dtx}. Notice that (for saving space) there is no +% space after \texttt{em} to terminate the assignment. We need to +% mimic that, otherwise a test would return false even if the +% definition has not been modified. % -% Here is the the definition the way it is in -% \texttt{classes.dtx}. Notice that (for saving space) there is no -% space after \texttt{em} to terminate the assignment. We need to -% mimic that, otherwise a test would return false even if the -% definition has not been modified. % +% \begin{macro}{\old@std@class@makefntext} % \begin{macrocode} \newcommand\old@std@class@makefntext[1]{% \parindent 1em% \noindent \hb@xt@1.8em{\hss\@makefnmark}#1} - % \end{macrocode} +% \end{macro} +% % Here is the messy code for patching. Note that this is only there % to help classes along that aren't updated yet so it does some % minimal patching to hopefully add configuration points in the @@ -822,7 +1242,6 @@ % \cs{@makefnmark} without surrounding it in a box and if that % fails it gives up with an \cs{ERROR} (which needs to get a proper definition). % \begin{macrocode} - \tl_new:N \l_@@_patch_tl \cs_new_eq:NN \@@_tmp:w \ERROR @@ -853,6 +1272,7 @@ %\begin{verbatim} % AAA \@makefntext@processX { \hbox BBB } %\end{verbatim} +% % \begin{macrocode} \cs_new:Npn \@@_patch_hbox:w #1 \hbox #2 # { \exp_stop_f: #1 \@makefntext@processX { \hbox #2 } } @@ -869,25 +1289,27 @@ % different structure so this is a simple reshuffling. Would be % better if we can patch the right structure in directly, but I'm % not a patch person, so this is the simple way out for now: -% +% % \begin{macrocode} \cs_new:Npn \@makefntext@processX #1#2{\@makefntext@cfgpoint{#1{#2}}} % \end{macrocode} +% % At \verb=\begin{document}= check if the current definition is % that of the standard classes and if so replace it by % \cs{fnote_makefntext:n} otherwise try and patch the definition % using the approach above. % \begin{macrocode} -\AddToHook{begindocument}{ - \cs_if_eq:NNTF \@makefntext \old@std@class@makefntext - { - \cs_set_eq:NN \@makefntext \fnote_makefntext:n - } - { - \@@_patch: - } -} +\AddToHook{begindocument} + { + \cs_if_eq:NNTF \@makefntext \old@std@class@makefntext + { + \cs_set_eq:NN \@makefntext \fnote_makefntext:n + } + { + \@@_patch: + } + } % possibly add the following to check for multiple \hbox in @@ -898,63 +1320,112 @@ % % \end{macrocode} % +% \subsection{Document-level commands} % +% \begin{macro}{\footnotetext} +% \begin{macrocode} +\DeclareDocumentCommand\footnotetext {o+m} + { + \fnote_set_fnmark:nn {#1} \@mpfn + \@footnotetext {#2} + } +% \end{macrocode} +% \end{macro} % % -% \subsection{Document-level commands} -% -% \changes{v0.6b}{2022/07/22}{Make mandatory arguments of \cs{footnote} -% and \cs{footnotetext} long (gh863)} +% \begin{macro}{\footnote} % \begin{macrocode} +\DeclareDocumentCommand\footnote {o+m} + { + \fnote_step_fnmark:nn {#1} \@mpfn + \cs_set_eq:NN \@@_footnotemark_finish: \prg_do_nothing: + \@footnotemark + \cs_set_eq:NN \@@_footnotemark_finish: \@@_finish: + \@footnotetext {#2} + \@@_footnotemark_finish: + } +% \end{macrocode} +% \end{macro} +% -\DeclareDocumentCommand\footnotetext {o+m} { - \fnote_set_fnmark:nn {#1} \@mpfn - \@footnotetext {#2} -} - - -%------------------------------------- - - -\DeclareDocumentCommand\footnote {o+m} { - \fnote_step_fnmark:nn {#1} \@mpfn - \cs_set_eq:NN \@@_footnotemark_finish: \prg_do_nothing: - \@footnotemark - \cs_set_eq:NN \@@_footnotemark_finish: \@@_finish: - \@footnotetext {#2} - \@@_footnotemark_finish: -} - -%------------------------------------- - - -\DeclareDocumentCommand\footnotemark {o} { - \fnote_step_fnmark:nn {#1} { footnote } - \@footnotemark -} - - -%------------------------------------- - -\DeclareDocumentCommand\footref {m}{% - \begingroup - \unrestored@protected@xdef\@thefnmark{\ref{#1}}% - \endgroup - \@footnotemark -} - +% \begin{macro}{\footnotemark} +% \begin{macrocode} +\DeclareDocumentCommand\footnotemark {o} + { + \fnote_step_fnmark:nn {#1} { footnote } + \@footnotemark + } % \end{macrocode} -% +% \end{macro} + +% \begin{macro}{\footref} +% \cs{footref} used the starred \cs{ref} in \cs{@thefnmark} +% as the linking is handled by the tagging code inside +% the \cs{@footnotemark}. +% \cs{footref} should not try to link to its related related +% note automatically but should instead use the label. +% This is passed to \cs{@footnotemark} through +% \cs{l__fnote_currentlabel_tl}. +% % \begin{macrocode} -%<@@=> +\DeclareDocumentCommand\footref {m} + { + \begingroup + \unrestored@protected@xdef\@thefnmark{\ref*{#1}}% + \endgroup + \bool_set_false:N \l_@@_autodetect_bool + \tl_set:Nn \l_@@_currentlabel_tl {#1} + \@footnotemark + \bool_set_true:N \l_@@_autodetect_bool + } % \end{macrocode} +% \end{macro} % % +% \subsection{Firstaid for packages and classes} % +% \subsection{Kernel patches} +% Tagging of footnotes in minipages require a change in the minipage commands +% We define at first a local configuration command for minipage footnotes. % +% TODO remove the dependency to etoolbox, and need for the patch. +% \begin{macrocode} +\cs_new_protected:Npn \@mpfootnotetext@cfgpoint #1 + { + \global\setbox\@mpfootins\vbox{% + \unvbox\@mpfootins + #1 + } + } +% \end{macrocode} +% Then we patch \cs{@iiiminipage} +% \begin{macrocode} +\RequirePackage{etoolbox} +\ExplSyntaxOff +\patchcmd\@iiiminipage + {\let\@footnotetext\@mpfootnotetext} + {\let\@footnotetext@cfgpoint\@mpfootnotetext@cfgpoint} + {}{\ERROR} +\ExplSyntaxOn +% \end{macrocode} % +% \subsubsection{\pkg{memoir}} +% The \pkg{memoir} class redefines various internal commands to inject its +% hooks and addtional code. The following reinstates the kernel command and +% so probably breaks various options of \pkg{memoir}, but without the +% changes it errors anyway. The \pkg{footmisc} package should be used to change +% for example to para footnotes. % -% \subsection{Firstaid for packages and classes} +% \begin{macrocode} +\AddToHook{class/memoir/before} + { \let\new@std@class@makecol\@makecol } +\AddToHook{class/memoir/after} + { + \cs_set_eq:NN \@footnotemark \fnote_footnotemark: + \cs_set_eq:NN \@makefntext\old@std@class@makefntext + \cs_set_eq:NN \@makecol\new@std@class@makecol + } +% \end{macrocode} % % \subsubsection{\pkg{setspace}} % @@ -967,156 +1438,410 @@ % \end{macrocode} % % -% -% % \subsubsection{\pkg{hyperref}} % -% Prevent hyperref from redefining footnote stuff --- this is a -% temp solution. +% hyperref has a hook which allows to disable its footnote +% related patches. As we will handle links directly in the code +% this is used. +% % \begin{macrocode} -\AddToHook{package/hyperref/after}{ - \let\H@@footnotetext\fnote_footnotetext:n - \let\H@@footnotemark\fnote_footnotemark: - \let \@footnotetext \fnote_footnotetext:n - \let \@footnotemark \fnote_footnotemark: -} - - - +\def\hyper@nopatch@footnote{} % \end{macrocode} -% -% \subsection{Stuff that needs cleanup and documentation} -% +% We use the hyperref commands for now for links. To avoid +% to have to test for hyperref we provide dummies. +% TODO consider to use specials to get similar spacing. % \begin{macrocode} - - -%------------------------------------- - -% use of kerns to mark h-mode positions (unit sp) +\AtBeginDocument + { + \providecommand\hyper@linkstart{\@gobbletwo} + \providecommand\hyper@linkend{\@empty} + } +% \end{macrocode} % -% 1 = CJK -% 2 = CJK -% 3 = multiple footnotes (footmisc, koma, eledmac, tufte, memoir, -% parnotes, sidenotes) -% 3 = outer kern in letter spacing (letterspace) -% 3 = beginning of list (examdesign.cls) -% 4 = CJK pigin -% 5 = CJK ruby - -% 1-4 = polyglossia for korean - -%------------------------------------- - - - -%------------------------------------- -% Tagging -%------------------------------------- - -% hyperref support only when loaded (improve integration) - -\newcounter{absfootnote} -\AddToHook{fnmark/begin}{\stepcounter{absfootnote}} % too simple (fails with opt args) - - - -% this is rubbish and should be handled better: - -\cs_new_protected:Npn \tag_if_loaded:TF { \cs_if_exist:NTF \tag_struct_begin:n } - - - -\cs_new_protected:Npn \tag@FEMark #1 { - \tag_if_loaded:TF +% It must be possible to suppress the hyperlinking, both locally +% and globally. hyperref should set the boolean \cs{l_fnote_link_bool}. +% For now we test for the hyperref boolean (so it can be suppressed only globally). +% \begin{macrocode} +\AtBeginDocument + { + \@ifpackageloaded{hyperref} { - \tag_mc_end_push: - \exp_args:Nx - \tag_struct_begin:n{tag=Lbl,ref=fn.\the\c@absfootnote} - \tag_mc_begin:n{tag=Lbl} - \IfPackageLoadedTF{hyperref}{ \hyper@linkstart - {link}{fn.\the\c@absfootnote} }{} - #1 - \IfPackageLoadedTF{hyperref}{ \hyper@linkend }{} - \tag_mc_end: - \tag_struct_end: - \tag_mc_begin_pop:n{} + \legacy_if:nF{Hy@hyperfootnotes}{\bool_set_false:N \l_fnote_link_bool} } - { #1 } -} - -% to be done next round around: + { + \bool_set_false:N \l_fnote_link_bool + } + } +% \end{macrocode} % -% \the\c@absfootnote should be replaced directly by some command with default meaning -% \the\c@absfootnote so that the actual reference can be changed from the outside. +% \subsection{Tagging and hyperlink code} +% \subsubsection{Rolemap for structure tags} +% We use role-mapping to get more speaking names +% in the PDF and so ease debugging. These names are already +% provided by tagpdf directly. +% +% \subsubsection{Extending the label system} +% For \cs{footref} and (perhaps later for labeled footnotes) +% we must extend the label system. +% Beside the normal values we also need the structure number of the note. +% We use the \pkg{nameref} hook until latex provides a hook for its label. +% At first we define a suitable attribute, it uses as value the structure +% number of the note as stored in \cs{l__fnote_currentstruct_tl} +% \begin{macrocode} +\ref_attribute_gset:nnnn {fnote/struct}{1}{now}{\l_@@_currentstruct_tl} +% \end{macrocode} % -% there are several instances that are curently hardwired. - -\cs_set_eq:NN \@kernel@process@makefnmark \tag@FEMark - - - -% kernel hook for tagging (2 args) -\cs_set:Npn \@kernel@process@footnotetext #1#2 { - \tag_if_loaded:TF +% We add a hook to the \pkg{nameref} hook. By default it does nothing +% \begin{macro}{\@@_label_hook:} +% \begin{macrocode} +\cs_new_protected:Npn \@@_label_hook: {} +\AddToHook{begindocument/before} + { + \RequirePackage{nameref} + \g@addto@macro\label@hook + { + \@@_label_hook: + } + } +% \end{macrocode} +% \end{macro} +% Inside a footnotetext we change the hook to store the structure number too. +% nameref provides the name of label in \cs{label@name}. +% \begin{macrocode} +\AddToHook{fntext/begin} + { + \cs_set_protected:Npn \@@_label_hook: { - \tag_mc_end_push: - \tag_struct_begin:n { tag=FENote,label=fn.\the\c@absfootnote } - #1 {#2} - \tag_struct_end: - \tag_mc_begin_pop:n{} + \ref_label:Vn \label@name {fnote/struct} } - { #1 {#2} } -} - - + } +% \end{macrocode} +% +% \subsubsection{Storing and retrieving reference data} +% To establish the connection between a mark and a note +% the mark has to store its representation, and the +% note has to analyse the stored representations to get +% the structure numbers of its mark. This is done +% with the public function to allow similar systems (e.g. +% tabular notes, other footnote series) to make use of this. +% +% +% \begin{macro}{\fnote_new:nn} +% This sets up a new footnote type, the first argument +% is the name, the second is meant for options. Currently +% it does nothing at all. +% It is not necessary to setup every footnote like +% command as its own type! +% +% \begin{macrocode} +\cs_new_protected:Npn \fnote_new:nn #1 #2 % #1 name, #2 options + { + \prop_new:c { g_@@_currentmarks_ #1 _prop } + } -\cs_set:Npn \@makefntext@cfgpoint #1 { - \noindent - \cs_if_exist:NT \tag_struct_begin:n { \tag_mc_end_push: } - \tag@FELbl { #1 } -} +\fnote_new:nn {default}{} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\fnote_mark_gput:nn} +% This commands takes as argument the representation of the mark +% (e.g. \cs{@thefnmark} and the type (typically default should work) +% \begin{macrocode} +\cs_new_protected:Npn \fnote_mark_gput:nn #1 #2 % #1 the representation of the mark, #2 type + { + \prop_gput:cxn { g_@@_currentmarks_ #2 _prop } + { \tag_get:n{struct_num} } + { #1 } + } -\cs_set:Npn \@makefntext@cfgpointii #1 { - \tag@FENote { #1 } - \cs_if_exist:NT \tag_struct_begin:n { \tag_mc_begin_pop:n{} } -} +\cs_generate_variant:Nn \fnote_mark_gput:nn {no,oo} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\fnote_mark_gpop:nnN} +% This commands takes as argument the representation of the mark +% (e.g. the content of\cs{@thefnmark}), the series (typically default should work) +% and a sequence into which every structure number in the property +% is stored that has the same value as the mark +% \begin{macrocode} +\cs_new_protected:Npn \fnote_mark_gpop:nnN #1 #2 #3 + { + \seq_clear:N #3 + \prop_set_eq:Nc \l_@@_tmpa_prop { g_@@_currentmarks_ #2 _prop } + \prop_map_inline:Nn \l_@@_tmpa_prop + { + \tl_if_eq:nnT {#1} { ##2 } + { +% \end{macrocode} +% store the key (the structure number) in the seq +% \begin{macrocode} + \seq_put_right:Nn #3 { ##1 } +% \end{macrocode} +% remove entry as used from the global prop +% \begin{macrocode} + \prop_gremove:cn { g_@@_currentmarks_ #2 _prop } {##1} + } + } + } +\cs_generate_variant:Nn\fnote_mark_gpop:nnN {ooN} +% \end{macrocode} +% \end{macro} +% \subsubsection{Enabling tagging and links for the mark command} +% To handle the mark in the text, we define a special command +% which will surround \cs{@makefntext}. +% At this time \cs{@thefnmark} is already set. +% \begin{macrocode} +\cs_new_protected:Npn \tag@FEMark #1 %#1 content + { +% \end{macrocode} +% end an open mc and start the structure. +% \begin{macrocode} + \tag_mc_end_push: + \tag_struct_begin:n { tag=footnotemark } +% \end{macrocode} +% The associated note is either auto detected +% or given by the user. +% \begin{macrocode} + \bool_if:NTF \l_@@_autodetect_bool + { +% \end{macrocode} +% For the auto detecting we store the structure number +% and \cs{@thefnmark} inside a prop and set +% the target name of the link to the current structure number. +% TODO: this should be usable for other footnote types +% which means the name of the prop shouldn't be fix. +% \begin{macrocode} + \fnote_mark_gput:oo {\@thefnmark}{\l_fnote_type_tl} + \tl_set:Nx \l_@@_linktarget_tl {footnote*.\tag_get:n{struct_num}} + } +% \end{macrocode} +% If there is no autodetecting we need some id, +% currently it is called \cs{l__fnote_currentlabel_tl}. +% the Ref is set by looking at the label value. +% We must also add the current structure number to the \ref of the FEnote. +% Both must be delayed as we don't know if the objects of the FEnote and the mark +% have already been created. +% \begin{macrocode} + { + \hook_gput_code:nne {tagpdf/finish/before} {tagpdf/footnote} + { + \exp_not:N\fnote_gput_refs:ee + { \tag_get:n{struct_num} } + { \ref_value:Vn\l_@@_currentlabel_tl {fnote/struct} } + } +% \end{macrocode} +% in this case we set the name of the linktarget in the note +% to the structure number of the text mark. +% \begin{macrocode} + \tl_set:Nx \l_@@_linktarget_tl {footnote*.\ref_value:Vn\l_@@_currentlabel_tl {fnote/struct}} + } +% \end{macrocode} +% And now the actual content +% \begin{macrocode} + \tag_mc_begin:n{tag=Lbl} + % + \bool_if:NTF \l_fnote_link_bool + { + \exp_args:No + \hyper@linkstart + { \l_fnote_link_type_tl } + { \l_@@_linktarget_tl } + #1 + \hyper@linkend + } + { #1 } + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% At last set the kernel command to this one +% \begin{macrocode} +\cs_set_eq:NN \@kernel@process@makefnmark \tag@FEMark +% \end{macrocode} +% \subsubsection{The footnote text} -\cs_new_protected:Npn \tag@FELbl #1 { - \tag_if_loaded:TF - { - % target should perhaps be raised ... - \IfPackageLoadedTF{hyperref}{ \hypertarget{fn.\the\c@absfootnote}{} }{} - %\tag_struct_begin:n { tag=FENote,label=fn.\the\c@absfootnote } %alternativ location for structure - \tag_struct_begin:n { tag=Lbl } - \tag_mc_begin:n { tag=Lbl } - #1 - \tag_mc_end: - \tag_struct_end: - } - { #1 } -} +% We need a public command to append values to the Ref keys +% \begin{macro}{\@@_gput_ref:nn,\fnote_gput_refs:nn,\fnote_gput_refs:ee} +% \begin{macrocode} +\cs_new_protected:Npn \@@_gput_ref:nn #1 #2 %#1 the structure number receiving the ref #2 + { + \tag_if_active:T + { + \tag_struct_gput:nne {#1}{ref}{\tag_struct_object_ref:e { #2 }} + } + } +\cs_new_protected:Npn \fnote_gput_refs:nn #1 #2 % pair of numbers + { + \@@_gput_ref:nn {#1}{#2} + \@@_gput_ref:nn {#2}{#1} + } +\cs_generate_variant:Nn \fnote_gput_refs:nn {ee} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\tl_new:N \l_@@_dflt_struct_tl +\tl_set:Nn \l_@@_dflt_struct_tl {1} +% \end{macrocode} +% kernel hook for tagging (2 args) +% this sets the structure around the whole text +% +% \begin{macrocode} +\cs_new_protected:Npn \tag@FENote #1#2 % #1 config point, \insert\footins #2 content + { + \tag_mc_end_push: +% \end{macrocode} +% test if a footnote is allowed, if not move up to the document structure. +% \begin{macrocode} + \tag_check_child:nnTF {FENote}{pdf2} + { + \tag_struct_begin:n { tag=footnote } + } + { + \tag_struct_begin:n { tag=footnote,parent=\l_@@_dflt_struct_tl } + } +% \end{macrocode} +% Store the current structure number for labels. +% \begin{macrocode} + \tl_set:Nx \l_@@_currentstruct_tl { \tag_get:n{struct_num} } +% \end{macrocode} +% We want to move the label structure here. So we provide a container +% It number is |\l__fnote_currentstruct_tl| plus 1. +% \begin{macrocode} + \tag_struct_begin:n { tag=footnotelabel }\tag_struct_end: +% \end{macrocode} +% after we have opened the structure we can use the structure number to +% try to detect the connected marks. As with the marks we assume that sometimes +% no auto detection is done. +% \begin{macrocode} + \bool_if:NTF \l_@@_autodetect_bool + { +% \end{macrocode} +% find open marks with identical \cs{@thefnmark} +% \begin{macrocode} + \fnote_mark_gpop:ooN { \@thefnmark }{ \l_fnote_type_tl } \l_@@_currentrefs_seq +% \end{macrocode} +% Then we store the object numbers of the marks in the /Ref of the FENote structure: +% and the number of the FEnote into the marks structure: +% \begin{macrocode} + \seq_map_inline:Nn \l_@@_currentrefs_seq + { + \fnote_gput_refs:ee {##1}{ \l_@@_currentstruct_tl } + } + } +% \end{macrocode} +% If no auto detection is done +% \begin{NOTE}{UF} +% TODO: decide what to do here: some label in the optional argument? +% or refer to \cs{footref} +% \end{NOTE} +% \begin{macrocode} + {%no auto -\cs_new_protected:Npn \tag@FENote #1 { - \tag_if_loaded:TF - { - \tag_mc_begin:n{tag=FENote} - #1 + } +% \end{macrocode} +% This finish the setup of the tagging structure. +% Now we process the text. The destinations for the links are set with the label +% so that we can be sure that we are in hmode. +% \begin{macrocode} + #1 {#2} + \tag_struct_end: + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% At last set the kernel command to this one +% \begin{macrocode} +\cs_set_eq:NN \@kernel@process@footnotetext \tag@FENote +% \end{macrocode} +% +% \cs{@makefntext@cfgpoint} is the configuration point responsible for +% typesetting the mark in the note. We use it to surround +% the mark with the needed tagging commands. +% +% TODO check if this should/can be kernel configuration points +% or if an additional kernel configuration points are needed. +% If yes, what about the paragraph start and the paratagging?? +% +% \begin{macrocode} +\cs_set_protected:Npn \@makefntext@cfgpoint #1 %#1 code that typesets the mark. + { + \noindent + \tag_mc_end_push: + \tag@FENoteLbl { #1 } + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% \cs{tag@FENoteLbl} creates the label in the note on the bottom. +% It also adds link targets for the hyperlinking. +% +% \begin{macro}{\tag@FENoteLbl} +% \begin{macrocode} +\cs_new_protected:Npn \tag@FENoteLbl #1 + { +% \end{macrocode} +% We create a link target for every related mark. The name is footnote* + structure number +% of the mark. We also add a link target for the current structure (for footref) +% \begin{macrocode} + %\seq_show:N\l_@@_currentrefs_seq + \seq_map_inline:Nn\l_@@_currentrefs_seq {\MakeLinkTarget*{footnote*.##1}} + \MakeLinkTarget*{footnote*.\l_@@_currentstruct_tl} +% \end{macrocode} +% now we add the tagging commands. We move the structure of the label to +% to the container at the begin of the note. +% \begin{NOTE}{UF} +% check if the NonStruct is really needed. Perhaps we can simply move the mc. +% \end{NOTE} +% \begin{macrocode} + \tag_struct_begin:n { tag=NonStruct,parent=\l_@@_currentstruct_tl +1 } + \tag_mc_begin:n { tag=Lbl } + #1 \tag_mc_end: - %\tag_struct_end: %alternative location for structure end but ends inside a P - } - { #1 } -} - + \tag_struct_end: + } +% \end{macrocode} +% \end{macro} +% +% +% \cs{@makefntext@cfgpointii} is the +% configuration point around the actual note text. +% +% TODO check if this should/can be kernel configuration points +% \begin{macrocode} +\cs_set_protected:Npn \@makefntext@cfgpointii #1 + { + \tag_mc_end_push: + \tag@FENotetext { #1 } + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% \begin{macro}{\tag@FENotetext} +% +% This command currently only adds an MC chunk, +% +% TODO Should it set a mc or could it rely on the content? +% \begin{macrocode} +\cs_new_protected:Npn \tag@FENotetext #1 + { + \tag_mc_begin:n{} + #1 + \tag_mc_end: + } +% \end{macrocode} +% \end{macro} %------------------------------------- - +% \begin{macrocode} \ExplSyntaxOff %</kernel> % \end{macrocode} -% +% \begin{macrocode} +%<@@=> +% \end{macrocode} % % \section{Reimplementing the \pkg{footmisc} package} % @@ -1571,7 +2296,10 @@ \ifFN@multiplefootnote \providecommand*{\multiplefootnotemarker}{3sp} - \providecommand*{\multfootsep}{,} +% we tag the separator as artifact + \ExplSyntaxOn + \providecommand*{\multfootsep}{\tag_mc_end_push:\tag_mc_begin:n{artifact},\tag_mc_end:\tag_mc_begin_pop:n{}} + \ExplSyntaxOff \AddToHook{fnmark} {\FN@mf@check} \AddToHook{fnmark/end} {\FN@mf@prepare} % diff --git a/macros/latex/required/latex-lab/latex-lab-footnotes.pdf b/macros/latex/required/latex-lab/latex-lab-footnotes.pdf Binary files differindex 32ea573774..b383bff74b 100644 --- a/macros/latex/required/latex-lab/latex-lab-footnotes.pdf +++ b/macros/latex/required/latex-lab/latex-lab-footnotes.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-graphic.dtx b/macros/latex/required/latex-lab/latex-lab-graphic.dtx new file mode 100644 index 0000000000..f9457e0524 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-graphic.dtx @@ -0,0 +1,1073 @@ +% \iffalse meta-comment +% +%% File: latex-lab-graphic.dtx (C) Copyright 2022-2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-graphic.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \textsf{latex-lab-graphic} package\\ +% Tagging of included graphics } +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{v0.8 2023-04-07} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% \begin{documentation} +% \begin{abstract} +% The following code implements a first draft for the tagging of graphics +% included with \cs{includegraphics}. +% \end{abstract} +% +% +% \section{Introduction} +% +% The code here handle the tagging of pictures included with \cs{includegraphics} +% and the picture environment. Pictures drawn with \texttt{l3draw} or \texttt{tikz} +% or similar packages aren't handled yet. +% +% Tagging of graphics included with \cs{includegraphics} is at a first glance trivial: +% They are either only decorations, in which case they should be in a \texttt{artifact} +% MC-chunk or (in pdf 2.0) tagged as an \texttt{Artifact} structure, +% or they are meaningful and then they should be tagged as a \texttt{Figure}. +% Such a graphic is a simple box and no other content can interfere so adding the +% structure commands shouldn't pose much problems. +% +% But things are actually not so easy. +% +% At first there are two ways to add a graphic +% to a structure: similar to text as a marked content item (by surrounding +% it with \cs{tagmcbegin} and \cs{tagmcend}) or by referencing the XObject +% with an OBJR object (similar to a link annotation). Which method is more sensible +% (and if it actually matters) is unknown but should be tested. +% Currently the first method is used as the second require changes in the backend files. +% +% +% At second---and this is actually a \emph{much} larger problem---a +% \texttt{Figure} structure should have an attribute with an \texttt{BBox} entry. +% The value of a \texttt{BBox} is an array of four numbers that gives the +% coordinates of the left, bottom, right, and top edges +% of the structure element’s bounding box. That is the rectangle that completely encloses +% its \emph{visible} content so not necessarly the TeX bounding box: +% if \texttt{viewport} or \texttt{trim} is used and the +% graphic is not clipped, the visible content can be larger. +% +% Getting the \texttt{BBox} is quite straightforward for a graphic that is +% used once as is. But graphics can be trimmed, scaled, reflected, rotated and reused +% in various ways. This transformations typically involve a mix of \TeX{} commands +% like shifting a box or changing the bounding box and backend commands like +% inserting a pdfliteral with a transformation matrix and +% and not in all cases getting the \texttt{BBox} is possible +% without rewriting large parts of the graphics/x packages. Problematic are +% \begin{itemize} +% \item manipulations through external box commands +% (\cs{rotatebox}, \cs{reflectbox}, \cs{scalebox}). The current implementation +% in the graphics/x packages do not pass the transformation matrix in way +% that allows to track the changes for the \texttt{BBox} +% of an included graphic: sometimes +% the values are set to late (after the box is already stored), and often the +% values are not grouped and can leak out from earlier uses of the commands. +% +% \item some combination of keys in the optional argument of \cs{includegraphics}. +% Examples are \texttt{origin} and multiple calls to \texttt{scale} +% and \texttt{angle}) as they internally call the box commands. +% Examples of failing combinations can be found in the test file +% \texttt{graphic-faults}. +% +% \item graphics that are stored in a box and reused: to get the \texttt{BBox} +% one has to set a label that stores the position with \cs{pdfsavepos}, +% and if a box is reused one gets multiply defined labels. +% One possible solution here is to make +% use of the new delayed \cs{pdfliteral}. It allows to change the label names +% in the shipout, but this requires careful tracking the box usages +% and so various kernel changes. +% \end{itemize} +% +% +% +% \section{Restrictions and Todos} +% Correct tagging is currently +% implemented only for simple \cs{includegraphics} and the keys +% \texttt{viewport}, \texttt{trim}, +% \texttt{scale} and \texttt{angle} (used at most once). +% +% Not supported +% \begin{itemize} +% \item graphics inside \cs{rotatebox}, \cs{reflectbox}, \cs{scalebox}. +% +% TODO: A new implementation with \texttt{l3graphics} and \texttt{l3box} is +% probably needed here. +% +% \item multiple uses of the \texttt{scale} and \texttt{angle} keys +% +% \item multiple use of graphics stored in boxes. For such graphics automated tagging +% should be probably deactivated when storing the content +% and tagging should be added around the \cs{usebox}. (How to +% proceed when content is saved in boxes needs generally more testing). +% \end{itemize} +% +% +% \section{Additional keys} +% The code defines additional keys for \cs{includegraphics}: +% +% \begin{description} +% \item[\texttt{tag}] with the values +% \begin{description} +% \item[\texttt{artifact}] When used the graphic will be tagged as artifact. This doesn't +% require a \texttt{BBox} and so works also in some of the not yet supported cases described +% above. +% \item[\texttt{false}] When used tagging will be stopped completly. It is then the +% responsability of the surrounding code to add appropriate tagging commands. +% \item[\meta{name}] Other values will be used as tag names in the structure. If the tag is not +% known as a structure tag you will get an warning from tagpdf. The default name is currently +% \texttt{Figure} +% \end{description} +% \item[\texttt{actualtext}] This allows to add an /ActualText to the structure. +% This is useful for small graphics that represent single chars or a short word like a +% logo. If \texttt{actualtext} is used, the graphics is not enclosed in \texttt{Figure} +% structure but in a \texttt{Span} structure and no \texttt{/BBox} attribute is added. +% This in accordance with (the draft of) PDF/UA-2 but violates perhaps PDF/UA-1. +% \item[\texttt{correct-BBox}] If the calculated \texttt{/BBox} values are wrong +% they can be correct with this key. It expects four dimensions that are added to the +% \texttt{/BBox} values. +% \item[\texttt{debug}] The value \texttt{BBox} will show the calculated \texttt{/BBox} +% as a half transparent red rectangle. +% \end{description} +% +% The code also redefines the \texttt{alt} key to actually add its values +% as an alternative text. If no \texttt{alt} value is given, a warning is issued +% and the file name of the graphic is used. +% +% \begin{macrocode} +%<@@=tag> +%<*package> +% \end{macrocode} +% \end{documentation} +% \begin{implementation} +% \section{Implementation} +% \begin{macrocode} +\ProvidesExplPackage {latex-lab-testphase-graphic} {2023-04-07} {0.8} + {Code related to the tagging of graphics} +% \end{macrocode} +% We load l3opacity for the debug code +% \begin{macrocode} +\RequirePackage{l3opacity} +% \end{macrocode} +% +%\subsection{Saving the position} +% We need a replacement for zref-savepos. This uses l3ref which loaded +% by the pdfmanagement/tagpdf. +% +% TODO: this is perhaps needed in other places too and should be moved to +% l3ref!! +% \begin{macrocode} +\ref_attribute_gset:nnnn{xpos}{0}{shipout}{\int_use:N\tex_lastxpos:D} +\ref_attribute_gset:nnnn{ypos}{0}{shipout}{\int_use:N\tex_lastypos:D} +% \end{macrocode} + +% \begin{macro}{\@@_graphic_savepos:n} +% this is the command which stores the position. It uses +% two savepos in case bidi needs it (see zref-savepos). +% \begin{macrocode} +\cs_new_protected:Npn\@@_graphic_savepos:n #1 + { + \tex_savepos:D + \ref_label:nn{#1}{xpos,ypos,abspage} + \tex_savepos:D + } +\cs_generate_variant:Nn \@@_graphic_savepos:n {e} +% \end{macrocode} +% \end{macro} +% +% \subsection{Variables} +% \begin{variable}{\l_@@_graphic_debug_bool} +% A boolean for debug code +% \begin{macrocode} +\bool_new:N \l_@@_graphic_debug_bool +\keys_define:nn { document / metadata } + { + debug / BBox .code:n = { \bool_set_true:N \l_@@_graphic_debug_bool } + } +% \end{macrocode} +% \end{variable} +% \begin{variable}{\g_@@_graphic_int} +% This is used to get unique labels in the savepos code. +% \begin{macrocode} +\int_new:N\g_@@_graphic_int +% \end{macrocode} +% \end{variable} + +% \begin{variable} +% { +% \g_@@_graphic_lx_tl, +% \g_@@_graphic_ly_tl, +% \g_@@_graphic_ux_tl, +% \g_@@_graphic_uy_tl, +% \l_@@_graphic_bboxcorr_seq +% \l_@@_graphic_bboxcorr_bool +% } +% This commands will hold the calculated BBox values. Local variables +% would probably work too, but global variables can be easier retrieved +% in tests and debugging code ... +% \begin{macrocode} +\tl_new:N \g_@@_graphic_lx_tl +\tl_new:N \g_@@_graphic_ly_tl +\tl_new:N \g_@@_graphic_ux_tl +\tl_new:N \g_@@_graphic_uy_tl +\seq_new:N\l_@@_graphic_bboxcorr_seq +\bool_new:N\l_@@_graphic_bboxcorr_bool +% \end{macrocode} +% \end{variable} +% \begin{variable}{\l_@@_graphic_currentlabel_tl} +% This holds the label name of the savepos. +% \begin{macrocode} +\tl_new:N \l_@@_graphic_currentlabel_tl +% \end{macrocode} +% \end{variable} + +% \begin{variable} +% { +% \l_@@_graphic_alt_tl, +% \l_@@_graphic_alt_dft_tl, +% \l_@@_graphic_actual_tl, +% \l_@@_graphic_struct_tl, +% \l_@@_graphic_artifact_bool, +% \l_@@_graphic_BBox_bool +% } +% Variables for the alt text, the actualtext and the structure tag. +% \begin{macrocode} +\tl_new:N \l_@@_graphic_alt_tl +\tl_new:N \l_@@_graphic_alt_dflt_tl +\tl_set:Nn \l_@@_graphic_alt_dflt_tl {\Gin@base\Gin@ext} +\tl_new:N \l_@@_graphic_actual_tl +\tl_new:N \l_@@_graphic_struct_tl +\tl_set:Nn\l_@@_graphic_struct_tl {Figure} +\bool_new:N\l_@@_graphic_artifact_bool +\bool_new:N\l_@@_graphic_BBox_bool +\bool_set_true:N\l_@@_graphic_BBox_bool +% \end{macrocode} +% \end{variable} + +% \begin{variable} +% { +% \l_@@_graphic_sin_fp +% ,\l_@@_graphic_cos_fp +% ,\l_@@_graphic_scale_fp +% ,\l_@@_graphic_lxly_fp +% ,\l_@@_graphic_lxuy_fp +% ,\l_@@_graphic_uxly_fp +% ,\l_@@_graphic_uxuy_fp +% ,\l_@@_graphic_ux_fp +% ,\l_@@_graphic_ly_fp +% ,\l_@@_graphic_lx_fp +% ,\l_@@_graphic_uy_fp +% ,\l_@@_graphic_trim_ux_fp +% ,\l_@@_graphic_trim_ly_fp +% ,\l_@@_graphic_trim_lx_fp +% ,\l_@@_graphic_trim_uy_fp +% } +% A bunch of fp-variables (we don't use tl-vars, +% to avoid to have to take care about minus signs everwhere) +% \begin{macrocode} +\fp_new:N\l_@@_graphic_sin_fp +\fp_new:N\l_@@_graphic_cos_fp +\fp_new:N\l_@@_graphic_lxly_fp +\fp_new:N\l_@@_graphic_lxuy_fp +\fp_new:N\l_@@_graphic_uxly_fp +\fp_new:N\l_@@_graphic_uxuy_fp +\fp_new:N\l_@@_graphic_ux_fp +\fp_new:N\l_@@_graphic_ly_fp +\fp_new:N\l_@@_graphic_lx_fp +\fp_new:N\l_@@_graphic_uy_fp +% \end{macrocode} +% this holds the scale value. Currently this only the one from +% \cs{Gin@scalex} +% \begin{macrocode} +\fp_new:N\l_@@_graphic_scale_fp +% \end{macrocode} +% the follow variables hold the four trim values (or the equivalent calculated +% values if viewport is used. +% \begin{macrocode} +\fp_new:N\l_@@_graphic_trim_ux_fp +\fp_new:N\l_@@_graphic_trim_ly_fp +\fp_new:N\l_@@_graphic_trim_lx_fp +\fp_new:N\l_@@_graphic_trim_uy_fp +% \end{macrocode} +% \end{variable} +% +%\subsection{Tagging commands} +% +% \begin{macro}{\Gin@tag@struct@begin} +% The command to start the tagging. +% \begin{macrocode} +\msg_new:nnn {tag}{alt-text-missing} + { + Alternative~text~for~graphic~is~missing.\\ + Using~'#1'~instead + } +\cs_new_protected:Npn\Gin@tag@struct@begin + { + \tag_if_active:T + { + \tag_mc_end_push: +% \end{macrocode} +% we don't open a structure for artifacts to make it easier to use +% graphics in saveboxes. +% \begin{macrocode} + \bool_if:NTF\l_@@_graphic_artifact_bool + { + \tag_mc_begin:n{artifact} + } + { + \tl_if_empty:NTF\l_@@_graphic_actual_tl + { + \tl_if_empty:NT\l_@@_graphic_alt_tl + { + \msg_warning:nnx{tag}{alt-text-missing}{\l_@@_graphic_alt_dflt_tl} + \tl_set:Nx\l_@@_graphic_alt_tl {\l_@@_graphic_alt_dflt_tl} + } + \tag_struct_begin:n + { + tag=\l_@@_graphic_struct_tl, + alt=\l_@@_graphic_alt_tl, + } + } + { + \tag_struct_begin:n + { + tag=Span, + actualtext=\l_@@_graphic_actual_tl, + } + \bool_set_false:N\l_@@_graphic_BBox_bool + } + \tag_mc_begin:n{} + } + } + } +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\Gin@tag@struct@end} +% \begin{macrocode} +\cs_new_protected:Npn\Gin@tag@struct@end + { + \tag_if_active:T + { + \tag_mc_end: + \bool_if:NF\l_@@_graphic_artifact_bool + { + \tag_struct_end: + } + \tag_mc_begin_pop:n{} + } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Patching graphics commands} +% All changes are currently done in \cs{Gin@setfile}. +% \begin{macrocode} +\AddToHook{package/graphics/after} + { + \def\Gin@setfile#1#2#3{% + \ifx\\#2\\\Gread@false\fi + \ifGin@bbox\else + \ifGread@ + \csname Gread@% + \expandafter\ifx\csname Gread@#1\endcsname\relax + eps% + \else + #1% + \fi + \endcsname{\Gin@base#2}% + \else + \Gin@nosize{#3}% + \fi + \fi + \Gin@viewport@code + \Gin@nat@height\Gin@ury bp% + \advance\Gin@nat@height-\Gin@lly bp% + \Gin@nat@width\Gin@urx bp% + \advance\Gin@nat@width-\Gin@llx bp% + \Gin@req@sizes + \expandafter\ifx\csname Ginclude@#1\endcsname\relax + \Gin@drafttrue + \expandafter\ifx\csname Gread@#1\endcsname\relax + \@latex@error{Can not include graphics of type: #1}\@ehc + \global\expandafter\let\csname Gread@#1\endcsname\@empty + \fi + \fi + \leavevmode +% \end{macrocode} +% Here the tagging begins. We want to catch also the draft box, +% and for luatex tagging must be started before the \cs{setbox}. +% \begin{macrocode} + \Gin@tag@struct@begin %NEW + \ifGin@draft + \hb@xt@\Gin@req@width{% + \vrule\hss + \vbox to \Gin@req@height{% + \hrule \@width \Gin@req@width + \vss + \edef\@tempa{#3}% + \rlap{ \ttfamily\expandafter\strip@prefix\meaning\@tempa}% + \vss + \hrule}% + \hss\vrule}% + \else + \@addtofilelist{#3}% + \ProvidesFile{#3}[Graphic file (type #1)]% + \setbox\z@\hbox{\csname Ginclude@#1\endcsname{#3}}% + \dp\z@\z@ + \ht\z@\Gin@req@height + \wd\z@\Gin@req@width +% \end{macrocode} +% This the main command to calculate the BBox values. +% \begin{macrocode} + \Gin@tag@bbox@attribute %new + \box\z@ +% \end{macrocode} +% and here the tagging stops. +% \begin{macrocode} + \Gin@tag@struct@end %new + \fi} + } +% \end{macrocode} +% +% \subsection{Additional keys for the graphics command} +% TODO: this is a bit temporary and will perhaps need more refinement. +% we also ensure that graphicx is loaded for the keyval support. +% \begin{macrocode} +\AddToHook{package/graphicx/after}[latex-lab] + { + \define@key{Gin}{alt} {\tl_set:Nx\l_@@_graphic_alt_tl{\text_purify:n{#1}}} + \define@key{Gin}{artifact}[] + { + \bool_set_true:N \l_@@_graphic_artifact_bool + \bool_set_false:N \l_@@_graphic_BBox_bool + } + \define@key{Gin}{actualtext} + { + \tl_set:Nx\l_@@_graphic_actual_tl{\text_purify:n{#1}} + \bool_set_false:N \l_@@_graphic_BBox_bool + } + \define@key{Gin}{correct-BBox} + { + \bool_set_true:N \l_@@_graphic_bboxcorr_bool + \seq_set_split:Nnn\l_@@_graphic_bboxcorr_seq{~}{#1~0pt~0pt~0pt~0pt} + } + \define@key{Gin}{tag} + { + \str_case:nnF {#1} + { + {artifact} + { + \bool_set_true:N \l_@@_graphic_artifact_bool + \bool_set_false:N \l_@@_graphic_BBox_bool + } + {false}{\tag_stop:} + } + {\tl_set:Nn\l_@@_graphic_struct_tl{#1}} + } + } +\AddToHook{package/graphics/after}[latex-lab] + {\RequirePackage{graphicx}} +% \end{macrocode} +% For picture and other environments we need a similar set of keys. +% TODO: redefine \cs{includegraphics} to make use of these here?? +% \begin{macrocode} +\keys_define:nn{tag/picture} + { + ,alt .code:n = + {\tl_set:Nx\l_@@_graphic_alt_tl{\text_purify:n{#1}}} + ,artifact .code:n = + { + \bool_set_true:N \l_@@_graphic_artifact_bool + \bool_set_false:N \l_@@_graphic_BBox_bool + } + ,actualtext .code:n = + { + \tl_set:Nx\l_@@_graphic_actual_tl{\text_purify:n{#1}} + \bool_set_false:N \l_@@_graphic_BBox_bool + } + ,correct-BBox .code:n = + { + \bool_set_true:N \l_@@_graphic_bboxcorr_bool + \seq_set_split:Nnn\l_@@_graphic_bboxcorr_seq{~}{#1~0pt~0pt~0pt~0pt} + } + ,tag .code:n = + { + \str_case:nnF {#1} + { + {artifact} + { + \bool_set_true:N \l_@@_graphic_artifact_bool + \bool_set_false:N \l_@@_graphic_BBox_bool + } + {false}{\tag_stop:} + } + {\tl_set:Nn\l_@@_graphic_struct_tl{#1}} + } + } +% \end{macrocode} +% +% \subsection{Calculating the BBox} +% +% \begin{macro}{\@@_graphic_get_trim:} +% Graphics can be trimmed with the trim and the viewport key. +% If the graphic is not clipped the values must be taken into +% account when rotating. +% If viewport is used we have to calculate the trim. +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_graphic_get_trim: + { + \legacy_if:nTF {Gin@clip} +% \end{macrocode} +% Setting to 0 is not strictly needed but looks cleaner. +% \begin{macrocode} + { + \fp_zero:N\l_@@_graphic_trim_lx_fp + \fp_zero:N\l_@@_graphic_trim_ly_fp + \fp_zero:N\l_@@_graphic_trim_ux_fp + \fp_zero:N\l_@@_graphic_trim_uy_fp + } + { + \fp_set:Nn \l_@@_graphic_trim_lx_fp {\l_@@_graphic_scale_fp*\Gin@vllx} + \fp_set:Nn \l_@@_graphic_trim_ly_fp {\l_@@_graphic_scale_fp*\Gin@vlly} + \fp_set:Nn \l_@@_graphic_trim_ux_fp {\l_@@_graphic_scale_fp*\Gin@vurx} + \fp_set:Nn \l_@@_graphic_trim_uy_fp {\l_@@_graphic_scale_fp*\Gin@vury} + \cs_if_exist:NT \Gin@ollx + { + \fp_set:Nn \l_@@_graphic_trim_ux_fp {\l_@@_graphic_scale_fp* (\Gin@ourx-(\Gin@urx)) } + \fp_set:Nn \l_@@_graphic_trim_uy_fp {\l_@@_graphic_scale_fp* (\Gin@oury-(\Gin@ury)) } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_graphic_get_scale:} +% \begin{macrocode} +\cs_new_protected:Npn \@@_graphic_get_scale: + { + \fp_set:Nn \l_@@_graphic_scale_fp { \Gin@scalex } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_graphic_applyangle:nnnn} +% This takes the current BBox and rotates it according to the use angle. +% This is the most laborious code, as we have to take also the trim values into +% account. We have to compare the values after the rotation to find the right corners +% for the BBox. Not sure, if this is the most effective code, +% the l3draw package has similar code to calculate a rotation, +% this can perhaps be reused ... +% \begin{macrocode} +\cs_new_protected:Npn \@@_graphic_applyangle:nnnn #1#2#3#4 %lx,ly,ux,uy + { + \bool_lazy_and:nnT + {\cs_if_exist_p:N \Grot@angle } + {! \int_compare_p:nNn { \Grot@angle }={0}} + { + \fp_set:Nn \l_@@_graphic_sin_fp { sind(\Grot@angle) } + \fp_set:Nn \l_@@_graphic_cos_fp { cosd(\Grot@angle) } + \fp_set:Nn \l_@@_graphic_lx_fp {#1} + \fp_set:Nn \l_@@_graphic_ly_fp {#2} + \fp_set:Nn \l_@@_graphic_ux_fp {#3} + \fp_set:Nn \l_@@_graphic_uy_fp {#4} +% \end{macrocode} +% get the x coordinates (cos,-sin) +% \begin{macrocode} + \fp_set:Nn\l_@@_graphic_lxly_fp + { + -\l_@@_graphic_trim_lx_fp * \l_@@_graphic_cos_fp + +\l_@@_graphic_trim_ly_fp * \l_@@_graphic_sin_fp + } + \fp_set:Nn\l_@@_graphic_lxuy_fp + { + (-\l_@@_graphic_trim_lx_fp) * \l_@@_graphic_cos_fp + + + (\l_@@_graphic_uy_fp-\l_@@_graphic_ly_fp-\l_@@_graphic_trim_ly_fp) + * (-\l_@@_graphic_sin_fp) + } + \fp_set:Nn\l_@@_graphic_uxly_fp + { + (\l_@@_graphic_ux_fp-\l_@@_graphic_lx_fp-\l_@@_graphic_trim_lx_fp) + * \l_@@_graphic_cos_fp + + + (\l_@@_graphic_trim_ly_fp) * (\l_@@_graphic_sin_fp) + } + \fp_set:Nn\l_@@_graphic_uxuy_fp + { + (\l_@@_graphic_ux_fp-\l_@@_graphic_lx_fp-\l_@@_graphic_trim_lx_fp) + * \l_@@_graphic_cos_fp + + + (\l_@@_graphic_uy_fp-\l_@@_graphic_ly_fp-\l_@@_graphic_trim_ly_fp) + * (-\l_@@_graphic_sin_fp) + } + \tl_gset:Nx\g_@@_graphic_lx_tl + { + \fp_eval:n + { + min + ( + \l_@@_graphic_lxly_fp, + \l_@@_graphic_lxuy_fp, + \l_@@_graphic_uxly_fp, + \l_@@_graphic_uxuy_fp, + ) + +\l_@@_graphic_lx_fp + +\l_@@_graphic_trim_lx_fp + } + } + \tl_gset:Nx\g_@@_graphic_ux_tl + { + \fp_eval:n + { + max + ( + \l_@@_graphic_lxly_fp, + \l_@@_graphic_lxuy_fp, + \l_@@_graphic_uxly_fp, + \l_@@_graphic_uxuy_fp + ) + +\l_@@_graphic_lx_fp + +\l_@@_graphic_trim_lx_fp + } + } +% \end{macrocode} +% get the y coordinates (sin,cos) +% \begin{macrocode} + \fp_set:Nn\l_@@_graphic_lxly_fp + { + -\l_@@_graphic_trim_lx_fp * \l_@@_graphic_sin_fp + -\l_@@_graphic_trim_ly_fp * \l_@@_graphic_cos_fp + } + \fp_set:Nn\l_@@_graphic_lxuy_fp + { + - \l_@@_graphic_trim_lx_fp * \l_@@_graphic_sin_fp + + + (\l_@@_graphic_uy_fp-\l_@@_graphic_ly_fp-\l_@@_graphic_trim_ly_fp) + * \l_@@_graphic_cos_fp + } + \fp_set:Nn\l_@@_graphic_uxly_fp + { + (\l_@@_graphic_ux_fp-\l_@@_graphic_lx_fp-\l_@@_graphic_trim_lx_fp) + * \l_@@_graphic_sin_fp + - \l_@@_graphic_trim_ly_fp * \l_@@_graphic_cos_fp + } + \fp_set:Nn\l_@@_graphic_uxuy_fp + { + (\l_@@_graphic_ux_fp-\l_@@_graphic_lx_fp-\l_@@_graphic_trim_lx_fp) + * \l_@@_graphic_sin_fp + + + (\l_@@_graphic_uy_fp-\l_@@_graphic_ly_fp-\l_@@_graphic_trim_ly_fp) + * \l_@@_graphic_cos_fp + } + \tl_gset:Nx\g_@@_graphic_ly_tl + { + \fp_eval:n + { + min + ( + \l_@@_graphic_lxly_fp, + \l_@@_graphic_lxuy_fp, + \l_@@_graphic_uxly_fp, + \l_@@_graphic_uxuy_fp + ) + + \l_@@_graphic_ly_fp + \l_@@_graphic_trim_ly_fp + } + } + \tl_gset:Nx\g_@@_graphic_uy_tl + { + \fp_eval:n + { + max + ( + \l_@@_graphic_lxly_fp, + \l_@@_graphic_lxuy_fp, + \l_@@_graphic_uxly_fp, + \l_@@_graphic_uxuy_fp, + ) + + \l_@@_graphic_ly_fp + \l_@@_graphic_trim_ly_fp + } + } + } + } +\cs_generate_variant:Nn\@@_graphic_applyangle:nnnn {VVVV} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_graphic_applycorr:NNNN} +% This command is used to add at the end the correction values. Quite dump ... +% \begin{macrocode} +\cs_new_protected:Npn \@@_graphic_applycorr:NNNN #1 #2 #3 #4 + { + \bool_if:NT\l_@@_graphic_bboxcorr_bool + { + \tl_set:Nx #1 + { + \fp_eval:n + { + #1 + + + \dim_to_decimal_in_bp:n {\seq_item:Nn \l_@@_graphic_bboxcorr_seq {1} } + } + } + \tl_set:Nx #2 + { + \fp_eval:n + { + #2 + + + \dim_to_decimal_in_bp:n {\seq_item:Nn \l_@@_graphic_bboxcorr_seq {2} } + } + } + \tl_set:Nx #3 + { + \fp_eval:n + { + #3 + + + \dim_to_decimal_in_bp:n {\seq_item:Nn \l_@@_graphic_bboxcorr_seq {3} } + } + } + \tl_set:Nx #4 + { + \fp_eval:n + { + #4 + + + \dim_to_decimal_in_bp:n {\seq_item:Nn \l_@@_graphic_bboxcorr_seq {4} } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\Gin@tag@bbox@attribute} +% This is the main command to calculate and set the Bbox attribute +% \begin{macrocode} +\cs_new_protected:Npn \Gin@tag@bbox@attribute + { +% \end{macrocode} +% the attribute is only needed if tagging is active and there is not artifact. +% \begin{macrocode} + \bool_lazy_all:nT + { + {\tag_if_active_p:} + {!\l_@@_graphic_artifact_bool} + {\l_@@_graphic_BBox_bool} + } + { + \fp_set:Nn \l_@@_graphic_scale_fp { \Gin@scalex } + \@@_graphic_get_trim: + \int_gincr:N\g_@@_graphic_int + \tl_set:Nx\l_@@_graphic_currentlabel_tl {_@@_graphic_\int_use:N \g_@@_graphic_int} + \@@_graphic_savepos:e { \l_@@_graphic_currentlabel_tl } + \tl_gset:Nx\g_@@_graphic_lx_tl + { + \dim_to_decimal_in_bp:n + { \@@_ref_value:enn {\l_@@_graphic_currentlabel_tl}{xpos}{0}sp } + } + \tl_gset:Nx\g_@@_graphic_ly_tl + { + \dim_to_decimal_in_bp:n + { \@@_ref_value:enn {\l_@@_graphic_currentlabel_tl}{ypos}{0}sp } + } + \tl_gset:Nx\g_@@_graphic_ux_tl + { + \fp_eval:n + { + \g_@@_graphic_lx_tl + + + \dim_to_decimal_in_bp:n { \Gin@req@width } + } + } + \tl_gset:Nx\g_@@_graphic_uy_tl + { + \fp_eval:n + { + \g_@@_graphic_ly_tl + + + \dim_to_decimal_in_bp:n { \Gin@req@height } + } + } +% \end{macrocode} +% If the graphics is not clipped we must add the trim values. +% \begin{macrocode} + \legacy_if:nF {Gin@clip} + { + \tl_gset:Nx\g_@@_graphic_ux_tl + { + \fp_eval:n + { + \g_@@_graphic_ux_tl + + + \l_@@_graphic_trim_ux_fp + } + } + \tl_gset:Nx\g_@@_graphic_lx_tl + { + \fp_eval:n + { + \g_@@_graphic_lx_tl + - + \l_@@_graphic_trim_lx_fp + } + } + \tl_gset:Nx\g_@@_graphic_uy_tl + { + \fp_eval:n + { + \g_@@_graphic_uy_tl + + + \l_@@_graphic_trim_uy_fp + } + } + \tl_gset:Nx\g_@@_graphic_ly_tl + { + \fp_eval:n + { + \g_@@_graphic_ly_tl + - + \l_@@_graphic_trim_ly_fp + } + } + } +% \end{macrocode} +% If there is an angle we now rotate the values. +% \begin{macrocode} + \@@_graphic_applyangle:VVVV + \g_@@_graphic_lx_tl + \g_@@_graphic_ly_tl + \g_@@_graphic_ux_tl + \g_@@_graphic_uy_tl +% \end{macrocode} +% At last we have to add the correction values +% \begin{macrocode} + \@@_graphic_applycorr:NNNN + \g_@@_graphic_lx_tl + \g_@@_graphic_ly_tl + \g_@@_graphic_ux_tl + \g_@@_graphic_uy_tl +% \end{macrocode} +% \begin{macrocode} + \bool_if:NT\l_@@_graphic_debug_bool + { + \@@_graphic_show_bbox:VVVVne + \g_@@_graphic_lx_tl + \g_@@_graphic_ly_tl + \g_@@_graphic_ux_tl + \g_@@_graphic_uy_tl + {red} + {\int_use:N\g_@@_graphic_int} + } +% \end{macrocode} +% Now we add the attribute. We do it manually as it had to be delayed until now. +% The structure and the mc must be open earlier, before the \cs{setbox} (at least +% for luatex it has to). TODO: think about interface if more attributes are needed. +% \begin{macrocode} + \@@_prop_gput:cnx + { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop } + { A } + { + << + /O /Layout /BBox~ + [ + \g_@@_graphic_lx_tl\c_space_tl + \g_@@_graphic_ly_tl\c_space_tl + \g_@@_graphic_ux_tl\c_space_tl + \g_@@_graphic_uy_tl + ] + >> + } + } + } +% \end{macrocode} +% \end{macro} +% \subsection{Support for the picture environment} +% +% \begin{macro}{\picture@tag@bbox@attribute} +% Picture needs a similar command to calculate the bbox. But here we stay simple +% and use simply the size of the picbox. +% +% \begin{macrocode} +\newcommand\picture@tag@bbox@attribute + { + \bool_lazy_all:nT + { + {\tag_if_active_p:} + {!\l_@@_graphic_artifact_bool} + {\l_@@_graphic_BBox_bool} + } + { + \int_gincr:N\g_@@_graphic_int + \tl_set:Nx\l_@@_graphic_currentlabel_tl {_@@_graphic_\int_use:N \g_@@_graphic_int} + \@@_graphic_savepos:e { \l_@@_graphic_currentlabel_tl } + \tl_gset:Nx \g_@@_graphic_lx_tl + { + \dim_to_decimal_in_bp:n + { \@@_ref_value:enn {\l_@@_graphic_currentlabel_tl}{xpos}{0}sp } + } + \tl_gset:Nx \g_@@_graphic_ly_tl + { + \dim_to_decimal_in_bp:n + { \@@_ref_value:enn {\l_@@_graphic_currentlabel_tl}{ypos}{0}sp - \dp\@picbox } + } + \tl_gset:Nx \g_@@_graphic_ux_tl + { + \dim_to_decimal_in_bp:n + { + \g_@@_graphic_lx_tl bp + \wd\@picbox + } + } + \tl_gset:Nx \g_@@_graphic_uy_tl + { + \dim_to_decimal_in_bp:n + { + \g_@@_graphic_ly_tl bp + \ht\@picbox + \dp\@picbox + } + } + \@@_graphic_applycorr:NNNN + \g_@@_graphic_lx_tl + \g_@@_graphic_ly_tl + \g_@@_graphic_ux_tl + \g_@@_graphic_uy_tl + \bool_if:NT\l_@@_graphic_debug_bool + { + \@@_graphic_show_bbox:VVVVne + \g_@@_graphic_lx_tl + \g_@@_graphic_ly_tl + \g_@@_graphic_ux_tl + \g_@@_graphic_uy_tl + {red} + {\int_use:N\g_@@_graphic_int} + } + \@@_prop_gput:cnx + { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop } + { A } + { + << + /O /Layout /BBox~ + [ + \g_@@_graphic_lx_tl\c_space_tl + \g_@@_graphic_ly_tl\c_space_tl + \g_@@_graphic_ux_tl\c_space_tl + \g_@@_graphic_uy_tl + ] + >> + } + } + } + +% \end{macrocode} +% \end{macro} +% We redefine \cs{picture} to accept an optional argument and +% change the default alt text. We also ensure that we are in +% hmode, so that stopping tagging doesn't confuse the paratags. +% \begin{macrocode} +\RenewDocumentCommand\picture{O{}m} + { + \leavevmode + \keys_set:nn{tag/picture}{#1} % + \tl_set:Nn\l_@@_graphic_alt_dflt_tl {picture~environment} + \pictur@#2 + } +% \end{macrocode} +% inside the picture box we stop tagging. +% \begin{macrocode} +\def\@picture(#1,#2)(#3,#4){% + \@defaultunitsset\@picht{#2}\unitlength + \@defaultunitsset\@tempdimc{#1}\unitlength + \Gin@tag@struct@begin + \setbox\@picbox\hb@xt@\@tempdimc\bgroup + \tag_stop: %do not tag inside the picture box + \@defaultunitsset\@tempdimc{#3}\unitlength + \hskip -\@tempdimc + \@defaultunitsset\@tempdimc{#4}\unitlength + \lower\@tempdimc\hbox\bgroup + \ignorespaces} +% \end{macrocode} +% +% \begin{macrocode} +\def\endpicture{% + \egroup\hss\egroup + \ht\@picbox\@picht\dp\@picbox\z@ + \picture@tag@bbox@attribute + \mbox{\box\@picbox} + \Gin@tag@struct@end} +% \end{macrocode} +% +% \subsection{Debugging code} +% +% \begin{macro}{\@@_graphic_show_bbox:nnnnnn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_graphic_show_bbox:nnnnnn #1#2#3#4#5#6%#5 color, #6 graphic + { + \iow_log:n {tag/graphic~debug:~BBox~of~graphics~#6~is~#1~#2~#3~#4} + \hook_gput_code:nnn + {shipout/foreground} + {tag/graphic} + { + \int_compare:nNnT + {\g_shipout_readonly_int} + = + {\@@_ref_value:enn{_@@_graphic_#6}{abspage}{0}} + { + \put + (#1 bp,\dim_eval:n{-\paperheight + \dim_eval:n{#2 bp}}) + { + \opacity_select:n{0.5}\color_select:n{#5} + \rule + {\dim_eval:n {#3 bp-\dim_eval:n{#1 bp}}} + {\dim_eval:n {#4 bp-\dim_eval:n{#2 bp}}} + } + } + } + } + \cs_generate_variant:Nn \@@_graphic_show_bbox:nnnnnn {VVVVne} +% \end{macrocode} +% \end{macro} + +% \begin{macrocode} +%</package> +% \end{macrocode} + +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{graphic-latex-lab-testphase.ltx} + [2023-04-07 v0.8 code related to the tagging included graphics] +\RequirePackage{latex-lab-testphase-graphic} +%</latex-lab> +% \end{macrocode} +% \end{implementation} diff --git a/macros/latex/required/latex-lab/latex-lab-graphic.pdf b/macros/latex/required/latex-lab/latex-lab-graphic.pdf Binary files differnew file mode 100644 index 0000000000..7a5a07325e --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-graphic.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-mathpkg.dtx b/macros/latex/required/latex-lab/latex-lab-mathpkg.dtx new file mode 100644 index 0000000000..14d8e94362 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-mathpkg.dtx @@ -0,0 +1,102 @@ +% \iffalse meta-comment +% +%% File: latex-lab-mathpkg.dtx +% +% Copyright (C) 2022,2023 The LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-mathpkg.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \texttt{latex-lab-mathpkg} code\thanks{}} +% \author{\LaTeX{} Project} +% +% \maketitle +% +% \newcommand\fmi[1]{\begin{quote} TODO: \itshape #1\end{quote}} +% \newcommand\NEW[1]{\marginpar{\mbox{}\hfill\fbox{New: #1}}} +% \providecommand\class[1]{\texttt{#1.cls}} +% \providecommand\pkg[1]{\texttt{#1}} +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% This file implements adaptions to various math packages needed for +% the tagging project. +% +% \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } +% +% \section{The Implementation} +% +% \begin{macrocode} +%<@@=math> +% \end{macrocode} +% +% \begin{macrocode} +%<*kernel> +% \end{macrocode} +% +% \subsection{File declaration} +% \begin{macrocode} +\ProvidesFile{latex-lab-mathpkg.ltx} + [2023-01-05 v0.1a mathpkg adaptions] +% \end{macrocode} +% \subsection{Tagpdf support} +% To make the code independent from tagging being loaded and active +% we load the \pkg{tagpdf-base} package: +% +% \begin{macrocode} +\RequirePackage{tagpdf-base} +% \end{macrocode} +% +% +% \begin{macrocode} +\AddToHook{package/breqn/after}{ + \RegisterMathEnvironment{dmath} + \RegisterMathEnvironment{dgroup*} + \AddToHook{env/dmath/begin}{\tagpdfparaOff} + \AddToHook{env/dgroup*/begin}{\tagpdfparaOff} +} +% \end{macrocode} +% +% Force loading of \pkg{amsmath} before \pkg{cases}. +% \begin{macrocode} +\AddToHook {package/cases/before}{\RequirePackage{amsmath}} +\AddToHook{package/cases/after}{ + \RegisterMathEnvironment{subnumcases} +} +% \end{macrocode} +% +% \begin{macrocode} +%</kernel> +% \end{macrocode} +% \subsection{Wrapper files for testphase key} +% \Finale +% diff --git a/macros/latex/required/latex-lab/latex-lab-mathpkg.pdf b/macros/latex/required/latex-lab/latex-lab-mathpkg.pdf Binary files differnew file mode 100644 index 0000000000..acc2d859a6 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-mathpkg.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-mathtagging.dtx b/macros/latex/required/latex-lab/latex-lab-mathtagging.dtx new file mode 100644 index 0000000000..923001f559 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-mathtagging.dtx @@ -0,0 +1,1280 @@ +% \iffalse meta-comment +% +%% File: latex-lab-mathtagging.dtx +% +% Copyright (C) 2022-2023 The LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +% +\def\ltmathtaggingdate{2023-03-08} +\def\ltmathtaggingversion{v0.5a} +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex + +\usepackage{todonotes} + +\begin{document} + \DocInput{latex-lab-mathtagging.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \texttt{latex-lab-mathtagging} code\thanks{}} +% \author{Frank Mittelbach, Joseph Wright, \LaTeX{} Project} +% +% \maketitle +% +% \newcommand\NEW[1]{\marginpar{\mbox{}\hfill\fbox{New: #1}}} +% \providecommand\class[1]{\texttt{#1.cls}} +% \providecommand\pkg[1]{\texttt{#1}} +% \providecommand\hook[1]{\texttt{#1}} +% +% ^^A \car {...} for marginal comments +% ^^A \car*{...} for longer inline comments +% +% \NewDocumentCommand\car{sO{}m} +% {\IfBooleanTF{#1}{\todo[inline,color=blue!10,#2]{#3}}^^A +% {\todo[color=blue!10,#2]{#3}}} +% +% \NewDocumentCommand\fmi{sO{}m} +% {\IfBooleanTF{#1}{\todo[inline,#2]{#3}}^^A +% {\todo[#2]{#3}}} +% +% +% +% \begin{abstract} +% This is an experimental prototype. It captures math material +% (basically okay, but the interfaces for packages aren't yet +% there) and tags the material (which is not yet anywhere near the +% final state). That part is provided for experimentation and to +% gather feedback, etc. +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% \car*{Todo: update all the documentation! Both here and +% (what little there is!) in the implementation section.} +% +% This file implements capture of all math mode material at the outer +% level, i.e., a formula is captured in its entirety with inner text +% blocks (possibly containing further math) absorbed as part of the +% formula. For example, +%\begin{verbatim} +% \[ a \in A \text{ for all $a<5$} \] +%\end{verbatim} +% would only result in a single capture of the tokens +% ``\verb*/a \in A \text{ for all $a<5$}/''. +% +% \subsection{Code level interfaces} +% +% \begin{function}{\math_register_env:n, \math_register_env:nn} +% \begin{syntax} +% \cs{math_register_env:n} \Arg{env} +% \cs{math_register_env:nn} \Arg{env} \Arg{options} +% \end{syntax} +% Registers the \meta{env} as a math environment which should be captured +% and made available. This is necessary for all top-level math mode +% environments: low-level errors may result if these are not correct +% set up. One or more key--value \meta{options} may also be given: +% \begin{itemize} +% \item[\texttt{arg-spec}] The argument specification taken by the +% beginning of the environment; this is used to remove non-mathematical +% material. +% \end{itemize} +% \end{function} +% +% \begin{function}{\math_processor:n} +% \begin{syntax} +% \cs{math_processor:n} \Arg{tokens} +% \end{syntax} +% Declares that the captured math content should be passed to the +% \meta{tokens}, which will receive the environment type as |#1| and +% the content as |#2|. +% \end{function} +% +% \subsection{Document level interfaces} +% +% \begin{function}{\RegisterMathEnvironment} +% \begin{syntax} +% \cs{RegisterMathEnvironment} \oarg{options} \Arg{env} +% \end{syntax} +% Registers the \meta{env} as a math environment which should be captured +% and made available. This is necessary for all top-level math mode +% environments: low-level errors may result if these are not correct +% set up. One or more key--value \meta{options} may also be given: +% \begin{itemize} +% \item[\texttt{arg-spec}] The argument specification taken by the +% beginning of the environment; this is used to remove non-mathematical +% material. +% \end{itemize} +% \end{function} +% +% \section{Known current bugs, etc.} +% \car*{New Section, now with subsections.\\ +% As indicated, these lists are probably incomplete.\\ +% Some of these have been addressed in a more recent branch.} +% +% \subsection{Capture/grabbing problems} +% +% \begin{enumerate} +% \item Incorrect grabbing of |$|-math when there is also +% explicit |$|-math within a \textit{text environment} +% that is itself within the math that should all be grabbed. +% \item Similar incorrect grabbing with |$$| also. +% \item The grabbing, for all the display environments (and |\) \]|), needs +% to deal with nesting: \pkg{amsmath} contains code for this. +% \item +% \end{enumerate} +% +% \subsection{Other problems} +% +% \begin{enumerate} +% \item +% The presence of \cs{m@th} in association with \cs{ensuremath} +% does not necessarily indicate fakemath. This is because +% wanting mathsurround to be zero is very reasonable and common, +% \emph{even when the math is genuine} (and hence needs to be collected). +% \item User-defined environments can create problems; but this area, of +% new, copied and changed environments, has not yet been developed. +% +% \car*{Joseph wrote, inter alia:\\ +% My thinking [regarding] \cs{RegisterMathEnvironment}\\ +% - (New) Math environments should not be created-then-patched, but only +% generated by a [(future)] dedicated command (\cs{DeclareMathEnviornment}, +% presumably)\\ +% - Math environments created with \pkg{ltcmd} [commands] should not be copied, . . .\\ +% - Package authors should be able to manually set up math environments with a public boolean.} +% +% \item +% \end{enumerate} +% +% +% \subsection{Other ToDos} +% +% \begin{enumerate} +% \item Add (some of) the math display commands that were \enquote{lifted from +% plain}, e.g., \cs{displaylines} \cs{eqalign}(??). +% \item +% \end{enumerate} +% +% +% \car*{\cs{MaybeStop} (temporarily) not executed, as it is unknown on Chris' system.} +% \iffalse +% \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } +% \else +% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } +% \fi +% +% \section{The Implementation} +% +% \begin{macrocode} +%<@@=math> +% \end{macrocode} +% +% \begin{macrocode} +%<*kernel> +% \end{macrocode} +% +% \subsection{File declaration} +% +% \car{Change description here?} +% \begin{macrocode} +\ProvidesFile{latex-lab-mathtagging.ltx} + [\ltmathtaggingdate\space + \ltmathtaggingversion\space + Grab all the math(s) and tag it (experiments)] +% \end{macrocode} +% +% Temp loading \ldots +% \begin{macrocode} +\AddToHook{begindocument/before}{\RequirePackage{latex-lab-testphase-block-tagging}} +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOn +% \end{macrocode} +% +% \subsection{Setup} +% +% Loading \pkg{amsmath} is an absolute requirement: this avoids needing to +% have conditional definitions and deals with how to define \cs{[}/\cs{]} +% neatly. +% \begin{macrocode} +\tl_gput_right:Nn \@kernel@before@begindocument + { \RequirePackage { amsmath } } +% \end{macrocode} +% +% +% \subsection{Data structures} +% +% +% +% \begin{variable}{\l_@@_collected_bool} +% Tracks whether math mode material has been collected, which happens inside +% \pkg{amsmath} environments as well as those handled directly here. +% +% +% \begin{macrocode} +\bool_new:N \l_@@_collected_bool +% \end{macrocode} +% \end{variable} +% +% \car{Change first tl name below: `env' $=>$ `info'?\\ +% Or do we need an extra storage tl?} +% +% \begin{variable}{\g_@@_grabbed_env_tl, \g_@@_grabbed_math_tl} +% \begin{macrocode} +\tl_new:N \g_@@_grabbed_env_tl +\tl_new:N \g_@@_grabbed_math_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Interface commands} +% +% \begin{macro} +% {\@@_process:nn, \@@_process:Vn, \@@_process_auxi:nn, \@@_process_auxii:nn} +% A no-op place-holder; the internal wrapper means that it does not need to +% be concerned with internals. +% \begin{macrocode} +\cs_new_protected:Npn \@@_process:nn #1#2 + { + \legacy_if:nF { measuring@ } + { + \tl_if_in:nnF {#2} { \m@th } + { \tl_trim_spaces_apply:nN {#2} \@@_process_auxi:nn {#1} } + } + } +\cs_generate_variant:Nn \@@_process:nn { V } +\cs_new_protected:Npn \@@_process_auxi:nn #1#2 + { + \tl_gset:Nn \g_@@_grabbed_env_tl {#2} + \tl_gset:Nn \g_@@_grabbed_math_tl {#1} + \@@_process_auxii:nn {#2} {#1} + } +\cs_new_protected:Npn \@@_process_auxii:nn #1#2 { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\math_processor:n} +% A simple installer +% \begin{macrocode} +\cs_new_protected:Npn \math_processor:n #1 + { \cs_set_protected:Npn \@@_process_auxii:nn ##1##2 {#1} } +% \end{macrocode} +% \end{macro} +% +% \subsection{Content grabbing} +% +% \begin{macro}{\@@_grab_dollar:w} +% Grab up to a single |$|, for inline math mode, suppressing +% any processing if the first token is \tn{m@th}. +% +% \fmi{what's that test doing?} +% +% \car{It is some kind of fix, to avoid the remote +% possibility that the math is empty, making the code +% produce an unwanted \texttt{\$\$}.} +% +%\car{cf.~the code for this in \cs{@ensuredmath}} +% +%\car{It is harmless but unnecessary in the dollardollar grabbing below.} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_grab_dollar:w % $ + #1 $ + { +% \end{macrocode} +% \fmi{what's that test doing?} +% \begin{macrocode} + \tl_if_blank:nF {#1} + { + \@@_process:nn { math } {#1} % $ +% fairly simple this one + \tagmcend %end P-chunk, in code: \tag_mc_end_push: + \@kernel@math@begin + #1 $ + \@kernel@math@end + \tagmcbegin{} % restart P-chunk (whatsits in pdftex) + } + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_grab_dollardollar:w} +% And for the classical \TeX{} display structure. +% \begin{macrocode} + +\skip_new:N \l_@@_tmpa_skip + +\cs_new_protected:Npn \@@_grab_dollardollar:w % $$ + #1 $$ + { + \tl_if_blank:nF {#1} + { + \@@_tag_dollardollar_display:nn { equation* }{#1} + #1 + $$ + } + } + +\cs_new_protected:Npn \@kernel@close@P { + \tagmcend %end P-chunk, in code: \tag_mc_end_push: + \int_gincr:N \g__tag_para_end_int + \bool_if:NT \l__tag_para_show_bool + { \tag_mc_begin:n{artifact} + \rlap{\color_select:n{red}\tiny\ \int_use:N\g__tag_para_end_int} + \tag_mc_end: + } + \tag_struct_end: +} + + + +\cs_new_protected:Npn \@@_tag_dollardollar_display:nn #1#2 { + \@@_process:nn {#1} {#2} + \@kernel@close@P + \@kernel@math@begin +% \skip_set:Nn \belowdisplayskip {-\belowdisplayskip} +% \skip_set:Nn \belowdisplayshortskip {-\belowdisplayshortskip} +% \int_set:Nn \postdisplaypenalty {10000} +%% +% \group_insert_after:N \@@_tag_dollardollar_display_end: +} + +\cs_new_protected:Npn \@@_tag_dollardollar_display_end: { +% \typeout{== tag dollarldollar display end} +% \ShowTagging{struct-stack} + \tagpdfparaOff + \para_raw_end: + \tagpdfparaOn + \l_@@_tmpa_skip \lastskip + \@kernel@math@end + \penalty \postdisplaypenalty + \skip_vertical:n { -\l_@@_tmpa_skip } +% + \@doendpe % this has no \end{...} to take care of it +} + + +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_grab_inline:w} +% Collect inline math content and deal with the need to move to math mode. +% \begin{macrocode} +\cs_new_protected:Npn \@@_grab_inline:w % \( + #1 \) + { + \tl_if_blank:nF {#1} + { + \@@_process:nn { math } {#1} + $ #1 $ + } + \bool_set_false:N \l_@@_collected_bool + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_grab_eqn:w} +% For the most common use of \cs{[}/\cs{]}: turn into an environment. +% \begin{macrocode} +\cs_new_protected:Npn \@@_grab_eqn:w % \[ + #1 \] + { +% \typeout{collected? = \bool_if:NTF \l_@@_collected_bool {true}{false}} + \begin { equation* } #1 \end { equation* } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Marking math environments} +% +% A general mechanism for math mode environments that do not grab their +% content (\emph{cf.}~most \pkg{amsmath} environments). +% +% \begin{variable}{\l_@@_env_name_tl} +% To allow us to carry out \enquote{special effects} +% \begin{macrocode} +\tl_new:N \l_@@_env_name_tl +% \end{macrocode} +% \end{variable} +% +% Here we set up specialised handling of environments. The idea for the +% \texttt{arg-spec} key is that if an environment takes arguments, we +% don't worry during the main grabbing. Rather, we remove the arguments +% from the grabbed content and forward only the payload. That is done by +% (ab)using \pkg{ltcmd}. +% \begin{macrocode} +\keys_define:nn { @@ } + { + arg-spec .code:n = + { + \ExpandArgs { c } \DeclareDocumentCommand + { @@_env \l_@@_env_name_tl _aux: } + {#1} + { \@@_env_forward:w } + } + } +% \end{macrocode} +% +% \begin{macro}{\math_register_env:nn} +% \begin{macro}{\math_register_env:n} +% \begin{macro}{\RegisterMathEnvironment} +% Set up to capture environment content and make available. +% +% \begin{macrocode} +\cs_new_protected:Npn \math_register_env:nn #1#2 + { + \tl_set:Nn \l_@@_env_name_tl {#1} + \keys_set:nn { @@ } {#2} + \cs_gset_eq:cc { @@_env_ #1 _begin: } {#1} + \cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 } +% + \ExpandArgs { nnx } \RenewDocumentEnvironment {#1} { b } + { +% \bool_set_true:N \exp_not:N \l_@@_collected_bool +% \cs_if_exist:cTF { @@_env #1 _aux: } +% { +% \exp_not:c { @@_env #1 _aux: } +% ####1 \exp_not:N \@@_env_end: {#1} +% } +% { \exp_not:N \@@_process:nn {#1} {####1} } + \exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool + { +% \typeout{===>B1} + } + { +% \typeout{===>B2} + \cs_if_exist:cTF { @@_env #1 _aux: } + { + \exp_not:c { @@_env #1 _aux: } + ####1 \exp_not:N \@@_env_end: {#1} + } + { \exp_not:N \@@_process:nn {#1} {####1} } + \exp_not:n { \@kernel@math@registered@begin } + \bool_set_true:N \exp_not:N \l_@@_collected_bool + } +% \exp_not:N \tracingall + \exp_not:c { @@_env_ #1 _begin: } + ####1 + \exp_not:c { @@_env_ #1 _end: } +% \exp_not:c { @@_env_ #1 _end: } +% \exp_not:N \tracingnone +% \exp_not:n { \@kernel@math@registered@end } + } + { + } + } + +\cs_set_protected:Npn \__cs_tmp:w #1 + { + \group_begin: + \exp_args:No \__cs_generate_internal_variant:n + { \tl_to_str:n {#1} } + \group_end: + } +\__cs_tmp:w { nnxx } + + +\cs_new_protected:Npn \math_register_halign_env:nn #1#2 + { + \tl_set:Nn \l_@@_env_name_tl {#1} + \keys_set:nn { @@ } {#2} + \cs_gset_eq:cc { @@_env_ #1 _begin: } {#1} + \cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 } +% + \ExpandArgs { nnxx } \RenewDocumentEnvironment {#1} { b } + { +% \bool_set_true:N \exp_not:N \l_@@_collected_bool +% \cs_if_exist:cTF { @@_env #1 _aux: } +% { +% \exp_not:c { @@_env #1 _aux: } +% ####1 \exp_not:N \@@_env_end: {#1} +% } +% { \exp_not:N \@@_process:nn {#1} {####1} } + \exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool + { +% \typeout{===>B1} + } + { +% \typeout{===>B2} + \cs_if_exist:cTF { @@_env #1 _aux: } + { + \exp_not:c { @@_env #1 _aux: } + ####1 \exp_not:N \@@_env_end: {#1} + } + { \exp_not:N \@@_process:nn {#1} {####1} } + \exp_not:n { \@kernel@math@registered@begin } + \bool_set_true:N \exp_not:N \l_@@_collected_bool + } +% \exp_not:N \tracingall + \exp_not:c { @@_env_ #1 _begin: } + ####1 +% \exp_not:c { @@_env_ #1 _end: } +% \exp_not:N \tracingnone + } + { + \exp_not:c { @@_env_ #1 _end: } + } + } + +\cs_new_protected:Npn \math_register_odd_env:nn #1#2 + { + \tl_set:Nn \l_@@_env_name_tl {#1} + \keys_set:nn { @@ } {#2} + \cs_gset_eq:cc { @@_env_ #1 _begin: } {#1} + \cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 } +% + \ExpandArgs { nnxx } \RenewDocumentEnvironment {#1} { b } + { + \exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool + { +% \typeout{===>B1} + } + { +% \typeout{===>B2} + \cs_if_exist:cTF { @@_env #1 _aux: } + { + \exp_not:c { @@_env #1 _aux: } + ####1 \exp_not:N \@@_env_end: {#1} + } + { \exp_not:N \@@_process:nn {#1} {####1} } + \exp_not:n { \@kernel@math@registered@begin } + \bool_set_true:N \exp_not:N \l_@@_collected_bool + } +% \exp_not:N \tracingall + \exp_not:c { @@_env_ #1 _begin: } + ####1 + } + { + \exp_not:c { @@_env_ #1 _end: } +% needed if we don't have $$...$$ +% \exp_not:n { \typeout{---> @kernel@math@registered@end }} + \exp_not:n { \@kernel@math@registered@end } + } + } + + +% FMi: compare with block change! +% +% \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}% +% \@execute@begin@hook{#1}% +% \csname #1\endcsname}}% +% \@ignorefalse +% \begingroup +% \@endpefalse % tmp!!! is it ok to drop this here? +% \reserved@a} + + +\cs_new:Npn \@kernel@math@registered@begin { +% \ShowTagging{struct-stack} +%\typeout{==>A1}\ShowTagging{struct-stack,mc-current} + \mode_if_vertical:TF + { +% \legacy_if:nTF { @endpe } +% { \legacy_if_set_false:n { @endpe } } +% { \__block_list_beginpar_vmode: } +% +% \typeout{==>~ at:~ \g__tag_struct_tag_tl} +% + \exp_args:Noo\str_if_eq:nnF \g__tag_struct_tag_tl { \l__tag_para_main_tag_tl } % needs correction! + { +% \typeout{==>A2} + \__block_beginpar_vmode: + } % needs correction! + } + { +% \typeout{==>A3} + \@kernel@close@P +% \tagmcend % needs correction! + } + \@kernel@math@begin + \tagpdfparaOff +% \typeout{==>MC1}\ShowTagging{mc-current} +} + +\cs_new:Npn \@kernel@math@registered@end { +% \typeout{==>MC2}\ShowTagging{mc-current} + \para_raw_end: + \tagpdfparaOn + \@kernel@math@end +% \typeout{==>MC3}\ShowTagging{mc-current} + \@endpetrue +} + +\cs_new_protected:Npn \math_register_env:n #1 + { \math_register_env:nn {#1} { } } +\NewDocumentCommand \RegisterMathEnvironment { O{} m } + { \math_register_env:nn {#2} {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_env_forward:w} +% \begin{macrocode} +\cs_new_protected:Npn \@@_env_forward:w #1 \@@_env_end: #2 + { \@@_process:nn {#2} {#1} } +% \end{macrocode} +% \end{macro} +% +% \subsection{Document commands} +% +% \car*{Add one more here: \texttt{displaymath}, which +% is equivalent to \cs{[} , \cs{]}\\ +% and hence to the basic \texttt{equation*}.\\ +% Added in more recent branch.} +% +% \begin{macro} +% {\equation, \@@_equation_begin:, \equation*, \@@_equation_star_begin:} +% \begin{macro} +% {\endequation, \@@_equation_end:, \endequation*, \@@_equation_star_end:} +% These environments are not set up by \pkg{amsmath} to collect their body, +% so we do that here. This has to be done \emph{after} we can be sure +% \pkg{amsmath} is loaded. +% +% \car*{Note that with \pkg{amsmath} loaded, \texttt{equation*} and \texttt{equation}\\ +% are the two basics: they are used to define the other single-row\\ +% display environments, etc.} +% +% \begin{macrocode} +\tl_gput_right:Nn \@kernel@before@begindocument + { + \math_register_env:n { equation } + \math_register_env:n { equation* } +% at the moment register_env can only do display math +% \math_register_env:n { math } + \RenewDocumentEnvironment{math} {b}{$#1$}{} +% and this one doesn't work either +% \math_register_env:n { displaymath } + \RenewDocumentEnvironment{displaymath} {b}{\[#1\]}{} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\(, \)} +% If math mode has not been collected, we need to do that; otherwise, worry +% about whether we are in math mode or not. The closing command here can only +% occur inside a collected math block: otherwise it will be simply used as +% a delimiter. +% \begin{macrocode} +\cs_gset_protected:Npn \( % \) + { + \bool_if:NTF \l_@@_collected_bool + { + \mode_if_math:TF + { \@badmath } + { $ } + } + { + \bool_set_true:N \l_@@_collected_bool + \@@_grab_inline:w + } + } % \( +\cs_gset_protected:Npn \) + { + \mode_if_math:TF + { $ } + { \@badmath } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\[, \]} +% Again, we need to watch for when \pkg{amsmath} is loaded after this code. +% The flag usage here is to cover the case where \cs{[}/\cs{]} is hidden +% inside another environment. In this case the grabbing happens on +% the outer level and should not be repeated. +% \begin{macrocode} +\tl_gput_right:Nn \@kernel@before@begindocument + { + \cs_gset_protected:Npn \[ % \] + { + \bool_if:NTF \l_@@_collected_bool + { \begin { equation* } } + { \@@_grab_eqn:w } + } % \[ + \cs_gset_protected:Npn \] + { + \bool_if:NTF \l_@@_collected_bool + { \end{ equation* } } + { \@badmath } + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\ensuremath} +% A bit of nesting fun to make sure we collect only if required. +% \fmi{why does ensuremath need handling at all?} +% +% \car{Indeed! Currently, this is setup to process the math that +% it has anyways already captured as its argument; thus it is more +% efficient than leaving the capture to be repeated by the \cs{everymath}} +% +% \begin{macrocode} +%\cs_gset_protected:Npn \ensuremath #1 +% { +% \mode_if_math:TF +% {#1} +% { +% \bool_if:NTF \l_@@_collected_bool +% { \@ensuredmath {#1} } +% { +% \bool_set_true:N \l_@@_collected_bool +% \@@_process:nn { math } {#1} +% \@ensuredmath {#1} +% \bool_set_false:N \l_@@_collected_bool +% } +% } +% } +% \end{macrocode} +% \end{macro} +% +% \subsection{\cs{everymath} and \cs{everydisplay}} +% +% The business end for grabbing inline math and \enquote{raw} \TeX{} +% display. Most display math mode is actually handled elsewhere, as we +% have macro control. +% \begin{macrocode} + +\tl_new:N\tmpmathcontent + + +\def\@kernel@math@begin { +% \typeout{==>~math~begin} +% needs different handling if we support nesting + \tl_gset:Nx\tmpmathcontent + { + LaTeX~ formula~ starts~ + \exp_not:N\begin{\g__math_grabbed_env_tl} + \space + \exp_not:V\g__math_grabbed_math_tl + \space + \exp_not:N\end{\g__math_grabbed_env_tl} + \space LaTeX~ formula~ ends~ + } + \tagstructbegin{tag=Formula, + AFinline-o=\tmpmathcontent, + title-o=\g__math_grabbed_env_tl, + actualtext=\tmpmathcontent +% alt=\tmpmathcontent + } +% inner formula if multiple parts (not really implemented yet) + \grabaformulapartandstart +% the above does: +% \tagstructbegin{tag=Formula}\tagmcbegin{} +% or just +% \tagmcbegin{} +} +\def\@kernel@math@end { +% \typeout{==>~math~end} +% \ShowTagging{struct-stack} + \tagmcend + \if@subformulas + \tagstructend + \else + \fi + \tagstructend +% \ShowTagging{struct-stack} +} + +\exp_args:No \tex_everymath:D + { + \tex_the:D \tex_everymath:D + \bool_if:NF \l_@@_collected_bool + { + \bool_set_true:N \l_@@_collected_bool + \@@_grab_dollar:w + } + } +\exp_args:No \tex_everydisplay:D + { + \tex_the:D \tex_everydisplay:D + \iftrue % this may have to be a settable flag! +% { +% \typeout{==>~ in~ everydisplay} + \skip_set:Nn \belowdisplayskip {-\belowdisplayskip} + \skip_set:Nn \belowdisplayshortskip {-\belowdisplayshortskip} + \int_set:Nn \postdisplaypenalty {10000} +% + \group_insert_after:N \@@_tag_dollardollar_display_end: +% } + \fi + \bool_if:NF \l_@@_collected_bool + { + \bool_set_true:N \l_@@_collected_bool + \@@_grab_dollardollar:w + } + } +% \end{macrocode} +% +% \subsection{Modifying kernel environments} +% +% We need to cover this even though it is, of course, not encouraged. +% \begin{macrocode} +\math_register_env:n { eqnarray } +\math_register_env:n { eqnarray* } +% \end{macrocode} +% +% Places where math mode is (ab)used. +% \begin{macrocode} +\clist_map_inline:nn + { tabular } + { + \AddToHook{ env / #1 / begin } + { \bool_set_true:N \l_@@_collected_bool } + } +% \end{macrocode} +% +% \begin{macro}{\@@_m@th:, \m@th} +% Handle non-math use of math mode. At present nesting isn't supported as +% \cs{m@th} pops up in a few places that \emph{are} math mode! +% \begin{macrocode} +\cs_new_eq:NN \@@_m@th: \m@th +\cs_gset_protected:Npn \m@th + { + \bool_set_true:N \l_@@_collected_bool + \@@_m@th: + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Modifying \pkg{amsmath}} +% +% \begin{macro}{\@@_amsmath_align@:nn} +% \begin{macro} +% { +% \@@_amsmath_gather@:n , +% \@@_amsmath_multline@:n +% } +% \begin{macro}{\align@} +% \begin{macro}{\gather@, \multline@} +% Mark up all of the display environments as the content is captured anyway. +% We then use an internal macro in each environment type to insert the +% processing code. Each of these is slightly different, so we cannot use a +% simple loop here. The test for \cs{split@tag} is required as the +% \texttt{split} environment internally uses \texttt{gather} \emph{when not +% within an \pkg{amsmath}} environment, for example inside \texttt{equation}. +% Without the precaution, we'd get two copies of the grabbed math, the second +% of which would start with \cs{split@tag}. +% \begin{macrocode} + + + +\tl_gput_right:Nn \@kernel@before@begindocument { +% +\renewenvironment{gather*}{% + \start@gather\st@rredtrue +} +{% +% this redirection doesn't work if we alter "gather"! + % \endgather +% so replace it with its real meaning + \math@cr \black@\totwidth@ \egroup + $$\ignorespacesafterend +} +% \end{macrocode} +% +% \begin{macrocode} +\def\common@align@ending { + \math@cr \black@\totwidth@ + \egroup + \ifingather@ + \restorealignstate@ + \egroup + \nonumber + \ifnum0=`{\fi\iffalse}\fi + \else + $$% + \fi + \ignorespacesafterend +} +\renewenvironment{alignat}{% + \start@align\z@\st@rredfalse +}{% + \common@align@ending +} +\renewenvironment{alignat*}{% + \start@align\z@\st@rredtrue +}{% + \common@align@ending +} +\renewenvironment{xalignat}{% + \start@align\@ne\st@rredfalse +}{% + \common@align@ending +} +\renewenvironment{xalignat*}{% + \start@align\@ne\st@rredtrue +}{% + \common@align@ending +} +\renewenvironment{xxalignat}{% + \start@align\tw@\st@rredtrue +}{% + \common@align@ending +} +\renewenvironment{align}{% + \start@align\@ne\st@rredfalse\m@ne +}{% + \common@align@ending +} +\renewenvironment{align*}{% + \start@align\@ne\st@rredtrue\m@ne +}{% + \common@align@ending +} +\renewenvironment{flalign}{% + \start@align\tw@\st@rredfalse\m@ne +}{% + \common@align@ending +} +\renewenvironment{flalign*}{% + \start@align\tw@\st@rredtrue\m@ne +}{% + \common@align@ending +} +% +\renewenvironment{multline*}{\start@multline\st@rredtrue} +{% + \iftagsleft@ \@xp\lendmultline@ \else \@xp\rendmultline@ \fi + \ignorespacesafterend +} +% \end{macrocode} +% Also for "false?" +% \begin{macrocode} +\def\measuring@true{\let\ifmeasuring@\iftrue\tag_stop:} +% \end{macrocode} +% +% \begin{macrocode} +% + \math_register_halign_env:nn {align}{} + \math_register_halign_env:nn {align*}{} + \math_register_halign_env:nn {flalign}{} + \math_register_halign_env:nn {flalign*}{} + \math_register_halign_env:nn {gather}{} + \math_register_halign_env:nn {gather*}{} + \math_register_halign_env:nn {multline}{} + \math_register_halign_env:nn {multline*}{} + \math_register_halign_env:nn {xalignat}{} + \math_register_halign_env:nn {xalignat*}{} + \math_register_halign_env:nn {xxalignat}{} + % + \@namedef{maketag @ @ @} #1{% +% \typeout{--->maketag @ @ @} + \ifmeasuring@ + \hbox{\m@th\normalfont#1}% + \else + \tagmcend \tagstructbegin{tag=Lbl}% + \tagmcbegin{tag=Lbl}% + \hbox{\m@th\normalfont#1}% + \tagmcend \tagstructend \tagmcbegin{}% + \fi + } +% \end{macrocode} +% +% \begin{macrocode} + \def\intertext@{% + \def\intertext##1{% + \ifvmode\else\\\@empty\fi + \noalign{% +% we have to flip the sign on the skip because we flipped it on the outside + \penalty\postdisplaypenalty\vskip-\belowdisplayskip + \vbox{ +% \end{macrocode} +% Stop tagging when measuring: +% \begin{macrocode} + \ifmeasuring@\tag_stop:\fi + \normalbaselines + \ifdim\linewidth=\columnwidth + \else \parshape\@ne \@totalleftmargin \linewidth + \fi +% \end{macrocode} +% End the previous mc:\fmi{if we use 2 levels of formulas this would +% need changing} +% \begin{macrocode} + \tag_mc_end_push: +% \end{macrocode} +% We are already in a par so we change now to Span:\fmi{not true any longer} +% \begin{macrocode} + \tagpdfsetup{paratag=P}% + \tagpdfparaOn + \noindent\ignorespaces##1\par +% \end{macrocode} +% Restart the MC +% \begin{macrocode} + \tag_mc_begin_pop:n{}}% + \penalty\predisplaypenalty\vskip\abovedisplayskip% + }% + } + } +% \end{macrocode} +% +% \begin{macrocode} +\@namedef{math@cr @ @ @ gather}{% + \ifst@rred\nonumber\fi + &\relax + \make@display@tag +% + \maybestartnewformulatag +% + \ifst@rred\else\global\@eqnswtrue\fi + \global\advance\row@\@ne + \cr +} +% \end{macrocode} +% +% \begin{macrocode} +\@namedef{math@cr @ @ @ align}{% + \ifst@rred\nonumber\fi + \if@eqnsw \global\tag@true \fi + \global\advance\row@\@ne + \add@amps\maxfields@ + \omit + \kern-\alignsep@ + \iftag@ + \setboxz@h{\@lign\strut@{\make@display@tag}}% + \place@tag + \fi +% + \maybestartnewformulatag +% + \ifst@rred\else\global\@eqnswtrue\fi + \global\lineht@\z@ + \cr +} +% \end{macrocode} +% +% \begin{macrocode} +\def\restore@math@cr{\@namedef{math@cr @ @ @}{ +% + \maybestartnewformulatag +% + \cr}} +\restore@math@cr +% \end{macrocode} +% +% \begin{macrocode} +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% + +% \begin{macro}{} +% +% \begin{macrocode} +\cs_new:Npn \@@_split_at_nl_first:w #1 \\ #2 \\ #3 \s_stop + { + \quark_if_nil:nTF {#2} + { {#1} { } } + { + \@@_split_chk_if_begin:ww #1 \begin \q_nil \s_mark + #2 \\ #3 \s_stop + } + } +\cs_new:Npn \@@_split_chk_if_begin:ww #1 \begin #2 #3 \s_mark + #4 \\ \q_nil \\ \s_stop + { + \quark_if_nil:nTF {#2} + { {#1} {#4} } + { + \exp_after:wN \@@_split_collect_one_end:w + \@@_split_cleanup_begin_q_nil:w #1 \begin{#2} #3 \\ #4 \s_stop + { } { 1 } + } + } +\cs_new:Npn \@@_split_cleanup_begin_q_nil:w #1 \begin \q_nil {#1} +\cs_new:Npn \@@_split_collect_one_end:w #1 \end #2 #3 \s_stop #4 #5 + { + \exp_args:Nf \@@_split_check_count_begins:nnnn + { \@@_split_count_begins:n { #4 #1 } } {#5} + { #4 #1 \end{#2} } {#3} + } +\cs_new:Npn \@@_split_count_begins:n #1 + { \int_eval:n { 0 \@@_split_count_begins:w #1 \begin \q_nil } } +\cs_new:Npn \@@_split_count_begins:w #1 \begin #2 + { \quark_if_nil:nF {#2} { +1 \@@_split_count_begins:w } } +\cs_new:Npn \@@_split_check_count_begins:nnnn #1 #2 #3 #4 + { + \int_compare:nNnTF {#1} = {#2} + { + \exp_last_unbraced:Nf \@@_split_final_cleanup:nn + { \split:n { \@@_split_guard:n {#3} #4 } } + } + { + \exp_args:No \use_ii_i:nn + { \exp_after:wN { \int_value:w \int_eval:n { #2 + 1 } } } + { \@@_split_collect_one_end:w #4 \s_stop {#3} } + } + } +\cs_new:Npn \@@_split_final_cleanup:nn #1 #2 + { + \exp:w \@@_split_final_cleanup:w #1 + \@@_split_guard:n \q_nil \s_mark { } + {#2} + } +\cs_new:Npn \@@_split_final_cleanup:w #1 \@@_split_guard:n #2 #3 \s_mark #4 + { + \quark_if_nil:nTF {#2} + { \exp_end: { #4 #1 } } + { \@@_split_final_cleanup:w #3 \s_mark { #4 #1 #2 } } + } +\NewDocumentCommand \splitnl { mm +m } + { + \tl_set:Nf \l_tmpa_tl { \split:n {#3} } + \show \l_tmpa_tl + \exp_after:wN \__splitnl_aux:nnNN \l_tmpa_tl #1 #2 + } + + +\cs_new:Npn \split:n #1 { + \@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop } + +\cs_new:Npn \@@_split_at_nl:NN #1#2 { + \tl_set:Nf \l_tmpa_tl { + \exp_after:wN \@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop } + \exp_after:wN \@@_split_at_nl_aux:nnNN \l_tmpa_tl #1 #2 +} + +\cs_new_protected:Npn \@@_split_at_nl_aux:nnNN #1 #2 #3 #4 + { + \tl_gset:Nn #4 {#1} + \tl_gset:Nn #3 {#2} +} + +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\maybestartnewformulatag} +% +% \begin{macrocode} + +\newif\if@subformulas +\tl_new:N \result + +\cs_new_protected:Npn\grabaformulapartandstart { + \@@_split_at_nl:NN \g__math_grabbed_math_tl \result + \typeout{====>first-result=\meaning\result} + \typeout{====>first-tmpmathcontent=\meaning\g__math_grabbed_math_tl} + \tl_if_empty:NTF \g__math_grabbed_math_tl + { + \typeout{====>formula~ has~ no~ subparts} + \global\@subformulasfalse + } + { + \typeout{====>formula~ has~ subparts} + \global\@subformulastrue + \edef\resulttitle{\g__math_grabbed_env_tl\space (part)} + \tagstructbegin{tag=Formula, +% \end{macrocode} +% For now we don't put anything in /alt or /ActualText on subformulas +% \begin{macrocode} +% alt=\result, + title-o=\resulttitle + } + } + \tagmcbegin{} +} + +\cs_new_protected:Npn\grabaformulapartandmayberestart { + \@@_split_at_nl:NN \g__math_grabbed_math_tl \result + \typeout{====>result=\meaning\result} + \typeout{====>tmpmathcontent=\meaning\g__math_grabbed_math_tl} +% \tl_if_empty:NTF \g__math_grabbed_math_tl +% { +% \typeout{====>tmpmathcontent=empty} +% } +% { +% \typeout{====>tmpmathcontent=not-empty} + \edef\resulttitle{\g__math_grabbed_env_tl\space (part)} + \tagstructbegin{tag=Formula, + alt=\result, + title-o=\resulttitle + } +% } + \tagmcbegin{} +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macrocode} +\def\maybestartnewformulatag { +\if@subformulas + \ifmeasuring@\else +% + \tl_if_empty:NF \g__math_grabbed_math_tl + { + \tagmcend + \tagstructend + \grabaformulapartandmayberestart + } + \fi +\fi +} +% \end{macrocode} +% +% The breqn packages changes catcodes and that isn't yet covered +% by our mechanism. +% \begin{macrocode} +%\AddToHook{package/breqn/after}{ +% \typeout{===>~ in~ hook} +% \math_register_halign_env:nn {dmath}{} +% \math_register_halign_env:nn {dgroup*}{} +%} +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOff +% \end{macrocode} +% +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \begin{macrocode} +%</kernel> +% \end{macrocode} +% +% \Finale +% +% + diff --git a/macros/latex/required/latex-lab/latex-lab-mathtagging.pdf b/macros/latex/required/latex-lab/latex-lab-mathtagging.pdf Binary files differnew file mode 100644 index 0000000000..6f6df64408 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-mathtagging.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-mathtools.dtx b/macros/latex/required/latex-lab/latex-lab-mathtools.dtx new file mode 100644 index 0000000000..c3f43243b1 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-mathtools.dtx @@ -0,0 +1,223 @@ +% \iffalse meta-comment +% +%% File: latex-lab-mathtools.dtx +% +% Copyright (C) 2022,2023 The LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-amsmath.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \texttt{latex-lab-mathtools} code\thanks{}} +% \author{\LaTeX{} Project} +% +% \maketitle +% +% \newcommand\fmi[1]{\begin{quote} TODO: \itshape #1\end{quote}} +% \newcommand\NEW[1]{\marginpar{\mbox{}\hfill\fbox{New: #1}}} +% \providecommand\class[1]{\texttt{#1.cls}} +% \providecommand\pkg[1]{\texttt{#1}} +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% This file implements adaptions to the \pkg{mathtools} package needed for +% the tagging project. +% +% \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } +% +% \section{The Implementation} +% +% \begin{macrocode} +%<@@=math> +% \end{macrocode} +% +% \begin{macrocode} +%<*kernel> +% \end{macrocode} +% +% \subsection{File declaration} +% \begin{macrocode} +\ProvidesFile{latex-lab-mathtools.ltx} + [2023-01-05 v0.1a mathtools adaptions] +% \end{macrocode} +% \subsection{Tagpdf support} +% To make the code independent from tagging being loaded and active +% we load the \pkg{tagpdf-base} package: +% +% \begin{macrocode} +\RequirePackage{tagpdf-base} +% \end{macrocode} +% +% \subsection{\cs{shortintertext}} +% Similar to the \cs{intertext} command from amsmath, +% \cs{shortintertext} errors with active tagging as it is processed twice +% which leads to duplicated structures. +% The fix is similar but is complicated as \pkg{mathtools} defines two version (and +% an additional \cs{intertext} version) and package options to switch between the variants. +% +% At first we redefine all the internal commands +% \begin{macrocode} +\ExplSyntaxOn +\tl_new:N\l_@@_mathtools_init_tl +\AddToHook{package/mathtools/after} + {% + \cs_if_eq:NNTF\intertext@ \MT_intertext: + { + \tl_set:Nn \l_@@_mathtools_init_tl {\MT_orig_intertext_false:} + } + { + \tl_set:Nn \l_@@_mathtools_init_tl {\MT_orig_intertext_true:} + } + \cs_if_eq:NNTF\shortintertext@ \MT_shortintertext:n + { + \tl_put_right:Nn \l_@@_mathtools_init_tl + {\MT_orig_shortintertext_false:} + } + { + \tl_put_right:Nn \l_@@_mathtools_init_tl + {\MT_orig_shortintertext_true:} + } + \def\MT_intertext: {% + \def\intertext##1{% + \ifvmode\else\\\@empty\fi + \noalign{% + \penalty\postdisplaypenalty\vskip\belowdisplayskip + \vskip-\lineskiplimit % CCS + \vskip\normallineskiplimit % CCS + \vskip\l_MT_above_intertext_sep + \vbox{% +% \end{macrocode} +% Stop tagging when measuring: +% \begin{macrocode} + \ifmeasuring@\tag_stop:\fi + \normalbaselines + \ifdim + \ifdim\@totalleftmargin=\z@ + \linewidth + \else + -\maxdimen + \fi + =\columnwidth + \else \parshape\@ne \@totalleftmargin \linewidth + \fi +% \end{macrocode} +% End the previous mc: +% \begin{macrocode} + \tag_mc_end_push: +% \end{macrocode} +% We are already in a par so we change now to Span: +% \begin{macrocode} + \tagpdfsetup{paratag=Span} + \noindent\ignorespaces##1\par +% \end{macrocode} +% Restart the MC +% \begin{macrocode} + \tag_mc_begin_pop:n{}}% + \penalty\predisplaypenalty\vskip\abovedisplayskip% + \vskip-\lineskiplimit % CCS + \vskip\normallineskiplimit % CCS + \vskip\l_MT_below_intertext_sep + }% + }% + \MH_let:NwN \shortintertext \shortintertext@ + } +% \end{macrocode} +% \begin{macrocode} + \def\MT_orig_shortintertext:n #1{% + \ifvmode\else\\\@empty\fi + \noalign{% + \penalty\postdisplaypenalty\vskip\abovedisplayshortskip + \vbox{% + \ifmeasuring@\tag_stop:\fi + \normalbaselines + \MH_if_dim:w + \MH_if_dim:w \@totalleftmargin=\z@ + \linewidth + \MH_else: + -\maxdimen + \MH_fi: + =\columnwidth + \MH_else: + \parshape\@ne \@totalleftmargin \linewidth + \MH_fi: + \tag_mc_end_push: + \tagpdfsetup{paratag=Span} + \noindent\ignorespaces#1\par + \tag_mc_begin_pop:n{}} + \penalty\predisplaypenalty\vskip\abovedisplayshortskip% + }% + } + + \def\MT_shortintertext:n #1{% + \ifvmode\else\\\@empty\fi + \noalign{% + \penalty\postdisplaypenalty\vskip\abovedisplayshortskip + \vskip-\lineskiplimit + \vskip\normallineskiplimit + \vskip\l_MT_above_shortintertext_sep + \vbox{% + \ifmeasuring@\tag_stop:\fi + \normalbaselines + \MH_if_dim:w + \MH_if_dim:w \@totalleftmargin=\z@ + \linewidth + \MH_else: + -\maxdimen + \MH_fi: + =\columnwidth + \MH_else: + \parshape\@ne \@totalleftmargin \linewidth + \MH_fi: + \tag_mc_end_push: + \tagpdfsetup{paratag=Span} + \noindent\ignorespaces#1\par + \tag_mc_begin_pop:n{}}% + \penalty\predisplaypenalty\vskip\abovedisplayshortskip% + \vskip-\lineskiplimit + \vskip\normallineskiplimit + \vskip\l_MT_below_shortintertext_sep + }% + } + +% \end{macrocode} +% end hook +% \begin{macrocode} + \l_@@_mathtools_init_tl +} +\ExplSyntaxOff +% \end{macrocode} +% +% \begin{macrocode} +%</kernel> +% \end{macrocode} +% +% \Finale +% diff --git a/macros/latex/required/latex-lab/latex-lab-mathtools.pdf b/macros/latex/required/latex-lab/latex-lab-mathtools.pdf Binary files differnew file mode 100644 index 0000000000..5a001d442d --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-mathtools.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-minipage.dtx b/macros/latex/required/latex-lab/latex-lab-minipage.dtx new file mode 100644 index 0000000000..00b1d649a1 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-minipage.dtx @@ -0,0 +1,202 @@ +% \iffalse meta-comment +% +%% File: latex-lab-minipage.dtx (C) Copyright 2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-minipage.dtx} +\end{document} +%</driver> +% +% \fi +% + +\def\ltlistsversion{v0.81} +\def\ltlistsdate{2023/05/10} + +% +% \title{The \textsf{latex-lab-minipage} package\\ +% Changes related to the tagging of minipage and parbox} +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{\ltlistsversion\ \ltlistsdate} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \section{Introduction} +% +% How to tag minipages and parboxes is still under discussion. +% But as they start and contain paragraphs it is clear that +% hooks are needed to interrupt and restart the tagging. +% +% The tagging added is currently quite simple minded. See the todo-testfiles and the +% code comments for some open points. +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \section{Implementation} +% \begin{macrocode} +\ProvidesExplPackage {latex-lab-testphase-minipage} {2023-05-10} {0.81} + {Code related to the tagging of minipages and parboxes} +% \end{macrocode} +% + +% \subsection{Provide the kernel hooks} +% [kernel?] +% We need to check/set the status before the +% initial \cs{leavevmode} to decide how to handle the structure. +% Perhaps the same command will work for both? +% \begin{macrocode} +\def\@kernel@init@minipage{} +\def\@kernel@init@parbox{} +% \end{macrocode} +% We need a few hooks. +% \begin{macrocode} +\def\@kernel@before@minipage{} +\def\@kernel@after@minipage{} +\def\@kernel@before@parbox{} +\def\@kernel@after@parbox{} +% \end{macrocode} +% +% \subsection{Patch minipage} +% [kernel?] +% The begin hook is inserted in \cs{@iiiminipage} +% \begin{macrocode} +\def\@iiiminipage#1#2[#3]#4{% +% \end{macrocode} +% Before switching to hmode we insert a hook. It is currently unused +% but could for example check if we are in vmode and change the following +% paragraph tag. +% \begin{macrocode} + \@kernel@init@minipage + \leavevmode + \@pboxswfalse + \setlength\@tempdima{#4}% + \def\@mpargs{{#1}{#2}[#3]{#4}}% +% \end{macrocode} +% insert the hook +% \begin{macrocode} + \@kernel@before@minipage% new + \setbox\@tempboxa\vbox\bgroup + \color@begingroup + \hsize\@tempdima + \textwidth\hsize \columnwidth\hsize + \@parboxrestore + \def\@mpfn{mpfootnote}\def\thempfn{\thempfootnote}\c@mpfootnote\z@ + \let\@footnotetext\@mpfootnotetext + \let\@listdepth\@mplistdepth \@mplistdepth\z@ + \@minipagerestore + \@setminipage} +% \end{macrocode} +% And a hook at the end +% \begin{macrocode} +\def\endminipage{% + \par + \unskip + \ifvoid\@mpfootins\else + \vskip\skip\@mpfootins + \normalcolor + \footnoterule + \unvbox\@mpfootins + \fi + \@minipagefalse %% added 24 May 89 + \color@endgroup + \egroup +% \end{macrocode} +% as the parbox command is called, we must prevent that it adds its additional +% tagging commands: +% \begin{macrocode} + \tag_stop:n{minipage} + \expandafter\@iiiparbox\@mpargs{\unvbox\@tempboxa}% + \tag_start:n{minipage} + \@kernel@after@minipage%new end ... + } +% \end{macrocode} +% +% And similar for \cs{parbox} +% \begin{macrocode} +\long\def\@iiiparbox#1#2[#3]#4#5{% + \@kernel@init@parbox + \leavevmode + \@pboxswfalse + \setlength\@tempdima{#4}% + \@kernel@before@parbox% new + \@begin@tempboxa\vbox{\hsize\@tempdima\@parboxrestore#5\@@par}% + \ifx\relax#2\else + \setlength\@tempdimb{#2}% + \edef\@parboxto{to\the\@tempdimb}% + \fi + \if#1b\vbox + \else\if #1t\vtop + \else\ifmmode\vcenter + \else\@pboxswtrue $\vcenter + \fi\fi\fi + \@parboxto{\let\hss\vss\let\unhbox\unvbox + \csname bm@#3\endcsname}% + \if@pboxsw \m@th$\fi + \@end@tempboxa% + \@kernel@after@parbox%new end + } +% \end{macrocode} +% +% \subsection{Tagging commands} +% +% \begin{macrocode} +\tl_new:N \l__ltboxes_tag_tl +\tl_set:Nn \l__ltboxes_tag_tl {Div} +\cs_set_protected:Npn\@kernel@before@minipage + { +% \end{macrocode} +% As there was a \cs{leavevmode} before that is a P/text open that we have to close. +% \begin{macrocode} + \tag_mc_end_push:\tag_struct_end: +% \end{macrocode} +% TODO: the P can be further up, we need a proper method to test and handle this. +% \begin{macrocode} + \tag_struct_begin:n{tag=\l__ltboxes_tag_tl}} +\cs_set_protected:Npn\@kernel@after@minipage + {\tag_struct_end:\tag_struct_begin:n{tag=\l__tag_para_tag_tl}\tag_mc_begin_pop:n{}} +\cs_set_protected:Npn\@kernel@before@parbox + {\tag_mc_end_push:\tag_struct_end:\tag_struct_begin:n{tag=\l__ltboxes_tag_tl}} +\cs_set_protected:Npn\@kernel@after@parbox + {\tag_struct_end:\tag_struct_begin:n{tag=\l__tag_para_tag_tl}\tag_mc_begin_pop:n{}} +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} + +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{minipage-latex-lab-testphase.ltx} + [2022-10-26 v0.8 code related to the tagging of sectioning commands] +\RequirePackage{latex-lab-testphase-minipage} +%</latex-lab> +% \end{macrocode} diff --git a/macros/latex/required/latex-lab/latex-lab-minipage.pdf b/macros/latex/required/latex-lab/latex-lab-minipage.pdf Binary files differnew file mode 100644 index 0000000000..8660ffa7ab --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-minipage.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-new-or-1.dtx b/macros/latex/required/latex-lab/latex-lab-new-or-1.dtx new file mode 100644 index 0000000000..ef799e813c --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-new-or-1.dtx @@ -0,0 +1,159 @@ +% \iffalse meta-comment +% +%% File: latex-lab-new-or-1.dtx (C) Copyright 2020-2023 Frank Mittelbach +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +%<*driver> +\documentclass{l3doc} + +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-new-or-1.dtx} +\end{document} +%</driver> +% +% \fi +% +% \providecommand\hook[1]{\texttt{#1}} +% +% +% +% \title{Temporary output patches for tagging and better link support} +% \author{Frank Mittelbach \and Ulrike Fischer} +% +% \maketitle +% +% \section{Introduction} +% +% This file contains a few patches of internal \LaTeX{} commands +% to support paragraph tagging across +% page boundaries (in \pdfTeX) and improve the behaviour of links across page breaks. +% +% Until this get properly integrated with the kernel code this has +% to be taken as a prototype and code, interfaces as well as +% behavior may change without notice and certainly without any +% backwards compatibility! +% +% +% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } +% +% +% \section{The Implementation} +% \begin{macrocode} +%<*code> +% \end{macrocode} +% +% \begin{macrocode} +\ProvidesPackage{latex-lab-testphase-new-or-1} + [2022-11-94 v0.1a Temporary output patches for tagging and better link support] +\RequirePackage{etoolbox} +% \end{macrocode} +% +% +% \subsection{Patching the OR} +% This adds hooks around header and footer, in \cs{@makecol} and in multicol. +% At first initialize some of the hooks. We use providecommand to avoid problems if +% the kernel changes here and provides them directly. +% \begin{macrocode} +\providecommand\@kernel@before@head{} +\providecommand\@kernel@before@foot{} +\providecommand\@kernel@after@head{} +\providecommand\@kernel@after@foot{} +\providecommand\@mult@ptagging@hook{}% multicol +% \end{macrocode} +% +% \begin{macrocode} + +\patchcmd\@outputpage + {\vfil\color@hbox\normalcolor\hb@xt@\textwidth{\@thehead}\color@endbox} + {\vfil\@kernel@before@head\color@hbox\normalcolor\hb@xt@\textwidth{\@thehead}\color@endbox\@kernel@after@head} + {\typeout{Patching header in \string\@outputpage}}{\PATCHerror } + + +\patchcmd\@outputpage + {\color@hbox\normalcolor\hb@xt@\textwidth{\@thefoot}\color@endbox} + {\@kernel@before@foot\color@hbox\normalcolor\hb@xt@\textwidth{\@thefoot}\color@endbox\@kernel@after@foot} + {\typeout{Patching footer in \string\@outputpage}}{\PATCHerror } +% \end{macrocode} +% +% \begin{macro}{\@makecol} +% We have to patch \cs{@makecol} in two places: +% \begin{itemize} +% \item +% update 255 up front to add missing tmb/tme if necessary +% \item +% update the \cs{footins} stream if that one got split +% \end{itemize} +% +% We patch \cs{@makecol}, if new-or-2 is loaded too it will overwrite that again. +% \begin{macrocode} + \providecommand\@kernel@before@footins{} + \providecommand\@kernel@before@cclv{} + + \patchcmd\@makecol + {\vskip\skip\footins} + {\vskip\skip\footins\@kernel@before@footins} + {\typeout{Patching \string\@makecol\space for tagging}}{\PATCHerror } + +%for some reason patching with etoolbox only works in this order ... + + \pretocmd\@makecol{\@kernel@before@cclv} + {\typeout{Patching \string\@makecol\space for tagging}}{\PATCHerror } +% \end{macrocode} +% \end{macro} +% +% \subsection{\pkg{multicol} adjustments} +% +% The patches for pkg{multicol} are fairly minimal: +% \begin{itemize} +% \item At the start of the environment anything already on the +% page is picked up and stored in \cs{partial@page}, we may need to add +% a TMB to that (it should have a proper TME). This has to happen +% in the \enquote{main} stream context. +% \item +% \item +% \end{itemize} +% +% \begin{macrocode} +\AddToHook{package/multicol/after} + {% multicol needs later loading +% \end{macrocode} +% +% \begin{macrocode} + \patchcmd\page@sofar + {\global\dimen\tw@\dp\z@}% + {% + \global\dimen\tw@\dp\z@ + \@mult@ptagging@hook + }% + {\typeout{Patching \string\page@sofar\space for tagging}}{\PATCHerror}% +} +% \end{macrocode} +% +% \subsection{Interrupt hooks} +% This requires the l3pdfannot module! +% We add the code here and not in hyperref, as it should also work with links +% created directly with the l3pdfannot commands. The file is only +% loaded by the pdfmanagement, so no need to test if the commands exist. +% \begin{macrocode} +\ExplSyntaxOn +\def\@kernel@before@head{\pdfannot_link_off:} +\def\@kernel@before@foot{\pdfannot_link_off:} +\def\@kernel@after@head {\pdfannot_link_on:} +\def\@kernel@after@foot {\pdfannot_link_on:} +\ExplSyntaxOff +% \end{macrocode} +% +% \begin{macrocode} +%</code> +% \end{macrocode} +% +% \Finale +% diff --git a/macros/latex/required/latex-lab/latex-lab-new-or-1.pdf b/macros/latex/required/latex-lab/latex-lab-new-or-1.pdf Binary files differnew file mode 100644 index 0000000000..d5576ad3c9 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-new-or-1.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-new-or.dtx b/macros/latex/required/latex-lab/latex-lab-new-or-2.dtx index 08b58a7286..74d56d687f 100644 --- a/macros/latex/required/latex-lab/latex-lab-new-or.dtx +++ b/macros/latex/required/latex-lab/latex-lab-new-or-2.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: latex-lab-new-or.dtx +%% File: latex-lab-new-or-2.dtx % Copyright (C) 2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the @@ -22,14 +22,14 @@ \EnableCrossrefs \CodelineIndex \begin{document} - \DocInput{latex-lab-new-or.dtx} + \DocInput{latex-lab-new-or-2.dtx} \end{document} %</driver> % % \fi % % -% \title{The \texttt{latex-lab-new-or} code\thanks{}} +% \title{The \texttt{latex-lab-testphase-new-or-2} code\thanks{}} % \author{Frank Mittelbach, \LaTeX{} Project} % % \maketitle @@ -128,8 +128,8 @@ % % \subsection{File declaration} % \begin{macrocode} -\ProvidesFile{latex-lab-new-or.ltx} - [2022-03-09 v0.1b changes to the output routine] +\ProvidesPackage{latex-lab-testphase-new-or-2} + [2022-11-04 v0.1c changes to the output routine] % \end{macrocode} % \subsection{\cs{@makecol} reimplementation} % diff --git a/macros/latex/required/latex-lab/latex-lab-new-or.pdf b/macros/latex/required/latex-lab/latex-lab-new-or-2.pdf Binary files differindex 279e14f1a3..1a1ce038d1 100644 --- a/macros/latex/required/latex-lab/latex-lab-new-or.pdf +++ b/macros/latex/required/latex-lab/latex-lab-new-or-2.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-sec.dtx b/macros/latex/required/latex-lab/latex-lab-sec.dtx new file mode 100644 index 0000000000..5df3803b54 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-sec.dtx @@ -0,0 +1,819 @@ +% \iffalse meta-comment +% +%% File: latex-lab-sec.dtx (C) Copyright 2022-2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-sec.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \textsf{latex-lab-sec} package\\ +% Changes related to the tagging of sectioning commands} +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{v0.83 2023-06-07} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% The following code implements a first draft for the tagging of sectioning commands. +% \end{abstract} +% +% \section{Limitations} +% +% Sectioning commands are in not defined by the format but by the classes. +% Their implementation vary: some are defined with the help of \cs{@startsection}, +% some are like \cs{chapter} handcrafted, +% some build with the help of extension packages or as in the KOMA classes +% with class code that extends the \cs{@startsection} functionality. +% +% The following code can therefore currently be used \emph{only} with the standard classes +% or with classes which do not overwrite the changed definitions. +% +% +% +% \section{Introduction} +% +% Tagging of sectioning commands consist of two parts: +% +% \begin{itemize} +% \item The heading/title text of the section should be surrounded by a +% heading tag, typically \texttt{Hn} with some value of \texttt{n}. +% The number of the section command can optionally be put in a \texttt{Lbl}. +% The number of the \texttt{Hn} tag should reflect the \enquote{natural} level. +% So in an article \cs{section} will use \texttt{H1}, in a book \cs{chapter} will use +% \texttt{H1} and \cs{section} \texttt{H2}. +% Titles of \cs{part} are a bit out of this system as they are normally +% not part of the hierarchy: often only some chapters are grouped under a part. +% Their title is therefore tagged as \texttt{Title}. +% \item +% The whole section should normally be surrounded by +% a \texttt{Sect} tag. Parts should be surrounded by \texttt{Part}. +% It is a bit unclear if the headings should be inside or outside of these +% structures---the best practice guide puts them outside---but on the whole +% it sounds more logical to group the heading with the text inside the \texttt{Sect}. +% For the part this is actually required, as there can be only one \texttt{Title} +% in a structure, so the part title can't be at the same level as the +% document \texttt{Title}. +% +% Starting such an enclosing \texttt{Sect} structure is rather easy, +% but closing it requires code in various place, +% for example the commands \cs{mainmatter}, \cs{backmatter}, +% \cs{frontmatter} and \cs{appendix} should typically close everything. +% Following sectioning commands should close all previous structures +% with a level equal or higher than their own level. +% \end{itemize} +% +% \section{Technical details and problems} +% +% The implementation has to take care of various details. +% +% \begin{itemize} +% +% \item As sections in \LaTeX{} are not environments, the +% \texttt{<Sect>} structures can be wrongly nested with other structures. For example +% if a document puts a sectioning command into a list or a trivlist or +% a minipage then it can no longer close previous \texttt{<Sect>} structures correctly. +% The problem can be detected by checking the structure stack +% and a warning can be issued, but the author then has to close the structures +% manually before the list or minipage. +% +% Thus there have to be user interfaces to handle such cases. +% It should also be possible not to create all the \texttt{<Sect>} structures +% automatically but to tag only the headings so that the author can handle special +% cases manually. +% +% \item If hyperref is used, targets for links should be inserted, either with +% \cs{refstepcounter} or manually with \cs{MakeLinkTarget}. These targets must be +% in the correct structure for the structure destinations. They replace some +% of the current patches in hyperref. +% +% \item With lualatex the mc-commands set attributes \emph{locally}, so the +% commands must be at the right grouping level. +% \end{itemize} +% +% \subsection{Funktions and keys} +% +% \begin{function}{\tag_tool:n,\tagtool} +% +% \end{function} +% +% \subsection{TODO} +% +% \begin{itemize} +% \item A dedicated command to close a sectioning unit should be provided. +% +% \item A dedicated command to open a sectioning unit should be provided too. +% +% \item It should also be possible to suppress the sectioning unit in sectioning commands +% to allow e.g. to put an epigraph or similar in front. +% +% \item The number in \cs{part} and \cs{chapter} is currently not correctly +% tagged as a \texttt{Lbl} as this requires to redefine the internal (class dependant) +% commands too. +% +% \end{itemize} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \section{Implementation} +% \begin{macrocode} +\ProvidesExplPackage {latex-lab-testphase-sec} {2023-05-20} {0.81} + {Code related to the tagging of sectioning commands} +% \end{macrocode} +% +% \subsection{Surrounding by \texttt{Sect} structures} +% We use a stack to record the levels of the open \texttt{Sect}. The first item +% has level -100. A sectioning command will take a record from the stack. If its level is +% greater or equal it closes this structure and takes the next record from the stack. +% If the record has a smaller level then it puts it back and stops. +% The stack is compared with the main structure stack, if they don't match +% it means we can't safely close the \texttt{Sect} and so we issue a warning +% and do nothing. +% +% \subsubsection{Loading general kernel changes} +% [kernel?] +% Also loaded in the toc-tagging code. +% \begin{macrocode} +\RequirePackage{latex-lab-kernel-changes} +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} +% \subsubsection{Glyphtounicode improvements} +% +% As lualatex runs with legacy encodings in the test files, we enable and +% load glyphtounicode. For the math we load additional definitions. +% +% \begin{macrocode} +%<*kernelchange> +\ifdefined\directlua + \pdfvariable gentounicode =1 + \protected\def\pdfglyphtounicode {\pdfextension glyphtounicode } + \protected\edef\pdfgentounicode {\pdfvariable gentounicode} + \input{glyphtounicode} +\fi +\ifdefined\pdfglyphtounicode + \input{glyphtounicode-cmex} +\fi +%</kernelchange> +% \end{macrocode} +% +% \subsubsection{updating \cs{@currentHref}} +% [kernel?] +% +% We must ensure that manual targets (e.g. in unnumbered sections) +% correctly update \cs{@currentHref}. For this we extend the kernel definition of +% \cs{MakeLinkTarget} +% +% \begin{macrocode} +%<*kernelchange> +\ExplSyntaxOn +\int_new:N\g__kernel_target_int +\RenewDocumentCommand\MakeLinkTarget{sO{}m} + {% + \ifvmode + \special{}% + \else + \@savsf\spacefactor + \smash{}% + \spacefactor\@savsf + \fi + \IfBooleanTF {#1} + { + \tl_gset:Nx \@currentHref {#3} + } + { + \int_gincr:N\g__kernel_target_int + \tl_gset:Nx \@currentHref {target*.\int_use:N\g__kernel_target_int} + } + } +\ExplSyntaxOff +%</kernelchange> +% \end{macrocode} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% \subsubsection{Tagging commands} +% +% +% \begin{variable}{\g__tag_sec_stack_seq} +% The stack holds the tag and the level. +% \begin{macrocode} +\seq_new:N \g__tag_sec_stack_seq +\seq_gpush:Nn\g__tag_sec_stack_seq {{Document}{-100}} +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l__tag_sec_Sect_bool} +% This boolean controls if a Sect structure is opened. +% \begin{macrocode} +\bool_new:N \l__tag_sec_Sect_bool +\bool_set_true:N\l__tag_sec_Sect_bool +% \end{macrocode} +% \end{variable} + +% +% \begin{macro}{\__tag_sec_begin:nn} +% This starts a sectioning structure. +% Currently the tag is fix, either Sect or Part, depending on the level, +% but this will perhaps change. The second argument is currently unused. +% \begin{macrocode} +\cs_new_protected:Npn\__tag_sec_begin:nn #1 #2 %#1 level #2 keyval + { + \tag_struct_begin:n + { + tag= {\int_compare:nNnTF {#1}={-1}{Part}{Sect}} + ,#2 + } + \seq_gpush:Nx \g__tag_sec_stack_seq {{\g__tag_struct_tag_tl}{\int_eval:n{#1}}} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\__tag_sec_end:n} +% \begin{macrocode} +\msg_new:nnn { tag } {wrong-sect-nesting} + { + The~structure~#1~can~not~be~closed.\\ + It~is~not~equal~to~the~current~structure~#2~on~the~main~stack + } + +\cs_new_protected:Npn\__tag_sec_end:n #1 % #1 level + { + \seq_get:NN \g__tag_sec_stack_seq \l__tag_tmpa_tl + \int_compare:nNnT {#1}<{\exp_last_unbraced:NV\use_ii:nn\l__tag_tmpa_tl+1} + { + \seq_get:NN\g__tag_struct_tag_stack_seq \l__tag_tmpb_tl + \exp_args:Nee + \tl_if_eq:nnTF + {\exp_last_unbraced:NV\use_i:nn\l__tag_tmpa_tl} + {\exp_last_unbraced:NV\use_i:nn\l__tag_tmpb_tl} + { + \seq_gpop:NN \g__tag_sec_stack_seq \l__tag_tmpa_tl + \tag_struct_end: + \__tag_sec_end:n {#1} + } + { + \msg_warning:nnxx {tag}{wrong-sect-nesting} + { \exp_last_unbraced:NV\use_i:nn \l__tag_tmpa_tl } + { \exp_last_unbraced:NV\use_i:nn \l__tag_tmpb_tl } + } + } + } +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\__tag_tool_para_split:} +% Runin-sectioning command must separate the heading from the following text. +% +% \begin{macrocode} +\cs_new_protected:Npn \__tag_tool_para_split: + { + \tag_mc_end: + \tag_struct_end: + \tag_struct_begin:n{tag=\l__tag_para_tag_default_tl} + \tag_mc_begin:n{} + \__tag_setup_restore_para_default: + } +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\__tag_setup_restore_para_default:} +% We change the para tagging in the sectioning code. +% This here restores the default. Currently it only resets the +% the tag, but perhaps more will be needed later. +% \begin{macrocode} +\cs_new_protected:Npn \__tag_setup_restore_para_default: + { + \tl_set:Nn \l__tag_para_main_tag_tl {text-unit} + \tl_set_eq:NN\l__tag_para_tag_tl\l__tag_para_tag_default_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\__tag_sec_end_display:} +% \begin{macrocode} +\cs_new_protected:Npn \__tag_sec_end_display: + { + \tag_struct_end: %P = Hn + \__tag_setup_restore_para_default: + } +% \end{macrocode} +% \end{macro} +% +% Open sec structures should be closed at the end of the document. This should +% be done before tagpdf closes the Document structure. +% \begin{macrocode} +\hook_gput_code:nnn{tagpdf/finish/before}{tagpdf/sec}{\__tag_sec_end:n{-10}} +\hook_gset_rule:nnnn {tagpdf/finish/before}{tagpdf/sec}{before}{tagpdf} +% \end{macrocode} +% +% The commands \cs{mainmatter}, \cs{backmatter}, \cs{frontmatter} and +% \cs{appendix} close all \texttt{Sect} and \texttt{Part} structures. +% \begin{macrocode} +\AddToHook{cmd/frontmatter/before}{\__tag_sec_end:n{-10}} +\AddToHook{cmd/mainmatter/before} {\__tag_sec_end:n{-10}} +\AddToHook{cmd/backmatter/before} {\__tag_sec_end:n{-10}} +\AddToHook{cmd/appendix/before} {\__tag_sec_end:n{-10}} +% \end{macrocode} +% +% \subsection{Tagging tools} +% We need to provide user and package level commands +% +% \begin{macrocode} +\cs_if_free:NT \tag_tool:n + { + \cs_new_protected:Npn \tag_tool:n #1 + { + \tag_if_active:T { \keys_set:nn {tag / tool}{#1} } + } + \cs_set_eq:NN\tagtool\tag_tool:n + } +\keys_define:nn { tag / tool} + { + ,sec-start-part .code:n = + { + \bool_if:NT\l__tag_sec_Sect_bool + { + \__tag_sec_end:n {-1} + \__tag_sec_begin:nn{-1}{tag=Part} + } + \tag_struct_begin:n{tag=part,title=#1} +% \end{macrocode} +% We remap here the text-unit from the paragraph to NonStruct. +% It would be better to suppress it completly as with the other +% sectioning commands, but this would require to redefine \cs{@spart} +% and \cs{@part}, as there is the grouping, and these commands are +% all slightly different in the standard classes. So this is delayed +% to the time when sectioning commands are redefined with templates. +% \begin{macrocode} + \tl_set:Nn\l__tag_para_main_tag_tl {NonStruct} + \tl_set:Nn\l__tag_para_tag_tl {Span} + } + ,sec-stop-part .code:n = {\__tag_sec_end_display:} + ,sec-start-chapter .code:n = + { + \bool_if:NT\l__tag_sec_Sect_bool + { + \__tag_sec_end:n {0} + \__tag_sec_begin:nn{0}{tag=Sect} + } + \tag_struct_begin:n{tag=chapter,title=#1} +% \end{macrocode} +% similar to part we remap to NonStruct for now ... +% \begin{macrocode} + \tl_set:Nn\l__tag_para_main_tag_tl {NonStruct} + \tl_set:Nn\l__tag_para_tag_tl {Span} + } + ,sec-stop-chapter .meta:n = { sec-stop-part} + ,sec-start .code:n = % #1 is a name like "section" + { + \bool_if:NT\l__tag_sec_Sect_bool + { + \__tag_sec_end:n {\cs_if_exist_use:c{toclevel@#1}+0} + \__tag_sec_begin:nn {\cs_if_exist_use:c{toclevel@#1}+0}{tag=Sect} + } + \tl_set:Nn\l__tag_para_tag_tl{#1} + } + ,sec-start .value_required:n = true + ,sec-split-para .code:n = {\__tag_tool_para_split:} + ,restore-para .code:n = {\__tag_setup_restore_para_default:} + ,sec-stop .code:n = + { + \par\__tag_sec_end:n {\cs_if_exist_use:c{toclevel@#1}+0} + } + ,sec-stop .value_required:n = true + ,sec-add-grouping .bool_set:N = \l__tag_sec_Sect_bool + } +% \end{macrocode} +% +% +% \section{Sectioning commands} +% +% \subsection{\cs{part} and \cs{chapter}} +% +% \cs{part} and \cs{chapter} are defined by the classes. +% To tag them we redefine the user commands. +% This will probably break with various classes and with titlesec. +% The tagging inside relies on the para tagging. +% We do not yet use keyval in the optional argument, as this requires latex-dev +% and the naming of the keys and their key family is unclear. +% \begin{macrocode} +\AddToHook{class/after} + { + \@ifundefined{chapter} + { +% \end{macrocode} +% This redefines \cs{part} in article class. +% \begin{macrocode} + \RenewDocumentCommand\part{ s O{#3} m } + { + \if@noskipsec \leavevmode \fi + \par + \addvspace{4ex}% + \@afterindentfalse +% \end{macrocode} +% This are the tagging commands needed at the begin. They open a Part structure +% and the structure for the title of the heading. +% \begin{macrocode} + % tagging start commands + \tag_tool:n {sec-start-part=#2} + % end tagging start commands +% \end{macrocode} +% This adds a manual target if the part is unnumbered or starred. +% It replaces the hyperref patches. +% \begin{macrocode} + \bool_lazy_any:nT + { + { #1 } + { + \int_compare_p:nNn {\c@secnumdepth}<{-1} + } + } + { + \MakeLinkTarget[part]{} + } +% \end{macrocode} +% The main call to the underlying commands. +% \begin{macrocode} + \IfBooleanTF + {#1} + { \@spart {#3} } + { \@part [#2]{#3} } +% \end{macrocode} +% and now the closing command for the tagging of the title. +% \begin{macrocode} + \tag_tool:n {sec-stop-part} + } + } +% \end{macrocode} +% Redefinitions for book and report +% \begin{macrocode} + { + \RenewDocumentCommand\chapter{ s O{#3} m } + { + \if@openright\cleardoublepage\else\clearpage\fi + \thispagestyle{plain}% + \global\@topnum\z@ + \@afterindentfalse +% \end{macrocode} +% This are the tagging commands needed at the begin. They open a Sect structure +% and the structure for the title of the heading. +% \begin{macrocode} + \tag_tool:n { sec-start-chapter= #2 } +% \end{macrocode} +% This adds a manual target if the chapter is unnumbered or starred. +% It replaces the hyperref patches. +% \begin{macrocode} + \bool_lazy_any:nT + { + { #1 } + { + \int_compare_p:nNn {\c@secnumdepth}<{0} + } + { + %in book target also needed in frontmatter + \bool_lazy_and_p:nn + { \cs_if_exist_p:c { @mainmattertrue } } + { ! \legacy_if_p:n { @mainmatter } } + } + } + { + \MakeLinkTarget[chapter]{} + %todo public function for this update! + \tl_if_blank:VF \@currentHref + { + \prop_gput:Nxx \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} + } + } +% \end{macrocode} +% The main call to the underlying commands. +% \begin{macrocode} + \IfBooleanTF + {#1} + { \@schapter {#3} } + { \@chapter [#2]{#3} } +% \end{macrocode} +% and now the closing command for the tagging of the title. +% \begin{macrocode} + \tag_tool:n {sec-stop-chapter} + } +% \end{macrocode} +% and similar for \cs{part} +% \begin{macrocode} + \RenewDocumentCommand\part{ s O{#3} m } + { + \if@openright + \cleardoublepage + \else + \clearpage + \fi + \thispagestyle{plain}% + \if@twocolumn + \onecolumn + \@tempswatrue + \else + \@tempswafalse + \fi + \null\vfil +% \end{macrocode} +% This are the tagging commands needed at the begin. They open a Part structure +% and the structure for the title of the heading. +% \begin{macrocode} + \tag_tool:n {sec-start-part=#2} +% \end{macrocode} +% This adds a manual target if the part is unnumbered or starred. +% It replaces the hyperref patches. +% \begin{macrocode} + \bool_lazy_any:nT + { + { #1 } + { + \int_compare_p:nNn {\c@secnumdepth}<{-1} + } + { + %in book target also needed in frontmatter + \bool_lazy_and_p:nn + { \cs_if_exist_p:c { @mainmattertrue } } + { ! \legacy_if_p:n { @mainmatter } } + } + } + { + \MakeLinkTarget[part]{} + \tl_if_blank:VF \@currentHref + { + \prop_gput:Nxx \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} + } + } +% \end{macrocode} +% The main call to the underlying commands. +% \begin{macrocode} + \IfBooleanTF + {#1} + { \@spart {#3} } + { \@part [#2]{#3} } +% \end{macrocode} +% and now the closing command for the tagging of the title. +% \begin{macrocode} + \tag_tool:n{sec-stop-part} + } + } + } +% \end{macrocode} +% +% \subsection{Sectioning commands based on \cs{@startsection}} +% +% The tagging relies again on the para tagging: +% we simply exchange the tag name by the one given as \#1. +% This assumes that a tag with the name of the sectioning type is defined. +% We don't try to pass the title, this will be done together with +% the new keyval handling in the user command. +% +% \subsubsection{Hyperref code} +% hyperref has to insert anchors. If the sectioning is numbered this is done by +% \cs{refstepcounter} (and so in vmode). For unnumbered section hyperref +% injects the anchor in hmode before the text, it also inserts a +% kern to compensate the indent. +% +% This means that the target of numbered and unnumbered sectioning commands +% differ, both regarding the location and in relation to the +% tagging structure: The anchor from the \cs{refstepcounter} is outside of +% the structure created by the heading title if the para tags are used, +% while the other anchors are inside and so the structure destinations are different. +% +% We unify this by suppressing the anchor from the refstepcounter. +% Also we only go back if the indent is positive. +% +% At first suppress all hyperref patches related to sectioning: +% \begin{macrocode} +\def\hyper@nopatch@sectioning{} +% \end{macrocode} +% +% \begin{macro}{\@hyp@section@target@nnn} +% A simple internal command. There is no need for something public, +% as packages defining their own version of \cs{@startsection} will +% probably need something slightly different based on \cs{MakeLinkTarget}. +% \begin{macrocode} +\cs_new_protected:Npn \@hyp@section@target@nnn #1 #2 #3 %#1 optarg #2 name/counter, #3 indent + { + \makebox[0pt][l] + { + \skip_set:Nn \@tempskipa {#3} + \dim_compare:nNnF {\@tempskipa}<{0pt}{\kern-\@tempskipa} + \MakeLinkTarget#1{#2} + } + \tl_if_blank:VF \@currentHref + { + \prop_gput:Nxx \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} + } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Adaption of the heading commands} +% We add to \cs{@startsection} the commands to open the \texttt{Sect} +% structure and to change the para tag. +% +% \begin{macrocode} +\def\@startsection#1#2#3#4#5#6{% + \if@noskipsec \leavevmode \fi + \par + \@tempskipa #4\relax + \@afterindenttrue + \ifdim \@tempskipa <\z@ + \@tempskipa -\@tempskipa \@afterindentfalse + \fi + \if@nobreak + \everypar{}% + \else + \addpenalty\@secpenalty\addvspace\@tempskipa + \fi + \tag_tool:n { sec-start=#1}%new + \@ifstar + {\@ssect{#3}{#4}{#5}{#6}}% + {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}} +% \end{macrocode} +% To be able to correctly tag the number we need a special +% \cs{@hangfrom} variant. This is a bit tricky: +% As the paragraph starts after the \cs{setbox} luatex attributes +% are not set yet and numbers are unmarked if one doesn't pay attention. +% The code assumes that we are in vmode! +% \begin{macrocode} +\cs_new_protected:Npn \@kernel@tag@hangfrom #1 + { + \tagstructbegin{tag=\l__tag_para_tag_tl} + \tagstructbegin{tag=Lbl} + \setbox\@tempboxa + \hbox + { +% \end{macrocode} +% In lua mode we have to set the attributes inside the box! +% \begin{macrocode} + \bool_lazy_and:nnT + {\tag_if_active_p:} + {\g__tag_mode_lua_bool} + {\tagmcbegin{tag=Lbl}} + {#1} + } +% \end{macrocode} +% We stop tagging now, to avoid that the \cs{noindent} triggers +% the paratagging. We do not disable paratagging completely, to +% avoid that the numbering goes wrong. +% \begin{macrocode} + \tag_stop:n{hangfrom} + \hangindent \wd\@tempboxa\noindent +% \end{macrocode} +% Restart tagging and insert the box. +% \begin{macrocode} + \tag_start:n{hangfrom} + \tagmcbegin{}\box\@tempboxa\tagmcend\tagstructend\tagmcbegin{}} +% \end{macrocode} +% This command is used to tag the numbers of runin. We do not try +% to avoid the empty container from the paratagging, this would require +% more changes. +% \begin{macrocode} +\cs_new_protected:Npn \@kernel@tag@svsec + { + \tag_mc_end_push: + \tag_struct_begin:n{tag=Lbl} + \tag_mc_begin:n{} + \@svsec + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% \cs{@sect} is only changed to replace the hyperref patches +% and to use the new \cs{@kernel@tag@hangfrom} and \cs{@kernel@tag@svsec} +% \begin{macrocode} +\def\@sect#1#2#3#4#5#6[#7]#8{% + \ifnum #2>\c@secnumdepth + \def\@svsec{\@hyp@section@target@nnn{[section]}{}{#3}} + \else + \LinkTargetOff + \refstepcounter{#1}% + \LinkTargetOn + \protected@edef\@svsec{\@hyp@section@target@nnn{}{#1}{#3}\@seccntformat{#1}\relax}% + \fi + \@tempskipa #5\relax + \ifdim \@tempskipa>\z@ + \begingroup + \tagtool{para-flattened=true} % or \bool_set_true\l__tag_para_flattened_bool + #6{% + \ifnum #2>\c@secnumdepth + \@hangfrom {\hskip #3\relax\@svsec}% + \else + \@kernel@tag@hangfrom{\hskip #3\relax\@svsec}% + \fi + \interlinepenalty \@M #8\@@par}% + \endgroup + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7}% + \else + \def\@svsechd{% + #6{\hskip #3\relax + \ifnum #2>\c@secnumdepth + \@svsec + \else + \@kernel@tag@svsec + \fi #8}% + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7}}% + \fi + \@xsect{#5}} +% \end{macrocode} +% similar for \cs{@ssect} +% \begin{macrocode} +\def\@ssect#1#2#3#4#5{% + \@tempskipa #3\relax + \ifdim \@tempskipa>\z@ + \begingroup + \tagtool{para-flattened=true} + #4{% + \@hangfrom{\hskip #1\relax\@hyp@section@target@nnn{[section]}{}{#1}}% + \interlinepenalty \@M #5\@@par}% + \endgroup + \else + \def\@svsechd{#4{\hskip #1\relax\@hyp@section@target@nnn{[section]}{}{#3}\relax #5}}% + \fi + \@xsect{#3}} +% \end{macrocode} +% At last \cs{@xsect} needs code in two places. For display headings it has to +% restore the default para code, for run in headings it has to separated the +% heading from the following text. +% \begin{macrocode} +\def\@xsect#1{% + \@tempskipa #1\relax + \ifdim \@tempskipa>\z@ + \par \nobreak + \vskip \@tempskipa + \tag_tool:n {restore-para} + \@afterheading + \else + \@nobreakfalse + \global\@noskipsectrue + \everypar{% + \if@noskipsec + \global\@noskipsecfalse + {\setbox\z@\lastbox}% + \clubpenalty\@M + \begingroup \@svsechd \endgroup + \unskip + \tag_tool:n {sec-split-para} + \@tempskipa #1\relax + \hskip -\@tempskipa + \else + \clubpenalty \@clubpenalty + \everypar{}% + \fi}% + \fi + \ignorespaces} +%</package> +% \end{macrocode} + +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{sec-tagging-latex-lab-testphase.ltx} + [2023-05-20 v0.82 code related to the tagging of sectioning commands] +\RequirePackage{latex-lab-testphase-sec} +%</latex-lab> +% \end{macrocode} diff --git a/macros/latex/required/latex-lab/latex-lab-sec.pdf b/macros/latex/required/latex-lab/latex-lab-sec.pdf Binary files differnew file mode 100644 index 0000000000..97f5caca08 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-sec.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-testphase.dtx b/macros/latex/required/latex-lab/latex-lab-testphase.dtx index d8d9c671c3..ce882030e8 100644 --- a/macros/latex/required/latex-lab/latex-lab-testphase.dtx +++ b/macros/latex/required/latex-lab/latex-lab-testphase.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment % %% File: latex-lab-testphase.dtx -% Copyright (C) 2021-2022 The LaTeX Project +% Copyright (C) 2021-2023 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -51,14 +51,69 @@ % % % \section{The Implementation} -% New output routine code is loaded in phase-II and new-or: +% new-or-1 contains the code for header and footer (tagging and +% suppressing links) and is always loaded % \begin{macrocode} -%<*tagpdf|phase-II|new-or> -\IfFileExists{latex-lab-testphase-new-or.sty} +%<*new-or-1> +\ProvidesFile{new-or-1-latex-lab-testphase.ltx} + [2022-11-04 v0.1a latex-lab wrapper new-or-1] +%</new-or-1> +% \end{macrocode} +% new-or combines all new-or parts (currently 1+2) +% \begin{macrocode} +%<*new-or> +\ProvidesFile{new-or-latex-lab-testphase.ltx} + [2022-11-04 v0.1a latex-lab wrapper new-or] +%</new-or> +% \end{macrocode} +% \begin{macrocode} +%<*phase-I> +\ProvidesFile{phase-I-latex-lab-testphase.ltx} + [2023-02-04 v0.1b latex-lab wrapper phase-I] +%</phase-I> +% \end{macrocode} +% \begin{macrocode} +%<*phase-II> +\ProvidesFile{phase-II-latex-lab-testphase.ltx} + [2022-11-04 v0.1a latex-lab wrapper phase-II] +%</phase-II> +% \end{macrocode} +% \begin{macrocode} +%<*phase-III> +\ProvidesFile{phase-III-latex-lab-testphase.ltx} + [2023-03-06 v0.1a latex-lab wrapper phase-III] +\input{phase-II-latex-lab-testphase.ltx} +\IfFormatAtLeastTF{2023-06-01} { - \RequirePackage{latex-lab-testphase-new-or} + \RequirePackage{latex-lab-testphase-block-tagging} + \RequirePackage{latex-lab-testphase-sec} + \RequirePackage{latex-lab-testphase-toc} + \RequirePackage{latex-lab-testphase-minipage} + \RequirePackage{latex-lab-testphase-graphic} + \RequirePackage{latex-lab-testphase-float} + \RequirePackage{latex-lab-testphase-bib} + \RequirePackage{latex-lab-testphase-text} } - {} + {\PackageWarning{latex-lab}{Testphase III needs newer format}{}} +%</phase-III> +% \end{macrocode} +% +% this is only provided for compatibility +% \begin{macrocode} +%<*tagpdf> +\ProvidesFile{tagpdf-latex-lab-testphase.ltx} + [2022-11-04 v0.1a latex-lab wrapper tagpdf (deprecated)] +%</tagpdf> +% \end{macrocode} +% \begin{macrocode} +%<*tagpdf|phase-I|phase-II|new-or|new-or-1> +\RequirePackage{latex-lab-testphase-new-or-1} +%</tagpdf|phase-I|phase-II|new-or|new-or-1> +% \end{macrocode} +% New output routine code is loaded in phase-II and new-or: +% \begin{macrocode} +%<*tagpdf|phase-II|new-or> +\RequirePackage{latex-lab-testphase-new-or-2} %</tagpdf|phase-II|new-or> % \end{macrocode} % \begin{macrocode} @@ -70,15 +125,33 @@ \AddToDocumentProperties [document]{testphase/tagpdf}{loaded} %</tagpdf|phase-I|phase-II> %<tagpdf|phase-II>\tagpdfsetup{activate,paratagging,interwordspace} +%<tagpdf|phase-II>\AddToDocumentProperties [document]{tagging/para}{active} %<phase-I>\tagpdfsetup{activate,interwordspace} %<*tagpdf|phase-I|phase-II> \AddToDocumentProperties [document]{tagging}{active} -\AddToDocumentProperties [document]{tagging/para}{active} \AddToDocumentProperties [document]{tagging/interwordspace}{active} % \end{macrocode} % % \begin{macrocode} %</tagpdf|phase-I|phase-II> % \end{macrocode} +% Wrapper files for math tagging: +% \begin{macrocode} +%<*math-lab> +\ProvidesFile{math-latex-lab-testphase.ltx} + [2023-01-07 v0.8 code related to the math tagging] +\RequirePackage{latex-lab-testphase-math} +%</math-lab> +% \end{macrocode} +% \begin{macrocode} +%<*math-sty> +\ProvidesPackage{latex-lab-testphase-math} + [2023-01-07 v0.8 code related to the math tagging] +\input{latex-lab-mathtagging.ltx} +\input{latex-lab-amsmath.ltx} +\input{latex-lab-mathtools.ltx} +\input{latex-lab-mathpkg.ltx} +%</math-sty> +% \end{macrocode} % \Finale % diff --git a/macros/latex/required/latex-lab/latex-lab-testphase.pdf b/macros/latex/required/latex-lab/latex-lab-testphase.pdf Binary files differindex cee61991a0..35f6b6cd8e 100644 --- a/macros/latex/required/latex-lab/latex-lab-testphase.pdf +++ b/macros/latex/required/latex-lab/latex-lab-testphase.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-text.dtx b/macros/latex/required/latex-lab/latex-lab-text.dtx new file mode 100644 index 0000000000..0f31c45969 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-text.dtx @@ -0,0 +1,132 @@ +% \iffalse meta-comment +% +%% File: latex-lab-text.dtx (C) Copyright 2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-text.dtx} +\end{document} +%</driver> +% +% \fi +% +% \title{The \textsf{latex-lab-text} package\\ +% Changes and additions to the kernel related to the tagging of various small text commands} +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{Version 0.80 2023-05-28} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \section{Introduction} +% +% The followings contains small changes to improve the tagging of +% (inline) text commands. +% +% While the tagging of the \LaTeX{} logo is quite straightforward, tagging of +% \cs{emph} as \texttt{EM} and \cs{textbf} as \texttt{Strong} +% can have unwanted side-effect as both tags are inline tags and so not every inner +% structure is allowed. Probably both commands will need an optional argument or a +% starred variant which suppress the tagging. +% +% \section{Implementation} +% \begin{macrocode} +%<*package> +%<@@=tag> +% \end{macrocode} +% \begin{macrocode} +\ProvidesExplPackage {latex-lab-testphase-text} {2023-05-28} {0.8} + {Code related to the tagging of inline text commands} +% \end{macrocode} + +% \subsection{The \LaTeX\ and \TeX\ logo} +% This uses the generic hooks, so that it catches also other definitions. +% For \cs{LaTeX} we stop tagging to avoid that the inner \cs{TeX} leads to a double tagging. +% \begin{macrocode} +\AddToHook{cmd/LaTeX/before} + { + \mode_leave_vertical: + \tag_mc_end_push: + \tag_struct_begin:n{tag=Span,actualtext=LaTeX} + \tag_mc_begin:n{} + \tag_stop:n{LaTeX} + } +\AddToHook{cmd/LaTeX/after} + { + \tag_start:n{LaTeX} + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} + } +\AddToHook{cmd/TeX/before} + { + \mode_leave_vertical: + \tag_mc_end_push: + \tag_struct_begin:n{tag=Span,actualtext=TeX} + \tag_mc_begin:n{} + } +\AddToHook{cmd/TeX/after} + { + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% +% \subsection{Emphasizing} +% We tag \cs{emph} but leave commands like \cs{textbf} alone, as it is not +% clear if they always have a semantic meaning. +% \begin{macrocode} +\AddToHook{cmd/emph/before} + { + \mode_leave_vertical: + \tag_mc_end_push: + \tag_struct_begin:n{tag=Em} + \tag_mc_begin:n{} + } + +\AddToHook{cmd/emph/after} + { + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{text-latex-lab-testphase.ltx} + [2023-05-28 v0.8 code related to the tagging of bib and citations] + +\RequirePackage{latex-lab-testphase-text} + +%</latex-lab> +% \end{macrocode} diff --git a/macros/latex/required/latex-lab/latex-lab-text.pdf b/macros/latex/required/latex-lab/latex-lab-text.pdf Binary files differnew file mode 100644 index 0000000000..f4879150ac --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-text.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.dtx b/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.dtx new file mode 100644 index 0000000000..186f388a19 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.dtx @@ -0,0 +1,202 @@ +% \iffalse meta-comment +% +%% File: latex-lab-toc-hyperref-changes.dtx (C) Copyright 2022-2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-toc-hyperref-changes.dtx} +\end{document} +%</driver> +% +% \fi +% \title{The \textsf{latex-lab-toc-hyperref-changes} package\\ +% Changes and additions to hyperref related to toc entries} +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{Version 0.83 2023-06-07} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \section{Introduction} +% +% The followings contains various change needed for hyperref for the new toc tagging +% code. They should be only loaded if hyperref is used! +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \section{Changes for hyperref} +% \subsection{\cs{contentsline},\cs{addcontentsline}} +% The standard \cs{contentsline} and \cs{addcontentsline} +% should also be used with hyperref (together +% with more changes below) so we have to disable the redefinition in hyperref (this +% requires hyperref version 7.00v! +% \begin{macrocode} +\def\hyper@nopatch@toc{} +\AddToHook{package/hyperref/after} + { + \@ifpackagelater{hyperref}{2023-02-07}{} + {\PackageWarning{latex-lab-testphase-toc-tagging}{hyperref too old}{}} + } +% \end{macrocode} +% +% \subsection{Add links to toc entries} +% \begin{macrocode} +\ExplSyntaxOn +\AddToHook{package/hyperref/after} + { + \AddToHookWithArguments{contentsline/text/before}[hyp] + { + \tl_if_blank:nF {#2}%text + { + \tl_if_blank:nF {#4}%destination + { + \int_case:nnF {\Hy@linktoc} + { + {0}{} %none + {1}{\hyper@linkstart{link}{#4}} %section + {2}{} %page + } + {\hyper@linkstart{link}{#4}} %all + } + } + } + \AddToHookWithArguments{contentsline/text/after}[hyp] + { + \tl_if_blank:nF {#2} + { + \tl_if_blank:nF {#4} + { + \int_case:nnF {\Hy@linktoc} + { + {0}{} %none + {1}{\hyper@linkend} %section + {2}{} %page + } + {\hyper@linkend} %all + } % none + } + } + + \AddToHookWithArguments{contentsline/page/before}[hyp] + { + \tl_if_blank:nF {#3} + { + \tl_if_blank:nF {#4} % + { + \int_case:nnF {\Hy@linktoc} + { + {0}{} %none + {1}{} %section + {2}{\hyper@linkstart{link}{#4}} %page + } + {\hyper@linkstart{link}{#4}} %all + } % none + } + } + \AddToHookWithArguments{contentsline/page/after}[hyp] + { + \tl_if_blank:nF {#3} + { + \tl_if_blank:nF {#4} + { + \int_case:nnF {\Hy@linktoc} + { + {0}{} %none + {1}{} %section + {2}{\hyper@linkend} %page + } + {\hyper@linkend} %all + } % none + } + } + \AddToHookWithArguments{cmd/addcontentsline/before}[hyp] + {% + \Hy@addcontentsline@addbookmark + {#1} + {#2} + {#3}% + } + } +\ExplSyntaxOff +% \end{macrocode} +% \subsection{Add bookmark code to \cs{addcontentsline}} +% +% \begin{macrocode} +\newcommand\Hy@addcontentsline@addbookmark[3]%#1 toc type, #2 level, #3 content + {% + \ifx\@currentHref\@empty + \Hy@Warning{% + No destination for bookmark of \string\addcontentsline,% + \MessageBreak destination is added% + }% + \phantomsection + \fi + \begingroup + \expandafter\ifx\csname toclevel@#2\endcsname\relax + \begingroup + \def\Hy@tempa{#1}% + \ifx\Hy@tempa\Hy@bookmarkstype + \Hy@WarningNoLine{% + bookmark level for unknown #2 defaults to 0% + }% + \else + \Hy@Info{bookmark level for unknown #2 defaults to 0}% + \fi + \endgroup + \expandafter\gdef\csname toclevel@#2\endcsname{0}% + \fi + \edef\Hy@toclevel{\csname toclevel@#2\endcsname}% + \Hy@writebookmark{\csname the#2\endcsname}% + {#3}% + {\@currentHref}% + {\Hy@toclevel}% + {#1}% + \ifHy@verbose + \begingroup + \def\Hy@tempa{#3}% + \@onelevel@sanitize\Hy@tempa + \let\temp@online\on@line + \let\on@line\@empty + \Hy@Info{% + bookmark\temp@online:\MessageBreak + thecounter {\csname the#2\endcsname}\MessageBreak + text {\Hy@tempa}\MessageBreak + reference {\@currentHref}\MessageBreak + toclevel {\Hy@toclevel}\MessageBreak + type {#1}% + }% + \endgroup + \fi + \endgroup + } +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} diff --git a/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.pdf b/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.pdf Binary files differnew file mode 100644 index 0000000000..6ae6eb3718 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.dtx b/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.dtx new file mode 100644 index 0000000000..1c1ce7f44e --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.dtx @@ -0,0 +1,473 @@ +% \iffalse meta-comment +% +%% File: latex-lab-toc-kernel-functions.dtx (C) Copyright 2022-2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-toc-kernel-changes.dtx} +\end{document} +%</driver> +% +% \fi +% +% \title{The \textsf{latex-lab-toc-kernel-changes} package\\ +% Changes and additions to the kernel related to tagging and links in toc entries} +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{Version 0.83 2023-06-07} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \section{Introduction} +% +% The followings contains various changes to kernel commands +% needed for the tagging of table of contents and similar lists. +% \section{General kernel and class changes} +% +% Some of the changes can probably could go into the kernel. +% This are marked with [kernel?], +% the other are marked with [latex-lab]. A few changes must be done in the classes. +% They are marked as [class]. They are inserted with hooks here: this will break +% if a non-standard class is used. +% +% \subsection{Providing the counter representation \cs{theHxx} generally} +% [kernel?] +% +% The \cs{theHxx} representation allows to create a unique representation of a counter +% that is for example used to create destination names. It will also be needed +% to add |/Ref| keys to various tagging structures. It makes therefore sense +% to provide it by default as soon as a counter is created. The |\@addtoreset| change +% (taken also from hyperref) tries to ensure the counter stays unique if it is reset. +% +% At first we suppress the patches from hyperref: +% \begin{macrocode} +%<*kernelchange> +\def\hyper@nopatch@counter{} +% \end{macrocode} +% +% \begin{macrocode} +\def\@definecounter#1{\expandafter\newcount\csname c@#1\endcsname + \setcounter{#1}\z@ + \global\expandafter\let\csname cl@#1\endcsname\@empty + \@addtoreset{#1}{@ckpt}% + \global\expandafter\let\csname p@#1\endcsname\@empty + \expandafter\gdef\csname theH#1\endcsname{\the\value{#1}}%new + \expandafter + \gdef\csname the#1\expandafter\endcsname\expandafter + {\expandafter\@arabic\csname c@#1\endcsname}} +\def\@addtoreset#1#2{\expandafter\@cons\csname cl@#2\endcsname {{#1}}% + \expandafter\gdef\csname theH#1\endcsname{\csname theH#2\endcsname.\the\value{#1}}% +} +% \end{macrocode} +% The following counters are defined in the kernel +% \begin{macrocode} +\gdef\theHenumi{\the\value{enumi}} +\gdef\theHenumii{\the\value{enumii}} +\gdef\theHenumiii{\the\value{enumiii}} +\gdef\theHenumiv{\the\value{enumiv}} +\gdef\theHequation{\the\value{equation}} +\gdef\theHfootnote{\the\value{footnote}} +\gdef\theHmpfootnote{\the\value{mpfootnote}} +% \end{macrocode} +% +% \subsection{Providing and updating \cs{@currentHref}} +% [kernel?] +% +% \cs{@currentHref} contains the current unique representation of a counter. +% It is useful also without hyperref as it allows to connect with a |/Ref| +% key a toc entry with the heading it refers too. So \cs{refstepcounter} +% is extended to update the command. This is done at the begin so that the +% hyperref code can still adapt it later (using the cmd/refstepcounter/after hook +% would be too late, and could also break with cleverref.) +% +% We also provide a kernel version that hyperref doesn't touch and so will never +% set a target. +% \begin{macrocode} +\def\@currentHref{} +\def\refstepcounter#1{\stepcounter{#1}% + \edef\@currentcounter{#1}% + \xdef\@currentHref {#1.\csname theH#1\endcsname}% + \protected@edef\@currentlabel + {\csname p@#1\expandafter\endcsname\csname the#1\endcsname}% +} +\let\@kernel@refstepcounter\refstepcounter +% \end{macrocode} +% +% \subsection{Assigning the headings level numbers} +% [kernel?] +% +% The code for the toc must be able to compare the level of |subsection| against +% |section|. So some numbers are needed. It uses for now the commands used by +% |hyperref| for the bookmark levels. While headings are more a class thing, it +% could make sense to provide a standard set already in the kernel. +% The numbers are a bit different to the one in hyperref, but imho sensible. +% +% Note for the future: +% once that heading stuff is turned into template +% instances the template should set that number. +% \begin{macrocode} +\def\toclevel@document{-10} +\def\toclevel@part{-1} +\def\toclevel@chapter{0} +\def\toclevel@section{1} +\def\toclevel@subsection{2} +\def\toclevel@subsubsection{3} +\def\toclevel@paragraph{4} +\def\toclevel@subparagraph{5} +\def\toclevel@figure{1} +\def\toclevel@table{1} +%</kernelchange> +% \end{macrocode} +% \subsection{load kernel changes} +% \begin{macrocode} +%<*package> +\RequirePackage{latex-lab-kernel-changes} +% \end{macrocode} +% +% \subsection{\cs{contentsline} extension} +% [latex-lab] +% The tagging code must add code at the begin and end of \cs{contentsline}. +% This code must have access to the arguments. We set it up as config point +% for now. +% \begin{macrocode} +\def\@contentsline@cfgpoint@before#1#2#3#4{} +\def\@contentsline@cfgpoint@after#1#2#3#4{} +% \end{macrocode} +% for the hooks we need that the \cs{l@XX} pass also the destination and +% that \cs{l@XX} takes three arguments. +% TODO: test that, if there are two many problems we should pass the +% destination through a command name ... +% \begin{macrocode} +\def\contentsline#1#2#3#4% + {% + \@contentsline@cfgpoint@before{#1}{#2}{#3}{#4}% + \gdef\@contentsline@destination{#4}% + \csname l@#1\endcsname{#2}{#3}% + \@contentsline@cfgpoint@after{#1}{#2}{#3}{#4}% + } +% \end{macrocode} +% +% \subsection{\cs{addcontentsline} changes} +% [latex-lab] +% +% \cs{addcontentsline} should always write the unique counter representation +% \cs{@currentHref} so that we can create the |/Ref| key. At the same time +% we need a hook, so that hyperref can add its bookmarks code, the generic hook +% with arguments is ok. +% +% \begin{macrocode} +\def\addcontentsline#1#2#3{% #1=toc extension, #2= heading type, tag + \addtocontents{#1}{% + \protect\contentsline{#2}{#3}{\thepage}{\@currentHref}\protected@file@percent + }} +% \end{macrocode} +% +% \subsection{\cs{@starttoc}} +% [kernel?] +% +% We add a configuration point before and after reading the file +% for the tagging. +% \begin{macrocode} +\def\@starttoc@cfgpoint@before#1{} +\def\@starttoc@cfgpoint@after#1{} +\def\@starttoc#1{% + \begingroup + \makeatletter + \@starttoc@cfgpoint@before{#1}% + \@input{\jobname.#1}% + \@starttoc@cfgpoint@after{#1} + \if@filesw + \expandafter\newwrite\csname tf@#1\endcsname + \immediate\openout \csname tf@#1\endcsname \jobname.#1\relax + \fi + \@nobreakfalse + \endgroup} +% \end{macrocode} +% +% \subsection{Formatting of the toc entries} +% +% \subsubsection{Kernel commands} +% [latex-lab] or [kernel?]? +% +% We need hooks before and after the content and before and after the page number. +% The number needs some thing so that it can be tagged as label. +% The text and the page +% hooks are used in manual \cs{l@xx} commands and in \cs{l@xx} defined by +% \cs{@dottedtocline} or by other means. +% The arguments of the following hooks are: +% \begin{itemize} +% \item[\#1] level as a \emph{number} (integer expression), see above for the standard +% numbering. The standard first argument of \cs{contentsline} is not used, as +% \cs{@dottedtocline} knows only a number. +% \item[\#2] content (the second argument of a \cs{contentsline} +% \item[\#3] page (the third argument of a \cs{contentsline} +% \item[\#3] target (the fourth argument of a \cs{contentsline} +% \end{itemize} +% \begin{macrocode} +\NewMirroredHookPairWithArguments{contentsline/number/before}{contentsline/number/after}{1}% +\NewMirroredHookPairWithArguments{contentsline/text/before}{contentsline/text/after}{4}% +\NewMirroredHookPairWithArguments{contentsline/page/before}{contentsline/page/after}{4}% +% \end{macrocode} +% +% The dot in the leader must be set as artifact. +% But luatex requires that the mc are set outside the leaders. +% So we need a config point. +% +% \cs{@dottedtocline} needs hooks and formatting commands. +% We add a sixth argument so that it can grab the destination too. +% \begin{macrocode} +\def\@dottedtocline@cfgpoint@leaders#1{#1} + +\def\@dottedtocline#1#2#3#4#5{% + \ifnum #1>\c@tocdepth \else + \vskip \z@ \@plus.2\p@ + {\leftskip #2\relax \rightskip \@tocrmarg \parfillskip -\rightskip + \parindent #2\relax\@afterindenttrue + \interlinepenalty\@M + \leavevmode + \@tempdima #3\relax + \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip + \UseHookWithArguments{contentsline/text/before}{4}{#1}{#4}{#5}{\@contentsline@destination}% + \csname contentsline@text@#1@format\endcsname{#4}% + \UseHookWithArguments{contentsline/text/after}{4}{#1}{#4}{#5}{\@contentsline@destination}% + \nobreak + \@dottedtocline@cfgpoint@leaders{% + \leaders\hbox{$\m@th + \mkern \@dotsep mu\hbox{.}\mkern \@dotsep + mu$}\hfill}% + \nobreak + \hb@xt@\@pnumwidth{\hfil\normalfont \normalcolor + \UseHookWithArguments{contentsline/page/before}{4}{#1}{#4}{#5}{\@contentsline@destination}% + #5% + \UseHookWithArguments{contentsline/page/after}{4}{#1}{#4}{#5}{\@contentsline@destination}% + \kern-\p@\kern\p@}% + \par}% + \fi} +% \end{macrocode} +% +% \subsubsection{\cs{numberline}} +% [kernel?] +% Inside or outside the box? +% \begin{macrocode} +\def\numberline#1{\hb@xt@\@tempdima{% + \UseHookWithArguments{contentsline/number/before}{1}{#1}% + #1\hfil + \UseHookWithArguments{contentsline/number/after}{1}{#1}% + }} +% \end{macrocode} +% +% \subsubsection{\cs{l@xx} in the classes} +% Depending on the class we have to redefine also more commands +% For other classes it should be documented what is needed. +% Let the commands grab also the third arguments. If a class redefines them again +% it will break tagging anyway. +% \begin{macrocode} +\AddToHook{class/article/after} + { + \renewcommand*\l@part[2]{% as in contentsline: content, page + \ifnum \c@tocdepth >-2\relax + \addpenalty\@secpenalty + \addvspace{2.25em \@plus\p@}% + \setlength\@tempdima{3em}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + {\leavevmode + \large \bfseries + \UseHookWithArguments{contentsline/text/before}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + \csname contentsline@text@-1@format\endcsname{#1}% + \UseHookWithArguments{contentsline/text/after}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + \hfil + \hb@xt@\@pnumwidth{\hss + \UseHookWithArguments{contentsline/page/before}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + #2% + \UseHookWithArguments{contentsline/page/after}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + \kern-\p@\kern\p@}}\par + \nobreak + \endgroup + \fi} +\renewcommand*\l@section[2]{% + \ifnum \c@tocdepth >\z@ + \addpenalty\@secpenalty + \addvspace{1.0em \@plus\p@}% + \setlength\@tempdima{1.5em}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \leavevmode \bfseries + \advance\leftskip\@tempdima + \hskip -\leftskip + \UseHookWithArguments{contentsline/text/before}{4} + {\toclevel@section}{#1}{#2}{\@contentsline@destination}% + \csname contentsline@text@1@format\endcsname{#1}% + \UseHookWithArguments{contentsline/text/after}{4} + {\toclevel@section}{#1}{#2}{\@contentsline@destination}% + \nobreak\hfil + \nobreak\hb@xt@\@pnumwidth{\hss + \UseHookWithArguments{contentsline/page/before}{4} + {\toclevel@section}{#1}{#2}{\@contentsline@destination}% + #2% + \UseHookWithArguments{contentsline/page/after}{4} + {\toclevel@section}{#1}{#2}{\@contentsline@destination}% + \kern-\p@\kern\p@}\par + \endgroup + \fi} + } +\AddToHook{class/report/after} + { + \renewcommand*\l@part[2]{% + \ifnum \c@tocdepth >-2\relax + \addpenalty{-\@highpenalty}% + \addvspace{2.25em \@plus\p@}% + \setlength\@tempdima{3em}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + {\leavevmode + \large \bfseries + \UseHookWithArguments{contentsline/text/before}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + \csname contentsline@text@-1@format\endcsname{#1}% + \UseHookWithArguments{contentsline/text/after}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + \hfil + \hb@xt@\@pnumwidth{\hss + \UseHookWithArguments{contentsline/page/before}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + #2% + \UseHookWithArguments{contentsline/page/after}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}% + \kern-\p@\kern\p@}}\par + \nobreak + \endgroup + \fi} + \renewcommand*\l@chapter[2]{% + \ifnum \c@tocdepth >\m@ne + \addpenalty{-\@highpenalty}% + \vskip 1.0em \@plus\p@ + \setlength\@tempdima{1.5em}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \leavevmode \bfseries + \advance\leftskip\@tempdima + \hskip -\leftskip + \UseHookWithArguments{contentsline/text/before}{4} + {\toclevel@chapter}{#1}{#2}{\@contentsline@destination}% + \csname contentsline@text@0@format\endcsname + {#1}% + \UseHookWithArguments{contentsline/text/after}{4} + {\toclevel@chapter}{#1}{#2}{\@contentsline@destination}% + \nobreak\hfil + \nobreak\hb@xt@\@pnumwidth{\hss + \UseHookWithArguments{contentsline/page/before}{4} + {\toclevel@chapter}{#1}{#2}{\@contentsline@destination}%% + #2% + \UseHookWithArguments{contentsline/page/after}{4} + {\toclevel@chapter}{#1}{#2}{\@contentsline@destination}%% + \kern-\p@\kern\p@}\par + \penalty\@highpenalty + \endgroup + \fi} + } +\AddToHook{class/book/after} + { + \renewcommand*\l@part[2]{% + \ifnum \c@tocdepth >-2\relax + \addpenalty{-\@highpenalty}% + \addvspace{2.25em \@plus\p@}% + \setlength\@tempdima{3em}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + {\leavevmode + \large \bfseries + \UseHookWithArguments{contentsline/text/before}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}%% + \csname contentsline@text@-1@format\endcsname{#1}% + \UseHookWithArguments{contentsline/text/after}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}%% + \hfil + \hb@xt@\@pnumwidth{\hss + \UseHookWithArguments{contentsline/page/before}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}%% + #2% + \UseHookWithArguments{contentsline/page/after}{4} + {\toclevel@part}{#1}{#2}{\@contentsline@destination}%% + \kern-\p@\kern\p@}}\par + \nobreak + \endgroup + \fi} + \renewcommand*\l@chapter[2]{% + \ifnum \c@tocdepth >\m@ne + \addpenalty{-\@highpenalty}% + \vskip 1.0em \@plus\p@ + \setlength\@tempdima{1.5em}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \leavevmode \bfseries + \advance\leftskip\@tempdima + \hskip -\leftskip + \UseHookWithArguments{contentsline/text/before}{4} + {\toclevel@chapter}{#1}{#2}{\@contentsline@destination}% + \csname contentsline@text@0@format\endcsname + {#1}% + \UseHookWithArguments{contentsline/text/after}{4} + {\toclevel@chapter}{#1}{#2}{\@contentsline@destination}% + \nobreak\hfil + \nobreak\hb@xt@\@pnumwidth{\hss + \UseHookWithArguments{contentsline/page/before}{4} + {\toclevel@chapter}{#1}{#2}{\@contentsline@destination}% + #2% + \UseHookWithArguments{contentsline/page/after}{4} + {\toclevel@chapter}{#1}{#2}{\@contentsline@destination}% + \kern-\p@\kern\p@}\par + \penalty\@highpenalty + \endgroup + \fi} + } +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} + +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{toc-tagging-latex-lab-testphase.ltx} + [2023-05-20 v0.81 code related to the tagging of toc and similar lists] + +\RequirePackage{latex-lab-testphase-toc} + +%</latex-lab> +% \end{macrocode} diff --git a/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.pdf b/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.pdf Binary files differnew file mode 100644 index 0000000000..96b9ac1514 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.pdf diff --git a/macros/latex/required/latex-lab/latex-lab-toc-tagging-functions.dtx b/macros/latex/required/latex-lab/latex-lab-toc-tagging-functions.dtx new file mode 100644 index 0000000000..a39ace44e5 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-toc-tagging-functions.dtx @@ -0,0 +1,365 @@ +% \iffalse meta-comment +% +%% File: latex-lab-toc-tagging-functions.dtx (C) Copyright 2022-2023 LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-toc-tagging-functions.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \textsf{latex-lab-toc-tagging-functions} package\\ +% Tagpdf functions related to the tagging of toc and similar lists} +% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} +% \date{Version 0.82 2023-05-20} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% \providecommand\hook[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% Header for the testphase package +% \begin{macrocode} +%<*header> +\ProvidesExplPackage {latex-lab-testphase-toc} {2023-05-20} {0.82} + { commands related to the tagging of toc-like lists} +%</header> +% \end{macrocode} +% +% \section{Introduction} +% +% The followings contains various functions related to the tagging of the +% table of contents and similar list. The functions will at some time +% be moved inside the tagpdf code. +% \begin{macrocode} +%<*package> +%<@@=tag> +% \end{macrocode} +% \section{Temporary variables} +% \begin{macro}{\l_@@_toc_tmpa_tl} +% \begin{macrocode} +\tl_new:N \l_@@_toc_tmpa_tl +% \end{macrocode} +% \end{macro} +% +% \section{General struct commands} +% The following variables and commands are not restricted to toc, but +% probably will be need in other places too. +% \begin{variable}{\g_@@_struct_dest_num_prop} +% This variable records for (some or all, not clear yet) +% destination names the related structure number to allow +% to reference them in a Ref. The key is the destination. +% Moved into tagpdf! +% \end{variable} +% +% We use \cs{refstepcounter} to store the relation between +% destination names/\cs{@currentHref} and structure numbers +% +% TODO: the functions should be moved into tagpdf so that one +% doesn't has to test if the prop exists or not. +% \begin{macrocode} +\AddToHook{cmd/refstepcounter/after} + { + \tl_if_blank:VF \@currentHref + { + \prop_if_exist:NT \g_@@_struct_dest_num_prop + { + \prop_gput:Nxx \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} + } + } + } +\AddToHook{cmd/H@refstepcounter/after} + { + \tl_if_blank:VF \@currentHref + { + \prop_if_exist:NT \g_@@_struct_dest_num_prop + { + \prop_gput:Nxx \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} + } + } + } +% \end{macrocode} +% \begin{variable}{\g_@@_struct_ref_by_dest_prop} +% This variable contains structures whose Ref key should be updated +% at the end to point to structured related with this destination. +% As this is probably need in other places too, it is not only a toc-variable. +% Moved into tagpdf! +% \end{variable} +% +% \begin{macro}{\g_@@_struct_ref_by_dest:} +% This command is executed and update the Ref keys +% of the structures listed in |\g_@@_struct_ref_by_dest_prop|. +% It is currently only relevant for the |TOCI|. But other structures +% could need that later too. +% The command is executed in the |tagpdf/finish/before| hook. +% \begin{macrocode} +\msg_new:nnn { tag } {struct-dest-unknown} + { + Destination~#1~has~no~related~structure.\\ + /Ref~for~structure~#2~not~updated + } + +\cs_new_protected:Npn \g_@@_struct_ref_by_dest: + { + \prop_map_inline:Nn\g_@@_struct_ref_by_dest_prop + { + \prop_get:NnNTF \g_@@_struct_dest_num_prop {##2} \l_@@_tmpa_tl + { + \@@_struct_gput_data_ref:ee + { ##1 } + { \tag_struct_object_ref:e{ \l_@@_tmpa_tl }} + } + { + \msg_warning:nnnn {tag}{struct-dest-unknown}{##2}{ ##1} + } + } + } +\hook_gput_code:nnn {tagpdf/finish/before}{tagpdf/struct/Ref}{\g_@@_struct_ref_by_dest:} +% \end{macrocode} +% \end{macro} +% +% \section{Toc code} +% \begin{variable}{\g_@@_toc_level_int,\g_@@_toc_stack_seq} +% |\g_@@_toc_level_int| records in a toc the current absolute level. +% We must close open structures at the end of the toc, for this +% we maintain a stack |\g_@@_toc_stack_seq|. +% \begin{macrocode} +\int_new:N \g_@@_toc_level_int +\seq_new:N \g_@@_toc_stack_seq +% \end{macrocode} +% \end{variable} + +% \begin{macro}{\_tag_toc_starttoc_init:n} +% The init code clears the stack, and set the level to -100 +% and start to TOC structure. We also disable paratagging. +% The |/Title| is currently simply the type, but this could be done nicer. +% \begin{macrocode} +\cs_new_protected:Npn \@@_toc_starttoc_init:n #1 + { + \bool_set_false:N \l_@@_para_bool + \seq_gclear:N \g_@@_toc_stack_seq + \int_gset:Nn \g_@@_toc_level_int {-100} + \tag_struct_begin:n{tag=TOC,title=#1} + } +% \end{macrocode} +% Now map it into the config point: +% \begin{macrocode} +\cs_set_protected:Npn\@starttoc@cfgpoint@before#1 + { + \@@_toc_starttoc_init:n{#1} + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_toc_starttoc_finalize:} +% \begin{macrocode} +\cs_new_protected:Npn \@@_toc_starttoc_finalize: + { + \int_step_inline:nn + {\seq_count:N \g_@@_toc_stack_seq } + {\tag_struct_end:} + \tag_struct_end: + \seq_gclear:N \g_@@_toc_stack_seq + } +% \end{macrocode} +% Now map it into the config point: +% \begin{macrocode} +\cs_set_protected:Npn\@starttoc@cfgpoint@after#1 + { + \@@_toc_starttoc_finalize: + } +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\@@_toc_end:n} +% This commands ends all TOC on the stack with a level higher than the argument +% \begin{macrocode} +\cs_new_protected:Npn \@@_toc_end:n #1 + { + \seq_get:NNT\g_@@_toc_stack_seq \l_@@_toc_tmpa_tl + { + \bool_lazy_and:nnT + { + \str_if_eq_p:ee{\tl_head:N\l_@@_toc_tmpa_tl}{TOC} + } + { + \int_compare_p:nNn {#1}<{\tl_tail:N \l_@@_toc_tmpa_tl} + } + { + \seq_gpop:NN\g_@@_toc_stack_seq \l_@@_toc_tmpa_tl + \tag_struct_end: + \@@_toc_end:n{#1} + } + } + } +\cs_generate_variant:Nn \@@_toc_end:n {e} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_toc_contentsline_begin:nnn} +% This is main command executed at the begin of a |\contentsline|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_toc_contentsline_begin:nnn #1 #2 #3 %#1 level, #2 content, #3 destination + { + \tag_if_active:T + { +% \end{macrocode} +% We detect the intended level by checking the value of |toclevel@...| +% (currently only provided by hyperref, but should be there always). +% To be on the safe side we set it to 1 if not defined. +% \begin{macrocode} + \ExpandArgs{c}\providecommand { toclevel@#1 }{ 1 } % just in case ... + \int_compare:nNnF { \use:c{toclevel@#1} } > {\use:c{c@tocdepth}} + { +% \end{macrocode} +% if level goes up, start new sub TOC unless we are at the begin +% \begin{macrocode} + \bool_lazy_and:nnT + { \int_compare_p:nNn { \g_@@_toc_level_int } > {-100} } + { \int_compare_p:nNn { \use:c{toclevel@#1} } > { \g_@@_toc_level_int } } + { + \seq_gpush:Nx \g_@@_toc_stack_seq {{TOC}\use:c{toclevel@#1}} + \tag_struct_begin:n{tag=TOC} + } +% \end{macrocode} +% if level goes down close all TOC's with a higher level +% \begin{macrocode} + \int_compare:nNnT + { \use:c{toclevel@#1} } < { \g_@@_toc_level_int } + { + \@@_toc_end:e { \use:c{toclevel@#1} } + } +% \end{macrocode} +%if same level do nothing +% update toclevel to the current level. +% \begin{macrocode} + \int_gset:Nn \g_@@_toc_level_int { \use:c{toclevel@#1} } +% \end{macrocode} +% now open the TOCI, the tagging of the +% inner structure is left to the |\l@xxx| commands. +% setting the title is not strictly necessary but looks nicer +% but we have to remove the |\numberline| +% \begin{NOTE}{UF} +% perhaps keep the number? How to insert a space then +% \end{NOTE} +% \begin{macrocode} + \group_begin: + \text_declare_expand_equivalent:Nn \numberline \use_none:n + \exp_args:Nx \tag_struct_begin:n{tag=TOCI,title={\text_purify:n {#2}}} +% \end{macrocode} +% The TOCI structure should get a /Ref, so we put a request with its destination +% name into the prop. +% \begin{NOTE}{UF} +% This only works with hyperref currently. Without hyperref we +% need to store fake names. +% \end{NOTE} +% \begin{macrocode} + \prop_gput:Nxx \g_@@_struct_ref_by_dest_prop + { \tag_get:n {struct_num} }{#3} + \seq_gpush:Nx \g_@@_toc_stack_seq {{TOCI}\use:c{toclevel@#1}} + \group_end: + } + } + } +% \end{macrocode} +% Now map it into the config point: +% \begin{macrocode} +\cs_set_protected:Npn\@contentsline@cfgpoint@before#1#2#3#4 + { + \@@_toc_contentsline_begin:nnn {#1}{#2}{#4} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_toc_contentsline_end:n} +% This is the closing code of a |\contentsline|. +% If the contentsline was actually printed, the code has to +% close the TOCI structure and to update the stack. +% \begin{macrocode} +\msg_new:nnn {tag}{toc-no-TOCI}{Missing~TOCI~structure~on~toc~stack} + +\cs_new_protected:Npn \@@_toc_contentsline_end:n #1 %#1 level name + { + \int_compare:nNnF { \use:c{toclevel@#1} } > {\use:c{c@tocdepth}} + { + \seq_gpop:NNT \g_@@_toc_stack_seq\l_@@_tmpa_tl + { + \str_if_eq:eeTF{\tl_head:N\l_@@_tmpa_tl}{TOCI} + { + \tag_struct_end: + } + { + \msg_warning:nn{tag}{toc-no-TOCI} + } + } + } + } +% \end{macrocode} +% Now we map it to the config point +% \begin{macrocode} +\cs_set_protected:Npn \@contentsline@cfgpoint@after #1#2#3#4 + { + \@@_toc_contentsline_end:n {#1} + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Tagging of the content} +% This need discussion. +% +% \begin{macrocode} +\AddToHook{contentsline/text/before}[tagpdf]{% + \tag_struct_begin:n{tag=Reference}% + \tag_mc_begin:n{tag=Reference}} +\AddToHook{contentsline/text/after}[tagpdf]{% + \tag_mc_end:} +\AddToHook{contentsline/page/before}[tagpdf]{% + \tag_mc_begin:n{tag=Reference}} +\AddToHook{contentsline/page/after}[tagpdf]{% + \tag_mc_end: + \tag_struct_end:} %Reference +\AddToHook{contentsline/number/before}[tagpdf]{% + \tag_mc_end: + \tag_struct_begin:n{tag=Lbl}% + \tag_mc_begin:n{tag=Lbl}} +\AddToHook{contentsline/number/after}[tagpdf]{% + \tag_mc_end: + \tag_struct_end: + \tag_mc_begin:n{tag=Reference}} +% \end{macrocode} +% +% \begin{macrocode} +\def\@dottedtocline@cfgpoint@leaders#1{% + \tag_mc_begin:n{artifact}\tag_stop:n{leaders}\nobreak#1\nobreak\tag_start:n{leaders}\tag_mc_end:} +% \end{macrocode} + +% +% \begin{macrocode} +%</package> +% \end{macrocode} diff --git a/macros/latex/required/latex-lab/latex-lab-toc-tagging-functions.pdf b/macros/latex/required/latex-lab/latex-lab-toc-tagging-functions.pdf Binary files differnew file mode 100644 index 0000000000..4ec6c4e614 --- /dev/null +++ b/macros/latex/required/latex-lab/latex-lab-toc-tagging-functions.pdf diff --git a/macros/latex/required/latex-lab/latex-lab.ins b/macros/latex/required/latex-lab/latex-lab.ins index bc668a71e1..1989ddcfa3 100644 --- a/macros/latex/required/latex-lab/latex-lab.ins +++ b/macros/latex/required/latex-lab/latex-lab.ins @@ -3,7 +3,7 @@ %% driver files from the dtx file(s) in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 2021-2022 The LaTeX Project +%% Copyright (C) 2021-2023 The LaTeX Project %% %% %% This file is part of the `LaTeX-lab Bundle' for LaTeX. @@ -35,7 +35,7 @@ This is a generated file. -Copyright 2021,2022 LaTeX Project +Copyright 2021-2023 LaTeX Project This file was generated from file(s) of the `LaTeX-lab Bundle'. ------------------------------------------------------------------------------------ @@ -68,15 +68,85 @@ where one can also log issues in case there are any. % #1-latex-lab-testphase.ltx \generate{\file{phase-I-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{phase-I}}} \generate{\file{phase-II-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{phase-II}}} +\generate{\file{phase-III-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{phase-III}}} + \generate{\file{tagpdf-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{tagpdf}}} \generate{\file{new-or-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{new-or}}} +\generate{\file{new-or-1-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{new-or-1}}} + +\generate{\file{math-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{math-lab}}} +\generate{\file{latex-lab-testphase-math.sty}{\from{latex-lab-testphase.dtx}{math-sty}}} % support files (the new-or code is a private package to make life easier) -\generate{\file{latex-lab-testphase-new-or.sty}{\from{latex-lab-new-or.dtx}{code}}} +\generate{\file{latex-lab-testphase-new-or-2.sty}{\from{latex-lab-new-or-2.dtx}{code}}} +\generate{\file{latex-lab-testphase-new-or-1.sty}{\from{latex-lab-new-or-1.dtx}{code}}} \generate{\file{latex-lab-footmisc.ltx}{\from{latex-lab-footnotes.dtx}{footmisc}}} \generate{\file{latex-lab-footnotes.ltx}{\from{latex-lab-footnotes.dtx}{kernel}}} +\generate{\file{latex-lab-mathtagging.ltx}{\from{latex-lab-mathtagging.dtx}{kernel}}} + +\generate{\file{latex-lab-amsmath.ltx}{\from{latex-lab-amsmath.dtx}{kernel}}} +\generate{\file{latex-lab-mathtools.ltx}{\from{latex-lab-mathtools.dtx}{kernel}}} +\generate{\file{latex-lab-mathpkg.ltx}{\from{latex-lab-mathpkg.dtx}{kernel}}} + +\generate{\file{latex-lab-testphase-sec.sty}{\from{latex-lab-sec.dtx}{package}}} +\generate{\file{sec-tagging-latex-lab-testphase.ltx}{\from{latex-lab-sec.dtx}{latex-lab}}} + + +\generate{\file{latex-lab-testphase-toc.sty}{% + \from{latex-lab-toc-tagging-functions.dtx}{header} + \from{latex-lab-toc-kernel-changes.dtx}{package} + \from{latex-lab-toc-tagging-functions.dtx}{package} + \from{latex-lab-toc-hyperref-changes.dtx}{package}}} + +\generate{\file{toc-tagging-latex-lab-testphase.ltx}{% + \from{latex-lab-toc-kernel-changes.dtx}{latex-lab}}} + +\generate{\file{latex-lab-kernel-changes.sty} + {\from{latex-lab-toc-kernel-changes.dtx}{kernelchange} + \from{latex-lab-sec.dtx}{kernelchange} + }} + + +\generate{\file{latex-lab-testphase-graphic.sty}{% + \from{latex-lab-graphic.dtx}{package}}} + +\generate{\file{graphic-latex-lab-testphase.ltx}{% + \from{latex-lab-graphic.dtx}{latex-lab}}} + +\generate{\file{latex-lab-testphase-block-tagging.sty}{\from{latex-lab-block-tagging.dtx}{package}}} +\generate{\file{block-tagging-latex-lab-testphase.ltx}{\from{latex-lab-block-tagging.dtx}{latex-lab}}} + +\generate{\file{latex-lab-testphase-minipage.sty}{% + \from{latex-lab-minipage.dtx}{package}}} + +\generate{\file{minipage-latex-lab-testphase.ltx}{% + \from{latex-lab-minipage.dtx}{latex-lab}}} + + \generate{\file{latex-lab-testphase-float.sty}{% + \from{latex-lab-float.dtx}{package}}} + +\generate{\file{float-latex-lab-testphase.ltx}{% + \from{latex-lab-float.dtx}{latex-lab}}} + +\generate{\file{latex-lab-testphase-bib.sty}{% + \from{latex-lab-bib.dtx}{package}}} + +\generate{\file{bib-latex-lab-testphase.ltx}{% + \from{latex-lab-bib.dtx}{latex-lab}}} + +\generate{\file{latex-lab-testphase-text.sty}{% + \from{latex-lab-text.dtx}{package}}} + +\generate{\file{text-latex-lab-testphase.ltx}{% + \from{latex-lab-text.dtx}{latex-lab}}} + +\generate{\file{latex-lab-testphase-firstaid.sty}{% + \from{latex-lab-firstaid.dtx}{package}}} +\generate{\file{firstaid-latex-lab-testphase.ltx}{% + \from{latex-lab-firstaid.dtx}{latex-lab}}} + \endbatchfile diff --git a/macros/latex/required/latex-lab/usage-of-@footnotemark.txt b/macros/latex/required/latex-lab/usage-of-@footnotemark.md index 684a695faa..ad50b36732 100644 --- a/macros/latex/required/latex-lab/usage-of-@footnotemark.txt +++ b/macros/latex/required/latex-lab/usage-of-@footnotemark.md @@ -1,6 +1,8 @@ -% packages that alter \@footnotemark ... +# Packages that alter \@footnotemark ... +Scan of TeXlive 2022 for checking ... may not be longer accurate and may contain a few false positives +``` % bibarts \let\ba@footnmark=\@footnotemark @@ -184,3 +186,4 @@ } +``` diff --git a/macros/latex/required/latex-lab/usage-of-@footnotetext.txt b/macros/latex/required/latex-lab/usage-of-@footnotetext.md index 48a3172843..deda69fcd8 100644 --- a/macros/latex/required/latex-lab/usage-of-@footnotetext.txt +++ b/macros/latex/required/latex-lab/usage-of-@footnotetext.md @@ -1,3 +1,8 @@ +# Packages that alter \@footnotetext ... + +Scan of TeXlive 2022 for checking ... may not be longer accurate and may contain a few false positives + +``` % ./bibarts/bibarts.sty @@ -840,3 +845,4 @@ not checked what this does this needs some further analysis +``` diff --git a/macros/latex/required/latex-lab/usage-of-@makefntext.md b/macros/latex/required/latex-lab/usage-of-@makefntext.md new file mode 100644 index 0000000000..d7cb0a9b92 --- /dev/null +++ b/macros/latex/required/latex-lab/usage-of-@makefntext.md @@ -0,0 +1,1751 @@ +# Packages that alter \@makefntext ... + +Scan of TeXlive 2022 for checking ... may not be longer accurate and may contain a few false positives + +``` + +% ./footmisc/footmisc.sty + +% latex def (used with para option) + + + + \long\def\@makefntext#1{% + \ifFN@hangfoot + \bgroup + \setbox\@tempboxa\hbox{% + \ifdim\footnotemargin>0pt + \hb@xt@\footnotemargin{\@makefnmark\hss}% + \else + \@makefnmark + \fi + }% + \leftmargin\wd\@tempboxa + \rightmargin\z@ + \linewidth \columnwidth + \advance \linewidth -\leftmargin + \parshape \@ne \leftmargin \linewidth + \footnotesize + \@setpar{{\@@par}}% + \leavevmode + \llap{\box\@tempboxa}% + \parskip\hangfootparskip\relax + \parindent\hangfootparindent\relax + \else + \parindent1em + \noindent + \ifdim\footnotemargin>\z@ + \hb@xt@ \footnotemargin{\hss\@makefnmark}% + \else + \ifdim\footnotemargin=\z@ + \llap{\@makefnmark}% + \else + \llap{\hb@xt@ -\footnotemargin{\@makefnmark\hss}}% + \fi + \fi + \fi + \footnotelayout#1% + \ifFN@hangfoot + \par\egroup + \fi + } + + + + +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/aastex/aastex631.cls +--------------------------------------------------------- +\def\@makefntext#1{\hsize=\columnwidth\mbox{}\hspace*{3mm}\@makefnmark~#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/paper/paper.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hbox to1.8em{\hss$\m@th^{\@thefnmark}$}##1}% +... + \long\def\@makefntext#1{% + \leftskip 2.0em% + \noindent + \hbox to 0em{\hss\@makefnmark\kern 0.25em}#1} +... + \long\def\@makefntext#1{% + \parindent 1em% + \noindent + \hbox to 1.8em{\hss\@makefnmark\kern 0.25em}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex4-1/aip4-1.rtx +--------------------------------------------------------- +\def\@makefntext#1{% + \def\baselinestretch{1}% + \leftskip1em% + \parindent1em% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex4-1/aps4-1.rtx +--------------------------------------------------------- +\long\def\@makefntext#1{% + \def\baselinestretch{1}% + \leftskip1em% + \parindent1em% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex4-1/revtex4-1.cls +--------------------------------------------------------- +\def\@makefntext#1{% + \def\baselinestretch{1}% + \parindent1em% + \noindent +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/smflatex/smfart.cls +--------------------------------------------------------- +\def\@makefntext{\parindent0pt\sloppy\indent\@makefnmark} +\hfuzz=1pt \vfuzz=\hfuzz +\def\sloppy{\tolerance9999 \emergencystretch 3em\relax} +\setcounter{topnumber}{4} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/smflatex/smfbook.cls +--------------------------------------------------------- +\def\@makefntext{\parindent0pt\sloppy\indent\@makefnmark} +\hfuzz=1pt \vfuzz=\hfuzz +\def\sloppy{\tolerance9999 \emergencystretch 3em\relax} +\setcounter{topnumber}{4} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/koma-script/scrlttr2.cls +--------------------------------------------------------- + \long\def\@makefntext##1{% + \raggedfootnote + \leftskip #2 + \l@addto@macro\@trivlist{% +... + \long\def\@makefntext##1{% + \setlength{\@tempdimc}{#3}% + \def\@tempa{#1}\ifx\@tempa\@empty + \@setpar{\@@par +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/koma-script/scrextend.sty +--------------------------------------------------------- + \long\def\@makefntext##1{% + \raggedfootnote + \leftskip #2 + \l@addto@macro\@trivlist{% +... + \long\def\@makefntext##1{% + \setlength{\@tempdimc}{#3}% + \def\@tempa{#1}\ifx\@tempa\@empty + \@setpar{\@@par +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/koma-script/scrreprt.cls +--------------------------------------------------------- + \long\def\@makefntext##1{% + \raggedfootnote + \leftskip #2 + \l@addto@macro\@trivlist{% +... + \long\def\@makefntext##1{% + \setlength{\@tempdimc}{#3}% + \def\@tempa{#1}\ifx\@tempa\@empty + \@setpar{\@@par +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/koma-script/scrartcl.cls +--------------------------------------------------------- + \long\def\@makefntext##1{% + \raggedfootnote + \leftskip #2 + \l@addto@macro\@trivlist{% +... + \long\def\@makefntext##1{% + \setlength{\@tempdimc}{#3}% + \def\@tempa{#1}\ifx\@tempa\@empty + \@setpar{\@@par +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/koma-script/scrbook.cls +--------------------------------------------------------- + \long\def\@makefntext##1{% + \raggedfootnote + \leftskip #2 + \l@addto@macro\@trivlist{% +... + \long\def\@makefntext##1{% + \setlength{\@tempdimc}{#3}% + \def\@tempa{#1}\ifx\@tempa\@empty + \@setpar{\@@par +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/uafthesis/uafthesis.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \parindent 1em% + \noindent + \hbox to 1.8em{\hss\@makefnmark}#1} +... + \edef\@currentlabel{\csname p@footnote\endcsname\@thefnmark}\@makefntext + {\rule{\z@}{\footnotesep}\ignorespaces + #1\strut}}} + +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/uwthesis/uwthesis.cls +--------------------------------------------------------- +\long\def\@makefntext#1{\parindent 1em\noindent \hangindent\parindent + \def\baselinestretch{1.0}\normalfont + \hb@xt@1.8em{\hss\@makefnmark}#1} + +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/uwa-letterhead/uwa-letterhead.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \global\@topnum\z@ +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/onrannual/onrannual.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \newpage +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/thuthesis/thuthesis.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \begingroup + % 序号取消上标 + \def\@makefnmark{\hbox{\normalfont\@thefnmark}}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/gaceta/gaceta.cls +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/jpsj/jpsj2.cls +--------------------------------------------------------- + \long\def\@makefntext##1{%\vskip2\p@ + \hangindent8\p@ \hangafter1 \noindent + \hb@xt@1em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/gmutils/gmtypos.sty +--------------------------------------------------------- + \ampulexdef#1{\long\def\@makefntext}% + \if@twocolumn{\gmu@ATfootnotes\if@twocolumn}% Ampulex redefinition + % of \incs{maketitle} for \pk{mwcls}. +} +... + \long\pdef\@makefntext##1{% + \ifdefined\@parindent \parindent\@parindent + \else \parindent 1em\relax + \fi +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/resphilosophica/resphilosophica.cls +--------------------------------------------------------- +\def\@makefntext{\noindent\@makefnmark + \if@enddoc\else + \immediate\write\@mainaux% + {\string\xdef\string\lastfootnote@page{\the\c@page}}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/tools/ftnright.sty +--------------------------------------------------------- +\long\def\@makefntext#1{\parindent 1em + \noindent\hbox to 2em{}% + \llap{\@thefnmark.\,\,}#1} +\setlength{\skip\footins} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/elegantnote/elegantnote.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ntgclass/rapport1.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent\z@ + \def\labelitemi{\textendash}\@revlabeltrue + \leavevmode\@textsuperscript{\@thefnmark}\kern1em\relax ##1} + \renewcommand*\thefootnote{\@fnsymbol\c@footnote}% +... + \long\def\@makefntext{\@xmakefntext{% + \@textsuperscript{\normalfont\@thefnmark}}}% + \if@twocolumn + \ifnum \col@number=\@ne +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ntgclass/brief.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \noindent\hb@xt@\leftmargini{\normalfont\@thefnmark.\hfil}#1} +\newcommand*\dutchbrief{% + \def\uwbrieftekst{Uw brief van} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ntgclass/boek.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent\z@ + \def\labelitemi{\textendash}\@revlabeltrue + \leavevmode\@textsuperscript{\@thefnmark}\kern1em\relax ##1} + \renewcommand*\thefootnote{\@fnsymbol\c@footnote}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ntgclass/rapport3.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent\z@ + \def\labelitemi{\textendash}\@revlabeltrue + \leavevmode\@textsuperscript{\@thefnmark}\kern1em\relax ##1} + \renewcommand*\thefootnote{\@fnsymbol\c@footnote}% +... + \long\def\@makefntext{\@xmakefntext{% + \@textsuperscript{\normalfont\@thefnmark}}}% + \if@twocolumn + \ifnum \col@number=\@ne +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ntgclass/boek3.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent\z@ + \def\labelitemi{\textendash}\@revlabeltrue + \leavevmode\@textsuperscript{\@thefnmark}\kern1em\relax ##1} + \renewcommand*\thefootnote{\@fnsymbol\c@footnote}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ntgclass/artikel2.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent\z@ + \def\labelitemi{\textendash}\@revlabeltrue + \leavevmode\@textsuperscript{\@thefnmark}\kern1em\relax ##1} + \renewcommand*\thefootnote{\@fnsymbol\c@footnote}% +... + \long\def\@makefntext##1{\parindent\z@ + \def\labelitemi{\textendash}% + \leavevmode\hb@xt@.5\unitindent{% + \@textsuperscript{\normalfont\@thefnmark}\hfil}##1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ntgclass/artikel3.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent\z@ + \def\labelitemi{\textendash}\@revlabeltrue + \leavevmode\@textsuperscript{\@thefnmark}\kern1em\relax ##1} + \renewcommand*\thefootnote{\@fnsymbol\c@footnote}% +... + \long\def\@makefntext{\@xmakefntext{% + \@textsuperscript{\normalfont\@thefnmark}}}% + \if@twocolumn + \ifnum \col@number=\@ne +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ntgclass/artikel1.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent\z@ + \def\labelitemi{\textendash}\@revlabeltrue + \leavevmode\@textsuperscript{\@thefnmark}\kern1em\relax ##1} + \renewcommand*\thefootnote{\@fnsymbol\c@footnote}% +... + \long\def\@makefntext{\@xmakefntext{% + \@textsuperscript{\normalfont\@thefnmark}}}% + \if@twocolumn + \ifnum \col@number=\@ne +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/cdpbundl/letteracdp.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \noindent + \hangindent 5\p@ + \hb@xt@5\p@{\hss\@makefnmark}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/courseoutline/courseoutline.cls +--------------------------------------------------------- +\setlength {\evensidemargin}{0.0in} % right margin 1.0 inch +\setlength {\textwidth}{6.5in} % right margin 1.0 inch +\setlength {\footnotesep}{14pt} % baseline skip for fn's 1st line +\setlength {\headheight}{0.2in} % make room for header +\setlength {\headsep}{0.2in} % modest header separation +\setlength {\parskip}{0.2in} % set a paragraph skip +\setlength {\parindent}{0.0in} % no para indents +% +% redefine the titlematter +% +\renewcommand\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}% + \newpage + \global\@topnum\z@ % Prevents figures from going at top of page. + \@maketitle + \thispagestyle{empty}\@thanks + \endgroup + \setcounter{footnote}{0}% + \global\let\thanks\relax + \global\let\maketitle\relax + \global\let\@maketitle\relax + \global\let\@thanks\@empty + % + \global\let\university\@empty + \global\let\department\@empty + \global\let\coursename\@empty +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/stellenbosch/ustitle.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/chextras/chextras.sty +--------------------------------------------------------- + \long\def\@makefntext#1{\settowidth\@tempdima{.\kern\marginparsep} + \parindent\z@ + \advance\parindent-\@tempdima + \rule\z@\footnotesep +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/aiaa/aiaa-tc.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \newpage +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/oberdiek/enparen.sty +--------------------------------------------------------- + \long\def\@makefntext##1{% + \enparen@org@makefntext{% + \enparenBeginContext{footnote}% + ##1% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/cleveref/cleveref.sty +--------------------------------------------------------- +\long\def\@makefntext{% + \cref@constructprefix{footnote}{\cref@result}% + \protected@edef\cref@currentlabel{% + [footnote][\arabic{footnote}][\cref@result]% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ametsoc/ametsoc.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\footnotesize\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1 + \vskip1sp +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/combine/combine.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/active-conf/active-conf.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent##1}% + \@note + \setcounter{footnote}{0} + \global\def\note##1{% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/iso/isov2.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \parindent 1em% + \noindent + \hbox to 1.8em{\hss\@makefnmark}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/elegantpaper/elegantpaper.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@0.1em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/fnpara/fnpara.sty +--------------------------------------------------------- +\long\def\@makefntext#1{% +% \parindent 1em% +% \noindent +% \hb@xt@1.8em{\hss\@makefnmark}#1 +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/bxjscls/bxjsarticle.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\advance\leftskip 3\jsZw + \parindent 1\jsZw\noindent + \llap{\@textsuperscript{\normalfont\@thefnmark}\hskip0.3\jsZw}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/bxjscls/bxjsbook.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\advance\leftskip 3\jsZw + \parindent 1\jsZw\noindent + \llap{\@textsuperscript{\normalfont\@thefnmark}\hskip0.3\jsZw}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/bxjscls/bxjsslide.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\advance\leftskip 3\jsZw + \parindent 1\jsZw\noindent + \llap{\@textsuperscript{\normalfont\@thefnmark}\hskip0.3\jsZw}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/bxjscls/bxjsreport.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\advance\leftskip 3\jsZw + \parindent 1\jsZw\noindent + \llap{\@textsuperscript{\normalfont\@thefnmark}\hskip0.3\jsZw}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/lettre/lettre.cls +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/titlefoot/titlefoot.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex/aip4-2.rtx +--------------------------------------------------------- +\def\@makefntext#1{% + \def\baselinestretch{1}% + \leftskip1em% + \parindent1em% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex/aps4-2.rtx +--------------------------------------------------------- +\long\def\@makefntext#1{% + \def\baselinestretch{1}% + \leftskip1em% + \parindent1em% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex/revtex4-2.cls +--------------------------------------------------------- +\def\@makefntext#1{% + \def\baselinestretch{1}% + \parindent1em% + \noindent +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex/sor4-2.rtx +--------------------------------------------------------- +\def\@makefntext#1{% + \def\baselinestretch{1}% + \leftskip1em% + \parindent1em% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex/aapm4-2.rtx +--------------------------------------------------------- +\def\@makefntext#1{% + \def\baselinestretch{1}% + \leftskip1em% + \parindent1em% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/lni/lni.cls +--------------------------------------------------------- + \long\def\@makefntext##1{% + \@setpar{\@@par + \@tempdima = \hsize + \advance\@tempdima -1em +... +\long\def\@makefntext#1{% + \parindent \fnindent% + \leftskip \fnindent% Einrückung vor der footnotemark + \noindent +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/arabtex/arabrep.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{\hss\@makefnmark}##1}% + \if@twocolumn + \ifnum \col@number=\@ne +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/arabtex/arabrep1.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{\hss\@makefnmark}##1}% + \if@twocolumn + \ifnum \col@number=\@ne +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/llncs/llncs.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \parindent \fnindent% + \leftskip \fnindent% + \noindent +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/frankenstein/blkcntrl.sty +--------------------------------------------------------- +\defcommand\@makefntext [1] {% + \setlength\parindent{\@ne em}% + \noindent + \hb@xt@ 1.8em{\hss\@makefnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/frankenstein/blkcntrl.stq +--------------------------------------------------------- +\defcommand\@makefntext [1] {% + \setlength\parindent{\@ne em}% + \noindent + \hb@xt@ 1.8em{\hss\@makefnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/cmpj/cmpj2.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/cmpj/cmpj3.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/cmpj/cmpj.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/pracjourn/pracjourn.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \newpage +... +\def\@makefntext#1{% + \parindent 0em\relax + \makebox[1.5em][l]{\normalfont\footnotesize\@thefnmark.}#1} +\def\@ifx@empty#1{% Implicit #2#3 +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/extsizes/extbook.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/extsizes/extletter.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \noindent + \hangindent 5\p@ + \hb@xt@5\p@{\hss\@makefnmark}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/extsizes/extarticle.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/extsizes/extproc.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \twocolumn[\@maketitle]% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/extsizes/extreport.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/h2020proposal/h2020proposal.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \newpage +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/biblatex-gb7714-2015/gb7714-2015ms.bbx +--------------------------------------------------------- + \long\def\@makefntext##1{%增加了脚注标记与正文的间隔 + \parindent 1em\noindent \hb@xt@ 0em{\hss \@makefnmark\makebox[\footbiblabelsep]{}}##1} + + } +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/biblatex-gb7714-2015/gb7714-2015mx.bbx +--------------------------------------------------------- + \long\def\@makefntext##1{%增加了脚注标记与正文的间隔 + \parindent 1em\noindent \hb@xt@ 0em{\hss \@makefnmark\makebox[\footbiblabelsep]{}}##1} + + } +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/biblatex-gb7714-2015/gb7714-2015ay.bbx +--------------------------------------------------------- + \long\def\@makefntext##1{%增加了脚注标记与正文的间隔 + \parindent 1em\noindent \hb@xt@ 0em{\hss \@makefnmark\makebox[\footbiblabelsep]{}}##1} + + } +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/biblatex-gb7714-2015/gb7714-2015.bbx +--------------------------------------------------------- + \long\def\@makefntext##1{%增加了脚注标记与正文的间隔 + \parindent 1em\noindent \hb@xt@ 0em{\hss \@makefnmark\makebox[\footbiblabelsep]{}}##1} + + } +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/suftesi/suftesi.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/mwcls/mwrep.cls +--------------------------------------------------------- + \long\def\@makefntext##1{ + \parindent\@parindent + \@textsuperscript{\normalfont\@thefnmark}\enspace##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/mwcls/mwart.cls +--------------------------------------------------------- + \long\def\@makefntext##1{ + \parindent\@parindent + \@textsuperscript{\normalfont\@thefnmark}\enspace##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/mwcls/mwbk.cls +--------------------------------------------------------- + \long\def\@makefntext##1{ + \parindent\@parindent + \@textsuperscript{\normalfont\@thefnmark}\enspace##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/tugboat/ltugboat.cls +--------------------------------------------------------- +\long\def\@makefntext#1{\parindent 1em\noindent\hb@xt@2em{}% + \llap{\@makefnmark}\null$\mskip5mu$#1} + +%% \long\def\@makefntext#1{\parindent 1em +... + \def\@makefntext##1{##1}% + \footnotetext{\noindent #1#2}% + \endgroup +} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ptptex/ptptex.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% +\parindent 1.5em\noindent \footnotesize % +\hbox to 2.5em{\hss$^{\@thefnmark}$}\hskip3\p@#1} +\gdef\@thanks{} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/aguplus/aguplus.sty +--------------------------------------------------------- + \long\def\@makefntext##1{##1} + \footnotetext{{\parindent=1em\indent + \let\@elt=\par\@titlenote}} + \fi +... + \long\def\@makefntext##1{##1} + \footnotetext{{\parindent=10pt\indent + \parskip=6pt\let\@elt=\par\@titlenote}} + \fi +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/aguplus/aguplus.cls +--------------------------------------------------------- + \long\def\@makefntext##1{##1} + \footnotetext{{\parindent=1em\indent + \let\@elt=\par\@titlenote}} + \fi +... + \long\def\@makefntext##1{##1} + \footnotetext{{\parindent=10pt\indent + \parskip=6pt\let\@elt=\par\@titlenote}} + \fi +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/protocol/protocol.cls +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/cje/cje.cls +--------------------------------------------------------- + \long\def\@makefntext##1{%\parindent 1em + \noindent +% \hb@xt@1.8em{% +% \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% +... +\long\def\@makefntext#1{\raggedright\@setpar{\@@par\@tempdima \hsize + \advance\@tempdima-\@footindent + \parshape \@ne \@footindent \@tempdima}\par + \noindent \hbox to \z@{\hss\@thefnmark\enskip}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/tufte-latex/tufte-common.def +--------------------------------------------------------- +\long\def\@makefntext#1{\@textsuperscript{\@tufte@sidenote@font\tiny\@thefnmark}\,\footnotelayout#1} + +% Set the in-text footnote mark in the same typeface as the body text itself. +\def\@makefnmark{\hbox{\@textsuperscript{\normalfont\footnotesize\@thefnmark}}} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/amscls/amsdtx.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hbox to1.8em{\hss$\m@th^{\@thefnmark}$}##1}% + \if@twocolumn + \ifnum \col@number=\@ne +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/amscls/amsbook.cls +--------------------------------------------------------- +\def\@makefntext{\indent\@makefnmark} +\long\def\@footnotetext#1{% + \insert\footins{% + \normalfont\footnotesize +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/amscls/amsproc.cls +--------------------------------------------------------- +\def\@makefntext{\indent\@makefnmark} +\long\def\@footnotetext#1{% + \insert\footins{% + \normalfont\footnotesize +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/amscls/amsart.cls +--------------------------------------------------------- +\def\@makefntext{\indent\@makefnmark} +\long\def\@footnotetext#1{% + \insert\footins{% + \normalfont\footnotesize +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/quantumarticle/quantumarticle.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \ifbool{@twocolumn} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ltxmisc/iagproc.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \twocolumn[\@maketitle]% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/acmart/acmart.cls +--------------------------------------------------------- +\def\@makefntext{\noindent\@makefnmark} +\if@ACM@sigchiamode +\long\def\@footnotetext#1{\marginpar{% + \reset@font\small +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/memoir/memoir.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\makethanksmark ##1} + \if@twocolumn + \ifnum \col@number=\@ne + \@maketitle +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/footnotebackref/footnotebackref.sty +--------------------------------------------------------- +% than redefine the \@makefntext and \@makefnmark +% The \@makefnmark macro is redefined in the space of +% the \@makefntext macro +% So the footnote numbers in the main text are not influenced +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/bangtex/barticle.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/bangtex/bletter.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \noindent + \hangindent 5\p@ + \hb@xt@5\p@{\hss\@makefnmark}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/bangtex/bbook.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\sbng\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/elbioimp/elbioimp.cls +--------------------------------------------------------- + \def \@makefntext ##1{\noindent + \small \@thefnmark. \it ##1} + \renewcommand{\thempfootnote}% + {\arabic{mpfootnote}} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ebsthesis/ebsthesis.cls +--------------------------------------------------------- + \long\def\@makefntext#1{% + \bgroup + \setbox\@tempboxa\hbox{% + \ifdim\footnotemargin>0pt +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/coursepaper/coursepaper.cls +--------------------------------------------------------- + \setlength {\evensidemargin}{0.5in} % right margin 1.5 inch + \setlength {\textwidth}{5.5in} % right margin 1.5 inch + \spacing{2} % double spacing for final + \renewenvironment{quote} % redef as single spaced + {\oldquote\spacing{1}} + {\oldendquote\spacing{2}} + \renewenvironment{quotation} % redef as single spaced + {\oldquotation\spacing{1}} + {\oldendquotation\spacing{2}} + \renewenvironment{verse} % redef as single spaced + {\oldquotation\spacing{1}} + {\oldendquotation\spacing{2}} +} +\setlength {\footnotesep}{14pt} % baseline skip for fn's 1st line +\setlength {\headheight}{0.2in} % make room for header +\setlength {\headsep}{0.2in} % modest header separation +\setlength {\parskip}{0.2in} % set a paragraph skip +\setlength {\parindent}{0.2in} % I hate unindented first lines +\renewenvironment{bibliography}[1] % automatically enter toc line + {\addcontentsline{toc}{chapter}{Bibliography}\oldbibliography {#1}} + {\oldendbibliography} +% +% Make footnotes single spaced +% +% code shamelessly stolen from setspace.sty +% written by Geoffrey Tobin <G.Tobin@latrobe.edu.au> +% +\long\def\@footnotetext#1{% + \insert\footins{% + \def\baselinestretch {1}% + \reset@font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth + \@parboxrestore + \protected@edef\@currentlabel{% + \csname p@footnote\endcsname\@thefnmark + }% + \color@begingroup + \@makefntext{% + \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% + \color@endgroup}} +% +% redefine the titlematter +% +\renewcommand\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}% + \newpage + \global\@topnum\z@ % Prevents figures from going at top of page. + \@maketitle + \thispagestyle{empty}\@thanks + \endgroup + \setcounter{footnote}{0}% + \global\let\thanks\relax + \global\let\maketitle\relax + \global\let\@maketitle\relax + \global\let\@thanks\@empty + \global\let\@author\@empty + \global\let\@date\@empty + \global\let\@title\@empty + % + \global\let\@studentnumber\@empty + \global\let\@coursenumber\@empty + \global\let\@coursename\@empty + \global\let\@coursesection\@empty + \global\let\@instructor\@empty + \global\let\@college\@empty + % + \global\let\title\relax + \global\let\author\relax + \global\let\date\relax + \global\let\and\relax +} +% +\def\@maketitle{% + \newpage + \null + \vskip 2em% + \begin{flushleft}% + \begin{spacing}{1}% + {\sffamily \LARGE \@title \par}% + \vskip 2em% + {\sffamily \large\lineskip .75em\@author}\\% + \sffamily \@studentnumber% + \vskip 1em% + \sffamily \@date + \vskip 3em% + \sffamily \@college\\% + \sffamily \@coursenumber\hskip 6pt\@coursesection\hskip 6pt% + \@coursename\\% + \sffamily For: \@instructor% + \par% + \end{spacing}% + \end{flushleft}\hrule\vskip 1em\par + \par + \vskip 1.5em} +% +% make section titles less obnoxious +% +\renewcommand\section{\@startsection {section}{1}{\z@}% + {-3.5ex \@plus -1ex \@minus -.2ex}% + {2.3ex \@plus.2ex}% + {\normalfont\large\bfseries}} +\renewcommand\subsection{\@startsection{subsection}{2}{\z@}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\normalfont\normalsize\bfseries}} +\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\normalfont\normalsize\bfseries}} +\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}% + {3.25ex \@plus1ex \@minus.2ex}% + {-1em}% + {\normalfont\normalsize\bfseries}} +\renewcommand\subparagraph{\@startsection{subparagraph}{5}{\parindent}% + {3.25ex \@plus1ex \@minus .2ex}% + {-1em}% + {\normalfont\normalsize\bfseries}} +% +% Set up headers +% +\def\ps@myheadings{% + \let\@oddfoot\@empty\let\@evenfoot\@empty + \def\@evenhead{\thepage -- \slshape\leftmark\hfil}% + \def\@oddhead{\hfil{\slshape\rightmark} -- \thepage}% + \let\@mkboth\@gobbletwo + \let\sectionmark\@gobble + \let\subsectionmark\@gobble + } +% +% Position the abstract depending on presence of titlepage +% +\if@titlepage + \renewenvironment{abstract}{% + \titlepage + \null\vfil + \@beginparpenalty\@lowpenalty + \begin{center}% + \bfseries \abstractname + \@endparpenalty\@M + \end{center}}% + {\par\vfil\null\endtitlepage} +\fi +% +% change some names +% +\renewcommand\contentsname{Table of Contents} +\renewcommand\refname{Bibliography} +% +% \epigraph{text}{byline} +% +\newcommand{\epigraph}[2]{\begin{flushright}\begin{minipage}{4in}% + \spacing{1}#1\begin{flushright}#2\end{flushright}% + \hrule\end{minipage}\vskip 12pt\end{flushright}} +% +%% End of file `coursepaper.cls'. +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/kotex-utf/contrib/dhucsfn.sty +--------------------------------------------------------- + \long\def\@makefntext#1{ + \settowidth{\foot@parindent}{\fn@markstyle} + \@setpar{\@@par\@tempdima \hsize + \advance\@tempdima-\foot@parindent +... + \long\def\@makefntext#1{% + \hbox{\fn@markstyle\hskip\footnumbersep #1} + }% +} +... + \long\def\@makefntext#1{% + \fn@markstyle\ifdim\footnumbersep=\z@\else~\fi #1 + }% +} +... + \long\def\@makefntext#1{ + \settowidth{\foot@parindent}{\reset@font 각주} + \settowidth{\footnumbersep}{\reset@font 주} + \divide\footnumbersep by2 +... + \long\def\@makefntext#1{ + \settowidth{\leftskip}{\reset@font 각주} + \settowidth{\foot@parindent}{\fn@markstyle} + \settowidth{\footnumbersep}{\reset@font 주} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ucthesis/ucthesis.cls +--------------------------------------------------------- +% \long\def\@makefntext#1{\@setpar{\@@par\@tempdima \hsize +% \advance\@tempdima-10pt\parshape \@ne 10pt \@tempdima}\par +% \parindent 1em\noindent +% \hbox to \z@{\hss$\m@th^{\@thefnmark}$}#1} +... +\long\def\@makefntext#1{\parindent 1em\noindent + \hbox to 1.8em{\hss$\m@th^{\@thefnmark}$}#1} + +% \@makefnmark : A macro to generate the footnote marker that goes +... + \edef\@currentlabel{\csname p@footnote\endcsname\@thefnmark}\@makefntext + {\rule{\z@}{\footnotesep}\ignorespaces + #1\strut}}} + +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/apa/apa.cls +--------------------------------------------------------- +\long\def\@makefntext#1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont{\tiny\@thefnmark}\hspace{1.5pt}}}#1}% + +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/uestcthesis/uestcthesis.cls +--------------------------------------------------------- +\def\@makefntext #1{\ifFN@hangfoot \bgroup \setbox \@tempboxa \hbox {\ifdim +\footnotemargin >0pt \hb@xt@ \footnotemargin {\hbox { \normalfont \@thefnmark} +\hss }\else \hbox { \normalfont \@thefnmark} \fi }\leftmargin \wd \@tempboxa +\rightmargin \z@ \linewidth \columnwidth \advance \linewidth -\leftmargin +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/gmdoc/gmdoc.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn \twocolumn [\@maketitle ]% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/titling/titling.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\makethanksmark ##1} + \null\vfil + \vskip 60\p@ + \vspace*{\droptitle} +... + \long\def\@makefntext##1{\makethanksmark ##1} + \if@twocolumn + \ifnum \col@number=\@ne + \@maketitle +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/chletter/chletter.cls +--------------------------------------------------------- +\long\def\@makefntext#1{\noindent\hb@xt@\z@{\hss\@makefnmark}#1} +\def\fromname{\@author} +\def\fromsig{\@author} +\let\fromlocation\@empty +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/jurarsp/jurarsp.sty +--------------------------------------------------------- +\long\def\@makefntext#1{% + \rsp@fntrue% + \@setpar{\@@par + \@tempdima = \hsize +... +/usr/local/texlive/2021/texmf-dist/tex/latex/kluwer/klunote.sty +--------------------------------------------------------- +% \long\def\@makefntext#1{\parindent 1em\noindent +% \hbox to 1.5em{\hss$^{\@thefnmark}$}\hskip0.5em\footnotesize#1} +% \def\@makefnmark{\hbox{$^{\@thefnmark}\m@th$}} +% SK: reimplemented with \textsuperscript, following LaTeX format +... +\long\def\@makefntext#1{\parindent 1em\noindent + \hbox to 1.5em{\hss\textsuperscript{\@thefnmark}}% + \hskip0.5em\footnotesize#1} +\def\@makefnmark{\hbox{\textsuperscript{\@thefnmark}}} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/kluwer/kluwer.cls +--------------------------------------------------------- +\long\def\@makefntext#1{\parindent 1em\noindent + \hbox to 1.5em{\hss\textsuperscript{\@thefnmark}}% + \hskip0.5em\footnotesize#1} +\def\@makefnmark{\hbox{\textsuperscript{\@thefnmark}}} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/asaetr/asaesub.sty +--------------------------------------------------------- + \edef\@currentlabel{\csname p@footnote\endcsname\@thefnmark}\@makefntext + {\rule{\z@}{\footnotesep}\ignorespaces + #1\strut}}} + +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/asaetr/asaetr.sty +--------------------------------------------------------- +\long\def\@makefntext#1{\parindent 1em\noindent + \hbox to 1.8em{\hss$^{\@thefnmark}$}#1} + + +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/refman/refrep.cls +--------------------------------------------------------- + \long\def\@makefntext##1{% + \@setpar{\@@par + \@tempdima = \hsize + \advance\@tempdima -1em +... + \long\def\@makefntext##1{% + \@setpar{\@@par + \@tempdima = \hsize + \advance\@tempdima -1em +... +\long\def\@makefntext#1{% + \@setpar{\@@par + \@tempdima = \hsize + \advance\@tempdima -1em +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/refman/refart.cls +--------------------------------------------------------- + \long\def\@makefntext##1{% + \@setpar{\@@par + \@tempdima = \hsize + \advance\@tempdima -1em +... + \long\def\@makefntext##1{% + \@setpar{\@@par + \@tempdima = \hsize + \advance\@tempdima -1em +... +\long\def\@makefntext#1{% + \@setpar{\@@par + \@tempdima = \hsize + \advance\@tempdima -1em +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/lwarp/lwarp-footnote.sty +--------------------------------------------------------- +\long\def\@makefntext#1{\textsuperscript{\@thefnmark}~#1} + +\LWR@ProvidesPackagePass{footnote}[1997/01/28] + +... +\long\def\@makefntext#1{\textsuperscript{\@thefnmark}~{#1}} + +\def\spewnotes{% + \endgroup% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/lwarp/lwarp.sty +--------------------------------------------------------- +\long\def\@makefntext#1{\textsuperscript{\@thefnmark}~{#1}} +\def\@makefnmark{% + \textsuperscript{\@thefnmark}% +} +... +\long\def\@makefntext##1{% +\textsuperscript{\@thefnmark}~% +{##1}% +}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/lwarp/lwarp-titling.sty +--------------------------------------------------------- + \long\def\@makefntext##1{% + \makethanksmark~% + {##1}% + }% \@makefntext +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/afthesis/afthesis.cls +--------------------------------------------------------- + \edef\@currentlabel{\csname p@footnote\endcsname\@thefnmark}\@makefntext + {\rule{\z@}{\footnotesep}\ignorespaces + #1\strut}}} + +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ijmart/ijmart.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\noindent\hangindent=2em\hangafter=1 + \hb@xt@2em{% + \hss\@textsuperscript{\normalfont\footnotesize\@thefnmark\space}}##1}% + \def\footnoterule{\kern-3pt\hrule width 2in\kern 2.6pt} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/oup-authoring-template/oup-authoring-template.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 3mm\noindent + \if@traditional\if@small\@hangfrom{{\normalfont\@thefnmark}\enskip}\else\@textsuperscript{\normalfont\@thefnmark}\fi\else\@textsuperscript{\normalfont\@thefnmark}\fi + ##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/akletter/akletter.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \noindent + \hangindent 5\p@ + \hb@xt@5\p@{\hss\@makefnmark}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex4/aps.rtx +--------------------------------------------------------- +\def\@makefntext#1{% + \def\baselinestretch{1}% + \reset@font + \footnotesize +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/revtex4/revtex4.cls +--------------------------------------------------------- +\def\@makefntext#1{% + \def\baselinestretch{1}% + \reset@font\footnotesize + \parindent 1em% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hitreport/hitreport.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \begingroup + % 序号取消上标 + \def\@makefnmark{\hbox{\normalfont\@thefnmark}}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/footnotehyper/footnotehyper.sty +--------------------------------------------------------- + \def\FNH@prefntext{\@makefntext{}}% + \iffootnotehyperwarn + \PackageInfo{footnotehyper}% + {Using the \string\@makefntext{} approach (see doc).\FNH@msgbk +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/basque-book/basque-book.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/dinbrief/dinbrief.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% + \noindent + \hangindent 5pt% + \hbox to 5pt{\hss $^{\@thefnmark}$}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/beamer/beamerbaseframecomponents.sty +--------------------------------------------------------- +\def\@makefntext#1{% + \def\insertfootnotetext{#1}% + \def\insertfootnotemark{\@makefnmark}% + \usebeamertemplate***{footnote}} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ucdavisthesis/ucdavisthesis.cls +--------------------------------------------------------- + \edef\@currentlabel{\csname p@footnote\endcsname\@thefnmark}\@makefntext + {\rule{\z@}{\footnotesep}\ignorespaces + #1\strut}\renewcommand\baselinestretch{\@spacing}}} +\ps@plain % 'plain' page style +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/computational-complexity/cclayout.sty +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/footmisx/footmisx.sty +--------------------------------------------------------- + \long\def\@makefntext#1{\leavevmode + \@makefnmark\nobreak + \hskip.5em\relax#1% + } +... + \long\def\@makefntext#1{% + \ifFN@hangfoot + \bgroup + \setbox\@tempboxa\hbox{% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/amsdtx.hyp +--------------------------------------------------------- + \long\def\@makefntext##1{% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/slides.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/book.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... + \long\def\@makefntext##1{% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/ltxguide.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... + \long\def\@makefntext##1{% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/ltnews.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/doc.hyp +--------------------------------------------------------- + \long\def\@makefntext##1{% + \hyper@currentfnmark% + \bgroup + \edef\@currenthyper{\hyper@current@fnmark} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/ftnright.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/letter.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/amsbook.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{\indent% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/ltxdoc.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... + \long\def\@makefntext##1{% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/proc.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/amsart.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{\indent% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/amsproc.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{\indent% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/article.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... + \long\def\@makefntext##1{% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hyper/report.hyp +--------------------------------------------------------- +\long\def\@makefntext#1{% + \bgroup% + \hyper@currentfnmark% + \edef\@currenthyper{\hyper@current@fnmark}% +... + \long\def\@makefntext##1{% + \hyper@currentfnmark% + \bgroup% + \edef\@currenthyper{\hyper@current@fnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/hitec/hitec.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \newpage +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/emulateapj/emulateapj.cls +--------------------------------------------------------- +\def\@makefntext#1{\mbox{}\hspace*{3mm}\@makefnmark~#1} + +\def\notetoeditor#1{}% % We do not need notes to editor in the preprint +\def\placetable#1{}% % We do not need notes to editor in the preprint +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ledmac/afoot.sty +--------------------------------------------------------- + \long\def\@makefntext#1{{$^{\@thefnmark}$}#1\nobreak } +\fi + +%%% Make the LaTeX \cs{footnote} catcode-safe, like in Plain TeX. +... + \global\long\def \@makefntext ##1{{$^{\@thefnmark }$}##1\nobreak }% + \setbox0=\hbox \bgroup % fnpara.sty is present + \floatingpenalty=20000 \footnotesize + \fi +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/footmisc/footmisc.sty +--------------------------------------------------------- + \long\def\@makefntext#1{\leavevmode + \@makefnmark\nobreak + \hskip.5em\relax#1% + } +... + \long\def\@makefntext#1{% + \ifFN@hangfoot + \bgroup + \setbox\@tempboxa\hbox{% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/footmisc/footmisc-2011-06-06.sty +--------------------------------------------------------- + \long\def\@makefntext#1{\leavevmode + \@makefnmark\nobreak + \hskip.5em\relax#1% + } +... + \long\def\@makefntext#1{% + \ifFN@hangfoot + \bgroup + \setbox\@tempboxa\hbox{% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/base/book.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/base/slides.cls +--------------------------------------------------------- +\long\def\@makefntext#1{ + \noindent + \hangindent 10\p@ + \hb@xt@10\p@{\hss\@makefnmark}#1} +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/base/doc.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hbox to1.8em{\hss$\m@th^{\@thefnmark}$}##1}% + \if@twocolumn \twocolumn [\@maketitle ]% + \else \newpage \global \@topnum \z@ \@maketitle \fi +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/base/proc.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \twocolumn[\@maketitle]% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/base/proc.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \twocolumn[\@maketitle]% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/base/doc-v3beta.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hbox to1.8em{\hss$\m@th^{\@thefnmark}$}##1}% + \if@twocolumn \twocolumn [\@maketitle ]% + \else \newpage \global \@topnum \z@ \@maketitle \fi +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/base/article.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/base/report.cls +--------------------------------------------------------- + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/twoinone/2in1.sty +--------------------------------------------------------- +\long\def\@makefntext##1{\parindent 1em\noindent +\hb@xt@1.8em{% +\hss\@textsuperscript{\normalfont\@thefnmark}}##1}% +\@maketitle +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/ltxtools/ltxtools-review.sty +--------------------------------------------------------- + \long\def\@makefntext##1{\rule\z@\footnotesep\parindent1em\noindent + \hb@xt@2em{\hss\@textsuperscript + {\normalfont\textcolor{#1}{\@thefnmark}}}% + \hspace{2\p@}\ignorespaces\textcolor{#1}{##1}% +... + \long\def\@makefntext##1{% + \rule\z@\footnotesep\parindent1em\noindent + \hb@xt@0em{\hss\@textsuperscript{\normalfont\color{#1}\@thefnmark}}% + \hspace{2\p@}\color{#1}\ignorespaces##1% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/skeyval/skeyval-testclass.cls +--------------------------------------------------------- + \long\def\@makefntext##1{% + \parindent1em\relax\noindent + \hb@xt@1.8em{\hss\@textsuperscript{% + \normalfont\skv@fnsymbol\@thefnmark}% +... +--------------------------------------------------------- +/usr/local/texlive/2021/texmf-dist/tex/latex/newlfm/newlfm.cls +--------------------------------------------------------- +\long\def\@makefntext#1{% +\noindent \hangindent 5\p@% +\hb@xt@5\p@{\hss\@makefnmark}#1}% +\renewcommand{\thefigure}{\@arabic\c@figure}% +... +--------------------------------------------------------- + +``` diff --git a/macros/latex/required/latex-lab/usage-of-kern-kern.txt b/macros/latex/required/latex-lab/usage-of-kern-kern.md index e119197b70..aac597db60 100644 --- a/macros/latex/required/latex-lab/usage-of-kern-kern.txt +++ b/macros/latex/required/latex-lab/usage-of-kern-kern.md @@ -1,3 +1,10 @@ +# Packages that use double \kern's + +Scan of TeXlive 2022 for checking ... may not be longer accurate and may contain a few false positives +(definitely contains bogus entries right now) + + +``` \ifdim\lastkern>\z@\ifdim\lastkern<5sp\relax ./bxjscls/bxjsja-minimal.def @@ -78,3 +85,4 @@ \NewDocumentCommand \@sidenotes@multisign { } {3sp} ./sidenotes/sidenotes.sty +``` diff --git a/macros/latex/required/tools/README.md b/macros/latex/required/tools/README.md index 5dba58d231..4778e9aca0 100644 --- a/macros/latex/required/tools/README.md +++ b/macros/latex/required/tools/README.md @@ -1,7 +1,7 @@ The LaTeX `tools` bundle ======================== -Release 2022-11-01 +Release 2023-06-01 Overview -------- diff --git a/macros/latex/required/tools/afterpage.dtx b/macros/latex/required/tools/afterpage.dtx index cf949c0aca..b94a85d26d 100644 --- a/macros/latex/required/tools/afterpage.dtx +++ b/macros/latex/required/tools/afterpage.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/afterpage.ins b/macros/latex/required/tools/afterpage.ins index 3aa1679f77..6fec5edc6f 100644 --- a/macros/latex/required/tools/afterpage.ins +++ b/macros/latex/required/tools/afterpage.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug reports for it can be opened at https://latex-project.org/bugs/ (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/required/tools/afterpage.pdf b/macros/latex/required/tools/afterpage.pdf Binary files differindex 0729c17175..375b75ae5d 100644 --- a/macros/latex/required/tools/afterpage.pdf +++ b/macros/latex/required/tools/afterpage.pdf diff --git a/macros/latex/required/tools/array.dtx b/macros/latex/required/tools/array.dtx index 4b163b5f18..72e2f095e9 100644 --- a/macros/latex/required/tools/array.dtx +++ b/macros/latex/required/tools/array.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/array.pdf b/macros/latex/required/tools/array.pdf Binary files differindex 26654a389b..ffdda545cc 100644 --- a/macros/latex/required/tools/array.pdf +++ b/macros/latex/required/tools/array.pdf diff --git a/macros/latex/required/tools/bm.dtx b/macros/latex/required/tools/bm.dtx index daf4dce66b..51ae53f041 100644 --- a/macros/latex/required/tools/bm.dtx +++ b/macros/latex/required/tools/bm.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/bm.ins b/macros/latex/required/tools/bm.ins index 51243a6090..a7424a0e67 100644 --- a/macros/latex/required/tools/bm.ins +++ b/macros/latex/required/tools/bm.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug reports for it can be opened at https://latex-project.org/bugs/ (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/required/tools/bm.pdf b/macros/latex/required/tools/bm.pdf Binary files differindex ad718d0741..f2b6887434 100644 --- a/macros/latex/required/tools/bm.pdf +++ b/macros/latex/required/tools/bm.pdf diff --git a/macros/latex/required/tools/calc.dtx b/macros/latex/required/tools/calc.dtx index 97ef72e7b9..c243eed8d3 100644 --- a/macros/latex/required/tools/calc.dtx +++ b/macros/latex/required/tools/calc.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/calc.pdf b/macros/latex/required/tools/calc.pdf Binary files differindex bf6ba15e27..1debba20b1 100644 --- a/macros/latex/required/tools/calc.pdf +++ b/macros/latex/required/tools/calc.pdf diff --git a/macros/latex/required/tools/changes.txt b/macros/latex/required/tools/changes.txt index 7b3e63dca5..74318d41bb 100644 --- a/macros/latex/required/tools/changes.txt +++ b/macros/latex/required/tools/changes.txt @@ -10,6 +10,30 @@ All changes above are only part of the development branch for the next release. ================================================================================ ######################### +# 2023-06-01 Release +######################### + +2023-05-11 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + + * showkeys.dtx: Use label hook if format new enough. + +2023-04-15 David Carlisle <David.Carlisle@latex-project.org> + + * shellesc.dtx: Normalise use of "." in messages. github/1008 + +2023-03-30 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * multicol.dtx (subsection{The output routines}]): + Make column min depth customizable through the command + \multicolmindepthstring defaulting to 'p' (gh/698) + +2023-02-25 Frank Mittelbach <Frank.Mittelbach@latex-project.org> + + * multicol.dtx: + Delay returning boxed multicols so that all parameters get restored first + in case the boxed multicols is used into another multicols (gh/1002) + +######################### # 2022-11-01 Release ######################### diff --git a/macros/latex/required/tools/dcolumn.dtx b/macros/latex/required/tools/dcolumn.dtx index 7415e23752..cfb7b4d33e 100644 --- a/macros/latex/required/tools/dcolumn.dtx +++ b/macros/latex/required/tools/dcolumn.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/dcolumn.pdf b/macros/latex/required/tools/dcolumn.pdf Binary files differindex 3de78c536a..3b100acf93 100644 --- a/macros/latex/required/tools/dcolumn.pdf +++ b/macros/latex/required/tools/dcolumn.pdf diff --git a/macros/latex/required/tools/delarray.dtx b/macros/latex/required/tools/delarray.dtx index d8aba52f32..86a1a6203f 100644 --- a/macros/latex/required/tools/delarray.dtx +++ b/macros/latex/required/tools/delarray.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/delarray.pdf b/macros/latex/required/tools/delarray.pdf Binary files differindex 4c15f62d47..cea166711c 100644 --- a/macros/latex/required/tools/delarray.pdf +++ b/macros/latex/required/tools/delarray.pdf diff --git a/macros/latex/required/tools/enumerate.dtx b/macros/latex/required/tools/enumerate.dtx index 89910438e9..49179cfa06 100644 --- a/macros/latex/required/tools/enumerate.dtx +++ b/macros/latex/required/tools/enumerate.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/enumerate.pdf b/macros/latex/required/tools/enumerate.pdf Binary files differindex c086811a7f..06a7029835 100644 --- a/macros/latex/required/tools/enumerate.pdf +++ b/macros/latex/required/tools/enumerate.pdf diff --git a/macros/latex/required/tools/fileerr.dtx b/macros/latex/required/tools/fileerr.dtx index 59c1bbbbec..eef222bb6e 100644 --- a/macros/latex/required/tools/fileerr.dtx +++ b/macros/latex/required/tools/fileerr.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/fileerr.pdf b/macros/latex/required/tools/fileerr.pdf Binary files differindex 8bf489506b..22c59c1158 100644 --- a/macros/latex/required/tools/fileerr.pdf +++ b/macros/latex/required/tools/fileerr.pdf diff --git a/macros/latex/required/tools/fontsmpl.dtx b/macros/latex/required/tools/fontsmpl.dtx index de2b55a608..525065cde5 100644 --- a/macros/latex/required/tools/fontsmpl.dtx +++ b/macros/latex/required/tools/fontsmpl.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/fontsmpl.pdf b/macros/latex/required/tools/fontsmpl.pdf Binary files differindex f8899bdfd2..31717658e3 100644 --- a/macros/latex/required/tools/fontsmpl.pdf +++ b/macros/latex/required/tools/fontsmpl.pdf diff --git a/macros/latex/required/tools/ftnright.dtx b/macros/latex/required/tools/ftnright.dtx index 1a7f7f584f..00e98c3f77 100644 --- a/macros/latex/required/tools/ftnright.dtx +++ b/macros/latex/required/tools/ftnright.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/ftnright.pdf b/macros/latex/required/tools/ftnright.pdf Binary files differindex d32b6e24aa..922c844c49 100644 --- a/macros/latex/required/tools/ftnright.pdf +++ b/macros/latex/required/tools/ftnright.pdf diff --git a/macros/latex/required/tools/hhline.dtx b/macros/latex/required/tools/hhline.dtx index 74143d1373..49ac1ae208 100644 --- a/macros/latex/required/tools/hhline.dtx +++ b/macros/latex/required/tools/hhline.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/hhline.pdf b/macros/latex/required/tools/hhline.pdf Binary files differindex 705e3db36a..58c210d9b3 100644 --- a/macros/latex/required/tools/hhline.pdf +++ b/macros/latex/required/tools/hhline.pdf diff --git a/macros/latex/required/tools/indentfirst.dtx b/macros/latex/required/tools/indentfirst.dtx index dff777d29d..295b678fd8 100644 --- a/macros/latex/required/tools/indentfirst.dtx +++ b/macros/latex/required/tools/indentfirst.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/indentfirst.pdf b/macros/latex/required/tools/indentfirst.pdf Binary files differindex bba40a3ee5..5eb885ce60 100644 --- a/macros/latex/required/tools/indentfirst.pdf +++ b/macros/latex/required/tools/indentfirst.pdf diff --git a/macros/latex/required/tools/layout.dtx b/macros/latex/required/tools/layout.dtx index 323705e9ba..fffa6d8e18 100644 --- a/macros/latex/required/tools/layout.dtx +++ b/macros/latex/required/tools/layout.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/layout.pdf b/macros/latex/required/tools/layout.pdf Binary files differindex 07204a943c..263351e751 100644 --- a/macros/latex/required/tools/layout.pdf +++ b/macros/latex/required/tools/layout.pdf diff --git a/macros/latex/required/tools/longtable.dtx b/macros/latex/required/tools/longtable.dtx index 72b8727d81..332a95d224 100644 --- a/macros/latex/required/tools/longtable.dtx +++ b/macros/latex/required/tools/longtable.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/longtable.ins b/macros/latex/required/tools/longtable.ins index 7f53df7c5e..5c3ad27063 100644 --- a/macros/latex/required/tools/longtable.ins +++ b/macros/latex/required/tools/longtable.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug reports for it can be opened at https://latex-project.org/bugs/ (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/required/tools/longtable.pdf b/macros/latex/required/tools/longtable.pdf Binary files differindex b41cd12101..dbae1ce35b 100644 --- a/macros/latex/required/tools/longtable.pdf +++ b/macros/latex/required/tools/longtable.pdf diff --git a/macros/latex/required/tools/multicol.dtx b/macros/latex/required/tools/multicol.dtx index aa21d75f07..2676d03aa1 100644 --- a/macros/latex/required/tools/multicol.dtx +++ b/macros/latex/required/tools/multicol.dtx @@ -20,7 +20,7 @@ % \iffalse This is a METACOMMENT % %% Package `multicol' to use with LaTeX2e -%% Copyright 1989-2019 Frank Mittelbach +%% Copyright 1989-2023 Frank Mittelbach %% %% In addition to the terms of LPPL any distributed version %% (unchanged or modified) of multicol has to keep the statement @@ -99,7 +99,7 @@ %<driver> \ProvidesFile{multicol.drv} % \fi % \ProvidesFile{multicol.dtx} - [2021/11/30 v1.9d multicolumn formatting (FMi)] + [2023/03/30 v1.9f multicolumn formatting (FMi)] % % %% @@ -1760,14 +1760,27 @@ \kept@firstmark \return@nonemptymark{bot}% \kept@botmark - \page@sofar +% \end{macrocode} +% When the boxed multicol is returned to the page it can happen +% that it doesn't fit onto it and \LaTeX{} therefore breaks +% earlier. The problem in that case is that during the generation +% \cs{hsize}, etc.\ got changed and this setting is still in effect +% right now, and if this boxed multicol is within, say, +% \texttt{multicols*} then its output routine gets very upset. We +% therefore delay returning the result by saving it in box for now +% until we have left the group below. +% \changes{v1.9e}{2023/02/25}{Delay returning boxed multicols (gh/1002)} +% \begin{macrocode} + \global\setbox\mc@boxedresult\vbox{% + \page@sofar % \end{macrocode} % % \begin{macrocode} - \global\let\kept@firstmark - \l@kept@firstmark - \global\let\kept@botmark - \l@kept@botmark + \global\let\kept@firstmark + \l@kept@firstmark + \global\let\kept@botmark + \l@kept@botmark + }% %<*marktrace> \mult@info\tw@ {Restore kept marks to\MessageBreak @@ -1879,12 +1892,15 @@ % \end{macrocode} % Now it's time to return any footnotes if we are in unrestricted % mode. In boxed mode footnotes are kept inside, but in that case -% we have to write another column status into the \texttt{.aux} +% we have to first return the saved box to the page and then write +% another column status into the \texttt{.aux} % file to support \cs{docolaction} in case we have nested % environments. % \changes{v1.8s}{2018/04/20}{Support for \cs{docolaction} (issue/39)} +% \changes{v1.9e}{2023/02/25}{Delay returning boxed multicols (gh/1002)} % \begin{macrocode} \if@boxedmulticols + \unvbox\mc@boxedresult \mc@col@status@write \else \reinsert@footnotes @@ -1949,6 +1965,7 @@ % \SpecialMainIndex{\multicolsep} % \SpecialMainIndex{\multicolbaselineskip} % \SpecialMainIndex{\partial@page} +% \SpecialMainIndex{\mc@boxedresult} % Let us end this section by allocating all the registers used so % far. % \begin{macrocode} @@ -1970,6 +1987,7 @@ \newskip\multicolbaselineskip \newbox\partial@page \newbox\last@line +\newbox\mc@boxedresult % \end{macrocode} % And here are their default values: % \begin{macrocode} @@ -2119,8 +2137,9 @@ % of the character ``p'' since that is one of the depths that % compete for the maximum. % \changes{v1.6a}{2003/03/15}{Preparing for adjusting \cs{prevdepth}} +% \changes{v1.9f}{2023/03/30}{Make column min depth customizable (gh/698)} % \begin{macrocode} - \setbox\z@\hbox{p}\global\dimen\tw@\dp\z@ + \setbox\z@\hbox{\multicolmindepthstring}\global\dimen\tw@\dp\z@ \moveright\multicol@leftmargin \hbox to\full@width{% % \end{macrocode} @@ -2135,9 +2154,11 @@ % The depths of the columns depend on their last lines. To ensure % that we will always get a similar look as far as the rules are % concerned we force the depth to be at least the depth of a -% letter~`p' (which is what we set |\dimen2| to above). +% letter~`p' or more exactly \cs{multicolmindepthstring} (which is what +% we set |\dimen2| to above). +% \changes{v1.9f}{2023/03/30}{Make column min depth customizable (gh/698)} % \begin{macrocode} - \rlap{\phantom p}% + \rlap{\phantom \multicolmindepthstring}% }% % \end{macrocode} % The processed material might consist of a last line with a @@ -2179,6 +2200,23 @@ % \end{macrocode} % \end{macro} % +% +% \begin{macro}{\multicolmindepthstring} +% The default minimum depth of each column corresponds to the depth +% of a `p' in the current font. This makes sense for Latin-based +% languages and was hard-wired intitially, but for Asian languages +% it is better to use a zero depth (and alternatively one might +% want to use the depth of a strut or a parentheses). So we now +% offer a way to adjust this while maintaining backward +% compatibility. Use \cs{renewcommand} to alter it. +% \changes{v1.9f}{2023/03/30}{Make column min depth customizable (gh/698)} +% \begin{macrocode} +\def\multicolmindepthstring{p} +% \end{macrocode} +% \end{macro} +% +% +% % \begin{macro}{\columnseprulecolor} % \changes{v1.6f}{2006/09/19}{Make the color of the rule a hook} % By default the vertical rule between columns will be in |\normalcolor|. diff --git a/macros/latex/required/tools/multicol.ins b/macros/latex/required/tools/multicol.ins index 9bbf2780ad..fa561e0bb1 100644 --- a/macros/latex/required/tools/multicol.ins +++ b/macros/latex/required/tools/multicol.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug reports for it can be opened at https://latex-project.org/bugs/ (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/required/tools/multicol.pdf b/macros/latex/required/tools/multicol.pdf Binary files differindex 56097a85a1..e7a2607bd3 100644 --- a/macros/latex/required/tools/multicol.pdf +++ b/macros/latex/required/tools/multicol.pdf diff --git a/macros/latex/required/tools/rawfonts.dtx b/macros/latex/required/tools/rawfonts.dtx index cbd1ba89ea..4b930f3ea7 100644 --- a/macros/latex/required/tools/rawfonts.dtx +++ b/macros/latex/required/tools/rawfonts.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/rawfonts.pdf b/macros/latex/required/tools/rawfonts.pdf Binary files differindex 4a77a6bb4b..865ba76370 100644 --- a/macros/latex/required/tools/rawfonts.pdf +++ b/macros/latex/required/tools/rawfonts.pdf diff --git a/macros/latex/required/tools/shellesc.dtx b/macros/latex/required/tools/shellesc.dtx index 4f60ff8d03..97ec542b66 100644 --- a/macros/latex/required/tools/shellesc.dtx +++ b/macros/latex/required/tools/shellesc.dtx @@ -1,6 +1,6 @@ % \iffalse %% Source File: shellesc.dtx -%% Copyright (C) 2015-2022 +%% Copyright (C) 2015-2023 %% %% The LaTeX Project and any individual authors listed elsewhere %% in this file. @@ -20,7 +20,7 @@ %<driver> \ProvidesFile{shellesc.drv} % \fi % \ProvidesFile{shellesc.dtx} - [2019/11/08 v1.0c unified shell escape interface for LaTeX] + [2023/04/15 v1.0d unified shell escape interface for LaTeX] % % \iffalse %<*driver> @@ -189,6 +189,7 @@ % % \begin{macro}{\ShellEscape@Lua} % \changes{v1.0a}{2019/10/13}{loging for gh/195} +% \changes{v1.0d}{2023/04/15}{Add dots in messages gh/1008} % Shared Lua code for \verb|\DelayedShellEscape| and \verb|\ShellEscape|. % \begin{macrocode} \ifx\directlua\@undefined\else @@ -197,15 +198,15 @@ local status, msg = os.execute("\luaescapestring{#1}")% if status == nil then texio.write_nl("log",% "runsystem(" .. "\luaescapestring{#1}"% - .. ")...(" .. msg .. ")\string\n") + .. ")...(" .. msg .. ").\string\n") elseif status == 0 then texio.write_nl("log",% "runsystem(" .. "\luaescapestring{#1}"% - .. ")...executed\string\n") + .. ")...executed.\string\n") else texio.write_nl("log",% "runsystem(" .. "\luaescapestring{#1}"% - .. ")...failed " .. (msg or "") .. "\string\n") + .. ")...failed. " .. (msg or "") .. "\string\n") end }} \fi diff --git a/macros/latex/required/tools/shellesc.pdf b/macros/latex/required/tools/shellesc.pdf Binary files differindex 77ca2657ca..abd95516e0 100644 --- a/macros/latex/required/tools/shellesc.pdf +++ b/macros/latex/required/tools/shellesc.pdf diff --git a/macros/latex/required/tools/showkeys.dtx b/macros/latex/required/tools/showkeys.dtx index 3aed90d304..9841004156 100644 --- a/macros/latex/required/tools/showkeys.dtx +++ b/macros/latex/required/tools/showkeys.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. @@ -39,7 +39,7 @@ %<driver> \ProvidesFile{showkeys.drv} % \fi % \ProvidesFile{showkeys.dtx} - [2022/04/12 v3.18 Show cite and label keys (DPC, MH)] + [2023/05/11 v3.19 Show cite and label keys (DPC, MH)] % % \iffalse %<*driver> @@ -342,16 +342,20 @@ % \begin{macro}{\label} % \changes{v3.09}{1996/08/30} % {Add extra group so brace hack works. Donald Arseneau tools/2147} +% \changes{v3.19}{2023/05/11} +% {Use label hook if format is new enough.} % The new definition, print the argument, and then do the old % definition. % \begin{macrocode} -\def\label#1{% +\@ifl@t@r\fmtversion{2023-06-01} + {\AddToHookWithArguments{label}{\SK@\SK@@label{#1}}} + {\def\label#1{% \@bsphack \SK@\SK@@label{#1}% \begingroup \SK@label{#1}% \endgroup - \@esphack} + \@esphack}} % \end{macrocode} % \end{macro} % diff --git a/macros/latex/required/tools/showkeys.pdf b/macros/latex/required/tools/showkeys.pdf Binary files differindex 010d132155..723b001ee1 100644 --- a/macros/latex/required/tools/showkeys.pdf +++ b/macros/latex/required/tools/showkeys.pdf diff --git a/macros/latex/required/tools/somedefs.dtx b/macros/latex/required/tools/somedefs.dtx index 24916b4286..02653a1393 100644 --- a/macros/latex/required/tools/somedefs.dtx +++ b/macros/latex/required/tools/somedefs.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/somedefs.pdf b/macros/latex/required/tools/somedefs.pdf Binary files differindex a270a16e17..71ad9c4617 100644 --- a/macros/latex/required/tools/somedefs.pdf +++ b/macros/latex/required/tools/somedefs.pdf diff --git a/macros/latex/required/tools/tabularx.dtx b/macros/latex/required/tools/tabularx.dtx index 0d1cbeac34..177d92f12f 100644 --- a/macros/latex/required/tools/tabularx.dtx +++ b/macros/latex/required/tools/tabularx.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/tabularx.ins b/macros/latex/required/tools/tabularx.ins index 0c6d26e940..6e81e93432 100644 --- a/macros/latex/required/tools/tabularx.ins +++ b/macros/latex/required/tools/tabularx.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug reports for it can be opened at https://latex-project.org/bugs/ (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/required/tools/tabularx.pdf b/macros/latex/required/tools/tabularx.pdf Binary files differindex c9c48f7a32..185925ebfb 100644 --- a/macros/latex/required/tools/tabularx.pdf +++ b/macros/latex/required/tools/tabularx.pdf diff --git a/macros/latex/required/tools/theorem.dtx b/macros/latex/required/tools/theorem.dtx index 2dc0412efb..58476db07e 100644 --- a/macros/latex/required/tools/theorem.dtx +++ b/macros/latex/required/tools/theorem.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/theorem.pdf b/macros/latex/required/tools/theorem.pdf Binary files differindex 7645a71fa2..28dec0a5bd 100644 --- a/macros/latex/required/tools/theorem.pdf +++ b/macros/latex/required/tools/theorem.pdf diff --git a/macros/latex/required/tools/tools-overview.pdf b/macros/latex/required/tools/tools-overview.pdf Binary files differindex 6080503698..a456c299aa 100644 --- a/macros/latex/required/tools/tools-overview.pdf +++ b/macros/latex/required/tools/tools-overview.pdf diff --git a/macros/latex/required/tools/tools-overview.tex b/macros/latex/required/tools/tools-overview.tex index 882a2ae77f..3bc325d67c 100644 --- a/macros/latex/required/tools/tools-overview.tex +++ b/macros/latex/required/tools/tools-overview.tex @@ -1,7 +1,7 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesFile{tools-overview.tex}[2015/03/31 v1.0 Tools overview] -% Copyright (C) 2006-2022 +% Copyright (C) 2006-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/tools.ins b/macros/latex/required/tools/tools.ins index b93f649153..6898faead3 100644 --- a/macros/latex/required/tools/tools.ins +++ b/macros/latex/required/tools/tools.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -49,7 +49,7 @@ reports for it can be opened at https://latex-project.org/bugs/ (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/required/tools/trace.dtx b/macros/latex/required/tools/trace.dtx index 93906eb76b..788f831620 100644 --- a/macros/latex/required/tools/trace.dtx +++ b/macros/latex/required/tools/trace.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/trace.pdf b/macros/latex/required/tools/trace.pdf Binary files differindex 1ca485dc97..cd6291818f 100644 --- a/macros/latex/required/tools/trace.pdf +++ b/macros/latex/required/tools/trace.pdf diff --git a/macros/latex/required/tools/varioref.dtx b/macros/latex/required/tools/varioref.dtx index 579c411868..e801c54f81 100644 --- a/macros/latex/required/tools/varioref.dtx +++ b/macros/latex/required/tools/varioref.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/varioref.ins b/macros/latex/required/tools/varioref.ins index cef11f9c2f..dcc41d0176 100644 --- a/macros/latex/required/tools/varioref.ins +++ b/macros/latex/required/tools/varioref.ins @@ -3,7 +3,7 @@ %% driver files from the doc files in this package when run through %% LaTeX or TeX. %% -%% Copyright (C) 1993-2022 +%% Copyright (C) 1993-2023 %% The LaTeX Project and any individual authors listed elsewhere %% in this file. %% @@ -45,7 +45,7 @@ The source is maintained by the LaTeX Project team and bug reports for it can be opened at https://latex-project.org/bugs/ (but please observe conditions on bug reports sent to that address!) -Copyright (C) 1993-2022 +Copyright (C) 1993-2023 The LaTeX Project and any individual authors listed elsewhere in this file. diff --git a/macros/latex/required/tools/varioref.pdf b/macros/latex/required/tools/varioref.pdf Binary files differindex 46aa65461e..4382c23f44 100644 --- a/macros/latex/required/tools/varioref.pdf +++ b/macros/latex/required/tools/varioref.pdf diff --git a/macros/latex/required/tools/verbatim.dtx b/macros/latex/required/tools/verbatim.dtx index 2018e85505..0085f166ea 100644 --- a/macros/latex/required/tools/verbatim.dtx +++ b/macros/latex/required/tools/verbatim.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/verbatim.pdf b/macros/latex/required/tools/verbatim.pdf Binary files differindex 43684a53b9..94a1159503 100644 --- a/macros/latex/required/tools/verbatim.pdf +++ b/macros/latex/required/tools/verbatim.pdf diff --git a/macros/latex/required/tools/xr.dtx b/macros/latex/required/tools/xr.dtx index 33e096c6cd..0dd5f3ad95 100644 --- a/macros/latex/required/tools/xr.dtx +++ b/macros/latex/required/tools/xr.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/xr.pdf b/macros/latex/required/tools/xr.pdf Binary files differindex 116b46c9b6..8af5483cd1 100644 --- a/macros/latex/required/tools/xr.pdf +++ b/macros/latex/required/tools/xr.pdf diff --git a/macros/latex/required/tools/xspace.dtx b/macros/latex/required/tools/xspace.dtx index 7b29b7b0be..807fc9c5df 100644 --- a/macros/latex/required/tools/xspace.dtx +++ b/macros/latex/required/tools/xspace.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 1993-2022 +% Copyright (C) 1993-2023 % % The LaTeX Project and any individual authors listed elsewhere % in this file. diff --git a/macros/latex/required/tools/xspace.pdf b/macros/latex/required/tools/xspace.pdf Binary files differindex a38c754c36..1ddc932527 100644 --- a/macros/latex/required/tools/xspace.pdf +++ b/macros/latex/required/tools/xspace.pdf diff --git a/macros/luatex/latex/luahttp/README.md b/macros/luatex/latex/luahttp/README.md new file mode 100644 index 0000000000..563992c77a --- /dev/null +++ b/macros/luatex/latex/luahttp/README.md @@ -0,0 +1,102 @@ +# README for LUAHTTP +Version 1.0 + +## INTRODUCTION +This is a small package that provides five commands to make HTTP requests using Lua and LuaTeX. Functionalities include API calls, fetching RSS feeds and the possibility to include images using a link. These commands run during the compilation of the PDF-Document and may require user interaction. + +This packages requires LuaTeX, Lua5.3, expat, openssl and the following Lua modules called "rocks": + +* luasec +* dkjson +* ltn12 +* feedparser +* luaexpat + +## MANUAL INSTALLATION +First the required dependencies need to be installed: + +Arch: +``` +lua53 luarocks expat openssl +``` + +Debian: +``` +liblua5.3-dev libssl-dev lua5.3 libexpat1-dev luarocks +``` + +MacOS: +``` +lua@5.3 luarocks expat openssl +``` + +The Lua rocks can be installed locally using ```luarocks```. To install the Lua rocks locally we need to initialize the directory where the ```.tex``` file(s) is located. In the directory execute the following commands to initialize a new Lua project and install the required dependencies: + +```bash +luarocks init --lua-version=5.3 +luarocks install dkjson --lua-version=5.3 +luarocks install luasec --lua-version=5.3 +luarocks install ltn12 --lua-version=5.3 +luarocks install luaexpat --lua-version=5.3 +luarocks install feedparser --lua-version=5.3 +``` + +For **MacOS** it may be necessary to add Lua 5.3 to your "$PATH" and install **luaexpat** and **luasec** using the commands bellow: +```bash +echo 'export PATH="/usr/local/opt/lua@5.3/bin:$PATH"' >> ~/.zshrc +luarocks install luaexpat EXPAT_DIR=/usr/local/Cellar/expat/${YOUR_VERSION_HERE} +luarocks install luasec OPENSSL_DIR=/usr/local/Cellar/openssl@3/${YOUR_VERSION_HERE} +``` + +## USAGE +Compilation requires the use of ```lualatex``` with the ```--shell-escape``` option. + +``` +lualatex --shell-escape +``` + +Add the package to your TeX file: +``` +\usepackage{luahttp} +``` + +Here is a quick overview of the commands and their parameters. For further details and examples please read the package documentation. + +* fetchJson, send a GET request and filter the response using optional keys: + ```tex + \fetchJson{URL}[optional: "key1,key2,.."] + ``` + +* fetchJsonUsingFile, send a request specified in a JSON-file and filter the response using optional keys: + ```tex + \fetchJsonUsingFile{Path to JSON-file}[optional: "key1,key2,.."] + ``` + +* fetchJsonUsingQuery, send a POST request with up to five query parameters and filter the response using keys: + ```tex + \fetchJsonUsingQuery{URL}{"key1,key2,.."} [optional: "?queryparameter1=value1"] .. [optional: "&queryparameter5=value5"] + ``` + +* fetchRss, send a GET request and filter the feed and entries (limited by the second argument) using optional keys: + ```tex + \fetchRss{URL}{limit}[optional: "feedinfokey1,feedinfokey2,.."][optional: "entrykey1,entrykey2,.."] + ``` + +* fetchImage, fetch an image from the internet and specify the width and height in **cm** using optional arguments: + ```tex + \fetchImage{URL}[optional: width in cm][optional: height in cm] + ``` + + +## AUTHOR / MAINTAINER + +* Johannes Casaburi (johannes.casaburi@protonmail.com) + +## LICENSE + +LATEX Project Public License, version 1.3c or later. + +## KNOWN PROBLEMS +* Not all URL leading to an image are detected +* Results that where filtered using keys may not be displayed in the order of the given keys. + diff --git a/macros/luatex/latex/luahttp/display.lua b/macros/luatex/latex/luahttp/display.lua new file mode 100644 index 0000000000..f7c25f7349 --- /dev/null +++ b/macros/luatex/latex/luahttp/display.lua @@ -0,0 +1,278 @@ +--[[ +-- This module is part of the LuaHTTP package +-- The purpose of this module is to correctly display the data reveived from the fetch module. +]] + +local moduleName = display +local M = {} + +---------- Dependencies ------------------------ +local fetch = require("fetch") + +---------- Local variables --------------------- +local tmp_image_counter = 0 -- Counter for image names + +---------- Helper functions -------------------- + +--- Displays an image using LuaTeX img.write function. +-- The image has to be saved first in order to be written to the PDF-Document using LuaTeX. +-- @param data image data +-- @param width optional width in cm +-- @param height optional height in cm +-- @see search_and_escape +local function display_image(data, width, height) + local tmp_image_name = '/tmp/tmp_image' -- filename of image saved temporarly + tmp_image_name = tmp_image_name .. tmp_image_counter + + local width = width or nil + local height = height or nil + local f = assert(io.open(tmp_image_name, 'wb')) + f:write(data) + f:close() + + -- LuaTeX does not provide built-in image scaling functions + local image = img.new({filename = tmp_image_name, width = width, height = height}) + if image then + img.write(image) + tmp_image_counter = tmp_image_counter + 1 + end +end + +--- Prompts the user to display an image. +-- If an image-URL is detected the user is asked to display the image or the plain URL. +-- @see is_image_url +local function prompt_user() + while true do + print("Do you want to display the image? (y/n)") + local answer = io.read() + + if answer == 'y' then + return true + elseif answer == 'n' then + return false + else + print("Invalid answer. Please enter 'y' or 'n'.") + end + end +end + +--- Searches the given URL for image extensions. +-- @param url some URL +-- @return true if an image extension was found, false otherwise +-- @see search_and_escape +local function is_image_url(url) + local image_extensions = { "jpg", "jpeg", "png", "gif" } + for _, ext in ipairs(image_extensions) do + if string.match(url, "%." .. ext) then + return true + end + end + return false +end + +--- Searches the given value for special characters that cause problems in LaTeX-Documents. +-- @param value single value of a table +-- @return if no special characters where found the value is retured unchanged, +-- if special characters where found the escaped value is returned, +-- if an image-URL is detected and the user chooses to display that image nil is returned +-- @see is_image_url, prompt_user +local function search_and_escape(value) + local value = tostring(value) + if string.find(value, "^http") then + if is_image_url(value) then + print("\nLooks like this URL leads to an image: " .. value) + if prompt_user() then + local body = fetch.image(value) + display_image(body, "5cm") + return nil + else + print("\nEscaping URL: " .. value) + value = [[\url{]] .. value .. [[}]] + end + else + print("\nEscaping URL: " .. value) + value = [[\url{]] .. value .. [[}]] + end + else + local latex_special_chars = '([%%$%{%}&%#_%^%~])' + value = value:gsub(latex_special_chars, "\\%1") + end + return value +end + +--- Prints a table to stdout. +-- @param t tagle to print +-- @param indent optional string used for indents +local function print_table(t, indent) + indent = indent or "" + for k, v in pairs(t) do + if type(v) == "table" then + print(indent .. k .. ":") + print_table(v, indent .. " ") + else + print(indent .. k .. ": " .. tostring(v)) + end + end +end + +--- Converts a table to text which can be written to the PDF-Document +-- The values of the table are first searched for special characters. +-- @param tbl table to be converted +-- @return text +-- @see search_and_escape +local function table_to_text(tbl) + local results = {} + for k, v in pairs(tbl) do + if type(v) == "table" then + table.insert(results, table_to_text(v)) + else + v = search_and_escape(v) + if v then + table.insert(results, v .. " \\\\ ") + end + end + end + return table.concat(results, " \\ ") +end + +--- Check if a table contains a certain value. +-- @param table input table +-- @param target_value value to be searched +-- @return true if value was found, false otherwise +local function table_contains(table, target_value) + for _, value in pairs(table) do + if type(value) == "table" then + table_contains(value, target_value) + elseif value == target_value then + return true + end + end + return false +end + +--- Filter out table entries that are not in the provided target keys. +-- @param input_table +-- @param target_keys array of target keys +-- @param results used for recursion +-- @return return a new table containing only the target keys and their values +local function filter_table(input_table, target_keys, results) + local results = results or {} + + for _, target_key in ipairs(target_keys) do + for key, value in pairs(input_table) do + if type(value) == "table" then + filter_table(value, target_keys, results) + elseif tostring(key) == target_key then + if not table_contains(results, value) then + table.insert(results, value) + break + end + end + end + end + return results +end + +--- Converts a string containing a comma seperated list of elements to an array (ipairs). +-- @param str input string +-- @return table containing the elements as values +local function string_to_ipairs(str) + local t = {} + for value in string.gmatch(str, "([^,]+)") do + table.insert(t, value) + end + return t +end + +---------- Module functions -------------------- + +--- Reads the contents of a JSON-file, filters the response and prints the result to the PDF-Document. +-- @param json_file_path path to the JSON-file +-- @param keys optional keys to filter out the relevant values from the response +function M.json_using_file(json_file_path, keys) + local data = fetch.json_using_file(json_file_path) + print_table(data) + if keys then + local keys = string_to_ipairs(tostring(keys)) + local values = filter_table(data, keys) + tex.sprint(table_to_text(values)) + else + tex.sprint(table_to_text(data)) + end +end + +--- Prints the response filtered by the keys to the PDF-Document. +-- @param url URL of the API +-- @param keys optional keys to filter out the relevant values from the response +function M.json(url, keys) + local data = fetch.json(tostring(url)) + print_table(data) + if keys then + local keys = string_to_ipairs(tostring(keys)) + local values = filter_table(data, keys) + tex.sprint(table_to_text(values)) + else + tex.sprint(table_to_text(data)) + end +end + +--- Print an image to the PDF-Document. +-- @param url URL of the image +-- @param width optional width in cm +-- @param height optional height in cm +function M.image(url, width, height) + local data = fetch.image(tostring(url)) + display_image(data, width, height) +end + +--- Print values from an rss-feed to the PDF-Document. +-- @param url URL of the feed +-- @param limit limits the amount of entries that get printed to the PDF-Document +-- @param feed_info_keys keys used to filter the feed information +-- @param entry_keys keys used to filter the feed entries +function M.rss(url, limit, feed_info_keys, entry_keys) + local data = fetch.rss(tostring(url)) + + if feed_info_keys then + local feed_info_keys = string_to_ipairs(tostring(feed_info_keys)) + local feed = data.feed + local feed_info_filtered = filter_table(feed, feed_info_keys) + + tex.sprint(table_to_text(feed_info_filtered)) + end + + local entries = {} + + for i = 1, limit do + if data.entries[i] then + table.insert(entries, data.entries[i]) + end + end + + if entry_keys then + local entry_keys = string_to_ipairs(tostring(entry_keys)) + local entries_filtered = filter_table(entries, entry_keys) + + print_table(entries_filtered) + tex.sprint(table_to_text(entries_filtered)) + else + tex.sprint(table_to_text(entries)) + end +end + +--- Print the reponse from a request using query parameters to the PDF-Document. +-- @param url URL of the API +-- @param keys keys to filter out the relevant values +-- @param ... multiple optional query parameters used in the request +function M.json_using_query(url, keys, ...) + local query_parameters = { ... } + local data = fetch.json_using_query(url, query_parameters) + + print_table(data) + + local keys = string_to_ipairs(tostring(keys)) + local values = filter_table(data, keys) + tex.sprint(table_to_text(values)) +end + +return M diff --git a/macros/luatex/latex/luahttp/fetch.lua b/macros/luatex/latex/luahttp/fetch.lua new file mode 100644 index 0000000000..c39997173d --- /dev/null +++ b/macros/luatex/latex/luahttp/fetch.lua @@ -0,0 +1,199 @@ +--[[ +-- This module is part of the LuaHTTP package +-- The purpose of this module is to make HTTP requests and return the response. +-- +-- Dependencies: +-- dkjson +-- luasec +-- ltn12 +-- feedparser +]] + +local moduleName = fetch +local M = {} + +---------- Dependencies ------------------------ +local http = require("socket.http") +local urlsocket = require("socket.url") +local https = require("ssl.https") +local dkjson = require("dkjson") +local ltn12 = require("ltn12") +local feedparser = require("feedparser") + +---------- Local variables --------------------- + +---------- Helper functions -------------------- + +--- Makes an HTTP request using the provided request parameter. +-- @param request table containing the request parameters +-- @return the response as a table +local function http_request(request) + local url = request.url + print("\nConnecting to " .. url) + + -- Detect HTTPS + local client = http + if url:lower():find("^https://") then + client = https + end + + -- Save optional body + local body = request.body + + -- Prepare request + local response = {} + local request = { + method = request.method or "GET", + url = url, + headers = request.headers or nil, + redirect = request.redirect or false, + sink = ltn12.sink.table(response) + } + + -- Send optional body + if body then + if type(body) == "table" then + body = dkjson.encode(body) + end + request.source = ltn12.source.string(body) + request.headers["Content-Length"] = #body + end + + -- Make the request + local response_status, response_code, response_header, response_message = client.request(request) + + local message = response_message or "(No response message recieved)" + + if response_status == nil then + error("\n!!! Error connecting to " .. url .. "\nResponse: " .. response_code .. "\nMessage: " .. message) + end + + -- Check for redirects and return body + if response_code == 301 or response_code == 302 or response_code == 303 then + print("\nResponse " .. message) + local redirect_url = response_header["location"] + if redirect_url == url then + error("\n!!! Error connecting to " .. url .. " results in a redirection loop") + else + print("\n!! Warning: redirecting to " .. redirect_url) + request.url = redirect_url + return http_request(request) + end + elseif response_code == 200 then + print("\nResponse " .. message) + if response == null or not next(response) then + error("\n!!! Error empty response") + end + return response + else + error("\n!!! Error connecting to " .. url .. "\nResponse: " .. response_code .. "\nMessage: " .. message) + end +end + +--- Parse the given JSON-file. +-- @param file_path path to JSON-file +-- @return table containing the JSON data +local function parse_json_file(file_path) + local file = io.open(file_path, "r") + local content = file:read("*all") + file:close() + return dkjson.decode(content) +end + +--- Split a given string on the first occurence of a given character. +-- @param str string containing the given character +-- @param char target character at which the string gets split +-- @return table containing the first part of the string as the key and the second part as the value +local function split_first(str, char) + local result = {} + local pos = str:find(char) + local key = str:sub(1, pos - 1) + local value = str:sub(pos + 1) + result[key] = value + return result +end + +---------- Module functions -------------------- + +--- Make a GET request using the provided URL +-- @param url target URL +-- @return table containg the response +function M.json(url) + local request = { + method = "GET", + url = url, + headers = { + ["Accept"] = "application/json" + }, + } + local response = http_request(request) + return dkjson.decode(table.concat(response)) +end + +--- Make a request using the provided JSON-file +-- @param json_file_path path to JSON-file +-- @return table containg the response +function M.json_using_file(json_file_path) + print("\nUsing file " .. json_file_path) + local request = parse_json_file(json_file_path) + local response = http_request(request) + return dkjson.decode(table.concat(response)) +end + +--- Make a GET request using the provided URL +-- @param url target URL +-- @return table containg the response +function M.rss(url) + local request = { + method = "GET", + url = url, + headers = { + ["Accept"] = "application/rss+xml" + }, + } + local response = http_request(request) + return feedparser.parse(table.concat(response)) +end + +--- Fetch image data using the provided URL +-- @param url target URL leading to an image +-- @return image data +function M.image(url) + local request = { + method = "GET", + url = url + } + local response = http_request(request) + return table.concat(response) +end + +--- Make a POST request using the provided URL and query parameters +-- @param url target URL +-- @param query_parameters parameters sent in the URL +-- @return table containg the response +function M.json_using_query(url, query_parameters) + local url = url + for _, value in ipairs(query_parameters) do + local params = split_first(value, "=") + for k, v in pairs(params) do + v = string.gsub(v, "\n", "") + url = url .. k .. "=" .. urlsocket.escape(v) + end + end + + print("\nURL: " .. url) + + local request = { + method = "POST", + url = url, + headers = { + ["Accept"] = "application/json", + ["Content-Type"] = "application/x-www-form-urlencoded"; + }, + redirect = false + } + local response = http_request(request) + return dkjson.decode(table.concat(response)) +end + +return M diff --git a/macros/luatex/latex/luahttp/luahttp-doc.pdf b/macros/luatex/latex/luahttp/luahttp-doc.pdf Binary files differnew file mode 100644 index 0000000000..99e690688a --- /dev/null +++ b/macros/luatex/latex/luahttp/luahttp-doc.pdf diff --git a/macros/luatex/latex/luahttp/luahttp-doc.tex b/macros/luatex/latex/luahttp/luahttp-doc.tex new file mode 100644 index 0000000000..fba575a478 --- /dev/null +++ b/macros/luatex/latex/luahttp/luahttp-doc.tex @@ -0,0 +1,226 @@ +\documentclass[11pt]{article} +\usepackage[english]{babel} +\usepackage{listings} + +\lstset{ + frame=shadowbox, + numbers=left, + basicstyle=\ttfamily, + keywordstyle=\bfseries, + breakatwhitespace=false, + breaklines=true, + keepspaces=true, +} + +% Document +\begin{document} + +\setlength{\parindent}{0pt} +\setlength{\parskip}{5pt plus 2pt minus 1pt} + +\title{The \textsf{LuaHTTP} package} +\author{Johannes Casaburi \\ \texttt{johannes.casaburi@protonmail.com}} + +\maketitle + +\tableofcontents + +\newpage + +\section{Introduction} +This is a small package that is the result of a case study on Internet-Interactive \LaTeX\ PDF-documents. It provides five commands to make API calls, fetch data from the internet and insert that data into the PDF-document. This package depends on LuaTex, Lua and additional dependencies that need to be installed. + +\section{Manual Installation} +First the required dependencies need to be installed: + +\texttt{MacOS using Homebrew} +\begin{lstlisting}[language=bash] +brew install lua@5.3 luarocks expat openssl +\end{lstlisting} + +\texttt{Arch} +\begin{lstlisting}[language=bash] +pacman -S lua53 luarocks expat openssl +\end{lstlisting} + +\texttt{Debian} +\begin{lstlisting}[language=bash] +apt install liblua5.3-dev libssl-dev lua5.3 libexpat1-dev luarocks +\end{lstlisting} + +Copy the \texttt{.sty} and \texttt{.lua} files in the directory where the \texttt{.tex} file is located. + +In order to get the package working, a few dependencies first need to be installed. An easy way to do so, is by using \texttt{luarocks} which is the package manager for Lua modules which are called \texttt{rocks}. + +To install the Lua rocks locally in the directory where the \lstinline{.tex} file(s) is located, execute the following commands. This will initialize a new Lua project and install the required dependencies (See below for MacOS): + +\begin{lstlisting}[language=bash] +luarocks --lua-version=5.3 init +luarocks --lua-version=5.3 install dkjson +luarocks --lua-version=5.3 install luasec +luarocks --lua-version=5.3 install ltn12 +luarocks --lua-version=5.3 install luaexpat +luarocks --lua-version=5.3 install feedparser +\end{lstlisting} + +The Lua version may be changed if the Lua rocks support the version. + +For \texttt{MacOS} you may need to add the Lua5.3 executable to your \texttt{\$PATH}. +\begin{lstlisting}[language=bash] +echo 'export PATH="/usr/local/opt/lua@5.3/bin:$PATH"' >> ~/.zshrc +\end{lstlisting} + +And it may also be necessary to install \texttt{luaexpat} and \texttt{luasec} using the commands below: +\begin{lstlisting}[language=bash] +luarocks install luaexpat EXPAT_DIR=/usr/local/Cellar/expat/${YOUR_VERSION_HERE} +luarocks install luasec OPENSSL_DIR=/usr/local/Cellar/openssl@3/${YOUR_VERSION_HERE} +\end{lstlisting} + +\section{Usage} +The LaTeX package can be used by adding the following line to the \texttt{.tex} file. +\begin{lstlisting}[language=tex] +\usepackage{luahttp} +\end{lstlisting} + +To compile the PDF-document use: +\begin{lstlisting}[language=bash] +lualatex --shell-escape +\end{lstlisting} + +\subsection{fetchJson} + +\begin{lstlisting}[language=tex] +\fetchJson{URL}[optional: "key1,key2,.."] +\end{lstlisting} + +This command takes an URL as the first argument and a list of comma separated keys as a second optional argument. Upon execution a GET request will be sent to the specified address. The accept header is set to \texttt{application/json}. The keys which are to be specified like \texttt{key1,key2,..} are used to filter out the desired values from the response. They have to exactly math the keys in the response otherwise the value will not be written to the PDF-Document. The same key can occur multiple times, this will output all values found to the PDF-Document. + +Values with special characters are escaped. Values are searched for URLs. If an URL pointing to a image is detected the user will be prompted to either display the image or the actual URL. + +\subsection{fetchJsonUsingFile} + +\begin{lstlisting}[language=tex] +\fetchJsonUsingFile{Path to JSON file}[optional: "key1,key2,.."] +\end{lstlisting} + +This is very similar to the \texttt{fetchJson} command but takes a path to a JSON file instead of an URL. This allows the user to specify the request method, headers and body. The file should look something like this: + +\begin{lstlisting} +{ + "method": "POST", + "url": "https://httpbin.org/post", + "redirect": false, + "headers": { + "Accept": "application/json", + "Content-Type": "application/json" + }, + "body": { + "name": "john", + "id" : 1234 + } +} +\end{lstlisting} + +Like the command before this command also takes and optional argument where the \texttt{keys} can be specified. If a value contains an URL leading to an image the user will be asked to either display the image or the URL. + +\subsection{fetchJsonUsingQuery} + +\begin{lstlisting}[language=tex] +\fetchJsonUsingQuery{URL}{"key1,key2,.."} [optional: "?queryparameter1=value1"] .. [optional: "&queryparameter5=value5"] +\end{lstlisting} + +This command can be used to send up to five query parameters using a POST request. The required arguments are the \texttt{URL} and a list of keys. The optional query parameters need to be written in key-value pairs: + +\begin{lstlisting}[language=tex] +\fetchJsonUsingQuery{URL}{key1,key2}[?q=The first value][&second=The second value and so on"] +\end{lstlisting} + +The values after the \texttt{=} sign are URL-encoded and sent using the \lstinline{application/json} Accept header and \texttt{application/x-www-form-urlencoded} Content-Type header. Like in the \texttt{fetchJson} command the user will be prompted if an URL leading to an image is detected. + +\subsection{fetchRss} + +\begin{lstlisting}[language=tex] +\fetchRss{URL}{limit}[optional: "feedinfokey1,feedinfokey2,.."][optional: "entrykey1,entrykey2,.."] +\end{lstlisting} + +This command takes an \texttt{URL} and a \texttt{limit}. The limit describes how many entries of the feed are written to the PDF-Document. There are two optional arguments. The first argument is a list of keys used to filter out feed information. At this time possible values are \texttt{title, subtitle, rights, generator, author, author\_detail, link, links, updated\_parsed, updated, id, contributors}. Every entry can be filtered using the second argument. Possible values for the entry keys are \texttt{id, link, links, updated, updated\_parsed, title, summary, contributors}. These values may change if the Lua rock called \texttt{feedparser} that is used to parse the feed changes. More information about \texttt{feedparser} can be found here: \lstinline{https://github.com/LuaDist-testing/feedparser} + +The \texttt{summary} from the entries may contain HTML which will just be written to the PDF-Document. As described in the \texttt{fetchJson} command you may be promoted when a link to an image is detected. + + +\subsection{fetchImage} + +\begin{lstlisting}[language=tex] +\fetchImage{URL}[optional: width in cm][optional: height in cm] +\end{lstlisting} + +Images can be inserted into the PDF-Document using the URL. To resize the image, one or two optional arguments can be given to specify the width or width and height in \texttt{centimeters}: + +\begin{lstlisting}[language=tex] +\fetchImage{URL}[7cm][5cm] +\end{lstlisting} + +\section{Examples} + +\subsection{fetchJson} + +To display the title and summary of the first article returned by the space-news API we have to specify the URL and the keys that hold the desired values: + +\begin{lstlisting}[language=tex] +\fetchJson{https://api.spaceflightnewsapi.net/v3/articles?_limit=1}[title,summary] +\end{lstlisting} + +\subsection{fetchJsonUsingFile} +Like the example above the same can be done using \texttt{fetchJsonUsingFile}. For that we need a \texttt{JSON} file with the following content: + +\begin{lstlisting} +{ + "method": "GET", + "url": "https://api.spaceflightnewsapi.net/v3/articles?_limit=1", + "redirect": false, + "headers": { + "Accept": "application/json" + } +} +\end{lstlisting} + +If the \texttt{JSON} file is located in the same directory as the \texttt{.lua} files the command looks like this: + +\begin{lstlisting}[language=tex] +\fetchJsonUsingFile{myjsonfile.json}[title,summary] +\end{lstlisting} + +If the package was not manually installed the absolute path must be used. + +\subsection{fetchJsonUsingQuery} + +Here is an example of an API call using query parameters: + +\begin{lstlisting}[language=tex] +\fetchJsonUsingQuery{http://127.0.0.1:5000/translate}{translatedText}[?q=I want to translate this text][&source=en][&target=de][&format=text] +\end{lstlisting} + +First we need to specify the first part of the URL, followed by the key(s) that hold the desired return values. The values of the query parameters get URL-encoded and put back together in a single URL. We may need to add an \texttt{\&} before the query parameter or an \texttt{?} depending on the location. + +\subsection{fetchRss} + +In this example the first the subtitle from the feed information is printed as a subsection. The second command prints the \texttt{title, link} and \texttt{updated} information of the first three entries received. + +\begin{lstlisting}[language=tex] +\subsection{ + \fetchRss{https://www.eff.org/rss/updates.xml}{1}[subtitle][none] +} + +\fetchRss{https://www.eff.org/rss/updates.xml}{3}[none][title,link,updated] +\end{lstlisting} + +Note that \texttt{none} is not a special keyword, if there was a key called \texttt{none} then its value would be printed to the PDF-Document. + +\subsection{fetchImage} +Here is an example how to embed an image and scaling it to have a width of 5cm: + +\begin{lstlisting}[language=tex] +\fetchImage{https://i0.wp.com/spacenews.com/wp-content/uploads/2023/03/vorb-march2023.jpg}[5cm] +\end{lstlisting} + +\end{document} diff --git a/macros/luatex/latex/luahttp/luahttp.sty b/macros/luatex/latex/luahttp/luahttp.sty new file mode 100644 index 0000000000..226c234d0f --- /dev/null +++ b/macros/luatex/latex/luahttp/luahttp.sty @@ -0,0 +1,91 @@ +%% luahttp.sty +%% Copyright 2023 Johannes Casaburi +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (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 work has the LPPL maintenance status `maintained'. +% +% The Current Maintainer of this work is Johannes Casaburi (johannes.casaburi@protonmail.com). +% +% This work consists of the files luahttp.sty, display.lua and fetch.lua. + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{luahttp}[LuaHTTP Package, Version 1.0] + +\RequirePackage{ifluatex} +\RequirePackage{url} +\RequirePackage{xparse} + +\ifluatex + \RequirePackage{luapackageloader} + \directlua{ + version = 5.3 + package.path = 'lua_modules/share/lua/' .. version .. '/?.lua;lua_modules/share/lua/' .. version .. '/?/init.lua;' .. package.path + package.cpath = 'lua_modules/lib/lua/' .. version .. '/?.so;' .. package.cpath + display = require("display") + } + + % \fetchJson{URL}[optional: "key1,key2,.."] + \NewDocumentCommand{\fetchJson}{m o}{ + \IfNoValueTF{#2} + {\directlua{display.json("\luaescapestring{#1}")}} % without arg 2 + {\directlua{display.json("\luaescapestring{#1}", "\luaescapestring{#2}")}} + } + + % \fetchJsonUsingFile{JSON file}[optional: "key1,key2,.."] + \NewDocumentCommand{\fetchJsonUsingFile}{m o}{ + \IfNoValueTF{#2} + {\directlua{display.json_using_file("\luaescapestring{#1}")}} % without arg 2 + {\directlua{display.json_using_file("\luaescapestring{#1}", "\luaescapestring{#2}")}} + } + + % \fetchJsonUsingQuery{URL}{"key1,key2,.."} [optional: "queryparameter1=value1"] .. [optional: "queryparameter5=value5"] + \NewDocumentCommand{\fetchJsonUsingQuery}{m m o o o o o}{ + \IfNoValueTF{#7} + {\IfNoValueTF{#6} + {\IfNoValueTF{#5} + {\IfNoValueTF{#4} + {\IfNoValueTF{#3} + {\directlua{display.json_using_query("\luaescapestring{#1}", "\luaescapestring{#2}")}} + {\directlua{display.json_using_query("\luaescapestring{#1}", "\luaescapestring{#2}", "\luaescapestring{#3}")}} + } + {\directlua{display.json_using_query("\luaescapestring{#1}", "\luaescapestring{#2}", "\luaescapestring{#3}", "\luaescapestring{#4}")}} + } + {\directlua{display.json_using_query("\luaescapestring{#1}", "\luaescapestring{#2}", "\luaescapestring{#3}", "\luaescapestring{#4}", "\luaescapestring{#5}")}} + } + {\directlua{display.json_using_query("\luaescapestring{#1}", "\luaescapestring{#2}", "\luaescapestring{#3}", "\luaescapestring{#4}", "\luaescapestring{#5}", "\luaescapestring{#6}")}} + } + {\directlua{display.json_using_query("\luaescapestring{#1}", "\luaescapestring{#2}", "\luaescapestring{#3}", "\luaescapestring{#4}", "\luaescapestring{#5}", "\luaescapestring{#6}", "\luaescapestring{#7}")}} + } + + % \fetchRss{URL}{limit}[optional: "feedinfokey1,feedinfokey2,.."][optional: "entrykey1,entrykey2,.."] + \NewDocumentCommand{\fetchRss}{m m o o}{ + \IfNoValueTF{#4} + {\IfNoValueTF{#3} + {\directlua{display.rss("\luaescapestring{#1}", #2)}} + {\directlua{display.rss("\luaescapestring{#1}", #2, "\luaescapestring{#3}")}} + } % without arg 4 + {\directlua{display.rss("\luaescapestring{#1}", #2, "\luaescapestring{#3}", "\luaescapestring{#4}")} + } + } + + %\fetchImage{URL}[optional: width][optional: height] + \NewDocumentCommand{\fetchImage}{m o o}{ + \IfNoValueTF{#2} + {\directlua{display.image("\luaescapestring{#1}")}} % whithout arg 2 + {\IfNoValueTF{#3} + {\directlua{display.image("\luaescapestring{#1}", "\luaescapestring{#2}")}} % without arg 3 + {\directlua{display.image("\luaescapestring{#1}", "\luaescapestring{#2}", "\luaescapestring{#3}")}} + } + } + +\else + \PackageError{luatexhttp}{LuaTeX is required}\@ehd + \expandafter\endinput % abort early +\fi |