# How can I change the margins of a page depending on its number with luatex?

For some reasons, I have a 100+ pages LaTeX document that I'm required to format the following way:

• if \thepage = 1 (modulo 4) then margins must be set to 5cm;
• if \thepage = 2 (modulo 4) then margins must be set to 4cm;
• else margins must be set to 2cm.

The geometry package provides macros for setting margins out of the preamble, namely \newgeometry and \restoregeometry.

Now I need a way to insert them automatically at the beginning of every pages.

Unfortunately, this does not seem to be possible due to the way the output routine works (see an example of a non working solution below).

\documentclass{article}
\usepackage{geometry}
\geometry{a4paper, margin = 2cm}
\usepackage{lipsum}

% https://tex.stackexchange.com/questions/34424/how-do-i-calculate-n-modulo-3-in-latex
\def\truncdiv#1#2{((#1-(#2-1)/2)/#2)}%
\def\moduloop#1#2{(#1-\truncdiv{#1}{#2}*#2)}%
\def\modulo#1#2{\number\numexpr\moduloop{#1}{#2}\relax}%

\makeatletter
\let\@@outputpage\@outputpage
\def\@outputpage{%
\ifcase\modulo{\thepage}{4}\relax
% Page 4
\or
% Page 1
\newgeometry{margin = 5cm}%
\or
% Page 2
\newgeometry{margin = 4cm}%
\or
% Page 3
\restoregeometry
\fi
\@@outputpage}
\makeatother

\begin{document}
\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum

\lipsum
\end{document}


I was wondering if luatex and its callbacks on lua side could be of any help with that matter?

• Wouldn't it be easier to adjust the margins after the shipout? – Henri Menke Jan 6 at 0:47
• Also at the point of shipout all the material of the page has already been added to the main vertical list with the margins that were active when the list was first started. So changing the margins just before shipout will not have the intended effect (if it has an effect at all). – Henri Menke Jan 6 at 0:48
• @HenriMenke You're right (see this question). So I was wondering if luatex could manipulate the main vertical list at some stage before shipout. – cjorssen Jan 6 at 14:08
• Not without huge effort. You'd have to somehow reverse the linebreaking and then run the linebreaking again with the new page dimensions. I don't think anyone has ever attempted to do this. I tried it once but failed because you need a solid understanding of TeX's linebreaking algorithm to even get anything usable out of it. – Henri Menke Jan 6 at 19:42
• @HenriMenke I see... And what about changing the margins at the beginning of a new page, when the main vertical list is (nearly) empty? – cjorssen Jan 7 at 10:18

I would be very surprised, and delighted, if somebody could come up with an automated solution.

LaTeX typesets a paragraph at a time. If a paragraph extends from one page to the next the same layout settings are used for the paragraph text on both pages. If you want to change the layout from one page to the next you have to ensure that the end of the first page coincides with the end of a paragraph and the start of the next page is the start of a paragraph (and in between change the layout).

I don't think that this can be done automatically. However, the memoir class includes a macro \parnopar defined as:

\newcommand{\parnopar}{\parfillskip=0pt\par\parskip=0pt\noindent}


which when inserted in the middle of a paragraph creates an "invisible" end/start paragraph. It can be used like this:

Lots of text and now at the bottom of the page
\parnopar
% change the layout (via geometry or changepage packages or ...)
continuation of lots of text


Unfortunately it may take several attempts to insert \parnopar into the optimum place in the paragraph's text.

PS. I find the layout requirements for your document very strange. I'm not at all sure that I would like to read it but presumably it is not up to you.

• Thanks for your efforts (+1). However, this is not what i'm looking for. – cjorssen Jan 9 at 8:51