Skip to content

Commit

Permalink
an afterpage emulation
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankMittelbach committed Jan 14, 2021
1 parent ba575e1 commit e46fbda
Show file tree
Hide file tree
Showing 2 changed files with 11,965 additions and 0 deletions.
394 changes: 394 additions & 0 deletions base/testfiles-lthooks2/shipout2-015.lvt
@@ -0,0 +1,394 @@
\RequirePackage[enable-debug]{expl3}
\ExplSyntaxOn
\debug_on:n { check-declarations , deprecation }
\ExplSyntaxOff

\documentclass[a4paper]{article}

\input{regression-test}

\usepackage{lipsum,etoolbox}
\usepackage[balancingshow]{multicol}


% the multicol stuff here is purely experimental because I think there is yet another deficiency there
% but one that needs adressing elsewhere ...

\makeatletter

\def\balance@columns{%
\get@keptmarks\mult@box
\setbox\mult@box\vbox{%
\penalty-\@M
\unvbox\mult@box
}%
\@tempdima\topskip
\splittopskip\@tempdima
\@plus\multicolundershoot
\@minus\multicolovershoot
\splitmaxdepth\@maxdepth
\boxmaxdepth\@maxdepth
\setbox\@tempboxa\vsplit\mult@box to\z@
\@tempdima\ht\mult@box
\advance\@tempdima\dp\mult@box
\divide\@tempdima\col@number
\count@\@tempdima
\divide\count@\baselineskip
\dimen@\count@\baselineskip
\advance\dimen@\topskip
\ifdim \dimen@ >\@tempdima
\advance\dimen@-\baselineskip
\fi
\@tempdima\dimexpr
\topskip +\c@minrows\baselineskip-\baselineskip\relax
\ifnum\dimen@<\@tempdima
\mult@info\@ne
{Start value
\the\dimen@ \space ->
\the\@tempdima \space (corrected for minrows)}%
\dimen@\@tempdima
\fi
\advance\dimen@\c@unbalance\baselineskip
\mult@info\@ne
{Balance columns\on@line:
\ifnum\c@unbalance=\z@\else
(off balance=\number\c@unbalance)\fi
\@gobbletwo}%
\ifnum\dimen@<\topskip
\mult@info\@ne
{Start value
\the\dimen@ \space ->
\the\topskip \space (corrected)}%
\dimen@\topskip
\fi
\vbadness\@M
\vfuzz \maxdimen
\last@try-\p@
\loop
{\process@cols\mult@grightbox
{\global\setbox\count@
\box\voidb@x}}%
\global\setbox\mult@grightbox
\copy\mult@box
\too@badfalse
\forcedbreak@leftoverfalse
{\process@cols\mult@firstbox{%
\global\setbox\count@
\vsplit\mult@grightbox to\dimen@
\global\setbox\count@
\vbox to\dimen@
{\unvbox\count@}%
\ifnum\c@tracingmulticols>\@ne
\@tempcnta\count@
\advance\@tempcnta-\mult@grightbox
\divide\@tempcnta \tw@
\message{^^JColumn
\number\@tempcnta\space
badness: \the\badness\space}%
\fi
\ifnum\badness>\c@columnbadness
\ifnum\c@tracingmulticols>\@ne
\message{too bad
(>\the\c@columnbadness)}%
\fi
\too@badtrue
\fi
}}%
\global\setbox\mult@grightbox
\vbox{\unvbox\mult@grightbox}%
\setbox\mult@nat@firstbox
\vbox{\unvcopy\mult@firstbox}%
%+++++++++++++++
\XXX\showbox\mult@nat@firstbox
%+++++++++++++++
\ifnum\c@tracingmulticols>\@ne
\message{^^JFirst column
= \the\dimen@\space
(\the\ht\mult@nat@firstbox)}\fi
\ifnum\c@tracingmulticols>\@ne
\message{<> last column =
\the\ht\mult@grightbox^^J}%
\fi
\ifdim\ht\mult@grightbox >\dimen@
\too@badtrue
\ifnum\c@tracingmulticols>\@ne
\typeout{Rejected: last
column too large!}%
%+++++++++++++++
% \ht\mult@nat@firstbox\dimen@ % pretend
%+++++++++++++++
\fi
\else
\setbox\@tempboxa
\copy\mult@grightbox
\setbox\z@\vsplit\@tempboxa to\maxdimen
\ifvoid\@tempboxa
\global\setbox\mult@grightbox
\vbox to\dimen@
{\unvbox\mult@grightbox}%
\ifnum\c@tracingmulticols>\@ne
\message{Final badness:
\the\badness}%
\fi
\ifnum\badness>\c@finalcolumnbadness
\global\setbox\mult@grightbox
\vbox to\dimen@
{\unvbox\mult@grightbox\vfil}%
\ifnum\c@tracingmulticols>\@ne
\message{ setting natural
(> \the\c@finalcolumnbadness)}%
\fi
\fi
\else
\@tempdima\@colroom
\advance\@tempdima \maxbalancingoverflow
\ifdim \dimen@ < \@tempdima
\too@badtrue
\ifnum\c@tracingmulticols>\@ne
\typeout{Rejected: unprocessed
forced break(s) in last column!}%
\fi
\else
\forcedbreak@leftovertrue
\ifnum\c@tracingmulticols>\@ne
\typeout{Failed: columns too large
with unprocessed forced break(s)!}%
\fi
\fi
\fi
\fi
%+++++++++++++++
\iffalse
\ifdim\ht\mult@nat@firstbox<\dimen@
\ifdim\ht\mult@nat@firstbox>\last@try
\too@badtrue
\ifnum\c@tracingmulticols>\@ne
\typeout{Retry: using natural
height of first column!}%
\fi
\dimen@\ht\mult@nat@firstbox
\last@try\dimen@
\advance\dimen@-\p@
\fi
\fi
\fi
%++++++++++++++++
\iftoo@bad
\advance\dimen@\p@
\repeat
\ifforcedbreak@leftover
\too@badtrue
\else
\if@boxedmulticols\else
\ifdim\dimen@>\@colroom
\dimen@\@colroom
\fi
\fi
\process@cols\mult@rightbox
{\@tempcnta\count@
\advance\@tempcnta\@ne
\vfuzz\z@
\setbox\count@\vbox to\dimen@
{%
\vskip \z@
\@plus-\multicolundershoot
\@minus-\multicolovershoot
\unvbox\@tempcnta
\ifshr@nking\vfilmaxdepth\fi
}%
\ifnum\badness>\@M
\vfuzz\maxdimen % no overfull warning
\setbox\@tempboxa \vbox to\dimen@
{\vskip-\maxbalancingoverflow
\unvcopy\count@}%
\ifnum\badness>\@M
\mult@info\@ne
{Balanced column more than
\the\maxbalancingoverflow\space
too large}%
\too@badtrue
\else
\mult@info\@ne
{Balanced column
too large, but less than
\the\maxbalancingoverflow}%
\fi
\fi
}%
\fi
}


\newdimen\multicolbalancestep \multicolbalancestep=1pt

\patchcmd\balance@columns{\last@try-\p@}{\last@try-\multicolbalancestep}{}{\ERROR1}
\patchcmd\balance@columns{\advance\dimen@-\p@}{\advance\dimen@-\multicolbalancestep}{}{\ERROR2}
\patchcmd\balance@columns{\advance\dimen@\p@}{\advance\dimen@\multicolbalancestep}{}{\ERROR4}
\makeatother

\newcommand\dofig[2][tbp]{\begin{figure}[#1] #2\caption{}\end{figure}}
\newcommand\dotab[2][tbp]{\begin{table}[#1] #2\caption{}\end{table}}

% a simple version of afterpage package

\makeatletter

% storage for \afterpage tokens
\let\afterpagecontent\@empty

\long\def\afterpage#1{%
\AddToHookNext{shipout/before}%
{%
% issue \afterpagecontinue once only
\ifx \afterpagecontent\@empty \afterpagecontinue \fi
% if there are more calls on the same page combine content
\g@addto@macro\afterpagecontent{#1}%
}%
}

% this \aftergroups out of the OR and if it reaches the OR group it aftergroup to
% \afterpagegrab

\def\afterpagecontinue{%
% just for debugging:
\begingroup
\@tempcnta\currentgrouptype

This comment has been minimized.

Copy link
@davidcarlisle

davidcarlisle Jan 14, 2021

Member

this is always going to be \begingroup type from the line above

This comment has been minimized.

Copy link
@FrankMittelbach

FrankMittelbach Jan 15, 2021

Author Member

yeah rubbish, I added it last night to avoid cluttering @tempcnta through debugging but of course that is the wrong way to do it.

\@tempcntb\currentgrouplevel
\typeout{Group type/level=\the\@tempcnta/\the\@tempcntb}%
\endgroup
% repeat if necessary
\ifnum \currentgrouptype =8
\aftergroup\afterpagegrab
\else
\aftergroup\afterpagecontinue
\fi
}

\newbox\APpartial

% when we \aftergroup out of the OR, there may or may not be any recent contributions
% and there could also be material added from the OR itself.
% the \aftergroup tokens are executed after the recent contributions (not before).

\def\afterpagegrab{%
%
% this means this OR setup is only called if the recent contributions are non-empty otherwise the
% \eject is discarded.
% Thus \APpartial tells us if there were some recent contributions (it is a \vbox) or not (it is void).
%
\begingroup
\output{\global\setbox\APpartial\vbox{\boxmaxdepth\maxdimen\unvbox255}}%
\eject
\endgroup
%
% Next execute the \afterpagecontent. Note that we are not on the top of the page
% or rather we are now because we grabbed the recent contributions!
% We also empty \afterpagecontent first, so that the content can even contain further \afterpage calls
% (but there are some restrictions to that)
%
\global\expandafter\let\expandafter\afterpagecontent\expandafter\@empty
\afterpagecontent
%
% this does whatever it does (such as typesetting material) ...
% ... and then we reinsert the saved "recent contributions" if any.
% (So this currently would be a problem if that material ends up being more than a page
% \emph{and} also calls \afterpage because then we might clobber \APpartial)
%
% Now there is a subtle point: going through the OR the \APpartial starts with a
% topskip glue. If we just unbox and above we added typeset material the spacing is wrong
% as the \prevdepth of that material is not taken into account.
% On the other hand if there is no such material there is no \prevdepth to account for, so we can't
% backup by \prevdepth.
% Instead we make an empty paragraph whose baseline should be exactly where the baseline of the first
% line of the box should be. Thus then backup up by \topskip should make everything come out right.
% Note that if there were no recent contributions then the whole stuff is bypassed and so it should come out right
% as well, because any following material will properly append itself as it is newly typeset not unboxed.
%
\ifvbox\APpartial
\par\nobreak\indent\par\nobreak\vskip-\topskip
%
% and one more adjustment is necessary: the \APpartial box may has as \depth but that depth
% will not show in \prevdepth if we \unvbox so we need to put it manually there.For that reason
% we also had to collect the box with \boxmaxdepth\maxdimen to get the true value.
% If we don't do that calculation of the next baselineskip will assume a \prevdepth of 0pt which may
% or may not be right.
\prevdepth\dp\APpartial
\unvbox\APpartial
\fi
}
\makeatother

\DebugShipoutsOn

%\showoutput

\begin{document}

\START

\lipsum[1-3]
%\afterpage{\clearpage}
\afterpage{\dotab{A}\dofig{F}\dotab{B}\dotab{C}\dotab{D}}
\dofig{A}
\dofig{B}
\dofig{C}
\dofig{D}
\dofig{E}
\lipsum[4-12]

\twocolumn \sloppy

\lipsum[1-3]
%\afterpage{\clearpage}
\afterpage{\dotab[!tbp]{A}\dofig[!tbp]{F}\dotab[!tbp]{B}\dotab[!tbp]{C}\dotab[!tbp]{D}}
\dofig{A}
\dofig{B}
\dofig{C}
\dofig{D}
\dofig{E}
\lipsum[4-6]

\ShowHook{shipout/before}

ZZZ\\ZZZ \afterpage{XXXX\par\empty}

\ShowHook{shipout/before}

\lipsum[7-8]

\newpage % this is a hard break so no recent contributions

AAAAAAAAAAAA

\lipsum[9-12]

\onecolumn

\showoutput


\begin{multicols}{3}

\lipsum[1-3] \par xxx\par
\afterpage{XXXX}
%\afterpage{hello}
\lipsum[4-10]

\vfill\null
\end{multicols}

\end{document}




\afterpage{g}
X1 \pagebreak X2g \\
X3 \\
X4g \\
X5





0 comments on commit e46fbda

Please sign in to comment.