6

I'm trying to typeset marginpars more accurately on the correct side of the page using a solution based on pdfsavepos by David Carlisle. (The code below is a slight alteration of it.) I got most of the alignment to work correctly, as can be seen for the marginpars below:

http://i.imgur.com/l6UFFea.png?2

The problem arises when I try typesetting marginpars at the bottom of the margin. The output is as follows:

http://i.imgur.com/3u5sBBX.png?1

The margins clearly flow out of the height of the text column, and that's obviously undesirable. The ideal workaround would maintain horizontal spacing conditionally, if the column is not overflown. In this specific case, that would possibly require marginpars 2 to 5 to move up.

http://i.imgur.com/fC5JLXx.png

A possible idea I have is to store the boxes and typeset them later, by iteratively calculating height and width of each box and setting the last box first, then the one but last box, etc. Except, I'm not sure how to get it done and where to start.

The code I'm using is pretty complex, so I've made annotations explaining (to the best of my abilities) what's happening. If you know any alternative solutions to fix the issue of the overflowing margin column, while maintaining the horizontal spacing of the \textsuperscripts from sidenotes, I'm open to suggestions.

As a final note, I've used the sidenotes package to make it clearer what alignment I'm looking for, which really quite clearly shows the required horizontal alignment of the superscripts. The sidenotes package is not related to the question.

\documentclass[twoside]{article}
\usepackage[paperwidth=170mm, paperheight=240mm,top=40pt, textwidth=280pt, marginparwidth=100pt,footskip=40pt]{geometry}%


\makeatletter

\newbox\@mpbox%
\newdimen\marginparmindistance \marginparmindistance=10\p@%     "marginparpush"
\global\setbox\@mpbox\vbox{}%                           empty vertical box

\long\def\marginpar#1{%
  \saveposition{mpar}%
  \global\setbox\@mpbox\vbox{\unvbox\@mpbox\hbox{%
  \hbox{\parbox{\marginparwidth}{\@marginparreset#1\@minipagefalse}}%   set marginparboxes for both sides
  \hbox{\parbox{\marginparwidth}{\@marginparreset#1\@minipagefalse}}%
}\break}}%                                          

\def\saveposition#1{%
\pdfsavepos\write\@auxout{%                                 save positions
  \noexpand\savedpos%                                   write to aux using saved position
    {#1}{\the\c@page}{\the\pdflastxpos}{\the\pdflastypos}}}

\def\savedpos#1#2#3#4{%                                 format to store the position: #1 = type // #2 = page // #3 = x // #4 = y
\begingroup
  \let\@positions\relax
  \expandafter\xdef\csname sp@#1-#2\endcsname{%                 define \csname sp@<something>
    \expandafter\ifx\csname sp@#1-#2\endcsname\relax%           if control sequence is \relax, do nothing
    \else%                                          else
      \csname sp@#1-#2\endcsname%                           
    \fi%                                                
  \@positions{#3}{#4}}%                                 append @positions to existing macro to create chain of \@positions
  \endgroup}%                                       @positions is just a placeholder to hold the pdflastxpos and pdflastypos

\def\@oddfoot{%
  \thepage\hss\rlap{\hskip\marginparsep\mcolumn}}%              append mcolumn to the footer (odd pages)
\def\@evenfoot{%
  \llap{\mcolumn\hskip\marginparsep}\hss\thepage\saveposition{foot}}%   save position of foot amd append mcolumn to footer (even pages)

\def\mcolumn{%
\saveposition{foot}%                                    save position of the footer
\expandafter\ifx\csname sp@foot-\the\c@page\endcsname\relax%        is a footer position known? no = do nothing
\else%                                          yes, 
  \let\@positions\origin@positions%                         @positions is temporarily parsed by \origin@positions
  \csname sp@foot-\the\c@page\endcsname%                    expand to look what absolute y position of foot is
  \smash{\raise\footskip\vbox to \textheight{\hsize\marginparwidth%     
  \hrule\@height\z@%                                    
  \let\@positions\mp@positions%                             the @positions from marginpars are now parsed by \mp@positions.
  \csname sp@mpar-\the\c@page\endcsname%                    the current expansion is the chain of \@positions
  \vskip\z@\@plus\textheight%                               each instance of \@positions will be parsed by mp@positions (down)
  \hrule\@height\z@}}%                                  This calculates the necessary vskip between the marginpars and typesets the
\fi}%                                               marginpars

\def\origin@positions#1#2{%                             this macro calculates the height of the top hrule (as determined by the footer @positions
%                                               the problem is that we have to measure from the bottom of the page, since
%                                               pdfsavedpos has an xy coordinate system that goes from the bottom left part
%                                               of the page....
  \dimen@#2sp%                                      set dimen@ to space between bottom edge of paper and baseline of footer
  \advance\dimen@\footskip%                             add the value of \footskip
  %                                             note that we've now added slightly too much, since footskip is more than
  %                                             the spacing between the baseline and the edge of the body text
  \advance\dimen@-.195\baselineskip%                            to address this issue, we adjust it by a value measured ``by hand''
  %                                             one could also decide to use \fontcharht and so on to do this
  \advance\dimen@\textheight%                               we now know the absolute value of the y height of the rule at the top of the
  %                                             margin column
\typeout{(page \thepage) Calculated absolute height of the top hrule: \the\dimen@^^J}%  we're going through this twice, since we have two pages
}%                                              why does this typeset twice on page two? Who knows...

\count6=0% auxiliary for the typeout info

\def\mp@positions#1#2{%                             This calculates the necessary vskip between the marginpars
  \advance\count6 by 1%                                 count the marginpars
  \advance\vbadness\@M
  \setbox\tw@=\vsplit\@mpbox to \maxdimen
  \advance\vbadness-\@M
  \setbox\tw@\vbox{%                                    following rows check/set the marginpar boxes, not very interesting for the
  \unvbox\tw@%                                      for the spacing, I guess
  \setbox\tw@\lastbox
  \setbox\tw@\hbox{%
  \unhbox\tw@
  \ifodd\c@page
    \global\setbox1\lastbox%                                box1 --> a single marginpar
  \fi
  \global\setbox1\lastbox%                              kill the right marginbox if page is odd, otherwise, simply use lastbox
  }}%                                               since it already holds the right marginpar
  %                                             we're iterating over this, since we have a CHAIN of `\@positions`
  \@tempdimb\dimen@%                                    temporarily set tempdimb to dimen@ and determine how large the vskip must be
  \advance\@tempdimb-#2sp%                              subtract the x position height of the marginpar
\typeout{(page \thepage) Calculated vskip from bottom of last marginpar (or top of hrule) for \the\count6: \the\@tempdimb^^J}%
  \ifdim\@tempdimb<\marginparmindistance%                       marginparpush: if the calculated height of tempdimb is smaller than this,
    \@tempdimb\marginparmindistance%                            simply set this as the next marginpar vskip...
  \fi%
  \vskip\@tempdimb%                                 this is where the magic happens: we have now determined the vskip
  \advance\dimen@-\@tempdimb%                           subtract the vskip and the height and depth of the marginparbox
  \advance\dimen@-\ht\@ne%                              and use \dimen@ for the next use of \@positions
  \advance\dimen@-\dp\@ne%                              in that sense \dimen@ is really an anchor point of current ypositioning to 
  \hrule\@height\z@%                                    determine vskip iteratively for the next marginpar.
  \box\@ne%                                     (typeset the marginpar)
  \hrule\@height\z@
}
\makeatother

\usepackage{sidenotes}

\def\blindtext{Hello, here is some text without a meaning. This text should
show what a printed text will look like at this place. If you
read this text, you will get no information. Really? Is there no
information? Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look. This text
should contain all letters of the alphabet and it should be written
in of the original language. There is no need for special content,
but the length of words should match the language.}

\begin{document}

Hello, here is some text without a meaning. This text should
show what a printed text will look like at this place. If you
read this text, you will get no information. Really? Is there no
information? Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look. This text
should contain all letters of the alphabet and it should be written
in of the original language. There is no need for special content,
but the length of words should match the language. Some words.\sidenote{ Really? Is there no
information? Is there a difference between this text and some
nonsense like .}

\blindtext\sidenote{ Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look.}

\blindtext\sidenote{ Is there a difference between this text and some
nonsense like Huardest gefburn"? }

\blindtext\sidenote{ This text
should contain all letters of the alphabet and it should be written
in of the original language.}\sidenote{ This text
should contain all letters of the alphabet and it should be written
in of the original language.}

\blindtext\sidenote{ This text
should contain all letters of the alphabet and it should be written
in of the original language.}

\blindtext\sidenote{ This text
should contain all letters of the alphabet and it should be written
in of the original language.}

\blindtext\sidenote{ This text
should contain all letters of the alphabet and it should be written
in of the original language.}

\end{document}
5

I ended up settling for the solution shown below. It requires three runs to typeset everything and is independent of the chosen page dimensions (as far as I know). I have done some superficial testing with fancyhdr and different classes, like article, book and scrartcl. Load the packages or adjust \@evenfoot or \@oddfoot directly before this code is read (to allow it to make the redefinitions of these macros).

19-5-2015: Updated the code for compatibility with fancyhdr

21-5-2015: Updated the code to fix a bug with the minimum marginpar distance

26-5-2015: Moved the offset declaration from the aux to the document itself to avoid bugs with custom classes (like mine)

Short version:

\documentclass[twoside]{article}
\usepackage[paperwidth=200mm, paperheight=240mm,top=50pt, textwidth=280pt, marginparwidth=95pt, textheight=45\baselineskip,footskip=40pt]{geometry}%

\makeatletter

\def\@oddfoot{\hss\thepage}
\def\@evenfoot{\thepage\hss}

\@ifpackageloaded{fancyhdr}{%
\def\ps@@fancy{%
\ps@@empty %
\def\@mkboth{\protect\markboth}%
\def\@oddhead{\@fancyhead\fancy@Oolh\f@ncyolh\f@ncyoch\f@ncyorh\fancy@Oorh}%
\def\@oddfoot{\@fancyfoot\fancy@Oolf\f@ncyolf\f@ncyocf\f@ncyorf\fancy@Oorf\rlap{\hskip\marginparsep\mcolumn}}%
\def\@evenhead{\@fancyhead\fancy@Oelh\f@ncyelh\f@ncyech\f@ncyerh\fancy@Oerh}%
\def\@evenfoot{\llap{\mcolumn\hskip\marginparsep}\@fancyfoot\fancy@Oelf\f@ncyelf\f@ncyecf\f@ncyerf\fancy@Oerf}%
}%
}{%
\expandafter\def\expandafter\@oddfoot\expandafter{%
\@oddfoot\rlap{\hskip\marginparsep\mcolumn}%
}%
\expandafter\def\expandafter\@evenfoot\expandafter{%
\expandafter\llap\expandafter{\expandafter\mcolumn\expandafter\hskip\expandafter\marginparsep\expandafter}\@evenfoot%
}%
}

\newbox\mp@box
\newdimen\marginparmindistance \marginparmindistance=10\p@
\newdimen\mp@min@ht@required
\newdimen\mp@tempdim
\newdimen\mp@ht@botrule
\countdef\mp@count=6 \mp@count\z@
\newcount\mp@count@ \mp@count@\z@%
\global\setbox\mp@box\vbox{}%
\newlength{\mp@maxht}
\newlength{\mp@maxdp}

\long\def\marginpar#1{%
  \saveposition{mpar}%
  \global\setbox\mp@box\vbox{\unvbox\mp@box\hbox{%
  \hbox{\parbox[t]{\marginparwidth}{\@marginparreset#1\@minipagefalse}}%
  \hbox{\parbox[t]{\marginparwidth}{\@marginparreset#1\@minipagefalse}}%
}\break}}

\def\saveposition#1{%
\pdfsavepos\write\@auxout{%
  \noexpand\savedpos%
    {#1}{\the\c@page}{\the\pdflastxpos}{\the\pdflastypos}}}

\def\savedpos#1#2#3#4{%
\begingroup
  \let\@positions\relax
  \expandafter\xdef\csname sp@#1-#2\endcsname{%
    \expandafter\ifx\csname sp@#1-#2\endcsname\relax
    \else
      \csname sp@#1-#2\endcsname                            
    \fi                                     
  \@positions{#3}{#4}}%
  \endgroup}%


\def\mcolumn{%
\saveposition{foot}%
\expandafter\ifx\csname sp@foot-\the\c@page\endcsname\relax%
\else%
  \let\@positions\origin@positions%
  \csname sp@foot-\the\c@page\endcsname%
  \vfuzz=\marginparmindistance
  \advance\vfuzz-\ht\@ne
  \smash{\raise\footskip\vbox to \textheight{\hsize\marginparwidth%
  \hrule\@height\z@%
  \let\@positions\mp@positions%
  \expandafter\ifx\csname mpars-page-\the\c@page\endcsname\relax
  \else
    \begingroup
      \loop
      \ifnum\mp@count@<\csname mpars-page-\the\c@page\endcsname%
        \setboxes
        \advance\mp@count@\@ne %
      \repeat
    \endgroup
  \fi
  \csname sp@mpar-\the\c@page\endcsname
  \vskip\z@\@plus\textheight%
  \hrule\@height\z@
  \immediate\write\@auxout{\string\global\noexpand\@namedef{mpars-page-\the\c@page}{\the\mp@count}}}}%
\fi}

\AtBeginDocument{%
\setbox0=\vtop{\textsuperscript{1}g}% temporary
\setlength{\mp@maxht}{\the\ht0}%
\setlength{\mp@maxdp}{\the\dp0}%
}

\def\origin@positions#1#2{%
  \dimen@#2sp
  \advance\dimen@\footskip
  \mp@ht@botrule\dimen@
  \advance\mp@ht@botrule-\mp@maxdp% correction for additional spacing in footskip
  \advance\dimen@\textheight
}

\def\setboxes{%
  \advance\mp@count\@ne%
  \advance\vbadness\@M
  \setbox0=\vsplit\mp@box to \maxdimen
  \advance\vbadness-\@M
  \setbox0\vbox{%
  \unvbox0% 
  \setbox0\lastbox
  \setbox0\hbox{%
  \unhbox0
  \ifodd\c@page
    \global\setbox\mp@count\lastbox%
  \fi
  \global\setbox\mp@count\lastbox%
  }}%
  }

\def\mp@positions#1#2{%
  \advance\mp@count\@ne%
  \@tempdimb\dimen@%
  \advance\@tempdimb-#2sp%
  \advance\@tempdimb-\mp@maxht
  \begingroup%
    \expandafter\ifx\csname mpars-page-\the\c@page\endcsname\relax%
    \else%
      \global\mp@min@ht@required\z@%
      \advance\mp@count\m@ne
      \loop%
      \ifnum\mp@count<\csname mpars-page-\the\c@page\endcsname%
        \advance\mp@count\@ne%
        \global\advance\mp@min@ht@required\ht\mp@count %
        \global\advance\mp@min@ht@required\dp\mp@count %
        \ifnum\mp@count=\csname mpars-page-\the\c@page\endcsname
        \else
          \global\advance\mp@min@ht@required\marginparmindistance%
        \fi
      \repeat
      \global\advance\mp@min@ht@required\@tempdimb
    \fi
  \endgroup
  \mp@tempdim\dimen@
  \advance\mp@tempdim-\mp@ht@botrule
  \ifdim\mp@tempdim<\mp@min@ht@required
    \advance\@tempdimb\mp@tempdim
    \advance\@tempdimb-\mp@min@ht@required
  \fi
  \ifnum\mp@count=\@ne
  \else
  \ifdim\@tempdimb<\marginparmindistance
    \@tempdimb\marginparmindistance
  \fi
  \fi
  \vskip\@tempdimb
  \advance\dimen@-\@tempdimb
  \advance\dimen@-\ht\mp@count %
  \advance\dimen@-\dp\mp@count %
  \hrule\@height\z@
  \box\mp@count %
  \hrule\@height\z@
}
\makeatother


\usepackage{sidenotes}

\def\blindtext{Hello, here is some text without a meaning. This text should
show what a printed text will look like at this place. If you
read this text, you will get no information. Really? Is there no
information? Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look. This text
should contain all letters of the alphabet and it should be written
in of the original language. There is no need for special content,
but the length of words should match the language.}

\begin{document}

Hello, here is some text without a meaning. This text should
show what a printed text will look like at this place. If you
read this text, you will get no information. Really? Is there no
information? Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look. This text
should contain all letters of the alphabet and it should be written
in of the original language. There is no need for special content,
but the length of words should match the language. Some words.\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext

\blindtext

Hello, here is some text without a meaning. This text should
show what a printed text will look like at this place. If you
read this text, you will get no information. Really? Is there no
information? Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look. This text
should contain all letters of the alphabet and it should be written
in of the original language. There is no need for special content,
but the length of words should match the language.\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\end{document}

Compatibility/debug version (this shows the calculations done). NB This version is not updated since 21-5-2015.

\documentclass[twoside]{article}
\usepackage[paperwidth=200mm, paperheight=240mm,top=70pt, textwidth=280pt, marginparwidth=100pt, textheight=47\baselineskip,footskip=30pt]{geometry}%

\makeatletter

\def\@oddfoot{\hss\thepage}
\def\@evenfoot{\thepage\hss}

\@ifpackageloaded{fancyhdr}{%
\def\ps@@fancy{%
\ps@@empty %
\def\@mkboth{\protect\markboth}%
\def\@oddhead{\@fancyhead\fancy@Oolh\f@ncyolh\f@ncyoch\f@ncyorh\fancy@Oorh}%
\def\@oddfoot{\@fancyfoot\fancy@Oolf\f@ncyolf\f@ncyocf\f@ncyorf\fancy@Oorf\rlap{\hskip\marginparsep\mcolumn}}%
\def\@evenhead{\@fancyhead\fancy@Oelh\f@ncyelh\f@ncyech\f@ncyerh\fancy@Oerh}%
\def\@evenfoot{\llap{\mcolumn\hskip\marginparsep}\@fancyfoot\fancy@Oelf\f@ncyelf\f@ncyecf\f@ncyerf\fancy@Oerf}%
}%
}{%
\expandafter\def\expandafter\@oddfoot\expandafter{%
\@oddfoot\rlap{\hskip\marginparsep\mcolumn}%
}%
\expandafter\def\expandafter\@evenfoot\expandafter{%
\expandafter\llap\expandafter{\expandafter\mcolumn\expandafter\hskip\expandafter\marginparsep\expandafter}\@evenfoot%
}%
}

\newbox\mp@box
\newdimen\marginparmindistance \marginparmindistance=10\p@
\newdimen\mp@min@ht@required
\newdimen\mp@tempdim
\newdimen\mp@ht@botrule
\countdef\mp@count=6 \mp@count\z@
\newcount\mp@count@ \mp@count@\z@%
\global\setbox\mp@box\vbox{}%

\long\def\marginpar#1{%
  \saveposition{mpar}%
  \global\setbox\mp@box\vbox{\unvbox\mp@box\hbox{%
  \hbox{\parbox[t]{\marginparwidth}{\@marginparreset#1\@minipagefalse}}%
  \hbox{\parbox[t]{\marginparwidth}{\@marginparreset#1\@minipagefalse}}%
}\break}}

\def\saveposition#1{%
\pdfsavepos\write\@auxout{%
  \noexpand\savedpos%
    {#1}{\the\c@page}{\the\pdflastxpos}{\the\pdflastypos}}}

\def\savedpos#1#2#3#4{%
\begingroup
  \let\@positions\relax
  \expandafter\xdef\csname sp@#1-#2\endcsname{%
    \expandafter\ifx\csname sp@#1-#2\endcsname\relax
    \else
      \csname sp@#1-#2\endcsname                            
    \fi                                     
  \@positions{#3}{#4}}%
  \endgroup}%


\def\mcolumn{%
\saveposition{foot}%
\expandafter\ifx\csname sp@foot-\the\c@page\endcsname\relax%
\else%
  \let\@positions\origin@positions%
  \csname sp@foot-\the\c@page\endcsname%
  %\vfuzz=\marginparmindistance
  %\advance\vfuzz-\ht\@ne
  \smash{\raise\footskip\vbox to \textheight{\hsize\marginparwidth%
  \hrule\@height\z@%
  \let\@positions\mp@positions%
  \expandafter\ifx\csname mpars-page-\the\c@page\endcsname\relax
  \else
    \begingroup
      \loop
      \ifnum\mp@count@<\csname mpars-page-\the\c@page\endcsname%
        \setboxes
        \advance\mp@count@\@ne %
      \repeat
    \endgroup
  \fi
  \csname sp@mpar-\the\c@page\endcsname
  \vskip\z@\@plus\textheight%
  \hrule\@height\z@
  \immediate\write\@auxout{\string\global\noexpand\@namedef{mpars-page-\the\c@page}{\the\mp@count}}}}%
\fi}

\newlength{\mp@maxht}
\newlength{\mp@maxdp}
\AtBeginDocument{%
\setbox0=\vtop{\textsuperscript{1}g}% temporary
\immediate\write\@auxout{\string\global\noexpand\setlength{\mp@maxht}{\the\ht0}}%
\immediate\write\@auxout{\string\global\noexpand\setlength{\mp@maxdp}{\the\dp0}}%
}

\def\origin@positions#1#2{%
  \dimen@#2sp
  \@tempdima#2sp
  \advance\dimen@\footskip
  \mp@ht@botrule\dimen@
  \advance\mp@ht@botrule-\mp@maxdp% correction for additional spacing in footskip
  \typeout{_____________________________}%
  \typeout{}%
  \typeout{*** Origin@positions calculations ***}%
  \typeout{_____________________________}%
  \typeout{}%
  \typeout{H_footer + \footskip - correction = H_botrule}%
  \typeout{\the\@tempdima\space+ \the\footskip\space - \the\mp@maxdp\space = \the\mp@ht@botrule}%
  \advance\dimen@\textheight
  \typeout{H_botrule+ \textheight = H_toprule}%
  \typeout{\the\mp@ht@botrule\space+ \the\textheight\space= \the\dimen@}%
  \typeout{_____________________________}%
  \typeout{}%
  \typeout{*** MP@positions calculations ***}%
  \typeout{_____________________________}%
}

\def\setboxes{%
  \advance\mp@count\@ne%
  \advance\vbadness\@M
  \setbox0=\vsplit\mp@box to \maxdimen
  \advance\vbadness-\@M
  \setbox0\vbox{%
  \unvbox0% 
  \setbox0\lastbox
  \setbox0\hbox{%
  \unhbox0
  \ifodd\c@page
    \global\setbox\mp@count\lastbox%
  \fi
  \global\setbox\mp@count\lastbox%
  }}%
  }

\newcount\@@@
\newdimen\mp@realheight
\def\mp@positions#1#2{%
  \advance\mp@count\@ne%
  \typeout{}%
  \typeout{*** Margin paragraph \the\mp@count\space ***}%
  \typeout{_____________________________}%
  \typeout{}%
  \@tempdimb\dimen@%
  \@tempdima#2sp%
  \advance\@tempdimb-#2sp%
  \advance\@tempdimb-\mp@maxht
  \typeout{Testing distance between bottom of last marginpar and current marginpar . . .}%
  \typeout{}%
  \typeout{H_last - H_curr - correction = V}%
  \typeout{\the\dimen@\space - \the\@tempdima - \the\mp@maxht= \the\@tempdimb}%
  \typeout{_____________________________}%
  \typeout{}%
  \typeout{Testing how much height is available not to overflow the marginpar column . . .}%
  \typeout{H_curr - H_botrule = d_available}%
  \@tempdima\dimen@
  \advance\@tempdima-\mp@ht@botrule
  %\advance\@tempdima\mp@maxht
  \typeout{\the\dimen@\space - \the\mp@ht@botrule = \the\@tempdima}%
  \typeout{_____________________________}%
  \typeout{}%
  \begingroup%
    \typeout{Testing how much height is required to typeset all marginpars and seps . . .}%
    \typeout{_____________________________}%
    \typeout{}%
    \expandafter\ifx\csname mpars-page-\the\c@page\endcsname\relax%
    \else%
      \global\mp@min@ht@required\z@%
      \@@@\mp@count
      \advance\mp@count\m@ne
      \loop%
      \ifnum\mp@count<\csname mpars-page-\the\c@page\endcsname%
        \advance\mp@count\@ne%
        \@tempdima\mp@min@ht@required
        \mp@tempdim\ht\mp@count
        \advance\mp@tempdim\dp\mp@count
        \global\advance\mp@min@ht@required\ht\mp@count %
        \global\advance\mp@min@ht@required\dp\mp@count %
        \ifnum\mp@count=\csname mpars-page-\the\c@page\endcsname
        \typeout{H_start + mpar\the\mp@count\space = H_min,new}%
        \typeout{\the\@tempdima\space + \the\mp@tempdim\space = \the\mp@min@ht@required}%
        \else
          \global\advance\mp@min@ht@required\marginparmindistance%
          \typeout{H_start + mpar\the\mp@count\space + delta_mpar = H_min,new}%
          \typeout{\the\@tempdima\space + \the\mp@tempdim\space + \the\marginparmindistance = \the\mp@min@ht@required}%
        \fi
      \repeat
      \@tempdima\mp@min@ht@required
      \global\advance\mp@min@ht@required\@tempdimb
      \typeout{}%
      \typeout{H_min,mpars + V = H_min,req}%
      \typeout{\the\@tempdima\space + \the\@tempdimb\space = \the\mp@min@ht@required}%
      \typeout{_____________________________}%
      \typeout{}%
    \fi
  \endgroup
%  \mp@tempdim\ht\mp@count
%  \advance\mp@tempdim\dp\mp@count
%  \typeout{(marginpar \the\mp@count\space - 4) Height and depth of this marginpar is \the\mp@tempdim.}%
  \mp@tempdim\dimen@
%  \advance\mp@tempdim-\@tempdimb
%  \advance\mp@tempdim-\ht\mp@count
%  \advance\mp@tempdim-\dp\mp@count
  \advance\mp@tempdim-\mp@ht@botrule
  %\advance\mp@tempdim\mp@maxht
%  \typeout{Calculating how much room is available . . .}%
%  \typeout{}%
%  \typeout{H_curr - H_botrule = d_avail}%
%  \typeout{\the\dimen@\space - \the\mp@ht@botrule\space = \the\mp@tempdim}%
%  \typeout{_____________________________}%
%  \typeout{}%
  \typeout{Comparing with the minimum calculated required height . . .}%
  \typeout{}%
  \ifdim\mp@tempdim<\mp@min@ht@required
    \typeout{d_available < H_min,req}%
    %\typeout{\the\dimen@\space - \the\mp@ht@botrule\space < \the\mp@min@ht@required}%

    %\advance\@tempdima\@tempdimb
    \typeout{\the\mp@tempdim\space < \the\@tempdima}%
    %\advance\@tempdimb\mp@tempdim
    \advance\@tempdimb\mp@tempdim
    \advance\@tempdimb-\mp@min@ht@required
    \else
    \typeout{d_available > H_min,req}%
    %\typeout{\the\dimen@\space - \the\mp@ht@botrule\space > \the\mp@min@ht@required}%
    \@tempdima\mp@min@ht@required
    %\advance\@tempdima\@tempdimb
    \typeout{\the\mp@tempdim\space > \the\@tempdima}%
  \fi
  \typeout{_____________________________}%
  \typeout{}%
  \ifnum\mp@count=\@ne
  \else
  \typeout{Testing if the calculated vskip is larger than the maximum allowed vskip . . .}%
  \typeout{}%
  \ifdim\@tempdimb<\marginparmindistance
    \typeout{V < delta_mpar}%
    \typeout{\the\@tempdimb\space < \the\marginparmindistance}%
      \@tempdimb\marginparmindistance
    \else
    \typeout{V > delta_mpar}%
    \typeout{\the\@tempdimb\space > \the\marginparmindistance}%
  \fi
  \fi
  \typeout{}%
  \typeout{*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.}%
  \typeout{}%
  \typeout{---> V = \the\@tempdimb.}%
  \vskip\@tempdimb
  \typeout{}%
  \typeout{*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.}%
  \typeout{_____________________________}%
  \typeout{}%
  \typeout{Determining new height . . .}%
  \typeout{}%
  \@tempdimc\ht\mp@count
  \advance\@tempdimc\dp\mp@count
  \@tempdima\dimen@
  \advance\dimen@-\@tempdimb
  \advance\dimen@-\ht\mp@count %
  \advance\dimen@-\dp\mp@count %
  %\typeout{}%
  \typeout{H_curr - V - mpar\the\mp@count\space = H_new}%
  \typeout{\the\@tempdima\space - \the\@tempdimb\space - \the\@tempdimc\space = \the\dimen@}%
  \hrule\@height\z@
  \ifnum\mp@count=\@ne
    %\vskip-\ht\mp@count
  \fi
  \box\mp@count %
  \hrule\@height\z@
  \typeout{}%
  \typeout{_____________________________}%
}
%\hbadness\@M
\makeatother


\usepackage{sidenotes}

\def\blindtext{Hello, here is some text without a meaning. This text should
show what a printed text will look like at this place. If you
read this text, you will get no information. Really? Is there no
information? Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look. This text
should contain all letters of the alphabet and it should be written
in of the original language. There is no need for special content,
but the length of words should match the language.}

\begin{document}

Hello, here is some text without a meaning. This text should
show what a printed text will look like at this place. If you
read this text, you will get no information. Really? Is there no
information? Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look. This text
should contain all letters of the alphabet and it should be written
in of the original language. There is no need for special content,
but the length of words should match the language. Some words.\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today. Now I'm making it slightly longer to make it stand out of the other marginpars.}\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext

Hello, here is some text without a meaning. This text should
show what a printed text will look like at this place. If you
read this text, you will get no information. Really? Is there no
information? Is there a difference between this text and some
nonsense like Huardest gefburn"? Kjift  not at all! A blind
text like this gives you information about the selected font, how
the letters are written and an impression of the look. This text
should contain all letters of the alphabet and it should be written
in of the original language. There is no need for special content,
but the length of words should match the language.\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\blindtext\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}\sidenote{This is a really nice marginpar. Hello, I'm a marginpar, and I'm doing great today.}

\end{document}
  • Don't know if it is bulletproof, but it shows a lot of effort! – Steven B. Segletes May 17 '15 at 0:46
  • @StevenB.Segletes After some small testing I found it wasn't bullet proof yet. :( The bottom hrule is apparently wrongly measured, and topskip from geometry changes some alignment... guess I have to go back to the drawing table again – 1010011010 May 17 '15 at 7:59
  • 1
    @StevenB.Segletes I believe everything is fixed now in the last version (3rd piece of code), if you're interested. – 1010011010 May 18 '15 at 21:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.