% \iffalse meta-comment
%
% Copyright (C) 1993-2026
%
% The LaTeX Project and any individual authors listed elsewhere
% in this file.
%
% This file is part of the Standard LaTeX `Tools Bundle'.
% -------------------------------------------------------
%
% It may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%    https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% The list of all files belonging to the LaTeX `Tools Bundle' is
% given in the file `manifest.txt'.
%
% \fi
% \iffalse
%% File: afterpage.dtx Copyright (C) 1994 1994 1995 David Carlisle
%
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{afterpage}
%<package>         [2023/07/04 v1.08 After-Page Package (DPC)]
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{afterpage}
\GetFileInfo{afterpage.sty}
\begin{document}
\title{The \textsf{afterpage} package\thanks{This file
        has version number \fileversion, last
        revised \filedate.}}
\author{David Carlisle}
\date{\filedate}
\MaintainedByLaTeXTeam{tools}
\maketitle
\DocInput{afterpage.dtx}
\end{document}
%</driver>
% \fi
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \changes{v1.00}{1993/01/25}{Initial version}
% \changes{v1.05}{1993/07/14}{First public version}
% \changes{v1.06}{1994/02/01}{Update for LaTeX2e}
% \changes{v1.07}{1994/05/23}{Documentation Changes}
% \changes{v1.08}{1995/10/27}
%      {Use \cs{par} not \cs{endgraf}, for tools/1579}
% \changes{v1.08}{1995/10/27}
%      {Try and do something sensible with nested \cs{clearpage},
%       for tools/1880}
% \changes{v1.08}{1995/10/27}
%      {Try and do something sensible with footnotes, for tools/1884}
%
%
% This package implements a command, |\afterpage|, that causes the
% commands specified in its argument to be expanded after the current
% page is output.\footnote{This is really a pre-release, to see whether
% people like the idea of a command like this. This implementation is
% \emph{not} particularly robust. This implementation does not work in
% two column mode, and can get `confused' by \LaTeX's floating
% environments.}
%
% \begin{enumerate}
% \item Sometimes \LaTeX's float positioning mechanism gets overloaded,
% and all floating |figure|s and |table|s drift to the end of the
% document. One may flush out all the unprocessed floats by issuing a
% |\clearpage| command, but this has the effect of making the current
% page end prematurely. Now you can issue |\afterpage{\clearpage}| and
% the current page will be filled up with text as usual, but then a
% |\clearpage| command will flush out all the floats before the next
% text page begins.
% \item An earlier mechanism to help with float placement was the
% optional argument |[H]| (meaning {\bf HERE!}) which was originally
% added to the standard floating environments by |here.sty|, and is now
% provided by |float.sty|. However some |[H]| users have commented that
% they did not really mean `Here!' They actually wanted `Somewhere
% close'. This can now be achieved by\\
%  |\afterpage{\clearpage\begin{figure}[H] |\ldots
%  |\end{figure}}|\\
% This ensures that the figure is at the top of the next page. (The
% |\clearpage| stops any other figures drifting past the |[H]| figure.)
% \item Floating longtables. |longtable.sty| provides the |longtable|
% environment, a multi-page version of |tabular|. Many |longtable| users
% have told me that it is difficult to set the text surrounding the long
% table, and that they wanted a `floating' version. As, presumably,
% |longtable|s are long, they are probably too large to hold in memory,
% and float in the way that the |table| environment is floated, however
% if the table is in a separate file, say |ltfile.tex|, you can now
% use one of:\\
% |\afterpage{\clearpage\input{ltfile}}|\\
% |\afterpage{\clearpage\input{ltfile}\clearpage}|.\\
% The first form lets text appear on the same page as the end of the
% longtable, the second ensures that the surrounding text starts again
% on a new page.
% \end{enumerate}
%
% \MaybeStop{}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% \begin{macro}{\afterpage}
% The token register used to save the old output routine.
%    \begin{macrocode}
\newtoks\AP@output
\global\AP@output\expandafter{\the\output}
%    \end{macrocode}
%
% A box register used to save any part of the next page which has
% already been processed.
%    \begin{macrocode}
\newbox\AP@partial
%    \end{macrocode}
%
% A box register used to save any footnote texts that are `tied' to
% the text that gets saved in |\AP@partial|.
%    \begin{macrocode}
\newbox\AP@footins
%    \end{macrocode}
%
% The following macro attempts to get safely into vertical mode, and
% then invokes a special output routine to grab the current page into
% |\AP@partial|.
%    \begin{macrocode}
\def\AP@savetop{%
%    \end{macrocode}
% Now begins a test to see what state we are in. |\AP@noindent|  will
% be defined so as to return to this state (well, almost!) after
% afterpage has finished.
%    \begin{macrocode}
  \ifvmode
%    \end{macrocode}
% Vertical mode. This is the simplest case, do nothing.
%    \begin{macrocode}
    \let\AP@noindent\empty
  \else\ifhmode
%    \end{macrocode}
% Horizontal mode.
% `Back out' into vertical mode, removing the indentation box as we go.
% If in fact there was no indentation box, the output routine was
% invoked by |\noindent| (what bad luck!) so we have to remember to
% re-insert the |\noindent| before the paragraph is seen again.
% |\everypar| tokens have already been inserted, so don't insert them
% again.
%    \begin{macrocode}
    \setbox\z@\lastbox
    \edef\AP@noindent
      {{\everypar{}\ifvoid\z@\noindent\else\indent\fi}}%
    \par
  \else
%    \end{macrocode}
% The remaining (even worse) possibility that the output routine
% was triggered by the start of displaymath within a paragraph.
%
% Come out of displaymath with |$$|, then adjust the spacing (getting
% into vmode at the same time). |\AP@noindent| will restart display math
% later. |\everydisplay| tokens have already been inserted (they apply
% to the math list that will be started by |\AP@noindent|, even though
% they were triggered by the display math that was closed by the lines
% below!). Save the values |\prevgraf| and |\predisplaysize| for use in
% the re-started math list.
%    \begin{macrocode}
    \abovedisplayshortskip\z@\abovedisplayskip\z@
    \belowdisplayshortskip\z@\belowdisplayskip\z@
    \xdef\AP@disp{%
      \predisplaysize\the\predisplaysize
      \prevgraf\the\prevgraf\relax}%
    $$\vskip-\baselineskip\vskip-\parskip
    \edef\AP@noindent{%
%    \end{macrocode}
% Do not insert |\everydisplay| tokens again.
%    \begin{macrocode}
      \toks@{\the\everydisplay}\everydisplay{}%
%    \end{macrocode}
% Start displaymath mode with no spurious paragraph line above it.
% Restore |\prevgraf| and |\predisplaysize|.  Use |\aftergroup| to
% restore the correct setting for |\everydisplay| after this display
% has finished.
%    \begin{macrocode}
      {\everypar{}\noindent}$$\AP@disp\aftergroup\noexpand\AP@ed}%
  \fi\fi
%    \end{macrocode}
% Now switch the  output routine and remove everything from the current
% page into the box |\AP@partial|.
%    \begin{macrocode}
  \begingroup
  \nointerlineskip\null
    \output{%
      \global\setbox\AP@partial\vbox{%
        \unvbox\@cclv
         \global\setbox\@ne\lastbox}%
%    \end{macrocode}
% If the text that is saved in |\AP@partial| had footnotes, we'd
% better grab them as well, otherwise they may come out on a page
% with the `afterpage' text, before the page that has the
% footnote mark! (Added at v1.08.)
%    \begin{macrocode}
       \global\setbox\AP@footins\box\footins}%
%    \end{macrocode}
% Having defined the output routine, trigger it\ldots
%    \begin{macrocode}
  \eject
  \endgroup}
%    \end{macrocode}
%
% |\AP@| stores all the commands that must be executed after the page
% break.
%    \begin{macrocode}
\let\AP@\relax
%    \end{macrocode}
%
% Restore the |\everydisplay| register. |\ignorespaces| prevents a space
% or newline after |$$| creating a rogue indentation or paragraph.
%    \begin{macrocode}
\def\AP@ed{\everydisplay\expandafter{\the\toks@}\ignorespaces}
%    \end{macrocode}
%
% Remove the current vertical list, insert the commands |\AP@|
% at the top of the page, and then re-insert the saved text.
%    \begin{macrocode}
\def\AP@@{%
  \AP@savetop
  \global\expandafter\let\expandafter\AP@\expandafter\relax\AP@
  \par
%    \end{macrocode}
% The text originally at the top of this page is now stored in the box
% |\AP@partial|, including  |\topskip| glue. Now we want to unbox
% |\AP@partial|, placing the baseline of the first row |\baselineskip|
% below the baseline of the last line coming from the afterpage text.
% If we assumed nothing has too much height or depth (and |\topskip| is
% rigid), it would be fairly trivial to position the contents of
% |\AP@partial| so that the baseline of the first row was
% |\baselineskip| below the last row just added.
%
% In this version, I thought it might be fun to try to exactly achieve
% the |\baselineskip|--or--|\lineskip| calculation that \TeX\ normally
% does internally.  The call to |\addboxcontents| does the right thing
% (I hope).
%    \begin{macrocode}
   \addboxcontents\AP@partial
%    \end{macrocode}
% Now re-insert any footnote text. This may not be quite the right
% place, as the text that has just been unboxed may break over a page
% in its new position. Also it may not be the right number if the text
% from |\afterpage| itself contains footnotes. Too bad!
%    \begin{macrocode}
  \ifvoid\AP@footins\else
         \insert\footins{\unvbox\AP@footins}\fi
%    \end{macrocode}
% Now repair things if we started off in horizontal mode.
%    \begin{macrocode}
  \AP@noindent}
%    \end{macrocode}
%
% If |\AP@| is not |\relax| then the current page already has some
% `afterpage' commands, so just add the new commands to the end of the
% list. Otherwise save the commands in |\AP@|. (within a local group),
% and switch the output routine. (The new output routine just calls the
% old one if it is invoked by a \LaTeX{} float.)
%    \begin{macrocode}
\long\def\afterpage#1{%
  \ifx\AP@\relax
    \gdef\AP@{{#1\par}}%
    \global\output{%
      \the\AP@output
      \ifnum\outputpenalty>-\@Mi
        \global\output\expandafter{\the\AP@output}%
        \aftergroup\AP@@
      \fi}%
  \else
    \expandafter\gdef\expandafter\AP@\expandafter{\AP@{#1\par}}%
  \fi}
%    \end{macrocode}
%
% If we have got to the end of the document or clearpage
% just put the stuff out  without any trickery.
%    \begin{macrocode}
\let\AP@clearpage\clearpage
\def\clearpage{%
  \ifx\AP@\relax
    \AP@clearpage
  \else
    \global\output\expandafter{\the\AP@output}%
    \AP@clearpage
%    \end{macrocode}
% At this point (since v1.08) need to clear |\AP@| \emph{before}
% using its expansion, as otherwise hit an infinite loop. Sigh.
%    \begin{macrocode}
    \global\expandafter\let\expandafter\AP@\expandafter\relax
    \expandafter\expandafter\AP@
  \fi}
\let\AP@enddocument\enddocument
\def\enddocument{%
  \ifx\AP@\relax\else
    \global\output\expandafter{\the\AP@output}%
    \AP@clearpage
    \global\expandafter\let\expandafter\AP@\expandafter\relax
    \expandafter\expandafter\AP@
  \fi
    \AP@enddocument}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\addboxcontents}
% Given a vbox |#1|, add to the current vertical list such that the end
% result is equivalent to the list that \TeX\ would have built had the
% contents of |#1| (apart from any initial glue) been added individually
% to the current list.

% So essentially, the problem is that of unboxing |#1|, but replacing
% the glue at the top of |#1| with (something equivalent to) the
% |\baselineskip| or |\lineskip| glue that \TeX\ would normally have
% placed before the first box in |#1|. Also |\prevdepth| must be set at
% the end.
%    \begin{macrocode}
\def\addboxcontents#1{{%
%    \end{macrocode}
% Perhaps I shouldn't use grouping here, as I probably don't really want
% to save |#1|. If it is removed, |\splittopskip| and |\splitmaxdepth|
% would need to be restored by hand.
%
% First replace any glue at the top by |\vskip 0pt|.
%    \begin{macrocode}
  \splittopskip\z@
  \splitmaxdepth\maxdimen
  \setbox#1\vbox{\break\unvbox#1}%
  \setbox\z@\vsplit#1to\z@
%    \end{macrocode}
% Put the breakpoint back.
%    \begin{macrocode}
  \setbox#1\vbox{\break\unvbox#1}%
%    \end{macrocode}
% Set |\skip@| to be height of |#1| (without top glue)
%    \begin{macrocode}
  \skip@\ht#1%
%    \end{macrocode}
% Now make the first baseline of the first row be |\vsize| from the top.
% (This assumes that the first row has height less than |\vsize|.)
%    \begin{macrocode}
  \splittopskip\vsize
  \setbox\z@\vsplit#1to\z@
%    \end{macrocode}
% Subtract the new height of |#1| from |\skip@|, and add back on
% |\splittopskip|, so |\skip@| is now the height of the first row of
% |#1|. This may still be 0pt if (eg) a mark or whatsit is between the
% top glue and the first box. Save (this height${}-{}$|\splittopskip|)
% in |\skip\tw@|.
%    \begin{macrocode}
  \advance\skip@-\ht#1%
  \skip\tw@\skip@
  \advance\skip@\splittopskip
%    \end{macrocode}
% Now fake \TeX's |\baselineskip| calculation.
%    \begin{macrocode}
  \advance\skip@\prevdepth
  \advance\skip@-\baselineskip
  \advance\skip\tw@\ifdim-\skip@<\lineskiplimit\lineskip\else-\skip@\fi
%    \end{macrocode}
% Finally add the glue.
%    \begin{macrocode}
  \vskip\skip\tw@
%    \end{macrocode}
% Now unbox the box, setting |\prevdepth| by hand, as |\unvbox| (unlike
% |\box|) does not automatically set it.
%    \begin{macrocode}
  \global\dimen@i\dp#1%
  \unvbox#1}%
  \prevdepth\dimen@i}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \Finale
%
