1

I am trying to automize setting the correct \headheight following Heiko Oberdiek's approach. It is based on the fact that the fancyhdr package usually increases the \headheight as required and saves this value at the very end to a file. The problem is that when using the calc package that value does not seem to change (although the log file still claims "We now make it that large for the rest of the document.").

I know that I could avoid the calc package by using \dimexpr and friends but I need the mathtools package which requires the calc package.

Does anyone have an idea how to get the correct value for \headheight even if the calc package is used?

\documentclass{article}
\usepackage{blindtext}
\usepackage{calc} % this suppresses fancyhdr's feature of increasing \headheight as required


% ===== save header and footer height =====
% https://tex.stackexchange.com/a/117810/120953
\usepackage{atveryend}
\makeatletter
\AtVeryEndDocument{%
    \if@filesw % respect \nofiles
        \begingroup
            % same write register as environment `filecontents` uses
            \chardef\reserved@c=15 %
            \immediate\openout\reserved@c=\jobname.heights\relax
            \immediate\write\reserved@c{%
                \string\setlength{\string\headheight}{\the\headheight}%
            }%
            \immediate\write\reserved@c{%
                \string\setlength{\string\footskip}{\the\footskip}%
            }%
            \immediate\closeout\reserved@c
        \endgroup
        \showthe\headheight
    \fi
}
\makeatother

%\InputIfFileExists{\jobname.heights}{}{} % I have commented this out for testing
\usepackage[
    includehead,
    includefoot,
    showframe,
]{geometry}


% ===== header & footer =====
\usepackage{fancyhdr}
\usepackage{lastpage}
\usepackage{graphicx}
\pagestyle{fancy}

\fancyhead{}
\fancyhead[L]{a rather long header\\ which needs to be broken into several lines}
%\fancyhead[R]{\includegraphics[height=\dimexpr\the\headheight-4.3501pt\relax]{icon}}

\fancyfoot{}
\fancyfoot[R]{page \thepage \ of \pageref{LastPage}}
\fancyfoot[L]{some footer}

\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}


% ===== test document =====
\begin{document}
    \blinddocument
\end{document}
jakun
  • 5,981
  • fancyhdr doesn't usually increase headheight, it just warns, and increases it if the settings are inconsistent with the specified heading. Rather than use this file to save this error-correction it woul dbe more natural just to set up the correct settings using the geometry package in the first place. – David Carlisle Feb 11 '17 at 08:53

1 Answers1

2

fancyhdr uses \global\setlength in one place which isn't supported LaTeX syntax and it doesn't work at all if calc is loaded. It is easy to avoid it in this case just delete \setlength and use a primitive assignment.

\documentclass{article}
\usepackage{blindtext}
\usepackage{calc} % this suppresses fancyhdr's feature of increasing \headheight as required


% ===== save header and footer height =====
% http://tex.stackexchange.com/a/117810/120953
\usepackage{atveryend}
\makeatletter
\AtVeryEndDocument{%
    \if@filesw % respect \nofiles
        \begingroup
            % same write register as environment `filecontents` uses
            \chardef\reserved@c=15 %
            \immediate\openout\reserved@c=\jobname.heights\relax
            \immediate\write\reserved@c{%
                \string\setlength{\string\headheight}{\the\headheight}%
            }%
            \immediate\write\reserved@c{%
                \string\setlength{\string\footskip}{\the\footskip}%
            }%
            \immediate\closeout\reserved@c
        \endgroup
        \showthe\headheight
    \fi
}
\makeatother

%\InputIfFileExists{\jobname.heights}{}{} % I have commented this out for testing
\usepackage[
    includehead,
    includefoot,
    showframe,
]{geometry}


% ===== header & footer =====
\usepackage{fancyhdr}

\makeatletter
\def\@fancyvbox#1#2{\setbox0\vbox{#2}\ifdim\ht0>#1\@fancywarning
  {\string#1 is too small (\the#1): ^^J Make it at least \the\ht0.^^J
    We now make it that large for the rest of the document.^^J
    This may cause the page layout to be inconsistent, however\@gobble}%
  \dimen0=#1\relax
  \global#1\ht0\ht0=\dimen0\fi
  \box0}
\makeatother

\usepackage{lastpage}
\usepackage{graphicx}
\pagestyle{fancy}

\fancyhead{}
\fancyhead[L]{a rather long header\\ which needs to be broken into several lines}
%\fancyhead[R]{\includegraphics[height=\dimexpr\the\headheight-4.3501pt\relax]{icon}}

\fancyfoot{}
\fancyfoot[R]{page \thepage \ of \pageref{LastPage}}
\fancyfoot[L]{some footer}

\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}


% ===== test document =====
\begin{document}
    \blinddocument
\end{document}
David Carlisle
  • 757,742
  • I left your code as it is not relevant to the question but it isn't really safe to use \chardef\reserved@c=15 % it could be overwritten without warning by other writing in the document. It would be better to allocate a \newwrite for this use in the preamble and use that instead of 15, or just use \@auxout and write to the aux file which would simplify things and avoid having to re-input. – David Carlisle Feb 10 '17 at 22:44
  • thank you, I will change that in my code. I had copied that from the answer I have provided a link to. – jakun Feb 10 '17 at 22:59
  • @DavidCarlisle The use of \reserved@c is perfect safe here. See the grouping that restores the meaning of \reserved@c. Also, the code in the group does not contain macro expansion that avoids the problem, that a macro expands to and uses \reserved@c. – Heiko Oberdiek Feb 10 '17 at 23:39
  • 1
    @Heiko it wasn't reserved@c I was worried about but \write15, filecontents is restricted to the beginning of the document so can assume its free but if someone has allocated \newwrites up to 15 then this may or may not trip up depending on the use – David Carlisle Feb 11 '17 at 00:31
  • 1
    @DavidCarlisle it seems to me that the aux file would not be the desired way here because as Joseph Wright states in this answer http://tex.stackexchange.com/a/120978 the aux file is read after the preamble but as far as I understand changing \headheight should happen before loading the geometry package. – jakun Feb 11 '17 at 08:26
  • @jakun that could be fixed (geometry could be delayed) but actually I see no point at all in doing this if you are loading geometry. the fancyhdr setting is just a last-fallback fix if it finds the page settings are inconsistent, so it moans at the user to fix them. I can see it might possibly be useful to save that fix for next time (although why? it's just as easy and a lot more robust to simply set headheight to the value specified) but if you are using geometry just use that package to set consistent settings and then fancyhdr will not complain. – David Carlisle Feb 11 '17 at 08:51
  • @jakun Good point. A solution for using the auxiliary write handle could then look the following way: In \AfterLastShipout code can be added at the end of the .aux file that writes the file for the headheight and gets executed, when the .aux file is read again at the end of the LaTeX job. – Heiko Oberdiek Feb 11 '17 at 09:54