% \iffalse meta-comment %% %% Copyright (C) 2020-2024 %% Frank Mittelbach, The LaTeX Project %% % % This file is part of the LaTeX base system. % ------------------------------------------- % % It may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % https://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2008 or later. % % This file has the LPPL maintenance status "maintained". % % The list of all files belonging to the LaTeX base distribution is % given in the file `manifest.txt'. See also `legal.txt' for additional % information. % % The list of derived (unpacked) files belonging to the distribution % and covered by LPPL is defined by the unpacking scripts (with % extension .ins) which are part of the distribution. % % \fi % % \iffalse % %%% From File: ltshipout.dtx % %<*driver> % \fi \ProvidesFile{ltshipout.dtx} [2024/02/11 v1.0n LaTeX Kernel (Shipout)] % \iffalse % \documentclass{l3doc} \GetFileInfo{ltshipout.dtx} \providecommand\InternalDetectionOff{} \providecommand\InternalDetectionOn{} \EnableCrossrefs \CodelineIndex \begin{document} \DocInput{ltshipout.dtx} \end{document} % % % \fi % % % \long\def\fmi#1{\begin{quote}\itshape Todo: #1\end{quote}} % % \providecommand\hook[1]{\texttt{#1}} % \providecommand\pkg[1]{\texttt{#1}} % % % \title{The \texttt{ltshipout} documentation\thanks{This file has version % \fileversion\ dated \filedate, \copyright\ \LaTeX\ % Project.}} % % \author{Frank Mittelbach, \LaTeX{} Project Team} % % \maketitle % % % \tableofcontents % % \section{Introduction} % % The code provides an interface to the \cs{shipout} primitive of % \TeX{} which is called when a finished pages is finally % \enquote{shipped out} to the target output file, e.g., the % \texttt{.dvi} or \texttt{.pdf} file. % A good portion of the code is based on ideas by Heiko Oberdiek % implemented in his packages \pkg{atbegshi} and \pkg{atenddvi} % even though the interfaces are somewhat % different.\footnote{Heiko's interfaces are emulated by the kernel % code, if a document requests his packages, so older documents % will continue to work.} % % \subsection{Overloading the \cs{shipout} primitive} % % % \begin{function}{\shipout} % With this implementation \TeX's shipout primitive is no longer % available for direct use. Instead \cs{shipout} is running some % (complicated) code that picks up the box to be shipped out % regardless of how that is done, i.e., as a constructed \cs{vbox} % or \cs{hbox} or as a box register. % % It then stores it in a named box register. This box can then be % manipulated through a set of hooks after which it is shipped out % for real. % % Each shipout that actually happens (i.e., where the material is % not discarded for one or the other reason) is recorded and the % total number is available in a readonly variable and in a % \LaTeX{} counter. % \end{function} % % % \begin{function}{\RawShipout} % This command implements a simplified shipout that bypasses the % foreground and background % hooks, e.g., only \hook{shipout/firstpage} and % \hook{shipout/lastpage} are executed and the total shipout % counters are incremented. % % The command doesn't use \cs{ShipoutBox} but its own private box % register so that it can be used inside of shipout hooks to do % some additional shipouts while already in the output routine with % the current page being stored in \cs{ShipoutBox}. It does have % access to \cs{ShipoutBox} if it is used in \hook{shipout/before} % (or \hook{shipout/after}) and can use its content. % % It is safe to use it in \hook{shipout/before} or % \hook{shipout/after} but not necessarily in the other % \hook{shipout/...} hooks as they are intended for special % processing. % \end{function} % % \begin{variable}{\ShipoutBox,\l_shipout_box} % This box register is called \cs{ShipoutBox} (alternatively % available via the L3 name \cs{l_shipout_box}). % % This box is a ``local'' box and assignments to it should be done % only locally. Global assignments (as done by some packages with % older code where this is box is known as 255) may work but they are % conceptually wrong and may result in errors under certain % circumstances. % % During the execution of \hook{shipout/before} this box contains % the accumulated material for the page, but not yet any material % added by other shipout hooks. % During execution of \hook{shipout/after}, i.e., after the shipout % has happened, the box also contains any background or foreground % material. % % Material from the hooks \hook{shipout/firstpage} or % \hook{shipout/lastpage} is not included (but only used during the % actual shipout) to facilitate reuse of the box data (e.g., % \hook{shipout/firstpage} material should never be added to a % later page of the output). % \end{variable} % % % \begin{variable}{\l_shipout_box_ht_dim, % \l_shipout_box_dp_dim,\l_shipout_box_wd_dim, % \l_shipout_box_ht_plus_dp_dim} % The shipout box dimensions are available in the L3 registers % \cs{l_shipout_box_ht_dim}, etc.\ (there are no \LaTeXe{} % names).\footnotemark{} These variables can be used % inside the hook code for \hook{shipout/before}, % \hook{shipout/foreground} and \hook{shipout/background} if needed. % \end{variable} % \footnotetext{Might need changing, but HO's version as strings % is not really helpful I think).} % % % % % \subsection{Provided hooks} % % \begin{variable}{shipout/before,shipout/after, % shipout/foreground,shipout/background, % shipout/firstpage, % shipout/lastpage} % The code for \cs{shipout} offers a number of hooks into which packages (or the % user) can add code to support different use cases. % These are: % \begin{description} % \item[\hook{shipout/before}] % % This hook is executed after the finished page has been stored in % \cs{ShipoutBox} / \cs{l_shipout_box}). % It can be used to alter that box content or to discard it % completely (see \cs{DiscardShipoutBox} below). % % You can use \cs{RawShipout} inside this hook for special use % cases. It can make use of \cs{ShipoutBox} (which doesn't yet % include the background and foreground material). % % \textbf{Note:} It is not possible (or say advisable) to try % and use this hook to typeset material with the intention to % return it to main vertical list, it will go wrong and give % unexpected results in many cases---for starters it will appear % after the current page not before or it will vanish or the % vertical spacing will be wrong! % \end{description} % \end{variable} % % \begin{description} % \item[\hook{shipout/background}] % % This hook adds a picture environment into the background of % the page with the \texttt{(0,0)} coordinate in the top-left % corner using a \cs{unitlength} of \texttt{1pt}. % % It should therefore only receive \cs{put} commands or other % commands suitable in a \texttt{picture} environment and the % vertical coordinate values would normally be % negative. % % Technically this is implemented by adding a zero-sized % \cs{hbox} as the very first item into the \cs{ShipoutBox} % containing that \texttt{picture} environment. Thus the rest of % the box content will overprint what ever is typeset by that hook. % % % \item[\hook{shipout/foreground}] % % This hook adds a picture environment into the foreground of % the page with the \texttt{(0,0)} coordinate in the top-left % corner using a \cs{unitlength} of \texttt{1pt}. % % Technically this is implemented by adding a zero-sized % \cs{hbox} as the very last item into the \cs{ShipoutBox} and % raising it up so that it still has its \texttt{(0,0)} point in % the top-left corner. % But being placed after the main box content it will be typeset % later and thus overprints it (i.e., is in the foreground). % % \item[\hook{shipout}] % This hook is executed after foreground and/or background % material has been added, i.e., just in front of the actual % shipout operation. Its purpose is to allow manipulation of the % finalized box (stored in \cs{ShipoutBox}) with the extra % material also in place (which is not yet the case in % \hook{shipout/before}). % % It cannot be used to cancel the shipout operation via % \cs{DiscardShipoutBox} (that has % to happen in \hook{shipout/before}, if desired! % % % \item[\hook{shipout/firstpage}] % % The material from this hook is executed only once at the very % beginning of the first output page that is shipped out (i.e., % not discarded at the last minute). It should only contain % \cs{special} or similar commands needed to direct post processors % handling the \texttt{.dvi} or \texttt{.pdf} output.\footnotemark % \footnotetext{In % \LaTeXe{} that was already existing, but implemented using a box % register with the name \cs{@begindvibox}.} % % ^^A \fmi{not sure it has to be that restrictive.} % % This hook is added to the very first page regardless of how it % is shipped out (i.e., with \cs{shipout} or \cs{RawShipout}). % % \item[\hook{shipout/lastpage}] % % The corresponding hook to add \cs{special}s at the very end of % the output file. It is only executed on the very last page of % the output file --- % or rather on the page that \LaTeX{} believes is the last one. % Again it is executed regardless of the shipout method. % % It may not be possible for \LaTeX{} to correctly determine % which page is the last one without several reruns. If this % happens and the hook is non-empty then \LaTeX{} will add an % extra page to place the material and also request a rerun to % get the correct placement sorted out. % % \item[\hook{shipout/after}] % % This hook is executed after a shipout has happened. If the % shipout box is discarded this hook is not looked at. % % You can use \cs{RawShipout} inside this hook for special use % cases and the main \cs{ShipoutBox} is still available at this % point (but in contrast to \hook{shipout/before} it now % includes the background and foreground material). % % \textbf{Note:} Just like \hook{shipout/before} this hook is % not meant to be used for adding typeset material back % to the main vertical list---it might vanish or the % vertical spacing will be wrong! % % % \end{description} % % As mentioned above the hook \hook{shipout/before} is executed % first and can manipulate the prepared shipout box stored in % \cs{ShipoutBox} or set things up for use in \cs{write} during the % actual shipout. It is even run if there was a % \cs{DiscardShipoutBox} request in the document. % % The other hooks (except \hook{shipout} and \hook{shipout/after}) are added inside % hboxes to the box being shipped out in the following order: % \begin{center} % \begin{tabular}{ll} % \hook{shipout/firstpage} & only on the first page \\ % \hook{shipout/background} & \\ % \meta{boxed content of \cs{ShipoutBox}} & \\ % \hook{shipout/foreground} & \\ % \hook{shipout/lastpage} & only on the last page \\ % \end{tabular} % \end{center} % If any of the hooks has no code then the corresponding box is % added at that point. % % Once the (page) box has got the above extra content it can % again be manipulated using the \hook{shipout} hook and then % is shipped out for real. % % Once the (page) box has been shipped out the \hook{shipout/after} % hook is called (while you are still inside the output routine). It % is not called if the shipout box was discarded. % % In a document that doesn't produce pages, e.g., only makes % \cs{typeout}s, none of the hooks are ever executed (as there is no % \cs{shipout}) not even the \hook{shipout/lastpage} hook. % % If \cs{RawShipout} is used instead of \cs{shipout} then only the % hooks \hook{shipout/firstpage} and \hook{shipout/lastpage} are % executed (on the first or last page), all others are bypassed. % % % % \subsection{Legacy \LaTeX{} commands} % % \begin{function}{\AtBeginDvi,\AtEndDvi} % \begin{syntax} % \cs{AtBeginDvi} \Arg{code} % \end{syntax} % \cs{AtBeginDvi} is the existing \LaTeXe{} interface to fill the % \hook{shipout/firstpage} hook. This is not really a good name % as it is not just supporting \texttt{.dvi} but also \texttt{.pdf} % output or \texttt{.xdv}. % % \cs{AtEndDvi} is the counterpart that was not available in the % kernel but only through the package \pkg{atenddvi}. It fills the % \hook{shipout/lastpage} hook. % % Neither interface can set a code label but uses the current default label. % % \end{function} % % As these two wrappers have been available for a long time we % continue offering them (but not enhancing them, e.g., by providing % support for code labels). % % For new code we strongly suggest using the high-level hook % management commands directly instead of ``randomly-named'' % wrappers. This will lead to code that is easier to understand % and to maintain and it also allows you to set code labels if % needed. % % For this reason we do not provide any other ``new'' wrapper % commands for the above hooks in the kernel, but only keep % the existing ones for backward compatibility. % % % \subsection{Special commands for use inside the hooks} % % \begin{function}{\DiscardShipoutBox,\shipout_discard:} % \begin{syntax} % \cs{AddToHookNext} \texttt{\{shipout/before\} \{...\cs{DiscardShipoutBox}...\}} % \end{syntax} % The \cs{DiscardShipoutBox} declaration (L3 name % \cs{shipout_discard:}) % requests that on the next % shipout the page box is thrown away instead of being shipped to % the \texttt{.dvi} or \texttt{.pdf} file. % % Typical applications wouldn't do this unconditionally, but have % some processing logic that decides to use or not to use the page. % % Note that if this declaration is used directly in the document it % may depend on the placement to which page it applies, given that % \LaTeX{} output routine is called in an asynchronous manner! % Thus normally one would use this only as part of the % \hook{shipout/before} code. % % \fmi{Once we have a new mark mechanism available we can improve % on that and make sure that the declaration applies to the page % that contains it --- not done (yet)} % % \cs{DiscardShipoutBox} cannot be used in any of the \hook{shipout/...} % hooks other than \hook{shipout/before}. % \end{function} % % In the \pkg{atbegshi} package there are a number of additional % commands for use inside the \hook{shipout/before} hook. They % should normally not be needed any more as one can instead simply % add code to the hooks \hook{shipout/before}, \hook{shipout}, % \hook{shipout/background} or % \hook{shipout/foreground}.\footnote{If that assumption turns out to % be wrong it would be trivial to change them to public functions % (right now they are private).} If \pkg{atbegshi} gets loaded then % those commands become available as public functions with their original % names as given below. % % % % \subsection{Provided Lua\TeX\ callbacks} % % \begin{variable}{pre_shipout_filter} % Under Lua\TeX{} the \texttt{pre\_shipout\_filter} Lua callback is % provided which gets called directly after the % \hook{shipout} hook, immediately before the shipout % primitive gets invoked. % The signature is % \begin{verbatim} % function( head) % return true % end % \end{verbatim} % The \texttt{head} is the list node corresponding to the box to be shipped out. % The return value should always be \texttt{true}. % \end{variable} % % \subsection{Information counters} % % % \begin{variable}{\ReadonlyShipoutCounter,\g_shipout_readonly_int} % \begin{syntax} % \cs{ifnum}\cs{ReadonlyShipoutCounter}\texttt{=...} % \cs{int_use:N} \cs{g_shipout_readonly_int} \texttt{\% expl3 usage} % \end{syntax} % This integer holds the number of pages shipped out up to now % (including the one to be shipped out when inside the output % routine). More precisely, it is incremented only after it is % clear that a page will be shipped out, i.e., after the % \hook{shipout/before} hook (because that might discard the page)! % In contrast \hook{shipout/after} sees the incremented value. % % Just like with the \texttt{page} counter its value is % only accurate within the output routine. In the body of the % document it may be off by one as the output routine is called % asynchronously! % % Also important: it \emph{must not} be set, only read. There are % no provisions to prevent that restriction, but if you manipulate % it, chaos will be the result. To emphasize this fact it is not % provided as a \LaTeX{} counter but as a \TeX{} counter (i.e., a % command), so \cs{Alph}\verb={=\cs{ReadonlyShipoutCounter}\verb=}= % etc, would not work. % \end{variable} % % \begin{variable}{totalpages,\g_shipout_totalpages_int} % \begin{syntax} % \cs{arabic}\texttt{\{totalpages\}} % \cs{int_use:N} \cs{g_shipout_totalpage_int} \texttt{\% expl3 usage} % \end{syntax} % In contrast to \cs{ReadonlyShipoutCounter}, the % \texttt{totalpages} counter is a \LaTeX{} counter and incremented % for each shipout attempt including those pages that are discarded % for one or the other reason. Again \hook{shipout/before} sees % the counter before it is incremented. In contrast % \hook{shipout/after} sees the incremented value. % % Furthermore, while it is incremented for each page, its value is % never used by \LaTeX. It can therefore be freely reset or changed by user % code, for example, to additionally count a number of pages that % are not build by \LaTeX\ but are added in a later part of the % process, e.g., cover pages or picture pages made externally. % % Important: as this is a page-related counter its value is only % reliable inside the output routine! % \end{variable} % % \begin{variable}{\PreviousTotalPages} % \begin{syntax} % \cs{thetotalpages}/\cs{PreviousTotalPages} % \end{syntax} % Command that expands to the number of total pages from the % previous run. If there was no previous run or if used in the % preamble it expands to % \texttt{0}. Note that this is a command and not a counter, so in order % to display the number in, say, Roman numerals you have to assign % its value to a counter and then use \cs{Roman} on that counter. % \end{variable} % % % \subsection{Debugging shipout code} % % \begin{function}{\DebugShipoutsOn,\DebugShipoutsOff, % \shipout_debug_on:,\shipout_debug_off:} % \begin{syntax} % \cs{DebugShipoutsOn} % \end{syntax} % Turn the debugging of shipout code on or off. This displays % changes made to the shipout data structures. \fmi{This needs % some rationalizing and may not stay this way.} % \end{function} % % % % % \section{Emulating commands from other packages} % % The packages in this section are no longer necessary, but as they % are used by other packages, they are emulated when they are % explicitly loaded with \cs{usepackage} or \cs{RequirePackage}. % % Please note that the emulation only happens if the package is % explicitly requested, i.e., the commands documented below are not % automatically available in the \LaTeX{} kernel! If you write a % new package we suggest to use the appropriate kernel hooks % directly instead of loading the emulation. % % % \subsection{Emulating \pkg{atbegshi}} % % % \begin{function}{\AtBeginShipoutUpperLeft,\AtBeginShipoutUpperLeftForeground} % \begin{syntax} % \cs{AddToHook} \texttt{\{shipout/before\} \{...\cs{AtBeginShipoutUpperLeft}}\Arg{code}\texttt{...\}} % \end{syntax} % This adds a \texttt{picture} environment into the background of the shipout % box expecting \meta{code} to contain \texttt{picture} % commands. The same effect can be obtained by simply using kernel % features as follows: % \begin{quote} % \cs{AddToHook}\texttt{\{shipout/background\}}\Arg{code} % \end{quote} % There is one technical difference: if % \cs{AtBeginShipoutUpperLeft} is used several times each % invocation is put into its own box inside the shipout box whereas % all \meta{code} going into \hook{shipout/background} ends up % all in the same box in the order it is added or sorted based on % the rules for the hook chunks. % % \cs{AtBeginShipoutUpperLeftForeground} is similar with the % difference that the \texttt{picture} environment is placed in the % foreground. To model it with the kernel functions use the hook % \hook{shipout/foreground} instead. % \end{function} % % % \begin{function}{\AtBeginShipoutAddToBox,\AtBeginShipoutAddToBoxForeground} % \begin{syntax} % \cs{AddToHook} \texttt{\{shipout/before\} \{...\cs{AtBeginShipoutAddToBox}}\Arg{code}\texttt{...\}} % \end{syntax} % These work like \cs{AtBeginShipoutUpperLeft} and % \cs{AtBeginShipoutUpperLeftForeground} with the difference that % \meta{code} is directly placed into an \cs{hbox} inside the % shipout box and not surrounded by a \texttt{picture} environment. % % To emulate them using \hook{shipout/background} or % \hook{shipout/foreground} you may have to wrap \meta{code} into % a \cs{put} statement but if the code is not doing any typesetting % just adding it to the hook should be sufficient. % \end{function} % % % % \begin{function}{\AtBeginShipoutBox} % This is the name of the shipout box as \pkg{atbegshi} knows it. % \end{function} % % % \begin{function}{\AtBeginShipoutOriginalShipout} % This is the name of the \cs{shipout} primitive as \pkg{atbegshi} % knows it. This bypasses all the mechanisms set up by the \LaTeX{} % kernel and there are various scenarios in which it can therefore % fail. It should only be used to run existing legacy % \pkg{atbegshi} code but not in newly developed applications. % % The kernel alternative is \cs{RawShipout} which is integrated % with the \LaTeX{} mechanisms and updates, for example, the % \cs{ReadonlyShipoutCounter} counter. Please use \cs{RawShipout} % for new code if you want to bypass the before, foreground and % background hooks. % \end{function} % % \begin{function}{\AtBeginShipoutInit} % By default \pkg{atbegshi} delayed its action until % \verb=\begin{document}=. This command was forcing it in an earlier % place. With the new concept it does nothing. % \end{function} % % \begin{function}{\AtBeginShipout,\AtBeginShipoutNext} % \begin{syntax} % \cs{AtBeginShipout}\Arg{code} $\equiv$ \cs{AddToHook}\texttt{\{shipout/before\}}\Arg{code} % \cs{AtBeginShipoutNext}\Arg{code} $\equiv$ \cs{AddToHookNext}\texttt{\{shipout/before\}}\Arg{code} % \end{syntax} % This is equivalent to filling the \hook{shipout/before} hook % by either using \cs{AddToHook} or \cs{AddToHookNext}, respectively. % \end{function} % % \begin{function}{\AtBeginShipoutFirst,\AtBeginShipoutDiscard} % The \pkg{atbegshi} names for \cs{AtBeginDvi} and \cs{DiscardShipoutBox}. % \end{function} % % % % % \subsection{Emulating \pkg{everyshi}} % % The \pkg{everyshi} package is providing commands to run arbitrary % code just before the shipout starts. % One point of difference: in the new shipout hooks the page is % available as \cs{ShipoutBox} for inspection of change, one should % not manipulate box 255 directly inside \hook{shipout/before}, so % old code doing this would change to use \cs{ShipoutBox} instead % of \texttt{255} or \cs{@cclv}. % % \begin{function}{\EveryShipout} % \begin{syntax} % \cs{EveryShipout}\Arg{code} $\equiv$ \cs{AddToHook}\texttt{\{shipout/before\}}\Arg{code} % \end{syntax} % \end{function} % % \begin{function}{\AtNextShipout} % \begin{syntax} % \cs{AtNextShipout}\Arg{code} $\equiv$ \cs{AddToHookNext}\texttt{\{shipout/before\}}\Arg{code} % \end{syntax} % \end{function} % % However, most use cases for \pkg{everyshi} are attempts to put % some picture or text into the background or foreground of the page % and that can be done today simply by using the % \hook{shipout/background} and % \hook{shipout/foreground} hooks without any need to coding. % % % \subsection{Emulating \pkg{atenddvi}} % % The \pkg{atenddvi} package implemented only a single command: % \cs{AtEndDvi} and that is now available out of the box so the % emulation makes the package a no-op. % % % % \subsection{Emulating \pkg{everypage}} % % This package patched the original \cs{@begindvi} hook and replaced % it with its own version. % Its functionality is now covered by the hooks offered by the % kernel so that there is no need for such patching any longer. % % \begin{function}{\AddEverypageHook} % \begin{syntax} % \cs{AddEverypageHook}\Arg{code} $\equiv$ % \qquad\cs{AddToHook}\texttt{\{shipout/background\}\{\cs{put}(1in,-1in)\Arg{code}\}} % \end{syntax} % \cs{AddEverypageHook} is adding something into the % background of every page at a position of 1in to the right and % 1in down from the top left corner of the page. % By using the kernel hook directly you can put your material % directly to the right place, i.e., use other coordinates in the % \cs{put} statement above. % \end{function} % % \begin{function}{\AddThispageHook} % \begin{syntax} % \cs{AddThispageHook}\Arg{code} $\equiv$ % \qquad\cs{AddToHookNext}\texttt{\{shipout/background\}\{\cs{put}(1in,-1in)\Arg{code}\}} % \end{syntax} % The \cs{AddThispageHook} wrapper is similar but uses % \cs{AddToHookNext}. % \end{function} % % % \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } % % % \section{The Implementation} % \begin{macrocode} %<@@=shipout> % \end{macrocode} % % At the moment the whole module rolls back in one go, but if we % make any modifications in later releases this will then need % splitting. % \begin{macrocode} %<*2ekernel|latexrelease> %\IncludeInRelease{2020/10/01}% % {\shipout}{Hook management (shipout)}% % \end{macrocode} % % % \begin{macrocode} \ExplSyntaxOn % \end{macrocode} % % % \subsection{Debugging} % % \begin{macro}{\g_@@_debug_bool} % Holds the current debugging state. % \begin{macrocode} \bool_new:N \g_@@_debug_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\shipout_debug_on:,\shipout_debug_off:} % \begin{macro}{\@@_debug:n} % \begin{macro}{\@@_debug_gset:} % Turns debugging on and off by redefining \cs{@@_debug:n}. % \begin{macrocode} \cs_new_eq:NN \@@_debug:n \use_none:n \cs_new_protected:Npn \shipout_debug_on: { \bool_gset_true:N \g_@@_debug_bool \@@_debug_gset: } \cs_new_protected:Npn \shipout_debug_off: { \bool_gset_false:N \g_@@_debug_bool \@@_debug_gset: } \cs_new_protected:Npn \@@_debug_gset: { \cs_gset_protected:Npx \@@_debug:n ##1 { \bool_if:NT \g_@@_debug_bool {##1} } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % % % % \begin{macro}{\ShipoutBox,\l_shipout_box} % The box filled with the page to be shipped out (both L3 and % \LaTeXe{} name). % \begin{macrocode} \box_new:N \l_shipout_box % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN \ShipoutBox \l_shipout_box % \end{macrocode} % \end{macro} % % % \begin{macro}{\l_@@_raw_box} % The \cs{RawShipout} gets its own box but it is internal as there % is no hook manipulation for it. % \begin{macrocode} \box_new:N \l_@@_raw_box % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_finalize_box:} % For Lua\TeX{} invoke the \texttt{pre\_shipout\_filter} callback. % \changes{v1.0i}{2021/01/22}{Add \texttt{pre\_shipout\_filter} Lua callback} % \begin{macrocode} \sys_if_engine_luatex:TF { \newprotectedluacmd \@@_finalize_box: \exp_args:Nx \everyjob { \exp_not:V \everyjob \exp_not:N \lua_now:n { luatexbase.create_callback('pre_shipout_filter', 'list') local~call, getbox, setbox = luatexbase.call_callback, tex.getbox, tex.setbox~ lua.get_functions_table()[\the \allocationnumber] = function() local~head = getbox(\the \l_shipout_box) local~result = call('pre_shipout_filter', head) if~not (result == head) then~ setbox(\the \l_shipout_box, result~or~nil) end~ end } } } { \cs_set_eq:NN \@@_finalize_box: \scan_stop: } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_execute:} % This is going to the be the code run by \cs{shipout}. The code % follows closely the ideas from \pkg{atbegshi}, so not % documenting that here for now. % \begin{macrocode} \cs_set_protected:Npn \@@_execute: { \tl_set:Nx \l_@@_group_level_tl { \int_value:w \tex_currentgrouplevel:D } \tex_afterassignment:D \@@_execute_test_level: \tex_setbox:D \l_shipout_box } % \end{macrocode} % \end{macro} % % % \begin{macro}{\shipout} % Overloading the \cs{shipout} primitive: % \begin{macrocode} \cs_gset_eq:NN \shipout \@@_execute: % \end{macrocode} % \end{macro} % % % \begin{macro}{\l_@@_group_level_tl} % Helper token list to record the group level at which % \cs{@@_execute:} is encountered. % \begin{macrocode} \tl_new:N \l_@@_group_level_tl % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_execute_test_level:} % If the group level has changed then we are still constructing % \cs{l_shipout_box} and to continue we need to wait until the % current group has finished, hence the \cs{tex_aftergroup:D}. % \begin{macrocode} \cs_new:Npn \@@_execute_test_level: { \int_compare:nNnT \l_@@_group_level_tl < \tex_currentgrouplevel:D \tex_aftergroup:D \@@_execute_cont: } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_execute_cont:} % This does the actual shipout running several hooks as part of it. % The code for them is passed as argument \verb=#2= to \verb=#4= % to \cs{@@_execute_main_cont:Nnnn}; the first argument is the box % to be shipped out. % \begin{macrocode} \cs_new:Npn \@@_execute_cont: { \@@_execute_main_cont:Nnnn \l_shipout_box { \hook_use:n {shipout/before} } { \hook_if_empty:nF {shipout/foreground} { \@@_add_foreground_picture:n { \hook_use:n {shipout/foreground} } } % \end{macrocode} % If the user hook for the background (\hook{shipout/background}) has % no code, there might still code in the kernel hook so we need to % test for this too. % We only test for the \cs{@kernel@before@shipout@background} % though. If the \cs{@kernel@after@shipout@background} needs % executing even if the user hook is empty then we can add another % test (or the kernel could put something into the before hook). % % \changes{v1.0d}{2020/11/23}{Check for both kernel and user hook (gh/431)} % \changes{v1.0f}{2021/01/08}{Added another kernel hook for more % flexibility (cf.\ \texttt{https://github.com/pgf-tikz/pgf/issues/960}} % \begin{macrocode} \bool_lazy_and:nnF { \hook_if_empty_p:n {shipout/background} } { \tl_if_empty_p:N \@kernel@before@shipout@background } { \@@_add_background_picture:n { \@kernel@before@shipout@background \hook_use:n {shipout/background} \@kernel@after@shipout@background } } } { \hook_use:n {shipout/after} } } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_execute_main_cont:Nnnn} % When we have reached this point the shipout box has been % processed and is available in \cs{l_shipout_box} and ready for % real ship out (unless it gets discarded during the process). % % The three arguments hold hook code that is executed just before the % actual shipout (\verb=#1=), within the shipout adding % background and foreground material (\verb=#2=) and after the % shipout has happened (\verb=#3=). % These are passed as arguments because the same code without those % hooks is also used when doing a ``raw'' shipout implemented by % \cs{RawShipout}. % The only hook that is always executed is that for the very last % page, i.e., \hook{shipout/lastpage}. % % First we quickly check if it is void (can't happen in the % standard \LaTeX{} output routine but \cs{shipout} might be called % from a package that has some special processing logic). If it is % void we aren't shipping anything out and processing ends.\footnote{In that % case we don't reset the deadcycles, that would be up to the OR % processing logic to do.} % \begin{macrocode} \cs_new:Npn \@@_execute_main_cont:Nnnn #1#2#3#4 { \box_if_empty:NTF #1 { \@latex@warning@no@line{ Ignoring~ void~ shipout~ box } } { % \end{macrocode} % Otherwise we assume that we will ship something and prepare for % final adjustments (in particular setting the state of % \cs{protect} while we are running the hook code). % We also save the current \cs{protect} state to restore it later. % \begin{macrocode} % \bool_gset_false:N \g_@@_discard_bool % setting this would disable % \DiscardShipoutBox on doc-level \cs_set_eq:NN \@@_saved_protect: \protect \set@typeset@protect % \end{macrocode} % We also store the current shipout box dimension in registers, so that % they can be used in the hook code.\footnote{This is not really % necessary as the code could access them via \cs{box_ht:N}, etc., % but it is perhaps convenient.} % \begin{macrocode} \@@_get_box_size:N #1 % \end{macrocode} % Then we execute the \hook{shipout/before} hook (or nothing in % case of \cs{RawShipout}). % \begin{macrocode} #2 % \end{macrocode} % In \cs{g_shipout_totalpages_int} we count all shipout attempts so % we increment that counter already here (the other one is % incremented later when we know for sure that we do a % \cs{shipout}. % % We increment it after running the above hook so that the values % for \cs{g_shipout_totalpages_int} and \cs{g_shipout_readonly_int} % are in sync while the % hook is executed (in the case that totalpages isn't manually % altered or through discarding pages that is). % \begin{macrocode} \int_gincr:N \g_shipout_totalpages_int % \end{macrocode} % The above hook might contain code that requests the page to be discarded so % we now test for it. % \begin{macrocode} \bool_if:NTF \g_@@_discard_bool { \@latex@info@no@line{Completed~ page~ discarded} \bool_gset_false:N \g_@@_discard_bool % \end{macrocode} % As we are discarding the page box and not shipping anything out, % we need to do some house cleaning and reset \TeX's deadcycles so % that it doesn't complain about too many calls to the OR without % any shipout. % \begin{macrocode} \tex_deadcycles:D \c_zero_int % \end{macrocode} % \fmi{In \pkg{atbegshi} the box was dropped but is that actually % needed? Or the resetting of \cs{protect} to its kernel value?} % \begin{macrocode} % \group_begin: % \box_set_eq_drop:NN #1 #1 % \group_end: % \cs_set_eq:NN \protect \exp_not:N } % \end{macrocode} % Even if there was no explicit request to discard the box it is % possible that the code for the hook \hook{shipout/before} has % voided the box (by mistake or deliberately). We therefore test % once more but this time make it a warning, because the best % practice way is to use the request mechanism. % \begin{macrocode} { \box_if_empty:NTF #1 { \@latex@warning@no@line { Ignoring~ void~ shipout~ box. \MessageBreak The~ shipout~ box~ was~ voided~ by~ hook~ code } } % \end{macrocode} % Finally, if the box is still non-empty we are nearly ready to % ship it out. % First we increment the total page counter so that we can later % test if we have reached the final page according to our available % information.\footnote{Doing that earlier would be wrong because we % might end up with the last page counted but discard and then we % have no place to add the final objects into the output file.} % \begin{macrocode} { \int_gincr:N \g_shipout_readonly_int \@@_debug:n { \typeout{Absolute~ page~ =~ \int_use:N \g_shipout_readonly_int \space (target:~ \@abspage@last)} } % \end{macrocode} % Then we store the box sizes again (as they may have % changed) and then look at the hooks \hook{shipout/foreground} % and \hook{shipout/background}. If either or both are non-empty % we add a \texttt{picture} environment to the box (in the % foreground and/or in the background) and execute the hook code % inside that environment. % % \begin{macrocode} \@@_get_box_size:N #1 % \end{macrocode} % The first hook we run is the \hook{shipout/firstpage} hook. This % is only done once, then the \cs{@@_run_firstpage_hook:} % command redefines itself to do nothing. If the hook contains % \cs{special}s for integration at the top of the page they will be % temporarily stored in a safe place and added later with % \cs{@@_add_firstpage_specials:}. % \begin{macrocode} \@@_run_firstpage_hook: % \end{macrocode} % Run the hooks for background and foreground or, if this % is called by \cs{RawShipout}, copy the box \cs{l_@@_raw_box} to % \cs{l_shipout_box} so that firstpage and lastpage material gets % added if necessary (that is always done to \cs{l_shipout_box}. % \begin{macrocode} #3 % \end{macrocode} % We then run \cs{@@_add_firstpage_specials:} that adds % the content of the hook \hook{shipout/firstpage} to the % start of the first page (if non-empty). It is then redefined to % do nothing on later pages. % \begin{macrocode} \@@_add_firstpage_specials: % \end{macrocode} % Then we check if we have to add the \hook{shipout/lastpage} hook % or the corresponding kernel hook % because we have reached the last page. This test will be false for % all but one (and hopefully the correct) page. % \changes{v1.0d}{2020/11/23}{Check for both kernel and user hook (gh/431)} % \begin{macrocode} \int_compare:nNnT \@abspage@last = \g_shipout_readonly_int { \bool_lazy_and:nnF { \hook_if_empty_p:n {shipout/lastpage} } { \tl_if_empty_p:N \@kernel@after@shipout@lastpage } { \@@_debug:n { \typeout{Executing~ lastpage~ hook~ on~ page~ \int_use:N \g_shipout_readonly_int } } \_@@_add_foreground_box:n { \UseHook{shipout/lastpage} \@kernel@after@shipout@lastpage } % \end{macrocode} % We record that we have handled the \hook{shipout/lastpage} hook % but only if we really did. % \changes{v1.0m}{2022/05/08}{Handle case where shipout/lastpage is % run too early (gh/813)} % \begin{macrocode} \bool_gset_true:N \g_@@_lastpage_handled_bool } } % \end{macrocode} % % \changes{v1.0n}{2022/11/08}{Add shipout hook (gh/920)} % \begin{macrocode} \hook_use:n {shipout} \@@_finalize_box: % \end{macrocode} % Finally we run the actual \TeX{} primitive for shipout. As that will % expand delayed \cs{write} statements inside the page in which % protected commands should not expand we first change \cs{protect} % to the appropriate definition for that case. % \begin{macrocode} \cs_set_eq:NN \protect \exp_not:N \tex_shipout:D \box_use:N \l_shipout_box % \end{macrocode} % The \cs{l_shipout_box} may contain the firstpage material if this % was the very first shipout. That makes it unsuitable for reuse in % another shipout, so as a safety measure the next command resets % \cs{l_shipout_box} to its earlier state if that is necessary. On % later pages this is then a no-op. % \begin{macrocode} \@@_drop_firstpage_specials: % \end{macrocode} % The \hook{shipout/after} hook (if in \verb=#4=) needs to run with % \cs{protect}ed commands again being executed, because that hook % will ``typeset'' material added at the top of the next page. % \begin{macrocode} \set@typeset@protect #4 } } % \end{macrocode} % Restore the value of \cs{protect} in case \cs{shipout} is called % outside of the output routine (where it is automatically restored % because of the implicit group). % \begin{macrocode} \cs_set_eq:NN \protect \@@_saved_protect: } } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\@@_execute_raw:, % \@@_execute_test_level_raw:} % % This implements the ``raw'' shipout which bypasses the before, % foreground, background and after hooks. It follows the same pattern than % \cs{_@@_execute_raw:} except that it finally calls % \cs{_@@_execute_main_cont:Nnnn} with three empty arguments. % instead of the hook code. % \begin{macrocode} \cs_set_protected:Npn \@@_execute_raw: { \tl_set:Nx \l_@@_group_level_tl { \int_value:w \tex_currentgrouplevel:D } \tex_afterassignment:D \@@_execute_test_level_raw: \tex_setbox:D \l_@@_raw_box } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_execute_test_level_raw: { \int_compare:nNnT \l_@@_group_level_tl < \tex_currentgrouplevel:D \tex_aftergroup:D \@@_execute_nohooks_cont: } % \end{macrocode} % Well, not totally empty arguments, we add some debugging if we % are actually doing a shipout. % \begin{macrocode} \cs_new:Npn \@@_execute_nohooks_cont: { \@@_execute_main_cont:Nnnn \l_@@_raw_box {} { \@@_debug:n{ \typeout{Doing~ raw~ shipout~ ...} } \box_set_eq:NN \l_shipout_box \l_@@_raw_box } {} } % \end{macrocode} % \end{macro} % \begin{macro}{\RawShipout} % The interface name for raw shipout. % \changes{v1.0g}{2021/01/10}{Macro added} % \begin{macrocode} \cs_gset_eq:NN \RawShipout \@@_execute_raw: % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\@@_saved_protect:} % Remember the current \cs{protect} state. % \begin{macrocode} \cs_new_eq:NN \@@_saved_protect: \protect % \end{macrocode} % \end{macro} % % \begin{macro}{shipout/before,shipout,shipout/after, % shipout/foreground,shipout/background, % shipout/firstpage,shipout/lastpage} % Declaring all hooks for the shipout code. % \changes{v1.0n}{2022/11/08}{Add shipout hook (gh/920)} % \begin{macrocode} \hook_new:n{shipout/before} \hook_new:n{shipout} \hook_new:n{shipout/after} \hook_new:n{shipout/foreground} \hook_new:n{shipout/background} \hook_new:n{shipout/firstpage} \hook_new:n{shipout/lastpage} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@kernel@after@shipout@lastpage, % \@kernel@before@shipout@background, % \@kernel@after@shipout@background} % And here are the internal kernel hooks going before or after the % public ones where needed. % \changes{v1.0g}{2021/01/10}{Internal hook % \cs{@kernel@after@shipout@background} added} % \begin{macrocode} \let\@kernel@after@shipout@lastpage\@empty \let\@kernel@before@shipout@background\@empty \let\@kernel@after@shipout@background\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_run_firstpage_hook:} % % \changes{v1.0h}{2021/01/19}{Handling of firstpage hook altered} % % There are three commands to handle the \hook{shipout/firstpage} % hook: % \cs{@@_run_firstpage_hook:}, \cs{@@_add_firstpage_specials:} and % \cs{@@_drop_firstpage_specials:}. % % That hook is supposed to contain \cs{special}s and similar % material to be placed at the very beginning of the output page % and so it needs careful placing to avoid that anything else gets % in front of it. And this means we have to wait with this until % other hooks such as \hook{shipout/background} have added their % bits. It is also important that such \cs{special}s show up only % on the very first page, so if this page gets saved before % \cs{shipout} for later reuse, we have to make sure that they % aren't in the saved version. % % In addition the hook may also contain code to be executed ``first'', e.g., % visible from code in \hook{shipout/background} and this conflicts % with adding the \cs{special}s late. % % Therefore the processing is split into different parts: % \cs{@@_run_firstpage_hook:} is done early and checks if there is % any material in the hook. % \begin{macrocode} \cs_new:Npn \@@_run_firstpage_hook: { \hook_if_empty:nTF {shipout/firstpage} % \end{macrocode} % If not then we define the other two commands to do nothing. % \begin{macrocode} { \cs_gset_eq:NN \@@_add_firstpage_specials: \prg_do_nothing: \cs_gset_eq:NN \@@_drop_firstpage_specials: \prg_do_nothing: } % \end{macrocode} % If there is material we execute inside a box, which means any % \cs{special} will end up in that box and any other code is % executed and can have side effects (as long as they are global). % \begin{macrocode} { \hbox_set:Nn \l_@@_firstpage_box { \UseHook{shipout/firstpage} } } % \end{macrocode} % Once we are here we change the definition to do nothing next time % and we also change the command used to implement \cs{AtBeginDvi} % to become a warning and not add further material to a hook that % is never used again. % \begin{macrocode} \cs_gset_eq:NN \@@_run_firstpage_hook: \prg_do_nothing: \cs_gset:Npn \@@_add_firstpage_material:Nn ##1 ##2 { \@latex@warning{ First~ page~ is~ already~ shipped~ out,~ ignoring \MessageBreak \string##1 } } } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@@_add_firstpage_specials:,\@@_drop_firstpage_specials:} % The \cs{@@_add_firstpage_specials:} then adds the \cs{special}s % stored in \cs{l_@@_firstpage_box} to the page to be shipped out % when the time is ready. Note that if there was no material in the % \hook{shipout/firstpage} hook then this command gets redefined to % do nothing. But for most documents there is something, e.g., some % PostScript header, or some meta data declaration, etc.\ so by % default we assume there is something to do. % \begin{macrocode} \cs_new:Npn \@@_add_firstpage_specials: { % \end{macrocode} % First we make a copy of the \cs{l_shipout_box} that we can % restore it later on. % \begin{macrocode} \box_set_eq:NN \l_@@_raw_box \l_shipout_box % \end{macrocode} % Adding something to the beginning means adding it to the % background as that layer is done first in the output. % \begin{macrocode} \@@_add_background_box:n { \hbox_unpack_drop:N \l_@@_firstpage_box } % \end{macrocode} % After the actual shipout \cs{@@_drop_firstpage_specials:} is % run to % restore the earlier content of \cs{l_shipout_box} and then % redefines itself again to do nothing. % % As a final act we change the definition to do nothing next time. % \begin{macrocode} \cs_gset_eq:NN \@@_add_firstpage_specials: \prg_do_nothing: } % \end{macrocode} % % The \cs{@@_drop_firstpage_specials:} is run after the shipout has % occurred but before the \hook{shipout/afterpage} hook is executed. % That is the point where we have to restore the \cs{ShipoutBox} to % its state without the \hook{shipout/firstpage} material. % \begin{macrocode} \cs_new:Npn \@@_drop_firstpage_specials: { \box_set_eq:NN \l_shipout_box \l_@@_raw_box % \end{macrocode} % If there was no such material then \cs{@@_run_firstpage_hook:} % will have changed the definition to a no-op already. Otherwise % this is what we do here. % \begin{macrocode} \cs_gset_eq:NN \@@_drop_firstpage_specials: \prg_do_nothing: } % \end{macrocode} % \end{macro} % % \begin{macro}{\l_@@_firstpage_box} % The box to hold any firstpage \cs{special}s. % \begin{macrocode} \box_new:N \l_@@_firstpage_box % \end{macrocode} % \end{macro} % % \begin{macro}{\g_@@_lastpage_handled_bool} % A boolean to signal if we have already handled the % \hook{shipout/lastpage} hook. % \begin{macrocode} \bool_new:N \g_@@_lastpage_handled_bool % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@@_add_firstpage_material:Nn} % This command adds material to the % \hook{shipout/firstpage} hook. It is used in % \cs{AtBeginDvi}, etc. The first argument is the % command through which is it called. Initially this is ignored but % once we are passed the first page it can be used to generate a % warning message mentioning the right user command. % \begin{macrocode} \cs_new:Npn \@@_add_firstpage_material:Nn #1#2 { \AddToHook{shipout/firstpage}{#2} } % \end{macrocode} % \end{macro} % % % % % % % % \begin{macro}{\@@_get_box_size:N} % Store the box dimensions in dimen registers. % \fmi{This could/should perhaps be generalized to set height depth and % width given an arbitrary box.} % \begin{macrocode} \cs_new:Npn \@@_get_box_size:N #1 { \dim_set:Nn \l_shipout_box_ht_dim { \box_ht:N #1 } \dim_set:Nn \l_shipout_box_dp_dim { \box_dp:N #1 } \dim_set:Nn \l_shipout_box_wd_dim { \box_wd:N #1 } \dim_set:Nn \l_shipout_box_ht_plus_dp_dim { \l_shipout_box_ht_dim + \l_shipout_box_dp_dim } } % \end{macrocode} % \end{macro} % % \begin{macro}{\l_shipout_box_ht_dim, % \l_shipout_box_dp_dim,\l_shipout_box_wd_dim, % \l_shipout_box_ht_plus_dp_dim} % And here are the variables set by \cs{@@_get_box_size:N}. % \begin{macrocode} \dim_new:N \l_shipout_box_ht_dim \dim_new:N \l_shipout_box_dp_dim \dim_new:N \l_shipout_box_wd_dim \dim_new:N \l_shipout_box_ht_plus_dp_dim % \end{macrocode} % \end{macro} % % % % % % \begin{macro}{\g_@@_discard_bool} % Indicate whether or not the current page box should be discarded % \begin{macrocode} \bool_new:N \g_@@_discard_bool % \end{macrocode} % \end{macro} % % % % \begin{macro}{\l_@@_tmp_box,\l_@@_saved_badness_tl} % We need a box for the background and foreground material and a % token register to remember badness settings as we disable them % during the buildup below. % \begin{macrocode} \box_new:N \l_@@_tmp_box \tl_new:N \l_@@_saved_badness_tl % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_add_background_box:n} % In standard \LaTeX{} the shipout box is always a \cs{vbox} but % here we are allow for other usage as well, in case some package % has its own output routine. % \begin{macrocode} \cs_new:Npn \@@_add_background_box:n #1 { \@@_get_box_size:N \l_shipout_box % \end{macrocode} % But we start testing for a vertical box as that should be the % normal case. % \begin{macrocode} \box_if_vertical:NTF \l_shipout_box { % \end{macrocode} % Save current values of \cs{vfuzz} and \cs{vbadness} then change % them to allow box manipulations without warnings. % \begin{macrocode} \tl_set:Nx \l_@@_saved_badness_tl { \vfuzz=\the\vfuzz\relax \vbadness=\the\vbadness\relax } \vfuzz=\c_max_dim \vbadness=\c_max_int % \end{macrocode} % Then we reconstruct \cs{l_shipout_box} \ldots % \begin{macrocode} \vbox_set_to_ht:Nnn \l_shipout_box \l_shipout_box_ht_plus_dp_dim { % \end{macrocode} % \ldots{} the material in \verb=#1= is placed into a horizontal % box with zero dimensions. % \begin{macrocode} \hbox_set:Nn \l_@@_tmp_box { \l_@@_saved_badness_tl #1 } \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim % \end{macrocode} % The we typeset that box followed by whatever was in % \cs{l_shipout_box} before (unpacked). % \begin{macrocode} \skip_zero:N \baselineskip \skip_zero:N \lineskip \skip_zero:N \lineskiplimit \box_use:N \l_@@_tmp_box \vbox_unpack:N \l_shipout_box % \end{macrocode} % The \cs{kern} ensures that the box has no depth which is % afterwards explicitly corrected. % \begin{macrocode} \kern \c_zero_dim } \box_set_ht:Nn \l_shipout_box \l_shipout_box_ht_dim \box_set_dp:Nn \l_shipout_box \l_shipout_box_dp_dim % \end{macrocode} % \fmi{The whole boxing maneuver looks a bit like overkill to me, but for % the moment I leave.} % \begin{macrocode} \l_@@_saved_badness_tl } { % \end{macrocode} % A horizontal box is handled in a similar way. The last case would % be a void box in which case we do nothing hence the missing % \texttt{F} branch. % \begin{macrocode} \box_if_horizontal:NT \l_shipout_box { \tl_set:Nx \l_@@_saved_badness_tl { \hfuzz=\the\hfuzz\relax \hbadness=\the\hbadness\relax } \hfuzz=\c_max_dim \hbadness=\c_max_int \hbox_set_to_wd:Nnn \l_shipout_box \l_shipout_box_wd_dim { \hbox_set:Nn \l_@@_tmp_box { \l_@@_saved_badness_tl #1 } \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim \box_move_up:nn \l_shipout_box_ht_dim { \box_use:N \l_@@_tmp_box } \hbox_unpack:N \l_shipout_box } \l_@@_saved_badness_tl } } } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\@@_add_foreground_box:n} % Foreground boxes are done in the same way, only the order and % placement of boxes has to be done differently. % \begin{macrocode} \cs_new:Npn \@@_add_foreground_box:n #1 { \box_if_vertical:NTF \l_shipout_box { \tl_set:Nx \l_@@_saved_badness_tl { \vfuzz=\the\vfuzz\relax \vbadness=\the\vbadness\relax } \vfuzz=\c_max_dim \vbadness=\c_max_int \vbox_set_to_ht:Nnn \l_shipout_box \l_shipout_box_ht_plus_dp_dim { \hbox_set:Nn \l_@@_tmp_box { \l_@@_saved_badness_tl #1 } \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim \skip_zero:N \baselineskip \skip_zero:N \lineskip \skip_zero:N \lineskiplimit \vbox_unpack:N \l_shipout_box \kern -\l_shipout_box_ht_plus_dp_dim \box_use:N \l_@@_tmp_box \kern \l_shipout_box_ht_plus_dp_dim } \l_@@_saved_badness_tl \box_set_ht:Nn \l_shipout_box \l_shipout_box_ht_dim \box_set_dp:Nn \l_shipout_box \l_shipout_box_dp_dim } { \box_if_horizontal:NT \l_shipout_box { \tl_set:Nx \l_@@_saved_badness_tl { \hfuzz=\the\hfuzz\relax \hbadness=\the\hbadness\relax } \hfuzz=\c_max_dim \hbadness=\c_max_int \hbox_set_to_wd:Nnn \l_shipout_box \l_shipout_box_wd_dim { \hbox_unpack:N \l_shipout_box \kern -\box_wd:N \l_shipout_box \hbox_set:Nn \l_@@_tmp_box { \l_@@_saved_badness_tl #1 } \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim \box_move_up:nn { \box_ht:N \l_shipout_box } { \box_use:N \l_@@_tmp_box } \kern \box_wd:N \l_shipout_box }% \l_@@_saved_badness_tl } } } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\@@_init_page_origins:,\c_@@_horigin_tl,\c_@@_vorigin_tl} % Two constants holding the offset of the top-left with respect to % the media box. % % Setting the constants this way is courtesy of Bruno. % % We delay setting the constants to the last possible place as % there might be updates in the preamble or even in the % \hook{begindocument} hook that affects their setup. % \begin{macrocode} \cs_new:Npn \@@_init_page_origins: { \tl_const:Nx \c_@@_horigin_tl { \cs_if_exist_use:NTF \pdfvariable { horigin } { \cs_if_exist_use:NF \pdfhorigin { 1in } } } \tl_const:Nx \c_@@_vorigin_tl { \cs_if_exist_use:NTF \pdfvariable { vorigin } { \cs_if_exist_use:NF \pdfvorigin { 1in } } } % \end{macrocode} % After the constants have been set there is no need to execute % this command again, in fact it would raise an error, so we % redefine it to do nothing. % \begin{macrocode} \cs_gset_eq:NN \@@_init_page_origins: \prg_do_nothing: } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_picture_overlay:n} % Put the argument into a \texttt{picture} environment that doesn't take up % any size and uses \texttt{1pt} for \cs{unitlength}. % \fmi{Could perhaps be generalized as it might be useful elsewhere. For % now it is not.} % \begin{macrocode} \cs_new:Npn \@@_picture_overlay:n #1 { % \end{macrocode} % The very first time this is executed we have to initialize (and % freeze) the origins. % \begin{macrocode} \@@_init_page_origins: % \end{macrocode} % % \begin{macrocode} \kern -\c_@@_horigin_tl \scan_stop: \vbox_to_zero:n { \kern -\c_@@_vorigin_tl \scan_stop: \unitlength 1pt \scan_stop: % \end{macrocode} % This mimics a simple zero-sized picture environment. The \cs{hss} % is need in case there is horizontal material (without using % \cs{put} with a positive width. % \changes{v1.0b}{2020/09/09} % {Prevent overfull box warnings (gh/387)} % \begin{macrocode} \hbox_set_to_wd:Nnn \l_@@_tmp_box \c_zero_dim { \ignorespaces #1 \hss } \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim \box_use:N \l_@@_tmp_box \tex_vss:D } } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_add_background_picture:n} % Put a \texttt{picture} env in the background of the shipout box % with its reference point in the top-left corner. % % \begin{macrocode} \cs_new:Npn \@@_add_background_picture:n #1 { \@@_add_background_box:n { \@@_picture_overlay:n {#1} } } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@@_add_foreground_picture:n} % % Put a \texttt{picture} env in the foreground of the shipout box % with its reference point in the top-left corner. % \begin{macrocode} \cs_new:Npn \@@_add_foreground_picture:n #1 { \@@_add_foreground_box:n { \@@_picture_overlay:n {#1} } } % \end{macrocode} % \end{macro} % % % \begin{macro}{\shipout_discard:} % Request that the next shipout box should be discarded. At the % moment this is just setting a boolean, but we may want to augment % this behavior that the position of the call is taken into account % (in case \LaTeX{} looks ahead and is not using the position for % on the next page). % \begin{macrocode} \cs_new_protected:Npn \shipout_discard: { \bool_gset_true:N \g_@@_discard_bool } % \end{macrocode} % \end{macro} % % % % % \subsection{Handling the end of job hook} % % At the moment this is partly solved by using the existing hooks. % But rather than putting the code into these hooks it should be % moved to the right place directly as we shouldn't prefill hooks % with material unless it needs to interact with other code. % % % % \begin{macro}{\g_shipout_readonly_int,\ReadonlyShipoutCounter} % We count every shipout activity that makes a page (but not those % that are discarded) in order to know how many pages got produced. % \begin{macrocode} \int_new:N \g_shipout_readonly_int % \end{macrocode} % For \LaTeXe{} it is available as a command (i.e., a \TeX{} % counter only. % \begin{macrocode} \cs_new_eq:NN \ReadonlyShipoutCounter \g_shipout_readonly_int % \end{macrocode} % \end{macro} % % \begin{macro}{\g_shipout_totalpages_int,\c@totalpages} % We count every shipout attempt (even those that are discarded) in % this counter. It is not used in the code but may get used in user % code. % \begin{macrocode} \int_new:N \g_shipout_totalpages_int % \end{macrocode} % For \LaTeXe{} this is offered as a \LaTeX{} counter so can be % easily typeset inside the output routine to display things like % \enquote{\cs{thepage}\texttt{/}\cs{thetotalpages}}, etc. % \begin{macrocode} \cs_new_eq:NN \c@totalpages \g_shipout_totalpages_int \cs_new:Npn \thetotalpages { \arabic{totalpages} } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\@abspage@last} % In \cs{@abspage@last} record the number of pages from the last % run. This is written to the \texttt{.aux} and this way made % available to the next run. In case there is no \texttt{.aux} file % or the statement is missing from it we initialize it with the % largest possible number in \TeX{}. We use this as the default % because then we are inserting the \hook{shipout/lastpage} on % the last page (or after the last page) but not on page 1 for a % multipage document. % \begin{macrocode} \xdef\@abspage@last{\number\maxdimen} % \end{macrocode} % \end{macro} % % % \begin{macro}{\enddocument} % % Instead of using the hooks \hook{enddocument} and % \hook{enddocument/afterlastpage} we add this code to private % kernel hooks to be 100\% sure when it is executed and to avoid % cluttering the hooks with data that is always there. % % Inside \cs{enddocument} there is a \cs{clearpage}. Just before % that we execute this code here. There is a good chance that we % are on the last page. Therefore, if we don't know the value from % the last run, we assume that the current page is the right % one. So we set \cs{@abspage@last} and as a result the next % shipout will run the \hook{shipout/lastpage} code. Of course, % if there are floats that still need a placement this guess will % be wrong but then rerunning the document will give us the correct % value next time around. % % \begin{macro}{\@kernel@after@enddocument} % \begin{macrocode} \g@addto@macro \@kernel@after@enddocument { \int_compare:nNnT \@abspage@last = \maxdimen { % \end{macrocode} % We use \LaTeXe{} coding as \cs{@abspage@last} is not an L3 name. % \begin{macrocode} \xdef\@abspage@last{ \int_eval:n {\g_shipout_readonly_int + 1} } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@kernel@after@enddocument@afterlastpage} % Once the \cs{clearpage} has done its work inside \cs{enddocument} % we know for sure how many pages this document has, so we record % that in the \texttt{.aux} file for the next run. % % \begin{macrocode} \g@addto@macro \@kernel@after@enddocument@afterlastpage { % \end{macrocode} % There is one special case: If no output is produced then there is % no point in a) recording the number as 0 will never match the % page number of a real page and b) adding an extra page to ran the % \hook{shipout/lastpage} is pointless as well (as it would % remain forever). So we test for this and run the code only if % there have been pages. % \begin{macrocode} \int_compare:nNnF \g_shipout_readonly_int = 0 { % \end{macrocode} % This ends up in the \texttt{.aux} so we use \LaTeXe{} names here. % \fmi{This needs an interface for \cs{nofiles} in expl3, doesn't at the moment!} % \begin{macrocode} \if@filesw \iow_now:Nx \@auxout { \gdef\string\@abspage@last {\int_use:N \g_shipout_readonly_int}} \fi % \end{macrocode} % But we may have guessed wrongly earlier and have run it too early % or we still have to run the % \hook{shipout/lastpage} even though there is no page to place % it into. If that is the case we make a trivial extra page and put % it there. This temporary page will then vanish again on the next % run but helps to keep pdf viewers happy. % In either case we should put out an appropriate ``rerun'' warning. % \changes{v1.0m}{2022/05/08}{Handle case where shipout/lastpage is % run too early (gh/813)} % \begin{macrocode} \bool_if:NTF \g_@@_lastpage_handled_bool { % \end{macrocode} % If the hook was already executed, we have to test if that total % shipouts match the shipouts from last run (because that % corresponds to the page it was executed). If not we output a warning. % \begin{macrocode} \int_compare:nNnF \@abspage@last = \g_shipout_readonly_int { \@latex@warning@no@line{Hook~ 'shipout/lastpage'~ executed~ on~ wrong~ page~ (\@abspage@last\space not~ \int_use:N\g_shipout_readonly_int).\MessageBreak Rerun~ to~ correct~ this}% } } { % \end{macrocode} % If the hook was not run, we need to add an extra page and place % it there. % However, making this extra page in case the hook is actually % empty would be forcing a rerun without any reason, so we check % that condition and also check if % \cs{@kernel@after@shipout@lastpage} contains any code. If both % are empty we omit the page generation. % \begin{macrocode} \bool_lazy_and:nnF { \hook_if_empty_p:n {shipout/lastpage} } { \tl_if_empty_p:N \@kernel@after@shipout@lastpage } { \tex_shipout:D\vbox to\textheight { \hbox:n { \UseHook{shipout/lastpage} \@kernel@after@shipout@lastpage } % \end{macrocode} % This extra page could be totally empty except for the hook % content, but to help the user understanding why it is there we % put some text into it. % \begin{macrocode} \@@_excuse_extra_page: \null } % \end{macrocode} % At this point we also signal to \LaTeX{}'s endgame that a rerun is % necessary so that an appropriate message can be shown on the % terminal. We do this by simply defining a command used as a flag and % tested in \cs{enddocument}. % \begin{macrocode} \cs_gset_eq:NN \@extra@page@added \relax } } } } % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\@@_excuse_extra_page:} % Say mea culpa \ldots % \begin{macrocode} \cs_new:Npn \@@_excuse_extra_page: { \vfil \begin{center} \bfseries Temporary~ page! \end{center} \LaTeX{}~ was~ unable~ to~ guess~ the~ total~ number~ of~ pages~ correctly.~ ~ As~ there~ was~ some~ unprocessed~ data~ that~ should~ have~ been~ added~ to~ the~ final~ page~ this~ extra~ page~ has~ been~ added~ to~ receive~ it. \par If~ you~ rerun~ the~ document~ (without~ altering~ it)~ this~ surplus~ page~ will~ go~ away,~ because~ \LaTeX{}~ now~ knows~ how~ many~ pages~ to~ expect~ for~ this~ document. \vfil } % \end{macrocode} % \end{macro} % % % \begin{macro}{\PreviousTotalPages,\@kernel@before@begindocument} % In the preamble before the \texttt{aux} file was read % \cs{PreviousTotalPages} is always zero. % \begin{macrocode} \def\PreviousTotalPages{0} % \end{macrocode} % In the \texttt{aux} file there should be an update for % \cs{@abspage@last} recording the number of pages from the % previous run. If not that macro holds the value of % \cs{maxdimen}. So we test for it and update % \cs{PreviousTotalPages} if there was a real value. This should % happen just before the \hook{begindocument} hook is executed so % that the value can be used inside that hook. % \begin{macrocode} \g@addto@macro\@kernel@before@begindocument {\ifnum\@abspage@last<\maxdimen \xdef\PreviousTotalPages{\@abspage@last}\fi} % \end{macrocode} % \end{macro} % % % \section{Legacy \LaTeXe{} interfaces} % % % % \begin{macro}{\DiscardShipoutBox} % Request that the next shipout box is to be discarded. % \begin{macrocode} \cs_new_eq:NN \DiscardShipoutBox \shipout_discard: % \end{macrocode} % \end{macro} % % % \begin{macro}{\AtBeginDvi} % If we roll forward from an earlier kernel \cs{AtBeginDvi} is % defined so we better not use \cs{cs_new_protected:Npn} here. % \changes{v1.0d}{2020/11/24}{Support for roll forward (gh/434)} % \begin{macrocode} \cs_set_protected:Npn \AtBeginDvi {\@@_add_firstpage_material:Nn \AtBeginDvi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\DebugShipoutsOn,\DebugShipoutsOff} % % \begin{macrocode} \cs_new_eq:NN \DebugShipoutsOn \shipout_debug_on: \cs_new_eq:NN \DebugShipoutsOff \shipout_debug_off: % \end{macrocode} % \end{macro} % % % \section{Internal commands needed elsewhere} % % These internal commands use double and triple \texttt{@} signs so % we need to stop getting them translated to the module name. % \begin{macrocode} %<@@=> % \end{macrocode} % % \begin{macro}{\@expl@@@shipout@add@firstpage@material@@Nn, % \@expl@@@shipout@add@background@box@@n, % \@expl@@@shipout@add@foreground@box@@n, % \@expl@@@shipout@add@background@picture@@n, % \@expl@@@shipout@add@foreground@picture@@n} % Some internals needed elsewhere. % % \InternalDetectionOff % \begin{macrocode} \cs_set_eq:NN \@expl@@@shipout@add@firstpage@material@@Nn \__shipout_add_firstpage_material:Nn % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN \@expl@@@shipout@add@background@box@@n \__shipout_add_background_box:n % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN \@expl@@@shipout@add@foreground@box@@n \__shipout_add_foreground_box:n % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN \@expl@@@shipout@add@background@picture@@n \__shipout_add_background_picture:n % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN \@expl@@@shipout@add@foreground@picture@@n \__shipout_add_foreground_picture:n % \end{macrocode} % \InternalDetectionOn % \end{macro} % % \begin{macrocode} \ExplSyntaxOff % %\EndIncludeInRelease % \end{macrocode} % % % Rolling back here doesn't undefine the interface commands as they % may be used in packages without rollback functionality. So we % just make them do nothing which may or may not work depending on % the code usage. % % \begin{macrocode} %\IncludeInRelease{0000/00/00}% % {\shipout}{Hook management (shipout)}% % % \end{macrocode} % If we roll forward then \cs{tex\_shipout:D} may not be defined in % which case \cs{shipout} does have it original definition and so % we must not \cs{let} it to something else which is \cs{relax}! % \changes{v1.0d}{2020/11/24}{Support for roll forward (gh/434)} % \begin{macrocode} %\ifcsname tex_shipout:D\endcsname %\expandafter\let\expandafter\shipout % \csname tex_shipout:D\endcsname %\fi % %\let \RawShipout\@undefined %\let \ShipoutBox\@undefined %\let \ReadonlyShipoutCounter \@undefined %\let \c@totalpages \@undefined %\let \thetotalpages \@undefined % %\let \DiscardShipoutBox \@undefined %\let \DebugShipoutsOn \@undefined %\let \DebugShipoutsOff \@undefined % %\DeclareRobustCommand \AtBeginDvi [1]{% % \global \setbox \@begindvibox % \vbox{\unvbox \@begindvibox #1}% %} % %\let \AtBeginShipout \@undefined %\let \AtBeginShipoutNext \@undefined % %\let \AtBeginShipoutFirst \@undefined % %\let \ShipoutBoxHeight \@undefined %\let \ShipoutBoxDepth \@undefined %\let \ShipoutBoxWidth \@undefined % % \end{macrocode} % We do not undo a substitution when rolling back. As the file % support gets undone the underlying data is no longer used (and % sufficiently obscure that it should not interfere with existing % commands) and properly removing it would mean we need to make the % \cs{undeclare@...} and its support macros available in all earlier % kernel releases which is pointless (and actually worse). % % \begin{macrocode} % %\let \AtEndDvi \@undefined % \end{macrocode} % We do not reenable a disabled package load when rolling back. As the file % support gets undone the underlying data is no longer checked (and % sufficiently obscure that it should not interfere with existing % commands) and properly removing it would mean we need to make the % \cs{reenable@package@load} command available in all earlier % kernel releases which is pointless (and actually worse). % \begin{macrocode} %\reenable@package@load{atenddvi} % \end{macrocode} % % \begin{macrocode} % %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % % % % % \section{Package emulation for compatibility} % % % \subsection{Package \pkg{atenddvi} emulation} % % % \begin{macro}{\AtEndDvi} % This package has only one public command, so simulating it is easy % and actually sensible to provide as part of the kernel. % \changes{v1.0l}{2022/01/06}{Correctly simulate \cs{AtEndDvi} without % extending the syntax} % \begin{macrocode} % %<*2ekernel|latexrelease> %\IncludeInRelease{2020/10/01}% % {\AtEndDvi}{atenddvi emulation}% \ExplSyntaxOn \cs_new_protected:Npn \AtEndDvi #1 {\AddToHook{shipout/lastpage}{#1}} \ExplSyntaxOff % \end{macrocode} % As the package is integrate we prevent loading (no need to roll that back): % \begin{macrocode} \disable@package@load{atenddvi} {\PackageWarning{atenddvi} {Functionality of this package is already\MessageBreak provided by LaTeX.\MessageBreak\MessageBreak It is there no longer necessary to load it\MessageBreak and you can safely remove it.\MessageBreak Found on}} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}% % {\AtEndDvi}{atenddvi emulation}% %\let \AtEndDvi \@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % % % \begin{macrocode} % % \end{macrocode} % % % \subsection{Package \pkg{atbegshi} emulation} % % % % % % \begin{macrocode} %<*atbegshi-ltx> \ProvidesPackage{atbegshi-ltx} [2021/01/10 v1.0c Emulation of the original atbegshi^^Jpackage with kernel methods] % \end{macrocode} % % % \begin{macro}{\AtBeginShipoutBox} % \begin{macrocode} \let \AtBeginShipoutBox \ShipoutBox % \end{macrocode} % \end{macro} % % % % \begin{macro}{\AtBeginShipoutInit} % Compatibility only, we aren't delaying \ldots % \begin{macrocode} \let \AtBeginShipoutInit \@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\AtBeginShipout,\AtBeginShipoutNext} % Filling hooks % \changes{v1.0l}{2022/01/06}{Correctly simulate \cs{AtBeginShipout} % and \cs{AtBeginShipoutNext} without extending the syntax} % \begin{macrocode} \protected\long\def\AtBeginShipout #1{\AddToHook{shipout/before}{#1}} \protected\long\def\AtBeginShipoutNext #1{\AddToHookNext{shipout/before}{#1}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\AtBeginShipoutFirst} % Slightly more complex as we need to know the name of the command under which the % \hook{shipout/firstpage} hook is filled. % \begin{macrocode} \protected \def \AtBeginShipoutFirst {\@expl@@@shipout@add@firstpage@material@@Nn \AtBeginShipoutFirst} % \end{macrocode} % \end{macro} % % % \begin{macro}{\AtBeginShipoutDiscard} % Just a different name. % \begin{macrocode} \let \AtBeginShipoutDiscard \DiscardShipoutBox % \end{macrocode} % \end{macro} % % % \begin{macro}{\AtBeginShipoutAddToBox,\AtBeginShipoutAddToBoxForeground, % \AtBeginShipoutUpperLeft,\AtBeginShipoutUpperLeftForeground} % We don't expose them. % \begin{macrocode} \let \AtBeginShipoutAddToBox \@expl@@@shipout@add@background@box@@n \let \AtBeginShipoutAddToBoxForeground \@expl@@@shipout@add@foreground@box@@n % \end{macrocode} % % \begin{macrocode} \let \AtBeginShipoutUpperLeft \@expl@@@shipout@add@background@picture@@n \let \AtBeginShipoutUpperLeftForeground \@expl@@@shipout@add@foreground@picture@@n % \end{macrocode} % \end{macro} % % \begin{macro}{\AtBeginShipoutOriginalShipout} % This offers the raw \cs{shipout} primitive of the engine. A page % shipped out with this is not counted by % \cs{ReadonlyShipoutCounter} counter and thus the mechanism to % place \cs{special}s at the very end of the output might fail, % etc. It should therefore not be used in new applications but is % only provided to allow running legacy code. For new code use the % commands provided by the kernel instead. % \begin{macrocode} \ExplSyntaxOn \cs_new_eq:NN \AtBeginShipoutOriginalShipout \tex_shipout:D % \end{macrocode} % \end{macro} % % % \begin{macro}{\ShipoutBoxHeight,\ShipoutBoxWidth,\ShipoutBoxDepth} % This is somewhat different from the original in \pkg{atbegshi} % where \cs{ShipoutBoxHeight} etc.\ only holds the % \verb=\the\ht= value. This may has some implications in some % use cases and if that is a problem then it might need changing. % \begin{macrocode} \cs_new:Npn \ShipoutBoxHeight { \dim_use:N \l_shipout_box_ht_dim } \cs_new:Npn \ShipoutBoxDepth { \dim_use:N \l_shipout_box_dp_dim } \cs_new:Npn \ShipoutBoxWidth { \dim_use:N \l_shipout_box_wd_dim } \ExplSyntaxOff % \end{macrocode} % \end{macro} % % % \begin{macrocode} % % \end{macrocode} % % If the package is requested we substitute the one above: % \begin{macrocode} %<*2ekernel> \declare@file@substitution{atbegshi.sty}{atbegshi-ltx.sty} % % \end{macrocode} % % % % % % % \subsection{Package \pkg{everyshi} emulation} % % This is now directly handled in that package so emulation is not % necessary any more. % % % Rather important :-) % \begin{macrocode} %<@@=> % \end{macrocode} % % \Finale % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \endinput %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%