summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/mparhack/mparhack.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/mparhack/mparhack.dtx
Initial commit
Diffstat (limited to 'macros/latex/contrib/mparhack/mparhack.dtx')
-rw-r--r--macros/latex/contrib/mparhack/mparhack.dtx860
1 files changed, 860 insertions, 0 deletions
diff --git a/macros/latex/contrib/mparhack/mparhack.dtx b/macros/latex/contrib/mparhack/mparhack.dtx
new file mode 100644
index 0000000000..11ea9965b9
--- /dev/null
+++ b/macros/latex/contrib/mparhack/mparhack.dtx
@@ -0,0 +1,860 @@
+% \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{418}
+%
+% \MakeShortVerb\|
+%
+% \iffalse
+% \begin{macrocode}
+%<*driver>
+\documentclass{ltxdoc}
+\RequirePackage{url}%
+\IfFileExists{hyperref.sty}{\RequirePackage{hyperref}}{%
+%%% alternative definitions if hyperref is not available
+ \newcommand\href[2]{#2}%
+ \newcommand\url{\texttt}%
+}
+\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.4",
+% date = "2005/04/17",
+% 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.4 2005/04/17\\[1ex] {\footnotesize CTAN:
+% \href{http://www.ucc.ie/cgi-bin/ctan?server=ftp.dante.de%2Ftex-archive&term=mparhack}
+% {\texttt{macros/latex/contrib/supported/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{1.0}{1999/03/02}{Created}
+% \changes{1.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{1.2a}{2000/03/14}{Fixed the \Com{NeedsTeXFormat} to use 1997/04/14}
+% \changes{1.2c}{2001/02/07}{Small documentation changes}
+% \changes{1.3}{2001/02/07}{Use \Com{mph@tempa} instead of \Com{@tempa} to avoid
+% possible clashes with other classes (e.g. scrpage2)}
+% \changes{1.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{http://www.latex-project.org/cgi-bin/ltxbugs2html}:
+% \href{http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/2361}{latex/2361},
+% \href{http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/2484}{latex/2484},
+% \href{http://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).
+%
+% ^^A --------------------------------------------------
+% ^^A Place to stop if implementation shouldn't be printed
+% ^^A --------------------------------------------------
+%
+% \typein[\answer]%
+% {^^JPrint an annotated listing of the macro definitions (y/n)? [n]}
+% \def\next{y}^^A
+% \ifx\answer\next
+% \AfterElseFi\AlsoImplementation
+% \else
+% \typeout{(not printing macro definitions.)}^^A
+% \expandafter\endinput
+% \fi
+% \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}
+ [2005/04/17 v1.4 (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{http://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.
+%
+% \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%
+ }%
+ }%
+ }%
+ \else
+ \def\mph@tempa{}%
+ \fi
+ \mph@orig@hb@xt@##1{##2\mph@tempa}%
+ }%
+ \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.}
+% \typein[\answer]%
+% {^^JPrint an index of command names (y/n)? [n]^^J^^A
+% -- Note: this requires a previous run of:^^J^^A
+% \space\space\space makeindex -s gind.ist \PackageNameNoExt^^J}
+% \def\next{y}^^A
+% \ifx\answer\next
+% \AfterElseFi\PrintIndex
+% \else
+% \typeout{(not printing index.)}^^A
+% \fi
+% \typein[\answer]%
+% {^^JPrint a history of changes (y/n)? [n]^^J^^A
+% -- Note: this requires a previous run of:^^J^^A
+% \space\space\space makeindex -s gglo.ist -o \PackageNameNoExt.gls \PackageNameNoExt.glo^^J}
+% \def\next{y}^^A
+% \ifx\answer\next
+% \AfterElseFi\PrintChanges
+% \else
+% \typeout{(not printing history of changes.)}^^A
+% \fi
+% \Finale