diff options
author | Karl Berry <karl@freefriends.org> | 2022-03-16 21:01:50 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-03-16 21:01:50 +0000 |
commit | edc4da5fa2ccf95dc2d8e78bd12c6532e6074098 (patch) | |
tree | 2cbeacd10abcd62cbf748f76a086d6dfb171b5d4 /Master/texmf-dist/source/latex-dev | |
parent | 68a75026205e8146e3f641432ffc7e569d4465f0 (diff) |
latex-lab-dev (16mar22)
git-svn-id: svn://tug.org/texlive/trunk@62742 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex-dev')
-rw-r--r-- | Master/texmf-dist/source/latex-dev/latex-lab/documentmetadata-support.dtx | 4 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-footnotes.dtx | 1822 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-new-or.dtx | 545 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-prototype.dtx | 827 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-testphase.dtx | 17 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex-dev/latex-lab/latex-lab.ins (renamed from Master/texmf-dist/source/latex-dev/latex-lab/documentmetadata-support.ins) | 20 |
6 files changed, 3228 insertions, 7 deletions
diff --git a/Master/texmf-dist/source/latex-dev/latex-lab/documentmetadata-support.dtx b/Master/texmf-dist/source/latex-dev/latex-lab/documentmetadata-support.dtx index 0c7a1d9d80a..7501de151f8 100644 --- a/Master/texmf-dist/source/latex-dev/latex-lab/documentmetadata-support.dtx +++ b/Master/texmf-dist/source/latex-dev/latex-lab/documentmetadata-support.dtx @@ -126,7 +126,7 @@ % removed or when the code is moved into the kernel. % \begin{description} % \item[\texttt{phase-I}] -% This value loads code implementing the first phase of the project~\cite{blueprint}, i.e., it +% This value loads code implementing the first phase of the project~\cite{blueprint}, i.e., it % will load the tagpdf package. It will also activate tagging by issuing % |\tagpdfsetup{activate,interwordspace}|. This phase % is frozen. @@ -336,9 +336,11 @@ { \tl_gput_right:Nn\g_@@_testphase_tl { + \AddToDocumentProperties [document]{testphase/#1}{loaded} \file_if_exist_input:nF {#1-latex-lab-testphase.ltx} { \msg_warning:nnn{meta}{latex-lab-pkg-missing}{#1} + \AddToDocumentProperties [document]{testphase/#1}{missing} } } } diff --git a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-footnotes.dtx b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-footnotes.dtx new file mode 100644 index 00000000000..330ae7b0cc8 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-footnotes.dtx @@ -0,0 +1,1822 @@ +% \iffalse meta-comment +% +%% File: latex-lab-footnotes.dtx +% Copyright (C) 2022 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-footnotes.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \texttt{latex-lab-footnotes} code\thanks{}} +% \author{Frank Mittelbach, \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} +% \emph{to be written} +% \end{abstract} +% +% \tableofcontents +% +% +% \section{Introduction} +% +% This code reimplements the footnote interfaces for \LaTeX{} +% 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 +% 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 +% 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 +% legacy methods (though there is some support for the latter as +% well, but if will not work in a cases). +% +% \subsection{Configuration methods} +% +% Historically, the footnote setup in \LaTeX{} was done by +% providing definitions for \cs{@makefnmark} (format the footnote +% mark in running text and in front of the footnote text) and +% \cs{@makefntext} (formatting the footnote text and placing a mark +% in front of it). +% +% There was a default definition for \cs{@makefnmark} in the format +% 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 +% for \cs{@makefnmark} only in very few. +% +% Furthermore, to enable special footnote layouts or provide +% additional functionality a few packages (and a few classes) +% overwrote other internal commands of \LaTeX's footnote +% mechanism. The commands affected in this way are mainly +% \cs{@footnotemark} and \cs{@footnotetext}. These overwrites could +% not be used in combination, so either the packages/classes had to +% be aware of being loaded together (which they sometimes did or +% tried to) or they would fail by overwriting each other +% unconditionally. +% +% The present rewrite is an attempt to improve this situation, but +% of course, it will only work if all packages/classes make use of +% the new interfaces. Fortunately, the number of problematical +% packages altering these internal commands are fairly small so +% arranging for updates is a realistic goal --- to achieve properly +% tagged PDF it is a requirement. +% +% +% +% \section{Hooks and configuration points} +% +% Note: the configuration points do not have an interface mechanism +% yet and all their names are temporary right now. +% Also note that configuration points are of interest only to very +% few specialized packages, mainly \pkg{footmisc}, and packages +% providing similar functionality---the current documentation is +% therefore fairly sketchy. +% +% 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. +% +% +% \subsection{Formatting the mark in the main text} +% +% This implements formatting the mark\footnote{Like this one.} and +% its relation to surrounding text, e.g., if several marks appear +% in the same place, etc. +% +% +% \subsubsection{Configuration points} +% +% None: everything is implemented through a single definition for +% \cs{@footnotemark} that offers a number of hooks that can be used +% by packages to implement handling of multiple marks and the +% formatting of marks. +% +% +% \subsubsection{Hooks} +% +% The hooks to customize the marks in the text are the following: +% \begin{description} +% \item[\hook{fnmark/before}] +% +% 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., +% they do not all check that they are in horizontal mode). +% +% This hook is paired with hook \hook{fnmark/after}. +% +% \item[\hook{fnmark}] +% +% Executed in horizontal mode and after the current space factor +% has been saved away for reuse. This is where currently code for multiple +% marks does its preparation (as done by \pkg{footmisc} and +% others). +% +% The hook is only executed in hmode, i.e., not if the mark is +% generated in math --- maybe that means the multiple handling +% should happen later? +% +% After the hook \cs{nobreak} is executed, so any +% ``material'' added in the hook is tied to the following mark +% unless it contains its own permissible penalty. +% +% \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. +% +% \item[\hook{fnmark/end}] +% +% This hook is executed directly after the typeset mark. It is +% used by \pkg{hyperref}, \pkg{memhfixc}, \pkg{scrlttr2}, and +% \pkg{footmisc}. Used, for example, to implement support for +% multiple marks in succession. +% +% It is \emph{not} a reversed hook. +% +% +% \item[\hook{fnmark/after}] +% +% This hook is executed at the very end of the \cs{footnotemark} command. +% +% It is a reversed hook to pair with \hook{fnmark/before} +% \end{description} +% +% +% +% +% \subsubsection{Additional configuration possibilities} +% +% The actual formatting is done through \cs{@makefnmark} --- no +% special customization support for now. +% +% +% +% \subsection{Formatting the footnote text} +% +% This implements the formatting of the footnote text the way it +% appears at the bottom of the page (default case), or possibly +% elsewhere, e.g. in the margin. +% +% \subsubsection{Configuration points} +% +% To cater for different layout configurations there are four +% configuration points which can be set only by one package or +% class, if two packages/classes set them they are mutually +% incompatible. +% These are: +% \begin{description} +% \item[\cs{@footnotetext@cfgpoint} (1 argument)] +% +% This receives all material that is to be processed (or stored) +% including color protection code and what have you. The default +% definition is to run \cs{insert}\cs{footins}. +% +% \item[\cs{@footnotetext@cfgpointii} (1 argument)] +% +% The default definition runs \cs{@makefntext} which contains +% various hooks for customization. For most scenarios this is +% sufficient. However, when running all footnotes as a single +% paragraph at the bottom, then each footnote needs to be +% prepared prior to storing in the insert and this configuration +% point allows running extra code to do that. +% +% \item[\cs{@footnotetext@cfgpointiii} (no argument)] +% +% By default this configuration point adds a strut to the +% 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 +% this configuration point can cancel the action or do something +% else instead. +% +% The configuration point is executed near the start of the +% argument for the configuration point +% \cs{@footnotetext@cfgpointii}. +% +% \item[\cs{@footnotetext@cfgpointiv} (no argument)] +% +% This configuration point is executed at the very end of the +% argument passed to \cs{@footnotetext@cfgpointii}. +% By default it adds a final strut as long as we are still in +% horizontal mode (i.e., processing the footnote text paragraph. +% When running several footnotes in one paragraph some additional +% material (some horizontal glue) needs adding at this point. +% +% \end{description} +% The configuration point \cs{@footnotetext@cfgpointii} runs +% \cs{@makefntext} and this command contains two further +% configuration points (and a few hooks): +% \begin{description} +% \item[\cs{@makefntext@cfgpoint} (1 argument)] +% +% This configuration point receives the material to typeset the +% footnote mark. By default, all it does is running \cs{indent} +% to get a paragraph indentation (if one is set up---in most +% layouts it is 0~points) and then typesets the mark, but in +% some designs it executes more elaborate code. +% +% 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}. +% +% \item[\cs{@makefntext@cfgpointii} (1 argument)] +% +% This configuration point manages the formatting of the footnote +% 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}. +% +% \end{description} +% +% +% The above configuration points are sufficient to implement all +% commonly used footnote layouts assuming L-R typesetting. For R-L +% typesetting they or may or may not need some extension (though +% that is not clear right now). +% +% +% +% \subsubsection{Hooks} +% +% \begin{description} +% \item[\hook{fntext/before}] +% +% Executed at the very beginning of \cs{footnotetext}. Currently +% there is on package (\pkg{linguex}) that +% prepends material at this point. +% +% This hook is paired with hook \hook{fnmark/after}. +% +% \item[\hook{fntext}] +% +% Executed at the beginning of the material passed to the first +% configuration point. Typically used to set any baseline +% stretch for the footnote text, e.g., by \pkg{setspace}, +% \pkg{footmisc}, \class{uathesis} and others. Could be done in a +% later hook but is a bit more efficient here. +% +% After the hook has run, the font is established, i.e., it can't +% be used to set a different font size. +% +% \item[\hook{fntext/para}] +% +% After the font is set default paragraph parameters are set up +% including \cs{interlinepenalty}, \cs{hsize}, \cs{parindent} and +% a number of others, as some of them depend on the font +% size. Then the \hook{fntext/para} is run. If one wants to +% change the font size, it is probably necessary to reset these +% other parameters too, e.g., \cs{parindent}, which can be done +% here. +% +% The configuration point \cs{@footnotetext@cfgpointii} normally +% runs the command \cs{@makefntext} or some code that eventually +% runs this command, and this then produces the footnote mark (in +% front of the footnote text) and the formatted footnote text. In +% front of both the mark and the footnote text some classes have +% placed paragraph parameter adjustments in their redefinition of +% \cs{@makefntext}. However, there is no need to place it there +% it could equally well go into the \hook{fntext/para} hook. We +% therefore do not provide another hook at this point. +% +% \item[\hook{fntext/begin} \& \hook{fntext/end}] +% +% The footnote text itself is surrounded by the hooks +% \hook{fntext/begin} and \hook{fntext/end}. The two hooks are +% not paired as they are typically used independently. +% +% \item[\hook{fntext/after}] +% +% 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 +% code in that position. +% +% \end{description} +% +% +% +% +% \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 +% \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: +% \begin{itemize} +% \item +% +% If it has the value \texttt{-}\cs{maxdimen} then the mark is +% generated by \cs{@makefnmark}. +% +% \item +% +% Otherwise, if the value is +% negative then the mark is placed into an \cs{llap} left aligned +% in a box of size \texttt{-}\cs{footnotemargin}. +% +% \item +% +% If the value is zero an \cs{llap} is used without an inner box. +% +% \item +% +% If the value is greater zero (but less than \cs{maxdimen}) the +% mark is placed right aligned into a box of size +% \cs{footnotemargin}. +% +% \item +% +% The value \cs{maxdimen} is used as a marker to indicate that +% no value was given and that the default should be used, +% i.e. 1.8em or \texttt{-}\cs{maxdimen} depending on the chosen +% option. +% \end{itemize} +% +% +% \section{Tagging support} +% +% \emph{To be documented} +% +% +% +% +% \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } +% +% +% \section{The Implementation} +% +% All this is very rough and misses a lot of documentation. +% +% \begin{macrocode} +%<*kernel> +%<@@=fnote> +% \end{macrocode} +% +% \subsection{File declaration} +% \begin{macrocode} +\ProvidesFile{latex-lab-footnotes.ltx} + [2022-03-10 v0.6a changes to the footnote interfaces] +% \end{macrocode} +% +% \begin{macrocode} + +% latex.ltx + + % 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} + + + +%------------------------------------- + + +\ExplSyntaxOn + + +\cs_new_protected:Npn \fnote_step_fnmark:nn #1#2 { + \tl_if_novalue:nTF {#1} + { + \stepcounter {#2} + \protected@xdef \@thefnmark { \use:c { the#2 } } + } + { + \group_begin: +% \end{macrocode} +% Note that this is a local assignment even though \LaTeX{} +% counters are normally globally changed. This is the way it was in +% 2e and so far we haven't changed it. The alternative would be to +% store the current value and restore it after \cs{@thefnmark} is +% altered. +% \begin{macrocode} + \int_set:cn { c@#2 }{ #1 } + \unrestored@protected@xdef \@thefnmark { \use:c { the#2 } } + \group_end: + } +} + +\cs_new_protected:Npn \fnote_set_fnmark:nn #1#2 { + \tl_if_novalue:nTF {#1} + { + \protected@xdef \@thefnmark { \use:c { the#2 } } + } + { + \group_begin: + \int_set:cn { c@#2 }{ #1 } + \unrestored@protected@xdef \@thefnmark { \use:c { the#2 } } + \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 + +%------------------------------------- + + + +\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 + { + \LogHook{fnmark/before} + \LogHook{fnmark} + \LogHook{fnmark/begin} + \LogHook{fnmark/end} + \LogHook{fnmark/after} + \cs_gset_eq:NN \@@_debug_footnotemark: \prg_do_nothing: + } +} + + +\cs_new_protected:Npn \fnote_footnotemark: { + \@@_debug_footnotemark: +%------- +% bibarts +% chextras --- actually in the wrong place does an \unskip + \UseHook{fnmark/before} +%------- + \leavevmode + \ifhmode + \edef\@x@sf{\the\spacefactor} +%------- +% bxjsja-minimal.def --- what they do could be done at ``bibarts'' +% (a bit less efficient) +% memhfixc.sty +% footmisc.sty + \UseHook{fnmark} +%------- + \nobreak + \fi +%------- +% hyperref.sty + \UseHook{fnmark/begin} +%------- + \@kernel@process@makefnmark + \@makefnmark +%------- +% \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 +% footnote these actions have to happen only after we have handled +% 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: { +% hyperref.sty +% memhfixc.sty --- could move fnmark/after +% scrlttr2.cls --- could vanish if footmisc uses a hook +% footmisc.sty + \UseHook{fnmark/end} +%------- + \ifhmode + \spacefactor \@x@sf \relax + \fi +% +%------- + \UseHook{fnmark/after} +%------- +} + + +\cs_new_eq:NN \@@_footnotemark_finish: \@@_finish: + + + +% Not a public config point but the kernel hook to add tagging +\def \@kernel@process@makefnmark { } + + +% alterations not covered: +% +% ./arabtex/afoot.sty --- too different (and probably too old) + + +% Provide the name \LaTeXe{} is used to. + +\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). +% \begin{macrocode} + \cs_gset_eq:NN \@@_debug_footnotetext: \prg_do_nothing: + } + } + +\cs_new_protected:Npn \fnote_footnotetext:n #1 { + \@@_debug_footnotetext: +%------- +% ./linguex/linguex.sty + \UseHook{fntext/before} +%------- + \@kernel@process@footnotetext + \@footnotetext@cfgpoint { % config point +%------- +% resetting baselinestretch ... (could be done further down) +% ./uafthesis/uafthesis.cls +% ./setspace/setspace.sty +% ./footmisc/footmisc.sty (normal) + \UseHook{fntext} +%------- + \reset@font + \footnotesize +%------- +% some classes use a different font size, e.g., +% ./nrc/nrc1.cls ./nrc/nrc2.cls +% but those could be done in fntext/para instead +%------- +% \end{macrocode} +% In case of sidenotes the next settings are pointless, but as they +% do not hurt (except for the \cs{hsize} setting) and are needed +% for all other cases we make them here and overwrite them for side notes +% \begin{macrocode} + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox + \floatingpenalty \@MM + \hsize\columnwidth + \@parboxrestore + \parindent 1em % typical default used in \@makefntext moved up here + \def\@currentcounter{footnote} + \protected@edef \@currentlabel { \p@footnote \@thefnmark } +%------- +% for altering para parameters ... +% code for resphilosophica came earlier but it could go here. +% Has the advantage that one can also overwrite \cs{@currentcounter} +% and \cs{@currentlabel} is that is necessary. +% +% ./resphilosophica/resphilosophica.cls + \UseHook{fntext/para} +%------- + \color@begingroup +%------- +% fnpara wants to replace \@makefntext{...} and para and side option of footmisc etc too ... +% so we make this a config point +%------- + \@footnotetext@cfgpointii % config point + { +%------- +% ./resphilosophica/resphilosophica.cls +%------- + \@footnotetext@cfgpointiii % config point +%------- +% bibarts +% fnbreak.sty + \UseHook{fntext/begin} +%------- + \ignorespaces + #1 +%------- +% bibarts +% fnbreak.sty + \UseHook{fntext/end} +%------- + \@footnotetext@cfgpointiv % config point + } + \par + \color@endgroup + } +%------- +% ./linguex/linguex.sty + \UseHook{fntext/after} +%------- +} + +% default for config point (1 arg) +\cs_new_protected:Npn \@footnotetext@cfgpoint { \insert\footins } + +% default for config point (1 arg) +\cs_new_protected:Npn \@footnotetext@cfgpointii { \@makefntext } + + +% default for config point (0 args) +\cs_new_protected:Npn \@footnotetext@cfgpointiii { \rule\z@\footnotesep } + +% default for config point (0 args) +\cs_new_protected:Npn \@footnotetext@cfgpointiv { \@finalstrut\strutbox } + + +% kernel hook for tagging (2 args) +\cs_new_protected:Npn \@kernel@process@footnotetext {} + +% 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: +% +% ./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 +% don't want to do this like that in the kernel but for now I have +% used this interface unchanged. + + +\newdimen\footnotemargin +\footnotemargin\maxdimen % no value given + +\AtBeginDocument{ + \ifdim \footnotemargin=\maxdimen + \setlength\footnotemargin{1.8em} + \fi +} + + +\cs_new_protected:Npn \fnote_makefntext:n #1 { +% \end{macrocode} +% Some classes in their redefinition for \cs{@makefntext} have +% places some paragraph parameters at this point, but those can +% equally well go into the hook \hook{fntext/para}. We therefore do +% not provide a further hook at this point. +% \begin{macrocode} + \@makefntext@cfgpoint + { + \ifdim\footnotemargin>\z@ + \hb@xt@ \footnotemargin{\hss\@makefnmark} + \else + \ifdim\footnotemargin=\z@ + \llap{\@makefnmark} + \else + \ifdim\footnotemargin=-\maxdimen + \@makefnmark + \else + \llap{\hb@xt@ -\footnotemargin{\@makefnmark\hss}} + \fi + \fi + \fi + } + \@makefntext@cfgpointii + { #1 } +} + + + + +% default for config point (1 arg) +\cs_new_protected:Npn \@makefntext@cfgpoint { \noindent } + +% default for config point (1 arg) +\cs_new_protected:Npn \@makefntext@cfgpointii #1 { #1 } +% \end{macrocode} +% +% +% +% 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 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{macrocode} +\newcommand\old@std@class@makefntext[1]{% + \parindent 1em% + \noindent + \hb@xt@1.8em{\hss\@makefnmark}#1} + +% \end{macrocode} +% 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 +% right place. +% +% What it does is roughly the +% following: It look for a definition of \cs{@makefntext} of the form +%\begin{verbatim} +% {AAA \hbox BBB { CCC } DDD #1 EEE } +%\end{verbatim} +% where ``BBB'' is something like \texttt{to 1em} or similar. It then +% replaces that with +%\begin{verbatim} +% {AAA \@makefntext@cfgpoint{\hbox BBB { CCC }} DDD +% \@makefntext@cfgpointii{#1} EEE } +%\end{verbatim} +% The patching is not very careful, i.e., it assumes there is only +% one \verb=#1= in the replacement text and that a \cs{hbox} found +% is the right one to patch. But that is enough to cater for all +% definitions of \cs{@makefntext} out there in the TL distribution. +% +% If \cs{hbox} is not found it tries the same looking for +% \cs{hb@xt@} which is what some classes use and if that is not +% found either it assume that this is a version that uses +% \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 + +\cs_new_protected:Npn \@@_patch: + { + \tl_set:No \l_@@_patch_tl { \@makefntext { \@makefntext@cfgpointii{##1} } } + \tl_if_in:NnTF \l_@@_patch_tl { \hbox } + { \cs_set_eq:NN \@@_tmp:w \@@_patch_hbox:w } + { + \tl_if_in:NnTF \l_@@_patch_tl { \hb@xt@ } + { \cs_set_eq:NN \@@_tmp:w \@@_patch_hb@xt@:w } + { + \tl_if_in:NnTF \l_@@_patch_tl { \@makefnmark } + { \cs_set_eq:NN \@@_tmp:w \@@_patch_@makefnmark:w } + { \ERROR + \cs_set_eq:NN \@@_tmp:w \exp_stop_f: } + } + } + \tl_set:Nf \l_@@_patch_tl + { \exp_after:wN \@@_tmp:w \l_@@_patch_tl } + \cs_set:Npn \@@_tmp:w { \long \def \@makefntext ####1 } + \exp_after:wN \@@_tmp:w \exp_after:wN { \l_@@_patch_tl } + } +% \end{macrocode} +% +% If \cs{@makefntext} contains \cs{hbox} then grab ``AAA'' as +% \verb=#1= and ``BBB'' (up to the open \verb={=) and return it as +%\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 } } +% \end{macrocode} +% Same for the other cases. +% \begin{macrocode} +\cs_new:Npn \@@_patch_hb@xt@:w #1 \hb@xt@ #2 # + { \exp_stop_f: #1 \@makefntext@processX { \hb@xt@ #2 } } +\cs_new:Npn \@@_patch_@makefnmark:w #1 \@makefnmark + { \exp_stop_f: #1 \@makefntext@processX { \use:n } { \@makefnmark } } +% \end{macrocode} +% +% The code provided by Bruno above expects 2 arguments but we need a +% 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: + } +} + + +% possibly add the following to check for multiple \hbox in +% the definition: +% +% \seq_set_split:NnV \l_@@_patch_seq { \hbox } \l_@@_patch_tl +% \int_compare:nT { \seq_count:N \l_@@_patch_seq } > 2 \ERROR +% +% \end{macrocode} +% +% +% +% +% \subsection{Document-level commands} +% +% \begin{macrocode} + +\DeclareDocumentCommand\footnotetext {om} { + \fnote_set_fnmark:nn {#1} \@mpfn + \@footnotetext {#2} +} + + +%------------------------------------- + + +\DeclareDocumentCommand\footnote {om} { + \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 +} + +% \end{macrocode} +% +% \begin{macrocode} +%<@@=> +% \end{macrocode} +% +% +% +% +% +% +% \subsection{Firstaid for packages and classes} +% +% \subsubsection{\pkg{setspace}} +% +% It should not overwrite it any longer but use a hook, so for now we +% do just that here. +% \begin{macrocode} +\AddToHook{package/setspace/after} + {\let \@footnotetext \fnote_footnotetext:n + \AddToHook{fntext}[setspace]{\let\baselinestretch\setspace@singlespace}} +% \end{macrocode} +% +% +% +% +% \subsubsection{\pkg{hyperref}} +% +% Prevent hyperref from redefining footnote stuff --- this is a +% temp solution. +% \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: +} + + + +% \end{macrocode} +% +% \subsection{Stuff that needs cleanup and documentation} +% +% \begin{macrocode} + + +%------------------------------------- + +% 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 + +% 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 + { + \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{} + } + { #1 } +} + +% to be done next round around: +% +% \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. +% +% 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 + { + \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{} + } + { #1 {#2} } +} + + + +\cs_set:Npn \@makefntext@cfgpoint #1 { + \noindent + \cs_if_exist:NT \tag_struct_begin:n { \tag_mc_end_push: } + \tag@FELbl { #1 } +} + +\cs_set:Npn \@makefntext@cfgpointii #1 { + \tag@FENote { #1 } + \cs_if_exist:NT \tag_struct_begin:n { \tag_mc_begin_pop:n{} } +} + + + + +\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 } +} + +\cs_new_protected:Npn \tag@FENote #1 { + \tag_if_loaded:TF + { + \tag_mc_begin:n{tag=FENote} + #1 + \tag_mc_end: + %\tag_struct_end: %alternative location for structure end but ends inside a P + } + { #1 } +} + +%------------------------------------- + + +\ExplSyntaxOff +%</kernel> +% \end{macrocode} +% +% +% \section{Reimplementing the \pkg{footmisc} package} +% +% \begin{macrocode} +%<*footmisc> +%% +%% Copyright (c) 1995-2011 Robin Fairbairns +%% Copyright (c) 2018-2022 Robin Fairbairns, Frank Mittelbach +%% +%% This file is part of the `latex-lab Bundle'. +%% -------------------------------------------- +%% +%% It may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3c +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% https://www.latex-project.org/lppl.txt +%% and version 1.3c or later is part of all distributions of LaTeX +%% version 2008 or later. +%% +%% This work has the LPPL maintenance status 'maintained'. +%% +%% +%% File: footmisc.dtx (C) Copyright 1995-2011 Robin Fairbairns +%% (C) Copyright 2018-2022 Frank Mittelbach +\NeedsTeXFormat{LaTeX2e} +\providecommand\DeclareRelease[3]{} +\providecommand\DeclareCurrentRelease[2]{} + +\DeclareRelease{v5}{2011-06-06}{footmisc-2011-06-06.sty} +\DeclareCurrentRelease{}{2022-02-14} +\ProvidesPackage{latex-lab-footmisc}% + [2022/03/08 v6.0d + a miscellany of footnote facilities -- latex-lab version% + ] + +\NeedsTeXFormat{LaTeX2e}[2020/10/01] +\newtoks\FN@temptoken +\providecommand\protected@writeaux{% + \protected@write\@auxout +} +\def\l@advance@macro{\@@dvance@macro\edef} +\def\@@dvance@macro#1#2#3{\expandafter\@tempcnta#2\relax + \advance\@tempcnta#3\relax + #1#2{\the\@tempcnta}% +} +\let\@advance@macro\l@advance@macro +\DeclareOption{symbol}{\renewcommand\thefootnote{\fnsymbol{footnote}}} +\newif\ifFN@robust \FN@robustfalse +\DeclareOption{symbol*}{% + \renewcommand\thefootnote{\@fnsymbol\c@footnote}% + \FN@robusttrue + \AtEndOfPackage{\setfnsymbol{lamport*-robust}}% +} +\newif\ifFN@para \FN@parafalse +\DeclareOption{para}{% +% \end{macrocode} +% Options are executed in the order of declaration, thus no point in +% checking for side option as footmisc did in the past +% \begin{macrocode} +% \PackageError{footmisc}{Option "\CurrentOption" incompatible with +% option "side"}% +% {I shall ignore "\CurrentOption"}% + \FN@paratrue + \setlength\footnotemargin{-\maxdimen} % default when para is used +} +% \end{macrocode} +% +% \begin{macrocode} +\DeclareOption{side}{\ifFN@para + \PackageError{footmisc}{Option "\CurrentOption" incompatible with + option "para"}% + {I shall ignore "\CurrentOption"}% + \else + \def\@footnotetext@cfgpoint {\marginpar} + \AddToHook{fntext/para}{% + \hsize\marginparwidth % correct the default \hsize + \footnotesep\z@ % don't add a default separation + } + \def\@footnotetext@cfgpointii {\@makefntext} + \def\@footnotetext@cfgpointiii {} + \def\@footnotetext@cfgpointiv {} + \fi +} +\let\footnotelayout\@empty +\DeclareOption{ragged}{% + \@ifundefined{RaggedRight}% + {\renewcommand\footnotelayout{\linepenalty50 \raggedright}}% + {\renewcommand\footnotelayout{\linepenalty50 \RaggedRight}}% +} +\newif\ifFN@perpage +\FN@perpagefalse +\DeclareOption{perpage}{% + \FN@perpagetrue +} +\newif\ifFN@fixskip \FN@fixskipfalse + +\let\FN@bottomcases\thr@@ +\newif\ifFN@abovefloats \FN@abovefloatstrue +\DeclareOption{bottom}{% + \let\FN@bottomcases\@ne + \FN@abovefloatsfalse + \FN@fixskiptrue +} +\DeclareOption{bottomfloats}{% + \let\FN@bottomcases\tw@ + \FN@abovefloatstrue \FN@fixskiptrue +} +\DeclareOption{abovefloats}{\FN@abovefloatstrue \FN@fixskiptrue} +\DeclareOption{belowfloats}{\FN@abovefloatsfalse \FN@fixskiptrue} +\DeclareOption{marginal}{% + \footnotemargin-0.8em\relax +} +\DeclareOption{flushmargin}{% + \footnotemargin0pt\relax +} +\newif\ifFN@hangfoot \FN@hangfootfalse +\DeclareOption{hang}{% + \FN@hangfoottrue +} +\newcommand*\hangfootparskip{0.5\baselineskip} +\newcommand*\hangfootparindent{0em}% +\DeclareOption{norule}{% + \renewcommand\footnoterule{}% + \advance\skip\footins 4\p@\@plus2\p@\relax +} +\DeclareOption{splitrule}{% + \gdef\split@prev{0} + \let\pagefootnoterule\footnoterule + \let\mpfootnoterule\footnoterule + \def\splitfootnoterule{\kern-3\p@ \hrule \kern2.6\p@} + \def\footnoterule{\relax + \ifx \@listdepth\@mplistdepth + \mpfootnoterule + \else + \ifnum\split@prev=\z@ + \pagefootnoterule + \else + \splitfootnoterule + \fi + \xdef\split@prev{\the\insertpenalties}% + \fi + }% +} +\newif\ifFN@stablefootnote \FN@stablefootnotefalse +\DeclareOption{stable}{\FN@stablefootnotetrue} +\newif\ifFN@multiplefootnote \FN@multiplefootnotefalse +\DeclareOption{multiple}{\FN@multiplefootnotetrue} +\ProcessOptions +% \end{macrocode} +% This version of \pkg{footmisc} can assume that the new OR code is +% already available, thus nothing needs loading at this +% point. However, as long as we use this code also in a package +% version that can be loaded by other package while we are in a +% transition phase it is not clear whether not the kernel code is +% already available for other packages. +% \begin{macrocode} +%\@ifundefined{@kernel@before@cclv} +% {\input{latex-lab-new-or.ltx}}{} +% \end{macrocode} +% +% Footnote box layout for para footnotes; +% this would also be the hook to support dblfootnotes (from the +% \texttt{dblfnote} package if we integrate that). +% \begin{macrocode} +\ifFN@para + \def\@makecol@cfgpointii {% + \global\setbox\footins\vbox{\FN@makefootnoteparagraph}% + } +\fi +% \end{macrocode} +% +% \begin{macrocode} +\ifFN@fixskip + \def\@outputbox@removebskip{% + \ifx\@textbottom\relax \else + \@outputbox@append{% + \@tempskipa\lastskip + \ifnum \gluestretchorder\@tempskipa>\z@ + \vskip-\@tempskipa + \xdef\@outputbox@reinsertbskip + {\noexpand\@outputbox@append{\vskip\the\@tempskipa}}% + \else + \global\let\@outputbox@reinsertbskip\relax + \fi + }% + \fi + } +\let\@outputbox@reinsertbskip\relax +\else + \let\@outputbox@removebskip \relax + \let\@outputbox@reinsertbskip\relax +\fi +% \end{macrocode} +% +% +% +% \begin{macrocode} +\ifcase \FN@bottomcases\relax +\ERROR +\or + \ifFN@abovefloats + \def\@makecol@cfgpoint {% + \@if@footnotes@TF + {\@outputbox@append{\vfill}}% + {\@if@bfloats@TF{\@outputbox@append{\vfill}}% + {\@outputbox@reinsertbskip}}% + \@outputbox@appendfootnotes + \@outputbox@attachfloats + } + \else + \def\@makecol@cfgpoint {% + \@outputbox@attachfloats + \@if@footnotes@TF + {\@outputbox@append{\vfill}}% + {\@outputbox@reinsertbskip}% + \@outputbox@appendfootnotes + } + \fi +\or + \ifFN@abovefloats + \def\@makecol@cfgpoint {% + \@outputbox@appendfootnotes + \@if@bfloats@TF + {\@outputbox@append{\vfill}}% + {\@outputbox@reinsertbskip}% + \@outputbox@attachfloats + } + \else + \def\@makecol@cfgpoint {% + \@if@footnotes@TF + {\@outputbox@append{\vfill}}% + {\@if@bfloats@TF{\@outputbox@append{\vfill}}% + {\@outputbox@reinsertbskip}}% + \@outputbox@attachfloats + \@outputbox@appendfootnotes + } + \fi +\or + \ifFN@abovefloats + \def\@makecol@cfgpoint {% + \@outputbox@appendfootnotes + \@outputbox@attachfloats + \@outputbox@reinsertbskip + } + \else + \def\@makecol@cfgpoint {% + \@outputbox@attachfloats + \@outputbox@appendfootnotes + \@outputbox@reinsertbskip +} + \fi +\else +\ERROR +\fi + +% next can be dropped when cleaned up +\newif\ifFN@setspace +\@ifpackageloaded{setspace}% + {% + \FN@setspacetrue + \@ifclassloaded{memoir}% + {% + \AddToHook{fntext}{\let\baselinestretch\m@m@singlespace}% + \let\FN@baselinestretch\m@m@singlespace + }% + {% +% \AddToHook{fntext}{\let\baselinestretch\setspace@singlespace}% + \let\FN@baselinestretch\setspace@singlespace + }% + }% + {% + \FN@setspacefalse + } + + + +\ifFN@para + \def\@footnotetext@cfgpoint {\insert\footins} + + \long\def\@footnotetext@cfgpointii #1{% + \setbox\FN@tempboxa\hbox{\@makefntext{#1}}% + \dp\FN@tempboxa\z@ + \ht\FN@tempboxa + \dimexpr\wd\FN@tempboxa *% + \footnotebaselineskip /\columnwidth\relax + \box\FN@tempboxa + } + + + \def\@footnotetext@cfgpointiii {} + \def\@footnotetext@cfgpointiv {% config point + \strut + \penalty-10\relax + \hskip\footglue + } +\fi + + + +\ifFN@para + \let\FN@tempboxa\@tempboxa + \newbox\FN@tempboxb + \newbox\FN@tempboxc + \newskip\footglue \footglue=1em plus.3em minus.3em + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + \newdimen\footnotebaselineskip + + % establish late: + +\AddToHook{begindocument/before} {% + {% + \footnotesize + \global\footnotebaselineskip=\normalbaselineskip + }% +} +% \end{macrocode} +% The coding is based on David Kastrup's improvement to Don Knuth's +% original implementation. You find in the \TeX{}book if you own +% the latest edition. +% \begin{macrocode} + + \long\def\FN@makefootnoteparagraph{% + \FN@setfootnoteparawidth + \@parboxrestore + \baselineskip=\footnotebaselineskip + \unvbox\footins \FN@removehboxes + \RawParEnd + } + \def\FN@removehboxes{\setbox\FN@tempboxa\lastbox + \ifhbox\FN@tempboxa{\FN@removehboxes}% + \unhbox\FN@tempboxa + \else + \RawNoindent + \rule\z@\footnotesep + \fi + } +\fi + + +\@ifpackageloaded{multicol} + {\def\FN@setfootnoteparawidth + {\hsize\ifnum\doublecol@number>\@ne + \textwidth + \else \columnwidth \fi}} + {\def\FN@setfootnoteparawidth{\hsize\columnwidth}} + +\ifFN@perpage + \RequirePackage{perpage} + \MakePerPage{footnote} +% \end{macrocode} +% Fix a bug in perpage \ldots +% \begin{macrocode} + \def\@stpelt#1{\global\csname c@#1\endcsname \m@ne + \stepcounter{#1}% + \pp@fix@MakePerPage{#1}% + } + \def\pp@fix@MakePerPage#1{% + \ifnum \value{#1}>\z@ + \addtocounter{#1}\m@ne\fi + } +% \end{macrocode} +% The above code may look a bit odd: the \cs{stepcounter} sets the +% counter to zero and then we alter it if it is not zero. The +% reason is that \cs{stepcounter} resets other counters and when +% perpage is loaded this results in updating counters on the reset +% list to 1 (or to a higher starting value if \cs{MakePerPage} is +% used with an optional argument, which is precisely the problem +% here. By subtracting 1 in that case we set it back to 1 lower +% than the starting value. +% +% But to make this fully work we also need to update a support +% command in \pkg{perpage}: +% \begin{macrocode} + \def\pp@cl@end@iii\stepcounter#1\pp@fix@MakePerPage#2{} +\fi + + +\ifFN@para + +% This can use the default interface, except that a negative value for +% \footnotemargin makes little sense, so we test for this and warn if +% necessary. But -\maxdimen is ok again, so would need to be a litte bit more elaborate. +% + +%\AddToHook{fntext/para}{ +% \ifdim \footnotemargin >\z@ \else +% \PackageWarningNoline{footmisc}{Option 'para' needs positive \noexpand\footnotemargin}% +% \footnotemargin 1.8em\relax +% \fi +%} + + +\AddToHook{fntext/begin}{\nobreak \hspace{.2em}} + + + + +\else + + \ifFN@hangfoot + \long\def\@makefntext#1{% + \bgroup + \setbox\@tempboxa\hbox{% + \ifdim\footnotemargin>\z@ + \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 + \footnotelayout#1% + \par + \egroup + } + + \else + +% This is now using the default interface: +% +% \long\def\@makefntext#1{% +% \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 +% \footnotelayout#1% +% } + + \fi +\fi + + + + +\ifFN@multiplefootnote + \providecommand*{\multiplefootnotemarker}{3sp} + \providecommand*{\multfootsep}{,} + \AddToHook{fnmark} {\FN@mf@check} + \AddToHook{fnmark/end} {\FN@mf@prepare} +% + \def\FN@mf@prepare{% + \kern-\multiplefootnotemarker + \kern\multiplefootnotemarker\relax + } + \def\FN@mf@check{% + \ifdim\lastkern=\multiplefootnotemarker\relax +%?? is that necessary or even correct ?? + \edef\@x@sf{\the\spacefactor}% +%?? shouldn't that be 2 unkerns ?? (none would also be ok) + \unkern % new + \unkern + \textsuperscript{\multfootsep}% + \spacefactor\@x@sf\relax + \fi + } +\else + \let\FN@mf@prepare\relax +\fi +\ifFN@stablefootnote +\let\FN@sf@@footnote\footnote +\def\footnote{\ifx\protect\@typeset@protect + \expandafter\FN@sf@@footnote + \else + \expandafter\FN@sf@gobble@opt + \fi +} +\edef\FN@sf@gobble@opt{\noexpand\protect + \expandafter\noexpand\csname FN@sf@gobble@opt \endcsname} +\expandafter\def\csname FN@sf@gobble@opt \endcsname{% + \@ifnextchar[%] + \FN@sf@gobble@twobracket + \@gobble +} +\def\FN@sf@gobble@twobracket[#1]#2{} +\let\FN@sf@@footnotemark\footnotemark +\def\footnotemark{\ifx\protect\@typeset@protect + \expandafter\FN@sf@@footnotemark + \else + \expandafter\FN@sf@gobble@optonly + \fi +} +\edef\FN@sf@gobble@optonly{\noexpand\protect + \expandafter\noexpand\csname FN@sf@gobble@optonly \endcsname} +\expandafter\def\csname FN@sf@gobble@optonly \endcsname{% + \@ifnextchar[%] + \FN@sf@gobble@bracket + {}% +} +\def\FN@sf@gobble@bracket[#1]{} +\fi +\newcommand\setfnsymbol[1]{% + \@bsphack + \@ifundefined{FN@fnsymbol@#1}% + {% + \PackageError{footmisc}{Symbol style "#1" not known}% + \@eha + }{% + \expandafter\let\expandafter\@fnsymbol\csname + FN@fnsymbol@#1\endcsname + }% + \@esphack +} +\let\FN@fnsymbol@lamport\@fnsymbol +\newif\if@tempswb +\DeclareDocumentCommand\DefineFNsymbols {smO{text}m}{% + \expandafter\ifx\csname FN@fnsymbol@#2\endcsname\relax + \PackageInfo{footmisc}{Declaring symbol style #2}% + \else + \PackageWarning{footmisc}{Redeclaring symbol style #2}% + \fi + \toks@{}% + \def\@tempb{\end}% + \FN@build@symboldef#4\end + \def\@tempc{math}% + \def\@tempd{#3}% + \expandafter\xdef\csname FN@fnsymbol@#2\endcsname##1{% + \ifx\@tempc\@tempd + \noexpand\ensuremath + \else + \noexpand\nfss@text + \fi + {% + \noexpand\ifcase##1% + \the\toks@ + \noexpand\else + \IfBooleanTF#1{\noexpand\@ctrerr}% + {\noexpand\FN@orange##1}% + \noexpand\fi + }% + }% +} +\def\FN@build@symboldef#1{% + \def\@tempa{#1}% + \ifx\@tempa\@tempb + \else + \toks@\expandafter{\the\toks@\or#1}% + \expandafter\FN@build@symboldef + \fi +} +\DeclareDocumentCommand\DefineFNsymbolsTM {smm}{% + \expandafter\ifx\csname FN@fnsymbol@#2\endcsname\relax + \PackageInfo{footmisc}{Declaring symbol style #2}% + \else + \PackageWarning{footmisc}{Redeclaring symbol style #2}% + \fi + \toks@{}% + \def\@tempb{\end}% + \FN@build@symboldefTM#3\end\@null + \expandafter\xdef\csname FN@fnsymbol@#2\endcsname##1{% + \noexpand\ifcase##1% + \the\toks@ + \noexpand\else + \IfBooleanTF#1{\noexpand\@ctrerr}% + {\noexpand\FN@orange##1}% + \noexpand\fi + }% +} +\def\FN@build@symboldefTM#1#2{% + \def\@tempa{#1}% + \ifx\@tempa\@tempb + \else + \toks@\expandafter{\the\toks@\or\TextOrMath{#1}{#2}}% + \expandafter\FN@build@symboldefTM + \fi +} +\def\FN@orange#1{% + \ifFN@robust + \@arabic#1% + \@bsphack + \PackageInfo{footmisc}{Footnote number \number#1 out of range}% + \protect\@fnsymbol@orange + \@esphack + \else \@ctrerr \fi +} +\global\let\@diagnose@fnsymbol@orange\relax +\AtEndDocument{\@diagnose@fnsymbol@orange} +\def\@fnsymbol@orange{% + \gdef\@diagnose@fnsymbol@orange{% + \PackageWarningNoLine{footmisc}{Some footnote number(s) + were out of range + \MessageBreak + see log for details% + }% + }% +} +\DefineFNsymbolsTM{bringhurst}{% + \textasteriskcentered *% + \textdagger \dagger + \textdaggerdbl \ddagger + \textsection \mathsection + \textbardbl \|% + \textparagraph \mathparagraph +}% +\DefineFNsymbolsTM{chicago}{% + \textasteriskcentered *% + \textdagger \dagger + \textdaggerdbl \ddagger + \textsection \mathsection + \textbardbl \|% + \#\#% +}% +\DefineFNsymbolsTM{wiley}{% + \textasteriskcentered *% + {\textasteriskcentered\textasteriskcentered}{**}% + \textdagger \dagger + \textdaggerdbl \ddagger + \textsection \mathsection + \textparagraph \mathparagraph + \textbardbl \|% +}% +\DefineFNsymbolsTM{lamport-robust}{% + \textasteriskcentered *% + \textdagger \dagger + \textdaggerdbl \ddagger + \textsection \mathsection + \textparagraph \mathparagraph + \textbardbl \|% + {\textasteriskcentered\textasteriskcentered}{**}% + {\textdagger\textdagger}{\dagger\dagger}% + {\textdaggerdbl\textdaggerdbl}{\ddagger\ddagger}% +} +\DefineFNsymbolsTM*{lamport*}{% + \textasteriskcentered *% + \textdagger \dagger + \textdaggerdbl \ddagger + \textsection \mathsection + \textparagraph \mathparagraph + \textbardbl \|% + {\textasteriskcentered\textasteriskcentered}{**}% + {\textdagger\textdagger}{\dagger\dagger}% + {\textdaggerdbl\textdaggerdbl}{\ddagger\ddagger}% + {\textsection\textsection}{\mathsection\mathsection}% + {\textparagraph\textparagraph}{\mathparagraph\mathparagraph}% + {\textasteriskcentered\textasteriskcentered\textasteriskcentered}{***}% + {\textdagger\textdagger\textdagger}{\dagger\dagger\dagger}% + {\textdaggerdbl\textdaggerdbl\textdaggerdbl}{\ddagger\ddagger\ddagger}% + {\textsection\textsection\textsection}%% + {\mathsection\mathsection\mathsection}% + {\textparagraph\textparagraph\textparagraph}%% + {\mathparagraph\mathparagraph\mathparagraph}% +} +\setfnsymbol{lamport*} +\DefineFNsymbolsTM{lamport*-robust}{% + \textasteriskcentered *% + \textdagger \dagger + \textdaggerdbl \ddagger + \textsection \mathsection + \textparagraph \mathparagraph + \textbardbl \|% + {\textasteriskcentered\textasteriskcentered}{**}% + {\textdagger\textdagger}{\dagger\dagger}% + {\textdaggerdbl\textdaggerdbl}{\ddagger\ddagger}% + {\textsection\textsection}{\mathsection\mathsection}% + {\textparagraph\textparagraph}{\mathparagraph\mathparagraph}% + {\textasteriskcentered\textasteriskcentered\textasteriskcentered}{***}% + {\textdagger\textdagger\textdagger}{\dagger\dagger\dagger}% + {\textdaggerdbl\textdaggerdbl\textdaggerdbl}{\ddagger\ddagger\ddagger}% + {\textsection\textsection\textsection}%% + {\mathsection\mathsection\mathsection}% + {\textparagraph\textparagraph\textparagraph}%% + {\mathparagraph\mathparagraph\mathparagraph}% +} +\newcommand\mpfootnotemark{% + \@ifnextchar[% + \@xmpfootnotemark + {% + \stepcounter\@mpfn + \protected@xdef\@thefnmark{\thempfn}% + \@footnotemark + }% +} +\def\@xmpfootnotemark[#1]{% + \begingroup + \csname c@\@mpfn\endcsname #1\relax + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup + \@footnotemark +} +% \end{macrocode} +% TEMP PATCHES FOR TESTING +% \begin{macrocode} + +\endinput +%</footmisc> +% \end{macrocode} +% \Finale +% diff --git a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-new-or.dtx b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-new-or.dtx new file mode 100644 index 00000000000..08b58a72860 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-new-or.dtx @@ -0,0 +1,545 @@ +% \iffalse meta-comment +% +%% File: latex-lab-new-or.dtx +% Copyright (C) 2022 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-new-or.dtx} +\end{document} +%</driver> +% +% \fi +% +% +% \title{The \texttt{latex-lab-new-or} code\thanks{}} +% \author{Frank Mittelbach, \LaTeX{} Project} +% +% \maketitle +% +% \newcommand\fmi[1]{\begin{quote} TODO: \itshape #1\end{quote}} +% \newcommand\NEW[1]{\marginpar{\mbox{}\hfill\fbox{New: #1}}} +% \providecommand\pkg[1]{\texttt{#1}} +% +% \begin{abstract} +% \end{abstract} +% +% \section{Introduction} +% +% This code implements changes to the output routine. +% +% +% +% +% \section{Hooks and configuration points} +% +% Note: the configuration points do not have an interface mechanism +% yet and all their names are temporary right now. +% +% +% \subsubsection{Configuration points} +% +% To cater for different layouts with respect to text, footnotes, +% and bottom-floats placements there are two configuration points for +% now. +% \begin{description} +% \item[\cs{@makecol@cfgpoint} (0 arguments)] +% +% In this configuration point the \cs{@outputbox} (holding the +% galley text for the current column or page) is augmented by +% attaching floats and footnote areas together with appropriate +% spacing. Before the code is run any existing glue at the bottom +% of the \cs{@outputbox} is removed and stored in a safe +% place. If needed, it can be reinserted with one of the helper +% commands. +% +% To support setting this up the following helper commands are available: +% \begin{description} +% \item[\cs{@outputbox@append} (1 argument)] +% +% This general purpose command alters the \cs{@outputbox} box by +% appending material to it. +% +% \item[\cs{@outputbox@appendfootnotes} (0 arguments)] +% +% This command appends the footnotes to the \cs{@outputbox} (if +% there are any). If not, then it does nothing. +% +% \item[\cs{@outputbox@attachfloats} (0 arguments)] +% \item[\cs{@outputbox@attachtopfloats} (0 arguments)] +% \item[\cs{@outputbox@attachbottomfloats} (0 arguments)] +% +% Attaching top and bottom floats can usually be done in one +% go, but for special layouts we might want more control so we +% provide also separate commands. +% +% \item[\cs{@outputbox@reinsertbskip} (0 arguments)] +% +% Reinsert the bottom skip of the \cs{@outputbox} that was +% saved before. +% +% \item[Testing for existence of material] +% +% There are a number of helpers to run conditional code +% depending on whether or not there are footnotes or bottom +% floats. They are \cs{@if@footnotes@TF} and +% \cs{@if@bfloats@TF} +% (names are likely to change). +% +% \end{description} +% This configuration point needs an appropriate definition; a +% default is already given in the kernel. +% +% \item[\cs{@makecol@cfgpointii} (0 arguments)] +% +% This configuration point is used to manipulate the footnote +% material inside \cs{box}\cs{footins}. It if contains code, it +% is supposed to do some processing of that box and then write +% the result back into it (and nothing else!). By default it +% does nothing. +% +% \end{description} +% +% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } +% +% +% \section{The Implementation} +% +% \begin{macrocode} +%<*code> +% \end{macrocode} +% +% \subsection{File declaration} +% \begin{macrocode} +\ProvidesFile{latex-lab-new-or.ltx} + [2022-03-09 v0.1b changes to the output routine] +% \end{macrocode} +% \subsection{\cs{@makecol} reimplementation} +% +% In order for other packages to prepend or append code to +% \cs{@makecol}, they can use the generic command hooks +% \texttt{cmd/@makecol/before} and \texttt{cmd/@makecol/after}, so +% there is nothing we need to do here. +% +% +% \begin{macro}{\@makecol} +% \cs{@makecol} is shortened a lot, basically all the hardwired +% code in the middle has moved into a configuration point. +% \begin{macrocode} +\def \@makecol {% + \@kernel@before@cclv + \setbox\@outputbox \box\@cclv +% \end{macrocode} +% The only real addition is the next command which either does +% nothing or removes an infinite glue from the bottom of the +% \cs{@outputbox}. +% \begin{macrocode} + \@outputbox@removebskip +% \end{macrocode} +% Any ``here'' floats in the \cs{@outputbox} are now handled so we +% recycle their registers and put them back to the \cs{@freelist}. +% \begin{macrocode} + \let\@elt\relax + \xdef\@freelist{\@freelist\@midlist}% + \global \let \@midlist \@empty +% \end{macrocode} +% Here we have the configurable part. +% \fmi{Interface to configuration points will change in the future} +% \begin{macrocode} + \@makecol@cfgpoint +% \end{macrocode} +% The we deal with any \cs{enlargethispage} or run the normal code +% to build a column. +% \begin{macrocode} + \ifvbox\@kludgeins + \@makespecialcolbox + \else + \@makenormalcolbox + \fi + \global \maxdepth \@maxdepth +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@outputbox@depth} +% We need to know the depth of \cs{@outputbox} once in a +% while. Rather than using a temp dimen (as it was done in the +% past), we give it a proper register. +% \begin{macrocode} +\newdimen\@outputbox@depth +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@makenormalcolbox} +% Taken out of \cs{@makecol} for readability. +% \begin{macrocode} +\def \@makenormalcolbox {% + \setbox\@outputbox \vbox to\@colht {% + \@texttop + \@outputbox@depth \dp\@outputbox + \unvbox \@outputbox + \vskip -\@outputbox@depth + \@textbottom + }% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@makespecialcolbox} +% Make the colbox when \cs{enlargethispage} was used. +% \begin{macrocode} +\def \@makespecialcolbox {% + \@outputbox@append {\vskip-\@outputbox@depth}% + \@tempdima \@colht + \ifdim \wd\@kludgeins>\z@ + \advance \@tempdima -\ht\@outputbox + \advance \@tempdima \pageshrink + \setbox\@outputbox \vbox to \@colht {% + \unvbox\@outputbox + \vskip \@tempdima + \@textbottom + }% + \else + \advance \@tempdima -\ht\@kludgeins + \setbox \@outputbox \vbox to \@colht {% + \vbox to \@tempdima {% + \unvbox\@outputbox + \@textbottom}% + \vss}% + \fi + {\setbox \@tempboxa \box \@kludgeins}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@outputbox@removebskip} +% +% This is really a bug fix for the kernel but one we only +% automatically make in new documents using \cs{DocumentMetadata}. +% \fmi{may make optional for legacy docs} +% If +% \cs{raggedbottom} is in force, footnotes get attached to the main +% galley at a distance of \cs{footskip} on all pages except on +% those that are ended by \cs{newpage} or \cs{clearpage} where the +% \cs{vfil} from \cs{newpage} pushes the footnotes to the very bottom. +% +% This is kind of a weird difference to a page ending with +% \cs{pagebreak}---in that case the page is also run +% short, but the footnotes are not pushed to the bottom. +% +% In \pkg{footmisc} \cs{@outputbox@removebskip} is only applied when +% \pkg{footmisc} is called with with an option specifying the +% footnote placement, i.e., not in the default case. +% In new documents we apply it always. +% \begin{macrocode} +\def\@outputbox@removebskip{% +% \end{macrocode} +% We first test if we are in a \cs{raggedbottom} layout. If not we +% do nothing, but we don't disable the code because +% \cs{raggedbottom} may get used only for some parts of the +% document. +% \begin{macrocode} + \ifx\@textbottom\relax \else +% \end{macrocode} +% We then append some negative glue at the end of \cs{@outputbox} +% provided it has a glue stretch order of 1 or more (i.e., contains +% a \texttt{fil} or \texttt{fill} part). +% \begin{macrocode} + \@outputbox@append{% + \@tempskipa\lastskip + \ifnum \gluestretchorder\@tempskipa>\z@ + \vskip-\@tempskipa +% \end{macrocode} +% \begin{macro}{\@outputbox@reinsertbskip} +% We also record the value so that it can be reinserted +% elsewhere. As we have to do this globally, we also need to +% explicitly reset it if we don't find any such glue. +% \begin{macrocode} + \xdef\@outputbox@reinsertbskip + {\noexpand\@outputbox@append{\vskip\the\@tempskipa}}% + \else + \global\let\@outputbox@reinsertbskip\relax + \fi + }% + \fi +} +% \end{macrocode} +% We need a trivial top-level definition for +% \cs{@outputbox@reinsertbskip} in case the first page has no +% bottom glue and the command gets called. +% \begin{macrocode} +\let\@outputbox@reinsertbskip\relax +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% \begin{macro}{\@kernel@before@cclv} +% \begin{macro}{\@kernel@before@footins} +% These two commands are internal kernel hooks intended for tagging +% support in case that is active. By default they do nothing (and +% may have been defined already by \cs{DocumentMetadata}). +% \begin{macrocode} +\providecommand\@kernel@before@cclv{} +\providecommand\@kernel@before@footins{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% +% \subsection{The output routine configuration components} +% +% Here we provide the components that are used to define +% \cs{@makecol@cfgpoint}. +% +% +% \begin{macro}{\@outputbox@append} +% +% This general purpose command alters the \cs{@outputbox} box by +% appending material to it. As this is a box typesetting operation +% we make sure that the last line of the box reflects the true +% depth of the last line (in case that is needed later). We also +% expose the current depth of \cs{@outputbox} as +% \cs{@outputbox@depth} before unboxing so that its value can be +% used by \verb=#1= if wanted. +% \begin{macrocode} +\def\@outputbox@append #1{% +% \if!\detokenize{#1}!\else + \setbox\@outputbox \vbox {% + \boxmaxdepth \@maxdepth + \@outputbox@depth\dp\@outputbox % if needed in #1 + \unvbox \@outputbox + #1% + }% +% \fi +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% \begin{macro}{\@outputbox@appendfootnotes} +% +% This command appends the footnotes to the \cs{@outputbox} (if +% there are any). If not then it does nothing. +% \begin{macrocode} +\def\@outputbox@appendfootnotes {% + \ifvoid\footins \else +% \end{macrocode} +% First come two configuration points: what to do if we are in a split +% footnote situation and a second one that does some manipulation +% of the \cs{footins} box before it gets appended. +% \fmi{this code will get revised as part of CP handling in the future} +% \begin{macrocode} + \@makecol@handlesplitfootnotes + \@makecol@cfgpointii +% \end{macrocode} +% Then the footnotes are appended: +% \begin{macrocode} + \@outputbox@append{% + \vskip \skip\footins + \@kernel@before@footins + \color@begingroup + \normalcolor + \footnoterule +% \end{macrocode} +% Support for \pkg{pdfcolfoot}, eventually this can go once color +% is properly supported. +% \begin{macrocode} + \csname pdfcolfoot@current\endcsname + \unvbox \footins + \color@endgroup + }% + \fi +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@outputbox@attachfloats} +% \begin{macro}{\@outputbox@attachtopfloats} +% \begin{macro}{\@outputbox@attachbottomfloats} +% Attaching top and bottom floats can usually be done in one go, +% but for special layouts we might want more control so we provide +% also separate commands. +% \begin{macrocode} +\let \@outputbox@attachfloats \@combinefloats +% \end{macrocode} +% +% \begin{macrocode} +\def \@outputbox@attachtopfloats {% + \ifx \@toplist\@empty \else \@cflt \fi +} +\def \@outputbox@attachbottomfloats {% + \ifx \@botlist\@empty \else \@cflb \fi +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% +% \begin{macro}{\@makecol@handlesplitfootnotes} +% \begin{macro}{\@makecol@splitfootnotemessagehook} +% This is only an early draft and doesn't do much. +% Contains incomplete preparation for tagging commented out. +% \fmi{Interfaces and code will change in the future} +% \begin{macrocode} +\def\@makecol@handlesplitfootnotes {% +% \ifx\splitfootnote@continuation\@empty \else +% \setbox\footins\vbox{\splitfootnote@continuation\unvbox\footins}% +% \global\let\splitfootnote@continuation\@empty +% \fi + \ifnum\insertpenalties>\z@ + \@makecol@splitfootnotemessagehook +% \setbox\footins\vbox{\unvbox\footins --- END at split}% +% \gdef\splitfootnote@continuation {--- START after split}% + \fi +} +%\def\splitfootnote@continuation{} +% \end{macrocode} +% This could issue warning if split footnotes are encountered. +% \begin{macrocode} +\let \@makecol@splitfootnotemessagehook \@empty +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% \begin{macro}{\@makecol@cfgpointii} +% +% Configuration point to support manipulation of footins box +% (result needs to be moved back in there). Used by the +% \texttt{para} option. +% \fmi{Interface will change in the future} +% \begin{macrocode} +\let \@makecol@cfgpointii \@empty +% \end{macrocode} +% +% \end{macro} +% +% +% +% \fmi{Some temp interfaces until configuration points are available.} +% +% \begin{macro}{\@if@flushbottom@TF} +% Test for \cs{flushbottom} (currently not used). +% \begin{macrocode} +\def\@if@flushbottom@TF{% + \ifx\@textbottom\relax + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@if@footnotes@TF} +% Test if footnotes are present on the current page. +% \begin{macrocode} +\def\@if@footnotes@TF{% + \ifvoid\footins + \expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@if@bfloats@TF} +% Test if bottom floats are around. +% \begin{macrocode} +\def\@if@bfloats@TF{% + \ifx \@botlist\@empty + \expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi +} +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{The \cs{@makecol} configuration} +% +% +% \begin{macro}{\@makecol@cfgpoint} +% +% Here is only the configuration for the default case for now, +% others are provided by \pkg{footmisc}. +% +% \begin{macrocode} + \def\@makecol@cfgpoint {% + \@outputbox@appendfootnotes + \@outputbox@attachfloats +% \end{macrocode} +% We do, however, reinsert the bottom skip from \cs{newpage} if it +% was taken out earlier. This is, strictly speaking, not necessary +% in most cases, but it is a \cs{vfil} while \cs{raggedbottom} is +% only generating \verb=\vspace{0pt plus .0001fil}=, so if you have +% several \cs{vfil} on the page before the \cs{newpage} you would +% alter the space distribution if one is taken out. +% \begin{macrocode} + \@outputbox@reinsertbskip + } +% \end{macrocode} +% \end{macro} +% +% +% \section {Replacement for the \pkg{footmisc} package} +% +% The replacement for \pkg{footmisc}. If the new code is used, we must replace +% the package if it is loaded by the user: +% \begin{macrocode} +\declare@file@substitution{footmisc.sty}{latex-lab-footmisc.ltx} +% \end{macrocode} +% +% +% +% \section {Temp stuff that is related but should go to the kernel} +% +% \begin{macrocode} +\input{latex-lab-footnotes.ltx} +% \end{macrocode} +% +% +% \begin{macrocode} +%</code> +% \end{macrocode} +% +% \Finale +% diff --git a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-prototype.dtx b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-prototype.dtx new file mode 100644 index 00000000000..090e6c91a4f --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-prototype.dtx @@ -0,0 +1,827 @@ +% \iffalse meta-comment +% +%% File: latex-lab-prototype.dtx +% +% Copyright (C) 1999 Frank Mittelbach, Chris Rowley, David Carlisle +% (C) 2004-2010 Frank Mittelbach, The LaTeX Project +% (C) 2011-2022 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 +% +% This file is part of the "latex-lab bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/latex3/latex2e +% +% for those people who are interested. +% +%<*driver> +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{^^A +% The \textsf{latex-lab-prototype} package\\ Prototype document functions^^A +% } +% +% \author{^^A +% The \LaTeX{} Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released 2022-03-09} +% +% \maketitle +% +% \tableofcontents +% +% \bigskip +% +% \begin{documentation} +% +% There are three broad \enquote{layers} between putting down ideas into +% a source file and ending up with a typeset document. These layers of +% document writing are +% \begin{enumerate} +% \item authoring of the text with mark-up; +% \item document layout design; +% \item implementation (with \TeX{} programming) of the design. +% \end{enumerate} +% We write the text as an author, and we see the visual output of the design +% after the document is generated; the \TeX{} implementation in the middle is +% the glue between the two. +% +% \LaTeX{}'s greatest success has been to standardise a system of mark-up that +% balances the trade-off between ease of reading and ease of writing to suit +% almost all forms of technical writing. It's +% other original strength was a good background in typographical design; while +% the standard \LaTeXe{} classes look somewhat dated now in terms of their +% visual design, their typography is generally sound. (Barring the occasional +% minor faults.) +% +% However, \LaTeXe{} has always lacked a standard approach to customising +% the visual design of a document. Changing the looks of the standard classes +% involved either: +% \begin{itemize} +% \item Creating a new version of the implementation code of the class and +% editing it. +% \item Loading one of the many packages to customise certain elements of +% the standard classes. +% \item Loading a completely different document class, such as +% \textsf{KOMA-Script} or \textsf{memoir}, that allows easy customisation. +% \end{itemize} +% All three of these approaches have their drawbacks and learning curves. +% +% The idea behind this module is to cleanly separate the three layers +% introduced at the beginning of this section, so that document authors who +% are not programmers can easily change the design of their documents. +% The approach here also makes it easier for \LaTeX{} programmers to provide +% their own customisations on top of a pre-existing class. +% +% \section{What is a document?} +% +% Besides the textual content of the words themselves, the source file +% of a document contains mark-up elements that add structure to the +% document. These elements include sectional divisions, figure/table +% captions, lists of various sorts, theorems/proofs, and so on. +% The list will be different for every document that can be written. +% +% Each element can be represented logically without worrying about the +% formatting, with mark-up such as \cs{section}, \cs{caption}, +% |\begin{enumerate}| and so on. The output of each one of these +% document elements will be a typeset representation of the information +% marked up, and the visual arrangement and design of these elements +% can vary widely in producing a variety of desired outcomes. +% +% For each type of document element, there may be design variations that +% contain the same sort of information but present it in slightly +% different ways. For example, the difference between a numbered and an +% unnumbered section, \cs{section} and |\section*|, or the difference +% between an itemised list or an enumerated list. +% +% There are three distinct layers in the definition of +% \enquote{a document} at this level +% \begin{enumerate} +% \item semantic elements such as the ideas of sections and lists; +% \item a set of design solutions for representing these elements +% visually; +% \item specific variations for these designs that represent the +% elements in the document. +% \end{enumerate} +% In the parlance of the template system, these are called object types, +% templates, and instances, and they are discussed below in sections +% \ref{sec:objects}, \ref{sec:templates}, and~\ref{sec:instances}, +% respectively. +% +% By formally declaring documents to be composed of mark-up elements +% grouped into objects, which are interpreted and typeset with a set of +% templates, each of which has one or more instances with which to +% compose each and every semantic unit of the text, we can cleanly +% separate the components of document construction. +% +% \section{Object types} +% \label{sec:objects} +% +% An \emph{object type} (sometimes just \enquote{object}) is an +% abstract idea of a document element that takes a fixed number of +% arguments corresponding to the information from the document author +% that it is representing. A sectioning object, for example, might take +% three inputs: \enquote{title}, \enquote{short title}, and +% \enquote{label}. +% +% Any given document class will define which object types are to be +% used in the document, and any template of a given object type can be +% used to generate an instance for the object. (Of course, different +% templates will produce different typeset representations, but the +% underlying content will be the same.) +% +% \begin{function}{\prototype_declare_object:nn} +% \begin{syntax} +% \cs{prototype_declare_object:nn} \Arg{object type} \Arg{no.~of args} +% \end{syntax} +% This function defines an \meta{object type} taking +% \meta{no.~of arguments}, where the \meta{object type} is an +% abstraction as discussed above. For example, +% \begin{verbatim} +% \prototype_declare_object:nn { sectioning } { 3 } +% \end{verbatim} +% creates an object type \enquote{sectioning}, where each use of that +% object type will need three arguments. +% +% While not formally verified the semantics of all arguments are part +% of the object declaration and need to be carefully documented in +% order to make the use of different templates for the same object +% type meaningful. +% \end{function} +% +% \section{Templates} +% \label{sec:templates} +% +% A \emph{template} is a generalised design solution for representing +% the information of a specified object type. Templates that do the same +% thing, but in different ways, are grouped together by their object type +% and given separate names. There are two important parts to a template: +% \begin{itemize} +% \item the parameters it takes to vary the design it is producing; +% \item the implementation of the design. +% \end{itemize} +% +% \begin{function}{\prototype_declare_template:nnnn} +% \begin{syntax} +% \cs{prototype_declare_template:nnnn} +% ~~\Arg{object type} \Arg{template} +% ~~\Arg{key definitions} \Arg{code} +% \end{syntax} +% A \meta{template} interface is declared for a particular +% \meta{object type}. The interface itself is +% defined by the \meta{key definitions}, which is itself a key--value list +% using the same interface as \cs{keys_define:nn}. (The keys created +% here \emph{are} managed \pkg{l3keys} in the tree +% \texttt{prototype/\meta{object}/\meta{template}}). As described below, +% the keys should be defined such that they can be set multiple times: +% first to a default value, then to a specific value for an instance +% and finally to a per-use override. +% +% The \meta{code} argument of \cs{template_declare_template:nnnn} is used +% as the replacement text for the template when it is used, either +% directly or as an instance. This may therefore accept arguments +% |#1|, |#2|, \emph{etc}.~as detailed by the \meta{number of arguments} +% taken by the object type. The template and instance key values (see +% below) are assigned before the \meta{code} is inserted. +% \end{function} +% +% \begin{function}{\prototype_declare_defaults:nnn} +% \begin{syntax} +% \cs{prototype_declare_template:nnnn} +% ~~\Arg{object type} \Arg{template} \Arg{defaults} +% \end{syntax} +% Sets the default values for each \meta{key} in a \meta{template}. When +% a template is used, these values are applied first \emph{before} those +% set by \cs{prototype_use_template:nnn} or +% \cs{prototype_declare_instance:nnnn}. If not default is given, the +% prevailing state when the template is used will apply. +% \end{function} +% +% \section{Instances} +% \label{sec:instances} +% +% After a template is defined it still needs to be put to use. The +% parameters that it expects need to be defined before it can be used in +% a document. Every time a template has parameters given to it, an +% \emph{instance} is created, and this is the code that ends up in the +% document to perform the typesetting of whatever pieces of information +% are input into it. +% +% For example, a template might say \enquote{here is a section with or +% without a number that might be centred or left aligned and print its +% contents in a certain font of a certain size, with a bit of a gap +% before and after it} whereas an instance declares \enquote{this is a +% section with a number, which is centred and set in $12\,\text{pt}$ +% italic with a $10\,\text{pt}$ skip before and a +% $12\,\text{pt}$ skip after it}. Therefore, an instance is just a +% frozen version of a template with specific settings as chosen by the +% designer. +% +% \begin{function}{\prototype_declare_instance:nnnn} +% \begin{syntax} +% \cs{prototype_declare_instance:nnnn} +% ~~\Arg{object type} \Arg{template} \Arg{instance} \Arg{parameters} +% \end{syntax} +% This function uses a \meta{template} for an \meta{object type} +% to create an \meta{instance}. The \meta{instance} will be set +% up using the \meta{parameters}, which will set some of the +% \meta{keys} in the \meta{template}. +% +% As a practical example, consider an object type for document sections +% (which might include chapters, parts, sections, \emph{etc}.), which +% is called \texttt{sectioning}. One possible template for this +% object type might be called \texttt{basic}, and one instance of this +% template would be a numbered section. The instance declaration might +% read: +% \begin{verbatim} +% \prototype_declare_instance:nnnn { sectioning } { basic } { section-num } +% { +% numbered = true , +% justification = center , +% font = \normalsize\itshape , +% before-skip = 10pt , +% after-skip = 12pt , +% } +% \end{verbatim} +% Of course, the key names here are entirely imaginary, but illustrate +% the general idea of fixing some settings. +% \end{function} +% +% \section{Document interface} +% +% After the instances have been chosen, document commands must be +% declared to use those instances in the document. +% \cs{prototype_use_instance:nn} +% calls instances directly, and this command should be used internally +% in document-level mark-up. +% +% \begin{function}{\prototype_use_instance:nn, \prototype_use_instance:nnn} +% \begin{syntax} +% \cs{prototype_use_instance:nn} +% ~~\Arg{object type} \Arg{instance} \meta{arguments} +% \cs{prototype_use_instance:nn}n +% ~~\Arg{object type} \Arg{instance} \Arg{overrides} \meta{arguments} +% \end{syntax} +% Uses an \meta{instance} of the \meta{object type}, which will require +% \meta{arguments} as determined by the number specified for the +% \meta{object type}. The \meta{instance} must have been declared +% before it can be used, otherwise an error is raised. The \texttt{nnn} +% version allows for local overrides of the instance settings using the +% additional keyval argument. +% \end{function} +% +% \begin{function}{\prototype_use_template:nnnn} +% \begin{syntax} +% \cs{prototype_use_template:nnnn} \Arg{object type} \Arg{template} +% ~~\Arg{settings} \meta{arguments} +% \end{syntax} +% Uses the \meta{template} of the specified \meta{object type}, +% applying the \meta{settings} and absorbing \meta{arguments} as +% detailed by the \meta{object type} declaration. This in effect +% is the same as creating an instance using +% \cs{template_declare_instance:nnnn} and immediately using it with +% \cs{template_use_instance:nnn}, but without the instance having any +% further existence. It is therefore useful where a template needs to +% be used once. +% \end{function} +% +% \section{Showing template information} +% +% \begin{function} +% { +% \prototype_show_template_code:nn , +% \prototype_show_template_defaults:nn , +% \prototype_show_instance_values:nn +% } +% \begin{syntax} +% \cs{prototype_show_template_code:nn} \Arg{object type} \Arg{template} +% \cs{prototype_show_template_defaults:nn} \Arg{object type} \Arg{template} +% \cs{prototype_show_instance_values:nn} \Arg{object type} \Arg{instance} +% \end{syntax} +% Show information about a declare template or instance for +% debugging purposes. +% \end{function} +% +% \section{Open questions and comparison with \pkg{xtemplate}} +% +% The approach here is modelled on that from \pkg{xtemplate}, but since it uses +% \pkg{l3keys} rather than dedicated key handling, there are some differences. +% There is also a simplification in that collections are not supported +% (because we now think that they provided the wrong kind of abstraction). +% +% The various open questions, including those linked to \pkg{xtemplate} +% concepts, are collected here. +% +% \subsection{Module name} +% +% This is currently open for ideas: traditionally \texttt{template} has +% been used. This may link to the need for both templates and instances +% (\emph{vide infra}). +% +% \subsection{Design-level names} +% +% These are currently not provided. That allows both this code and +% \pkg{xtemplate} to be loaded in the same document. We will likely want +% to decide on these names: they could for example include +% \texttt{Prototype} or \texttt{Design}, or could use the existing +% \pkg{xtemplate} if a compatibility approach can be designed. +% +% \subsection{Objects} +% +% Is this name clear? A possible alternative is `element'. +% +% \subsection{Efficiency and repetition of key setting} +% +% In the \pkg{xtemplate} implementation, keys values are stored in property +% lists before being applied. This means that when creating an instance, the +% template defaults can be replaced entirely by any instance values. In +% contrast, the approach here simply precompiles all of the template defaults, +% then appends the precompiled list from the instance. Some variables are +% therefore set twice. More importantly, this means that arbitrary code +% could be executed twice: authors need to be aware of this. +% +% \subsection{Key ordering} +% +% Linked to the previous idea, in \pkg{xtemplate} keys are set in the +% order they are declared in the setup. In contrast, using \pkg{l3keys} +% they are set in the order the keys are given in the input. Is this OK? +% +% \subsection{Setting defaults} +% +% The current approach requires setting the defaults separately from +% the key creation. That means listing keys twice. However, it also +% avoids further overloading of the keyval setup. Is this reasonable? +% +% \subsection{The need for templates and instances} +% +% In \pkg{xtemplate}, storing keys in a \texttt{prop} means that there +% is a real efficiency when creating an instance. In contrast, using +% precompiled keys here, creating a template and creating an instance +% are almost identical. Could we drop the distinction? That would then +% work well if we allowed instances to be derived from others: effectively +% the same as instances from templates, but with a `flatter' approach. +% +% \subsection{Assignment of key values} +% +% The \pkg{xtemplate} approach uses \cs{AssignTemplateKeys} to +% specify when keys are assigned. In contrast, here key assignment is +% automatic. If you look over \TeX{} Live, the only places that +% \cs{AssignTemplateKeys} is not the first thing in the code are in limited +% use cases in \pkg{enotez} and \pkg{xgalley}. In both packages, that's because +% they want to limit the scope of assignment. In \pkg{enotez} the key setting +% is placed inside a group, whereas in \pkg{xgalley} there is a +% save-and-restore approach as a group is not possible. Both of those use-cases +% could be covered in other ways: it's a question of setting up the template +% keys so they assign to an intermediate variable, then assigning those as +% necessary to the live ones for these cases. +% +% The main reason for not using \cs{AssignTemplateKeys} is that the common +% case doesn't need it. We could of course stick to an explicit-assignment +% approach, or have two variants or template-creation, etc., where assignment +% is manual in one of them. +% +% \subsection{Values from other keys} +% +% The \pkg{xtemplate} approach offers \cs{KeyValue} to pass the value of +% one key as the default for another. That relies on the fact that key +% setting is ordered (\emph{vide supra}). It also means that there is +% some code to check for this as part of key setting: it's non-trivial +% to support. The current \pkg{l3keys}-based code doesn't offer this. +% Instead one could use for example meta keys. That is a different +% interface and might occasionally be awkward. We can add some +% \texttt{.store-value:n} property to allow a \cs{keys_value:nn} approach, +% but without key ordering it might still not work in the same way. +% +% \subsection{The nature of debugging data} +% +% Due to the differences in data storage, the \pkg{xtemplate} method offers +% a richer ability to debug template internals than the one here. We can look +% at \emph{e.g.}\ tracking all keys for a template to make this easier. +% It is worth noting that much of this data is really something that +% should be part of the documentation anyway. Also, it would be trivial +% to save the raw defaults and do the `hard' processing only if asked +% to show the values (\emph{i.e.}\ using code similar to that in +% \pkg{xtemplate}). +% +% \subsection{Collections} +% +% These are not implemented at all: we likely want a new approach to +% contexts. +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{latex-lab-prototype} Implementation} +% +% \subsection{File declaration} +% \begin{macrocode} +%<*package> +\ProvidesFile{latex-lab-prototype.sty} + [2022-03-09 v0.1b Experimental prototype document functions] +%</package> +% \end{macrocode} +% +% \begin{macrocode} +%<*2ekernel> +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOn +% \end{macrocode} +% +% \subsection{\cs{keys_precompile:nnN}} +% +% \begin{macrocode} +%<@@=keys> +% \end{macrocode} +% +% This may not yet be available in \pkg{expl3} so we ensure it is set up +% here: all temporary. We just redefine those internals that need it. +% \begin{macrocode} +\tl_if_exist:NF \l_@@_precompile_tl + { + \bool_new:N \l_@@_precompile_bool + \tl_new:N \l_@@_precompile_tl + } +\cs_gset_protected:Npn \@@_precompile:n #1 + { + \bool_if:NTF \l_@@_precompile_bool + { \tl_put_right:Nn \l_@@_precompile_tl } + { \use:n } + {#1} + } +\cs_gset_protected:Npn \@@_bool_set:Nnnn #1#2#3#4 + { + \bool_if_exist:NF #1 { \bool_new:N #1 } + \@@_choice_make: + \@@_cmd_set:nx { \l_keys_path_str / true } + { \exp_not:c { bool_ #2 set_ #3 :N } \exp_not:N #1 } + \@@_cmd_set:nx { \l_keys_path_str / false } + { \exp_not:c { bool_ #2 set_ #4 :N } \exp_not:N #1 } + \@@_cmd_set_direct:nn { \l_keys_path_str / unknown } + { + \msg_error:nnx { keys } { boolean-values-only } + \l_keys_key_str + } + \@@_default_set:n { true } + } +\cs_gset_protected:Npn \@@_choice_make_aux:N #1 + { + \cs_set_nopar:cpn { \c_@@_type_root_str \l_keys_path_str } + { choice } + \@@_cmd_set_direct:nn \l_keys_path_str { #1 {##1} } + \@@_cmd_set_direct:nn { \l_keys_path_str / unknown } + { + \msg_error:nnxx { keys } { choice-unknown } + \l_keys_path_str {##1} + } + } +\cs_gset_protected:Npn \@@_cmd_set:nn #1#2 + { \@@_cmd_set_direct:nn {#1} { \@@_precompile:n {#2} } } +\cs_gset_protected:Npn \@@_cmd_set_direct:nn #1#2 + { \cs_set_protected:cpn { \c_@@_code_root_str #1 } ##1 {#2} } +\cs_gset_protected:Npn \@@_cs_set:NNpn #1#2#3# + { + \cs_set_protected:cpx { \c_@@_code_root_str \l_keys_path_str } ##1 + { + \@@_precompile:n + { #1 \exp_not:N #2 \exp_not:n {#3} {##1} } + } + \use_none:n + } +\cs_gset_protected:Npn \@@_meta_make:n #1 + { + \exp_args:NVo \@@_cmd_set_direct:nn \l_keys_path_str + { + \exp_after:wN \keys_set:nn \exp_after:wN + { \l_@@_module_str } {#1} + } + } +\cs_gset_protected:Npn \@@_meta_make:nn #1#2 + { + \exp_args:NV \@@_cmd_set_direct:nn + \l_keys_path_str { \keys_set:nn {#1} {#2} } + } +\cs_gset_protected:Npn \keys_precompile:nnN #1#2#3 + { + \bool_set_true:N \l_@@_precompile_bool + \tl_clear:N \l_@@_precompile_tl + \keys_set:nn {#1} {#2} + \bool_set_false:N \l_@@_precompile_bool + \tl_set_eq:NN #3 \l_@@_precompile_tl + } +\cs_gset_protected:Npn \@@_show:Nnn #1#2#3 + { + #1 { keys } { show-key } + { \@@_trim_spaces:n { #2 / #3 } } + { + \keys_if_exist:nnT {#2} {#3} + { + \exp_args:Nnf \msg_show_item_unbraced:nn { code } + { + \exp_args:Ne \@@_show:n + { + \exp_args:Nc \cs_replacement_spec:N + { + \c_@@_code_root_str + \@@_trim_spaces:n { #2 / #3 } + } + } + } + } + } + { } { } + } +\cs_gset:Npx \@@_show:n #1 + { + \exp_not:N \@@_show:w + #1 + \tl_to_str:n { \@@_precompile:n } + #1 + \tl_to_str:n { \@@_precompile:n } + \exp_not:N \s_@@_stop + } +\use:x + { + \cs_gset:Npn \exp_not:N \@@_show:w + ##1 \tl_to_str:n { \@@_precompile:n } + ##2 \tl_to_str:n { \@@_precompile:n } + ##3 \exp_not:N \s_@@_stop + } + { + \tl_if_blank:nTF {#2} + {#1} + { \@@_show:Nw #2 \s_@@_stop } + } +\use:x + { + \cs_gset:Npn \exp_not:N \@@_show:Nw ##1##2 + \c_right_brace_str \exp_not:N \s_@@_stop + } + {#2} +% \end{macrocode} +% +% \subsection{Setup} +% +% \begin{macrocode} +%<@@=prototype> +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_tl} +% \begin{macrocode} +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Data structures} +% +% \begin{variable}{\l_@@_object_prop} +% \begin{macrocode} +\prop_new:N \l_@@_object_prop +% \end{macrocode} +% \end{variable} +% +% \subsection{Creating objects} +% +% \begin{macro}{\prototype_declare_object:nn, \@@_declare_object:nn} +% Although the object type is the \enquote{top level} of the template +% system, it is actually very easy to implement. All that happens is that +% the number of arguments required is recorded, indexed by the name of the +% object type. +% \begin{macrocode} +\cs_new_protected:Npn \prototype_declare_object:nn #1#2 + { + \exp_args:Nx \@@_declare_object:nn { \int_eval:n {#2} } {#1} + } +\cs_new_protected:Npn \@@_declare_object:nn #1#2 + { + \int_compare:nTF { 0 <= #1 <= 9 } + { + \msg_info:nnnn { prototype } { declare-object-type } {#2} {#1} + \prop_put:Nnn \l_@@_object_prop {#2} {#1} + } + { \msg_error:nnxx { prototype } { bad-number-of-arguments } {#2} {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Templates and instances} +% +% \begin{variable}{\l_@@_assignments_tl} +% Used to insert the set keys. +% \begin{macrocode} +\tl_new:N \l_@@_assignments_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\prototype_declare_template:nnnn} +% \begin{macro}{\prototype_declare_defaults:nnn} +% Creating a template means defining the keys, storing the defaults and +% creating the function. The defaults are done separately from the other +% parts as that fits the \pkg{l3keys} pattern but also makes it easy to +% alter that aspect without changing the core implementation. +% \begin{macrocode} +\cs_new_protected:Npn \prototype_declare_template:nnnn #1#2#3#4 + { + \prop_get:NnNTF \l_@@_object_prop {#1} \l_@@_tmp_tl + { + \keys_define:nn { prototype / #1 / #2 } {#3} + \tl_clear_new:c { l_@@_defaults_ #1 _ #2 _tl } + \cs_generate_from_arg_count:cNnn + { @@_template_ #1 _ #2 :w } + \cs_set_protected:Npn + { \l_@@_tmp_tl } + { + \tl_use:N \l_@@_assignments_tl + #4 + } + } + { \msg_error:nnn { prototype } { unknown-object-type } {#1} } + } +\cs_new_protected:Npn \prototype_declare_defaults:nnn #1#2#3 + { + \cs_if_exist:cTF { @@_template_ #1 _ #2 :w } + { \tl_set:cn { l_@@_defaults_ #1 _ #2 _tl } {#3} } + { \msg_error:nnn { prototype } { unknown-template } {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +\cs_generate_variant:Nn \keys_precompile:nnN { v , nv } +% \end{macrocode} +% +% \begin{macro}{\prototype_use_template:nnn} +% \begin{macro}{\prototype_declare_instance:nnnn} +% \begin{macro}{\@@_declare_aux:nnnn} +% Using a template and creating an instance are the same thing other +% than the final step: using the template or storing the key settings. +% We do not attempt to maximise efficiency in setting, rather we have +% a clear approach in which the final assignments may have multiple +% entries. +% \begin{macrocode} +\cs_new_protected:Npn \prototype_use_template:nnn #1#2#3 + { + \@@_declare_aux:nnnn {#1} {#2} {#3} + { \use:c { @@_template_ #1 _ #2 :w } } + } +\cs_new_protected:Npn \prototype_declare_instance:nnnn #1#2#3#4 + { + \@@_declare_aux:nnnn {#1} {#2} {#4} + { + \tl_clear_new:c { l_@@_instance_ #1 _ #3 _pars_tl } + \tl_set_eq:cN { l_@@_instance_ #1 _ #3 _pars_tl } + \l_@@_assignments_tl + \tl_clear_new:c { l_@@_instance_ #1 _ #3 _template_tl } + \tl_set:cn { l_@@_instance_ #1 _ #3 _template_tl } {#2} + } + } +\cs_new_protected:Npn \@@_declare_aux:nnnn #1#2#3#4 + { + \cs_if_exist:cTF { @@_template_ #1 _ #2 :w } + { + \keys_precompile:nvN + { prototype / #1 / #2 } + { l_@@_defaults_ #1 _ #2 _tl } + \l_@@_assignments_tl + \keys_precompile:nnN { prototype / #1 / #2 } {#3} \l_@@_tmp_tl + \tl_put_right:NV \l_@@_assignments_tl \l_@@_tmp_tl + #4 + } + { \msg_error:nnn { prototype } { unknown-template } {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\prototype_use_instance:nn} +% \begin{macro}{\prototype_use_instance:nnn} +% Recover the values and insert the code. +% \begin{macrocode} +\cs_new_protected:Npn \prototype_use_instance:nn #1#2 + { \prototype_use_instance:nnn {#1} {#2} { } } +\cs_new_protected:Npn \prototype_use_instance:nnn #1#2#3 + { + \tl_if_exist:cTF { l_@@_instance_ #1 _ #2 _template_tl } + { + \tl_set_eq:Nc \l_@@_assignments_tl + { l_@@_instance_ #1 _ #2 _pars_tl } + \tl_if_blank:nF {#3} + { + \keys_precompile:vnN + { + prototype / #1 / + \tl_use:c { l_@@_instance_ #1 _ #2 _template_tl } + } + {#3} + \l_@@_tmp_tl + \tl_put_right:NV \l_@@_assignments_tl + \l_@@_tmp_tl + } + \use:c + { + @@_template_ #1 _ + \tl_use:c { l_@@_instance_ #1 _ #2 _template_tl } + :w + } + } + { \msg_error:nnn { prototype } { unknown-instance } {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Showing information} +% +% \begin{macro} +% { +% \prototype_show_template_code:nn , +% \prototype_show_template_defaults:nn , +% \prototype_show_instance_values:nn +% } +% \begin{macrocode} +\cs_new_protected:Npn \prototype_show_template_code:nn #1#2 + { + \prop_if_in:NnTF \l_@@_object_prop {#1} + { \cs_show:c { @@_template_ #1 _ #2 :w } } + { \msg_error:nnn { prototype } { unknown-object-type } {#1} } + } +\cs_new_protected:Npn \prototype_show_template_defaults:nn #1#2 + { + \cs_if_exist:cTF { @@_template_ #1 _ #2 :w } + { \tl_show:c { l_@@_defaults_ #1 _ #2 _tl } } + { \msg_error:nnn { prototype } { unknown-template } {#1} {#2} } + } +\cs_new_protected:Npn \prototype_show_instance_values:nn #1#2 + { + \tl_if_exist:cTF { l_@@_instance_ #1 _ #2 _template_tl } + { \tl_show:c { l_@@_instance_ #1 _ #2 _pars_tl } } + { \msg_error:nnn { prototype } { unknown-instance } {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { prototype } { bad-number-of-arguments } + { Bad~number~of~arguments~for~object~type~'#1'. } + { + An~object~may~accept~between~0~and~9~arguments.\\ + You~asked~to~use~#2~arguments:~this~is~not~supported. + } +\msg_new:nnnn { prototype } { unknown-instance } + { The~instance~'#2'~of~type~'#1'~is~unknown. } + { + You~have~asked~to~use~an~instance~'#2',~ + but~this~has~not~been~created. + } +\msg_new:nnnn { prototype } { unknown-object-type } + { The~object~type~'#1'~is~unknown. } + { An~object~type~needs~to~be~declared~prior~to~using~it. } +\msg_new:nnnn { prototype } { unknown-template } + { The~template~'#2'~of~type~'#1'~is~unknown. } + { + No~interface~has~been~declared~for~a~template~ + '#2'~of~object~type~'#1'. + } +% \end{macrocode} +% +% \begin{macrocode} +\msg_new:nnn { prototype } { declare-object-type } + { Declaring~object~type~'#1'~taking~#2~argument(s). } +% \end{macrocode} +% +% \begin{macrocode} +\ExplSyntaxOff +% \end{macrocode} +% +% \begin{macrocode} +%</2ekernel> +% \end{macrocode} +% +% \end{implementation} diff --git a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-testphase.dtx b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-testphase.dtx index 670bbaf481d..d8d9c671c39 100644 --- a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-testphase.dtx +++ b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-testphase.dtx @@ -41,17 +41,26 @@ % \section{Introduction} % % This code implements small files which can be loaded with the |testphase| -% key of \cs{DocumentMetadata}. Currently it only contains a -% wrapper for \pkg{tagpdf}, but this will be extended to allow user to load +% key of \cs{DocumentMetadata}. This will be extended to allow user to load % well defined parts of the tagged PDF project. -% +% Currently the values |phase-I|, |phase-II| and |new-or| are provided. +% |tagpdf| is an undocumented alias for |phase-II| which is kept for compability. % % % \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } % % % \section{The Implementation} -% +% New output routine code is loaded in phase-II and new-or: +% \begin{macrocode} +%<*tagpdf|phase-II|new-or> +\IfFileExists{latex-lab-testphase-new-or.sty} + { + \RequirePackage{latex-lab-testphase-new-or} + } + {} +%</tagpdf|phase-II|new-or> +% \end{macrocode} % \begin{macrocode} %<*tagpdf|phase-I|phase-II> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex-dev/latex-lab/documentmetadata-support.ins b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab.ins index 431f88d8109..eb0b066af0e 100644 --- a/Master/texmf-dist/source/latex-dev/latex-lab/documentmetadata-support.ins +++ b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab.ins @@ -35,7 +35,7 @@ This is a generated file. -Copyright 2021 LaTeX Project +Copyright 2021,2022 LaTeX Project This file was generated from file(s) of the `LaTeX-lab Bundle'. ------------------------------------------------------------------------------------ @@ -64,8 +64,24 @@ where one can also log issues in case there are any. \generate{\file{documentmetadata-support.ltx}{\from{documentmetadata-support.dtx}{code}}} -\generate{\file{tagpdf-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{tagpdf}}} +% files that should be loadable with the testphase key should use the naming scheme +% #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{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}}} + +% 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-footmisc.ltx}{\from{latex-lab-footnotes.dtx}{footmisc}}} +\generate{\file{latex-lab-footnotes.ltx}{\from{latex-lab-footnotes.dtx}{kernel}}} + +% for \DocumentMetadata trials +\generate{\file{prototype-latex-lab-testphase.ltx}{\from{latex-lab-prototype.dtx}{2ekernel}}} + +% for standalone trials +\generate{\file{latex-lab-prototype.sty}{\from{latex-lab-prototype.dtx}{2ekernel}}} + \endbatchfile |