summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/sphack/sphack.sty
blob: 3761a432cf5380832735c74b59f2ceb35d98b6cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
% SPHACK.STY
% Oliver Pretzel  (o.pretzel@ic.ac.uk)
% Created 22 May 1998, Version 1.0 22May 1998
% Modified space hacks for LateX (209 and 2e)
%   (to prevent \label, \index and similar commands
%    affecting spacing in vertical mode).
%
%
% DOCUMENTATION at end of file
%
% ALL RIGHTS RESERVED
%
% This file may be distributed freely.
% It may be modified for local use (an email copy of the 
% modified file would be appreciated).
% Modified versions may only be distributed if
% 1. The name is changed
% 2. A statement acknowledging the modification heads the file.
%
% DO NOT USE \neq in this file
\chardef\neq\the\catcode`\@
\makeatletter\@makeother\"
%

\typeout{`sphack.sty <1.0>}
%*************************

\ifx\@savdim\undefined\let\@savdim\@savsk\newskip\@savsk\fi
\def\@bsphack{\relax\ifmmode\else\@savsk\lastskip\@savsf\ifhmode\spacefactor
    \else\lastpenalty\@savdim\prevdepth\removelastskip\fi\fi}
\def\@esphack{\relax\ifmmode\else\ifvmode\penalty\if@nobreak\@M\else
    \if@inlabel\@M\else\if@noskipsec\@M\else\@savsf\fi\fi\fi
    \prevdepth\@savdim\vskip\@savsk\else
    \spacefactor\@savsf\ifdim\@savsk>\z@\ignorespaces\fi\fi\fi}
\ifx\LateXe\undefined
\def\@Esphack{\@esphack\ifhmode\ifdim\@savsk>\z@
    \global\@ignoretrue\ignorespaces\fi\fi}
\else
\def\@Esphack{\@esphack\ifhmode\ifdim\@savsk>\z@
    \@ignoretrue\ignorespaces\fi\fi}
\fi

% This line must be last line of code
\catcode`\@\neq\let\neq\ne\endinput

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

LaTeX deals with this as follows
 in maths mode do nothing,
 in horizontal mode restore the space factor,
 if the last thing on the list was a space
   add \ignorespaces (and (\global)\ignoretrue at the end of an environment),
 in vertical mode do nothing.

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 \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; \index is a particular problem in
LaTeX209 since it inserts a delayed write if an index is actually being built
(\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 LaTeX2e makes \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 \index immediately after
an \item can cause the page to break between the item label and content.

The code above remedies this fault and other common anomalies so that commands
are nearly always invisible in vertical mode as well. It works as follows:

Rename LaTeX's dimension \@savsk to \@savdim set a new skip \@savsk
  (because we need a true skip and a dimension in vertical mode)

\@bsphack (at start of invisible command)
in hmode (non-math)
   store spacefactor in \@savsf
   store lastskip in \@savsk (used to test whether space already present)
in vmode
   store lastpenalty in \@savsf
   store lastskip in \@savsk (used for movement)
   store previous depth  in \@savdim
   skip back \lastskip

\@esphack (at end of invisible command)
in hmode (non-math)
   set spacefactor = \@savsf
   if \@savsk > \z@ \ignorespaces
in vmode
   if in a label, or just after section heading, or if \@nobreak
      insert infinite penalty, (to prevent a page break)
   else insert penalty \@savsf
   endif
   set previous depth = \@savdim
   skip \@savsk

Just as in standard LateX, \@Esphack is \@esphack + (\global)\@ignoretrue.

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

End of sphack.sty
*******************