2

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.

enter image description here

\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.

enter image description here

However, when the macro falls at the top of the page and is preceded by a top float, the spaces are totally unbalanced.

enter image description here

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 (I haven't managed to reproduce this phenomenon in the MWE below, but I've encountered it).

Example: Here I get \pdflastypos = 0 even though the command is not at the top of the page.

enter image description here

\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% } \makeatother

\newlength{\myLength} \setlength{\myLength}{30pt}% exaggerated value to illustrate

\newcommand{\mycommand}{\par% \pdfsavepos%
\ifTopFloat{% \ifnum\pdflastypos=0% If there's a top float AND you're right after it \vspace{\dimexpr\myLength-\textfloatsep} {\centering\LARGE * * (a, \textbackslash lastypos: \the\pdflastypos )\par} \else% If there is a top float BUT you are not right after it \vspace{\myLength} {\centering\LARGE * * * (b, \textbackslash lastypos: \the\pdflastypos )\par} \fi }{% If there is no top float \vspace{\myLength} {\centering\LARGE * * * (c, \textbackslash lastypos: \the\pdflastypos )\par} }
\vspace{\myLength} }

\begin{document}

\lipsum[1]

\lipsum[1]

\lipsum[1]

\lipsum[1]

\begin{figure}[t] \centering \includegraphics{example-image} \end{figure}

\mycommand

\lipsum[2]

\lipsum[2]

\begin{figure}[t] \centering \includegraphics{example-image} \end{figure}

\mycommand

\lipsum[2]

\mycommand

\lipsum[1]

\mycommand

\lipsum[1] \end{document}

B Legrand
  • 521
  • TeX is essentially never at the top of a page. – egreg Mar 25 '24 at 18:33
  • 3
    Possibly an XY problem .... Can you explain the purpose of your macro? Then somebody might be able to suggest an alternative approach. – cfr Mar 25 '24 at 18:42
  • What happens if you add \par following each \lipsum[] ? – rallg Mar 25 '24 at 19:21
  • @rallg There's already one (generated by the blank line). – egreg Mar 25 '24 at 22:30
  • a top float may be added above the point you test \pagetotal and even if it is not you can not test within the document. You can use \pdfsavepos and write the y coordinate to the aux file and test it on the next run – David Carlisle Mar 25 '24 at 22:34
  • @cfr I've added the context to my question. – B Legrand Mar 26 '24 at 21:02
  • @egreg I've added the context to my question. It's not about the "geometric" top of the page, but rather the "first line" (after any top floats) of the page, where, as I understand it, you have \pagetotal=0pt. I did not express myself well, sorry. – B Legrand Mar 26 '24 at 21:05
  • @DavidCarlisle In my case, I detect the presence or absence of top floats in a page by compiling the document twice. What I can't do is determine whether I'm just after this possible float (in which case, if I've understood correctly, \pagetotal=0pt) or "further" down the page. – B Legrand Mar 26 '24 at 21:10
  • 1
    you should use pdflastpos as I say and look on the next run. pagetotal is completely unusable here for example it is never updated during a paragraph so if you have a long paragraph text breaking over a page, if you test the value anywhere in the paragraph it will refer to the value at the start which may not even be on the same page as the point you test. if you test in vertical mode it's a bit more reliable, but not much – David Carlisle Mar 27 '24 at 00:36

0 Answers0