\documentclass[pagesize=auto]{scrartcl}

\usepackage{fixltx2e}
\usepackage{etex}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage{microtype}
\usepackage{hyperref}

\newcommand*{\mail}[1]{\href{mailto:#1}{\texttt{#1}}}
\newcommand*{\pkg}[1]{\textsf{#1}}
\newcommand*{\cs}[1]{\texttt{\textbackslash#1}}
\makeatletter
\newcommand*{\cmd}[1]{\cs{\expandafter\@gobble\string#1}}
\makeatother

\addtokomafont{title}{\rmfamily}

\title{The \pkg{sphack} package\thanks{This manual corresponds to \pkg{sphack.sty}~v1.0, dated~22 May 1998.}}
\author{Oliver Pretzel\thanks{\mail{o.pretzel@ic.ac.uk}}}
\date{22 May 1998}


\begin{document}

\maketitle

\noindent
Standard \LaTeX\ uses the macros \cmd{\@bsphack}, \cmd{\@esphack}, and \cmd{\@Esphack}, for
inserts into the text that should be invisible. So, for instance a space
before and after a \cmd{\label} command should not result in two spaces in the
output.

\LaTeX\ deals with this as follows
%
\begin{itemize}
\item in maths mode do nothing,
\item in horizontal mode restore the space factor,
\item if the last thing on the list was a space
  add \cmd{\ignorespaces} (and (\cmd{\global})\cmd{\ignore\-true} at the end of an environment),
\item in vertical mode do nothing.
\end{itemize}

Doing nothing in maths mode is (nearly) harmless because maths mode does its
own spacing (and anyway hidden commands will usually appear only at the start
or end of maths).

Doing nothing in vertical mode is not harmless. Many invisible commands such
as \cmd{\index} may insert delayed write commands into \TeX's output (so that page
numbers are correctly calculated). These commands can cause vertical space to
accumulate, and may cause a page break; \cmd{\index} is a particular problem in
\LaTeX2.09 since it inserts a delayed write if an index is actually being built
(\cmd{\makeindex} in preamble) but does nothing otherwise. That can change the page
breaks in a document.

It is not possible to solve this problem completely in \LaTeX\ because \TeX\ does
not remove things from the main vertical list once they have been
contributed. So \LaTeXe\ makes \cmd{\index} insert something into the vertical
list whether the index is being written or not. That has the virtue of
consistancy, but is far from ideal. For instance, an \cmd{\index} immediately after
an \cmd{\item} can cause the page to break between the item label and content.

\pagebreak[2]

The code in the \pkg{sphack} package remedies this fault and other common anomalies so that commands
are nearly always invisible in vertical mode as well. It works as follows:
%
\begin{itemize}
\item Rename \LaTeX's dimension \cmd{\@savsk} to \cmd{\@savdim} set a new skip \cmd{\@savsk}
  (because we need a true skip and a dimension in vertical mode)

\item \cmd{\@bsphack} (at start of invisible command)
  \begin{itemize}
  \item in hmode (non-math)
    \begin{enumerate}
    \item store spacefactor in \cmd{\@savsf}
    \item store lastskip in \cmd{\@savsk} (used to test whether space already present)
    \end{enumerate}

  \item in vmode
    \begin{enumerate}
    \item store lastpenalty in \cmd{\@savsf}
    \item store lastskip in \cmd{\@savsk} (used for movement)
    \item store previous depth  in \cmd{\@savdim}
    \item skip back \cmd{\lastskip}
    \end{enumerate}
  \end{itemize}

\item \cmd{\@esphack} (at end of invisible command)
  \begin{itemize}
  \item in hmode (non-math)
    \begin{enumerate}
    \item set spacefactor = \cmd{\@savsf}
    \item if \cmd{\@savsk} > \cmd{\z@} \cmd{\ignorespaces}
    \end{enumerate}

  \item in vmode
    \begin{enumerate}
    \item if in a label, or just after section heading, or if \cmd{\@nobreak}\\
      insert infinite penalty, (to prevent a page break)\\
      else insert penalty \cmd{\@savsf}\\
      endif
    \item set previous depth = \cmd{\@savdim}
    \item skip \cmd{\@savsk}
    \end{enumerate}
  \end{itemize}
\end{itemize}
%
Just as in standard \LaTeX, \cmd{\@Esphack} is \cmd{\@esphack} + (\cmd{\global})\cmd{\@ignoretrue}.

It is not necessary to change any of the label or index macros to fit with
this code.

\end{document}
