# How to track a page change within an environment?

I'm trying to define an environment that can automatically detect when the material within it moves to a new page, reprint one of its arguments at the top of the new page, and change how it closes as a result. So far, this is what I've come up with:

\newif\ifnewpage\newpagefalse
\newenvironment{sungpsalm}[2]%
{\def\antiphon{#1}\gdef\tone{#2}\antiphon\par\tone\par\AtBeginPage{%
\setlength{\unitlength}{1in}
\put(1.5, -1.75){\makebox(0,0)[tl]{\tone}}}\newpagetrue}
{\par\ifnewpage\antiphon\else\textit{Repeat Antiphon}\fi\newpagefalse}


The \AtBeginPage macro comes from the bophook package. The problem is that this places the contents of \tone in the background and so the text appears overtop of it and it puts it on the page on which the environment starts too. Is there a way to do something like this except instead of it placing the contents of \tone in the background, they get inserted into the stream of the text at the beginning of the new page?

Complete MWE:

\documentclass[openany,12pt]{book}

\usepackage{bophook}
\usepackage{blindtext}
\usepackage{atbegshi}

\newif\ifnewpage\newpagefalse
\newenvironment{sungpsalm}[2]%
{\def\antiphon{#1}
\gdef\tone{#2}
\antiphon\par\tone\par
\AtBeginShipoutNext{
\AtBeginPage{%
\setlength{\unitlength}{1in}
\put(1.5, -1.75){\makebox(0,0)[tl]{\tone}}
}
\global\newpagetrue
}
}
{\par\ifnewpage\antiphon\else\textit{Repeat Antiphon}\fi\global\newpagefalse
\AtBeginShipoutNext{
\AtBeginPage{}
}

\begin{document}

\begin{sungpsalm}{Some text to represent the antiphon.  Normally this would be a snippet of music created using lilypond.}
{Some text to represent the psalm tone.}
\Blindtext
\end{sungpsalm}

\end{document}


Edit: Some further searching online led me to the atbegshi package which has similar functionality to bophook. After playing around with this package for a while, I found that by using both packages I could solve some of my problems. The above MWE has been modified so that the appearence of \tone is correct so long as a new sungpsalm environment does not start on the same page as the previous one ended. Since my application most likely will call for each sungpsalm to start a new page (or nearly so, with just a section header before) due to the page size considerations, I consider what I've got to be acceptable in that regard.

However, that still left the problem that \tone was being placed as a background image, rather than directly in the text. I found a hacky way of dealing with this by expanding \topmargin (and shrinking \textheight) when the \tone is added to the page and then reverting them when it is cleared. Thus, while \tone is still technically being placed on a background layer, the regular text doesn't appear over top of it. I consider this a work around, not a solution. If anyone has a better idea as to how to do this right I'd appreciate it.

• Perhaps the needspace package is of use to you? See ctan.org/pkg/needspace for documentation. – user31729 Jun 7 '14 at 15:09
• @ChristianHupfer, as I read the documentation for needspace, it serves to prevent a page break, which I'm not interested in doing. The idea isn't to prevent a page break, but react to the occurrence by altering the text. – rpspringuel Jun 7 '14 at 17:46
• the fwlw package may help. its aim is pretty nearly congruent with yours, but i can’t say whether it would solve your problem. (the package is in all the major distributions, but strangely the doc doesn't show up in tl's texdoc command on my machine (tl2013). – wasteofspace Jun 8 '14 at 11:20

It is not exactly clear what you want. But this is the best I could interpret your request. Summary of changes from your logic:

1. \def\tone{} in the preamble, so that it is defined.

2. commented out \gdef\tone{#2} at the beginning of the sungpsalm environment, and instead placed the same definition at the beginning of the \AtBeginShipoutNext macro later in the sungpsalm pre-code. This has the effect of not presenting \tone on the first page of its invocation, but only on the second and subsequent pages.

3. Added a \AtBeginShipoutNext{\gdef\tone{}} in the sungpsalm post-code, to reset the \tone macro on the subsequent page (so that it still prints out on the page of the environment closing).

4. I added extra text and sungpsalm invocations to test items 1-3 above.

Here is the MWE

\documentclass[openany,12pt]{book}
\def\tone{}
\usepackage{bophook}
\usepackage{blindtext}
\usepackage{atbegshi}

\newif\ifnewpage\newpagefalse
\newenvironment{sungpsalm}[2]%
{\def\antiphon{#1}
%\gdef\tone{#2}
\antiphon\par\tone\par
\AtBeginShipoutNext{
\gdef\tone{#2}
\AtBeginPage{%
\setlength{\unitlength}{1in}
\put(1.5, -1.75){\makebox(0,0)[tl]{\tone}}
}
\global\newpagetrue
}
}
{\par\ifnewpage\antiphon\else\textit{Repeat Antiphon}\fi\global\newpagefalse
\AtBeginShipoutNext{
\AtBeginPage{}
\AtBeginShipoutNext{%
\gdef\tone{}%
}
}

\begin{document}

\begin{sungpsalm}{Some text to represent the antiphon.  Normally this would be a snippet of music created using lilypond.}
{Some text to represent the psalm tone.}
\Blindtext
\end{sungpsalm}

Now for something else

\Blindtext

get ready here it comes

\begin{sungpsalm}{Some text to represent the antiphon.  Normally this would be a snippet of music created using lilypond.}
{Some text to represent the psalm tone.}
\Blindtext
\end{sungpsalm}

Now for something else

\Blindtext

\end{document}

• I'm just now getting back to this project. I don't want the complete suppression of \tone on the first page of the environment, just it's placement in the header. This answer, however, gets closer to that than my MWE. To get all the way there I just needed to make \antiphon\par\tone\par read \antiphon\par#2\par. However, this still doesn't solve my issue with the \tone being placed as a background image and not in the text. – rpspringuel Dec 15 '16 at 20:33