diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/fancyhdr/fancyhdr.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/fancyhdr/fancyhdr.dtx | 1122 |
1 files changed, 835 insertions, 287 deletions
diff --git a/Master/texmf-dist/source/latex/fancyhdr/fancyhdr.dtx b/Master/texmf-dist/source/latex/fancyhdr/fancyhdr.dtx index f0666afc42b..60aa3469b23 100644 --- a/Master/texmf-dist/source/latex/fancyhdr/fancyhdr.dtx +++ b/Master/texmf-dist/source/latex/fancyhdr/fancyhdr.dtx @@ -22,11 +22,13 @@ % % \begin{macrocode} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\NeedsTeXFormat{LaTeX2e} +% \changes{V5.2}{2025/01/15}{Require \LaTeX{} version at least 2018-04-01.} +%<fancyhdr|extramarks|extramarks-v4>\NeedsTeXFormat{LaTeX2e}[2018-04-01] +%<fancyheadings>\NeedsTeXFormat{LaTeX2e} %<fancyhdr>\ProvidesPackage{fancyhdr}% %<fancyheadings>\ProvidesPackage{fancyheadings} %<extramarks|extramarks-v4>\ProvidesPackage{extramarks} -%<fancyhdr|extramarks> [2025/01/07 v5.1.1 +%<fancyhdr|extramarks> [2025/02/07 v5.2 %<fancyhdr> Extensive control of page headers and footers]% %<fancyheadings> [2022/11/09 v4.1 %<fancyheadings> Legacy package to call fancyhdr] @@ -76,7 +78,7 @@ \usepackage{subcaption} \usepackage[colorlinks,linktocpage]{hyperref} \usepackage{ifthen} -\usepackage{xparse} +\ifdefined\NewDocumentCommand\else\usepackage{xparse}\fi \usepackage{enumitem} \setlist{itemsep=1pt} \usepackage{fancyhdr} @@ -134,14 +136,48 @@ } % Our own page style: +\NewMarkClass{whichpage} +\newcommand\whichpage{} + +\newcommand\checkposinpage{ + \ifthenelse{\lengthtest{\pagetotal<4\baselineskip}}% + {\renewcommand{\whichpage}{top\thepage}}% + {\renewcommand{\whichpage}{\thepage}}% +} + \pagestyle{fancy} \setlength{\headheight}{16.0pt} \addtolength{\headwidth}{\marginparsep} \addtolength{\headwidth}{0.5\marginparwidth} +\newcommand\normalheader{% + \ifthenelse{\equal{\FirstMark{whichpage}}{\thepage}}% + {\TopMark{2e-right-nonempty}}% + % whichpage != page + {\IfMarksEqualTF{whichpage}{top}{first}% + {\TopMark{2e-right-nonempty}}% no mark on this page + {\rightmark}% title at/near the top of the page + }% +} + \fancyhf{} -\fancyhead[L]{\rightmark} +\fancyhead[L]{\normalheader} \fancyhead[R]{\textbf{\thepage}} -\renewcommand{\sectionmark}[1]{\markright{\thesection\quad#1}} + +\AddToHook{cmd/section/before}{\checkposinpage} +\AddToHook{cmd/subsection/before}{\checkposinpage} + +\newcommand\setmarks[1]{% + \InsertMark{whichpage}{\whichpage}% + \markright{#1}% +} + +\renewcommand{\sectionmark}[1]{% + \setmarks{\thesection\quad#1}% +}% + +\renewcommand{\subsectionmark}[1]{% + \setmarks{\thesubsection\quad#1}% +}% % Page style for demonstrating struts, \headruleskip and \footruleskip. @@ -169,7 +205,7 @@ \fancyhead[L]{% \ifthenelse{\value{page}=\getpagerefnumber{showstruts}}% {\strutheader}% - {\rightmark}% + {\normalheader}% } \fancyfoot[L]{% \ifthenelse{\value{page}=\getpagerefnumber{showstruts}}% @@ -188,6 +224,12 @@ } } +\fancypagestyle{copyright}{% + \fancyfoot[L]{% + Copyright \copyright~1994-2025 by Pieter van Oostrum. Distributed under the \LaTeX{}\\ + Project Public License (LPPL), see \url{http://www.latex-project.org/lppl.txt}} +} + \newcommand\exampleindex{} \def\exampleindex#1#2#3\relax{% \ifx \relax#2\relax \index{Example 0#1=Example #1}\else \index{Example #1#2#3}\fi} @@ -378,7 +420,7 @@ % \maketitle % \begin{abstract} % This document describes how to customize the page layout of your LaTeX -% documents, i.e., how to change page margings and sizes, +% documents, i.e., how to change page margins and sizes, % headers and footers, and the % proper placement of figures and tables (collectively called floats) on % the page. @@ -389,11 +431,13 @@ % the \pkg{fancyhdr} and \pkg{extramarks} packages (except % for the changes mentioned in sections~\ref{sec:version-4} and % \ref{sec:version-5}). -% % \end{abstract} % % \tableofcontents -% \markright{Contents} +% \thispagestyle{copyright} +% \newpage +% \checkposinpage +% \setmarks{Introduction} % % \begin{documentation} % \part{Introduction} @@ -404,8 +448,6 @@ % the user commands of the \pkg{fancyhdr} and \pkg{extramarks} packages. % % Part II contains elaborate documentation on page layout in \LaTeX. -% This used to be the complete documentation of \pkg{fancyhdr} and -% \pkg{extramarks} for several years. % % Part III contains Questions and Answers. % @@ -496,14 +538,19 @@ % % \begin{function}{\fancyheadwidth,\fancyfootwidth,\fancyhfwidth} % \begin{syntax} -% \cmd{\fancyheadwidth}\oarg{places}\marg{length} \\ -% \cmd{\fancyfootwidth}\oarg{places}\marg{length} \\ -% \cmd{\fancyhfwidth}\oarg{places}\marg{length} +% \cmd{\fancyheadwidth}\oarg{places}\oarg{alignment}\marg{length} \\ +% \cmd{\fancyfootwidth}\oarg{places}\oarg{alignment}\marg{length} \\ +% \cmd{\fancyhfwidth}\oarg{places}\oarg{alignment}\marg{length} \\[1ex] +% \cmd{\fancyheadwidth}*\oarg{places}\oarg{alignment}\marg{length} \\ +% \cmd{\fancyfootwidth}*\oarg{places}\oarg{alignment}\marg{length} \\ +% \cmd{\fancyhfwidth}*\oarg{places}\oarg{alignment}\marg{length} % \end{syntax} -% These define widths for the header and footer fields. The fields will -% be typeset in a \cs{parbox} of this width, which can be different for -% each \emph{place}. If the width of a field is not specified, it -% defaults to \cs{headwidth}, which may cause them to overlap. See +% These define widths and optionally the alignments for the header and +% footer fields. The fields will be typeset in a \cs{parbox} of this +% width, which can be different for each \emph{place}. If the width of a +% field is not specified, it defaults to \cs{headwidth}, which may cause +% them to overlap. The alignment option and the \texttt{*} version are +% available in \pkg{fancyhdr} version 5.2 and later. See % section~\ref{sec:field-width} for more details. % \end{function} % @@ -768,10 +815,6 @@ % \begin{verbatim} % \usepackage{extramarks}[=v4] % \end{verbatim} -% or if you have an old \LaTeX{} system where the above doesn't work -% \begin{verbatim} -% \usepackage{extramarks-v4} -% \end{verbatim} % Please note that in that case the % \cs{topleftxmark}, \cs{toprightxmark} and \cs{topxmark} commands may % give you unexpected results. @@ -816,7 +859,7 @@ % \LaTeX{} parameter but it has a different use (namely the indentation of % lists). % \item Most of the parameters should not be changed in the middle of a -% document. Some changes might work at a pagebreak. If you want to change +% document. Some changes might work at a page break. If you want to change % the height of a single page, you can use the \cs{enlargethispage} % command. % \end{enumerate} @@ -1200,24 +1243,39 @@ % now you can override this with the commands \cs{fancyheadwidth}, % \cs{fancyfootwidth} or \cs{fancyhfwidth}. These work exactly like the % \cs{fancyhead} etc. commands but instead of a header/footer value they -% have a \meta{length} as parameter. +% have a \meta{length} and an optional alignment as parameters. % % \begin{syntax} -% \cmd{\fancyheadwidth}\oarg{places}\marg{length} \\ -% \cmd{\fancyfootwidth}\oarg{places}\marg{length} \\ -% \cmd{\fancyhfwidth}\oarg{places}\marg{length} +% \cmd{\fancyheadwidth}\oarg{places}\oarg{alignment}\marg{length} \\ +% \cmd{\fancyfootwidth}\oarg{places}\oarg{alignment}\marg{length} \\ +% \cmd{\fancyhfwidth}\oarg{places}\oarg{alignment}\marg{length} \\[1ex] +% \cmd{\fancyheadwidth}*\oarg{places}\oarg{alignment}\marg{length} \\ +% \cmd{\fancyfootwidth}*\oarg{places}\oarg{alignment}\marg{length} \\ +% \cmd{\fancyhfwidth}*\oarg{places}\oarg{alignment}\marg{length} % \end{syntax} % Field widths that are not specified default to \cs{headwidth}. % -% NOTE: The widths will be stored as expressions, not as calculated -% values. The values will be calculated when the header or footer is -% constructed. So they can change, for example when different pages have -% different \cs{headwidth} and you use e.g., \texttt{0.3\cs{headwidth}} -% or another expression with a `variable' as value. Note, however, that -% at definition time, the width is assigned to a temporary length -% variable, to check if it is a legal \meta{length}. So any variables -% used in it should have a value, although this may be different from -% the value at its final use. +% NOTE: In the non-\texttt{*} versions of these commands, the widths +% will be stored as expressions, not as calculated values. The values +% will be calculated when the header or footer is constructed. So they +% can change, for example when different pages have different +% \cs{headwidth} and you use e.g., \texttt{0.3\cs{headwidth}} or another +% expression with a `variable' as value. Note, however, that at +% definition time, the width is assigned to a temporary length variable, +% to check if it is a legal \meta{length}. So any variables used in it +% should have a value, although this may be different from the value at +% its final use. +% +% In the \texttt{*} versions of these commands, the width will be +% calculated at the call of the command, and the calculated value will +% be stored. So for example if you use an expression like +% `\texttt{0.4\cs{headwidth}}', and \cs{headwidth} is 10~cm, the value +% `4~cm' will be stored. If then then later \cs{headwidth} is changed to +% 15~cm when the header or footer is constructed, the value +% used for the field will still be 4~cm, which no longer is +% `\texttt{0.4\cs{headwidth}}'. With the non-\texttt{*} version, +% however, the value `6~cm' will be used, i.e. 0.4 of the then current +% \cs{headwidth}. % % The fields are typeset in a \cs{parbox} with the specified width or % the default \cs{headwidth}. It is still possible to get overlaps if @@ -1331,6 +1389,52 @@ % } % \smallskip % +% The \meta{alignment} optional parameter consists of two letters: a +% vertical alignment, which indicates where the baseline of the +% \cs{parbox} will be, followed by a horizontal alignment that specifies +% how the lines will be positioned horizontally in the \cs{parbox}. The +% alignment option is available in \pkg{fancyhdr} version 5.2 and later. +% \\[1ex] +% The possibilities for the vertical alignment are: +% \begin{description}[font=\texttt] +% \item[T] The baseline of the \cs{parbox} is on the top of the first line, i.e., just +% where the top of the tallest character or item in the line is. +% \item[t] The baseline of the \cs{parbox} is the baseline of the first line. +% \item[c] The baseline of the \cs{parbox} is on the vertical center +% of the \cs{parbox}. +% \item[b] The baseline of the \cs{parbox} is the baseline of the last line. +% \item[B] The baseline of the \cs{parbox} is on the bottom of the last line, i.e., just +% where the bottom of the deepest character or item in the line is. +% \item[-] Use the default vertical alignment. +% \end{description} +% The letters are the same as the vertical alignment in \cs{fancyhdrbox} +% (see section~\ref{sec:fancyhdrbox} for examples). The \texttt{t}, +% \texttt{c} and \texttt{b} are the standard options for \cs{parbox}. +% \\[1ex] +% The horizontal alignment can be: +% \begin{description}[font=\texttt] +% \item[l] left aligned +% \item[c] centered +% \item[r] right aligned +% \item[j] fully justified +% \end{description} +% These are the same as the horizontal alignment in \cs{fancyhdrbox}, +% except that the \texttt{j} option is extra. This one gives the default +% behavior in a \cs{parbox}. +% +% The default for the vertical alignment is \texttt{b} for a header +% field, and \texttt{t} for a footer field. The default for the +% horizontal alignment is \texttt{l} for an \texttt{L} field, \texttt{c} +% for a \texttt{C} field, \texttt{r} for an \texttt{R} field. +% +% Please note that a single \texttt{c} as the alignment counts as a +% vertical alignment, and the horizontal alignment will then be the +% default. If you want to specify only the horizontal alignment and take +% the default for the vertical alignment, specify the vertical alignment +% as \texttt{-}. For the horizontal alignment just omit it to get the default. +% +% See section~\ref{sec:with-fancyheadwidth} for examples. +% % \textbf{NOTE:} The \cs{fancyheadwidth}, % \cs{fancyfootwidth} and \cs{fancyhfwidth} commands are still % experimental. This means that they have not been thoroughly tested, so @@ -1346,7 +1450,7 @@ % package by Alexander I. Rozhenko.}. % % The fields in a fancy header and footer are prepared using \cs{parbox} -% command. So, you can use multiline fields. In the header, they are +% command. So, you can use multi-line fields. In the header, they are % aligned to the bottom line, but, in the footer, they are aligned to % the top line. The maximum width of every field is by default equal to the % \cs{headwidth} (unless changed by the commands \cs{fancyheadwidth}, @@ -1410,11 +1514,11 @@ % document. Then \cs{linewidth} will be the width of the box or text in % which it is used. % -% \section{The \cs{fancyhdrbox} command} +% \section{The \Cmd{fancyhdrbox} command} % \label{sec:fancyhdrbox} % % The \cs{fancyhdrbox} command can be used to align multi-line header -% and footer fields and, for example, images. It is modeled after the +% and footer fields and, for example, images. It is modelled after the % \PKGindex{makecell} % \pkg{makecell} package by Olga Lapko, but it is a bit simplified, and also has extra % vertical alignments \texttt{T} and \texttt{B}. And the vertical @@ -1468,7 +1572,7 @@ % % The second optional parameter, \meta{width}, specifies the width of % the box. If this is not given, the box has its ``natural'' width, -% detemined by its contents. With the \meta{width} parameter, the width +% determined by its contents. With the \meta{width} parameter, the width % of the box is fixed to this value, independent of the contents. Note % that there will be no automatic line breaking of the lines if they % don't fit in the specified width. If a line is too long it will just @@ -1594,7 +1698,7 @@ % % The first box has an explicit \texttt{[c]} positioning, which implies % both vertical and horizontal centering. The second one uses the -% default positioning (i.e., it is not explicitely specified), which make +% default positioning (i.e., it is not explicitly specified), which make % it \texttt{[cl]}, i.e., horizontally left aligned. % % \begin{code} @@ -1821,6 +1925,7 @@ % \begin{itemize} % \item The header and footer fields in all variants (EO,LRC,HF) (12 items) % \item The header and footer field widths in all variants (EO,LRC,HF) (12 items) +% \item The header and footer field alignments in all variants (EO,LRC,HF) (12 items) % \item The header and footer offsets (EO,LR,HF) (8 items), see % section~\ref{sec:book-examples} and~\ref{sec:headwidth} % \item The header and footer init values (2 items), see section~\ref{sec:curpagestyle} @@ -1916,7 +2021,7 @@ % header and/or footer definitions, use % \Cmd{fancypagestyle*\{fancydefault\}}\marg{your definitions}. % -%\subsection{The \cs{fancypagestyleassign} command} +%\subsection{The \Cmd{fancypagestyleassign} command} % \label{sec:fancypagestyleassign} % % The \cs{fancypagestyleassign} command is only available in @@ -1951,7 +2056,7 @@ % \end{raggedright} % % \cs{fancypagestyleassign} comes especially handy if you want to -% temporaryly redefine a page style, and later to restore it to its +% temporarily redefine a page style, and later to restore it to its % original value. For example, if we have a page style % \texttt{special}, and we want temporarily to define page style % \texttt{plain} to be equal to this, but later to restore it to its @@ -2374,7 +2479,7 @@ % \fancyhead[R]{\leftmark\\\rightmark} % \end{example} % -% Note that if you want to use header or footer layouts with multiline +% Note that if you want to use header or footer layouts with multi-line % parts that have to be aligned, you can do this with % the \cs{fancyhdrbox} command. See section~\ref{sec:fancyhdrbox}. % @@ -2486,7 +2591,7 @@ % parameter \cs{footruleskip}. It % defines the distance between the decorative line in the footer and the top % of the footer text line. By default it is set to 30\% of the normal line -% distance. You may want to adjust it if you use unusally large or small +% distance. You may want to adjust it if you use unusually large or small % fonts in the footer. Change it with \cs{renewcommand}. % % You can also change the distance between the baseline of the header text and the @@ -2664,7 +2769,7 @@ % in the neighborhood of your header/footer definitions, unless you % already use such an \texttt{\ldots offset} command, of course. % \vspace{\baselineskip} -% For the second example, we take the \ams/-\LaTeX{} book\footnote{George Gratzer, +% For the second example, we take the \ams/-\LaTeX{} book\footnote{George Grätzer, % \textit{Math into LaTeX, An Introduction to \LaTeX{} and \ams/-\LaTeX}, Birkhauser, Boston.}. % % Chapter pages have no headers or footers. So we declare @@ -2735,8 +2840,8 @@ % \end{example} % % -%\section{Summary of \cs{headwidth} calculation} -%\label{sec:headwidth} +% \section{Summary of \Cmd{headwidth} calculation} +% \label{sec:headwidth} % % Here is a summary of the calculation of the widths of headers and % footers, as illustrated in \smartref{sec:headwidth}{sec:book-examples}. @@ -2750,7 +2855,7 @@ % for \cs{headwidth} is \cs{textwidth}. This is used for the width of % both the header and the footer. It is possible to change the value of % \cs{headwidth}, for example with \cs{setlength} or \cs{addtolength}. -% The excess or deficit will be applied to the right for a onesided +% The excess or deficit will be applied to the right for a one-sided % document, and for a two-sided document to the right on odd pages and to % the left on even pages. The header and the footer will have the same % width, \cs{headwidth}. @@ -2906,7 +3011,7 @@ % % In technical documentation very often page numbers are used of the form % 2-10 where the first number is the chapter number and the second is the -% pagenumber relative to the chapter. Sometimes section is used rather than +% page number relative to the chapter. Sometimes section is used rather than % chapter. The package \PKGindex{chappg}\pkg{chappg} can be used to get this format. % % Basically this package redefines \cs{thepage} as @@ -2938,7 +3043,7 @@ % % In the frontmatter of your document (for example the Table of % Contents) there will be no chapter numbers. Therefore a simple page -% number will be used there. This may be confusing, so you might prefer to use roman pagenumbers +% number will be used there. This may be confusing, so you might prefer to use roman page numbers % in the front matter. Do this by using \verb+\pagenumbering{roman}+ in % the beginning of the document and \verb+pagenumbering{bychapter}+ % after the first \cs{chapter} command. If you want to do it before the @@ -3850,7 +3955,7 @@ % ``Continued'' information like in the previous examples. The % \cs{extramarks} contain essentially the same information as in the % previous examples, just formatted a little differently. -% But the \cs{...leftxmark} is not put in the header, but is eventually used as +% But the \Cmd{...leftxmark} is not put in the header, but is eventually used as % the argument in \cs{afterpage} so that it will appear at the top of the % next page body. This is also the reason for the \verb|\\[1ex]|, to % separate it from the rest of the page text. @@ -3954,7 +4059,7 @@ % fixed text as argument for \cs{afterpage} but by using a macro \cs{APcommand} % as argument. When we want to stop the sequence of \cs{afterpage} calls, % we make this macro empty. To get a proper timing we reset this macro -% in the righthand footer field when this is empty, which indicates that +% in the right-hand footer field when this is empty, which indicates that % we are outside of a `Continued' block. % % We must then take care of restarting the \cs{afterpage} sequence when @@ -4097,7 +4202,7 @@ % styles, especially if you also want the first page of these to have % a special page style. % -% Supose you have defined a special page style \texttt{tocstyle} for the +% Suppose you have defined a special page style \texttt{tocstyle} for the % Table of contents. The Table of contents is generated by the command % \cs{tableofcontents} and it can be several pages long, all generated % by this simple command. So if you want this to have the page style @@ -4114,7 +4219,7 @@ % % If we use a chapter based documentclass, like the standard classes % \pkg{report} and \pkg{book}, with this setup the first page of the Table -% of Contents, and similar parts of the document will stil use the +% of Contents, and similar parts of the document will still use the % \texttt{plain} page style. Usually this is the best choice, but there % may be cases where you want these also to use the \texttt{tocstyle} % page style (or another special page style). The \texttt{plain} page @@ -4270,7 +4375,7 @@ % the page number and that we use the \pkg{graphics} or \pkg{graphicx} package. % \PKGindex{graphics} % \PKGindex{graphicx} -% To put the movie in the righthandside bottom corner the following will work: +% To put the movie in the right-hand side bottom corner the following will work: % % \Example{30} % \begin{example} @@ -4306,7 +4411,7 @@ % requires some hand-tuning to get the blobs nicely spaced out vertically. % For the application that I originally designed this for, there were 12 sections, % so I made the blobs -% 18 mm apart, i.e., 9~mm blob separated by 9~mm whitespace. In order to avoid +% 18 mm apart, i.e., 9~mm blob separated by 9~mm white space. In order to avoid % calculations they are set in a \texttt{picture} environment with the % \cs{unitlength} set to 18~mm. Page numbers are set in the headers at the % outer sides, and the blobs are attached to these. In this example the @@ -4547,7 +4652,7 @@ % If in spite of all your attempts \LaTeX{} still moves your floats to the end % of the document or the end of a chapter, you can insert a \cs{clearpage} % command. This will start a new page and insert all pending floats before -% continuing. If it is undesirable to have a pagebreak you can use the +% continuing. If it is undesirable to have a page break you can use the % \pkg{afterpage} package and the following command: % \PKGindex{afterpage}\CmdIndex{afterpage}\CmdIndex{clearpage}% % \begin{code} @@ -4568,7 +4673,7 @@ % in the preamble. Now you will be able to % specify \texttt{[H]} as the position parameter, which will mean ``HERE % and only HERE''. This may cause an unwanted page break however. -% If you want to avoid the unwanted pagebreak, i.e., let +% If you want to avoid the unwanted page break, i.e., let % \LaTeX{} move the float only if it doesn't fit on the page, then use the % \pkg{afterpage} package with: % \PKGindex{afterpage}\CmdIndex{afterpage}\CmdIndex{clearpage}% @@ -4598,7 +4703,7 @@ % \\Also on Stackexchange:\\ % \url{https://tex.stackexchange.com/questions/39017/how-to-influence-the-position-of-float-environments-like-figure-and-table-in-lat}}. % -% \section{Multipage Floats} +% \section{Multi-page Floats} % % \LaTeX's floats cannot be split across pages. Sometimes, however, you want % to have a table or figure that doesn't fit on one page. The easiest way is @@ -4676,14 +4781,14 @@ % \begin{figure}[!htbp] % \centering % \includegraphics[scale=0.5]{example-image-a} -% \caption[This is a multipart figure] % For the list of figures -% {This is a multipart figure (a)} +% \caption[This is a multi-part figure] % For the list of figures +% {This is a multi-part figure (a)} % \label{fig:first} % \end{figure} % \begin{figure}[!htbp] % \centering % \includegraphics[scale=0.5]{example-image-b} -% \fakecaption{fig:first}{This is a multipart figure (b)} +% \fakecaption{fig:first}{This is a multi-part figure (b)} % \end{figure} % . . . % \end{example} @@ -4706,14 +4811,14 @@ % \begin{figure}[!htbp] % \centering % \includegraphics[scale=0.5]{example-image-a} -% \caption[This is a multipart figure] % For the list of figures -% {This is a multipart figure (a)} +% \caption[This is a multi-part figure] % For the list of figures +% {This is a multi-part figure (a)} % \label{fig:second} % \end{figure} % \begin{figure}[!htbp] % \centering % \includegraphics[scale=0.5]{example-image-b} -% \fakecaption{fig:second}{This is a multipart figure (b)} +% \fakecaption{fig:second}{This is a multi-part figure (b)} % . . . % } % . . . @@ -4721,7 +4826,7 @@ % \end{example} % \CmdIndex{afterpage} % -% If you want your multipage figure to start at a lefthand-side +% If you want your multi-page figure to start at a left-hand side % (even-numbered) page you can use a test in the \cs{afterpage} command % (using the \PKGindex{ifthen}\pkg{ifthen} package): % \CmdIndex{afterpage} @@ -4734,7 +4839,7 @@ % \end{code} % % If there are too many floats on the skipped page, this may still fail to -% start your multipage figure on an even page, however. +% start your multi-page figure on an even page, however. % % But if there is enough space left on a page, some of the text will go % between the figures. Also, if there is still some figure part of a @@ -4763,14 +4868,14 @@ % \begin{figure}[p] % \centering % \includegraphics[scale=0.5]{example-image-a} -% \caption[This is a multipart figure] % For the list of figures -% {This is a multipart figure (a)} +% \caption[This is a multi-part figure] % For the list of figures +% {This is a multi-part figure (a)} % \label{fig:third} % \end{figure} % \begin{figure}[p] % \centering % \includegraphics[scale=0.5]{example-image-b} -% \fakecaption{fig:third}{This is a multipart figure (b)} +% \fakecaption{fig:third}{This is a multi-part figure (b)} % . . . % } % . . . @@ -5010,7 +5115,7 @@ % \item Updated contact information. % \item Restore \cs{newtoks}\cs{@temptokenb} % \end{itemize} -% \item Version 3.10, Januari 25, 2019 +% \item Version 3.10, January 25, 2019 % \begin{itemize} % \item Distribution based on fancydhr.dtx. % \item Use \cs{f@nch@ifundefined} instead of \cs{ifx} or \cs{@ifundefined}. @@ -5157,16 +5262,20 @@ % \end{itemize} % \item Version 5.1.1, Jan 7, 2025 % \begin{itemize} -% \item Bugfix in save, clear and restore paragraph hooks in headers/footers. +% \item Bug fix in save, clear and restore paragraph hooks in headers/footers. +% \end{itemize} +% \item Version 5.2, Jan 14-Feb 7, 2025 +% \begin{itemize} +% \item Use official interface to reset the paragraph hooks. +% \item Conditionally require package \pkg{xparse} in fancyhdr. +% \item Require \LaTeX{} version 2018-04-01 or later, +% \item therefore cleanup some pre-2018 code. +% \item Implement \cs{fancyhfwidth} etc. \meta{alignment} option and +% the \texttt{*} form of these commands. +% \item Documentation updates. % \end{itemize} % \end{itemize} % -% -% -% \StopEventually{% -% \PrintChanges -% \PrintIndex} -% % \part{Questions \& Answers} % % This part contains answers to questions that have been emailed to me, @@ -5207,7 +5316,7 @@ % \hrule height\headrulewidth width\textwidth} % \bigskip % \noindent which isn't very nice. -% There are basically three options to solve this problem. +% Here I give four options to solve this problem. % % \subsection{Using optional arguments} % @@ -5322,7 +5431,7 @@ % \fancyhead[LO,RE]{\nouppercase{% % \truncate{0.5\headwidth}{\leftmark}}} % Chapter title % \end{example} -% We don't have to make any changes to the chaper and section titles +% We don't have to make any changes to the chapter and section titles % because \cs{truncate} will take care of this. % This arrangement gives the following header when both titles are too % big, like in the example above: @@ -5347,6 +5456,72 @@ % if one of the header parts is small enough and then truncate the other % one for the remaining space. % +% \subsection{Using \Cmd{fancyheadwidth}} +% \label{sec:with-fancyheadwidth} +% +% For this solution we use the \cs{fancyheadwidth} command to give each +% part a little less than half of the \cs{headwidth}. This command is +% available in \texttt{fancyhdr} version 5.0 and later. +% Of course it is also possible to make asymmetric arrangements. +% \Example{34d} +% \begin{example} +% \setlength{\headheight}{35pt} +% \fancyhead[LE,RO]{\nouppercase{\rightmark}} % Section title +% \fancyhead[LO,RE]{\nouppercase{\leftmark}} % Chapter title +% \fancyfoot[LE,RO]{\thepage} +% \fancyheadwidth[L,R]{0.48\headwidth} +% . . . +% \chapter{This is a very long chapter title to see if we can +% let fancyhdr fit it in the header} +% \section{This is a very long section title that will not fit in the header} +% \end{example} +% We don't have to make any changes to the chapter and section titles. +% This arrangement gives the following header when both titles are too +% big, like in the example above: +% +% \bigskip +% \showheader{ +% \setlength{\headheight}{35pt} +% \fancyhead[L]{Chapter 1. This is a very long chapter title to see if we can +% let fancyhdr fit it in the header} +% \fancyhead[R]{1.1. This is a very long section title that will not fit in the header} +% \fancyheadwidth[L,R]{0.48\headwidth} +% } +% +% You may not like that the two parts of the header are aligned at the +% bottom, which is the default for the header. We can use the second +% optional parameter of \cs{fancyheadwidth} to specify a different +% alignment (in \pkg{fancyhdr} version 5.2 or later). See the following example. +% \Example{34e} +% \begin{example} +% \setlength{\headheight}{35pt} +% \fancyhead[LE,RO]{\nouppercase{\rightmark}} % Section title +% \fancyhead[LO,RE]{\nouppercase{\leftmark}} % Chapter title +% \fancyfoot[LE,RO]{\thepage} +% \fancyheadwidth*[L,R][tj]{0.48\headwidth} +% \fancyfootwidth*[LE,RO][-c]{0.1\headwidth} +% \end{example} +% We use \texttt{t} for the vertical alignment, and also \texttt{j} +% (justified) for the horizontal alignment. Just for fun we use the +% \texttt{*} form of the command, and also add \cs{fancyfootwidth*}. +% This puts the page number under the page a little bit away from the +% edge of the text. +% +% The resulting header looks like: +% +% \bigskip +% \showheader{ +% \setlength{\headheight}{35pt} +% \fancyhead[L]{Chapter 1. This is a very long chapter title to see if we can +% let fancyhdr fit it in the header} +% \fancyhead[R]{1.1. This is a very long section title that will not fit in the header} +% \fancyheadwidth*[L,R][tj]{0.48\headwidth} +% } +% +% Please note, that these solutions also have disadvantages. The header +% must be quite tall, and when a smaller title is used there is a gap +% between the title and the line under the header. +% % \section{I lost my chapter/section titles} % % Some time ago I got a question like this (edited to get the @@ -5453,14 +5628,17 @@ % extract the last left mark (\cs{leftmark}) and the first right mark % (\cs{rightmark}). This means that if there are two or more sections on % the page you get the last one, which can be counter-intuitive. -% The newer \LaTeX{} releases (November 2022 or newer) have a command to +% The newer \LaTeX{} releases (November 2022 or later) have a command +% (\Cmd{FirstMark\{2e-left\}}) to % get the first of the left marks, however. \textbf{We assume in the % following code that your \LaTeX{} is recent enough.} % \item \LaTeX{} uses \cs{markboth} at a section title in the % \pkg{article} class. This also sets an empty right mark. So in -% some cases you would get an empty subsection title in the header. To -% avoid this, \LaTeX{} now also has a mark that saves the non-empty -% right mark in a separate mark \texttt{2e-right-nonempty} +% some cases you would get an empty subsection title in the header. Also +% a \cs{part} command issues a \Cmd{markboth\{\}\{\}}, so it generates +% empty marks too. To avoid this, \LaTeX{} now has an additional mark +% \texttt{2e-right-nonempty} in which only the non-empty right marks are +% saved. This is also set by \cs{markboth} and \cs{markright}. % \end{itemize} % % If there is no \cs{section} command on the page, it `inherits' the @@ -5480,11 +5658,11 @@ % \subsection{Subsection One} % . . . % \end{example} -% This effectively solves the problem, but it has some undesirable +% This mostly solves the problem, but it has some undesirable % properties, see below. Therefore, some refinement is -% possible. But we need an extra mark for this. So we are going -% to use the \LaTeX{} marks directly, instead of using the standard -% marks. This gives us a bit more control. We need two marks for this, +% possible. But we need an extra mark for this. We are also going +% to use new marks, instead of using the standard +% marks to get more control. We need two marks for this, % one for the section title, and one for the subsection title. We call % these \texttt{section} and \texttt{subsection} respectively. We % replace the marking code above with the following, which gives @@ -5503,9 +5681,9 @@ % \InsertMark{subsection}{\thesubsection. #1}} % \end{example} % -% When you have a \cs{section} command on a page, but it doesn't have a -% subsection for an extended length, then, the -% previous subsection title is `inherited'. This may be sub-optimal, +% Now when you have a \cs{section} command on a page, but it doesn't +% have a subsection for an extended length, then, the previous +% subsection title is `inherited' on this page. This may be sub-optimal, % because it combines the title of section $n$ with a subsection title % that belongs to a previous section, so the subsection isn't even % present on the page, which looks unnatural. You may want to @@ -5538,7 +5716,7 @@ % the \meta{true code} is executed when there is no subsection title on the % current page, and the \meta{false code} when there is at least one. % -% However, there is no command to see if the pagebreak is at the section +% However, there is no command to see if the page break is at the section % or subsection level, because the two are independent. And we % cannot use \LaTeX{} variables for this, because of the asynchronous % processing of the page breaking. But we can do this if we introduce a @@ -5548,14 +5726,20 @@ % indicates if the page ends within a subsection or not. And as the % topmark on the following page is the same as lastmark on the previous % page, we can use this topmark to see whether the text at the beginning -% of the page comes from a subsection (topmark = 1 means yes). -% -% There is one caveat, however. If the page begins immediately with a -% section title, the topmark may indicate that the previous page ended -% with a subsection, but that subsection did not extend past the -% pagebreak. It is tricky to detect this situation, but we will propose -% a solution at the end of the current section. -% So the new code for the right header becomes the following. We use the +% of the page comes from a section or a subsection (topmark = 0 means +% section, 1 means subsection). +% +% So the interim new code for the right header becomes the following.\\ +% \textbf{if} there is no subsection on the page\\ +% \textbf{then}\\ +% \hspace*{2em}\textbf{if} the previous page ended in a subsection\\ +% \hspace*{2em}\textbf{then} use (inherit) that subsection\\ +% \hspace*{2em}\textbf{else} use an empty header\\ +% \hspace*{2em}\textbf{fi}\\ +% \textbf{else} (there is at least one subsection on the page)\\ +% \hspace*{2em}use the first subsection\\ +% \textbf{fi}\\[1ex] +% We use the % package \PKGindex{ifthen}\pkg{ifthen} for the test. % % \Example{35}[(continued)] @@ -5567,8 +5751,8 @@ % \IfMarksEqualTF{subsection}{top}{first} % {% no subsection mark on this page % \ifthenelse{\TopMark{which}=1} % previous page ended in a subsection -% % then use that subsection -% {\TopMark{subsection}}% = \FirstMark{subsection} +% % then use (inherit) that subsection +% {\TopMark{subsection}}% % {}% otherwise empty right header % } % {% there is a subsectionmark on the page, use it @@ -5585,19 +5769,23 @@ % } % \end{example} % -% Now we want to suppress the `inheritance' of the subsection if there +% There is one caveat, however. If the page begins immediately with a +% section title, the topmark may indicate that the previous page ended +% with a subsection, but that subsection did not extend past the +% page break. +% So we want to suppress the `inheritance' of the subsection if there % is a section title at the top of the page and the page contains no % subsection title. The information whether a section title is at the % top of the page is not available in the marks, so we need some other % way to detect this. % % \TeX{} has two variables that can help us, \cs{pagegoal} is the vertical size -% that is still available on the page, and \cs{pagetotal} is the amount we +% that is available on the page, and \cs{pagetotal} is the amount we % have used so far\footnote{This doesn't include floats and footnotes.}. % So if \cs{pagetotal}=\texttt{0pt} we are at the top of % the page, otherwise somewhat further down. We can use this information to % communicate to the header that no inheritance should take place. In -% reality, sometimes there is already a small amount of whitespace on +% reality, sometimes there is already a small amount of white space on % the page, so the test should be less strict than % \cs{pagetotal}=\texttt{0pt}. We might even choose to not inherit the % subsection title if only a few lines of the previous subsection are @@ -5607,80 +5795,227 @@ % \cs{pagetotal}$<$0.33\cs{pagegoal}. In the code below we choose a few % lines as the limit. % -% We have to do the test just before the \cs{section} command is -% processed. This can be done with a \LaTeX{} \emph{hook}. +% We have to do the test at the beginning of the \cs{section} command +% processing. This can be done with a \LaTeX{} \emph{hook}. % % The next question is how to communicate the fact that the section -% starts at (or near) to top of the page to the header. A simple way to -% do this is to set the `\texttt{which}' mark to $-1$ instead of 0. -% (Another way could be to define a special page style that does not do -% the inheritance, and activate that with \cs{thispagestyle}.) +% starts at (or near) the top of the page to the header. A simple way to +% do this could be to set the `\texttt{which}' mark to a different value, e.g, +% $-1$ instead of 0. However, below we will present a better way. % % \begin{code} % \AddToHook{cmd/section/before}{% % % use whatever test your design requires % \ifthenelse{\lengthtest{\pagetotal<4\baselineskip}} -% {\InsertMark{which}{-1}} -% {\InsertMark{which}{0}} +% {indicate section at top of page} +% {indicate section somewhere else} % } % \end{code} % -% It appears, however that this is the wrong place to set the mark. A -% pagebreak could occur between this code and the actual section title, -% so that the mark is put on the wrong page. The proper place for setting the -% mark is in the \cs{sectionmark} command, as that is guaranteed to -% always be together with the section title. So we must put the required -% value for the mark in a variable. -% % There is another situation where a section title could end up at the % top of the page: when it is processed at the bottom of the page, but % there isn't enough space left to place it there. It will then be % pushed to the next page. In that case the \cs{pagetotal} will be in -% the neighbourhood of \cs{pagegoal}. In the code below we test for -% \cs{pagetotal}$>$0.9\cs{pagegoal}, but some experimentation may be -% necessary to find a proper value. -% In the example 35 file you can see this in section~6. +% the neighbourhood of \cs{pagegoal}. However, it is very difficult to +% find a proper value for the cutoff of \cs{pagetotal}. In many cases it +% will be too small or too big, depending on the size of the section +% title. So we need a different way. +% +% If the section title is pushed to the next page, the page number of +% the page where the section title is processed will be different from +% the page number that is current when the header is created. (We assume +% that all page numbers are different.) So by storing the page number +% atvthe time of processing the section title, and then comparing it in the header with +% the \texttt{page} counter, we can check that the header was +% moved to another page from an earlier page. This doesn't have +% to be \textbf{the} next page, as there could be float pages in +% between. The test has to be done while we are in the header, not while +% we are processing the section title. And it is not enough to store the page +% number in a variable because there can be subsequent section titles on +% the next page and these would overwrite the saved value. So it must be stored in +% yet another mark. Let's call this mark \texttt{whichpage}. We can save +% this in the \cs{sectionmark} command. +% +% Now, in the right header, we can check if \Cmd{FirstMark\{whichpage\}} +% is equal to \cs{thepage}. If they are different, the section title was +% pushed across a page boundary, so it is at the top of the page. Note +% that this test makes only sense if there is a section title on the +% page, so we have to include a test for this also. This can be done +% with \Cmd{IfMarksEqualTF\{section\}\{top\}\{first\}}. A compact way to +% do this is: +% \begin{code} +% \equal{\IfMarksEqualTF{section}{top}{first} +% {\thepage}{\FirstMark{whichpage}}}{\thepage}}% +% \end{code} +% +% So if there is no section on the page, we don't compare +% \texttt{whichpage} to \cs{thepage}, but instead compare \cs{thepage} +% with itself, which gives \emph{true}, i.e. no section at the top of the page. % -% \emph{(Another way could be to put the current page number in a mark -% and then check in the header if this is the same as the page number -% where the header is put on the page. If different, don't -% inherit. This is left as an exercice for the reader.)} +% We use a string comparison for the page number, not a numerical +% comparison, because page numbers can be non-numeric, for example roman +% numbers, which can't be compared numerically. +% +% This gives us now a way to indicate the previous case for a section +% title at the top of the page: Just put a value in the +% \texttt{whichpage} mark that is different from the actual page number. +% But as the test is done in the hook, and the setting of the mark in +% \cs{sectionmark}, we must communicate this through a variable. Let's +% call this variable \cs{whichpage}. I have chosen to just put the text +% ``top'' in front of the page number to make it different, but any +% value that can't be a page number would be good. % % \Example{35}[(continued)] % \begin{example} -% \newcommand{\which}{} +% \NewMarkClass{whichpage} +% \newcommand\whichpage{} +% % \AddToHook{cmd/section/before}{% -% \ifthenelse{\lengthtest{\pagetotal<4\baselineskip}\or -% \lengthtest{\pagetotal>0.9\pagegoal}}{% -% {\renewcommand\which{-1}}% -% {\renewcommand\which{0}}% +% % use whatever test your design requires +% \ifthenelse{\lengthtest{\pagetotal<4\baselineskip}} +% {\renewcommand{\whichpage}{top\thepage}}% +% {\renewcommand{\whichpage}{\thepage}}% % } +% % \renewcommand{\sectionmark}[1]{% % \InsertMark{section}{\thesection\ #1}% -% \InsertMark{which}{\which}% -% }% +% \InsertMark{which}{0}% +% \InsertMark{whichpage}{\whichpage}% +% } % \end{example} % +% In the example 35 file you can see this in section~6. +% % The final code for the right header will now be: +% % \Example{35}[(continued)] % \begin{example} % \fancyhead[R]{% -% \IfMarksEqualTF{subsection}{top}{first} -% {% no subsection mark on this page -% \ifthenelse{\TopMark{which}=1}{% -% % use previous subsection unless suppressed by which = -1 -% \ifthenelse{\FirstMark{which}<0} % -1 -% {\FirstMark{subsection}}% = \TopMark{subsection} +% \IfMarksEqualTF{subsection}{top}{first} +% {% no subsection mark on this page +% \ifthenelse{% +% % previous page ended in a subsection +% \TopMark{which}=1\and +% % Is there a section on the page? +% \equal{\IfMarksEqualTF{section}{top}{first} +% {\thepage}{\FirstMark{whichpage}}}{\thepage}}% +% { +% % use previous subsection unless suppressed by section on top +% \TopMark{subsection}% +% } +% % otherwise use empty right header +% {}% % } -% } -% {% if there is a subsectionmark on the page, use it -% \FirstMark{subsection}% -% }% +% {% if there is a subsectionmark on the page, use it +% \FirstMark{subsection}% +% }% % } % \end{example} % In the actual code in the Example 35 file there is also some debugging % code added. % +% \subsection{The headers in this document} +% +% Now we will describe how the headers in the \pkg{fancyhdr} +% documentation (this document) are constructed. This documentation +% consists of a number of sections, some of which have one or more +% subsections. There is only one title in the header, which is the +% title of the [sub]section that is current at the top of the page. In +% other words, the last one on a previous page. This asks for a `top mark'. +% +% Because both sections and subsections are treated the same, we use a +% single mark for both, and we put the common code in macros. We could +% have chosen a new mark for the titles, but \LaTeX's standard right +% mark is sufficient for this\footnote{This is better than the left mark, bcause that +% doesn't have a way to filter out empty ones which are generated by the +% \cs{part} commands in the document, and also \cs{leftmark} will +% produce the last title of the current page, which isn't useful.}. +% +% When a [sub]section title is at or near the top of the page, we will +% use that title in the header instead of the one from the previous +% page, because this look more natural (the previous one does have no or +% very little text on the current page), just like in the previous +% example (35). We use the same mechanism, with a mark \texttt{whichpage} to +% achieve this. Because we put sections and subsections together, we +% don't need a mark to distinguish them. Example~36 has essentially the +% same headers as this documentation. +% +% The macro \cs{checkposinpage} checks whether the [sub]section starts +% at or near the top of the page, and puts this information in the +% variable \cs{whichpage}, just like in example~35. The macro +% \cs{setmarks}, sets the marks, both the right mark for the title (with +% \cs{markright}), and the extra mark \texttt{whichpage}. +% +% \Example{36} +% \begin{example} +% \NewMarkClass{whichpage} +% \newcommand\whichpage{} +% +% \newcommand\checkposinpage{ +% \ifthenelse{\lengthtest{\pagetotal<4\baselineskip}}% +% {\renewcommand{\whichpage}{top\thepage}}% +% {\renewcommand{\whichpage}{\thepage}}% +% } +% +% \AddToHook{cmd/section/before}{\checkposinpage} +% \AddToHook{cmd/subsection/before}{\checkposinpage} +% +% \newcommand\setmarks[1]{% +% \InsertMark{whichpage}{\whichpage}% +% \markright{#1}% +% } +% +% \renewcommand{\sectionmark}[1]{% +% \setmarks{\thesection\quad#1}% +% }% +% +% \renewcommand{\subsectionmark}[1]{% +% \setmarks{\thesubsection\quad#1}% +% }% +% \end{example} +% +% Finally, the header code. For the last title of the/a previous page we +% use \Cmd{TopMark\{2e-right-nonempty\}}, for a title that is at/near +% the top of the page we use \cs{rightmark}. The algorithm is similar to +% example~35, but simplified:\\[1ex] +% ^^A +% \textbf{if} \texttt{whichpage} = \verb|\thepage| (i.e., no [sub]section at or near top)\\ +% \textbf{then}\\ +% \hspace*{2em} use last [sub]section from a previous page\\ +% \textbf{else} (\texttt{whichpage} $\ne$ \verb|\thepage|)\\ +% \hspace*{2em} \textbf{if} there is no \texttt{whichpage} mark on this page\\ +% \hspace*{3em} (this means the \texttt{whichpage} mark is not valid for this page)\\ +% \hspace*{2em} \textbf{then} use last [sub]section from a previous page\\ +% \hspace*{2em} \textbf{else} (there is a [sub]section title at/near the top of the page)\\ +% \hspace*{3em} use first [sub]section of current page\\ +% \textbf{fi} +% +% \Example{36}[(Continued)] +% \begin{example} +% \fancypagestyle*{fancy}{% +% \fancyhf{} +% \fancyhead[L]{% +% \ifthenelse{\equal{\FirstMark{whichpage}}{\thepage}}% +% {\TopMark{2e-right-nonempty}}% +% % whichpage != page +% {\IfMarksEqualTF{whichpage}{top}{first}% +% {\TopMark{2e-right-nonempty}}% no mark on this page +% {\rightmark}% title at/near the top of the page +% }% +% } +% \fancyhead[R]{\textbf{\thepage}} +% } +% \end{example} +% +% In the example~36 file there is some additional code for debugging +% that we don't show here. +% +% In this documentation there are some cases that aren't covered by this +% code: the \Cmd{part} commands do not have a corresponding +% \Cmd{partmark}, and there are some hidden \Cmd{section*} commands that +% do not call \Cmd{sectionmark}. In these cases we manually add the +% \cs{checkposinpage} and \cs{setmarks} commands. +% % \section{How to change shapes and traits of horizontal lines in headers/footers?} % \label{sec:headrules} % @@ -5720,7 +6055,7 @@ % \smash{\color{blue}\rule{\headwidth}{2.5pt}}% % } % \end{code} -% The \cs{interlineskip} is to prevent \LaTeX{} to insert the normal +% The \cs{nointerlineskip} is to prevent \LaTeX{} to insert the normal % vertical space between lines, and the \cs{smash} to let the % \cs{headrule} not occupy any vertical space. Whether you want that is % up to you, but if it occupies vertical space it may distort the page layout.\\ @@ -5817,7 +6152,16 @@ % Of course you would have to make sure not to place anything in the % right part of the header. % +% \MaybeStop{% +% \setmarks{Change History}\PrintChanges +% \setmarks{Index} +% ^^A Temporary workaround for mark problems in `multicol' +% \fancyhead[L]{Index} +% \PrintIndex +% } +% % \newpage +% \checkposinpage\setmarks{Implementation} % \part{Implementation} % % \begin{implementation} @@ -5900,7 +6244,7 @@ % \changes{fancyhdr v1.99a}{1996/05/10}{Added a few more \% signs.} % % \changes{fancyhdr v1.99b}{1996/05/10}{Changed the syntax of -% \cs{f@nch@for} to be resistent to catcode changes of \texttt{:!=}.\protect\\ +% \cs{f@nch@for} to be resistant to catcode changes of \texttt{:!=}.\protect\\ % Removed the \texttt{[1]} from the defs of \cs{lhead} etc. because the parameter is % consumed by the \cs{@[xy]lhead} etc. macros.} % @@ -5940,7 +6284,7 @@ % \changes{fancyhdr v2.1x=fancyhdr v2.1}{2002/12/09}{The defaults for % \cs{footrulewidth}, \cs{plainheadrulewidth} and % \cs{plainfootrulewidth} are changed from \cs{z@skip} to 0pt. In this -% way when someone inadvertantly uses \cs{setlength} to change any of these, the value +% way when someone inadvertently uses \cs{setlength} to change any of these, the value % of \cs{z@skip} will not be changed, rather an errormessage will be given.} % % \changes{fancyhdr v3.0}{2004/03/03}{Release of version 3.0.} @@ -5980,13 +6324,8 @@ % \changes{fancyhdr v3.9}{2016/10/11}{Put everything in a \texttt{.dtx} file.} % \changes{fancyhdr v3.9}{2016/10/12}{Rename some macros to have 'f@nch@' % in their names, to get a more uniform naming scheme for internal macros.} -% -% \begin{macro}[internal]{\if@nch@mpty} -% This macro tests if its argument is empty. -% \begin{macrocode} -\newcommand\if@nch@mpty[1]{\def\temp@a{#1}\ifx\temp@a\@empty} -% \end{macrocode} -% \end{macro} +% \changes{fancyhdr v5.2}{2025/01/15}{Conditionally require package \pkg{xparse}.} +\ifdefined\NewDocumentCommand\else\RequirePackage{xparse}\fi % % \begin{macro}[internal]{\iff@nch@check} % Boolean for the \texttt{nocheck} option. @@ -6045,48 +6384,29 @@ % \end{macro} % % \begin{macro}[internal]{\f@nch@def} -% This macro defines another macro (usually a header or footer field). +% This macro defines another macro (a header or footer field). % Depending on the value of \cs{f@nch@gbl} the definition will be % global or local. % Default it is always local. But with the \texttt{compatV3} option it % is \cs{global} in the normal definitions, and local in \cs{fancypagestyle}. % The \cs{global} case is now considered a bug (or at least undesirable). % -% If the value (argument 2) is empty, a \cs{leavevmode} will be substituted. -% If it is not empty, a \cs{strut} will be added. -% -% \begin{macrocode} -\newcommand\f@nch@def[2]{\if@nch@mpty{#2}\f@nch@gbl\def#1{\leavevmode}\else - \f@nch@gbl\def#1{#2\strut}\fi} -% \end{macrocode} -% \end{macro} +% If the value (argument 2) is not empty, a \cs{strut} will be added. +% \changes{fancyhdr v5.2}{2025/02/07}{Inline \cs{if@nch@mpty}.} +% \changes{fancyhdr v5.2}{2025/02/07}{Remove \cs{leavevmode}, because +% the initialisation code also inserts a \cs{leavevmode}.} % -% \begin{macro}[internal]{\f@nch@ifundefined} -% This macro tests if a command is undefined. Older versions of -% fancyhdr used \cs{@ifundefined}, but this had an undesired side effect -% in the original \LaTeX{} (the command was made equal to \cs{relax} if -% it was undefined). Another way was\\ -% \verb+\ifx\thecommand\undefined ...+ or \verb+\ifx\thecommand\@undefined ...+ -% but that could conflict with packages that use the \cs{@ifundefined} -% method. \LaTeX{} versions later than 2018 have a definition of -% \cs{@ifundefined} that avoids these problems, but not everybody may -% have such a version installed. Therefore we define our own version -% \cs{f@nch@ifundefined}. -% This definition is copied from the \PKGindex{tocloft}\pkg{tocloft} package by Peter -% Wilson and Will Robertson. % \begin{macrocode} -\newcommand{\f@nch@ifundefined}[1]{% - \begingroup\expandafter\expandafter\expandafter\endgroup - \expandafter\ifx\csname #1\endcsname\relax - \expandafter\@firstoftwo - \else - \expandafter\@secondoftwo - \fi} +\newcommand\f@nch@def[2]{% + \def\temp@a{#2}\ifx\temp@a\@empty\f@nch@gbl\def#1{}% + \else\f@nch@gbl\def#1{#2\strut}\fi} % \end{macrocode} % \end{macro} % % \changes{fancyhdr v4.0}{2019/03/17}{Added \texttt{headings} and % \texttt{myheadings} options.} +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % Standard styles are redefined optionally. These definitions are % borrowed from the \PKGindex{nccfancyhdr}\pkg{nccfancyhdr} package % by by Alexander I. Rozhenko. @@ -6099,7 +6419,7 @@ % \OPTindex{myheadings}\PSindex{myheadings} % \begin{macrocode} \DeclareOption{myheadings}{% - \f@nch@ifundefined{chapter}{% + \@ifundefined{chapter}{% % \end{macrocode} % An article-like class without chapters: % \begin{macrocode} @@ -6136,9 +6456,11 @@ % \cs{@mkboth} from \cs{let}\cs{@mkboth}\cs{markboth} to % \cs{def}\Cmd{@mkboth\{\cs{protect}\cs{markboth}\}} so that it will pick up changes % to \cs{markboth}} +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % \begin{macrocode} \DeclareOption{headings}{% - \f@nch@ifundefined{chapter}{% + \@ifundefined{chapter}{% \if@twoside % \end{macrocode} % An article in two-side mode: @@ -6222,9 +6544,9 @@ % Execute the body for each character in \texttt{charstring} bound % to \cs{var}. % This is similar to \LaTeX's \cs{@tfor}, but it expands the \texttt{charstring}. -% \begin{macrocode} % \changes{fancyhdr v3.10}{2019/01/25}{Use \cs{newcommand} instead of \cs{def}.} % \changes{fancyhdr v4.0.2}{2021/05/29}{Make \cs{f@nch@rc} \cs{long}.} +% \begin{macrocode} \newcommand{\f@nch@forc}[3]{\expandafter\f@nchf@rc\expandafter#1\expandafter{#2}{#3}} \newcommand{\f@nchf@rc}[3]{\def\temp@ty{#2}\ifx\@empty\temp@ty\else \f@nch@rc#1#2\f@nch@rc{#3}\fi} @@ -6401,12 +6723,18 @@ % The commands for field widths. % \changes{fancyhdr v5.0}{2025/01/01}{New commands \cs{fancyheadwidth}, % \cs{fancyfootwidth} and \cs{fancyhfwidth}.} +% \changes{fancyhdr v5.2}{2025/01/25}{Second optional parameter \meta{alignment}.} +% \changes{fancyhdr v5.2}{2025/01/27}{Implement \texttt{*} version of +% these commands.} % Pick up the parameters, % and supply an 'h' (\cs{fancyheadwidth}) or 'f' (\cs{fancyfootwidth}). % \begin{macrocode} -\newcommand{\fancyheadwidth}[2][]{\f@nch@fancyhfwidth\fancyheadwidth h[#1]{#2}}% -\newcommand{\fancyfootwidth}[2][]{\f@nch@fancyhfwidth\fancyfootwidth f[#1]{#2}}% -\newcommand{\fancyhfwidth}[2][]{\f@nch@fancyhfwidth\fancyhfwidth {}[#1]{#2}}% +\NewDocumentCommand {\fancyheadwidth}{ s O{} O{} m } + {\f@nch@fancyhfwidth{#1}\fancyheadwidth h[#2][#3]{#4}}% +\NewDocumentCommand {\fancyfootwidth}{ s O{} O{} m } + {\f@nch@fancyhfwidth{#1}\fancyfootwidth f[#2][#3]{#4}}% +\NewDocumentCommand {\fancyhfwidth} { s O{} O{} m } + {\f@nch@fancyhfwidth{#1}\fancyhfwidth {}[#2][#3]{#4}}% % \end{macrocode} % \end{macro} % @@ -6414,39 +6742,79 @@ % This macro interprets the parameters for the header and footer field % widths.\\ % Parameters:\\ -% (1) The user command that was used (like \cs{fancyheadwidth}). This is used +% (1) The optional \texttt{*} argument.\\ +% (2) The user command that was used (like \cs{fancyheadwidth}). This is used % for errors/warnings.\\ -% (2) \texttt{h} (for \cs{fancyheadwidth}), \texttt{f} (for \cs{fancyfootwidth}), +% (3) \texttt{h} (for \cs{fancyheadwidth}), \texttt{f} (for \cs{fancyfootwidth}), % or \texttt{\{\}} (for \cs{fancyhfwidth}).\\ -% (3) The optional parameter that was given to these commands (default \texttt{[]}).\\ -% (4) The required parameter that was given to these commands.\\ +% (4-5) The two optional parameters that were given to these commands +% (default for each \texttt{[]}).\\ +% (6) The required parameter that was given to these commands.\\ % The header and footer field widths are stored in command sequences with % names of the form: \cs{f@nch@width@}\meta{x}\meta{y}\meta{z} with \meta{x} from % \texttt{[eo]}, \meta{y} from \texttt{[lcr]} and \meta{z} from \texttt{[hf]}. +% The header and footer alignments are stored (after defaults have +% been applied) in command sequences with names of the form: +% \cs{f@nch@align@}\meta{x}\meta{y}\meta{z} with \meta{x} from +% \texttt{[eo]}, \meta{y} from \texttt{[lcr]} and \meta{z} from +% \texttt{[hf]}. % % First we assign the \meta{width} argument to a temporary length -% variable, to check if it is a legal \meta{length}. Then we store the -% \meta{width} in variables for all the specified places. +% variable, to check if it is a legal \meta{length}. % % \begin{macrocode} -\def\f@nch@fancyhfwidth#1#2[#3]#4{% - \setlength\@tempdima{#4}% +\def\f@nch@fancyhfwidth#1#2#3[#4][#5]#6{% + \setlength\@tempdima{#6}% \def\temp@c{}% - \f@nch@forc\tmpf@ra{#3}% + \f@nch@forc\tmpf@ra{#4}% {\expandafter\f@nch@ifin\tmpf@ra{eolcrhf,EOLCRHF}% {}{\edef\temp@c{\temp@c\tmpf@ra}}}% \ifx\@empty\temp@c\else \PackageError{fancyhdr}{Illegal char `\temp@c' in - \string#1 argument: [#3]}{}% - \fi \f@nch@for\temp@c{#3}% + \string#2 argument: [#4]}{}% + \fi + \f@nch@for\temp@c{#4}% {\f@nch@default\f@nch@@eo{eo}\temp@c - \f@nch@fancyhf@Echeck{#1}% + \f@nch@fancyhf@Echeck{#2}% \f@nch@default\f@nch@@lcr{lcr}\temp@c - \f@nch@default\f@nch@@hf{hf}{#2\temp@c}% + \f@nch@default\f@nch@@hf{hf}{#3\temp@c}% \f@nch@forc\f@nch@eo\f@nch@@eo {\f@nch@forc\f@nch@lcr\f@nch@@lcr {\f@nch@forc\f@nch@hf\f@nch@@hf - {\expandafter\def\csname - f@nch@width@\f@nch@eo\f@nch@lcr\f@nch@hf\endcsname {#4}}}}}} +% \end{macrocode} +% Then we store the \meta{width} in variables for all the specified +% places. If the \texttt{*} form was given we use the calculated value, +% otherwise the bare argument. +% \begin{macrocode} + {% + \IfBooleanTF{#1}{% + \expandafter\edef\csname + f@nch@width@\f@nch@eo\f@nch@lcr\f@nch@hf\endcsname{\the\@tempdima}% + }% + {% + \expandafter\def\csname + f@nch@width@\f@nch@eo\f@nch@lcr\f@nch@hf\endcsname{#6}% + }% +% \end{macrocode} +% Then we apply the defaults to the \meta{alignment} argument. +% The defaults are: +% \begin{itemize} +% \item for the vertical alignment (v): \texttt{b} in a +% header, and \texttt{t} in a footer. This is done by executing a +% corresponding macro. +% \item for the horizontal alignment (h): l, c, r: the same as the +% field. Just copy the field letter. +% \end{itemize} +% If the optional parameter is empty, we leave it at these defaults, +% otherwise we process the arguments with \cs{f@nchdrwdt@align}. +% Finally we store the result in variables for the specified places. +% \begin{macrocode} + \csname f@nchdrwdt@align@v@\f@nch@hf\endcsname + \edef\f@nch@align@@h{\f@nch@lcr}% + \def\temp@a{#5}% + \ifx\temp@a\@empty \else \f@nchdrwdt@align#5\@nil{#2}\fi + \expandafter\edef\csname + f@nch@align@\f@nch@eo\f@nch@lcr\f@nch@hf\endcsname + {\f@nch@align@@v\f@nch@align@@h}}}}}} % \end{macrocode} % \end{macro} % @@ -6492,6 +6860,88 @@ % \end{macro} % \end{macro} % +% \begin{macro}[internal]{\f@nch@align@elh} +% \begin{macro}[internal]{\f@nch@align@ech} +% \begin{macro}[internal]{\f@nch@align@erh} +% \begin{macro}[internal]{\f@nch@align@olh} +% \begin{macro}[internal]{\f@nch@align@och} +% \begin{macro}[internal]{\f@nch@align@orh} +% \begin{macro}[internal]{\f@nch@align@elf} +% \begin{macro}[internal]{\f@nch@align@ecf} +% \begin{macro}[internal]{\f@nch@align@erf} +% \begin{macro}[internal]{\f@nch@align@olf} +% \begin{macro}[internal]{\f@nch@align@ocf} +% \begin{macro}[internal]{\f@nch@align@orf} +% +% Alignment parameters for the widths. +% +% \begin{macrocode} +\def\f@nch@align@elh{bl} +\def\f@nch@align@ech{bc} +\def\f@nch@align@erh{br} +\def\f@nch@align@olh{bl} +\def\f@nch@align@och{bc} +\def\f@nch@align@orh{br} +\def\f@nch@align@elf{tl} +\def\f@nch@align@ecf{tc} +\def\f@nch@align@erf{tr} +\def\f@nch@align@olf{tl} +\def\f@nch@align@ocf{tc} +\def\f@nch@align@orf{tr} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[internal]{\f@nchdrwdt@align@v@h, \f@nchdrwdt@align@v@f, \f@nchdrwdt@align} +% \cs{f@nchdrwdt@align@v@h}: set v to \texttt{b}\\[1ex] +% \cs{f@nchdrwdt@align@v@f}: set v to \texttt{t}\\[1ex] +% \cs{f@nchdrwdt@align}\marg{vert}\marg{hor}\texttt{\cs{@nil}}\marg{originating command}\\[1ex] +% The internal processing for \meta{alignment} parameter in \cs{fancyhfwidth}, +% etc.\\ +% ALGORITHM \cs{f@nchdrwdt@align}:\\ +% (v = vertical position; h = horizontal position)\\ +% These have been set to their defaults before calling us.\\ +% \textbf{IF} \texttt{\#1} in \texttt{\{T,t,c,b,B,-\}} \\ +% \textbf{THEN} \textbf{if} \texttt{\#1} $\ne$ `\texttt{-}' \textbf{then} +% v := \texttt{\#1} \textbf{fi}\\ +% \hspace*{1em} \textbf{if} \texttt{\#2} is not empty \textbf{then} h := \texttt{\#2} +% \textbf{fi}\\ +% \textbf{ELSE} (\texttt{\#1} not in \texttt{\{T,t,c,b,B,-\}} -- it must be +% a horizontal alignment)\\ +% \hspace*{1em} h := \texttt{\#1}\\ +% \textbf{FI}\\ +% \textbf{if} h not in \texttt{\{l,c,r,j\}} \textbf{then} ERROR \textbf{fi}\\ +% +% The result can be found in the variables \cs{f@nch@align@@v} and \cs{f@nch@align@@h}. +% \begin{macrocode} +\def\f@nchdrwdt@align@v@h{\def\f@nch@align@@v{b}}% +\def\f@nchdrwdt@align@v@f{\def\f@nch@align@@v{t}}% +\long\def\f@nchdrwdt@align#1#2\@nil#3{% + \f@nch@ifin{#1}{TtcbB-}{% + \f@nch@ifin{#1}{-}{}{\def\f@nch@align@@v{#1}}% + \def\@tempa{#2}% + \ifx\@tempa\@empty \else \def\f@nch@align@@h{#2}\fi + }% + {\def\f@nch@align@@h{#1}}% + \expandafter\f@nch@ifin\expandafter{\f@nch@align@@h}{lcrj}{}% + {\PackageError{fancyhdr} + {\string#3: Illegal char `\f@nch@align@@h'\MessageBreak + in alignment argument}{}}% +} +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\lhead} % \changes{fancyhdr v3.9}{2016/10/12}{Let \cs{newcommand} do the % handling of the optional parameter.} @@ -6552,8 +7002,8 @@ % \changes{fancyhdr v4.0.2}{2021/03/27}{Change the offset length variables % \cs{f@nch@O@xyz} to \cs{f@nch@offset@xyz}} % Length parameter to be used for \cs{headwidth}. We use this rather -% than defining \cs{headwidth} as a length paramater directly to protect -% ourself to someone saying: \verb+\let\headwidth\textwidth+. +% than defining \cs{headwidth} as a length parameter directly to protect +% ourselves to someone saying: \verb+\let\headwidth\textwidth+. % \begin{macrocode} \newlength{\f@nch@headwidth} \let\headwidth\f@nch@headwidth % \end{macrocode} @@ -6598,8 +7048,10 @@ % \begin{macro}{\headruleskip} % Don't define \cs{headruleskip} if it is already defined. % \changes{fancyhdr v4.0}{2019/03/22}{Parameter \cs{headruleskip}.} +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % \begin{macrocode} -\f@nch@ifundefined{headruleskip}% +\@ifundefined{headruleskip}% {\newcommand{\headruleskip}{0pt}}{} % \end{macrocode} % \end{macro} @@ -6607,8 +7059,10 @@ % \begin{macro}{\footruleskip} % Memoir also defines \cs{footruleskip}. % Don't define \cs{footruleskip} if it is already defined. +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % \begin{macrocode} -\f@nch@ifundefined{footruleskip}% +\@ifundefined{footruleskip}% {\newcommand{\footruleskip}{.3\normalbaselineskip}}{} % \end{macrocode} % \end{macro} @@ -6686,8 +7140,10 @@ % \changes{fancyhdr v5.1}{2025/01/06}{A new way to disable the paragraph % hooks in headers and footers.} % \changes{fancyhdr v5.1.1}{2025/01/07}{Use low-level commands to reset -% paragraph hooks to prevent LaTeX error when ruinning with latex3 +% paragraph hooks to prevent LaTeX error when running with latex3 % debugging.} +% \changes{fancyhdr v5.2}{2025/01/14}{Use official interface to reset +% the paragraph hooks.} % The way we do this now: Every hook consists of 4 global `variables': % \begin{itemize} % \item \cs{__hook \meta{name}} @@ -6699,26 +7155,23 @@ % \texttt{para/end}, and \texttt{para/after}). At the beginning of a % header/footer, i.e., before any init code and hooks, all these variables are % locally saved into variables with the same name, prefixed with -% `\texttt{f@nch@}', and then globally reset to their `empty' value. At -% the end of the header/footer they are globally restored to the saved value. +% `\texttt{f@nch@}', and then clear the hook. At the end of the +% header/footer they are globally restored to the saved value. % So we do only global assignments to them to avoid problems. % Save a (paragraph) hook locally and and clear it globally. % Restore it globally at the end of header/footer processing. % \begin{macrocode} - \prop_new:N \f@nch@empty_code_prop \def\f@nch@saveclr@parhook #1{ \expandafter\let\csname f@nch@__hook~#1\expandafter\endcsname \csname __hook~#1\endcsname - \expandafter\gdef\csname __hook~#1\endcsname { } \expandafter\let\csname f@nch@__hook_toplevel~#1\expandafter\endcsname \csname __hook_toplevel~#1\endcsname - \expandafter\gdef\csname __hook_toplevel~#1\endcsname { } \expandafter\let\csname f@nch@__hook_next~#1\expandafter\endcsname \csname __hook_next~#1\endcsname - \expandafter\gdef\csname __hook_next~#1\endcsname { } \expandafter\let\csname f@nch@g__hook_#1_code_prop\expandafter\endcsname \csname g__hook_#1_code_prop\endcsname - \global\expandafter\let\csname g__hook_#1_code_prop\endcsname \f@nch@empty_code_prop + \RemoveFromHook{#1}[*] + \ClearHookNext{#1} } \def\f@nch@restore@parhook #1{ \global\expandafter\let\csname __hook~#1\expandafter\endcsname @@ -6767,7 +7220,7 @@ % We want \cs{nouppercase} to work with the various evolutionary stages of % \cs{MakeUppercase}. The current version (2022/11/09) accepts an optional % argument with a language specification. Therefore we define a dummy macro -% \cs{f@nch@noUppercase} which copies its mandatory agument, as a +% \cs{f@nch@noUppercase} which copies its mandatory argument, as a % replacement for \cs{MakeUppercase} while \cs{nouppercase} is active. % \begin{macrocode} \newcommand\f@nch@noUppercase[2][]{#2} @@ -6781,10 +7234,10 @@ % Also reset the catcodes that are changed in verbatim environments, % \cs{makeatother} and \cs{ExplSyntaxOn}. It also % defines a \cs{nouppercase} command that disables \cs{uppercase} and -% \cs{Makeuppercase}. It can only be used in the headers and footers. Set +% \cs{MakeUppercase}. It can only be used in the headers and footers. Set % \cs{hsize} to \cs{headwidth} (this helps for multicol); reset % \bsbs, \cs{raggedleft}, \cs{raggedright} and \cs{centering} to -% their default values (for tabu), and \cs{everypar} to empty.\\ +% their default values (for \pkg{tabu}), and \cs{everypar} to empty.\\ % The font is reset to \cs{normalfont}. Actually this is done in the % \LaTeX{} output routine, so we don't have to do it here. % \changes{fancyhdr v4.1}{2022/11/09}{Change \cs{nouppercase} to work with @@ -6794,6 +7247,8 @@ % is active. (Issue \# 8 \url{https://github.com/pietvo/fancyhdr/issues/8}.)} % \changes{fancyhdr v4.3}{2024/05/08}{Remove pre-NFSS stuff} % \changes{fancyhdr v4.3}{2024/07/17}{Replace \cs{f@nch@everypar} by \cs{f@nch@resetpar}.} +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % \begin{macrocode} \def\f@nch@reset{\f@nch@resetpar\restorecr\endlinechar=13 \catcode`\\=0\catcode`\{=1\catcode`\}=2\catcode`\$=3\catcode`\&=4 @@ -6811,7 +7266,7 @@ \expandafter\def\csname MakeUppercase\space\space\space\endcsname [####1]####2{####2}% ##1}}% - \f@nch@ifundefined{@normalsize} {\normalsize} % for ucthesis.cls + \@ifundefined{@normalsize} {\normalsize} % for ucthesis.cls {\@normalsize}% } % \end{macrocode} @@ -6952,7 +7407,7 @@ % % \begin{macro}[internal]{\f@nch@height} % \changes{fancyhdr v5.0}{2021/02/20}{Length variable \cs{f@nch@height} added} -% Length variable to store heigth of header/footer for use in \cs{fancyhdrsettoheight} +% Length variable to store height of header/footer for use in \cs{fancyhdrsettoheight} % \begin{macrocode} \newlength\f@nch@height % \end{macrocode} @@ -7077,7 +7532,7 @@ % However, if the \texttt{[nocheck]} options is given, we just make the % height of the header/footer equal to the reserved space, so that no % warning about ``Overfull vbox'' will be given. So we pretend that it -% fits, and it is the users's responsibility to make sure no unwanted +% fits, and it is the user's responsibility to make sure no unwanted % effects take place. % \begin{macrocode} \else @@ -7102,6 +7557,8 @@ % \cs{fancyfootwidth} and \cs{fancyhfwidth}.} % \changes{fancyhdr v5.1}{2025/01/06}{Add paragraph hook restore code % (\cs{f@nch@restorepar}).} +% \changes{fancyhdr v5.2}{2025/01/25}{Implement \cs{fancyhfwidth} etc. +% \meta{alignment} option.} % Put together a header (\cs{f@nch@head}) or footer (\cs{f@nch@foot}) % given the left, center and right text and their widths, % fillers at left and right and a rule. The \cs{xlap} commands put @@ -7118,7 +7575,7 @@ % This is the right component. \\ % 5. RIGHTSIDE BEARING. This is always \cs{relax} or \cs{hss} % (after expansion).\\ -% 6-8. The specified widths for the left, center and right fields. +% 6. Even (\texttt{e}) or odd (\texttt{o}). % % Before constructing the header or footer, the environment is reset to % a known state, the appropriate hooks (\texttt{fancyhdr/before} and @@ -7133,14 +7590,14 @@ % \TTindex{fancyhdr/after}% % \texttt{fancyhdr/after}) are run. % \begin{macrocode} -\newcommand\f@nch@head[8]{% +\newcommand\f@nch@head[6]{% \f@nch@reset \ifdefined\UseHook\UseHook{fancyhdr/before}\UseHook{fancyhdr/head/begin}\fi \f@nch@headinit\relax #1% \hbox to\headwidth{% \f@nch@vbox\headheight{% - \f@nch@hfbox{#2}{#3}{#4}{b}{#6}{#7}{#8}% + \f@nch@hfbox{#2}{#3}{#4}{#6}{h}% \vskip\headruleskip\relax \headrule }% @@ -7170,13 +7627,15 @@ % \cs{fancyfootwidth} and \cs{fancyhfwidth}.} % \changes{fancyhdr v5.1}{2025/01/06}{Add paragraph hook restore code % (\cs{f@nch@restorepar}).} +% \changes{fancyhdr v5.2}{2025/01/25}{Implement \cs{fancyhfwidth} etc. +% \meta{alignment} option.} % We put the \cs{footrule} in a \cs{vbox} to accommodate for flexible % footrules (e.g., using \cs{hrulefill}), so that the \cs{headwidth} will % be used as the line width. But to preserve the vertical spacing we % then \cs{unvbox} this box. % % \begin{macrocode} -\newcommand\f@nch@foot[8]{% +\newcommand\f@nch@foot[6]{% \f@nch@reset \ifdefined\UseHook\UseHook{fancyhdr/before}\UseHook{fancyhdr/foot/begin}\fi \f@nch@footinit\relax @@ -7185,7 +7644,7 @@ \f@nch@vbox\footskip{% \setbox0=\vbox{\footrule}\unvbox0 \vskip\footruleskip - \f@nch@hfbox{#2}{#3}{#4}{t}{#6}{#7}{#8}% + \f@nch@hfbox{#2}{#3}{#4}{#6}{f}% % \end{macrocode} % \changes{fancyhdr v5.0}{2024/05/13}{\cs{vskip}\meta{length} % added if \cs{fancyfootalign}\protect\marg{length} was given.} @@ -7213,12 +7672,12 @@ % % \end{macro} % \begin{macro}[internal]{\f@nch@hfbox} -% This macro constructs the box with the header or footer. It has 7 parameters:\\ +% This macro constructs the box with the header or footer. It has 5 parameters:\\ % 1. Left field\\ % 2. Center field\\ % 3. Right field\\ -% 4. Vertical alignment: \texttt{b} for the header or \texttt{t} for the footer\\ -% 5-7. Widths for the left, center and right fields. +% 4. Even (\texttt{e}) or odd (\texttt{o}).\\ +% 5. Header (\texttt{h}) or footer (\texttt{f}). % % Algorithm:\\ % First we store the field widths in length variables.\\ @@ -7232,12 +7691,14 @@ % put the center field centered between the left and right field, i.e., % with equal gaps on both sides. This is done by the macro % \cs{f@nch@hfbox@fit}. +% \changes{fancyhdr v5.2}{2025/01/25}{Implement \cs{fancyhfwidth} etc. +% \meta{alignment} option.} % % \begin{macrocode} -\newcommand\f@nch@hfbox[7]{% - \setlength\f@nch@widthL{#5}% - \setlength\f@nch@widthC{#6}% - \setlength\f@nch@widthR{#7}% +\newcommand\f@nch@hfbox[5]{% + \setlength\f@nch@widthL{\csname f@nch@width@#4l#5\endcsname}% + \setlength\f@nch@widthC{\csname f@nch@width@#4c#5\endcsname}% + \setlength\f@nch@widthR{\csname f@nch@width@#4r#5\endcsname}% \let\@tempa\f@nch@hfbox@center \ifdim \dimexpr \f@nch@widthL+\f@nch@widthC+\f@nch@widthR>\headwidth \else @@ -7248,7 +7709,7 @@ \let \@tempa\f@nch@hfbox@fit \fi \fi - \@tempa{#1}{#2}{#3}{#4}% + \@tempa{#1}{#2}{#3}#4#5% } % \end{macrocode} % \end{macro} @@ -7260,15 +7721,18 @@ % 1. Left field\\ % 2. Center field\\ % 3. Right field\\ -% 4. Vertical alignment: \texttt{b} for the header or \texttt{t} for the footer\\ +% 4. Even (\texttt{e}) or odd (\texttt{o}).\\ +% 5. Header (\texttt{h}) or footer (\texttt{f}). +% \changes{fancyhdr v5.2}{2025/01/25}{Implement \cs{fancyhfwidth} etc. +% \meta{alignment} option.} % \begin{macrocode} -\newcommand\f@nch@hfbox@center[4]{% +\newcommand\f@nch@hfbox@center[5]{% \hbox to \headwidth{% - \rlap{\parbox[#4]{\f@nch@widthL}{\raggedright\leavevmode\ignorespaces#1}}% + \rlap{\f@nch@parbox{#1}\f@nch@widthL{#4}l{#5}}% \hfill - \parbox[#4]{\f@nch@widthC}{\centering\leavevmode\ignorespaces#2}% + \f@nch@parbox{#2}\f@nch@widthC{#4}c{#5}% \hfill - \llap{\parbox[#4]{\f@nch@widthR}{\raggedleft\leavevmode\ignorespaces#3}}% + \llap{\f@nch@parbox{#3}\f@nch@widthR{#4}r{#5}}% }% } % \end{macrocode} @@ -7280,34 +7744,108 @@ % 1. Left field\\ % 2. Center field\\ % 3. Right field\\ -% 4. Vertical alignment: \texttt{b} for the header or \texttt{t} for the footer\\ +% 4. Even (\texttt{e}) or odd (\texttt{o}).\\ +% 5. Header (\texttt{h}) or footer (\texttt{f}). +% \changes{fancyhdr v5.2}{2025/01/25}{Implement \cs{fancyhfwidth} etc. +% \meta{alignment} option.} % \begin{macrocode} -\newcommand\f@nch@hfbox@fit[4]{% +\newcommand\f@nch@hfbox@fit[5]{% \hbox to \headwidth{% - \parbox[#4]{\f@nch@widthL}{\raggedright\leavevmode\ignorespaces#1}% + \f@nch@parbox{#1}\f@nch@widthL{#4}l{#5}% \hfill - \parbox[#4]{\f@nch@widthC}{\centering\leavevmode\ignorespaces#2}% + \f@nch@parbox{#2}\f@nch@widthC{#4}c{#5}% \hfill - \parbox[#4]{\f@nch@widthR}{\raggedleft\leavevmode\ignorespaces#3}% + \f@nch@parbox{#3}\f@nch@widthR{#4}r{#5}% }% }% % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\MakeUppercase} -% Define \MakeUppercase for old \LaTeX{}en. Note: we used \cs{def} rather -% than \cs{let}, so that \verb+\let\uppercase\relax+ (from the version 1 -% documentation) will still work. +% \begin{macro}[internal]{\f@nch@parbox} +% This macro constructs one \cs{parbox} in the header or footer. +% It has 4 parameters:\\ +% 1. The contents\\ +% 2. The width for the \cs{parbox}.\\ +% 3. Even (\texttt{e}) or odd (\texttt{o}).\\ +% 4. Left (\texttt{l}), center (\texttt{c}) or right (\texttt{r}).\\ +% 5. Header (\texttt{h}) or footer (\texttt{f}).\\ +% Result: the proper \cs{parbox}\\[1ex] +% First we get (with \Cmd{csname}) the proper alignment parameter. Then we +% expand this so that \cs{f@nch@parbox@align} gets the two alignment letters +% as separate arguments. Then \cs{f@nch@parbox@align} is called to set +% up the alignment variables. After that we construct the \cs{parbox} +% with the calculated variables. +% \begin{macrocode} +\newcommand\f@nch@parbox[5]{% + \expandafter\expandafter\expandafter\f@nch@parbox@align + \csname f@nch@align@#3#4#5\endcsname + \parbox[\f@nch@align@@v]{#2}% + {% + \f@nch@align@@pre + \f@nch@align@@h\leavevmode\ignorespaces#1% + \f@nch@align@@post + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\f@nch@parbox@align} +% The macro \cs{f@nch@parbox@align} sets the alignment variables for \cs{f@nch@parbox}. +% It has 2 parameters, the two letters for the vertical and horizontal +% alignment, with the defaults applied.\\ +% 1. Vertical (\texttt{T, t, c, b, B}).\\ +% 2. Horizontal (\texttt{l, c, r, j}).\\ +% Result variables: +% \begin{description} +% \item[\cs{f@nch@align@@v}] The vertical alignment for the \cs{parbox}: +% \texttt{t}, \texttt{c} or \texttt{b}. +% \item[\cs{f@nch@align@@h}] The horizontal alignment for the +% \cs{parbox}: \cs{raggedright}, \cs{centering}, \cs{raggedleft} or +% empty for \texttt{l, c, r, j}, respectively. +% \item[\cs{f@nch@align@@pre}] code before the contents of the +% \cs{parbox}: \Cmd{vspace\{0pt\}} for \texttt{T} alignment, otherwise empty. +% \item[\cs{f@nch@align@@post}] code after the contents of the +% \cs{parbox}: \Cmd{vspace\{0pt\}} for \texttt{B} alignment, otherwise empty. +% \end{description} +% First we set the defaults for \cs{f@nch@align@@pre} and +% \cs{f@nch@align@@post} (empty). Then we call the proper macros for the +% alignment parameters. +% \begin{macrocode} +\newcommand\f@nch@parbox@align[2]{% + \def\f@nch@align@@pre{}% + \def\f@nch@align@@post{}% + \csname f@nch@parbox@align@v#1\endcsname + \csname f@nch@parbox@align@h#2\endcsname +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\f@nch@parbox@align@vT, +% \f@nch@parbox@align@vt, \f@nch@parbox@align@vc, \f@nch@parbox@align@vb, \f@nch@parbox@align@vB, \f@nch@parbox@align@hl, \f@nch@parbox@align@hc, \f@nch@parbox@align@hr, \f@nch@parbox@align@hj} % +% The macro \cs{f@nch@parbox@align@\meta{v$|$h}\meta{x}} sets the variables for the +% vertical or horizontal alignment option \texttt{\meta{x}}. % \begin{macrocode} -\f@nch@ifundefined{MakeUppercase}{\def\MakeUppercase{\uppercase}}{}% +\def\f@nch@parbox@align@vT{\def\f@nch@align@@v{t}\def\f@nch@align@@pre{\vspace{0pt}}} +\def\f@nch@parbox@align@vt{\def\f@nch@align@@v{t}} +\def\f@nch@parbox@align@vc{\def\f@nch@align@@v{c}} +\def\f@nch@parbox@align@vb{\def\f@nch@align@@v{b}} +\def\f@nch@parbox@align@vB{\def\f@nch@align@@v{b}\def\f@nch@align@@post{\vspace{0pt}}} +\def\f@nch@parbox@align@hl{\def\f@nch@align@@h{\raggedright}} +\def\f@nch@parbox@align@hc{\def\f@nch@align@@h{\centering}} +\def\f@nch@parbox@align@hr{\def\f@nch@align@@h{\raggedleft}} +\def\f@nch@parbox@align@hj{\def\f@nch@align@@h{}} % \end{macrocode} % \end{macro} % +% \changes{fancyhdr v5.2}{2025/01/28}{Remove fallback definition of \cs{MakeUppercase}.} +% % \begin{macro}[internal]{\@chapapp} % Define \cs{@chapapp} for classes that don't have it, e.g., amsbook +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % \begin{macrocode} -\f@nch@ifundefined{@chapapp}{\let\@chapapp\chaptername}{}% +\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{}% % \end{macrocode} % \end{macro} % \begin{macro}[internal]{\f@nch@initialise} @@ -7323,9 +7861,11 @@ % \begin{macro}{\sectionmark} % \begin{macro}{\subsectionmark} % Standard definitions for \cs{chaptermark}, \cs{sectionmark} and \cs{subsectionmark}. +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % % \begin{macrocode} - \f@nch@ifundefined{chapter}% + \@ifundefined{chapter}% {\def\sectionmark##1{\markboth{\MakeUppercase{\ifnum \c@secnumdepth>\z@ \thesection\hskip 1em\relax \fi ##1}}{}}% @@ -7369,8 +7909,8 @@ % Initialisation of the head and foot text. % % The default values still contain \cs{fancyplain} for compatibility: -% lefthead empty on ``plain'' pages, \cs{rightmark} on even, \cs{leftmark} on odd pages; -% evenhead empty on ``plain'' pages, \cs{leftmark} on even, \cs{rightmark} on odd pages. +% left head empty on ``plain'' pages, \cs{rightmark} on even, \cs{leftmark} on odd pages; +% right head empty on ``plain'' pages, \cs{leftmark} on even, \cs{rightmark} on odd pages. % \begin{macrocode} \fancyhf{}% \if@twoside @@ -7463,6 +8003,8 @@ % \changes{fancyhdr v4.1}{2022/09/06}{Implement \texttt{twoside} option.} % \changes{fancyhdr v5.0}{2025/01/01}{Support for \cs{fancyheadwidth}, % \cs{fancyfootwidth} and \cs{fancyhfwidth}.} +% \changes{fancyhdr v5.2}{2025/01/25}{Implement \cs{fancyhfwidth} etc. +% \meta{alignment} option.} % The actual implementation of page style \texttt{fancy}. For amsbook/amsart, which do % strange things with \cs{topskip}, we start with \cs{f@nch@ps@empty}. We % construct the even and odd headers and footers from all the parts that @@ -7471,8 +8013,7 @@ \def\ps@f@nch@fancycore{% \f@nch@ps@empty \def\@mkboth{\protect\markboth}% - \def\f@nch@oddhead{\f@nch@head\f@nch@Oolh\f@nch@olh\f@nch@och\f@nch@orh\f@nch@Oorh - \f@nch@width@olh\f@nch@width@och\f@nch@width@orh}% + \def\f@nch@oddhead{\f@nch@head\f@nch@Oolh\f@nch@olh\f@nch@och\f@nch@orh\f@nch@Oorh{o}}% \def\@oddhead{% \iff@nch@twoside \ifodd\c@page @@ -7484,8 +8025,7 @@ \f@nch@oddhead \fi } - \def\f@nch@oddfoot{\f@nch@foot\f@nch@Oolf\f@nch@olf\f@nch@ocf\f@nch@orf\f@nch@Oorf - \f@nch@width@olf\f@nch@width@ocf\f@nch@width@orf}% + \def\f@nch@oddfoot{\f@nch@foot\f@nch@Oolf\f@nch@olf\f@nch@ocf\f@nch@orf\f@nch@Oorf{o}}% \def\@oddfoot{% \iff@nch@twoside \ifodd\c@page @@ -7497,10 +8037,8 @@ \f@nch@oddfoot \fi } - \def\@evenhead{\f@nch@head\f@nch@Oelh\f@nch@elh\f@nch@ech\f@nch@erh\f@nch@Oerh - \f@nch@width@elh\f@nch@width@ech\f@nch@width@erh}% - \def\@evenfoot{\f@nch@foot\f@nch@Oelf\f@nch@elf\f@nch@ecf\f@nch@erf\f@nch@Oerf - \f@nch@width@elf\f@nch@width@ecf\f@nch@width@erf}% + \def\@evenhead{\f@nch@head\f@nch@Oelh\f@nch@elh\f@nch@ech\f@nch@erh\f@nch@Oerh{e}}% + \def\@evenfoot{\f@nch@foot\f@nch@Oelf\f@nch@elf\f@nch@ecf\f@nch@erf\f@nch@Oerf{e}}% } % \end{macrocode} % \end{macro} @@ -7679,12 +8217,14 @@ % Declare it as a fancyhdr-based page style. % \changes{fancyhdr v4.0}{2019/09/05}{Make the definition of \cs{f@nch@pagestyle} \cs{long}.} % \changes{fancyhdr v5.0}{2021/02/17}{Add \cs{fancypagestyle*}} +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % \begin{macrocode} \long\def\f@nch@@pagestyle#1[#2]#3{% - \f@nch@ifundefined{ps@#2}{% + \@ifundefined{ps@#2}{% \PackageError{fancyhdr}{\string\fancypagestyle: Unknown base page style `#2'}{}% }{% - \f@nch@ifundefined{f@nch@ps@#2-is-fancyhdr}{% + \@ifundefined{f@nch@ps@#2-is-fancyhdr}{% \PackageError{fancyhdr}{\string\fancypagestyle: Base page style `#2' is not fancyhdr-based}{}% }% {% @@ -7714,6 +8254,10 @@ % \changes{fancyhdr v5.0}{2021/03/27}{Also save the offset length variables % \cs{f@nch@offset@xyz} with \cs{setlength}} % \changes{fancyhdr v5.0}{2022/01/24}{Replace \cs{myname} with \cs{temp@a}} +% \changes{fancyhdr v5.0}{2025/01/02}{Implement \cs{fancyhfwidth} etc., +% store \meta{width}.} +% \changes{fancyhdr v5.2}{2025/01/27}{Implement \cs{fancyhfwidth} etc., +% store \meta{alignment}.} % \begin{macrocode} \newcommand\f@nch@pagestyle@setup{% \iff@nch@pagestyle@star @@ -7723,8 +8267,9 @@ % \begin{macrocode} \iff@nch@check\@temptokenb={\f@nch@checktrue}\else\@temptokenb={\f@nch@checkfalse}\fi % \end{macrocode} -% Save values of all relevant macros (26 in total):\\ +% Save values of all relevant macros (50 in total):\\ % headers and footers (12), header and footer widths (12), +% header and footer alignments (12), % header and footer offsets (8), header and footer inits (2), % \cs{headrule} and \cs{footrule} and \texttt{...width} (4) % \begin{macrocode} @@ -7734,6 +8279,9 @@ \f@nch@width@elh\f@nch@width@ech\f@nch@width@erh\f@nch@width@olh \f@nch@width@och\f@nch@width@orh\f@nch@width@elf\f@nch@width@ecf \f@nch@width@erf\f@nch@width@olf\f@nch@width@ocf\f@nch@width@orf + \f@nch@align@elh\f@nch@align@ech\f@nch@align@erh\f@nch@align@olh + \f@nch@align@och\f@nch@align@orh\f@nch@align@elf\f@nch@align@ecf + \f@nch@align@erf\f@nch@align@olf\f@nch@align@ocf\f@nch@align@orf \f@nch@Oolh\f@nch@Oorh\f@nch@Oelh\f@nch@Oerh \f@nch@Oolf\f@nch@Oorf\f@nch@Oelf\f@nch@Oerf \f@nch@headinit\f@nch@footinit @@ -7782,6 +8330,8 @@ % \end{macro} % \begin{macro}{\fancypagestyleassign} % \changes{fancyhdr v5.0}{2024/12/25}{Macro \cs{fancypagestyleassign} added} +% \changes{fancyhdr v5.2}{2025/01/15}{Use \cs{@ifundefined} instead of +% \cs{f@nch@ifundefined}.} % \begin{syntax} % \cs{fancypagestyleassign}\marg{ps1}\marg{ps2} % \end{syntax} @@ -7791,26 +8341,18 @@ % command, like \cs{let}\cs{ps@\meta{ps1}}\cs{ps@\meta{ps2}}. % \begin{macrocode} \newcommand\fancypagestyleassign[2]{% - \f@nch@ifundefined{ps@#2}{% + \@ifundefined{ps@#2}{% \PackageError{fancyhdr}{\string\fancypagestyleassign: Unknown page style `#2'}{}% }{% \expandafter\let \csname ps@#1\expandafter\endcsname \csname ps@#2\endcsname % \end{macrocode} -% If \meta{ps2} is not fancyhdr-based, \meta{ps1} will also be -% fancyhdr-based, otherwise it will not. If \meta{ps2} is not -% fancyhdr-based, but \meta{ps1} is, give a warning that it is -% overwritten, which could give unexpected problems. -% \begin{macrocode} - \f@nch@ifundefined{f@nch@ps@#2-is-fancyhdr}{% - \f@nch@ifundefined{f@nch@ps@#1-is-fancyhdr}{}{% - \PackageNote{fancyhdr}{% - \string\fancypagestyleassign: You overwrite the\MessageBreak - fancyhdr-based page style `#1' with the\MessageBreak - non-fancyhdr-based page style `#2'.\MessageBreak - This could cause unexpected problems if you\MessageBreak - use `#1' as the base style in \string\fancypagestyle}}% +% If \meta{ps2} is fancyhdr-based, \meta{ps1} will also be +% fancyhdr-based, otherwise it is not. +% \changes{fancyhdr v5.2}{2025/01/27}{Remove \Cmd{PackageNote}.} +% \begin{macrocode} + \@ifundefined{f@nch@ps@#2-is-fancyhdr}{% \expandafter\let\csname f@nch@ps@#1-is-fancyhdr\endcsname\@undefined }{% \@namedef{f@nch@ps@#1-is-fancyhdr}{}% @@ -7928,7 +8470,7 @@ % \begin{macro}[internal]{\f@nchdrbox@cr, \@f@nchdrbox@xcr, % \@f@nchdrbox@argc, \@f@nchdrbox@xargc, \@f@nchdrbox@yargc} % This is the definition for \cmd{\\} inside \cs{fancyhdrbox}, -% \cmd{\\*} does nothing special here, but we acccept it anyway. +% \cmd{\\*} does nothing special here, but we accept it anyway. % The code is mostly copied from the \env{tabular} code from the % \LaTeX{} kernel, but simplified, and the names of the macros are % changed so that we don't rely on internals in the \LaTeX{} kernel that @@ -7988,6 +8530,8 @@ % \end{macro} % % \begin{macro}[internal]{\f@nchdrbox@align} +% \changes{fancyhdr v5.2}{2025/01/23}{Check for legal alignment +% argument added.} % \cs{f@nchdrbox@align}\marg{vert}\marg{hor}\texttt{\cs{@nil}}\marg{lines}\\[1ex] % The internal processing for the \cs{halign} in a vertical box.\\ % ALGORITHM \cs{f@nchdrbox@align}:\\ @@ -8001,10 +8545,11 @@ % \hspace*{1em} v := \texttt{c}\\ % \hspace*{1em} h := \texttt{\#1}\\ % \textbf{FI}\\ +% \textbf{if} h not in \texttt{\{l,c,r\}} \textbf{then} ERROR \textbf{fi}\\ % Set the \cs{halign} in a \cs{vtop} (for \texttt{T/t} alignment) or % \cs{vbox} (for others). This box is put into \cs{box0} because we have % to change it for the vertical alignment \texttt{c}. For the others it -% isn't necesary, but it just makes the code easier to do it anyway. +% isn't necessary, but it just makes the code easier to do it anyway. % We also insert the \cs{f@nchdrbox@@pre}, % \cs{f@nchdrbox@@postx} and \cs{f@nchdrbox@@posty} variables in the % proper places. The rest of the code is roughly based on the @@ -8017,6 +8562,9 @@ \ifx\@tempa\@empty\else \def\f@nchdrbox@@h{#2}\fi }% {\def\f@nchdrbox@@v{c}\def\f@nchdrbox@@h{#1}}% + \expandafter\f@nch@ifin\expandafter{\f@nchdrbox@@h}{lcr}{}% + {\PackageError{fancyhdr}{\string\fancyhdrbox: Illegal char `\f@nchdrbox@@h'\MessageBreak + in alignment argument}{}}% \let\\\f@nchdrbox@cr \setbox0=\if \f@nchdrbox@@v t\vtop \else \vbox @@ -8095,12 +8643,12 @@ % % \changes{extramarks v5.0}{2024/05/14}{New implementation with % independent marks, and fallback option to earlier version 4.} -% Provide a rollback to earlier version +% Provide a rollback to earlier version. +% \changes{extramarks v5.2}{2025/01/15}{Assume \cs{DeclareRelease} is +% present (\LaTeX{} version at lease 2018-04-01).} % \begin{macrocode} -\providecommand\DeclareRelease[3]{} -\providecommand\DeclareCurrentRelease[2]{} \DeclareRelease{v4}{2024/11/30}{extramarks-v4.sty} -\DeclareCurrentRelease{}{2025/01/07} +\DeclareCurrentRelease{v5}{2025/02/07} \@ifundefined{NewMarkClass} {\PackageWarningNoLine{extramarks}{% **************************************************\MessageBreak |