[Tex/LaTex] Why might \\* (“line break here, but no page break”) not work, and how can one fix this

footnotesline-breakingpage-breaking

One is often taught that "\\ causes a line break which is not a paragraph break" and "the variant \\* additionally prevents a page break".

(I hereby acknowledge user egreg's admonition that "\\* should not be used".)

But \\* often doesn't work! When does \\* not work? How can one fix this?

The following code produces a footnote example and then a body text example. Note that usage of \\* within body text is probably more common.

\documentclass{article}
\usepackage{lipsum}


\begin{document}

\lipsum[1-4]\footnote{
  no asterisk \\ asterisk \\*
  no asterisk \\ asterisk \\*
  no asterisk \\ asterisk \\*
  no asterisk \\ asterisk \\*
  no asterisk \\ asterisk \\*
  % the pagebreak happens here
  last line}
\lipsum[5]


\lipsum[6-8]
\lipsum[2]

Line 1 \\*
  % the pagebreak happens here
Line 2 \\*
Line 3 \\*
Line 4 \\*
Line 5 \\
Line 6

\end{document}

Best Answer

Theory

\\* throws an error if used in vertical mode; in horizontal mode it does the following actions:

\unskip        % remove any preceding spaces
\vadjust{\penalty 10000}% \nobreak in vertical mode after this line
\penalty 10000 % \nobreak in horizontal mode
\hfil          % fill current line
\penalty-10000 % force line break

Thus it looks as if there was a \nobreak in vertical mode between the two lines that prevents a page break.

However, what happens if TeX puts the lines of a paragraph in the vertical list?

  • It inserts interline glue between the boxes (depending on the values of \baselineskip, \lineskiplimit, and \lineskip). Glue after a non-discardable item would constitute a break point.

  • Therefore TeX adds a penalty before the interline glue to control the page breaks. This penalty is \interlinepenalty plus some other penalties depending on the context (\clubpenalty, \widowpenalty, \displaywidowpenalty, \brokenpenalty). Then the break point is this penalty, not the interline glue.

The penalty added via \vadjust is put right after the current line before the interline penalty and interline glue. Thus we have:

\hbox                         % the line
\penalty10000                 % \nobreak via \vadjust
\penalty\interlinepenalty+... % interline penalty
\vskip                        % interline glue
\hbox                         % next line

Thus we have a break point if the interline penalty is smaller than 10000, despite using \\*. If the interline penalty is 10000 or greater, then we do not have a break point anyway with an additional \nobreak of \\* or without.

However, there is one case where \\* actually prevents a line break. Namely "The TeXbook" is not always telling the truth: There is a situation, where TeX does not add a interline glue. It tries to be clever and rationalizes an interlinepenalty of value zero. It probably thinks: interline glue after \hbox – we have a break point; penalty of zero – neither good nor bad, since there is already a break point, we do not need it. In appendix A in answer to exercise 14.26 can be found:

(When the total penalty is zero, as between lines 3 and 4 in this case, no penalty is actually inserted.)

Then \nobreak of \\* kicks in:

\hbox          % line box
\penalty 10000 % of \\* via \vadjust
\vskip <interline glue>
\hbox          % next line

Voila, the page break is surprisingly prevented. Of course this over-optimization is not a "bug" (TeX is per definition bug-free, de facto), let's call it a "design misfeature". ;-)

For illustration, an example for ini-TeX (or plain TeX) for experimenting/studying. Macro \NPB simulates \\*:

% iniTeX or plain TeX
\showboxbreadth=10000
\showboxdepth=10000
\tracingonline=1
\catcode`\{=1
\catcode`\}=2
\font\rm=cmr10
\rm
\baselineskip=12pt
\parfillskip=0pt plus 1fil\relax
\hsize=2in
\vsize=4in

\interlinepenalty=1
\clubpenalty=-1
\widowpenalty=150

\def\NPB{% \\*
  \unskip
  \vadjust{\penalty10000}%
  \penalty10000\hfil\penalty-10000 %
}

\noindent
A\NPB B\NPB C

\scrollmode
\showlists
\end

Console output:

### vertical mode entered at line 0
### current page:
\glue(\topskip) 0.0
\hbox(6.83331+0.0)x144.54, glue set 137.03998fil
.\rm A
.\penalty 10000
.\glue 0.0 plus 1.0fil
.\penalty -10000
.\glue(\rightskip) 0.0
\penalty 10000
\glue(\baselineskip) 5.16669
\hbox(6.83331+0.0)x144.54, glue set 137.45663fil
.\rm B
.\penalty 10000
.\glue 0.0 plus 1.0fil
.\penalty -10000
.\glue(\rightskip) 0.0
\penalty 10000
\penalty 151
\glue(\baselineskip) 5.16669
\hbox(6.83331+0.0)x144.54, glue set 137.31776fil
.\rm C
.\penalty 10000
.\glue(\parfillskip) 0.0 plus 1.0fil
.\glue(\rightskip) 0.0
total height 30.83331
 goal height 289.07999
prevdepth 0.0, prevgraf 3 lines

! OK.
l.28 \showlists

The stuff between the first lines/\hboxes:

\penalty 10000
\glue(\baselineskip) 5.16669

The first penalty comes from \vadjust{\penalty10000}. The interline penalty sums up to zero: \interlinepenalty + \clubpenalty = 1 - 1 = 0

In the second case:

\penalty 10000
\penalty 151
\glue(\baselineskip) 5.16669

the interline penalty is not suppressed: \interlinepenalty + \widowpenalty = 1 + 150 = 151. This penalty allows a page break at this place.

Practice

The following part is inherited from this answer to the more specific question variant.

The problem is the automatically inserted \interlinepenalty. It is usually smaller than 10000 and allows a page break even if it is preceded by a \nobreak (= \penalty10000).

The following uses a workaround. Instead of ending the line, the paragraph is ended. Then the effects of \parskip and \parindent need to be reversed and avoided:

\documentclass{article}
\usepackage{lipsum}

\newcommand*{\NLS}{%
  \par
  \nobreak
  \vspace{-\parskip}%
  \noindent
  \ignorespaces
}

\begin{document}

\lipsum[1-4]\footnote{
  no asterisk \\ asterisk \NLS
  no asterisk \\ asterisk \NLS
  no asterisk \\ asterisk \NLS
  no asterisk \\ asterisk \NLS
  no asterisk \\ asterisk \NLS
  last line}
\lipsum[5]  

\end{document}

page1 page2

However, this is still a workaround and does not provide a correct implementation for \\*. By splitting a paragraph in two paragraphs, up to two interline penalties for the line break before and after the inserted \par are increased by \widowpenalty or \clubpenalty. That is, additional page breaks can be forbidden as a side effect, if the addition by \widowpenalty or \clubpenalty now increases the interline penalty to 10000.

The other case is less problematic: If the line break, where the \par gets inserted, would have get \clubpenalty or \widowpenalty, then this penalty is now lost. But since we forbid a page break already by \nobreak, a loss of an additional penalty does not matter.

Related Question