% \iffalse
%
% Copyright 2010 Stephen Hicks, All rights reserved.
% marginfix.dtx - 29 Jul 2010
% originally floatprobsbegone, created 21 Mar 2008
%
% Run LaTeX on this document to produce documentation.
% Run LaTeX on marginfix.ins to produce the package.
%<*driver>
\ProvidesFile{marginfix.dtx}
%</driver>
%
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{marginfix}%
           [2010/08/28 v0.9.1 Fix Margin Paragraphs]
%<*driver>
\documentclass{ltxdoc}
\CheckSum{546}
%\OnlyDescription % (un)comment this line to show (hide) source code
\RecordChanges
\EnableCrossrefs
\CodelineIndex   % (un)comment this line to index source by page (line)
\begin{document}
  \newcommand*\Lopt[1]{\textsf {#1}}
  \newcommand*\lit[1]{\texttt{\char`#1}} %% literal character (funny catcodes)
  \parindent0pt
  \def\*#1{\texttt{\string#1}} %% sdh - |...| doesn't work in headings
  \makeatletter
  %
  \let\pkg\textsf
  \newcount\mac@depth\mac@depth\z@
  \newcommand\@macros{}\newcommand\@endmacros{}
  \catcode`&3  %% we use a funny catcode to ensure never used.
  \def\@macros#1,{\macro{#1}\global\advance\mac@depth\@ne\relax
    \@ifnextchar&\@gobble\@macros}
  \def\@endmacros{\let\mac@next\relax\ifnum\mac@depth>\z@
    \endmacro\let\mac@next\@endmacros
    \global\advance\mac@depth\m@ne\fi\mac@next}
  \newenvironment{macros}[1]{\@macros#1,&}{\@endmacros}
  \catcode`&4  %% put it back 
  \makeatother %% must be balanced for character table to work properly
  %
  \DocInput{marginfix.dtx}
  \setcounter{IndexColumns}{2}
  \PrintIndex
  \PrintChanges
\end{document}
%</driver>
% \fi
% \changes{v0.0}{2008/03/21}
%       {(SDH) Initial version of floatprobsbegone.}
% \changes{v0.9}{2010/08/18}
%       {(SDH) Initial CTAN version.}
% \changes{v0.9.1}{2010/08/28}
%       {(SDH) Fix bug where we alternated sides in article.}
%
% \GetFileInfo{marginfix.dtx}
% \title{\Lopt{marginfix} package documentation}
% \author{Stephen Hicks\\%
%    \texttt{sdh33@cornell.edu}\\%
%    \texttt{http://shicks.github.com/marginfix}}
% \date{\fileversion{} -- \filedate}
% \maketitle
%
% \part*{Usage}
% \section{Overview}
% Authors using \LaTeX\ to typeset books with significant margin material
% often run into the problem of long notes running off the bottom of the
% page.  A typical workaround is to insert \cs{vshift}s by hand, but
% this is a tedious process that is invalidated when pagination changes.
% Another workaround is \pkg{memoir}'s \cs{sidebar} function, but this can be
% unsatisfying for short textual notes, and standard marginpars cannot
% be mixed with sidebars.  This package implements a solution to
% make marginpars "just work" by keeping a list of floating inserts and
% arranging them intelligently in the output routine.
%
% \section{Options}
% There are currently no options that do anything yet.
%
% \section{Commands}
% For the most part, this is a drop-in replacement.  Simply add
% |\usepackage{marginfix}| to the preamble, use \cs{marginpar}
% normally and hope for the best.
% In the event, however, that it doesn't work exactly as hoped,
% there are a number of tweaks that the user can apply.
%
% \DescribeMacro{\marginskip}
% Calling \cs{marginskip}\marg{length} will insert an incompressible
% skip in the margin.  These skips will force neighboring notes on
% the same page to be separated, but will disappear at the top or
% bottom of a margin.
%
% \DescribeMacro{\clearmargin}\DescribeMacro{\softclearmargin}
% In an analog to \cs{clearpage}, \cs{clearmargin} prevents any further
% material from being added to the current margin.  These calls are
% cumulative, so that two \cs{clearmargin}s in a row will produce a
% completely empty margin on the next page as well.  If this is not
% the desired effect, use \cs{softclearmargin}, which is effectively
% idempotent: multiple calls have the same effect as one call to
% end the current margin.
%
% \DescribeMacro{\extendmargin}
% If a page has too much margin material to fit and an important note
% is floating to the next page, \cs{extendmargin}\marg{length} will
% extend the margin (for the current page only) by the given length.
% If the length is negative, the margin will shrink.  Multiple calls
% on the same page are cumulative.
%
% \DescribeMacro{\mparshift}
% To adjust the position of a single note, use \cs{mparshift}\marg{length}
% before \cs{marginpar}.  Positive lengths move it down the page.  This
% essentially shifts the call-out location, so the actual position of the
% note might not change if the margin is sufficiently crowded.
% Multiple calls before the same note are cumulative.
%
% \DescribeMacro{\marginheightadjustment}
% If all the margins are the wrong size, the height of the margin on every
% page can be adjusted by assigning a non-zero value to the dimension
% register \cs{marginheightadjustment} (as in 
% \cs{marginheightadjustment}\texttt{=}$\langle$\emph{length}$\rangle$).
% This is effectively the same as a call to
% \cs{extendmargin} on every page.
%
% \DescribeMacro{\marginposadjustment}
% Similarly, if all the margins are in the wrong place, the callout
% positions can be adjusted by assigning a non-zero value to the dimension
% register \cs{marginposadjustment}.  This is effectively the same as a call
% to \cs{mparshift} before every note.  This is particularly useful at
% present because the height of the line on which the margin note is called
% is currently only estimated, and appears to be off by a point or two.
% This may get fixed in the future, but until then, the adjustment is
% possibly the easiest workaround.
%
% \section{Interaction with other packages}
% \subsection{memoir}
% There are no known issues with \Lopt{memoir} at present, provided that
% \cs{sidebar} is not used.
%
% \subsection{mparhack}
% \Lopt{mparhack} was designed to deal with the problem of margin notes
% showing up in the wrong margin because the left/right was decided before
% it was known exactly which page the note would be on.  Because we defer
% this decision to shipout time in this package, we are not susceptible
% to this problem, so \Lopt{mparhack} is no longer needed and should not
% be included (though I'm unaware whether it causes any actual problems).
%
% \subsection{Multiple columns}
% There is currently no support for multiple columns.
%
% \section{Coming attractions and known issues}
% Here is a list of things to possibly look forward to in a future version.
% If any of them are particularly important, please let me know.
% \begin{itemize}
% \item Margin phantoms.
% \item Use of pdf\TeX's \cs{pdfsavepos} and \cs{pdflastypos} for more
%   accurate margin placement.
% \item \cs{vadjust} to correct inconsistencies with \cs{@pageht}.
% \item Better interaction with floats.
%   (We can set a default one way
%   or the other and then allow a macro to override it (presumably with a
%   CS defined in terms of the box name/meaning, so as not to get in the
%   way of \LaTeX's use of the insert registers).  We would then add or
%   not add phantoms in the right spots.  We'd also need to shift all the
%   callout points by the size of the top figures (unless we're using
%   \cs{pdfsavepos}).)
% \end{itemize}
%
% \StopEventually{}
%
% \makeatletter
% \part*{Implementation}
% \section{Initial Setup}
% \begin{macros}{\@ight,\f@ur,\@C}
% Make the |@|-sign into a letter for use in macro names.  We also
% define a few other (hopefully) obvious and unambiguous macros that
% other packages won't destructively clobber.
%    \begin{macrocode}
%<*package>
\makeatletter
\chardef\@ight=8
\chardef\f@ur=4
\chardef\@c=100
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@debug}
% We have some optionally-included code for debugging.  \cs{MFX@debug}
% prints a new line followed by ``|MFX: |'' and then the message.
% The newline can be suppressed with a |*|.  We'll also ask for more
% error context in the debug mode.
%    \begin{macrocode}
%<debug>\def\MFX@debug{\@ifstar\message{\message{^^JMFX:}\message}}
%<debug>\errorcontextlines=20
%    \end{macrocode}
% \end{macros}
%
% The reader might begin to note at this point a convention we
% adopt throughout this package.  While we strive to avoid introducing
% new names as much as possible (using the \pkg{inlinedef} package
% whenever we can), any new names we do introduce will be prefixed
% by |\MFX@|, |\Mfx@|, or |\mfx@|, depending on the type of name.
% The all-capitol |\MFX@| is used for fully-constant macros.  The
% initial-caps |\Mfx@| is used for control sequences that are
% technically constant, but that refer to things that change, such
% as counters, token lists, dimension registers, etc.  Finally,
% the lowercase |\mfx@| is used for control sequences whose meaning
% changes dynamically (i.e. variable macros).
%
% \section{Options}
% Here we define the various package options.
% \begin{macros}{\ifmfx@ypos}
% The \Lopt{ypos} option signifies that we should use the pdf{\TeX}
% primitives \cs{pdfsavepos} and \cs{pdflastypos} to improve positioning
% of margin notes relative to their callouts.  This requires two
% passes to work, and the first time through, the margin notes
% will be positioned very na\"ively.
%    \begin{macrocode}
\newif\ifmfx@ypos
\DeclareOption{ypos}{\mfx@ypostrue}
%    \end{macrocode}
% \end{macros}
%
% Now we actually process the options.
%    \begin{macrocode}
\ProcessOptions\relax
%    \end{macrocode}
%
% \section{Variables}
% \begin{macros}{\mfx@marginlist}
% We need a place to store our list of marginal material.  We
% store material in this variable using insert registers and
% a variety of macros, to be explained later.
%    \begin{macrocode}
\let\mfx@marginlist\@empty
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\Mfx@marginbox}
% While we're building the margin, we need to put it in a box
% before we can attach it to the main columm.
%    \begin{macrocode}
\newbox\Mfx@marginbox
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\Mfx@marginboxspace,\Mfx@marginpos}
% While we build up the margin box, we need to keep track of both
% where we are in the margin (\cs{Mfx@marginpos}) and how
% much of that space is incompressible (\cs{Mfx@marginboxspace}).
%    \begin{macrocode}
\newdimen\Mfx@marginboxspace
\newdimen\Mfx@marginpos
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\Mfx@marginheight}
% Because the margin height can be altered by, \cs{extendmargin},
% we must maintain a dimension for the height of the current margin.
%    \begin{macrocode}
\newdimen\Mfx@marginheight
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\Mfx@mparshift}
% We store the current shift in a dimension register.
%    \begin{macrocode}
\newdimen\Mfx@mparshift
%    \end{macrocode}
% \end{macros}
%
% \section{User-configurable dimensions}
% We export a few dimensions that the user can redefine to tweak behavior.
% \begin{macros}{\marginheightadjustment}
% This length will be added to the total margin height of each page
% (the default is zero).
%    \begin{macrocode}
\newdimen\marginheightadjustment
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\marginposadjustment}
% We will offset each margin note from its callout location by this length
% (the default is zero).
%    \begin{macrocode}
\newdimen\marginposadjustment
%    \end{macrocode}
% \end{macros}
%
% \section{Plan of attack}
% \subsection{\cs{marginpar}}
% The default sequence of events for a \cs{marginpar} is roughly the following
% (assuming no errors):
% \begin{verbatim}
% \marginpar:
%   let \@floatpenalty := (horizontal ? -10002 : -10003)
%   allocate inserts \@currbox and \@marbox from \@freelist
%   let \count\@marbox := -1 % signifies marginpar (not float)
%   if optional argument then \@xmpar else \@ympar
% \@xmpar:
%   \@savemarbox \@currbox := required argument
%   \@savemarbox \@marbox := optional argument
%   \@xympar
% \@ympar:
%   \@savemarbox \@currbox := required argument
%   copy \@marbox := \@currbox
%   \@xympar
% \@xympar:
%   append \@marbox to \@currlist
%   \end@float
% \end@float:
%   append \@currbox to \@currlist
%   if horizontal then following two lines are in \vadjust:
%     \penalty -10004
%     \penalty \@floatpenalty
% \end{verbatim}
%
% To get the rest of the picture, we need to peek into the
% output routine.  The pertinent parts are as follows (in
% vanilla \LaTeX):
% \begin{verbatim}
% \output:
%   if \outputpenalty < -10000 then
%     \@specialoutput
%   else
%     do regular output...
%   details for dealing with footnotes...
% \@specialoutput:
%   switch \outputpenalty:
%    case -10001: \@doclearpage
%    case -10004: set box \@holdpg := \vbox{\unvbox255}
%    case -10002 or -10003:
%     set box \@holdpg := \vbox{\unvbox\@holdpg \unvbox255}
%     let \@pageht := \ht\@holdpg, \@pagedp := \dp\@holdpg
%     \unvbox\@holdpg
%     pop \@currbox off of \@currlist
%     \@addmarginpar (assuming \count\@currbox <= 0)
% \@addmarginpar:
%   pop \@marbox off of \@currlist
%   free \@currbox and \@marbox back to \@freelist
%   if left-hand margin then let \@marbox := \@currbox
%   let \@tempdima := \@mparbottom - \@pageht + \ht\@marbox
%   if \@tempdima < 0 then let \@tempdima := 0
%   let \@mparbottom := \@pageht + \@tempdima + \dp\@marbox + \marginparpush
%   decrement \@tempdima := \@tempdima - \ht\@marbox
%   prepend \vskip\@tempdima to \@marbox
%   let \ht\@marbox := \dp\@marbox := 0
%   \kern -\@pagedp, \nointerlineskip
%   set an \hbox to \columnwidth (zero height/depth):
%     attach \@marbox to correct margin
%   set a \vbox with height 0 and depth \@pagedp
% \end{verbatim}
%
% We see from here that \cs{@addmarginpar} is the place where {\LaTeX}
% does the work of calculating the current page position and where the
% next note should go, and then actually puts it there.  We will need
% to completely replace this routine, but can leave everything else
% as is.
%
% \subsection{\cs{output}}
% While \LaTeX's margin routines end with \cs{@addmarginpar}, we must
% dig even deeper to apply our patch, since we need to insert some
% code to run during the \emph{main} output routine that ships out
% each page.  Thus, we'll expand ``\texttt{do regular output...}''
% from the previous \cs{output} listing.
% \begin{verbatim}
% do regular output...:
%   \@makecol
%   do { \@opcol \@startcolumn } while @fcolmade
% \@makecol:
%   set box \@outputbox := box255 (plus any footnotes)
%   let \@freelist := \@freelist + \@midlist, \@midlist := \@empty
%   \@combinefloats
%   add \@texttop and \@textbottom to \@outputbox (default no-op)
% \@opcol:
%   \@outputpage (of \@outputdblcol in twocolumn mode)
%   let \@mparbottom := \@textfloatsheight := 0
%   \@floatplacement
% \@startcolumn:
%   try to make a float column from \@deferlist, setting @fcolmade
%   if !@fcolmade then add floats from \@deferlist to next column
% \@combinefloats:
%   aggregate \@toplist floats into a box and prepend to \@outputbox
%   aggregate \@botlist floats into a box and append to \@coutputbox
%   free inserts from \@toplist and \@botlist
% \@outputpage:
%   ship out the page
%   reset a bunch of stuff
%   let \@colht := \textheight (in \@outputpage)
% \end{verbatim}
%
% We've seen two main times when action occurs: callout time and
% shipout time.  We proceed chronologically with our patches.
%
% \section{Callout-time patches}
% \begin{macros}{\@addmarginpar}
% The first thing we must modify is that at callout time, we need to
% get the inserts into \cs{mfx@marginlist}.  This should happen in the
% output routine so that we can get ahold of the current page
% position.  Even if we have a better idea of the page position
% (e.g. from pdf\TeX), we still might as well do this in the OR.
%    \begin{macrocode}
\def\@addmarginpar{%
  \@next\@marbox\@currlist{}\MFX@bug
%<debug>\MFX@debug{addmarginpar (running insert) \@marbox/\@currbox at
%<debug>    \the\c@page:\the\@pageht, marginlist=\meaning\mfx@marginlist}%
  \MFX@getypos
  \MFX@cons\mfx@marginlist{% TODO: later this will be a run@marginlist
    \noexpand\mfx@margin@note\@marbox\@currbox{\mfx@ypos}% (^i.e. for phantoms)
    \noexpand\mfx@margin@skip{\the\marginparpush}%
  }%
%<debug>\MFX@debug{addmarginpar (exit): marginlist=\meaning\mfx@marginlist}%
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@cons,\MFX@snoc}
% In passing we'll define the cons macro, which fully-expands
% its second argument, but makes sure to only expand the first
% one once, so that any fragile control sequences in it are
% corectly protected.  We also define snoc, which prepends.
% Note that we could put the \cs{temp@} definition into a group
% if it was really gonna matter\ldots
%    \begin{macrocode}
\def\MFX@cons#1#2{%
  \edef\temp@{#2}%
  \expandafter\expandafter\expandafter\gdef
  \expandafter\expandafter\expandafter#1%
  \expandafter\expandafter\expandafter{\expandafter#1\temp@}%
}

\def\MFX@snoc#1#2{%
  \edef\temp@{#2}%
  \expandafter\expandafter\expandafter\gdef
  \expandafter\expandafter\expandafter#1%
  \expandafter\expandafter\expandafter{\expandafter\temp@#1}%
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@getypos,\mfx@ypos}
% We now need to settle on a way to determine the vertical position.
% Ultimately this will be an option, and will depend on a variety
% of factors.  But for starters, we define the simplest version.
% Note the subtraction of \cs{Mfx@strutheight}.  Ideally we would simply
% grab a copy of \cs{@holdpg} from the middle of \cs{@specialoutput}
% and then discard the last box to figure out what height we're really
% at, since \cs{@holdpg} includes the box from the line we're currently
% on, and we want to be level with the \emph{top} of that box, rather
% than the baseline.  But since \cs{@holdpg} is accessible only deep
% within \cs{@specialoutput}, and it's not worth the risky job of
% performing surgery on it (which is unfortunately brittle if anyone
% else has a similar idea), we instead resort to this approximation.
% And since this will ultimately be only a fallback for when
% \cs{pdflastypos} isn't available, it should be good enough.
% NOTE: we might be able to use a \cs{vadjust} instead here?
%    \begin{macrocode}
\def\MFX@getypos{%
  \edef\mfx@ypos{%
    \the\dimexpr\@pageht - \Mfx@strutheight
       + \marginposadjustment + \Mfx@mparshift\relax}%
  \global\Mfx@mparshift\z@
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\marginpar,\Mfx@strutheight}
% We need to make sure \cs{Mfx@strutheight} gets defined somewhere,
% and the best time is probably right before the \cs{marginpar} does
% its work, since that will most likely ensure we're using the right
% font for the line.
%    \begin{macrocode}
\newdimen\Mfx@strutheight
\edef\marginpar{%
  \unexpanded{\setbox\@tempboxa\hbox{\strut}\Mfx@strutheight\ht\@tempboxa}%
  \expandafter\unexpanded\expandafter{\marginpar}%
}
%    \end{macrocode}
% \end{macros}
%
% \section{Shipout-time patches}
% \begin{macros}{\@combinefloats,\MFX@combinefloats@before}
% We need to patch in somewhere before \cs{@combinefloats} at the latest,
% so that any heights calculated from \cs{@pageht} are correct---otherwise
% the top figures will confuse us.  So we'll start by simply adding our
% own \cs{MFX@combinefloats@before} at the very beginning of \cs{@combinefloats}
%    \begin{macrocode}
\expandafter\def\expandafter\@combinefloats\expandafter{\expandafter
  \MFX@combinefloats@before\@combinefloats}
%    \end{macrocode}
% 
% \cs{MFX@combinefloats@before} is then responsible for picking the
% needed notes from \cs{mfx@marginlist}, building them into a box, and
% attaching said box onto the correct side of \cs{@outputbox}.  This is
% also a convenient place to reset \cs{Mfx@marginheight} to zero (since
% we reuse the register for one-time extensions).
%    \begin{macrocode}
\def\MFX@combinefloats@before{%
  \MFX@buildmargin
  \MFX@attachmargin
  \Mfx@marginheight\marginheightadjustment
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@attachmargin}
% We'll start with the second half of \cs{MFX@combinefloats@before},
% since it's simpler.  We need to do several things here.
%    \begin{macrocode}
\def\MFX@attachmargin{%
%<debug>\MFX@debug{attachmargin}%
%    \end{macrocode}
% First, we need to make sure that the boxes we're combining are the
% same size.
%    \begin{macrocode}
  \ifdim\ht\@outputbox<\ht\Mfx@marginbox
    \setbox\@outputbox\vbox to \ht\Mfx@marginbox{%
      \box\@outputbox
      \vfill
    }%
  \else
    \setbox\Mfx@marginbox\vbox to \ht\@outputbox{%
      \unvbox\Mfx@marginbox
      \vfill
    }%
  \fi
%    \end{macrocode}
% Next we need to figure out which side of \cs{@outputbox} to attach
% the \cs{Mfx@marginbox} on.
%    \begin{macrocode}
  \setbox\@outputbox\vbox to \ht\@outputbox{%
    \hbox to \wd\@outputbox{%
      \if\MFX@leftmargin
        \llap{\box\Mfx@marginbox\hskip\marginparsep}%
        \box\@outputbox
      \else
        \box\@outputbox
        \rlap{\hskip\marginparsep\box\Mfx@marginbox}%
      \fi
  }}%
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@buildmargin}
% When \cs{MFX@buildmargin} is called, we have a list of tokens in
% \cs{mfx@marginlist} that need to be processed.  After it's done
% working, \cs{mfx@marginlist} should have the first $n>0$ of these
% removed, and leaving only notes that were deferred to the next
% page.  Additionally, \cs{Mfx@marginbox} must contain a
% box the same height as \cs{@outputbox}.  We do this in several
% steps.  We start with a height of \cs{@colroom} rather than
% \cs{textheight} because \cs{@colroom} has already subtracted
% off the top/bottom floats that have been set.  Eventually we
% will want to encroach on these floats, particularly if they
% don't encroach on the margin, but that will be tricky...
%    \begin{macrocode}
\def\MFX@buildmargin{%
  \advance\Mfx@marginheight\@colroom
%<debug>\MFX@debug{buildmargin: marginheight=\the\Mfx@marginheight}%
  \MFX@buildmargin@down
  \MFX@buildmargin@up
}
%    \end{macrocode}
% \end{macros}
%
% \subsection{First pass}
% \begin{macros}{\MFX@buildmargin@down}
% The first step is the ``down'' step, in which we move the notes
% that will go on the current page into \cs{mfx@marginout} in reverse order,
% and anything that will be deferred gets put back in
% \cs{mfx@marginlist}.  This behavior is configured by changing
% the meaning of \cs{mfx@margin@note}, \cs{mfx@margin@skip}, and
% \cs{mfx@margin@clear}.  Note that during the course of processing
% \cs{mfx@marginlist}, these meanings will continue to change.
%    \begin{macrocode}
\def\MFX@buildmargin@down{%
%<debug>\MFX@debug{buildmargin@down: ENTRY}%
%<debug>\MFX@debug{marginlist=\meaning\mfx@marginlist}%
  \let\mfx@margin@note\MFX@margin@note@down
  \let\mfx@margin@skip\@gobble
  \let\mfx@margin@clear\MFX@margin@clear@down
  \let\mfx@marginout\@empty
%    \end{macrocode}
% We do a little bit of \cs{expandafter} trickery here to first expand
% the current meaning of \cs{mfx@marginlist}, then clear it before
% actually executing anything.
%    \begin{macrocode}
  \expandafter\global\expandafter\let
  \expandafter\mfx@marginlist\expandafter\@empty
  \mfx@marginlist
%<debug>\MFX@debug{buildmargin@down: RETURN}%
%<debug>\MFX@debug{marginlist=\meaning\mfx@marginlist}%
}
%    \end{macrocode}
% \end{macros}
%
% We must now define the different meanings for the
% |\mfx@margin@...| macros.
% \begin{macros}{\MFX@margin@note@down,\MFX@whichbox,%
%     \MFX@margin@skip@down,\MFX@margin@clear@down}
% We'll dive right into the notes first.  When we see a note in the
% \cs{marginlist}, we need to do several things.
% \begin{enumerate}
% \item optionally add a \emph{compressible} skip before it, of length
%   $|#3| - \cs{Mfx@marginpos}$, to line it up with the callout
%   location
% \item figure out which box we need for the current page, not yet freeing
%   the allocated boxes, since we may still end up deferring
% \item add the height of the correct box to \cs{Mfx@marginboxspace} and
%   \cs{Mfx@marginpos}
% \item if \cs{Mfx@marginboxspace} exceeds \cs{Mfx@marginheight}, then
%   we defer this note and change the meaning of \cs{mfx@margin@note}
%   to defer all remaining notes
% \item otherwise, we add tokens to construct the box to \cs{toks@} and
%   free the allocated inserts.
% \item redefine \cs{mfx@margin@skip} to \cs{MFX@margin@skip@down}, now
%   that we've gotten a real note (it starts out as \cs{@gobble} since
%   we don't want to apply skips at the very beginning).
% \end{enumerate}
%    \begin{macrocode}
\def\MFX@margin@note@down#1#2#3{%
%<debug>\MFX@debug{note@down: ENTRY: #1/#2 at #3}%
  \ifdim#3>\Mfx@marginpos
    \dimen@\dimexpr#3-\Mfx@marginpos\relax
%<debug>\MFX@debug{note@down: adding compressible \the\dimen@}%
    \MFX@snoc\mfx@marginout{\noexpand\mfx@margin@compressible{\the\dimen@}}%
    \advance\Mfx@marginpos\the\dimen@
  \fi
  \MFX@whichbox#1#2%
  \advance\Mfx@marginboxspace\dimexpr\ht\@marbox+\dp\@marbox\relax
  \ifdim\Mfx@marginboxspace>\Mfx@marginheight
%    \end{macrocode}
% We've run out of margin space, so we now defer every following box,
% which means appending them back to \cs{mfx@marginlist}, except with
% a callout position of zero, since we want them as high up as possible
% (also, the position should be monotonic).
%    \begin{macrocode}
%<debug>\MFX@debug{note@down: out of space:
%<debug>    \the\Mfx@marginboxspace>\the\Mfx@marginheight}%
    \advance\Mfx@marginboxspace\dimexpr-\ht\@marbox-\dp\@marbox\relax
    \mfx@margin@clear
    \mfx@margin@note#1#2{#3}%
  \else
%    \end{macrocode}
% At this point, the box is definitely going onto this page, so we can
% arrange for the boxes to be freed and then add the correct box to the
% output list.
%    \begin{macrocode}
%<debug>\MFX@debug{note@down: adding \@marbox 
%<debug>    ht \the\ht\@marbox dp \the\dp\@marbox}%
    \advance\Mfx@marginpos\dimexpr\ht\@marbox+\dp\@marbox\relax
    \MFX@snoc\mfx@marginout{%
      \noexpand\mfx@margin@note\@marbox
      \noexpand\@cons\noexpand\@freelist#1%
      \noexpand\@cons\noexpand\@freelist#2%
    }%
  \fi
  \let\mfx@margin@skip\MFX@margin@skip@down
%<debug>\MFX@debug{note@down: RETURN space=\the\Mfx@marginboxspace,
%<debug>           pos=\the\Mfx@marginpos}%
}
%    \end{macrocode}
%
% We need to figure out which box to set.  This macro calls
% \cs{MFX@leftmargin} and then sets the correct box into
% \cs{@marbox} for use by \cs{MFX@margin@box@down}.
%    \begin{macrocode}
\def\MFX@whichbox#1#2{%
  \if\MFX@leftmargin
    \def\@marbox{#1}%
  \else
    \def\@marbox{#2}%
  \fi
%<debug>\MFX@debug{whichbox: \@marbox}%
}
%    \end{macrocode}
%
% The next macro we'll write is the skip.  This one just has to save itself
% onto whichever list we're working on (output or deferred) and in the case
% of output, update \cs{@Mfx@marginpos}.
%    \begin{macrocode}
\def\MFX@margin@skip@down#1{%
%<debug>\MFX@debug{skip@down #1}%
  \advance\Mfx@marginpos#1\relax
  \advance\Mfx@marginboxspace#1\relax
  \MFX@snoc\mfx@marginout{\noexpand\mfx@margin@skip{#1}}%
}
%    \end{macrocode}
%
% Finally, \cs{MFX@margin@clear@down} simply signals the end of this
% margin.  All further material will be deferred, so we redefine
% \cs{mfx@margin@note}, \cs{mfx@margin@skip}, and \cs{mfx@margin@clear}
% to defer.
%    \begin{macrocode}
\def\MFX@margin@clear@down{%
%<debug>\MFX@debug{clear@down}%
  \def\mfx@margin@note##1##2##3{%
    \MFX@cons\mfx@marginlist{\noexpand\mfx@margin@note##1##2{\MFX@minus@inf}}}%
  \def\mfx@margin@skip##1{%
    \MFX@cons\mfx@marginlist{\noexpand\mfx@margin@skip{##1}}}%
  \def\mfx@margin@clear{%
    \MFX@cons\mfx@marginlist{\noexpand\mfx@margin@clear}}%
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@minus@inf}
% Note that when we added deferred boxes to the list, we put them
% at \cs{MFX@minus@inf}.  We'll define that to be a large negative
% dimension.
%    \begin{macrocode}
\def\MFX@minus@inf{-4000pt}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@leftmargin}
% Here we figure out which box to use based on the page number and
% other flags.  This is a conditional that should be used after
% \cs{if}, as in \cs{if}\cs{MFX@leftmargin}\ldots\cs{else}\ldots\cs{fi}.
%
% This is different from the corresponding code in the {\LaTeX}
% routines because we don't support double columns.  In addition, we
% would ideally allow \cs{if@reversemargin} to work on a per-note
% basis (i.e. at callout time) but we also need something working at
% shipout time so we can figure out which margin to use.  Thus, until
% we figure out how to use multiple margins.
%    \begin{macrocode}
\def\MFX@leftmargin{%
  00\fi % close out the \if
  \@tempcnta\@ne
  \if@mparswitch
    \unless\ifodd\c@page
      \@tempcnta\m@ne
    \fi
  \fi
  \if@reversemargin
    \@tempcnta-\@tempcnta
  \fi
%<debug>\MFX@debug{margin on \ifnum\@tempcnta<\z@ left\else right\fi}%
  \ifnum\@tempcnta<\z@ % start a new \if
}
%    \end{macrocode}
% \end{macros}
%
% \subsection{Second pass}
% \begin{macros}{\MFX@buildmargin@up}
% Next is the ``up'' step.  Here we simply take the reversed
% list in \cs{mfx@marginout} and prepend each item in turn to
% \cs{Mfx@marginbox}.  We start by automatically discarding any
% skips, though we can't do this with a simple \cs{@gobble} anymore
% since we need to deduct them from \cs{Mfx@marginpos}.  Once we
% hit a note, we'll change the skips to be their normal meanings.
% Note that there are no clears in \cs{mfx@marginout}.
%    \begin{macrocode}
\def\MFX@buildmargin@up{%
%<debug>\MFX@debug{buildmargin@up: excess=\the\dimexpr
%<debug>           \Mfx@marginpos-\Mfx@marginheight\relax}%
%<debug>\MFX@debug{marginout=\meaning\mfx@marginout}
  \let\mfx@margin@note\MFX@margin@note@up
  \let\mfx@margin@compressible\MFX@margin@skip@gobble@up
  \let\mfx@margin@skip\MFX@margin@skip@gobble@up
  \mfx@marginout
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@margin@skip@gobble@up}
% In case we have any skips at the beginning of \cs{mfx@marginout},
% we'll gobble them and deduct their lenghts from \cs{Mfx@marginpos}.
%    \begin{macrocode}
\def\MFX@margin@skip@gobble@up#1{%
%<debug>\MFX@debug{skip@gobble@up: #1}%
  \advance\Mfx@marginpos-#1\relax
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@margin@note@up}
% Once we actually do hit a note, we need to set it in \cs{Mfx@marginbox}.
% We also redefine \cs{mfx@margin@skip} and \cs{mfx@margin@compressible}
% here.  Hopefully any skips aren't being dropped by our \cs{unvbox}ing.
%    \begin{macrocode}
\def\MFX@margin@note@up#1{%
%<debug>\MFX@debug{note@up: #1}%
  \setbox\Mfx@marginbox\vbox{\box#1\unvbox\Mfx@marginbox}%
  \let\mfx@margin@skip\MFX@margin@skip@up
  \let\mfx@margin@compressible\MFX@margin@compressible@up
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@margin@skip@up}
% This one is even easier---all we have to do is add a skip to the
% margin output box.  We also need to make sure it's not getting dropped,
% which might entail adding some \cs{vbox}\lit\{\lit\}s.
%    \begin{macrocode}
\def\MFX@margin@skip@up#1{%
%<debug>\MFX@debug{skip@up: #1}%
  \setbox\Mfx@marginbox\vbox{\vskip#1\relax\unvbox\Mfx@marginbox}%
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\MFX@margin@compressible@up}
% This token gets put into \cs{mfx@marginout} during the first pass.
% When it executes, it inserts a \cs{vskip} depending on how
% much extra margin space (stored in \cs{Mfx@marginpos})
% we need to excise.  If also updates \cs{Mfx@marginpos}.
%    \begin{macrocode}
\def\MFX@margin@compressible@up#1{%
%<debug>\MFX@debug{compressible@up: #1, excess=\the\dimexpr
%<debug>           \Mfx@marginpos-\Mfx@marginheight\relax}%
  \dimen@#1\relax
  \ifdim\Mfx@marginpos>\Mfx@marginheight
    \advance\dimen@\dimexpr\Mfx@marginheight-\Mfx@marginpos\relax
    \ifdim\dimen@<\z@
      \dimen@\z@
    \fi
    \advance\Mfx@marginpos\dimexpr\dimen@-#1\relax
  \fi
  \ifdim\dimen@>\z@
    \MFX@margin@skip@up\dimen@
  \fi
}
%    \end{macrocode}
% \end{macros}
%
% \section{Cleaning up}
% We need to worry about a few more things.  First, what happens
% if we reach the end of the document and there are still deferred
% margin notes?  We need to be able to dump all the margin notes
% whenever the user wants (i.e. before a new chapter), so we'll
% make a macro \cs{dumpmargins} to do this, and then make sure it
% gets called \cs{AtEndDocument}.  Since we're looping to do this,
% we need to make darned sure that every \cs{newpage} shrinks the
% marginlist.
% \begin{macros}{\dumpmargins}
%    \begin{macrocode}
\def\dumpmargins{%
%<debug>\MFX@debug{dumpmargins}%
  \loop
  \unless\ifx\mfx@marginlist\@empty
    \let\temp@\mfx@marginlist
    \vbox{}\clearpage
    \ifx\temp@\mfx@marginlist
      \PackageError{marginfix}{lost some margin notes%
%<debug>: \meaning\mfx@marginlist
      }\@eha
      \let\mfx@marginlist\@empty % be nicer by just dropping one?
      % TODO: also, set an emergency mode to allow oversized notes
    \fi
  \repeat
}
\AtEndDocument{\dumpmargins}
%    \end{macrocode}
% \end{macros}
%
% \section{User macros}
%
% \begin{macros}{\marginskip}
% Inserting a skip in the margin list is simple.  We need only
% append \cs{mfx@margin@skip} to \cs{mfx@marginlist}.
%    \begin{macrocode}
\def\marginskip#1{%
  \MFX@cons\mfx@marginlist{\noexpand\mfx@margin@skip{#1}}%
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\clearmargin,\softclearmargin}
% Likewise, \cs{clearmargin} is easy too.
%    \begin{macrocode}
\def\clearmargin{%
  \MFX@cons\mfx@marginlist{\noexpand\mfx@margin@clear}%
}
%    \end{macrocode}
% While we call \cs{softclearmargin} a ``clear margin'', it's
% actually just a big \cs{marginskip}.  This allows us to stack
% multiple copies without backing them all up.
%    \begin{macrocode}
\def\softclearmargin{%
  \marginskip{\the\textheight}%
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\extendmargin}
% We overload \cs{Mfx@marginheight} to be the amount of extension
% at all times except shipout-time.
%    \begin{macrocode}
\def\extendmargin#1{%
  \advance\Mfx@marginheight#1\relax
}
%    \end{macrocode}
% \end{macros}
%
% \begin{macros}{\mparshift}
% This is as simple as setting the dimen register.  We advance so that
% the shifts are cumulative, but there's not really any point either way.
%    \begin{macrocode}
\def\mparshift#1{%
  \advance\Mfx@mparshift#1\relax
}
%    \end{macrocode}
% \end{macros}
%
% \section{Random scribbles}
%
% Later we'll get fancier with putting notes next to top/bottom
% figures but for now, not so much.
%
% In the future we will support the use of \cs{pdfsavepos} and
% \cs{pdflastypos} for more accurately determining where the callouts
% actually were, which will end up going right around here.  But in
% order to work with older versions of \LaTeX, we still need to
% support the old style of using \cs{@pageht} to figure that out, so for
% now that's all we'll do.
%
% \section{Parting words}
% Finish it up
%    \begin{macrocode}
\makeatother
%</package>
%    \end{macrocode}
% \makeatother
% \Finale
%
%
% \iffalse
%
% The next line of code prevents DocStrip from adding the
% character table to the generated files(s).
\endinput
% \fi
%
%% \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         \~}
%%
