[texhax] Calculate remaining space after a page break and a \penalty of 10000

Wolfgang Lorenz w-lo at gmx.de
Fri Nov 12 14:41:23 CET 2010

Hello Paul,

Am Fri, 12 Nov 2010 00:38:36 +0100
schrieb Paul Isambert <zappathustra at free.fr>:

> Hello Wolfgang,
>
> I think a minimal example showing what you want to do would be
> better, because I for one really can't picture your problem.

Yes, I've thought so. ;-) Well, I'll try.

As I've written, I'm developing a package, that places the lyrics of a
song depending on the space, that's available on a page. In a bbLyrics
environment you first add verses (stanzas) to the current bbLyrics
environment using \bbVerse (see example). The verses are saved in
boxes. With the command \end{bbLyrics}, the magic begins:

First TeX calculates the remaining vertical space on the current page
via \pagegoal - \pagetotal.
Next it tries to assemble the lyrics boxes columnswise to fit the
remaining space. That means, it starts with putting all verses into one
column: (imagine, each number is a box)

------------ current position
1.
2.
3.
4.
------------ page end
5.
6.
7.

This may fail eventually, because the resulting box (the verses are
put in a \vbox which again is put in an \hbox, to cover multiple
columns, but these are mere details...) is too high. Now the number
of verses in the first column is reduced, until the resulting box fits
the remaining space of the current page:

------------ current position
1.    5.
2.    6.
3.    7.
4.
------------ page end

Now the contents would fit the page, but it may be possible, that
some of the vertical space that is needed may be saved, so the number
of verses in the first column is further reduced until some verses
would be left out, since the width of the resulting box must be smaller
than \hsize:

------------ current position
1.  3.  5.
2.  4.  6.

------------ page end

Then, the last version, prior to losing verses is chosen:

------------ current position
1.  4.  7.
2.  5.
3.  6.

------------ page end

Right? This is how it works, if all verses are fitting. Now there may
be a case, that some verses must be put on the next page, or even on a
page beyond:

------------ current position
1.  2.  3.
------------ page end/next page
4.   6.
5.   7.

------------ page end

This is also working. Now here comes the problem. If there is not
enough space left, for putting even one verse on the current page AND
the last box in TeX's main vertical list is a section head I must not
simply \eject the current page, because that would break an unbreakable
\penalty. So I could simply assume, that the whole page is unused,
which would result in a box too high for the current page and TeX would
eject the page BEFORE the section head. This is working in most cases,
since most songs are not that long. But there may be cases (and I've
already had some) where the resulting lyrics box is using up the whole
space. Now TeX stands there with a section head to place and a box in
the main vertical list, which is (again) too high to be placed under

-------------- current position

-------------- page end/next page
1... 5...
2... 6...
3... 7...
---4...------- page end

These cases I want to cover, but I'm at a loss. I have no idea how
to tell TeX to eject the current page, without breaking spaces that are
not to be broken. After such a page break \pagegoal - \pagetotal should
work again.
And I also don't know how to get the height and depth of the recently
contributed content, or the items on TeX's main vertical list. I think,
this way I could calculate the available space correctly.

Now, here's a minimal example, that should only show how the current
version of the package is used:

% example: song.tex
\documentclass{book}
\usepackage{bblyrics}   % <- the package I'm writing on

\begin{document}

% here may be random stuff...

\section{Wenn alle Brünnlein fliesen}
\begin{bbLyrics}{Wenn alle Brunnlein fliesen}
\bbVerse{1.}{%
\hbox{Wenn alle Brünnlein fließen, so muss man trinken}
\hbox{wenn ich mein Schatz nicht rufen darf, tu ich ihm winken,}
\hbox{wenn ich mein Schatz nicht rufen darf,}
\hbox{juja, rufen darf, tu ich ihm winken.}
}
\bbVerse{2.}{%
\hbox{Ja winken mit dem Äugelein und treten auf den Fuß.}
\hbox{Sitzt eine in der Stube drin, die meine werden muss.}
}
\bbVerse{3.}{%
\hbox{Warum sollt sie's nicht werden, ich hab sie ja so gern,}
\hbox{sie hat zwei blaue Äugelein, die leuchten wie zwei Stern.}
}
\bbVerse{4.}{%
\hbox{Sie hat zwei rote Wängelein, sind röter als der Wein,}
\hbox{ein solches Mädel findst du nicht wohl unterm Sonnenschein.}
}
\bbVerse{5.}{%
\hbox{So herzig wie mein Mädele ist keines auf der Welt,}
\hbox{vom Kopf bis zu den Füßele ist alles wohlbestellt.}
}
\end{bbLyrics}
\end{document}
% end of example

> Using \pagetotal and \pagegoal to compute available space is a good
> solution, assuming there is no vertical rubber glue, but I can't see
> what's wrong. And actually I don't understand what "as little
> vertical space" means, nor that "page breaks are left up to TeX",
> since that's the default behavior.
>

I hope the explanation made it all a little clearer. If it helps I also
could send you the current dtx-file. It's not properly documented,
though. AND: I'm sorry, but I'm not really into the TeX terminology
yet. That may make the explanations somewhat hard to read and
understand.

> Best,
> Paul
>

Thank you,
Wolfgang