\documentclass[a4paper,12pt]{article}

\usepackage[vmargin=1in]{geometry}
\usepackage{parskip}
\usepackage{verbatim}
\usepackage[ascii]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}

\makeatletter
\g@addto@macro\maketitle{%
  \thispagestyle{empty}%
}
\providecommand*{\cs}[1]{%
  \texttt{\textbackslash #1}%
}
\providecommand*{\eTeX}{%
  $\m@th\varepsilon$-\TeX
}
\providecommand*{\xpackage}[1]{%
  \textsf{#1}%
}
\newenvironment{code}{%
  \quote
  \verbatim
}{%
  \endverbatim
  \endquote
}
\makeatother

\title{%
  Safe redefinition of \cs{shipout} (I)
  using \eTeX's \cs{currentgrouplevel}%
}
\author{Heiko Oberdiek}
\date{27th April 2007}

\begin{document}
\maketitle

Goal: Redefine \cs{shipout} to do something with its box.

First we catch its box by \cs{setbox} and \cs{afterassignment}:
\begin{code}
\shipout := \afterassignment\@Test
            \setbox\@Box=
\end{code}
There are two different cases:
\begin{code}
(a) \shipout\box0      -> \setbox\@Box=\box0 \@Test
(b) \shipout\vbox{...} -> \setbox\@Box=\vbox{\@Test ...}
\end{code}
In case (b) we want to postpone \cs{@Test} after the \cs{vbox} group
by \cs{aftergroup}. But how can we differentiate between these cases?

\eTeX's \cs{currentgrouplevel} helps:
\begin{code}
\shipout := \edef\@Level{\the\currentgrouplevel}
            \afterassignment\@Test
            \setbox\@Box=
\@Test   := \ifnum\@Level<\currentgrouplevel
              \expandafter\aftergroup
            \fi
            \@Output
\end{code}
The original \cs{shipout} ignores void boxes.
\begin{code}
\@Output := \ifvoid\@Box
            \else
              % do something with box \@Box
            \fi
            \@OrigShipout\box\@Box
\end{code}
(For completeness:)
\begin{code}
\newbox\@Box
\let\@OrigShipout=\shipout
\end{code}
This is one of the methods implemented by package \xpackage{atbegshi}.
\end{document}
