In a macro, I need to know whether I'm at the top of a page or not (excluding the top float). So I use the length of \pagetotal to find out whether I am or not. If \pagetotal is zero, then I'm at the top of the page. However, I've noticed that \pagetotal isn't always "up to date" and distorts the use of my macro.
How can I force \pagetotal to be updated? Or have I misunderstood the meaning of \pagetotal?
You'll find an example below where \pagetotal ~ 552 pt while the macro is at the top of the page.
\documentclass{article} \usepackage{lipsum} \newcommand{\test}{% \par \ifdim\pagetotal=0pt TRUE% \else FALSE : \textbackslash pagetotal = \the\pagetotal \fi} \begin{document} \lipsum[1] \lipsum[1] \lipsum[1] \lipsum[3] \test \the\pagetotal\lipsum[1] \the\pagetotal \end{document} Context
This question is linked to two of my previous questions: How to determine from the document body whether or not a page has a top float? and How can we ensure that the spacing before or after a \vbox is correct when using \addvspace?.
I'm trying to create a macro which adds a different vertical space depending on the context.
Normally, I'd like to insert a space of value \myLength at the beginning of my macro and at the end.
If the macro falls at the top of the page, after a page break (where \pagetotal=0pt, if I've understood correctly), \vspace{\myLength} is ignored and no vertical space is added, which is what I want.
BUT the problem arises when, as in the previous case, the macro falls at the top of the page, but is preceded by one or more top floats (it's no longer really the "top of the page" stricto sensu, but if I've understood correctly, we still have \pagetotal=0pt). In this case, I'd like the macro to insert a vertical \vspace*{\dimexpr\myLength-\textfloatsep} to maintain consistency.
Here's an example to illustrate:
Here, the macro behaves correctly: when it falls at the top of the page, no space is inserted at the start of the macro; when it is not at the top of the page, \vspace{\myLength} is correctly inserted.
However, when the macro falls at the top of the page and is preceded by a top float, the spaces are totally unbalanced.
Here is a non-working minimal example :
\documentclass{article} \usepackage{lipsum, mwe, refcount} \makeatletter %From : https://tex.stackexchange.com/questions/712713/how-to-determine-from-the-document-body-whether-or-not-a-page-has-a-top-float \def \@combinefloats {% \ifx \@toplist\@empty% \else% \@cflt% \immediate\write\@auxout{\string\global\string\@namedef{pageWithTopFloat-\thepage}{1}}% \fi% \ifx \@botlist\@empty \else \@cflb \fi% } \newcounter{ifTopFloatCnt} \def\iftopfloat#1#2{% \global\advance\c@ifTopFloatCnt\@ne% \label{\the\c@ifTopFloatCnt @ifTopFloat}% \ifcsname pageWithTopFloat-\getpagerefnumber{\the\c@ifTopFloatCnt @ifTopFloat}\endcsname% #1% \else% #2% \fi% } \makeatother \newlength{\myLength} \setlength{\myLength}{30pt}% exaggerated value to illustrate \newcommand{\mycommand}{\par% \iftopfloat{% \ifdim\pagetotal=0pt% If there's a top float AND you're right after it \vspace*{\dimexpr\myLength-\textfloatsep} \else% If there is a top float BUT you are not right after it \vspace{\myLength} \fi }{% If there is no top float \vspace{\myLength} } {\centering\LARGE * * *\par} \vspace{\myLength} } \begin{document} \lipsum[1] \lipsum[1] \lipsum[1] \lipsum[3] \begin{figure}[t] \centering \includegraphics{example-image} \end{figure} \mycommand \lipsum[1] \lipsum[2] \mycommand \lipsum[1] \mycommand \lipsum[1] \end{document} Test with \pdfsavepos
As suggested in the comments, I've tried using the \pdfsavepos and \pdflastypos primitives. This seems to work better than using \pagetotal, but I still encountered a few "bugs" with the use of my command.
In some cases, \pdfsavepos gives the information that the command is at the top of the page (\pdflastypos = 0) when it isn't (see MWE below). On the other hand, sometimes when the command is at the top of the page, just after a top-of-page float, \pdflastypos is not zero, suggesting that \pdflastypos actually refers to the bottom of the previous page.
Example: Here I get \pdflastypos ≠ 0 even though the command is at the top of the page.
\documentclass{article} \usepackage{lipsum, mwe, refcount, iftex} \ifluatex% For compatibility with LuaTeX, which I generally use. \let\pdfsavepos\savepos \let\pdflastypos\lastypos \fi \makeatletter %From : https://tex.stackexchange.com/questions/712713/how-to-determine-from-the-document-body-whether-or-not-a-page-has-a-top-float \def \@combinefloats {% \ifx \@toplist\@empty% \else% \@cflt% \immediate\write\@auxout{\string\global\string\@namedef{pageWithTopFloat-\thepage}{1}}% \fi% \ifx \@botlist\@empty \else \@cflb \fi% } \newcounter{ifTopFloatCnt} \long\def\ifTopFloat#1#2{% \global\advance\c@ifTopFloatCnt\@ne% \label{\the\c@ifTopFloatCnt @ifTopFloat}\nopagebreak% \ifcsname pageWithTopFloat-\getpagerefnumber{\the\c@ifTopFloatCnt @ifTopFloat}\endcsname% #1% \else% #2% \fi% } \newlength{\myLength} \setlength{\myLength}{30pt}% exaggerated value to illustrate \newcounter{myCommandCnt} \newcounter{myCommandCntAux} \newcommand{\myCommand}{\par% \stepcounter{myCommandCnt}% \pdfsavepos% \write\@auxout{% \string\global\string\stepcounter{myCommandCntAux}% \string\global\string\@namedef{myCommand-\string\themyCommandCntAux}{\the\pdflastypos}% }% \ifTopFloat{% \ifnum\@nameuse{myCommand-\themyCommandCnt}=0% If there's a top float AND you're right after it \vspace*{\dimexpr\myLength-\textfloatsep} {\centering\LARGE * * * (a, \textbackslash lastypos: \@nameuse{myCommand-\themyCommandCnt} )\par} \else% If there is a top float BUT you are not right after it \vspace{\myLength} {\centering\LARGE * * * (b, \textbackslash lastypos: \@nameuse{myCommand-\themyCommandCnt} )\par} \fi }{% If there is no top float \vspace{\myLength} {\centering\LARGE * * * (c, \textbackslash lastypos: \@nameuse{myCommand-\themyCommandCnt} )\par} } \vspace{\myLength} } \makeatother \begin{document} \lipsum[1] \lipsum[1] \lipsum[1] \lipsum[2] \begin{figure}[t] \centering \includegraphics{example-image} \end{figure} \myCommand \lipsum[1] \lipsum[2] \begin{figure}[t] \centering \includegraphics{example-image-9x16} \end{figure} \myCommand \lipsum[2] \myCommand \lipsum[1] \myCommand \lipsum[1] \end{document} 



\immediate\writethat defeats the point of the\writewhich is to write it once it is known, as the page is shipped out