% \iffalse meta-comment %<=*COPYRIGHT> %% Copyright (c) 2011-2022 by Martin Scharrer %% ------------------------------------------------------------------- %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 %% of this license or (at your option) any later version. %% The latest version of this license is in %% http://www.latex-project.org/lppl.txt %% and version 1.3 or later is part of all distributions of LaTeX %% version 2005/12/01 or later. %% %% This work has the LPPL maintenance status `maintained'. %% %% The Current Maintainer of this work is Martin Scharrer. %% %% This work consists of the files ifoddpage.dtx and ifoddpage.ins %% and the derived filebase ifoddpage.sty. %% %<=/COPYRIGHT> % \fi % % \iffalse %<*driver> \ProvidesFile{ifoddpage.dtx}[% %<=*DATE> 2022/10/18 %<=/DATE> %<=*VERSION> v1.2 %<=/VERSION> DTX file for ifoddpage package] \documentclass{ydoc} \GetFileInfo{ifoddpage.dtx} \usepackage{ifoddpage}[\filedate] \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{ifoddpage.dtx} \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{90} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{v1.0}{2011/09/13}{First version.} % \changes{v1.1}{2016/04/23}{Fixed misspelled macro name.} % \changes{v1.2}{2022/10/18}{Updated documentation.} % % % \DoNotIndex{\newcommand,\newenvironment} % % \GetFileInfo{ifoddpage.dtx} % \author{Martin Scharrer} % \email{martin.scharrer@web.de} % \repository{https://github.com/MartinScharrer/ifoddpage} % \maketitle % % \section{Introduction} % Sometimes it is required to know if a macro is placed on an odd or even page. % Simply testing the value of the \texttt{page} counter is not reliable, because \TeX\ reads and processes often more material than fits on the currently processed % page in order to decide where to place the page break. Also moving material like floats can be placed on completely different pages than where the surrounding material % is placed. The only reliable way to determine the correct page number is to write it to the auxiliary file using a label and read it back in the next compiler run. % Labels use a so called \emph{whatsit}s (see \emph{The TeXBook}) to write the given code to the auxiliary file \emph{just when the material is shipped out}, i.e.\ a full page has % been filled and is written to the output file. This way ensures that the determined page number is always correct, but adds an overhead. % % This package implements the described technique. A macro must be used to generate and read-back the label before the conditional can be used. % A counter is used internally to provide unique names to the labels. % % % \section{Usage} % The following macros are provided for \LaTeX\ document authors: % % \DescribeMacro{\checkoddpage} % This macro checks if the current page is odd or even by placing a label to the auxiliary file and reading it back in. % This requires a second compiler run to work perfectly, but the code falls back to use the \texttt{page} counter value % if the label is not yet defined, i.e.\ the label was just added or no auxiliary file existed. % This fallback code might return wrong values for material just around page breaks, but % is better than using a constant. % % Note that this macro inserts an invisible element (a so called \emph{whatsit}) which is placed on the page. % It is possible that this happens to be at the very end of the last line of the page and any other code following it would then be placed % on the next page. Some code like |\checkoddpage \ifoddpage odd\else even\fi| might then place the first macro on the current, say even, page but % print `|even|' at the top of the next page which is odd. In order to avoid this both the check macro and the output text can be placed in the same % box (e.g.\ |\mbox|). If the full content can't be placed in a box, e.g.\ because line breaking is required a |\mbox| can also be substituded by % |\leavevmode| (to start a paragraph if required) and |\hbox| where the |{}| are replaced by |\bgroup| and |\egroup| so two alternative box ends can be specified: % % \begin{lstlisting}[gobble=2,numbers=none,basicstyle=\ttfamily] % \leavevmode\hbox\bgroup % \checkoddpage % \ifoddpage % odd\egroup\ more text % \else % even\egroup\ other text % \fi % \end{lstlisting} % % \noindent % This boxes the \Macro\checkoddpage with the first word of both clauses. Note that in this case it the settings are local to the box scope and \Macro\ifoddpage should % be used outside of it again (without another \Macro\checkoddpage). % % \DescribeMacro{ifoddpage} % This \TeX\ conditional is set (locally) by \Macro\checkoddpage. % It is true if the current page is odd, or false if it is even. This is independent from whether the \texttt{oneside} or \texttt{twoside} mode is used. % % \DescribeMacro{ifoddpageoroneside} % This \TeX\ conditional is set (locally) by \Macro\checkoddpage. % Like the previous conditional it is true if the current page is odd, or false if it is even. % However, if the \texttt{oneside} mode is active it is always true. % This is useful for code which needs to check if the odd or even page layout is used, because in \texttt{oneside} mode the odd page layout is used for all pages. % % \par\medskip\par\noindent % The following macros are intended for package authors: % % \DescribeMacro{\@ifoddpage}{}{} % This \LaTeX\ macro uses \Macro{ifoddpage} and executes its first argument if that conditional is true but the second argument if it is false. % The \Macro\checkoddpage must be used closely beforehand to get correct results. % % \DescribeMacro{\@ifoddpageoroneside}{}{} % This \LaTeX\ macro uses \Macro{ifoddpageoroneside} and executes its first argument if that conditional is true but the second argument if it is false. % The \Macro\checkoddpage must be used closely beforehand to get correct results. % % \DescribeMacro{\oddpage@page} % This macro expands (using multiple steps) to a text representation of the page number for the last \Macro\checkoddpage. % It is used in this macro together with \Macro\ifodd to set the provided conditionals. % % % \section{Similar packages} % The \pkg{changepage} package and the \pkg{memoir} class also provide the core functionality of this package, i.e.\ they define \Macro\checkoddpage and \Macro\ifoddpage but no other of the mentioned macros. % That package uses this conditional internally in order to allow the user to change the page layout for odd or even pages, which is its main function. % The \pkg{ifoddpage} should work together with that package and class, but should be loaded last to ensure the correct functionality of \Macro{ifoddpageoroneside}. % It also uses labels if it is loaded using the \texttt{strict} option. % The \pkg{ifoddpage} has the following benefits over \pkg{changepage} (if the page layout doesn't have to be changed): % % \begin{itemize} % \item Smaller code base, because no additional functionality is provided. % \item The \Macro{ifoddpageoroneside} conditional is also provided which simplifies code which has to handle odd/even margins. % \item The label code uses the same internal \LaTeX-core code as the normal \Macro\label and generates identical error, warning and info messages. % \item The fallback page number is not constant (0) but the current \texttt{page} counter value is used, which is a good approximation. % \end{itemize} % % \StopEventually{} % % \clearpage % \section{Implementation} % % \iffalse %<*ifoddpage.sty> % \fi % \begin{macrocode} % \NeedsTeXFormat{LaTeX2e}[1999/12/01] \ProvidesPackage{ifoddpage}[% % % %<*DRIVER> 2099/01/01 develop % Conditionals for odd/even page detection] % \end{macrocode} % % \begin{macro}{\c@checkoddpage} % Counter |checkoddpage| is needed to give each use of \Macro\checkoddpage an unique ID for % \begin{macrocode} \newcount\c@checkoddpage % \end{macrocode} % \end{macro} % % \begin{macro}{\thecheckoddpage} % Expands to the value of |checkoddpage|, i.e. ID of last used \Macro\checkoddpage. % \begin{macrocode} \def\thecheckoddpage{\number\c@checkoddpage} % \end{macrocode} % \end{macro} % % \begin{macro}{\ifoddpage} % Conditional: true if used on odd page after \Macro\checkoddpage. % \begin{macrocode} \newif\ifoddpage % \end{macrocode} % \end{macro} % % \begin{macro}{\ifoddpageoroneside} % Conditional: true if used on odd page after \Macro\checkoddpage. % Always true if used in a |oneside| document. % \begin{macrocode} \newif\ifoddpageoroneside % \end{macrocode} % \end{macro} % % \begin{macrocode} \let\oddpage@checkpage\relax % \end{macrocode} % % \begin{macro}{\oddpage@page} % \begin{macrocode} \def\oddpage@page{1} % \end{macrocode} % \end{macro} % % % \begin{macro}{\oddpage@label} % Produces a LaTeX label using the |checkoddpage| counter. % An internal LaTeX macro is used for this. % \begin{macrocode} \def\oddpage@label{% \@newl@bel{checkoddpage}% }% \write\@auxout{\noexpand\providecommand\noexpand\oddpage@label[2]{}}% % \end{macrocode} % \end{macro} % % % \begin{macro}{\oddpage@checkpage} % Writes the oddpage label with the current page number to the AUX file, % so it can be read back during the following \LaTeX{} runs. % \begin{macrocode} \def\oddpage@checkpage#1{% \@bsphack \write\@auxout{\string\oddpage@label{#1}{\the\c@page}}% \@esphack }% % \end{macrocode} % \end{macro} % % % \begin{macro}{\oddpage@page} % Returns the page number of the last \Macro\checkoddpage macro. % If there is no label for it defined in the AUX file, e.g.\ first compile run, % then the current page number is used instead as a fallback. % \begin{macrocode} \def\oddpage@page{% \expandafter\ifx\csname checkoddpage@\thecheckoddpage\endcsname\relax \the\c@page \else \csname checkoddpage@\thecheckoddpage\endcsname \fi }% % \end{macrocode} % \end{macro} % % % \begin{macro}{\checkoddpage} % User macro to check if the current page has an odd page number. % Increases |checkoddpage| counter to produce an unique ID for this macro usage. % Calls \Macro\oddpage@checkpage to produce a reference entry in the AUX file. % Then checks if the \Macro\oddpage@page is odd and sets % \Macro{ifoddpage} and \Macro{ifoddpageoroneside} accordantly. % Finally checks if the |twoside| setting is active and set \Macro{ifoddpageoroneside} % to |true| if so. % \begin{macrocode} \DeclareRobustCommand\checkoddpage{% \stepcounter{checkoddpage}% \expandafter\oddpage@checkpage\expandafter{\number\c@checkoddpage}% \ifodd\oddpage@page\relax \oddpagetrue \oddpageoronesidetrue \else \oddpagefalse \oddpageoronesidefalse \fi \if@twoside\else \oddpageoronesidetrue \fi }% % \end{macrocode} % \end{macro} % % % \begin{macro}{\@ifoddpage} % Wrapper around \Macro{ifoddpage}. Will expand to the next token if odd, to the second token if not. % \begin{macrocode} \def\@ifoddpage{% \ifoddpage \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@ifoddpageoroneside} % Wrapper around \Macro{ifoddpageoroneside}. Will expand to the next token if odd, to the second token if not. % \begin{macrocode} \def\@ifoddpageoroneside{% \iftwosideoddside \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } % \end{macrocode} % \end{macro} % % \iffalse % % \fi % % \Finale % \endinput