9

I'm trying to build an environment where if a page breaks in the environment some additional text is automatically printed at the end of the page, while this text is not printed when no page break occurs. So, for example:

\begin{special_env}{Please also check following page}
  A lot of text goes here...
  And even more text goes here...
\end{special_env}

Should print the text in the environment as normal, but whenever a page break occurs should add "Please also check following page" to the bottom of the page.

I know things like longtable can do this, but my text isn't really a table and I'm not sufficiently advanced in my TeX skills to figure out how they do it. I've seen Add customized text at an optional page-break, which almost does what I need except it requires me to already know approximately where the page break will be. I've also seen Add customized text at an optional page-break, which again seems to focus too much on tables (unless I'm misunderstanding).

My question is, how can I code this so that it will automatically figure out where the page breaks end up being and inserts the text where needed?

While I have some experience as a LaTeX user and have occasionally ventured into doing some slightly more advanced scripting, my knowledge is really rather limited, so please bear with me while I try to digest your answers.

[Edit]

Thanks both for your help. I have played with the different variants proposed, but haven't quite been able to achieve what I need. It's close, but not quite there yet. Let me give you a little bit more detail on what I'm trying to achieve. I am extending a class that defines a question environment for the purposes of writing exam papers. When a question continues on a new page, we're required to add "Question X continues on next page" on that page. The class currently uses an interesting method to determine whether to page break after a question.

A document then consists essentially of a \maketitle followed by a sequence of question environments, normally with no other text between them.

At the moment, my code looks somewhat like this:

\documentclass{article}

\usepackage{lipsum}

\makeatletter

\newif\ifinenv
\inenvfalse

\newcommand \@@footer{\ifinenv {QUESTION \thequestion\ CONTINUES ON NEXT PAGE} \fi}

\def \ps@exam{%
  \let \@mkboth \@gobbletwo%
  \def \@oddhead{}%
  \def \@oddfoot{\@@footer}%
  \def \@evenhead{}%
  \def \@evenfoot{\@@footer}%
}
\pagestyle{exam}

\newcommand \testpagebreak[1]{%
  \vfil%
  \penalty #1%
  \vfilneg%
}

\newcounter{question}

\newenvironment{question}{%
  \refstepcounter{question}%
  \inenvtrue
  \begin{list}{}{}%
      \item[\bf \thequestion.]% 
}{%
  \end{list}%
  \testpagebreak{-350}%
}

\begin{document}

  \begin{question}
    \lipsum[1-7]
  \end{question}

  \begin{question}
    \lipsum[8-13]
  \end{question}

  \begin{question}
    Just a single line

    And another
  \end{question}
\end{document}

This works quite well, except where the start of a question is pushed to the start of a new page. In this case, the PTO text will be printed on the page before the question starts, so for example:

Text of Question 1
Question 2 continues on the next page
----page break----
Text of Question 2

Clearly the problem is that the start of the environment of Question 2 is still processed before TeX decides to open a new page. If I replace the \testpagebreak code with a hard \newpage or leave it out completely all is fine. Is there a way to fiddle with this code to make it work with \testpagebreak (or a variant thereof)?

[/Edit]

[Edit 2]

I've experimented some more based on @Werner's idea. My code can be found at PasteBin. Note that in the second question there are two alternative versions of the contents, a short one and a longer one. Using the short one (so that Question 2 doesn't actually span multiple pages) all is well. Using the long one (so that Question 2 does span multiple pages) the "Question 2 continues" text is shown already on the last page of Question 1; that is one page too early.

From this, I deduce that the label mechanism works correctly. However, the code in the footer doesn't always correctly pick up whether a question actually starts on the page currently being shipped out. I have no idea how to fix this, but maybe someone out there can point me in a useful direction?

[/Edit 2]

Many thanks in advance,

Steffen

  • Welcome to TeX.SX! Breakable boxes/environments are always a little bit difficult. I would suggest to remove the See on next page etc. stuff from the bottom and rather print it at the bottom of the first part of the page-broken environment. You could use tcolorbox (with no colours ;-) for breaking such boxes and environments and adding this text at the bottom etc. – user31729 Jun 26 '15 at 11:58
  • Thanks Christian. I'm not sure I fully understand your suggestion. I need this to print on the bottom of every page that has text from this environment except for the last one. I currently manually insert the text manually once I know where the page breaks are, but that's a little awkward, especially as a document gets edited over time. – Steffen Zschaler Jun 26 '15 at 12:00
  • You should show us what you have, perhaps there will be some amendments/suggestions – user31729 Jun 26 '15 at 12:00
  • What I have is literally just a three step manual process: 1. enter main text and compile to PDF, 2. see whereabouts page breaks occur and add See on next page text in approximate location into LaTeX, 3. recompile and keep my fingers crossed. – Steffen Zschaler Jun 26 '15 at 12:19
  • Sounds as if you have plenty of time and no other work to do ;-) – user31729 Jun 26 '15 at 12:21
6

What about the following idea?

It's much different from yours (or perhaps the class author's), but perhaps more robust as it uses the \label-\ref system to determine whether a page break has occurred mid-question:

enter image description here

\documentclass{article}

\usepackage[paper=a5paper,margin=1in]{geometry}% Just for this example
\usepackage{multido}% Just for this example
\usepackage[nopar]{lipsum}% Just for this example
\usepackage{refcount}
\usepackage{fancyhdr}

\newcounter{question}

\newenvironment{question}{%
    \begin{list}{}{}%
      \refstepcounter{question}%
      \item[\bfseries\thequestion.]%
      \leavevmode% Start paragraph
      \label{question-start-\thequestion}%
  }{%
    \label{question-end-\thequestion}%
    \end{list}
  }

\pagestyle{fancy}
\fancyhf{}% Clear header/footer
\fancyfoot[L]{% Left footer
  \ifnum\getpagerefnumber{question-start-\thequestion}<\getpagerefnumber{question-end-\thequestion}
    Question~\thequestion{} continues on the next page%
  \fi}
\fancyfoot[R]{See next page}% Right footer
\renewcommand{\headrulewidth}{0pt}% Remove header rule

\AtEndDocument{\fancyfoot[R]{}}% Remove right footer at end of document

\sloppypar% Just for this example
\begin{document}

\multido{\i=1+1}{50}{%
  \begin{question}
    \lipsum[\i]
  \end{question}
  \bigskip
}

\end{document}

At each \item inside question, a \label is set, and then another \label at the end of the question. A check is made to see whether the page number at the start is different from (less than) the ending page number. Accordingly, the footer sets the appropriate clause.

  • Thanks, this looks very interesting indeed. I'll give it a spin once back at my main computer and report back. – Steffen Zschaler Jun 26 '15 at 21:49
  • I've now tried this. Unfortunately, it suffers from the same problem as my attempts in the edits above: when the open label is created, TeX hasn't necessarily decided yet whether to move the start of the question onto a new page, so in those cases I get the text a page too early. – Steffen Zschaler Jun 27 '15 at 12:36
  • @SteffenZschaler: Retry with the minor addition of \leavevmode... – Werner Jun 28 '15 at 17:23
  • Thanks, @werner. Unfortunately, this doesn't seem to make any difference at all. I'm not sure I fully understand how \leavevmode works, but I couldn't figure out why it would help. – Steffen Zschaler Jun 29 '15 at 9:02
  • 1
    @SteffenZschaler: I see you've mixed in your \testpagebreak with my construction. I think That's wrong. Why do you use or need \testpagebreak? Is it because you need to leave a specific amount of space at the bottom of a page blank? Or perhaps because you need space left blank after a question? In that regard, one could also use needspace. Regardless, I'm not entirely clear on the need for using \testpagebreak. – Werner Jun 29 '15 at 20:15
1

My original idea was to change the footer at the environment start and revert it at the end, but this fails if the environment ends whilst TeX is storing material that will ultimately contain a page break (most likely if the environment end ends up near the top of a page).

I think the right way to do this is to put a switch in the footer itself, to detect whether or not the environment is active when the page is constructed. I've used the fancyhdr package because it makes changing the footer very easy, but it isn't strictly necessary. Similarly, I've used the geometry package to adjust the page dimensions and move the end of the environment from place to place, but this is just for testing purposes. Finally, note that there is no need to execute \inenvfalse at the end of the environment, because \inenvtrue is local, and the global setting is restored at \end{myenv}.

\documentclass{article}
\usepackage[width=16cm,height=20cm]{geometry}
\usepackage{lipsum} % For dummy text
\usepackage{fancyhdr}

\pagestyle{fancy}
\newif\ifinenv
\inenvfalse
\newcommand\myrfoot{\ifinenv PTO \else Hello! \fi}
\rfoot\myrfoot

\newenvironment{myenv}
{\section*{Environment start!}\inenvtrue}
{\par\medskip\noindent\centering\rule{0.75\textwidth}{2pt}\par\bigskip}
\begin{document}
\lipsum[1-8]
\begin{myenv}
\lipsum[9-16]
\end{myenv}
\lipsum[17-24]
\end{document}
  • Thanks @ian-thompson. This almost fixes it, but one problem remains (see my edits to my original post). Any ideas how to fix this? Thanks, Steffen – Steffen Zschaler Jun 26 '15 at 19:38
  • @SteffenZschaler --- I'll think about this, but won't have time until tomorrow. – Ian Thompson Jun 26 '15 at 19:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.