9

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
    \global\addtolength{\topmargin}{1in}
    \global\addtolength{\textheight}{-1in}
}
}
{\par\ifnewpage\antiphon\else\textit{Repeat Antiphon}\fi\global\newpagefalse
 \AtBeginShipoutNext{
      \AtBeginPage{}
      \global\addtolength{\topmargin}{-1in}
      \global\addtolength{\textheight}{1in}}
}

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

3
  • 1
    Perhaps the needspace package is of use to you? See ctan.org/pkg/needspace for documentation.
    – user31729
    Commented Jun 7, 2014 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. Commented Jun 7, 2014 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). Commented Jun 8, 2014 at 11:20

2 Answers 2

3

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
    \global\addtolength{\topmargin}{1in}
    \global\addtolength{\textheight}{-1in}
}
}
{\par\ifnewpage\antiphon\else\textit{Repeat Antiphon}\fi\global\newpagefalse
 \AtBeginShipoutNext{
      \AtBeginPage{}
      \global\addtolength{\topmargin}{-1in}
      \global\addtolength{\textheight}{1in}}
\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}
1
  • 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. Commented Dec 15, 2016 at 20:33
0

In reviewing my account, I found I never posted the answer I settled on for this question, so I'm doing it now. Better late than never.

What I did was combine the longtable package with a patch based on https://tex.stackexchange.com/a/202685/49327 applied (to provide for both even and odd headers and footers in the longtable) and some use of labels to enable comparison of the page number of the beginning and the end of the environment before setting the contents of the last footer. The relevant environment definition is as follows:

\usepackage{longtable}

\newbox\LT@oddhead
\newbox\LT@evenhead
\def\endoddhead{\LT@end@hd@ft\LT@oddhead}
\def\endevenhead{\LT@end@hd@ft\LT@evenhead}
\def\LT@head{\ifodd\c@page\LT@oddhead\else\LT@evenhead}
\newbox\LT@oddfoot
\newbox\LT@evenfoot
\def\endoddfoot{\LT@end@hd@ft\LT@oddfoot}
\def\endevenfoot{\LT@end@hd@ft\LT@evenfoot}
\def\LT@foot{\ifodd\c@page\LT@oddfoot\else\LT@evenfoot}

\newcounter{sungpsalm}

\newenvironment{sungpsalm}[2]
{%
  \stepcounter{sungpsalm}%
  \label{psalmstart-\thesungspalm}%
  \def\do@antiphon{#1}%
  \def\do@tone{#2}%
  \begin{longtable}[l]{p{\textwidth}}%
    \do@antiphon
    \do@tone\endfirsthead
    \do@tone\endevenhead
    Continued next page\endoddfoot
    \ifodd\getpagerefnumber{psalmstart-\thesungpsalm}%
      \ifnum\getpagerefnumber{psalmend-\thesungpsalm}>\getpagerefnumber{psalmstart-\thesungpsalm}\relax%
        \do@antiphon%
      \else%
        Repeat antiphon%
      \fi%
    \else%
      \ifnum\getpagerefnumber{psalmend-\thesungpsalm}>\numexpr(\getpagerefnumber{psalmstart-\thesungpsalm}+1)\relax%
        \do@antiphon%
      \else%
        Repeat antiphon%
      \fi%
    \fi%
    \endlastfoot
}
{%
  \label{psalmend-\thesungpsalm}
  \end{longtable}%
}

I've been using this for several years now and haven't run into any major problems.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .