GeneralMaking pages with different widths

LaTeX specific issues not fitting into one of the other forums of this category.
Post Reply
robertjlee
Posts: 17
Joined: Thu Aug 07, 2008 7:51 pm

Making pages with different widths

Post by robertjlee »

Hi there.

I am trying to find a way to make different pages with different printable areas. Changing the printable height between pages is easy but the width is much harder. The problem is that I can't figure out how to tell TeX to re-box the “overflow” output of a page to make it a different width.

Here is a minimal example to demonstrate the problem:

Code: Select all

\documentclass{letter}
\usepackage{lipsum}
\makeatletter

\begin{document}

  % simple output routine to change hsize at each page break
  \output{
    \ifodd\c@page
      \global\hsize=2in
    \else
      \global\hsize=4in
    \fi
    \shipout\expandafter\box\@cclv
    \stepcounter{page}
  }

  % Generate some blurb
  \lipsum[1-50]
\end{document}
This uses the output routine to change \hsize (the page width) between each output page, and it sort-of works; the page width is changed (ignore the first page). But the paragraph spanning page breaks is always set to the width of the page on which it starts, so the end of the paragraph that starts each page has the width of the previous page, not the correct width for that page.

I think I understand why this happens, but I don't know how to fix it. What seems to happen is this:

The page builder works on one paragraph at a time, setting the paragraph to the width of \hsize before working out the appropriate page break to fix the height at \vsize, and shoving the resulting page into box255. But it's already made the rest of the paragraph with the width of the old \hsize, and so it keeps hold of that.

My output routine then runs and ships out box255, changing \hsize (as shown), which tells the page builder to set the width of the next paragraph that it processes.

I want to change this to make it fix the width of the end-paragraph at the top of the page (what I call the “overflow text” from the previous page) to be the same as the rest of the page upon which it appears.

One option is to get the box that contains this text, and change its width myself (eg. by unpacking it into a parbox of appropriate width). This is not ideal as it would cause problems with existing hyphenation points, and possibly with vertical spacing – but I can't even find where the page builder stores its working text (box255 only contains the completed page, not the following paragraph).

Another option might be to record the point of the page break in an auxiliary file somehow, and have LaTeX change the page width at the correct point on the next run (by wrapping the last line in an \@@line, then introducing a \pagebreak, followed by a \par and \noindent). But I don't know if it's even possible to do that without inserting some new command between every glyph in the input document (to check for the page break), and I don't know of any way to identify the position in the input document in order to write it out to the aux file.

Beyond that, it may be possible to modify TeX's page builder (rather than its output routine) in some way. This would seem to be the best solution, in that any explicit penalties and spaces from the input would not yet have been discarded, but I can't find any information on how I might do that.

Any ideas?

Recommended reading 2024:

LaTeXguide.org • LaTeX-Cookbook.net • TikZ.org

NEW: TikZ book now 40% off at Amazon.com for a short time.

User avatar
Juanjo
Posts: 657
Joined: Sat Jan 27, 2007 12:46 am

Making pages with different widths

Post by Juanjo »

You may be interested in the chngpage package. This year the changepage package, which intends to replace chngpage, has been released. The documentation is at the end of the corresponding sty files.
The CTAN lion is an artwork by Duane Bibby. Courtesy of www.ctan.org.
User avatar
localghost
Site Moderator
Posts: 9202
Joined: Fri Feb 02, 2007 12:06 pm

Making pages with different widths

Post by localghost »

An alternative could be to use geometry in combination with gmeometric.


Best regards
Thorsten¹
robertjlee
Posts: 17
Joined: Thu Aug 07, 2008 7:51 pm

Making pages with different widths

Post by robertjlee »

Thanks for your suggestions. I've been trying these packages but so far have had no luck in changing the page width in the middle of a paragraph.

This example illustrates the problems I'm having with changepage:

Code: Select all

\documentclass{letter}
\usepackage{lipsum}
\usepackage{changepage}
\begin{document}
  %\changepage{4in}{4in}{0in}{0in}{0in}{0in}{0in}{0in}{0in}
  \lipsum[1-10]
    \changepage{2in}{2in}{0in}{0in}{0in}{0in}{0in}{0in}{0in}
  \lipsum[11-20]
    \changepage{4in}{4in}{0in}{0in}{0in}{0in}{0in}{0in}{0in}
  \lipsum[21-30]
    \changepage{2in}{2in}{0in}{0in}{0in}{0in}{0in}{0in}{0in}
  \lipsum[31-40]
    \changepage{4in}{4in}{0in}{0in}{0in}{0in}{0in}{0in}{0in}
\end{document}
The output on the top of page 3 shows a narrow overflow paragraph followed by full paragraphs of the correct width. And if you uncomment the first \changepage, all the text is set with the same width for some reason.

I haven't had any luck with the gmeometric package so far either. When I put it in the page text, it seems to produce the right margins but doesn't change \hsize (the width of the text), resulting in all text the same width but some of it pushed sideways off the page. I thought I might have more luck by putting a call to geometry in the output routine (which is called after the “overflow” paragraph is built) but then it just errors. I am also worried by the documentation saying that I am better to put a \clearpage or similar after each \geometry; this is obviously not possible in the normal case where the page breaks mid-paragraph.

Code: Select all

\documentclass{letter}
\usepackage{lipsum}
\usepackage{gmeometric}

\begin{document}
%%   \output{
%%     \makeatletter
%%     \ifodd\c@page
%%        \makeatother
%%        \geometry{hmargin=0in}
%%     \else
%%        \makeatother
%%       \geometry{hmargin=4in}
%%     \fi
%%     \makeatletter
%%     \shipout\expandafter\box\@cclv
%%     \makeatother
%%     \stepcounter{page}
%%   }
%%   \lipsum[1-50]

  \lipsum[1-5]
  \geometry{hmargin=0in,centering=true}
  \lipsum[6-10]
  \geometry{hmargin=4in,centering=true}
  \lipsum[1-5]
  \geometry{hmargin=0in,centering=true}
  \lipsum[6-10]
  \geometry{hmargin=4in,centering=true}
  \lipsum[1-5]
  \geometry{hmargin=0in,centering=true}
  \lipsum[6-10]
  \geometry{hmargin=4in,centering=true}
  \lipsum[1-5]
  \geometry{hmargin=0in,centering=true}
  \lipsum[6-10]
  \geometry{hmargin=4in,centering=true}
\end{document}
I don't know if there is a better way to use these packages. They seem to be designed to change the output document when a particular position in the input document is reached, rather than doing anything on a page-by-page basis. Or am I approaching this in the wrong way?
robertjlee
Posts: 17
Joined: Thu Aug 07, 2008 7:51 pm

Making pages with different widths

Post by robertjlee »

Is it possible to tell LaTeX not to break a page except at a paragraph break (i.e. only break pages at the end of a paragraph)?

I've still had no luck in trying to get this to work by changing the page width inside a paragraph. According to a friend of mine, I've accidentally hit one of the fundamental limitations of TeX identified by Knuth, in that you can't change the text width between pages, only between paragraphs, because paragraphs are built asynchronously before pages are built. I haven't found any way to confirm this — I remember reading Knuth's limitations of TeX online, but now I can't find them.

I still think that there may be a way around this, if I can use code similar to multicol's rebalancing mechanism to force TeX to tear apart the end of the paragraph at the top of the page and lay it out again. This sounds quite hard to get working, and I think I'd rather concentrate on other things just now.

So, as a stop-gap measure, I'm trying to force TeX to only break pages at paragraph breaks.

My first thought was to inject a pagebreak hint in between each paragraph. Here's my minimal example:

Code: Select all

\documentclass{article}
\usepackage{lipsum}

\newcommand{\lip}[1]{\section{#1}\lipsum[0-20]\pagebreak}

\begin{document}
  \lip{No pagebreak}
  \def \par {\pagebreak[3] \endgraf}
  \lip{pagebreak 3}
  \def \par {\pagebreak[4] \endgraf}
  \lip{pagebreak 4}
  \def \par {\pagebreak \endgraf}
  \lip{pagebreak}
\end{document}
The problem here is that \pagebreak[3] (and [1] and [2] for that matter) will cause LaTeX to break the last paragraph on the first page, while \pagebreak[4] will cause it to break the page between each and every paragraph.

I guess I could fiddle around with some sort of tolerance setting and get something that would work for this lipsum text, but I would like to know that it would work properly regardless of what text I throw at it (at least if it's not taken to extremes, eg a paragraph longer than a page).

Is there some other way I could achieve this? I want to have the last full paragraph always be at the end of the page so that there are no page breaks between paragraphs, and (ultimately) the next page could be set with a different \hsize?

My second idea was to put each paragraph in a samepage environment by modifying \par, but I haven't got that to work at all. With plain text, I just get the pagebreak in the middle of a paragraph (apparently inside the samepage environment?!):

Code: Select all

\documentclass{article}
\usepackage{lipsum}

\newenvironment{pagebreakatpara}{
  \begin{samepage}
  \gdef\par{
    \end{samepage}
    \endgraf
    \begin{samepage}
  }
}{
    \end{samepage}
    \gdef\par{\endgraf}
}

\begin{document}
  \begin{pagebreakatpara}
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.

    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.

    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.

    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.

    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.

    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.
    The quick brown fox jumps over the lazy dog.

  \end{pagebreakatpara}%
\end{document}
And replacing the text with a lipsum, I get an error:

Code: Select all

\documentclass{article}
\usepackage{lipsum}

\newenvironment{pagebreakatpara}{
  \begin{samepage}
  \gdef\par{
    \end{samepage}
    \endgraf
    \begin{samepage}
  }
}{
    \end{samepage}
    \gdef\par{\endgraf}
}

\begin{document}
  \begin{pagebreakatpara}
    \lipsum
  \end{pagebreakatpara}%
\end{document}
! Undefined control sequence.
\lips@dolipsum ...m \value {lips@count}<\lips@max
\relax \addtocounter {lips...
l.19 \end
{pagebreakatpara}%
! Missing number, treated as zero.
Any help as to what I am doing wrong, or alternative approaches I could take, would be most appreciated!

Thanks in advance,

—Robert J Lee
User avatar
Juanjo
Posts: 657
Joined: Sat Jan 27, 2007 12:46 am

Re: Making pages with different widths

Post by Juanjo »

I can't really help in solving your problem. However, it seems to me that you are not facing it with the right tools. For example, you are playing with samepage as it were an environment. In fact, it is a LaTeX2.09 command no longer supported in LaTeX2e (although it still works for compatibility). See Lamport's guide p. 229 and the source2e document p. 344. Likewise, you try redefinitions of \par (having side effects for lipsum, for example), involving only high level LaTeX commands. Without a good knowledge on how TeX builds and breaks paragraphs and without the use of low level TeX and LaTeX commands, I find quite difficult to achieve your goals.
The CTAN lion is an artwork by Duane Bibby. Courtesy of www.ctan.org.
Post Reply