# Break line only if it's too long, but breaking won't create a new page

I'm the author of the contracard package/class for typesetting calling cards for traditional dances. Currently, if you typeset a particularly long figure on a calling card it wraps like this (look at the 'Ladies left hand star all the way' in B1):

However, the way dance cards work if you're reading down the list your eye needs to jump straight to the beginning of each move. When a line wraps like that, I'd like it to break at the separator (the semi-colon in this case) like so:

Since we're dealing with index cards here and space is rather tight, I would like to return only if doing so would not create a page break anywhere inside the containing environment (the contra environment in my package, or mweenv in the MWE below).

For instance, if you have a really, really, long line that takes up a full line and part of the previous line:

| A1. This is a figure; This is a really, really, long     |
|     figure that takes up an entire line and the next one |


and you break it at the semi-colon:

| A1. This is a figure;
|     This is a really, really, long figure that takes up  |
|     an entire line and the next one |


There's a chance that the new (third) line that's created will cause a new page break. If so, this line should be left alone.

At first I thought this would be as simple as getting the remaining space left on the line, checking if the width of the new moves text was smaller than that, and breaking if not. According to several threads online, however, this information isn't available from TeX's programming layer, so that's a no go.

I then thought I could store the previous moves text in a temporary macro somewhere, compare the whole line to the \columnwidth (this should always be one column, but you never know I guess), and break only if it's longer. This is actually difficult to do because there may be more than two moves on a line, things like semi-colons and commas get inserted at certain counts, etc. This is not unsurmountable, however, it would just require a lot of fiddling and would end up being rather hackish in the end.

As for checking if a page break is created, I couldn't think of a way to do that without saving the number of pages to a temp file and recompiling once for every long line to see if they change. If you have more than a handful of dances this turns into a lot of compiles (if you have 10 dances with 4 long figures that require two recomipiles each that's 80 recompiles).

So my question is simply:

Am I making this overly complicated? Is there some better way to do this, or make the line easier to read in a different way?

A MWE (sort of; the description is probably what's really needed here as a lot of the package-specific stuff that makes this complicated can't be present in a MWE) is presented below:

\documentclass{article}
%
\usepackage[margin=0.5in,top=0.75in,paperwidth=6in,paperheight=4in]{geometry}
\usepackage{ifthen}
%
\newenvironment*{mweenv}{}{}%
\newcounter{textcounter}
\setcounter{textcounter}{1}
\newcommand{\inserttext}[1]{%
\ifthenelse{\value{textcounter}=1}{\par}{}#1%
\ifthenelse{\value{textcounter}=1}{;\ \setcounter{textcounter}{0}}{\setcounter{textcounter}{1}}%
}
%
\begin{document}
%
\begin{mweenv}
\inserttext{This is a long line that wraps around the document}%
\inserttext{A line break should happen at the semi-colon if it would not cause
the page to break as well.}
\inserttext{This is more text}\inserttext{It should not break}%
\end{mweenv}
%
\end{document}


Sorry for the long, rather vague, question. Please let me know if any clarification is needed. (Worth noting, this question is in regards to this specific issue on GitHub)

-
One remark: you could test if the lenght of the argument of \inserttext is greater/equal/less than the \textwidth, by \ifthenelse{\lengthtest{\the\mylength>\textwidth}}{<>}{<>}; it's only an idea that I'm working on but it's progress. – Andrea L. Sep 17 '13 at 19:09
@AndreaL. That won't account for other text on the same line though. As I mentioned in this post, it could be done, but due to all the stuff the package inserts it may be more difficult than it seems. Also, I think \columnwidth would be a better choice here. Normally it will be the same as \textwidth, but on the offchance that a user has multiple columns (for some weird reason) it will still work. Thanks! – Sam Whited Sep 17 '13 at 19:10
One way to implement this inside would be a test on two different strings, like if a after b < \textwidth do... else but it is beyond my abilities, sorry! – Andrea L. Sep 17 '13 at 19:13
What you don't say is what to do if a page break would occur: if line break makes an extra line that would force a page break, if you don't line break presumably the text goes off the margin. It is easy to stop page breaks within a group of lines (just put them in a box) but to keep the text in that box, you have to linit the words or reduce the font or ...? – David Carlisle Sep 17 '13 at 19:33
ah so \looseness will be your friend – David Carlisle Sep 17 '13 at 20:30

Normally you don't need to measure you can just balance the penalties to encourage breaks at the desired point. Also don't allocate the counter inside the environment, just allocate it once and re-use the same counter. (Actually a count register is overkill just for a toggle, but I left it that way here)

\documentclass{article}
%
\usepackage[margin=0.5in,top=0.75in,paperwidth=6in,paperheight=4in]{geometry}
\usepackage{ifthen}
%
\newcounter{textcounter}

\newenvironment*{mweenv}{\raggedright}{}%
\setcounter{textcounter}{1}%
\newcommand{\inserttext}[1]{%
\ifthenelse{\value{textcounter}=1}{\par}{}#1%
\ifthenelse{\value{textcounter}=1}{;\linebreak[2]\space\setcounter{textcounter}{0}}{\setcounter{textcounter}{1}}%
}
%
\begin{document}
%
\begin{mweenv}
\inserttext{This is a long line that wraps around the document}%
\inserttext{A line break should happen at the semi-colon if it would not cause
the page to break as well.}
\inserttext{This is more text}\inserttext{It should not break}%
\end{mweenv}
%
\end{document}

-
Yah, the counter was just part of the quick MWE, a global counter is reused (in a lot of other palces too; it's actually counting beats of music) in the package. Unfortunately the weights don't seem to work; they either break all the time if they're greater than about 2, or none of the time if they're 2 or less. – Sam Whited Sep 17 '13 at 20:14
@SamWhited normally you need to put a glue/penalty/neagtive glue combination, but I simplified it a bit with raggedright and in reality there are 10000 penalty values to play with not just the 4 predefined values in the \linbreak interface. But I didn't do more as I don't understand the page break requirement – David Carlisle Sep 17 '13 at 20:28
I went ahead and marked this answer; thanks! This was fixed partially with info from this answer, and partially with infro from your comment above about \looseness. The original fix is here: github.com/SamWhited/contracard/commit/… – Sam Whited Sep 18 '13 at 14:36