# Why does a negative after skip in \@startsection go weird if you fiddle with the everypar hook?

So, I'm trying to answer this question: Extended draft mode which includes source information for manual print-out to source synchronisation and I've run into a weird problem. Check out this example:

\documentclass{article}
\usepackage{everyhook,marginnote}
\newif\ifnotmarginhook
\notmarginhooktrue
\PushPreHook{par}{%
\ifnotmarginhook
\notmarginhookfalse
\smash{\marginnote{\small\ttfamily\the\inputlineno}}
\notmarginhooktrue
\fi
}
\makeatletter
% \renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
%                                     {3.25ex \@plus1ex \@minus.2ex}%
%                                     {1em}%
%                                     {\normalfont\normalsize\bfseries}}
\makeatother
\begin{document}

\section{This works}

Here is some text and it will go on and on
Here is some text and it will go on and on
Here is some text and it will go on and on

\subsection{This too}

Here is some text and it will go on and on
Here is some text and it will go on and on
Here is some text and it will go on and on

\paragraph{Broken!}

Here is some text and it will go on and on
Here is some text and it will go on and on
Here is some text and it will go on and on

\end{document}

If you change the definition of \paragraph to have a positive value for afterskip (as in the commented out redefinition) then everything is fine. What is going on and how do I fix it? It looks like something is messing with boxes, but I don't understand what...

It looks like there's some funny business going on: my guess is that the negative skip means that TeX does \rlap of the paragraph name, measures the text of the paragraph title, then puts that much space at the start of a noindent paragraph plus the afterskip amount. Is something like that going on? How can I stop it overlapping?

-
The \paragraph command uses \everypar to typeset its title at the start of the next paragraph, so there's nothing really surprising that a conflict can exist. In your example, the problem seems to disappear by using \PushPostHook instead of \PushPreHook and recompiling twice. – Philippe Goutet Aug 8 '11 at 18:10
Building upon Philippe Goutet's suggestion, I'd note that the everyhook documentation has a remark along the lines of "careful if you use \PushPreHook{par}: you should \setbox0\lastbox and put \box0 after your tokens, to propagate the indentation box". Indeed, indentation removal (by \@doendpe and friends) is done with \lastbox. – Bruno Le Floch Aug 8 '11 at 19:47
@Bruno I did see that, but I couldn't quite get an example working. I think mainly because I don't understand enough about the box handling macros and how to use them. – Seamus Aug 9 '11 at 10:06

The \marginnote command, when stripped down to what it does in your context, is more or less

\newcommand*{\marginnote}[1]{\setbox0\vbox{#1}\wd0=0pt\box0}

and \paragraph is

\renewcommand*{\paragraph}[1]{%
\global\@noskipsectrue
\everypar{%
\if@noskipsec
\global\@noskipsecfalse
\else
\everypar{}%
\fi
}%
}

The problem comes from the \vbox of \marginnote (if you change it to \hbox, the problem disappears in your context). What causes the word Broken! to be typesetted over the text of the paragraph is just the change of width of the \vbox (in fact \marginnote also modifies its height and depth, which is why it is also moved up in your example).

Here's the full stripped down code showing the phenomenon (the margin numbers are not correctly placed as \marginnote would have to do a few more things for that):

\documentclass{article}

\usepackage{everyhook}

\newif\ifnotmarginhook
\notmarginhooktrue
\PushPreHook{par}{%
\ifnotmarginhook
\notmarginhookfalse
\marginnote{\small\ttfamily\the\inputlineno}%
\notmarginhooktrue
\fi
}

%\newcommand*{\marginnote}[1]{\setbox0\hbox{#1}\wd0=0pt\box0}% works
\newcommand*{\marginnote}[1]{\setbox0\vbox{#1}\wd0=0pt\box0}% doesn't work

\makeatletter
\renewcommand*{\paragraph}[1]{%
\global\@noskipsectrue
\everypar{%
\if@noskipsec
\global\@noskipsecfalse
\else
\everypar{}%
\fi
}%
}
\makeatother

\begin{document}

\section{This works}

Here is some text and it will go on and on
Here is some text and it will go on and on
Here is some text and it will go on and on

\subsection{This too}

Here is some text and it will go on and on
Here is some text and it will go on and on
Here is some text and it will go on and on

\paragraph{Broken!}

Here is some text and it will go on and on
Here is some text and it will go on and on
Here is some text and it will go on and on

\end{document}

Of course, here your solution is to use \PushPostHook as already mentioned.

-

(This doesn't answer the question per se, but does provide a workaround.)

Attaching the \marginpar command to the post-par hook instead (i.e. \PushPostHook) seems to magically fix the issue:

(The extra spaces seen at the beginning of the line are from spaces in the hook.)

-