This question was apparently brought up back in 2001[1] but with no
answer. I hope I will be luckier this time. I am using margin notes at
the beginning of each paragraph (to provide hints about what the main
idea is). When the beginning of a paragraph is a potential orphan,
this causes TeX (pdflatex in that case) to fail to handle them
correctly, even when it is forced to avoid orphans (with window and
club penalty = 9999). I made a (as minimal as possible) test file
here:
http://jo.irisson.free.fr/dropbox/marginpar-penalty-test.zip
and you also get the pdf outputs. Which are:
no penalty -> orphan
penalty -> OK
no penalty+note -> orphan and note sticking out vertically
penalty+note -> no orphan, note on previous page, still sticking
out
penalty+new note -> orphan and note sticking out
NB: the new note is a classic redefinition of notes that make them
raggedleft or right depending on the page, in a two page layout. it is
the one I am using in the real document.
I am also using memoir, and, with it, the behaviour is the same except
that penalty must be set at 10000 (9999 is not enough).
In all cases, there are absolutely no warnings or "badnesses" in
pdflatex output.
So my questions are:
- is there a way to get latex to avoid these orphans (other than
placing the note later in the paragraph)?
- is there a way to at least avoid that the notes stick out of the
page? i.e. notes should be centered on the portion of the paragraph to
which they are attached when in the middle of the page but should bump
again page top and page bottom so that notes on the last line are
bottom aligned with the line and notes on the first line are top
aligned. (NB: with the new definition, notes are always top aligned).
Thank you very much in advance.
-- JiHO
Thanks for your anwser. Unfortunately, mparhack does not help with
that particular problem. From the description on CTAN:
"Implements a workaround for the LaTeX bug that marginpars will
sometimes come out at the wrong margin."
I tested it, it does not change the behavior above (but helps in some
cases in which the margin notes were indeed in the wrong margin).
For your first question about avoiding the orphan, what about
inserting a \leavevmode before each \marginpar?
Regarding the second question about the marginpar falling off the
bottom of the page, I'm not sure to what extent it's possible with the
current LaTeX marginpar code. Presumably, one could hook into
\@addmarginpar and ask if the appropriate box (\@currbox or \@marbox)
will fit in the margin as it stands. If it would fall out the bottom,
then the next thing it could try would be to push it upward enough to
keep the bottom of the box lined up with the bottom of the page (as
given by \textheight or \@colroom or something). This should solve
most problems, unless there's already another box above it that would
cause an intersection. Because this previous box was set long before
we even knew there would be another box after it, there's nothing we
can do about it at this point. So the best bet would be to defer the
margin note. As far as I know, there is no built-in way to do this,
but it wouldn't be hard to save all such deferred notes onto a list
(we'd need to hold off on automatically freeing the boxes at the
beginning of \@addmarginpar) and then run them at the beginning of the
next page to stack them up at the top.
steve hicks
\documentclass[10pt,a4paper,oneside]{book}
%
% This is an attempt to fix a problem in which a marginpar near
% the bottom of a page prints at the bottom of the page even
% though the user set the widow and club PENALTIES so that the
% paragraph is now on the next page. The mparhack package did
% not fix the problem (but it fixes other problems).
%
% If you copy the macros to your own .sty file, remove the
% \makeatother and \makeatletter commands.
%
%
% The afterpage package allows the user to run a macro after
% the current page has been shipped out (printed):
\usepackage{afterpage}
\usepackage{mparhack}
% Custom note definition
% \let\oldmarginpar\marginpar
% \renewcommand\marginpar[1]{\-\oldmarginpar[\raggedleft#1]%
% {\raggedright#1}}
%
% COMMENT THE PENALTIES TO TEST THE MARGINPAR PLACEMENT:
\widowpenalty=10000
\clubpenalty=10000
%%
\makeatletter
\global\newif\if@firstrun \@firstruntrue
%
\ifx\@currbox\@undefined
\newbox\@currbox
\fi
\def\marginparP#1#2{%
% pass two arguments:
% 1) a label name for the marginpar (enter regular text without
% spaces or numbers or funny chars)
% 2) the content of the marginpar
%
% WARNING: if you modify this macro and accidently insert a
% character or trailing space, the entire macro could be ruined.
%
% This assumes that the new marginpar command (\marginparP, the
% "P" is for "penalty") is placed as the first item
% in the new paragraph and is glued
% to the front of the first word in the paragraph.
%
% The approach was to wrap the marginpar command in another macro
% and let latex compile the first time with no margin pars. I also
% set a label so that I can tell on the next pass if the block went
% to the next page. If so, I save a code that says to send the
% marginpar to the next page, else I save a different code that
% says to leave the marginpar alone. All subsequent compiles will
% use the selected placement for the marginpar.
%
% save some page numbers
\edef\MPPhere{\thepage}%
\edef\MPPlabel{\pageref{#1}}%
%
% Write a code to the aux file that will process in the
% next compile and tell me that I'm no longer in the
% "first run" (not in the first compile of the LaTeX
% document):
\protected@write\@auxout{}{%
\string\gdef\string\secondrun{1}}%
\@ifundefined{secondrun}{%
\typeout{*********** first run}%
% I am printing a character to leave vertical mode.
% When this happens, the label will stick to the text while
% the call to \marginparP will remain on the old page because
% latex is still collecting info for the prior paragraph until
% it hits a character or a \leavevmode command (or something
% like that.
%{.}\label{#1}%
\leavevmode\label{#1}%
}%
{% after first run:
\@firstrunfalse
\typeout{*** beyond first run}%
% this is the second run or beyond
\@ifundefined{thirdrun}{%
% this is exactly the second run, so run it exactly once:
\ifnum\MPPhere=\MPPlabel
\typeout{**** the par stayed on the original page}%
\marginpar{#2}%
\protected@write\@auxout{}{%
\string\gdef\string\thirdrun{1}}%code 1 for "old page"
\else
% push the margin par to the next page by redefining the macro
% that was defined after the first word of the line
\typeout{**** the par moved to the next page}%
\afterpage{\protect\marginpar{#2}}%
\protected@write\@auxout{}{%
\string\gdef\string\thirdrun{2}}%code 2 for "next page"
\fi
}%
{% else we are on the third run or beyond
% use the saved value in "thirdrun" to determine how to
% place the float
\typeout{*** third run or more}%
\ifnum2=\thirdrun
\afterpage{\protect\marginpar{#2}}%
\else
\marginpar{#2}
\fi
\protected@write\@auxout{}{%
\string\gdef\string\thirdrun{\thirdrun}}%save the code
}
}
% note that "\string{" writes a left parenthesis, and the "{"
% does not open a argument for the \string macro:
}
\makeatother
%%
\begin{document}
\section{CHAPTER I -- Down the Rabbit-Hole}
Alice was beginning to get very tired of sitting by her sister on the
bank, and of having nothing to do: once or twice she had peeped into
the book her sister was reading, but it had no pictures or
conversations in it, `and what is the use of a book,' thought Alice
`without pictures or conversation?'
So she was considering in her own mind (as well as she could, for the
hot day made her feel very sleepy and stupid), whether the pleasure of
making a daisy-chain would be worth the trouble of getting up and
picking the daisies, when suddenly a White Rabbit with pink eyes ran
close by her.
There was nothing so very remarkable in that; nor did Alice think it
so very much out of the way to hear the Rabbit say to itself, `Oh
dear! Oh dear! I shall be late!' (when she thought it over afterwards,
it occurred to her that she ought to have wondered at this, but at the
time it all seemed quite natural); but when the Rabbit actually took a
watch out of its waistcoat-pocket, and looked at it, and then hurried
on, Alice started to her feet, for it flashed across her mind that she
had never before seen a rabbit with either a waistcoat-pocket, or a
watch to take out of it, and burning with curiosity, she ran across
the field after it, and fortunately was just in time to see it pop
down a large rabbit-hole under the hedge.
In another moment down went Alice after it, never once considering how
in the world she was to get out again.
The rabbit-hole went straight on like a tunnel for some way, and then
dipped suddenly down, so suddenly that Alice had not a moment to think
about stopping herself before she found herself falling down a very
deep well.
Either the well was very deep, or she fell very slowly, for she had
plenty of time as she went down to look about her and to wonder what
was going to happen next. First, she tried to look down and make out
what she was coming to, but it was too dark to see anything; then she
looked at the sides of the well, and noticed that they were filled
with cupboards and book-shelves; here and there she saw maps and
pictures hung upon pegs. She took down a jar from one of the shelves
as she passed; it was labelled `ORANGE MARMALADE', but to her great
disappointment it was empty: she did not like to drop the jar for fear
of killing somebody, so managed to put it into one of the cupboards as
she fell past it.
`Well!' thought Alice to herself, `after such a fall as this, I shall
think nothing of tumbling down stairs! How brave they'll all think me
at home! Why, I wouldn't say anything about it, even if I fell off the
top of the house!' (Which was very likely true.)
Down, down, down. Would the fall never come to an end! `I wonder how
many miles I've fallen by this time?' she said aloud. `I must be
getting somewhere near the centre of the earth. Let me see: that would
be four thousand miles down, I think--' (for, you see, Alice had
learnt several things of this sort in her lessons in the schoolroom,
and though this was not a very good opportunity for showing off her
knowledge, as there was no one to listen to her, still it was good
practice to say it over) `--yes, that's about the right distance--but
then I wonder what Latitude or Longitude I've got to?' (Alice had no
idea what Latitude was, or Longitude either, but thought they were
nice grand words to say.)
% Margin note added at the top of an orphan-generating paragraph
\marginparP{abcd}{A margin\\ note on\\ several lines}Presently she
began again. `I wonder if I shall fall right through the earth! How
funny it'll seem to come out among the people that walk with their
heads downward! The Antipathies, I think--' (she was rather glad there
was no one listening, this time, as it didn't sound at all the right
word) `--but I shall have to ask them what the name of the country is,
you know. Please, Ma'am, is this New Zealand or Australia?' (and she
tried to curtsey as she spoke--fancy curtseying as you're falling
through the air! Do you think you could manage it?) `And what an
ignorant little girl she'll think me for asking! No, it'll never do to
ask: perhaps I shall see it written up somewhere.'
Down, down, down. There was nothing else to do, so Alice soon began
talking again. `Dinah'll miss me very much to-night, I should
think!' (Dinah was the cat.) `I hope they'll remember her saucer of
milk at tea-time. Dinah my dear! I wish you were down here with me!
There are no mice in the air, I'm afraid, but you might catch a bat,
and that's very like a mouse, you know. But do cats eat bats, I
wonder?' And here Alice began to get rather sleepy, and went on saying
to herself, in a dreamy sort of way, `Do cats eat bats? Do cats eat
bats?' and sometimes, `Do bats eat cats?' for, you see, as she
couldn't answer either question, it didn't much matter which way she
put it. She felt that she was dozing off, and had just begun to dream
that she was walking hand in hand with Dinah, and saying to her very
earnestly, `Now, Dinah, tell me the truth: did you ever eat a bat?'
when suddenly, thump! thump! down she came upon a heap of sticks and
dry leaves, and the fall was over.
\end{document}
Thank you very much for your answers. Sorry not to have got back to
you sooner.
On Apr 2, 9:31 am, Steve Hicks <stephenhi...@gmail.com> wrote:
> For your first question about avoiding the orphan, what about
> inserting a \leavevmode before each \marginpar?
It does not seem to change anything, both on the test document and on
my complete text.
> Regarding the second question about the marginpar falling off the
> bottom of the page, I'm not sure to what extent it's possible with the
> current LaTeX marginpar code. Presumably, one could [...]
This is apparently more or less what vvvv did. I hate to say that
since you really took a great stab at the problem... but it seems not
to work for me :/. I tried your document and, for me, the margin note
is still on previous page, sticking out at the bottom of the text,
with our without the penalties. I am using pdflatex from TeXLive 2007.
Is there anything I can do to test?
Thank you again for having looked at the problem in such depth. I hope
we'll be able to make it work in the end.
-- JiHO
I tried copying the tex program from one computer to the other, and
the program did not seem to be the problem. I copied latex.ltx,
book.cls, afterpage.sty, and mparhack.sty from the computer that works
to the other one that didn't, and I still got the error.
Perhaps there is a difference in configuration files or in some
auxliary file that is input from book.cls. I'll see what I can
discover.
Check that there was no extra space introduced into the file that you
copied from my long example above. The culprit might have been near
the end of the marginparP macro -- delete the BLANK line that appears
before the last "}" so that the end of the macro looks like this::
...
\protected@write\@auxout{}{%
\string\gdef\string\thirdrun{\thirdrun}}%save the code
}
}
% note that "\string{" writes a left parenthesis, and the "{"
% does not open a argument for the \string macro:
}
Then check to be sure that another line didn't word wrap. The line
that says:
\marginparP{abcd}{A margin\\ note on\\ several lines}Presently she
should start on a new line and it should be glued to the front of the
first real word in the paragraph.
I had downloaded the program to my laptop, and the difference between
the computers was the space that was introduced as described above.
This form will wrap lines, and I guess I had a bunch of spaces at the
end of that line. I had noted in the original post that the macro
would break if a space were introduced!! It is fragile if you edit
that macro.
OK, I got it. Sorry for all the trouble it caused you. I am using
google groups and also saw the additional blank lines. Anyway, I
suppressed them and indeed it works! The last bit of trouble is that
the margin note, when moved on the next page, is shifted up a bit,
hence is not aligned with the text anymore. See
http://jo.irisson.free.fr/dropbox/marginpar-shift.png
I did not see any length measurement in your patch so do you have any
idea about where I should look to fix this? Maybe that's afterpage's
fault?
Thanks a lot for your help.
-- JiHO
\marginparP{abcd}{\vskip.5\baselineskip A margin\\ note on\\ several
lines}
to add half a line height to the margin par, and it aligned it on the
top even when the margin par had extra lines, like this:
\marginparP{abcd}{\vskip.5\baselineskip A margin\\ note on\\ several
lines\\two more\\lines}
If all of the margin pars are shifted by the same amount, you could
put the \vskip.5\baselineskip in the macro.
OK I see, thanks a lot. I just wondered if there, possibly, was a
general solution. In any case, this will be useful at the end of the
writing of the manuscript. I'll just review all marginpar and use your
modification when needed. Thanks again.
-- JiHO
I'm bringing the topic back up because I had more information from
another post regarding margin notes. There is a flaw in the way I
wrote them previously which caused some of the behaviours seen here.
When written before the first word of the paragraph as:
\marginpar{A margin\\ note on\\ several lines}Presently she began
again.
TeX considers that the margin note is in fact _before_ the beginning
of the paragraph, i.e. it sits between two paragraphs. It explains why
the note is not aligned with the text. In this situation, it is also
natural for the note to stay on previous page when the paragraph is
moved on the next: it does not belong to this paragraph at all (so I
am sorry for all your trouble vvvv but it seems that the issue of the
page shift was my fault, not marginpar's).
Now, when written as:
Presently \marginpar{A margin\\ note on\\ several lines} she began
again.
The note is correctly associated with the paragraph, is aligned, and
never is on a different page than the paragraph (at least in my tests
with this text). It is also the case when the marginpar command is
redefined as:
\let\oldmarginpar\marginpar
\renewcommand\marginpar[1]{\-\oldmarginpar[\raggedleft#1]%
{\raggedright#1}}
because the soft hyphen (\-) has the side effect of starting the
paragraph (Off-topic: a better redefinition would probably use
\leavevmode instead of \-)
But the issue of the orphan remains: the first line of the paragraph
is potentially an orphan but, when the note is not there, setting the
penalties high works and the line is pushed to the next page; but it
becomes an orphan when the marginpar is added (even when the penalties
are set to 10000).
So the problem is how to avoid orphans even with a marginpar. Any
suggestion would be welcome. Thank you in advance.
-- JiHO
Example:
\documentclass[10pt,a4paper,oneside]{article}
\widowpenalty=9999
\clubpenalty=9999
\begin{document}
% With margin note added: orphan
% Presently \marginpar{A margin\\ note on\\ several lines}she
% Without margin note: the penalties work and the paragraph
% is pushed to the next page