% \iffalse meta-comment
%%
%% Copyright (C) 2020-2025
%% 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}
             [2025/09/23 v1.0p LaTeX Kernel (Shipout)]
% \iffalse
%
\documentclass{l3doc}
\GetFileInfo{ltshipout.dtx}

\providecommand\InternalDetectionOff{}
\providecommand\InternalDetectionOn{}

\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{ltshipout.dtx}
\end{document}
%</driver>
%
% \fi
%
%
% \long\def\fmi#1{\begin{quote}\itshape Todo: #1\end{quote}}
%
% \providecommand\hook[1]{\texttt{#1}}
% \providecommand\pkg[1]{\texttt{#1}}
%
%
% \title{The \texttt{ltshipout} 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(<node> head)
%       return true
%     end
%    \end{verbatim}
%    The \texttt{head} is the list node corresponding to the box to be shipped out.
%    The return value should always be \texttt{true}.
%  \end{variable}
%
% \subsection{Information counters}
%
%
%  \begin{variable}{\ReadonlyShipoutCounter,\g_shipout_readonly_int}
%   \begin{syntax}
%     \cs{ifnum}\cs{ReadonlyShipoutCounter}\texttt{=...}
%     \cs{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{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>
%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease>                 {\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 metadata 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@before@enddocument@afterlastpage}
%    After the last page has been shipped out, we force further
%    \cs{write} calls to be always \cs{immediate} because we aren't
%    going to ship out any more pages. This goes before the
%    \texttt{enddocument/afterlastpage} hook because that may contain
%    such \cs{write} commands.
%  \changes{v1.4p}{2025/03/05}{Make all \cs{write}s immediate after
%    the last page (gh/1689)}
%    \begin{macrocode}
\g@addto@macro \@kernel@before@enddocument@afterlastpage {
  \@@_force_immediate_writes:
  % This is also the point where \__tag_lastpage_label: could be executed
  % instead of going into enddocument/afterlastpage
}
%    \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.
%    \changes{v1.0p}{2025/04/27}{Increment page counter gh/1717}
%    \begin{macrocode}
          \bool_lazy_and:nnF
            { \hook_if_empty_p:n {shipout/lastpage} }
            { \tl_if_empty_p:N \@kernel@after@shipout@lastpage }
            {
              \global\advance\c@page\@ne
              \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
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%    \end{macrocode}
%
%
%    Rolling back here doesn't undefine the interface commands as they
%    may be used in packages without rollback functionality. So we
%    just make them do nothing which may or may not work depending on
%    the code usage.
%    
%    \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease>                 {\shipout}{Hook management (shipout)}%
%<latexrelease>
%    \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}
%<latexrelease>\ifcsname tex_shipout:D\endcsname
%<latexrelease>\expandafter\let\expandafter\shipout
%<latexrelease>                \csname tex_shipout:D\endcsname
%<latexrelease>\fi
%<latexrelease>
%<latexrelease>\let \RawShipout\@undefined
%<latexrelease>\let \ShipoutBox\@undefined
%<latexrelease>\let \ReadonlyShipoutCounter \@undefined
%<latexrelease>\let \c@totalpages \@undefined
%<latexrelease>\let \thetotalpages \@undefined
%<latexrelease>
%<latexrelease>\let \DiscardShipoutBox \@undefined
%<latexrelease>\let \DebugShipoutsOn \@undefined
%<latexrelease>\let \DebugShipoutsOff \@undefined
%<latexrelease>
%<latexrelease>\DeclareRobustCommand \AtBeginDvi [1]{%
%<latexrelease>  \global \setbox \@begindvibox
%<latexrelease>    \vbox{\unvbox \@begindvibox #1}%
%<latexrelease>}
%<latexrelease>
%<latexrelease>\let \AtBeginShipout \@undefined
%<latexrelease>\let \AtBeginShipoutNext \@undefined
%<latexrelease>
%<latexrelease>\let \AtBeginShipoutFirst \@undefined
%<latexrelease>
%<latexrelease>\let \ShipoutBoxHeight \@undefined
%<latexrelease>\let \ShipoutBoxDepth \@undefined
%<latexrelease>\let \ShipoutBoxWidth \@undefined
%<latexrelease>
%    \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}
%<latexrelease>
%<latexrelease>\let  \AtEndDvi \@undefined
%    \end{macrocode}
%    We do not reenable a disabled package load when rolling back. As the file
%    support gets undone the underlying data is no longer checked (and
%    sufficiently obscure that it should not 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}
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
%    \end{macrocode}
%
%
%
%  \begin{macro}{\__shipout_force_immediate_writes:}
%    Change all writes to be immediate. To be used after the final
%    page has been shipped out.
%  \changes{v1.0o}{2025/03/05}{Macro added}
%  \changes{v1.0p}{2025/04/27}{Decrement page counter gh/1717}
%    \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2025/06/01}%
%<latexrelease>  {\__shipout_force_immediate_writes:}{Force immediate writes}%
\ExplSyntaxOn
\cs_new:Npn \__shipout_force_immediate_writes: {
%    \end{macrocode}
%    
%    Need to check if any variants are manually defined and if so
%    adjust them too --- not done!
%    \begin{macrocode}
  \cs_gset_eq:NN \iow_shipout:Nn \iow_now:Nn
  \cs_gset_eq:NN \lua_shipout:n \lua_now:n
%    \end{macrocode}
%
%    \begin{macrocode}
  \cs_gset:Npn \write {\tex_immediate:D \tex_write:D}
%    \end{macrocode}
%   As the writes will happen without a page break, reset the
%   page number so they reference the last page.
%    \begin{macrocode}
  \global\advance\c@page\m@ne
%    \end{macrocode}
%
%    \begin{macrocode}
}
\ExplSyntaxOff
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease>  {\__shipout_force_immediate_writes:}{Force immediate writes}%
%    \end{macrocode}
%    We want a definition for this even when doing rollback so that it
%    can stay in the kernel hook without forcing a rollback there as well.
%    \begin{macrocode}
%<latexrelease>\ExplSyntaxOn
%<latexrelease> \cs_new_eq:NN \__shipout_force_immediate_writes: \prg_do_nothing:
%<latexrelease>\ExplSyntaxOff
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
%    \end{macrocode}
%  \end{macro}
%
%
%
%
% \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>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease>                 {\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}
%</2ekernel|latexrelease>
%    \end{macrocode}
%    
%    \begin{macrocode}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease>                 {\AtEndDvi}{atenddvi emulation}%
%<latexrelease>\let \AtEndDvi \@undefined
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
%    \end{macrocode}
%  \end{macro}
%
%    
%
%    \begin{macrocode}
%</2ekernel>
%    \end{macrocode}
%
%
% \subsection{Package \pkg{atbegshi} emulation}
%
%
%
%
%
%    \begin{macrocode}
%<*atbegshi-ltx>
\ProvidesPackage{atbegshi-ltx}
   [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<box>= 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}
%</atbegshi-ltx>
%    \end{macrocode}
%
%    If the package is requested we substitute the one above:
%    \begin{macrocode}
%<*2ekernel>
\declare@file@substitution{atbegshi.sty}{atbegshi-ltx.sty}
%</2ekernel>
%    \end{macrocode}
%
%
%
%
%
%
% \subsection{Package \pkg{everyshi} emulation}
%
%    This is now directly handled in that package so emulation is not
%    necessary any more.
%
%
%    Rather important :-)
%    \begin{macrocode}
%<@@=>
%    \end{macrocode}
%
%    \Finale
%
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
\endinput
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
