% \iffalse meta-comment
%
% This program is free software; you can redistribute it and/or
% modify it under the terms of the GNU General Public License
% as published by the Free Software Foundation; either version 2
% of the License, or (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
%
% \fi
%
% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ }
% \DoNotIndex{\def,\long,\edef,\xdef,\gdef,\let,\global}
% \DoNotIndex{\if,\ifnum,\ifdim,\ifcat,\ifmmode,\ifvmode,\ifhmode,%
%             \iftrue,\iffalse,\ifvoid,\ifx,\ifeof,\ifcase,\else,\or,\fi,\loop,\do}
% \DoNotIndex{\box,\copy,\setbox,\unvbox,\unhbox,\hbox,%
%             \vbox,\vtop,\vcenter}
% \DoNotIndex{\@empty,\immediate,\write}
% \DoNotIndex{\egroup,\bgroup,\expandafter,\begingroup,\endgroup}
% \DoNotIndex{\divide,\advance,\multiply,\count,\dimen}
% \DoNotIndex{\relax,\space,\string}
% \DoNotIndex{\csname,\endcsname,\@spaces,\openin,\openout,%
%             \closein,\closeout}
% \DoNotIndex{\catcode,\endinput}
% \DoNotIndex{\jobname,\message,\read,\the,\noexpand}
% \DoNotIndex{\hsize,\vsize,\hskip,\vskip,\kern,\hfil,\hfill,\hss}
% \DoNotIndex{\m@ne,\z@,\@m,\z@skip,\@ne,\tw@,\p@}
% \DoNotIndex{\DeclareRobustCommand,\DeclareOption,\newcommand,\newcommand*}
% \DoNotIndex{\newcount,\newif,\newlinechar,\newread,\newtoks,\newwrite}
% \DoNotIndex{\dp,\wd,\ht,\vss,\unskip}
%
% \CheckSum{417}
%
% \MakeShortVerb\|
%
% \iffalse
%    \begin{macrocode}
%<*driver>
\documentclass{ltxdoc}
\RequirePackage{hyperref}
\EnableCrossrefs
 %\DisableCrossrefs % Say \DisableCrossrefs if index is ready
\CodelineIndex
\RecordChanges
\setcounter{IndexColumns}{2}    % make a twocolumn index
\setlength{\columnseprule}{0pt} % no rules between columns ...
\setlength{\columnsep}{2em}     % ... but more spacing instead.
\setcounter{unbalance}{4}
\setlength{\IndexMin}{100pt}
\OnlyDescription
\setlength\hfuzz{3pt}
%\hbadness=7000
\frenchspacing
\begin{document}
   \DocInput{mparhack.dtx}
   \raggedright
\end{document}
%</driver>
%    \end{macrocode}
% ^^A See CTAN:tools/filehdr/filehdr.dvi for an explanation for the following stuff
%
% ===================================================================
%  @LaTeX-package-file{
%     version         = "1.5",
%     date            = "2021-05-02",
%     filename        = "mparhack.sty",
%     author-1        = "Tom Sgouros",
%     email-1         = "tomfool@top.gso.uri.edu",
%     author-2        = "Stefan Ulrich",
%     email-2         = "stefanulrich@users.sourceforge.net",
%     codetable       = "ISO/ASCII",
%     keywords        = "marginpar, marginpars, marginal notes, wrong margin"
%     supported       = "yes",
%     docstring       = "User manual and documented source code and for the
%                        LaTeX package mparhack.sty"
%  }
% ===================================================================
% \fi
% \newcommand*\Com[1]{\texttt{\char`\\#1}}
% \newcommand*\File[1]{\texttt{#1}}
% \newcommand*\Explanation[1]{\noindent
%       \rule[.5ex]{.4\linewidth}{.6pt}\kern1em
%       ^^A$\bullet\bullet\bullet$
%       {\itshape\small #1}^^A
%       }^^A\kern1em\rule[.5ex]{6em}{.6pt}}
% \newenvironment{Addition}{\par\noindent\Explanation{begin addition}\par\noindent\ignorespaces}^^A
%       {\Explanation{end addition}}
% \newenvironment{Replacement}{\par\noindent\Explanation{begin replacement:}\par\noindent\ignorespaces}^^A
%       {\Explanation{end replacement}}
% \newcommand*\ReplacedBy{\par\noindent\Explanation{by:}\par\noindent\ignorespaces}
% \newcommand*\PackageNameNoExt{mparhack}
% \newcommand*\PackageName{\texttt{\PackageNameNoExt.sty}}
% \def\AfterElseFi#1\else#2\fi{\else#2\fi#1}
% \GetFileInfo{mparhack.sty}
% \title{\PackageName}
% \author{Tom Sgouros\\ {\small\texttt{tomfool@top.gso.uri.edu}} \and
%       Stefan Ulrich\\ {\small\href{mailto:stefanulrich@users.sourceforge.net}{\texttt{stefanulrich@users.sourceforge.net}}}}
% \date{v1.5 2021-05-02\\[1ex] {\footnotesize CTAN:
% \href{https://ctan.org/pkg/mparhack}
%      {\texttt{https://ctan.org/pkg/mparhack}}}
%  \\[1ex]
% {\footnotesize Github:
% \href{https://github.com/u-fischer/mparhack}
%      {\texttt{https://github.com/u-fischer/mparhack}}}
%      }
% \maketitle
%
% \begin{abstract}
%    This package implements a workaround for the \LaTeX\ bug
%    that marginpars sometimes show up on the wrong margin.
% \end{abstract}
%
% \changes{v1.0}{1999/03/02}{Created}
% \changes{v1.1}{1999/09/23}{Rewrite to use only one label per page, and to implement
%               `twocolumn' document option.}
% \changes{v1.2}{2000/02/29}{Small documentation changes}
% \changes{v1.2a}{2000/03/14}{Fixed the \Com{NeedsTeXFormat} to use 1997/04/14}
% \changes{v1.2c}{2001/02/07}{Small documentation changes}
% \changes{v1.3}{2001/02/07}{Use \Com{mph@tempa} instead of \Com{@tempa} to avoid
%               possible clashes with other classes (e.g. scrpage2)}
% \changes{v1.4}{2005/04/17}{Fix a bug with eso-pic.sty (latex/3775)}
%
%
% {\parskip 0pt \tableofcontents }
%
% ^^A --------------------------------------------------
% \section{Introduction}
% ^^A --------------------------------------------------
%
%    A persistent problem with the |\marginpar| command is that the
%    marginalia produced often show up on the wrong margin.  This has
%    been noted in the \LaTeX\ bugs database.^^A
%       \footnote{See \url{https://www.latex-project.org/cgi-bin/ltxbugs2html}:
%       \href{https://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/2361}{latex/2361},
%       \href{https://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/2484}{latex/2484},
%       \href{https://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/2617}{latex/2617}.}
%
%
%    The problem occurs most likely when a marginpar appears near
%    the top of a page. The problem is exacerbated when
%    the page break penalties are adjusted so that the page look is
%    quite ragged.  In cases like this, if there is a deal of white
%    space on a page, the marginpars on the next page will be on the
%    wrong side for the same length of the page.
%    The reason for this is that the \LaTeX\ output routine is not
%    in complete synchronization with the \TeX\ page breaker, so that
%    sometimes
%    material might still move to a later page \emph{after} \LaTeX's
%    marginpar algorithm has determined a page number for the marginpar.
%
%    The fix suggested in the bugs database is to insert |\pagebreak|
%    commands at the places where the page breaks naturally fall;
%    then the marginpars will appear on the correct side.  However, this is
%    awkward and unpleasant work for a document that changes
%    regularly, and seems to fly against the spirit of \LaTeX.
%
%    A different approach was suggested by D. E. Knuth in his
%    \emph{Macros for Jill}\footnote{Originally published in TUGboat
%    \textbf{8}, pp.~309--314, reprinted in his \emph{Digital
%    Typography} pp.~185--193.}: make two |.dvi| files, one with all
%    notes in the left margin, the other one with all notes in the
%    right margin. Then print the odd pages from one file, and the
%    even pages from the other file; merge them by hand.
%
%    However, Knuth also mentions the possibility to use an auxiliar
%    file to save the page information for each marginpar and use this
%    information to position it correctly in a second \TeX\ run; and
%    this is the strategy adopted by \PackageName.
%    Each marginpar is assigned a unique number; the output routine
%    writes the number of the last marginpar of each page\slash column
%    to the |.aux| file, and this information is used in
%    |\@addmarginpar| to position the current marginpar on the correct
%    margin.
%
%
% ^^A --------------------------------------------------
%    \section{Usage}
% ^^A --------------------------------------------------
%    Just insert |\usepackage{mparhack}| into your document preamble.
%    After the first run, you'll probably get the warning message
%    `\texttt{Marginpars may have changed. Rerun to get them right}'.
%    This is similar to \LaTeX's warning `\texttt{Label(s) may have
%    changed}'; it indicates that the |.aux| file doesn't contain the
%    information needed to position the marginpars correctly, due to
%    some changes in the document since the last run. The warning
%    should go away after running \LaTeX\ again (eventually several
%    times if there's also a table of contents etc.).
%
%    \DescribeMacro{debug}^^A
%    If you think something is going wrong, the package also has a
%    \texttt{debug} option; this will output a lot of tracing
%    information and will add numbers to the marginpars in the |.dvi|
%    file for reference.
%
%
% ^^A --------------------------------------------------
%    \section{Bugs\slash Restrictions}
% ^^A --------------------------------------------------
%    \begin{itemize}
%    \item
%       The package works with the |twocolumn| document option, but not
%       with the |multicol| package (you can't use marginpars inside
%       the |multicols| environment).
%    \item
%       The package uses one command sequence per page, and the total number
%       of command sequences available is limited on most \TeX\ systems.
%       Note however that most current \TeX\ implementations
%       can allocate more than several thousand command names, and some can
%       be configured to allocate more than the default during run-time,
%       so this shouldn't be a problem for moderately sized documents.
%    \item
%       The package has to hook into three commands of the \LaTeX2e\ output
%       routine (by redefining some command), so it requires at least
%       \LaTeX\ version 1997/04/14 and might break with future \LaTeX\
%       versions that change these commands.
%       We try to detect this by requiring a version newer than 1997/04/14
%       and using some heuristics to check if the redefinitions have worked.
%       You should watch out for this warning message:\par
%       {\ttfamily\footnotesize\begin{tabular}{@{}l@{}l@{}}
%LaTeX Warning:&\  You have requested release `1997/04/14' of LaTeX,\\
%              &\  but only release `...' is available.
%       \end{tabular}}\par\noindent
%       It might be that the package also works with older versions of \LaTeX,
%       but this hasn't been tested. If one of the heuristics detects an incompatible
%       change, it will raise an error:\par
%       {\ttfamily\footnotesize\begin{tabular}{@{}l@{}}
%Package mparhack Error: Couldn't hook into command `xyz'.
%       \end{tabular}}\par\noindent
%       \vskip-\lastskip\noindent
%       It might also happen that the heuristics don't detect a change
%       properly. If the package simply seems to fail, this could be a reason.
%       In both cases, please send a bug report to
%       \href{mailto:stefanulrich@users.sourceforge.net}{\texttt{stefanulrich@users.sourceforge.net}}
%       (if neccessary including the
%       |.log| file of your \LaTeX\ run with the \texttt{debug}
%       package option enabled). Suggestions/improvements are also welcome,
%       of course.
%    \end{itemize}
%
% ^^A --------------------------------------------------
%    \section{Acknowledgements}
% ^^A --------------------------------------------------
%    Thanks to Donald Arseneau and Robin Fairbairns for providing
%    detailed hints\footnote{in \texttt{<23AUG199920123097@erich.triumf.ca>} and
%    \texttt{<7prb8s\$dpr\$1@pegasus.csx.cam.ac.uk>}, respectively.}
%    on how to implement the page referencing mechanism using only one
%    label per page (instead of one label each marginpar, as in a
%    previous version).
%
%    \AlsoImplementation
%    \StopEventually{\relax}
% ^^A --------------------------------------------------
%    \section{Implementation}
% ^^A --------------------------------------------------
%
% ^^A --------------------------------------------------
%    \subsection{Overview}\label{implementation}
% ^^A --------------------------------------------------
%    Here's the algorithm for recording the positioning information for
%    marginpars in more detail: Every marginpar has a unique number $n$ and
%    writes to the |.aux| file a string like\par\medskip
% ^^A
%    \begin{tabular}{@{}l}
%       |\def\mph@nr{|$n$|}|.
%    \end{tabular}\par\medskip
%
%    The commands shipping out the columns and pages write to the
%    |.aux| file strings like:\par\medskip
% ^^A
%    \begin{tabular}{@{}l}
%       |\mph@setcol{|$x{\texttt{:}}$|\thepage}{\mph@nr}|,
%    \end{tabular}\par\medskip\noindent
% ^^A
%    with $x = \mbox{i}$ for the first column and $x = \mbox{ii}$
%    otherwise. Then when reading the |.aux|
%    file at the begin of the \LaTeX\ run, |\mph@nr| will be substitued
%    by the number of the last marginpar (the value of the |\mph@nr| command
%    read before that),
%    and |\mph@setcol| will assign that number to the command sequence |\csname|
%    |mph@last@|$x{\texttt{:}}$|\thepage\endcsname|; so this will contain
%    the number of the last marginpar on column\slash page $x{\texttt{:}}$|\thepage|.
%
%    Later on, in the document itself, |\@addmarginpar| will be able to check the value of
%    |\csname| |mph@last@|$x{\texttt{:}}$\Com{thepage}\Com{end\-csname},
%    using the current values for $x$ and |\thepage|.  Then there are two
%    cases:
%
%    (a) |\csname| |mph@last@|$x{\texttt{:}}$|\thepage\endcsname| is
%    undefined, which means that there has been no |.aux| file
%    previously, or that there are more pages\slash marginpars than in
%    the previous run; in this case, |\@addmarginpar| will fall back to using
%    the value of |\c@page| to determine the current page number (yielding the
%    same result as without this package), or
%
%    (b) |\csname| |mph@last@|$x{\texttt{:}}$|\thepage\endcsname| is defined as
%    an integer $z$, the number of the last marginpar on |\thepage|.
%    Then $z \leq n$, the number of the current marginpar.^^A
%    \footnote{$z$ cannot be greater than $n$: this would
%    mean that \TeX\ had shifted some material (including a marginpar)
%    from later pages to earlier pages, which AFAIK cannot happen.}
%    While $z < n$, the page counter will be incremented (inside a group)
%    until |\csname| |mph@last@|$x{\texttt{:}}$|\thepage\endcsname| for
%    that new page is $\geq n$, or until
%    we end up in case (a). The incremented value for the page counter
%    now represents the actual page number of the current marginpar,
%    and it will be used instead of the original page counter in the
%    check for even-\slash oddness.
%
% ^^A --------------------------------------------------
%    \subsection{Code}
% ^^A --------------------------------------------------
%
%    We need at least \LaTeX\ version 1997/04/14 which introduced
%    |\normalsfcodes| into |\@outputdblcol|.
%    \begin{macrocode}
%<*sty>
\NeedsTeXFormat{LaTeX2e}[1997/04/14]
\ProvidesPackage{mparhack}
      [2021-05-02 v1.5  (T. Sgouros and S. Ulrich)]
%    \end{macrocode}
% ^^A --------------------------------------------------
%    \subsubsection{Booleans, Options, etc.}
% ^^A --------------------------------------------------
%    Some boolean switches which we will be using:
%    |\if@mph@firstcol@| indicates that the current column is the
%    first column, |\if@mph@warning@| toggles the warning message
%    about changed marginpars, and |\if@debug@| toggles printing (lots
%    of) debugging messages.
%    \begin{macrocode}
\newif\if@mph@firstcol@
\newif\if@mph@warning@
\newif\if@debug@
%    \end{macrocode}
%    \begin{macro}{\mph@debug}
%    This command will print the debugging messages if |@debug@| is |true|:
%    \begin{macrocode}
\newcommand*\mph@debug[2][]{%
    \if@debug@
       \typeout{DBG: #2}%
    \else
        \ifx#1\@empty\else
            \typeout{DBG (#1): #2}%
        \fi
    \fi
}
%    \end{macrocode}
%    \end{macro}
%    The |debug| package option sets |@debug@| to true and adds
%    numbers to each marginpar by redefining \Com{@xmpar} and
%    \Com{@ympar}. The numbers are put into boxes of dimension
%    zero so that they don't alter the spacing.
%    \begin{macrocode}

\DeclareOption{debug}{%
    \newcommand\mph@info{%
        \@tempcnta=\mph@cnt
        \advance\@tempcnta1
        \raisebox{0pt}[0pt][0pt]{\makebox[0pt][r]{\tiny\the\@tempcnta}}%
    }%
    \long\def\@xmpar[#1]#2{%
        \@savemarbox\@marbox{\mph@info#1}%
        \@savemarbox\@currbox{\mph@info#2}%
        \@xympar
    }%
    \long\def\@ympar#1{%
        \@savemarbox\@marbox{\mph@info#1}%
        \global\setbox\@currbox\copy\@marbox
        \@xympar
    }%
    \global\@debug@true
}%
\ProcessOptions*
%    \end{macrocode}
% ^^A --------------------------------------------------
%    \subsubsection{Commands}
% ^^A --------------------------------------------------
%    \begin{macro}{\mph@nr}
%    A command sequence containing the current marginpar number (which
%    will be written to the |.aux| file).
%    \begin{macrocode}
\newcommand*\mph@nr{0}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\mph@pg@new}
%    A command sequence for saving the newly determined value of |\thepage| for later use.
%    \begin{macrocode}
\newcommand*\mph@pg@new{0}
\newcommand*\mph@lastpage{0}
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\mph@cnt}
%    Emulate a counter with a command name to save one count
%    register. Oh well~\dots \texttt{;-)}
%    \begin{macrocode}
\newcommand*\mph@cnt{0}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\mph@step@cnt}
%    Use this instead of |\stepcounter| to increment the `counter'
%    passed as the argument.
%    \begin{macrocode}
\newcommand*\mph@step@cnt[1]{%
    \begingroup
    \@tempcnta#1
    \advance\@tempcnta\@ne
    \protected@xdef#1{\the\@tempcnta}%
    \endgroup
}

%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\mph@setcol}
%    The command sequence written to the |.aux| file that will save
%    the column number\slash page number of the last marginpar on the
%    column\slash page.^^A  The additional |ignore@warn#1| macro is used
%    ^^A in the |\mph@check| macro.
%    \begin{macrocode}
\newcommand*\mph@setcol[2]{%
%  \@ifundefined{mph@last@#1}{%
%        \relax
%  }{%
%        \expandafter\xdef\csname ignore@warn#1\endcsname{x}%
%  }%
  \expandafter\xdef\csname mph@last@#1\endcsname{#2}%
}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\mph@check}
%    Similar to \LaTeX's |\@testdef| for labels, this will be called
%    at the end of the \LaTeX\ run to check if the meaning of |#2| is
%    still equal to |mph@last@#1| or if it has changed since the last
%    run.
%    \begin{macrocode}
\newcommand*\mph@tempa{}
\newcommand*\mph@check[2]{%
    \protected@edef\mph@tempa{#2}%
    \expandafter\ifx\csname mph@last@#1\endcsname\mph@tempa
        \mph@debug{\csname mph@last@#1\endcsname\space == \mph@tempa}%
    \else
        \mph@debug{\csname mph@last@#1\endcsname\space != \mph@tempa!}%
        \global\@mph@warning@true
    \fi
}
\newcommand*\mph@do@warn{%
    \if@mph@warning@
        \PackageWarningNoLine{mparhack}{Marginpars may have
            changed.\MessageBreak Rerun to get them right%
        }%
    \fi
}
%    \end{macrocode}
%    \end{macro}
%    To avoid warnings about undefined commands when someone stops using
%    this package, we |\providecommand| the |\mph@setcol| command that
%    we're going to write to the |.aux| file.
%    \begin{macrocode}
\AtBeginDocument{%
    \protected@write\@auxout{}{%
        \string\providecommand\string\mph@setcol[2]{}%
    }%
%    \end{macrocode}
%    Fix for latex/3775\footnote{^^A
%    \url{https://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/3775}^^A
%    }: eso-pic uses \Com{@picture} inside the output routine,
%    which causes problems with our redefinition of \Com{hb@xt@} in \Com{@outputdblcol}.
%    So, as suggested by M. H\o gholm in his reply to the above bug report, we patch
%    \Com{@picture} to revert to the original definition of \Com{hb@xt@}.
%    \begin{macrocode}
    \@ifpackageloaded{eso-pic}{%
        \let\mph@orig@picture\@picture
        \renewcommand\@picture{\let\hb@xt@\mph@orig@hb@xt@\mph@orig@picture}%
    }{%
        \relax
    }%
}
%    \end{macrocode}
%    Add the needed checks to |\@enddocumenthook|. Again, use
%    |\csname| ... |\endcsname| to avoid warnings about undefined
%    commands.
%    \changes{v1.2}{2000/02/29}{%
%         Use \Com{csname...} when writing commands to \texttt{.aux} file
%    }%
%    \begin{macrocode}
\AtEndDocument{%
    \let\mph@setcol\mph@check
    \clearpage
    \immediate\write\@auxout{%
        \string\gdef\string\mph@lastpage{\the\c@page}^^J%
        \string\csname\space mph@do@warn\string\endcsname
    }%
}
%    \end{macrocode}
%
%    \begin{macro}{\mph@ifundef@or@smaller}
%    A helper macro that checks if the command sequence in |#1| is
%    undefined or if its value is smaller than |\mph@cnt| (it assumes
%    that |#1| is never empty). If one of these conditions is true,
%    the second argument is evaluated, else the third argument is
%    evaluated (similar to \LaTeX's |\@ifundefined|). This macro
%    will be used to shorten the body of the next macro definition.
%    \changes{v1.2}{2000/02/29}{%
%         Renamed this command, and updated the documentation
%    }%
%    \begin{macrocode}
\newcommand*\mph@ifundef@or@smaller[1]{%
    \expandafter\ifx#1\relax
        \let\mph@tempa\@firstoftwo
    \else
        \ifnum#1<\mph@cnt\relax
            \let\mph@tempa\@firstoftwo
        \else
            \let\mph@tempa\@secondoftwo
        \fi
    \fi
    \mph@tempa
}

%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\mph@pg@orig}
%    \changes{v1.2}{2000/02/29}{%
%         Added the \Com{mph@pg@orig} macro
%    }%
%    The macro |\mph@pg@orig| is used to
%    save the original value of |\c@page| which is used in case the |.aux|
%    file information is not up-to date and we can't determine the
%    correct value; this should give the same results as if \PackageName\
%    hadn't been used.
%    \begin{macrocode}
\newcommand*\mph@pg@orig{}
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\mph@get@margin}
%    This macro does most of the work described in
%    section~\ref{implementation}.
%    \changes{v1.2}{2000/02/29}{%
%         Use \Com{c@page} instead of \Com{thepage} as value in \Com{mph@pg@new}
%    }%
%    \begin{macrocode}
\newcommand*\mph@get@margin{%
    \begingroup
    \edef\mph@pg@orig{\the\c@page}
    \loop
%    \end{macrocode}
%    This loop will be controlled by |\@tempswa|; all changes to that
%    and to |\thepage| will be local to the current group.
%    \begin{macrocode}
    \@tempswafalse
    \mph@debug{--- checking marginpar \mph@cnt}%
    \if@twocolumn
%    \end{macrocode}
%    When we are in twocolumn mode, first check if the current
%    marginpar number is greater than the last marginpar in the first
%    column. If it isn't, we're in the first column. If it is, do the
%    check for the last marginpar of the entire page. If this returns
%    false, we're in the second column. Else, advance the page number
%    and try again.
%    \begin{macrocode}
        \mph@debug{last on page \thepage:
                \csname mph@last@i:\thepage\endcsname(i)
                \csname mph@last@ii:\thepage\endcsname(ii),
        }%
        \mph@ifundef@or@smaller{%
            \csname mph@last@i:\thepage\endcsname
        }{%
            \mph@ifundef@or@smaller{%
                \csname mph@last@ii:\thepage\endcsname
            }{%
                \global\@mph@firstcol@true
                \@tempswatrue
                \advance\c@page by 1
                \mph@debug{\mph@cnt\space >
                    \csname mph@last@ii:\thepage\endcsname,
                    incrementing \thepage, set col to i
                }%
            }{%
                \global\@mph@firstcol@false
                \@tempswafalse
                \mph@debug{\mph@cnt\space <=
                    \csname mph@last@ii:\thepage\endcsname,
                    exiting loop
                }%
            }%
        }{%
            \@tempswafalse
            \global\@mph@firstcol@true
            \mph@debug{exiting loop}%
        }%
    \else
%    \end{macrocode}
%    Not in twocolumn mode, we need only check for |mph@last@ii|:
%    \begin{macrocode}
        \mph@debug{last on page \thepage\space is
                \csname mph@last@ii:\thepage\endcsname
        }%
        \mph@ifundef@or@smaller{%
            \csname mph@last@ii:\thepage\endcsname
        }{%
            \@tempswatrue
            \advance\c@page by 1
            \mph@debug{\mph@cnt\space >
                \csname mph@last@ii:\thepage\endcsname,
                incrementing page number
            }%
        }{%
            \@tempswafalse
            \mph@debug{\mph@cnt\space <=
                \csname mph@last@ii:\thepage\endcsname,
                exiting loop
            }%
        }%
    \fi
%    \end{macrocode}
%    Now we have either found the correct page, or reached the end of the document
%    without finding the appropriate page (e.\,g., if the |.aux| file hasn't existed
%    before, or if the document has grown a lot since the last run).
%    In this case we reset |\c@page| and |\if@mph@firstcol@| to their original values
%    and jump out of the loop.
%    \changes{v1.2}{2000/02/29}{%
%         Use original values for page and column number by default%
%    }%
%    \begin{macrocode}
    \ifnum\mph@lastpage>\c@page
    \else
        \@tempswafalse
        \mph@debug{\c@page >= \mph@lastpage!}%
        \c@page=\mph@pg@orig
        \if@firstcolumn
            \global\@mph@firstcol@true
        \else
            \global\@mph@firstcol@false
        \fi
        \mph@debug{using original value: \c@page for
            \string\c@page and exiting loop.
        }%
    \fi
    \if@tempswa
        \mph@debug{iterating ...}%
    \repeat
%    \end{macrocode}
%    After having finished the loop, we save the current (eventually modified)
%    value of |\c@page| to |\mph@pg@new|:
%    \begin{macrocode}
    \mph@debug{=== marginpar \mph@cnt\space is on page \thepage%
        \if@twocolumn, col \if@mph@firstcol@ 1 \else 2 \fi\fi
        }%
    \protected@xdef\mph@pg@new{\the\c@page}%
    \endgroup
}

%    \end{macrocode}
%    \end{macro}
%
% ^^A --------------------------------------------------
%    \subsubsection{Patching the output routine}
% ^^A --------------------------------------------------
%    We have to hook into 3 commands that are part of \LaTeX's output routine:
%    |\@addmarginpar|, |\@outputdblcol| and |\@outputpage|. For the latter, we can use the default
%    \LaTeX\ mechanism |\g@addto@macro|. For the others, this is more difficult,
%    since the changes need to go somewhere `in between'.
%
%    One could use  hard redefinitions (plus
%    \Com{CheckCommand*} to verify that the correct version of
%    the command was being defined); but this soon gets too bothersome
%    with new \LaTeX2e\ versions introducing minor changes that don't
%    affect the stuff which we are concerned, but that nevertheless
%    would require multiplying the redefinitions for the various versions.
%
%    So instead, we locally redefine some
%    commands to hook into the existing definitions. As a heuristic of
%    detecting whether we change the appropriate commands, we check
%    the values of some special counters \Com{mph@chk@xyz} that get
%    incremented by some of the `hooks'.
%
%    \changes{v1.3a}{2003/05/22}{%
%         Use \Com{g@addto@macro} for \Com{@outputpage} to
%         improve compatibility with e.g. the memoir class
%    }%
%    \changes{v1.2}{2000/02/29}{%
%         Added \Com{CheckCommand*} for \Com{@addmarginpar}, \Com{@outputpage}
%         and \Com{@outputdblcol}
%    }%
%    \changes{v1.2b}{2000/09/01}{%
%         Replaced \Com{CheckCommand*} and the full redefinitions of
%         \Com{@addmarginpar}, \Com{@outputpage} and \Com{@outputdblcol}
%         by hooking into certain commands inside them
%    }%
%
%    \begin{macro}{\mph@error}
%    Error message if something suspicious happened with the redefintions:
%    \begin{macrocode}
\newcommand\mph@error[1]{%
    \PackageError{mparhack}{%
        Couldn't hook into command `#1'
    }{%
        This means that a LaTeX version incompatible with
        mparhack.sty^^J%
        has been used. See also the section on `Bugs/Restrictions'^^J%
        in mparhack.dvi. Please send an email about this bug to^^J%
        <stefanulrich@users.sourceforge.net>, along with the file `\jobname.log'.
    }%
}
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\@addmarginpar}
%    This command adds the marginpar box to the current page.
%    We change the \Com{c@page} counter and the \Com{if@firstcolumn} switch
%    to the values that have been set correctly by the \Com{mph@get@margin}
%    command. There's no further error checking done here.
%
%    \begin{macrocode}
\newcommand\mph@orig@c@page{}
\newcommand\mph@orig@addmarginpar{}
\let\mph@orig@addmarginpar\@addmarginpar

\renewcommand\@addmarginpar{%
    \mph@step@cnt\mph@cnt
    \protected@write\@auxout{}%
         {\string\def\string\mph@nr{\mph@cnt}}%
    \mph@get@margin
    \def\mph@orig@c@page{\c@page}
    \c@page=\mph@pg@new
    \if@mph@firstcol@
        \@firstcolumntrue
    \else
        \@firstcolumnfalse
    \fi
    \mph@orig@addmarginpar
    \c@page=\mph@orig@c@page
}

%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\@outputpage}
%    Add the |\mph@outputpage@hook| hook to |\@outputpage|.
%    We need to decrement |\c@page|, since |\@outputpage| will
%    have incremented it after dumping the page contents.
%    The group in |\mph@outputpage@hook| is to keep this change local.
%    \begin{macrocode}
\newcommand*\mph@outputpage@hook{%
    \bgroup
    \advance\c@page\m@ne
    \immediate\write\@auxout{%
        \string\mph@setcol{ii:\thepage}{\string\mph@nr}%
    }%
    \egroup
}
\g@addto@macro{\@outputpage}{\mph@outputpage@hook}

%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\@outputdblcol}
%    In case an entire twocolumn page is finished, this command calls
%    \Com{hb@xt@} with the boxes for the two columns inside, and each
%    one needs to set a marker with the current column number. So
%    we hook into \Com{hb@xt@} and check if its first argument equals
%    \Com{columnwidth} (\Com{hb@xt@} is also called for the entire page,
%    but in this case the first argument is \Com{textwidth}).
%
%    The current column number is represented by \Com{mph@chk@dcl}, and at
%    the end we check if this number equals 0 (in which case the
%    page hadn't been fininshed yet, and we didn't need to do anything)
%    or 2 (the `interesting' case); else we signal an error.
%    \changes{v1.5}{2021-04-02}{%
%         Changed definition of \Com{@outputdblcol} to allow
%         \Com{hb@xt@} to correctly expands in shipout hooks. See
%         \url{https://tex.stackexchange.com/q/595272/2388}
%    }%

%    \begin{macrocode}
\newcommand\mph@orig@hb@xt@{}
\newcommand\mph@orig@outputdblcol{}
\newcommand\mph@chk@dcl{0}%
\let\mph@orig@hb@xt@\hb@xt@
\let\mph@orig@outputdblcol\@outputdblcol

\renewcommand\@outputdblcol{%
    \def\mph@chk@dcl{0}%
    \def\hb@xt@##1##2{%
        \ifx##1\columnwidth
            \mph@step@cnt\mph@chk@dcl
            \protected@edef\mph@tempa{%
                \noexpand\write\noexpand\@auxout{%
                    \noexpand\string\noexpand\mph@setcol{%
                        \romannumeral\mph@chk@dcl:\noexpand\thepage%
                    }{%
                        \noexpand\string\noexpand\mph@nr%
                    }%
                }%
            }%
            \mph@orig@hb@xt@##1{##2\mph@tempa}%
        \else
            \mph@orig@hb@xt@##1{##2}%
        \fi
    }%
    \mph@orig@outputdblcol
    \def\hb@xt@{\mph@orig@hb@xt@}%
    \ifnum\mph@chk@dcl=0\relax
    \else
        \ifnum\mph@chk@dcl=2\relax
        \else
            \mph@error{\string\@outputdblcol}%
        \fi
    \fi
}

%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\mph@orig@picture}
%    \begin{macrocode}
\newcommand\mph@orig@picture{}
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macrocode}
%</sty>
%    \end{macrocode}
% ^^A\typeout{End of package documentation.}
% ^^A makeindex -s gind.ist \PackageNameNoExt^^J}
%   \PrintIndex
%   \PrintChanges
% \Finale
