Insert correct checksums.
[mdwtools] / mdwtab.dtx
1 % \begin{meta-comment}
2 %
3 % $Id: mdwtab.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
4 %
5 % Another rewrite of the tabular environment, and maths alignments
6 %
7 % (c) 1996 Mark Wooding
8 %
9 %----- Revision history -----------------------------------------------------
10 %
11 % $Log: mdwtab.dtx,v $
12 % Revision 1.1 2002/02/03 20:49:03 mdw
13 % Checkin for new build system.
14 %
15 % Revision 1.8 1996/12/09 23:20:42 mdw
16 % (\tab@setstrut): Fixed so that it uses \dimen@ii for the strut depth,
17 % as advertised.
18 %
19 % Revision 1.7 1996/11/29 21:59:16 mdw
20 % Fixed a little formatting mistake in a syntax diagram, and switched over
21 % to the new syntax diagram commands on the grounds that they're slightly
22 % less messy. Maybe.
23 %
24 % Revision 1.6 1996/11/19 20:54:33 mdw
25 % Entered into RCS
26 %
27 %
28 % \end{meta-comment}
29 %
30 % \begin{meta-comment} <general public licence>
31 %%
32 %% mdwtab package -- another rewrite of the tabular environment, etc.
33 %% Copyright (c) 1996 Mark Wooding
34 %%
35 %% This program is free software; you can redistribute it and/or modify
36 %% it under the terms of the GNU General Public License as published by
37 %% the Free Software Foundation; either version 2 of the License, or
38 %% (at your option) any later version.
39 %%
40 %% This program is distributed in the hope that it will be useful,
41 %% but WITHOUT ANY WARRANTY; without even the implied warranty of
42 %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 %% GNU General Public License for more details.
44 %%
45 %% You should have received a copy of the GNU General Public License
46 %% along with this program; if not, write to the Free Software
47 %% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
48 %%
49 % \end{meta-comment}
50 %
51 % \begin{meta-comment} <Package preambles>
52 %<+mdwtab>\NeedsTeXFormat{LaTeX2e}
53 %<+mdwtab>\ProvidesPackage{mdwtab}
54 %<+mdwtab> [1998/04/28 1.9 Table typesetting with style]
55 %<+mathenv>\NeedsTeXFormat{LaTeX2e}
56 %<+mathenv>\ProvidesPackage{mathenv}
57 %<+mathenv> [1998/04/28 1.9 Various maths environments]
58 % \end{meta-comment}
59 %
60 % \CheckSum{2876}
61 %% \CharacterTable
62 %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
63 %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
64 %% Digits \0\1\2\3\4\5\6\7\8\9
65 %% Exclamation \! Double quote \" Hash (number) \#
66 %% Dollar \$ Percent \% Ampersand \&
67 %% Acute accent \' Left paren \( Right paren \)
68 %% Asterisk \* Plus \+ Comma \,
69 %% Minus \- Point \. Solidus \/
70 %% Colon \: Semicolon \; Less than \<
71 %% Equals \= Greater than \> Question mark \?
72 %% Commercial at \@ Left bracket \[ Backslash \\
73 %% Right bracket \] Circumflex \^ Underscore \_
74 %% Grave accent \` Left brace \{ Vertical bar \|
75 %% Right brace \} Tilde \~}
76 %%
77 %
78 % \begin{meta-comment}
79 %
80 %<*driver>
81 \input{mdwtools}
82 \describespackage{mdwtab}
83 \describespackage{mathenv}
84 \addcontents{lot}{\listoftables}
85 \mdwdoc
86 %</driver>
87 %
88 % \end{meta-comment}
89 %
90 %^^A-------------------------------------------------------------------------
91 % \renewcommand{\tabstyle}{\small}
92 %
93 % \section{User guide}
94 %
95 %
96 % The \package{mdwtab} package contains a reimplementation of the standard
97 % \LaTeX\ \env{tabular} and \env{array} environments. This is not just an
98 % upgraded version: it's a complete rewrite. It has several advantages over
99 % the official \package{array} package (not raw \LaTeX's, which is even less
100 % nice), and it's more-or-less compatible. Most of these are rather
101 % technical, I'll admit.
102 %
103 % \begin{itemize}
104 %
105 % \item The newcolumn system is properly and perfectly integrated into the
106 % system. There are now \emph{no} `primitive' column types -- all the
107 % standard types are created as user-defined columns.
108 %
109 % \item You can define entirely different table-like environments using the
110 % equipment here. It's still hard work, although less so than before.
111 % I'll do an example of this some time.
112 %
113 % \item Construction of the preamble is generally much tidier. I've used
114 % token registers rather than |\edef|, and it's all done very nicely.
115 %
116 % \item Fine spacing before and after rules (described by DEK as `a mark of
117 % quality') is now utterly trivial, since the preamble-generator will
118 % store the appropriate information.
119 %
120 % \item You can use \env{array} in LR and paragraph modes without having
121 % to surround it with `|$|' signs.
122 %
123 % \item Usually you don't want tables in the middle of paragraphs. For these
124 % cases, I've provided a simpler way to position the table
125 % horizontally.
126 %
127 % \item Footnotes work properly inside \env{tabular} environments (hoorah!).
128 % You can `catch' footnotes using the \env{minipage} environment if
129 % you like. (It uses an internal version of the \package{footnote}
130 % package to handle footnotes, which doesn't provide extra goodies like
131 % the \env{footnote} environment; you'll need to load the full package
132 % explicitly to get them.)
133 %
134 % \item Standard \LaTeX\ tabular environments have a problem with lining up
135 % ruled tables. The |\firsthline| command given in the \textit{\LaTeX\
136 % Companion} helps a bit, but it's not really good enough, and besides,
137 % it doesn't \emph{actually} line the text up right after all. The
138 % \package{mdwtab} package does the job properly to begin with, so you
139 % don't need to worry.
140 %
141 % \end{itemize}
142 %
143 % I've tested the following packages with \package{mdwtab}, and they all
144 % work. Some of the contortions required to make them work weren't pleasant,
145 % but you don't need to know about them. By a strange coincidence, all the
146 % packages were written by David Carlisle. Anyway, here's the list:
147 % \begin{itemize}
148 % \item The quite nice \package{dcolumn} package.
149 % \item The more useful \package{delarray} package.
150 % \item The rather spiffy \package{hhline} package.
151 % \item The truly wonderful \package{tabularx} package.
152 % \item The utterly magnificent \package{longtable} package.
153 % \end{itemize}
154 %
155 % Note that I've looked at \package{supertabular} as well: it won't work, so
156 % use \package{longtable} instead, 'cos it's much better.
157 %
158 %
159 % \subsection{The downside}
160 %
161 % There's no such thing as a free lunch. The \package{mdwtab} environment
162 % is not 100\% compatible with the \env{tabular} environment found in
163 % \LaTeXe\ or the \package{array} package.
164 %
165 % The differences between \package{mdwtab} and \LaTeXe's \env{tabular}
166 % environment are as follows:
167 %
168 % \begin{itemize} \synshorts \let\`=\lq
169 %
170 % \item The vertical spacing in \env{array} environments is different to
171 % that in \env{tabular} environments. This produces more attractive
172 % results in most mathematical uses of \env{array}s, in the author's
173 % opinion. The spacing can be modified by playing with length
174 % parameters.
175 %
176 % \item The presence of horizontal and vertical rules will alter the spacing
177 % of the table (so a pair of columns separated by a `|' is wider than
178 % a pair with no separation by "\\arrayrulewidth". This does mean that
179 % horizontal and vertical rules match up properly -- the usual \LaTeX\
180 % environment makes the horizontal rules stop just short of the edge
181 % of the table, making an ugly mess (check out the \textit{\LaTeX\
182 % book} if you don't believe me -- page~62 provides a good example).
183 % The \package{array} package handles rules in the same way as
184 % \package{mdwtab}.
185 %
186 % \setbox0=\hbox{\footnotesize`\\def\\xcs{\\tabskip=\\fill}'}
187 % \setbox2=\hbox{\footnotesize`...@{\\span\\xcs}...'}
188 % \item In common with the \package{array} package, there are some
189 % restrictions on the use of the "\\extracolsep" command in preambles:
190 % you may use at most one "\\extracolsep" command in each `@' or `!'
191 % expression. Also, you can't say
192 % \begin{listing}
193 %\newcommand{\xcs}{\extracolsep{\fill}}
194 % \end{listing}
195 % and then expect something like `...@{\\xcs}...' to actually work --
196 % the "\\extracolsep" mustn't be hidden inside any other
197 % commands. Because things like `@' expressions aren't expanded at
198 % the time, "\\extracolsep" has to be searched and processed
199 % \`by hand'.\footnote{^^A
200 % All \cs{extracolsep} does is modify the \cs{tabskip} glue, so
201 % if you were an evil \TeX\ hacker like me, you could just say
202 % \unhbox0\ and put \unhbox2\ in your preamble. That'd work nicely.
203 % It also works with the \package{array} package.}
204 %
205 % \item Control sequences (commands) in a table's preamble aren't expanded
206 % before the preamble is read. In fact, commands in the preamble are
207 % considered to be column types, and their names are entirely
208 % independent of normal \LaTeX\ commands. No column types of this
209 % nature have yet been defined\footnote{^^A
210 % There used to be an internal \cs{@magic} type used by
211 % \env{eqnarray}, but you're not supposed to know about that.
212 % Besides, it's not there any more.}
213 % but the possibility's always there. Use the "\\newcolumntype" or
214 % "\\coldef" commands to define new column types.
215 %
216 % \item The preamble parsing works in a completely different way. There is
217 % a certain amount of compatibility provided, although it's heavily
218 % geared towards keeping \package{longtable} happy and probably won't
219 % work with other packages.
220 %
221 % \item Obscure constructs which were allowed by the old preamble parser but
222 % violate the syntax shown in the next section (e.g., `|@{}|' to
223 % suppress the "\\doublerulesep" space between two vertical rules,
224 % described in \textit{The \LaTeX\ Companion} as \`a misuse of the
225 % `@{...}' qualifier') are now properly outlawed. You will be given
226 % an error message if you attempt to use such a construction.
227 %
228 % \item The `*' forms (which repeat column types) are now expanded at a
229 % different time. Previously, preambles like `c@*{4}{{:}@}{--}c'
230 % were considered valid (the example would expand to
231 % `c@{:}@{:}@{:}@{:}@{--}c'), because `*'s were expanded before the
232 % preamble was actually parsed. In the new system, `*' is treated
233 % just like any other preamble character (it just has a rather odd
234 % action), and preambles like this will result in an error (and
235 % probably a rather confusing one).
236 %
237 % \end{itemize}
238 %
239 % There are also several incompatibilities between \package{mdwtab} and
240 % \package{array}:
241 %
242 % \begin{itemize} \synshorts \let\`=\lq
243 %
244 % \item Because of the way "\\newcolumntype" works in the \package{array}
245 % package, a horrid construction like
246 % \begin{listing}
247 %\newcolumntype{x}{{:}}
248 %\begin{tabular}{|c!xc|}
249 % \end{listing}
250 % is considered to be valid, and is interpreted as `|c!{:}c|'. My
251 % reading of pages~54 and~55 of the \textit{\LaTeX\ book} tells me
252 % that this sort of thing is forbidden in normal \LaTeX\ commands.
253 % The \package{mdwtab} preamble parser now treats column type letters
254 % much more like commands with the result that the hacking above won't
255 % work any more. The construction above would actually be interpreted
256 % as `|c!{x}c|' (i.e., the `x' column type wouldn't be expanded to
257 % `{:}' because the parser noticed that it was the argument to the
258 % `!' modifier\footnote{^^A
259 % This is a direct result of the way \TeX\ treats undelimited
260 % arguments. See chapters~5 and~20 of \textit{The \TeX book} for
261 % more information about how grouping affects argument reading.}).
262 %
263 % \item Most of the points above, particularly those relating to the
264 % handling of the preamble, also apply to the \package{array} package.
265 % it's not such an advance over the \LaTeXe\ version as everyone said
266 % it was.
267 %
268 % \end{itemize}
269 %
270 %
271 % \subsection{Syntax}
272 %
273 % \DescribeEnv{tabular}
274 % \DescribeEnv{tabular*}
275 % \DescribeEnv{array}
276 % So that everyone knows where I stand, here's a complete syntax for my
277 % version of the \env{tabular} environment, and friends
278 %
279 % \begin{grammar}
280 %
281 % <tabular-env> ::= \[[
282 % "\\begin"
283 % \begin{stack}
284 % "{tabular}" \\ "{tabular*}" "{" <length> "}" \\
285 % "{array}" \\ "{smarray}"
286 % \end{stack}
287 % \[ "[" <position-arg> "]" \]
288 % "{" <preamble> "}" <text>
289 % "\\end"
290 % \( "{tabular}" \\ "{tabular*}" \\ "{array}" \\ "{smarray}" \)
291 % \]]
292 %
293 % <position-arg> ::= (see below)
294 %
295 % <preamble> ::= \[[
296 % <first-column>
297 % \[ \< <column> \> \]
298 % \]]
299 %
300 % <first-column> ::= \[[ \[ <rule> \] <column> \]]
301 %
302 % <column> ::= \[[
303 % \[ <spacing> \] \[ \< <user-pre-text> \> \] <column-type>
304 % \[ \< <user-post-text> \> \] \[ <spacing> \] \[ <rule> \]
305 % \]]
306 %
307 % <spacing> ::= \[[ "@" "{" <text> "}" \]]
308 %
309 % <user-pre-text> ::= \[[ ">" "{" <text> "}" \]]
310 %
311 % <column-type> ::= \[[
312 % \begin{stack}
313 % \[ "T" \\ "M" \] \( "l" \\ "c" \\ "r" \) \\
314 % \( "p" \\ "m" \\ "b" \) "{" <length> "}" \\
315 % "#" "{" <raw-pre-text> "}" "{" <raw-post-text> "}"
316 % \end{stack}
317 % \]]
318 %
319 % <user-post-text> ::= \[[ "<" "{" <text> "}" \]]
320 %
321 % <rule> ::= \[[ \( "|" \\ "!" "{" <text> "}" \) \]]
322 %
323 % \end{grammar}
324 %
325 % If you examine the above very carefully, you'll notice a slight deviation
326 % from the original -- an |@|-expression \emph{following} a rule is
327 % considered to be part of the \emph{next} column, not the current one. This
328 % is, I think, an almost insignificant change, and essential for some of the
329 % new features. You'll also notice the new |#| column type form, which
330 % allows you to define new real column types instead of just modifying
331 % existing ones. It's not intended for direct use in preambles -- it's
332 % there mainly for the benefit of people who know what they're doing and
333 % insist on using |\newcolumntype| anyway.
334 %%
335 % The actual column types are shown in table~\ref{tbl:columns}.
336 %
337 % \begin{table}
338 % \begin{tabular}[C]{| >{\synshorts} c | m{3in} |} \hlx{hv[1]}
339 %
340 % \multicolumn{2}{|c|}{\bf Column types} \\ \hlx{v[1]hv}
341 % \bf Name & \bf Meaning \\ \hlx{vhv.}
342 % "l" & Left aligned text (\env{tabular}) or
343 % equation (\env{array}). \\ \hlx{.}
344 % "c" & Centred text (\env{tabular}) or
345 % equation (\env{array}). \\ \hlx{.}
346 % "r" & Right aligned text (\env{tabular}) or
347 % equation (\env{array}). \\ \hlx{vhv.}
348 % "Ml", "Mc" and "Mr" & Left, centre and right aligned
349 % equations.* \\ \hlx{.}
350 % "Tl", "Tc" and "Tr" & Left, centre and right aligned
351 % text.* \\ \hlx{vhv.}
352 % "p{"<width>"}" & Top aligned paragraph with the given
353 % width. \\ \hlx{.}
354 % "m{"<width>"}" & Vertically centred paragraph with
355 % the given width. \\ \hlx{.}
356 % "b{"<width>"}" & Bottom aligned paragraph with the
357 % given width. \\ \hlx{vhv.}
358 % "#{"<pre>"}{"<post>"}" & User defined column type:
359 % \<pre> is inserted before the
360 % cell entry, \<post> is inserted
361 % afterwards.* \\ \hlx{vhhv[1]}
362 %
363 % \multicolumn{2}{|c|}{\bf Other modifier characters} \\ \hlx{v[1]hv}
364 % \bf Name & \bf Meaning \\ \hlx{vhv.}
365 % "|" & Inserts a vertical rule between
366 % columns. \\ \hlx{.}
367 % "$*["<width>"]" & Inserts a vertical rule of given
368 % width between columns; "*" selects
369 % "\arraythickrulewidth". \\ \hlx{.}
370 % "!{"<text>"}" & Inserts \<text> between columns,
371 % treating it as a vertical rule. \\ \hlx{vhv.}
372 % "@{"<text>"}" & Inserts \<text> instead of the
373 % usual intercolumn space. \\ \hlx{vhv.}
374 % ">{"<text>"}" & Inserts \<text> just before the
375 % actual column entry. \\ \hlx{.}
376 % "<{"<text>"}" & Inserts \<text> just after the
377 % actual column entry. \\ \hlx{vhv.}
378 % "*{"<count>"}{"<chars>"}" & Inserts \<count>
379 % copies of the \<chars> into the
380 % preamble. \\ \hlx{vhs}
381 %
382 % \multicolumn{2}{@{}l}{* This column type is a new feature}
383 % \end{tabular}
384 %
385 % \caption{\package{array} and \package{tabular} column types and modifiers}
386 % \label{tbl:columns}
387 % \end{table}
388 %
389 % Now that's sorted everything out, there shouldn't be any arguments at all
390 % about what a column means.
391 %
392 % The lowercase \<position-arg>s \lit{t}, \lit{c} and \lit{b} do exactly
393 % what they did before: control the vertical positioning of the table. The
394 % uppercase ones control the \emph{horizontal} positioning -- this is how you
395 % create \emph{unboxed} tables. You can only create unboxed tables in
396 % paragraph mode.
397 %
398 % Note that unboxed tables still can't be broken across pages. Use
399 % the \package{longtable} package for this, because it already does an
400 % excellent job.
401 %
402 % \DescribeMacro{\tabpause}
403 % One thing you can to with unboxed tables, however, is to `interrupt' them,
404 % do some normal typesetting, and then continue. This is achieved by the
405 % |\tabpause| command: its argument is written out in paragraph mode, and
406 % the table is continued after the argument finishes.
407 % Note that it isn't a real argument as far as commands like |\verb| are
408 % concerned -- they'll work inside |\tabpause| without any problems.
409 %
410 % \DescribeMacro{\vline}
411 % \DescribeMacro{\vline*}
412 % The |\vline| command draws a vertical rule the height of the current table
413 % cell (unless the current cell is being typeset in paragraph mode -- it
414 % only works in the simple LR-mode table cells, or in \lit{@} or \lit{!}
415 % modifiers). It's now been given an optional argument which gives the
416 % width of the rule to draw. The |*|-version uses the |\arraythickrulewidth|
417 % thickness rather than the default.
418 %
419 % { \let\tabstyle=\relax
420 % \begin{demo}{An example of \cmd\vline}
421 %\large
422 %\begin{tabular}
423 % {| c !{\vline[5pt]} c | c |}
424 % \hlx{hv}
425 % \bf A & \it B & \sf C \\
426 % \hlx[2pt]{vhv}
427 % \bf D & \it E & \sf F \\
428 % \hlx{vh}
429 %\end{tabular}
430 % \end{demo}
431 % }
432 %
433 % \DescribeMacro{smarray}
434 % You've probably noticed that there's an unfamiliar environment mentioned
435 % in the syntax shown above. The \env{smarray} environment produces a
436 % `small' array, with script size cells rather than the normal full text
437 % size cells. I've seen examples of this sort of construction\footnote{^^A
438 % There's a nasty use of \env{smallmatrix} in the |testmath.tex| file which
439 % comes with the \package{amslatex} distribution. It's actually there to
440 % simulate a `smallcases' environment, which the \package{mathenv} package
441 % includes, based around \env{smarray}.}
442 % being implemented by totally unsuitable commands. Someone may find it
443 % handy.
444 %
445 %
446 % \subsection{An updated \cs{cline} command}
447 %
448 % \DescribeMacro{\cline}
449 % \DescribeMacro{\hline}
450 % The standard \LaTeX\ |\cline| command has been updated. As well as just
451 % passing a range of columns to draw lines through, you can now pass a comma
452 % separated list of column numbers and ranges:
453 %
454 % \begin{grammar}
455 % <cline-cmd> ::= \[[
456 % "\\cline"
457 % \[ "*" \\ \tok{"["<width>"]"} \]
458 % "{" \< <number> \[ "-" <number> \] \\ "," \> "}"
459 % \]]
460 % \end{grammar}
461 %
462 % The thickness of the rules may be modified. The default is given by the
463 % |\arrayrulewidth| length parameter. The |\cline*| command uses the
464 % |\arraythickrulewidth| parameter instead. If neither of these does what
465 % you want, then you can give a length yourself as an optional argument.
466 % This feature is also available in the |\hline| and |\hlx| commands, and
467 % (for vertical rules) in the |$| column type.\footnote{I couldn't use the
468 % \texttt{\char`\|} type, because that would break old documents which
469 % expect \texttt{\char`\| *\char`\{...\char`\}} to work properly.}
470 %
471 % The positioning of the horizontal lines has also been improved a bit, so
472 % that they meet up with the vertical lines properly. Displays like the one
473 % in the example below don't look good unless this has been done properly.
474 %
475 % {\let\tabstyle\relax
476 % \begin{demo}[w]{A \cs{cline} example}
477 %\newcommand{\mc}{\multicolumn{1}}
478 %\begin{tabular}[C]{|c|c|c|c|} \cline{2,4}
479 % \mc{c|}{one} & two & three & four \\ \hline
480 % five & six & seven & \mc{c}{eight} \\ \cline{1,3}
481 %\end{tabular}
482 % \end{demo}
483 % }
484 %
485 % \subsection{Spacing control}
486 %
487 % One of the most irritating things about \LaTeX's tables is that there isn't
488 % enough space around horizontal rules. Donald Knuth, in \textit{The
489 % \TeX book}, describes addition of some extra vertical space here as `a mark
490 % of quality', and since \TeX\ was designed to produce `beautiful documents'
491 % it seems a shame that \LaTeX\ doesn't allow this to be done nicely. Well,
492 % it does now.
493 %
494 % \DescribeMacro{\vgap}
495 % The extra vertical space is added using a command |\vgap|, with the
496 % following syntax:
497 %
498 % \begin{grammar}
499 %
500 % <vgap-cmd> ::= \[[
501 % "\\vgap" \[ "[" <which-cols> "]" \] "{" <length> "}"
502 % \]]
503 %
504 % <which-cols> ::= \[[ \< <number> \[ "-" <number> \] \\ "," \> \]]
505 %
506 % \end{grammar}
507 %
508 % This command must appear either immediately after the beginning of the
509 % table or immediately after the |\\| which ends a row. (Actually, there are
510 % other commands which also have this requirement -- you can specify a
511 % collection of them wherever you're allowed to give any one.) It adds some
512 % vertical space (the amount is given by the \<length>) to the table,
513 % making sure that the vertical rules of the table are extended correctly.
514 %
515 % The |\vgap| command relies on information stored while your table preamble
516 % is being examined. However, it's possible that you might not want some
517 % of the rules drawn (e.g., if you've used |\multicolumn|). The optional
518 % \<which-cols> argument allows you to specify which rules are \emph{not}
519 % to be drawn. You can specify either single column numbers or ranges. The
520 % rule at the very left hand side is given the number~0; the rules at the
521 % end of column~$n$ are numbered~$n$. It's easy really.
522 %
523 % \DescribeMacro{\hlx}
524 % Using |\vgap| is all very well, but it's a bit cumbersome, and takes up a
525 % lot of typing, especially when combined with |\hline| commands. The |\hlx|
526 % command tries to tidy things.
527 %
528 % The syntax is simple:
529 % \begin{grammar}
530 %
531 % <hlx-cmd> ::= \[[
532 % "\\hlx"
533 % \[ "*" \\ \tok{"["<width>"]"} \]
534 % "{"
535 % \begin{rep}
536 % \begin{stack}
537 % "h" \\
538 % \tok{"v["<which-cols>"]["<length>"]"} \\
539 % \tok{"s["<length>"]"} \\
540 % \tok{"c{"<which-cols>"}"} \\
541 % "b" \\
542 % \tok{"/["<number>"]"} \\
543 % "."
544 % \end{stack}
545 % \end{rep}
546 % "}"
547 % \]]
548 %
549 % \end{grammar}
550 % The |*| or optional \<width> specify the width of horizontal rules to be
551 % drawn, as for |\hline| and |\cline|. (Note that you can't pass a |*| or
552 % optional argument to the |h| or |c| subcommands.)
553 %
554 % The argument works a bit like a table preamble, really. Each letter is a
555 % command. The following are supported:
556 %
557 % \begin{description}
558 %
559 % \item [\lit*{h}] Works just like |\hline|. If you put two adjacent to each
560 % other, a gap will be put between them.
561 %
562 % \item [\lit*{v[}\<which-cols>\lit*{][}\<length>\lit*{]}] Works
563 % like \syntax{"\\vgap["<which-cols>"]{"<length>"}"}. If the
564 % \<length> is omitted, the value of |\doublerulesep| is used.
565 % This usually looks right.
566 %
567 % \item [\lit*{s[}\<length>\lit*{]}] Leaves a vertical gap with the
568 % given size. If you omit the \<length> then |\doublerulesep| is
569 % used. This is usually right.
570 %
571 % \item [\lit*{c\char`\{}\<which-cols>\lit*{\char`\}}] Works just like
572 % |\cline|.
573 %
574 % \item [\lit*{b}] Inserts a backspace the width of a rule. This is useful
575 % when doing \package{longtable}s.
576 %
577 % \item [\lit*{/[}\<number>\lit*{]}] Allows a page break in a table. Don't
578 % use this except in a \env{longtable} environment. The \<number>
579 % works exactly the same as it does in the |\pagebreak| command,
580 % except that the default is 0, which just permits a break without
581 % forcing it.
582 %
583 % \item [\lit*{.}] (That's a dot) Starts the next row of the table. No
584 % more characters may follow the dot, and no |\hline|, |\hlx|, |\vgap|
585 % or |\multicolumn| commands may be used after it. You don't have to
586 % include it, and most of the time it's totally useless. It can be
587 % handy for some macros, though. I used it in (and in fact added it
588 % especially for) the table of column types.
589 %
590 % \end{description}
591 %
592 % An example of the use of |\hlx| is given, so you can see what's going on.
593 %
594 % \begin{figure}
595 % \let\tabstyle\relax
596 % \begin{demo}[w]{Beautiful table example}
597 %\newcommand{\zerowidth}[1]{\hbox to 0pt{\hss#1\hss}}
598 %\setlength{\tabcolsep}{1.5em}
599 %\begin{tabular}[C]{| r | c | r |} \hlx{hv[1,2]}
600 % \multicolumn{3}{|c|}{\bf AT\&T Common Stock} \\ \hlx{v[1,2]hv}
601 % \multicolumn{1}{|c|}{\zerowidth{\bf Year}} &
602 % \multicolumn{1}{c|}{\zerowidth{\bf Price}} &
603 % \multicolumn{1}{c|}{\zerowidth{\bf Dividend}} \\ \hlx{vhv}
604 % 1971 & 41--54 & \$2.60 \\
605 % 2 & 41--54 & 2.70 \\
606 % 3 & 46--55 & 2.87 \\
607 % 4 & 40--53 & 3.24 \\
608 % 5 & 45--52 & 3.40 \\
609 % 6 & 51--59 & .95\rlap{*} \\ \hlx{vhs}
610 % \multicolumn{3}{@{}l}{* (first quarter only)}
611 %\end{tabular}
612 % \end{demo}
613 % \end{figure}
614 %
615 %
616 % \subsection{Creating beautiful long tables}
617 %
618 % You can use the |\vgap| and |\hlx| commands with David Carlisle's
619 % stunning \package{longtable} package. However, there are some things you
620 % should be away of to ensure that your tables always come out looking
621 % lovely.
622 %
623 % The \package{longtable} package will break a table at an |\hline| command,
624 % leaving a rule at the bottom of the page and another at the top of the
625 % next page. This means that a constructions like |\hlx{vhv}| will be
626 % broken into something like |\hlx{vh}| at the bottom of the page and
627 % |\hlx{hv}| at the top of the next. You need to design the table headers
628 % and footers with this in mind.
629 %
630 % However, there appears to be a slight problem:\footnote
631 % {You might very well call it a bug. I couldn't possibly comment.}
632 % if the footer starts with an |\hline|, and a page is broken at an |\hline|,
633 % then you get an extra thick rule at the bottom of the page. This is a bit
634 % of a problem, because if the rule isn't there in the footer and you get
635 % a break between two rows \emph{without} a rule between them, then the page
636 % looks very odd.
637 %
638 % If you want to do ruled longtables, I'd recommend that you proceed as
639 % follows:
640 % \begin{itemize}
641 % \item End header sections with an |\hlx{vh}|.
642 % \item Begin footer sections with an |\hlx{bh}|.
643 % \item Begin the main table with |\hlx{v}|.
644 % \item Insert |\hlx{vhv}| commands in the main table body as usual.
645 % \end{itemize}
646 % If \package{longtable} gets modified appropriately, the use of the \lit{b}
647 % command won't be necessary.
648 %
649 % Here's an example of the sort of thing you'd type.
650 %
651 % \begin{listinglist} \listingsize
652 % \verb"\begin{longtable}[c]{|c|l|} \hlx{hv}" \\
653 % \verb"\bf Heading & \bf Also heading \\ \hlx{vh}" \\
654 % \verb"\endhead" \\
655 % \verb"\hlx{bh}" \\
656 % \verb"\endfoot" \\
657 % \verb"\hlx{v}" \\
658 % \verb"First main & table line \\ \hlx{vhv}" \\
659 % \verb"Lots of text & like this \\ \hlx{vhv}" \\
660 % \null\quad\vdots \\
661 % \verb"Lots of text & like this \\ \hlx{vhv}" \\
662 % \verb"Last main & table line \\ \hlx{vh}" \\
663 % \verb"\end{longtable}"
664 % \end{listinglist}
665 %
666 %
667 % \subsection{Rules and vertical positioning}
668 %
669 % In the \LaTeXe\ and \package{array.sty} versions of \env{tabular}, you run
670 % into problems if you try to use ruled tables together with the \lit{[t]} or
671 % \lit{[b]} position specifiers -- the top or bottom rule ends up being
672 % nicely lined up with the text baseline, giving you an effect which is
673 % nothing like the one you expected. The \textit{\LaTeX\ Companion} gives
674 % two commands |\firsthline| and |\lasthline| which are supposed to help with
675 % this problem. (These commands have since migrated into the \package{array}
676 % package.) Unfortunately, |\firsthline| doesn't do its job properly --
677 % it gets the text position wrong by exactly the width of the table rules.
678 %
679 % The \package{mdwtab} package makes all of this automatic. It gets the
680 % baseline positions exactly right, whether or not you use rules. Earlier
681 % versions of this package required that you play with a length parameter
682 % called |\rulefudge|; this is no longer necessary (or even possible -- the
683 % length parameter no longer exists). The package now correctly compensates
684 % for all sorts of rules and |\vgap|s at the top and bottom of a table and
685 % it gets the positioning right all by itself. You've never had it so good.
686 %
687 %
688 % \subsection{User serviceable parts}
689 %
690 % There are a lot of parameters which you can modify in order to make arrays
691 % and tables look nicer. They are all listed in table~\ref{tbl:config}.
692 %
693 % \begin{table}
694 % \begin{tabular}[C]{| l | m{3in} |} \hlx{hv}
695 % \bf Parameter & \bf Meaning \\ \hlx{vhv}
696 % |\tabstyle| & A command executed at the beginning of
697 % a \env{tabular} or \env{tabular$*$}
698 % environment. By default does nothing.
699 % Change using |\renewcommand|. \\ \hlx{vhv}
700 % |\extrarowheight| & A length added to the height of every
701 % row, used to stop table rules
702 % overprinting ascenders. Default 0\,pt.
703 % Usage is deprecated now: use |\hlx|
704 % instead. \\ \hlx{vhv}
705 % |\tabextrasep| & Extra space added between rows in a
706 % \env{tabular} or \env{tabular$*$}
707 % environment (added \emph{before} any
708 % following |\hline|). Default 0\,pt. \\
709 % |\arrayextrasep| & Analogous to |\tabextrasep|, but for
710 % \env{array} environments. Default
711 % 1\,jot (3\,pt). \\
712 % |\smarrayextrasep| & Analogous to |\tabextrasep|, but for
713 % \env{smarray} environments. Default
714 % 1\,pt. \\ \hlx{vhv}
715 % |\tabcolsep| & Space added by default on each side of
716 % a table cell (unless suppressed by an
717 % \lit{@}-expression) in \env{tabular}
718 % environments. Default is defined by
719 % your document class. \\
720 % |\arraycolsep| & Analogous to |\tabcolsep|, but for
721 % \env{array} environments. Default is
722 % defined by your document class. \\
723 % |\smarraycolsep| & Analogous to |\tabcolsep|, but for
724 % \env{smarray} environments. Default
725 % is 3\,pt. \\ \hlx{vhv}
726 % |\arrayrulewidth| & The width of horizontal and vertical
727 % rules in tables. \\
728 % |\arraythickrulewidth|& The width of starred rules in tables. \\
729 % |\doublerulesep| & Space added between two adjacent
730 % vertical or horizontal rules. Also
731 % used by |\hlx{v}|. \\ \hlx{vhv}
732 % |\arraystretch| & Command containing a factor to
733 % multiply the default row height.
734 % Default is defined by your document
735 % class (usually 1). \\ \hlx{vh}
736 % \end{tabular}
737 %
738 % \caption{Parameters for configuring table environments}
739 % \label{tbl:config}
740 %
741 % \end{table}
742 %
743 %
744 % \subsection{Defining column types}
745 %
746 % \DescribeMacro{\newcolumntype}
747 % The easy way to define new column types is using |\newcolumntype|. It
748 % works in more or less the same way as |\newcommand|:
749 %
750 % \begin{grammar}
751 %
752 % <new-col-type-cmd> ::= \[[
753 % "\\newcolumntype"
754 % "{" <column-name> "}"
755 % \[ "[" <num-args> "]" \]
756 % \[ "[" <default-arg> "]" \]
757 % "{" <first-column> \[ \< <column> \> \] "}"
758 % \]]
759 %
760 % \end{grammar}
761 %
762 % (The \env{array.sty} implementation doesn't accept the \<default-arg>
763 % argument. I've no idea why not, 'cos it was very easy to implement.)
764 %
765 % \DescribeMacro{\colset}
766 % This implementation allows you to define lots of different sets of columns.
767 % You can change the current set using the |\colset| declaration:
768 % \begin{grammar}
769 % <colset-cmd> ::= \[[ "\\colset" "{" <set-name> "}" \]]
770 % \end{grammar}
771 % This leaves a problem, though: at any particular moment, the current
772 % column set could be anything, since other macros and packages can change
773 % it.
774 %
775 % \DescribeMacro{\colpush}
776 % \DescribeMacro{\colpop}
777 % What actually happens is that a stack of column sets is maintained. The
778 % |\colset| command just replaces the item at the top of the stack. The
779 % command |\colpush| pushes its argument onto the top of the stack, making
780 % it the new current set. The corresponding |\colpop| macro (which doesn't
781 % take any arguments) removes the top item from the stack, reinstating the
782 % previous current column set.
783 %
784 % \begin{grammar}
785 % <colpush-cmd> ::= \[[ "\\colpush" "{" <set-name> "}" \]]
786 % <colpop-cmd> ::= \[[ "\\colpop" \]]
787 % \end{grammar}
788 %
789 % The macros which manipulate the column set stack work \emph{locally}.
790 % The contents of the stack are saved when you open a new group.
791 %
792 % To make sure everyone behaves themselves properly, these are the rules for
793 % using the column set stack:
794 %
795 % \begin{itemize}
796 %
797 % \item Packages defining column types must ensure that they preserve the
798 % current column set. Either they must push their own column type
799 % and pop it off when they're finished defining columns, or they must
800 % avoid changing the stack at all, and use the optional arguments to
801 % |\coldef| and |\collet|.
802 %
803 % \item Packages must not assume that any particular column set is current
804 % unless they have made sure of it themselves.
805 %
806 % \item Packages must ensure that they pop exactly as much as they push.
807 % There isn't much policing of this (perhaps there should be more),
808 % so authors are encouraged to behave responsibly.
809 %
810 % \item Packages must change the current column set (using |\colset|) when
811 % they start up their table environment. This will be restored when
812 % the environment closes.
813 %
814 % \end{itemize}
815 %
816 % \DescribeMacro{\coldef}
817 % |\newcolumntype| is probably enough for most purposes. However, Real
818 % \TeX nicians, and people writing new table-generating environments, require
819 % something lower-level.
820 %
821 % \begin{grammar}
822 % <coldef-cmd> ::= \[[
823 % "\\coldef"
824 % \[ "[" <set-name> "]" \]
825 % <col-name> <arg-template> "{" <replacement-text> "}"
826 % \]]
827 % \end{grammar}
828 %
829 % Note that this defines a column type in the current colset. It works
830 % almost exactly the same way as \TeX's primitive |\def|. There is a
831 % potential gotcha here: a |\tab@mkpream| token is inserted at the end of
832 % your replacement text. If you need to read an optional argument or
833 % something, you'll need to gobble this token before you carry on. The
834 % |\@firstoftwo| macro could be handy here:
835 % \begin{listing}
836 %\coldef x{\@firstoftwo{\@ifnextchar[\@xcolumn@i\@xcolumn@ii}}}
837 % \end{listing}
838 % This isn't a terribly pretty state of affairs, and I ought to do something
839 % about it. I've not seen any use for an optional argument yet, though.
840 % Note that if you do gobble the |\tab@mkpream|, it's your responsibility to
841 % insert another one at the very end of your macro's expansion (so that
842 % further preamble characters can be read).
843 %
844 % The replacement text is inserted directly. It's normal to insert preamble
845 % elements here. There are several to choose from:
846 %
847 % \begin{description}
848 %
849 % \item [Column items] provide the main `meat' of a column. You insert a
850 % column element by saying
851 % \syntax{"\\tabcoltype{"<pre-text>"}{"<post-text>"}"}.
852 % The user's text gets inserted between these two. (So do user pre-
853 % and post-texts. Bear this in mind.)
854 %
855 % \item [User pre-text items] work like the \lit{>} preamble command. You
856 % use the \syntax{"\\tabuserpretype{"<text>"}"} command to insert it.
857 % User pre-texts are written in \emph{reverse} order between the
858 % pre-text of the column item and the text from the table cell.
859 %
860 % \item [User post-text items] work like the \lit{<} preamble command. You
861 % use the \syntax{"\\tabuserposttype{"<text>"}"} command to insert it.
862 % Like user pre-texts, user post-texts are written in reverse order,
863 % between the table cell text and the column item post-text.
864 %
865 % \item [Space items] work like the \lit{@} preamble command. They're
866 % inserted with the \syntax{"\\tabspctype{"<text>"}"} command.
867 %
868 % \item [Rule items] work like the `\verb"|"' and \lit{!} commands. You
869 % insert them with the \syntax{"\\tabruletype{"<text>"}"} command.
870 % Note that the text is inserted by |\vgap| too, so it should contain
871 % things which adjust their vertical size nicely. If you really need
872 % to, you can test |\iftab@vgap| to see if you're in a |\vgap|.
873 %
874 % \end{description}
875 %
876 % \DescribeMacro{\collet}
877 % As well as defining columns, you can copy definitions (rather like |\let|
878 % allows you to copy macros). The syntax is like this:
879 %
880 % \begin{grammar}
881 %
882 % <collet-cmd> ::= \[[
883 % \[ "[" <set-name> "]" \] <col-name> \[ "=" \] \[ "[" <set-name> "]" \]
884 % <col-name>
885 % \]]
886 %
887 % \end{grammar}
888 %
889 % (In other words, you can copy definitions from other column sets.)
890 %
891 %
892 % \subsection{Defining new table-generating environments}
893 %
894 % Quite a few routines are provided specifically to help you to define new
895 % environments which do alignment in a nice way.
896 %
897 % \subsubsection{Reading preambles}
898 %
899 % The main tricky bit in doing table-like environments is parsing preambles.
900 % No longer.
901 %
902 % \DescribeMacro{\tab@readpreamble}
903 % \DescribeMacro{\tab@doreadpream}
904 % The main parser routine is called |\tab@doreadpream|. Given a user
905 % preamble string as an argument, it will build an |\halign| preamble to
906 % return to you. However, the preamble produced won't be complete. This is
907 % because you can actually make multiple calls to |\tab@doreadpream| with
908 % bits of user preambles. The |\newcolumntype| system uses this mechanism,
909 % as does the \lit{*} (repeating) modifier. When there really is no more
910 % preamble to read, you need to \emph{commit} the heldover tokens to the
911 % output. The |\tab@readpreamble| routine will do this for you -- given a
912 % user preamble, it builds a complete output from it.
913 %
914 % A token register |\tab@preamble| is used to store the generated preamble.
915 % Before starting, you must initialise this token list to whatever you want.
916 % There's another token register, |\tab@shortline|, which is used to store
917 % tokens used by |\vgap|. For each column in the table, the list contains
918 % an |\omit| (to override the standard preamble) and an |\hfil| space taking
919 % up most of the column. Finally, for each rule item in the user preamble,
920 % the shortline list contains an entry of the form:
921 % \begin{quote} \synshorts
922 % "\\tab@ckr{"<column-number>"}{"<rule-text>"}"
923 % \end{quote}
924 % This is used to decide whether to print the rule or an empty thing of the
925 % same width. You probably ought to know that the very first column does
926 % \emph{not} have a leading |\omit| -- this is supplied by |\vgap| so that
927 % it can then look for optional arguments.
928 %
929 % \DescribeMacro{\tab@initread}
930 % As well as initialising |\tab@preamble| and emptying |\tab@shortline|,
931 % there are several other operations required to initialise a preamble read.
932 % These are all performed by the |\tab@initread| macro, although you may want
933 % to change some of the values for your specific application. For reference,
934 % the actions performed are:
935 % \begin{itemize}
936 % \item initialising the parser state by setting $|\tab@state| =
937 % |\tab@startstate|$;
938 % \item clearing the token lists |\tab@preamble| and |\tab@shortlist|;
939 % \item initialising the macros |\tab@tabtext|, |\tab@midtext|, and
940 % |\tab@multicol| to their default values of `|&|',
941 % `|\ignorespaces#\unskip|' and the empty token list respectively.^^A
942 % \footnote{^^A
943 % These are macros rather than token lists to avoid hogging all
944 % the token list registers. Actually, the package only allocates
945 % two, although it does use almost all of the temporary registers as
946 % well. Also, there's a lie: \cs{unskip} is too hamfisted to remove
947 % trailing spaces properly; I really use a macro called
948 % \cs{@maybe@unskip}}
949 % \item clearing the internal token list registers |\tab@pretext|,
950 % |tab@userpretext| and |\tab@posttext|;
951 % \item clearing the column counter |\tab@columns| to zero;
952 % \item clearing the action performed when a new column is started (by making
953 % the |\tab@looped| macro equal to |\relax|; this is used to make
954 % |\multicolumn| macro raise an error if you try to do more than one
955 % column); and
956 % \item setting up some other switches used by the parser (|\iftab@rule|,
957 % |\iftab@initrule| and |\iftab@firstcol|, all of which are set to be
958 % |true|).
959 % \end{itemize}
960 %
961 % The macro |\tab@multicol| is used by the |\multicolumn| command to insert
962 % any necessary items (e.g., struts) before the actual column text. If you
963 % set this to something non-empty, you should probably consider adding a
964 % call to the macro to the beginning of |\tab@preamble|.
965 %
966 % When parsing is finally done, the count register |\tab@columns| contains
967 % the number of columns in the alignment. Don't corrupt this value, because
968 % it's used for handling |\hline| commands.
969 %
970 % \subsubsection{Starting new lines}
971 %
972 % The other messy bit required by table environments is the newline command
973 % |\\|. There are nasty complications involved with starting new lines, some
974 % of which can be handled by this package, and some on which I can only give
975 % advice.
976 %
977 % \DescribeMacro{\tab@cr}
978 % The optional arguments and star-forms etc. can be read fairly painlessly
979 % using the |\tab@cr| command:
980 %
981 % \begin{grammar}
982 % <tabcr-cmd> ::= \[[
983 % "\\tab@cr" <command> "{" <non-star-text> "}" "{" <star-text> "}"
984 % \]]
985 % \end{grammar}
986 %
987 % This will call your \<command> with two arguments. The first is the
988 % contents of the optional argument, or `|\z@|' if there wasn't one. The
989 % second is either \<star-text> or \<non-star-text> depending on
990 % whether the user wrote the $*$-form or not.
991 %
992 % Somewhere in your \<command>, you'll have to use the |\cr| primitive to
993 % end the table row. After you've done this, you \emph{must} ensure that you
994 % don't do anything that gets past \TeX's mouth without protecting it --
995 % otherwise |\hline| and co.\ won't work. I usually wrap things up in a
996 % |\noalign| to protect them, although there are other methods. Maybe.
997 %
998 % You might like to have a look at the \env{eqnarray} implementation provided
999 % to see how all this gets put into practice.
1000 %
1001 %
1002 % \subsection{The \env{mathenv} package alignment environments}
1003 %
1004 % The \env{mathenv} package provides several environments for aligning
1005 % equations in various ways. They're mainly provided as a demonstration of
1006 % the table handling macros in \package{mdwtab}, so don't expect great
1007 % things. If you want truly beautiful mathematics, use
1008 % \package{amsmath}.\footnote{^^A
1009 % Particularly since nice commands like \cmd\over\ are being reactivated
1010 % in a later release of \package{amsmath}.}
1011 % However, the various environments do nest in an approximately useful way.
1012 % I also think that the \env{matrix} and \env{script} environments provided
1013 % here give better results than their \package{amsmath} equivalents, and
1014 % they are certainly more versatile.
1015 %
1016 % \subsubsection{The new \env{eqnarray} environment}
1017 %
1018 % \DescribeEnv{eqnarray}
1019 % \DescribeEnv{eqnarray*}
1020 % As an example of the new column defining features, and because the original
1021 % isn't terribly good, I've included a rewritten version of the
1022 % \env{eqnarray} environment. The new implementation closes the gap between
1023 % \env{eqnarray} and \AmSTeX\ alignment features. It's in a separate,
1024 % package called \package{mathenv}, to avoid wasting your memory.
1025 %
1026 % \begin{grammar}
1027 %
1028 % <eqnarray-env> ::= \[[
1029 % <begin-eqnarray> \< <row> \\ "\\\\" \> <end-eqnarray>
1030 % \]]
1031 %
1032 % <begin-eqnarray> ::= \[[
1033 % "\\begin" \( "{eqnarray}" \\ "{eqnarray*}" \)
1034 % \[ "[" \< <eqa-column> \> "]" \]
1035 % \]]
1036 %
1037 % <eqa-column> ::= \[[
1038 % \[ "q" \\ ":" \]
1039 % \[ \< ">" "{" <pre-text> "}" \> \]
1040 % \begin{stack}
1041 % \[ "T" \] \( "r" \\ "c" \\ "l" \) \\
1042 % "L" \\
1043 % "x"
1044 % \end{stack}
1045 % \[ \< "<" "{" <post-text> "}" \> \]
1046 % \]]
1047 %
1048 % <end-eqnarray> ::= \[[
1049 % "\\end" \begin{stack} "{eqnarray}" \\ "{eqnarray*}" \end{stack}
1050 % \]]
1051 %
1052 % \end{grammar}
1053 %
1054 % Descriptions of the various column types are given in
1055 % table~\ref{tbl:eqnarray}.
1056 %
1057 % \begin{table}
1058 % \begin{tabular}[C]{| >{\synshorts} c | m{3in} |} \hlx{hv[1]}
1059 %
1060 % \multicolumn{2}{|c|}{\bf Column types} \\ \hlx{v[1]hv}
1061 % \bf Name & \bf Meaning \\ \hlx{vhv.}
1062 % "l" & Left aligned piece of equation. \\ \hlx{.}
1063 % "c" & Centred piece of equation. \\ \hlx{.}
1064 % "x" & Centred or flush-left whole equation
1065 % (depending on \textsf{fleqn} option). \\ \hlx{.}
1066 % "r" & Right aligned piece of equation. \\ \hlx{vhv.}
1067 % "L" & Left aligned piece of equation whose
1068 % width is considered to be 2\,em. \\ \hlx{vhv.}
1069 % "Tl", "Tc" and "Tr" & Left, centre and right aligned
1070 % text. \\ \hlx{vhhv[1]}
1071 %
1072 % \multicolumn{2}{|c|}{\bf Other modifier characters} \\ \hlx{v[1]hv}
1073 % \bf Name & \bf Meaning \\ \hlx{vhv.}
1074 % ":" & Leaves a big gap between equations.
1075 % By default, the `chunks' separated by
1076 % \lit{:}s are equally spaced on the
1077 % line. \\ \hlx{.}
1078 % "q" & Inserts 1\,em of space \\ \hlx{vhv.}
1079 % ">{"<text>"}" & Inserts \<text> just before the
1080 % actual column entry. \\ \hlx{.}
1081 % "<{"<text>"}" & Inserts \<text> just after the
1082 % actual column entry. \\ \hlx{vhv.}
1083 % "*{"<count>"}{"<chars>"}" & Inserts \<count>
1084 % copies of the \<chars> into the
1085 % preamble. \\ \hlx{vh}
1086 % \end{tabular}
1087 %
1088 % \caption{\package{eqnarray} column types and modifiers}
1089 % \label{tbl:eqnarray}
1090 % \end{table}
1091 %
1092 % The default preamble, if you don't supply one of your own, is \lit{rcl}.
1093 % Most of the time, \lit{rl} is sufficient, although compatibility is more
1094 % important to me.
1095 %
1096 % By default, there is no space between columns, which makes formul\ae\ in an
1097 % \env{eqnarray} environment look just like formul\ae\ typeset on their own,
1098 % except that things get aligned in columns. This is where the default
1099 % \env{eqnarray} falls down: it leaves |\arraycolsep| space between each
1100 % column making the thing look horrible.
1101 %
1102 % An example would be good here, I think. This one's from exercise 22.9 of
1103 % the \textit{\TeX book}.
1104 %
1105 % \begin{demo}[w]{Simultaneous equations}
1106 %\begin{eqnarray}[*3{rc}rl]
1107 % 10w & + & 3x & + & 3y & + & 18z & = 1 \\
1108 % 6w & - & 17x & & & - & 5z & = 2
1109 %\end{eqnarray}
1110 % \end{demo}
1111 %
1112 % Choosing a more up-to-date example, here's some examples from the
1113 % \textit{\LaTeX\ Companion}.
1114 %
1115 % \begin{demo}[w]{Lots of equations}
1116 %\begin{eqnarray}[rl:rl:lq]
1117 % V_i &= v_i - q_i v_j, & X_i &= x_i - q_i x_j, &
1118 % U_i = u_i, \qquad \mbox{for $i \ne j$} \\
1119 % V_j &= v_j, & X_j &= x_j &
1120 % U_j u_j + \sum_{i \ne j} q_i u_i. \label{eq:A}
1121 %\end{eqnarray}
1122 % \end{demo}
1123 %
1124 % \begin{figure}
1125 % \begin{demo}[w]{Plain text column and \cs{tabpause}}
1126 %\begin{eqnarray}[rlqqTl]
1127 % x &= y & by (\ref{eq:A}) \\
1128 % x' &= y' & by definition \\
1129 %\tabpause{and}
1130 % x + x' &= y + y' & by Axiom~1
1131 %\end{eqnarray}
1132 % \end{demo}
1133 % \end{figure}
1134 %
1135 % The new features also mean that you don't need to mess about with
1136 % |\lefteqn| any more. This is handled by the \lit{L} column type:
1137 %
1138 % \begin{demo}{Splitting example}
1139 %\begin{eqnarray*}[Ll]
1140 % w+x+y+z = \\
1141 % & a+b+c+d+e+ \\
1142 % & f+g+h+i+j
1143 %\end{eqnarray*}
1144 % \end{demo}
1145 %
1146 % Finally, just to prove that the spacing's right at last, here's another one
1147 % from the \textit{Companion}.
1148 %
1149 % \begin{demo}{Spacing demonstration}
1150 %\begin{equation}
1151 % x^2 + y^2 = z^2
1152 %\end{equation}
1153 %\begin{eqnarray}[rl]
1154 % x^2 + y^2 &= z^2 \\
1155 % y^2 &< z^2
1156 %\end{eqnarray}
1157 % \end{demo}
1158 %
1159 % Well, that was easy enough. Now on to numbering. As you've noticed, the
1160 % equations above are numbered. You can use the \env{eqnarray$*$}
1161 % environment to turn off the numbering in the whole environment, or say
1162 % |\nonumber| on a line to suppress numbering of that one in particular.
1163 %
1164 % \DescribeMacro{\eqnumber}
1165 % More excitingly, you can say |\eqnumber| to enable numbering for a
1166 % particular equation, or \syntax{"\\eqnumber["<text>"]"} to choose what to
1167 % show instead of the line number. This works for both starred and unstarred
1168 % versions of the environment. Now |\nonumber| becomes merely a synonym for
1169 % `|\eqnumber[]|'.
1170 %
1171 % A note for cheats: you can use the sparkly new \env{eqnarray} for simple
1172 % equations by specifying \lit{x} as the column description. Who needs
1173 % \AmSTeX?\ |;-)|
1174 %
1175 % \DescribeEnv{eqlines}
1176 % \DescribeEnv{eqlines*}
1177 % In fact, there's a separate environment \env{eqlines}, which is equivalent
1178 % to \env{eqnarray} with a single \lit{x} column; the result is that you can
1179 % insert a collection of displayed equations separated by |\\| commands. If
1180 % you don't like numbering, use \env{eqlines$*$} instead.
1181 %
1182 % \subsubsection{The \env{eqnalign} environment}
1183 %
1184 % \DescribeEnv{eqnalign}
1185 % There's a new environment, \env{eqnalign}, which does almost the same
1186 % thing as \env{eqnarray} but not quite. It doesn't do equation numbers,
1187 % and it wraps its contents up in a box. The result of this is that:
1188 %
1189 % \begin{itemize}
1190 %
1191 % \item You can use \env{eqnalign} for just a part of a formula.
1192 % The \env{eqnarray} environment must take up the whole display.
1193 %
1194 % \item You can use \env{eqnalign} within \env{eqnarray} for extra fine
1195 % alignment of subsidiary bits.
1196 %
1197 % \item You can break off from doing an \env{eqnarray} using the |\tabpause|
1198 % command. You can't use |\tabpause| inside
1199 % \env{eqnalign}.\footnote{^^A
1200 % Well, technically speaking there's nothing to stop you. However,
1201 % the results won't be pretty.}
1202 %
1203 % \end{itemize}
1204 %
1205 % The \env{eqnalign} environment works like this:
1206 %
1207 % \begin{grammar}
1208 %
1209 % <eqnalign-env> ::= \[[
1210 % <begin-eqnalign> <contents> <end-eqnalign>
1211 % \]]
1212 %
1213 % <begin-eqnalign> ::= \[[
1214 % "\\begin" "{eqnalign}"
1215 % \[ "[" \< <eqa-column> \> "]" \]
1216 % \[ "[" \( "t" \\ "c" \\ "b" \) "]" \]
1217 % \]]
1218 %
1219 % <end-eqnalign> ::= \[[ "\\end" "{eqnalign}" \]]
1220 %
1221 % \end{grammar}
1222 %
1223 % As the syntax suggests, the preamble for the \env{eqnalign} environment
1224 % works exactly the same way as for \env{eqnarray}. Example time: another
1225 % one from the \textit{\TeX book}.
1226 %
1227 % \begin{figure}
1228 % \begin{demo}[w]{Example of \env{eqnalign}}
1229 %\[
1230 % \left\{ \begin{eqnalign}[rl]
1231 % \alpha &= f(z) \\ \beta &= f(z^2) \\
1232 % \gamma &= f(z^3)
1233 % \end{eqnalign} \right\}
1234 % \qquad
1235 % \left\{ \begin{eqnalign}[rl]
1236 % x &= \alpha^2 - \beta \\ y &= 2\gamma
1237 % \end{eqnalign} \right\}.
1238 %\]
1239 % \end{demo}
1240 % \end{figure}
1241 %
1242 % \DescribeMacro{\multicolumn}
1243 % The |\multicolumn| command works correctly in both the \env{eqnarray} and
1244 % \env{eqnalign} environments, although you should bear in mind that you
1245 % should give \env{eqnarray} column types, not \env{array} ones.
1246 %
1247 % \subsubsection{A note on spacing in alignment environments}
1248 %
1249 % Most of the time, equations in \env{eqnarray} and \env{eqnalign}
1250 % environments will be beautiful. However, there are some things you should
1251 % bear in mind when you produce beautiful equations.
1252 %
1253 % The main problem with spacing is making sure that binary relations and
1254 % binary operators have the correct amount of space on each side of them.
1255 % The alignment environments insert `hidden' objects at the ends of table
1256 % cells to assist with the spacing: \lit{l} column types have a hidden object
1257 % on the left, \lit{r} types have a hidden object on the right, and \lit{c}
1258 % types have a hidden object on \emph{both} ends. These hidden objects add
1259 % the correct space when there's a binary operator or relation next to them.
1260 % If some other sort of object is lurking there, no space is added. So far,
1261 % so good.
1262 %
1263 % The only problem comes when you have something like this:
1264 %
1265 % \begin{demo}{How not to do an \env{eqnarray}}
1266 %\begin{eqnarray*}[rcl]
1267 % x + y & = & 12 \\
1268 % 2x - 5y & = & -6
1269 %\end{eqnarray*}
1270 % \end{demo}
1271 %
1272 % The `$-$' sign in the second equation has been treated as a binary operator
1273 % when really it should be a unary prefix operator, but \TeX\ isn't clever
1274 % enough to know the difference. (Can you see the difference in the spacing
1275 % between $-6$~and~${}-6$?) There are two possible solutions to the
1276 % problem. You could wrap the `|-6|' up in a group (`|{-6}|'), or just the
1277 % $-$ sign (`|{-}6|'). A better plan, though, is to get rid of the middle
1278 % column altogether:
1279 %
1280 % \begin{demo}{How to do an \env{eqnarray}}
1281 %\begin{eqnarray*}[rl]
1282 % x + y & = 12 \\
1283 % 2x - 5y & = -6
1284 %\end{eqnarray*}
1285 % \end{demo}
1286 %
1287 % Since the things in the middle column were the same width, it's not
1288 % actually doing any good. Also, now that \TeX\ can see that the thing on
1289 % the left of the `$-$' sign is a relation (the `$=$' sign), it will space
1290 % the formula correctly.
1291 %
1292 % In this case, it might be even better to add some extra columns, and line
1293 % up the $x$ and $y$ terms in the left hand side:
1294 %
1295 % \begin{demo}{Extra beautiful \env{eqnarray}}
1296 %\begin{eqnarray*}[rrl]
1297 % x + & y & = 12 \\
1298 % 2x - & 5y & = -6
1299 %\end{eqnarray*}
1300 % \end{demo}
1301 %
1302 % ^^A Some hacking now to display box sizes.
1303 %
1304 % {
1305 % \catcode`p=12 \catcode`t=12
1306 % \gdef\magni#1pt{#1}
1307 % }
1308 %
1309 % \newcommand{\widthof}[1]{^^A
1310 % \settowidth{\dimen0 }{#1}^^A
1311 % \expandafter\magni\the\dimen0\,pt^^A
1312 % }
1313 %
1314 % ^^A The text below makes an assumption which looks correct to me (I asked
1315 % ^^A TeX, and it agreed with me), although in case anything changes, I want
1316 % ^^A to be informed.
1317 %
1318 % \sbox0{$+$} \sbox2{$-$} \ifdim\wd0=\wd2\else%
1319 % \errmessage{Assertion failed: `+' and `-' are different widths!}
1320 % \fi
1321 %
1322 % There's no need to put the `$+$' and `$-$' operators in their own column
1323 % here, because they're both \widthof{$+$} wide, even though they don't
1324 % look it.
1325 %
1326 % \subsubsection{Configuring the alignment environments}
1327 %
1328 % There are a collection of parameters you can use to make the equation
1329 % alignment environments (\env{eqnarray} and \env{eqnalign}) look the way
1330 % you like them. These are all shown in table~\ref{tbl:eqnparms}.
1331 %
1332 % \begin{table}
1333 % \begin{tabular}[C]{| l | p{3in} |} \hlx{hv}
1334 % \bf Parameter & \bf Use \\ \hlx{vhv}
1335 % |\eqaopenskip| & Length put on the left of an
1336 % \env{eqnarray} environment. By
1337 % default, this is |\@centering| (to
1338 % centre the alignment) or |\mathindent|
1339 % (to left align) depending on whether
1340 % you're using the \textsf{fleqn}
1341 % document class option. \\
1342 % |\eqacloseskip| & Length put on the right of an
1343 % \env{eqnarray} environment. By
1344 % default, this is |\@centering|, to
1345 % align the environment correctly. \\ \hlx{vhv}
1346 % |\eqacolskip| & Space added by the \lit{:} column
1347 % modifier. This should be a rubber
1348 % length, although it only stretches in
1349 % \env{eqnarray}, not in \env{eqnalign}.
1350 % The default value is 1\smallf1/2\,em
1351 % with 1000\,pt of stretch. \\
1352 % |\eqainskip| & Space added at each side of a normal
1353 % column. By default this is 0\,pt. \\ \hlx{vhv}
1354 % |\eqastyle| & The maths style used in the alignment.
1355 % By default, this is |\textstyle|,
1356 % and you probably won't want to change
1357 % it. \\ \hlx{vh}
1358 % \end{tabular}
1359 %
1360 % \caption{Parameters for the \env{eqnarray} and \env{eqnalign} environments}
1361 % \label{tbl:eqnparms}
1362 % \end{table}
1363 %
1364 %
1365 % \subsection{Other multiline equations}
1366 %
1367 % Sometimes there's no sensible alignment point for splitting equations. The
1368 % normal thing to do under these circumstances is to put the first line way
1369 % over to the left of the page, and the last line over to the right. (If
1370 % there are more lines, I imagine we put them in the middle.)
1371 %
1372 % \DescribeEnv{spliteqn}
1373 % \DescribeEnv{spliteqn*}
1374 % The \env{spliteqn} environment allows you to do such splitting of
1375 % equations. Rather than tediously describe it, I'll just give an example,
1376 % because it's really easy. The $*$-version works the same, except it
1377 % doesn't put an equation number in.
1378 %
1379 % \begin{figure}
1380 % \begin{demo}[w]{A split equation}
1381 %\begin{spliteqn}
1382 % \sum_{1\le j\le n}
1383 % \frac {1} { (x_j - x_1) \ldots (x_j - x_{j-1})
1384 % (x - x_j) (x_j - x_{j+1}) \ldots (x_j - x_n) }
1385 % \\
1386 % = \frac {1} { (x - x_1) \ldots (x - x_n) }.
1387 %\end{spliteqn}
1388 % \end{demo}
1389 % \end{figure}
1390 %
1391 % \DescribeEnv{subsplit}
1392 % If you have a very badly behaved equation, you might want to split a part
1393 % of it (say, a bit of a fraction), particularly if you're doing things in
1394 % narrow columns.
1395 %
1396 % \begin{figure}
1397 % \begin{demo}[w]{A \env{subsplit} environment}
1398 %\begin{equation}
1399 % \frac{
1400 % \begin{subsplit}
1401 % q^{\frac{1}{2} n(n+1)}(ea; q^2)_\infty (eq/a; q^2)_\infty \\
1402 % (caq/e; q^2)_\infty (cq^2/ae; q^2)_\infty
1403 % \end{subsplit}
1404 % }{
1405 % (e; q)_\infty (cq/e; q)_\infty
1406 % }
1407 %\end{equation}
1408 % \end{demo}
1409 % \end{figure}
1410 %
1411 % \subsection{Matrices}
1412 %
1413 % Also included in the \package{mathenv} package is a collection of things
1414 % for typesetting matrices. The standard \env{array} doesn't (in my opinion)
1415 % provide the right sort of spacing for matrices. \PlainTeX\ provides some
1416 % quite nice matrix handling macros, but they don't work in the appropriate
1417 % \LaTeX\ way.
1418 %
1419 % \textbf{Warning:} These definitions will make old versions of
1420 % \package{plain.sty} unhappy; newer versions correctly restore the
1421 % Plain~\TeX\ macros |\matrix| and |\pmatrix|.
1422 %
1423 % \DescribeEnv{matrix}
1424 % The simple way to do matrices is with the \env{matrix} environment.
1425 %
1426 % \begin{grammar}
1427 %
1428 % <matrix-env> ::= \[[ <begin-matrix> <contents> <end-matrix> \]]
1429 %
1430 % <begin-matrix> ::= \[[ "\\begin{matrix}" \[ "[" <matrix-cols> "]" \] \]]
1431 %
1432 % <matrix-cols> ::= \[[
1433 % \< \[ "[" \] \[ "T" \] \( "l" \\ "c" \\ "r" \) \>
1434 % \]]
1435 %
1436 % <end-matrix> ::= \[[ "\\end{stack}" \]]
1437 %
1438 % \end{grammar}
1439 %
1440 % The \lit{l}, \lit{c} and \lit{r} columns are fairly obvious -- they align
1441 % their contents in the appropriate way. The \lit{[} character is more
1442 % complicated. It means `repeat the remaining column types forever', so a
1443 % preamble of \lit{cc[lr} means `two centred columns, then alternating left-
1444 % and right-aligned columns for as often as needed'. The default preamble,
1445 % if you don't specify one, is \lit{[c} -- `any number of centred columns'.
1446 %
1447 % \DescribeMacro{\multicolumn}
1448 % The |\multicolumn| command works correctly in matrices, although you should
1449 % bear in mind that you should give \env{matrix} column types, not
1450 % \env{array} ones.
1451 %
1452 % \DescribeEnv{pmatrix}
1453 % The standard \env{matrix} environment doesn't put any delimiters around the
1454 % matrix. You can use the standard |\left| and |\right| commands, although
1455 % this is a bit nasty. The \env{pmatrix} environment will put parentheses
1456 % around the matrix it creates; it's otherwise exactly the same as
1457 % \env{matrix}.
1458 %
1459 % \DescribeEnv{dmatrix}
1460 % A \env{dmatrix} environment is also provided. It takes two extra
1461 % arguments: the left and right delimiter characters (without |\left| or
1462 % |\right|).
1463 %
1464 % \begin{figure}
1465 % \begin{demo}[w]{Various \env{matrix} environments}
1466 %\[ \begin{matrix} 1 & 0 \\ 0 & -1 \end{matrix} \quad
1467 % \begin{pmatrix}
1468 % \cos\theta & \sin\theta \\
1469 % -\sin\theta & \cos\theta
1470 % \end{pmatrix} \quad
1471 % \begin{dmatrix}[] 0 & -i \\ i & 0 \end{dmatrix}
1472 %\]
1473 % \end{demo}
1474 % \end{figure}
1475 %
1476 % \DescribeEnv{smatrix}
1477 % Normal matrices always come out the same size; they don't change size
1478 % according to the surrounding context (unfortunately). However, it can be
1479 % occasionally useful to put matrices in running text, so you can talk about
1480 % $A$ being $\bigl( \begin{smatrix} a & b \\ b & c \end{smatrix} \bigr)$
1481 % being its own transpose (i.e., $A = A^T$). This is accomplished using the
1482 % \env{smatrix} (the `s' stands for `small' -- I thought that `smallmatrix'
1483 % was too big to type inline). As well as inline text, the \env{smatrix}
1484 % can be useful in displays, if the matrix is deep in a subformula. I can't
1485 % think of any examples offhand, though.
1486 %
1487 % \DescribeEnv{spmatrix}
1488 % \DescribeEnv{sdmatrix}
1489 % The \env{smatrix} environment doesn't supply any delimiters, like
1490 % \env{matrix}. There are \env{spmatrix} and \env{sdmatrix} environments
1491 % which do, though. Note that delimiters have a tendency to get too big and
1492 % mess up the line spacing -- I had to use explicitly |\big| delimiters
1493 % in the above example.
1494 %
1495 % \DescribeEnv{pmatrix*}
1496 % \DescribeEnv{spmatrix*}
1497 % \DescribeEnv{sdmatrix*}
1498 % All the small matrix environments have starred versions, which are more
1499 % suitable for use in displays, since they have more space between the rows.
1500 % They're intended for typesetting really big matrices in displays.
1501 %
1502 % \DescribeMacro{\ddots}
1503 % \DescribeMacro{\vdots}
1504 % The standard |\vdots| and |\ddots| commands don't produce anything at all
1505 % nice in small matrices, so this package redefines them so that they scale
1506 % properly to smaller sizes.
1507 %
1508 % \DescribeEnv{genmatrix}
1509 % Actually, all these environments are special cases of one: \env{genmatrix}.
1510 % This takes oodles of arguments:
1511 % \begin{quote} \synshorts
1512 % "\\begin{genmatrix}{"<matrix-style>"}{"<outer-style>"}" \\
1513 % \null \qquad "{"<spacing>"}{"<left-delim>"}{"<right-delim>"}" \\
1514 % \null \quad\vdots \\
1515 % "\\end{genmatrix}"
1516 % \end{quote}
1517 % The two `style' arguments should be things like |\textstyle| or
1518 % |\scriptstyle|; the first, \<matrix-style>, is the style to use for the
1519 % matrix elements, and the second, \<outer-style>, is the style to assume
1520 % for the surrounding text (this affects the spacing within the matrix; it
1521 % should usually be the same as \<matrix-style>). The \<spacing> is inserted
1522 % between the matrix and the delimiters, on each side of the matrix. It's
1523 % usually `|\,|' in full-size matrices, and blank for small ones. The
1524 % delimiters are inserted around the matrices, and sized appropriately.
1525 %
1526 % \DescribeEnv{newmatrix}
1527 % You can create your own matrix environments if you like, using the
1528 % |\newmatrix| command. It takes two arguments, although they're a bit
1529 % odd. The first is the name of the environment, and the second contains
1530 % the arguments to pass to \env{genmatrix}. For example, the \env{pmatrix}
1531 % environment was defined by saying
1532 %
1533 % \begin{listing}
1534 %\newmatrix{pmatrix}{{\textstyle}{\textstyle}{\,}{(}{)}}
1535 % \end{listing}
1536 %
1537 % If you don't pass all three arguments, then you end up requiring the
1538 % user to specify the remaining ones. This is how \env{dmatrix} works.
1539 %
1540 % \DescribeEnv{script}
1541 % Finally, although it's not really a matrix, stacked super- and subscripts
1542 % follow much the same sorts of spacing rules. The \env{script} environment
1543 % allows you to do this sort of thing very easily. It essentially provides
1544 % a `matrix' with the right sort of spacing. The default preamble string is
1545 % \lit{c}, giving you centred scripts, although you can say
1546 % |\begin{script}[l]| for left-aligned scripts, which is better if the
1547 % script is being placed to the right of its operator. If you're really
1548 % odd, you can have more than one column.
1549 %
1550 % \begin{demo}{Example of \env{script}}
1551 %\[ \mathop{{\sum}'}_{x \in A}
1552 % f(x)
1553 % \stackrel{\mathrm{def}}{=}
1554 % \sum_{\begin{script}
1555 % x \in A \\ x \ne 0
1556 % \end{script}} f(x)
1557 %\]
1558 % \end{demo}
1559 %
1560 %
1561 % \subsection{Other \package{mathenv} environments}
1562 %
1563 % The \package{mathenv} package contains some other environments which may
1564 % be useful, based on the enhanced \env{tabular} and \env{array}
1565 % environments.
1566 %
1567 % \DescribeEnv{cases}
1568 % The \env{cases} environment lets you say things like the following:
1569 %
1570 % \begin{demo}[w]{Example of \env{cases}}
1571 %\[ P_{r-j} = \begin{cases}
1572 % 0 & if $r-j$ is odd \\
1573 % r!\,(-1)^{(r-j)/2} & if $r-j$ is even
1574 % \end{cases}
1575 %\]
1576 % \end{demo}
1577 %
1578 % The spacing required for this is a bit messy, so providing an environment
1579 % for it is quite handy.
1580 %
1581 % \DescribeEnv{smcases}
1582 % The \env{smcases} environment works the same way as \env{cases}, but with
1583 % scriptsize lettering.
1584 %
1585 % \implementation
1586 %
1587 %
1588 %^^A-------------------------------------------------------------------------
1589 % \section{Implementation of table handling}
1590 %
1591 %
1592 % Here we go. It starts horrid and gets worse. However, it does stay nicer
1593 % than the original, IMHO.
1594 %
1595 % \begin{macrocode}
1596 %<*mdwtab>
1597 % \end{macrocode}
1598 %
1599 %
1600 % \subsection{Registers, switches and things}
1601 %
1602 % We need lots of these. It's great fun.
1603 %
1604 % The two count registers are simple enough:
1605 %
1606 % \begin{description}
1607 % \item [\cs{tab@state}] contains the current parser state. Since we
1608 % probably won't be parsing preambles recursively, this is a global
1609 % variable.
1610 % \item [\cs{tab@columns}] contains the number of the current column.
1611 % \item [\cs{tab@hlstate}] contains the state required for hline management.
1612 % \end{description}
1613 %
1614 % \begin{macrocode}
1615 \newcount\tab@state
1616 \newcount\tab@columns
1617 % \end{macrocode}
1618 %
1619 % We need \emph{lots} of token registers. Fortunately, most of them are only
1620 % used during parsing. We'll use \PlainTeX's scratch tokens for this. Note
1621 % that |\toks\tw@| isn't used here. It, and |\toks@|, are free for use by
1622 % column commands.
1623 %
1624 % \begin{macrocode}
1625 \newtoks\tab@preamble
1626 \newtoks\tab@shortline
1627 \toksdef\tab@pretext 4
1628 \toksdef\tab@posttext 6
1629 \toksdef\tab@userpretext 8
1630 % \end{macrocode}
1631 %
1632 % The dimens are fairly straightforward. The inclusion of |\col@sep| is a
1633 % sacrifice to compatibility -- judicious use of |\let| in \package{array}
1634 % would have saved a register.
1635 %
1636 % \begin{macrocode}
1637 \newdimen\extrarowheight
1638 \newdimen\tabextrasep
1639 \newdimen\arrayextrasep
1640 \newdimen\smarraycolsep
1641 \newdimen\smarrayextrasep
1642 \newdimen\tab@width
1643 \newdimen\col@sep
1644 \newdimen\tab@endheight
1645 \newdimen\arraythickrulewidth
1646 \newdimen\tab@rulewidth
1647 % \end{macrocode}
1648 %
1649 % Some skip registers too. Phew.
1650 %
1651 % \begin{macrocode}
1652 \newskip\tab@leftskip
1653 \newskip\tab@rightskip
1654 % \end{macrocode}
1655 %
1656 % And some switches. The first three are for the parser.
1657 %
1658 % \begin{macrocode}
1659 \newif\iftab@firstcol
1660 \newif\iftab@initrule
1661 \newif\iftab@rule
1662 \newif\iftab@vgap
1663 % \end{macrocode}
1664 %
1665 % Now assign some default values to new dimen parameters. These definitions
1666 % are essentially the equivalent of an |\openup 1\jot| in \env{array}, but
1667 % not in \env{tabular}. This looks nice, I think.
1668 %
1669 % \begin{macrocode}
1670 \tabextrasep\z@
1671 \arrayextrasep\jot
1672 \smarraycolsep\thr@@\p@
1673 \smarrayextrasep\z@
1674 \arraythickrulewidth\p@
1675 % \end{macrocode}
1676 %
1677 % Set some things up for alien table environments.
1678 %
1679 % \begin{macrocode}
1680 \let\tab@extrasep\tabextrasep
1681 \let\tab@penalty\relax
1682 % \end{macrocode}
1683 %
1684 %
1685 % \subsection{Some little details}
1686 %
1687 % \begin{macro}{\@maybe@unskip}
1688 %
1689 % This macro solves a little problem. In an alignment (and in other places)
1690 % it's desirable to suppress trailing space. The usual method, to say
1691 % |\unskip|, is a little hamfisted, because it removes perfectly reasonable
1692 % aligning spaces like |\hfil|s. While as a package writer I can deal with
1693 % this sort of thing by saying |\kern\z@| in appropriate places, it can
1694 % annoy users who are trying to use |\hfill| to override alignment in funny
1695 % places.
1696 %
1697 % My current solution seems to be acceptable. I'll remove the natural width
1698 % of the last glue item, so that it can still stretch and shrink if
1699 % necessary. The implementation makes use of the fact that multiplying
1700 % a \<skip> by a \<number> kills off the stretch. (Bug fix: don't do this
1701 % when we're in vertical mode.)
1702 %
1703 % \begin{macrocode}
1704 \def\@maybe@unskip{\ifhmode\hskip\m@ne\lastskip\relax\fi}
1705 % \end{macrocode}
1706 %
1707 % \end{macro}
1708 %
1709 % \begin{macro}{\q@delim}
1710 %
1711 % Finally, for the sake of niceness, here's a delimiter token I can use
1712 % for various things. It's a `quark', for what it's worth (i.e., it expands
1713 % to itself) although I'm not really sure why this is a good thing. As far
1714 % as I'm concerned, it's important that it has a unique meaning (i.e., that
1715 % it won't be |\ifx|-equal to other things, or something undefined) and that
1716 % it won't be used where I don't expect it to be used. \TeX\ will loop
1717 % horridly if it tries to expand this, so I don't think that quarks are
1718 % wonderfully clever thing to use. (Maybe it should really expand to
1719 % something like `\syntax{<quark>"."}', which will rapidly fill \TeX's memory
1720 % if it gets accidentally expanded. Still, I'll leave it as it is until
1721 % such time as I understand the idea more.)
1722 %
1723 % \begin{macrocode}
1724 \def\q@delim{\q@delim}
1725 % \end{macrocode}
1726 %
1727 % \end{macro}
1728 %
1729 %
1730 % \subsection{Parser states}
1731 %
1732 % Now we start on the parser. It's really simple, deep down. We progress
1733 % from state to state, extracting tokens from the preamble and building
1734 % command names from them. Each command calls one of the element-building
1735 % routines, which works out which state it should be in. We go through each
1736 % of the states in between (see later) doing default things for the ones we
1737 % missed out.
1738 %
1739 % Anyway, here's some symbolic names for the states. It makes my life
1740 % easier.
1741 %
1742 % \begin{macrocode}
1743 \chardef\tab@startstate 0
1744 \chardef\tab@loopstate 1
1745 \chardef\tab@rulestate 1
1746 \chardef\tab@prespcstate 2
1747 \chardef\tab@prestate 3
1748 \chardef\tab@colstate 4
1749 \chardef\tab@poststate 5
1750 \chardef\tab@postspcstate 6
1751 \chardef\tab@limitstate 7
1752 % \end{macrocode}
1753 %
1754 %
1755 % \subsection{Adding things to token lists}
1756 %
1757 % Define some macros for adding stuff to the beginning and end of token
1758 % lists. This is really easy, actually. Here we go.
1759 %
1760 % \begin{macrocode}
1761 \def\tab@append#1#2{#1\expandafter{\the#1#2}}
1762 \def\tab@prepend#1#2{%
1763 \toks@{#2}#1\expandafter{\the\expandafter\toks@\the#1}%
1764 }
1765 % \end{macrocode}%
1766 %
1767 %
1768 % \subsection{Committing a column to the preamble}
1769 %
1770 % Each time we pass the `rule' state, we `commit' the tokens we've gathered
1771 % so far to the main preamble token list. This is how we do it. Note the
1772 % icky use of |\expandafter|.
1773 %
1774 % \begin{macrocode}
1775 \def\tab@commit{%
1776 % \end{macrocode}
1777 %
1778 % If this isn't the first column, then we need to put in a column separator.
1779 %
1780 % \begin{macrocode}
1781 \iftab@firstcol\else%
1782 \expandafter\tab@append\expandafter\tab@preamble%
1783 \expandafter{\tab@tabtext}%
1784 \fi%
1785 % \end{macrocode}
1786 %
1787 % Now we spill the token registers into the main list in a funny order (which
1788 % is why we're doing it in this strange way in the first place.
1789 %
1790 % \begin{macrocode}
1791 \toks@\expandafter{\tab@midtext}%
1792 \tab@preamble\expandafter{%
1793 \the\expandafter\tab@preamble%
1794 \the\expandafter\tab@pretext%
1795 \the\expandafter\tab@userpretext%
1796 \the\expandafter\toks@%
1797 \the\tab@posttext%
1798 }%
1799 % \end{macrocode}
1800 %
1801 % Now reset token lists and things for the next go round.
1802 %
1803 % \begin{macrocode}
1804 \tab@firstcolfalse%
1805 \tab@pretext{}%
1806 \tab@userpretext{}%
1807 \tab@posttext{}%
1808 }
1809 % \end{macrocode}
1810 %
1811 %
1812 % \subsection{Playing with parser states}
1813 %
1814 % \begin{macro}{\tab@setstate}
1815 %
1816 % This is how we set new states. The algorithm is fairly simple, really.
1817 %
1818 % ^^A Let's see how good my TeX really is... ;-)
1819 % ^^A Actually, it doesn't seem to have worked out too badly. Maybe I should
1820 % ^^A write a package to do this automatically. It's rather tricky, though.
1821 %
1822 % \def\qq{\mbox{\quad}}
1823 % \sbox{0}{\itshape\textunderscore}\def\_{\usebox{0}}
1824 %
1825 % \begin{quote}
1826 % {\bf while} $\it tab\_state \ne s$ {\bf do} \\
1827 % \qq $\mathit{tab\_state = tab\_state}+1$; \\
1828 % \qq {\bf if} $\it tab\_state = tab\_limitState$ {\bf then}
1829 % $\it tab\_state=tab\_loopState$; \\
1830 % \qq {\bf if} $\it tab\_state = tab\_preSpcState$ {\bf then} \\
1831 % \qq \qq {\bf if} $\it tab\_initRule$ {\bf then} \\
1832 % \qq \qq \qq $\it tab\_initRule = {\bf false}$; \\
1833 % \qq \qq {\bf else} \\
1834 % \qq \qq \qq {\bf if} $\it tab\_inMultiCol$ {\bf then moan}; \\
1835 % \qq \qq \qq $\it commit$; \\
1836 % \qq \qq \qq $\it append(tab\_shortLine,\hbox{`|&\omit|')}$; \\
1837 % \qq \qq {\bf end\,if}; \\
1838 % \qq {\bf end\,if}; \\
1839 % \qq {\bf if} $\it tab\_state \ne s$ {\bf then}
1840 % $\it do\_default(tab\_state)$; \\
1841 % {\bf end\,while};
1842 % \end{quote}
1843 %
1844 % First we decide if there's anything to do. If so, we call another macro to
1845 % do it for us.
1846 %
1847 % \begin{macrocode}
1848 \def\tab@setstate#1{%
1849 \ifnum#1=\tab@state\else%
1850 \def\@tempa{\tab@setstate@i{#1}}%
1851 \@tempa%
1852 \fi%
1853 }
1854 % \end{macrocode}
1855 %
1856 % This is where the fun is. First we bump the state by one, and loop back
1857 % if we fall off the end.
1858 %
1859 % \begin{macrocode}
1860 \def\tab@setstate@i#1{%
1861 \global\advance\tab@state\@ne%
1862 \ifnum\tab@state>\tab@limitstate%
1863 \global\tab@state\tab@loopstate%
1864 \fi%
1865 % \end{macrocode}
1866 %
1867 % Now, if we've just passed the ruleoff state, we commit the current text
1868 % \emph{unless} this was the strange initial rule at the very beginning. We
1869 % provide a little hook here so that |\multicolumn| can moan if you try and
1870 % give more than one column there. We also add another tab/omit pair to the
1871 % list we use for |\vgap|.
1872 %
1873 % \begin{macrocode}
1874 \ifnum\tab@state=\tab@prespcstate%
1875 \iftab@initrule%
1876 \tab@initrulefalse%
1877 \else%
1878 \tab@looped%
1879 \tab@commit%
1880 \tab@append\tab@shortline{&\omit}%
1881 \fi%
1882 \fi%
1883 % \end{macrocode}
1884 %
1885 % Now we decide whether to go round again. If not, we do the default thing
1886 % for this state. This is mainly here so that we can put the |\tabcolsep| or
1887 % whatever in if the user didn't give an \lit{@} expression.
1888 %
1889 % \begin{macrocode}
1890 \ifnum#1=\tab@state%
1891 \let\@tempa\relax%
1892 \else%
1893 \csname tab@default@\number\tab@state\endcsname%
1894 \fi%
1895 \@tempa%
1896 }
1897 % \end{macrocode}
1898 %
1899 % \end{macro}
1900 %
1901 % Now we set up the default actions for the various states.
1902 %
1903 % In state~2 (pre-space) we add in the default gap if either we didn't have
1904 % an \lit{@} expression in the post-space state or there was an explicit
1905 % intervening rule.
1906 %
1907 % \begin{macrocode}
1908 \@namedef{tab@default@2}{%
1909 \iftab@rule%
1910 \tab@append\tab@pretext{\hskip\col@sep}%
1911 \fi%
1912 }
1913 % \end{macrocode}
1914 %
1915 % If the user omits the column type, we insert an `l'-type column and moan
1916 % a lot.
1917 %
1918 % \begin{macrocode}
1919 \@namedef{tab@default@4}{%
1920 \tab@err@misscol%
1921 \tab@append\tab@pretext{\tab@bgroup\relax}%
1922 \tab@append\tab@posttext{\relax\tab@egroup\hfil}%
1923 \tab@append\tab@shortline{\hfil}%
1924 \advance\tab@columns\@ne%
1925 }
1926 % \end{macrocode}
1927 %
1928 % Finally we deal with the post-space state. We set a marker so that we
1929 % put in the default space in the pre-space state later too.
1930 %
1931 % \begin{macrocode}
1932 \@namedef{tab@default@6}{%
1933 \tab@append\tab@posttext{\hskip\col@sep}%
1934 \tab@ruletrue%
1935 }
1936 % \end{macrocode}
1937 %
1938 %
1939 % \subsection{Declaring token types}
1940 %
1941 % \begin{macro}{\tab@extracol}
1942 %
1943 % Before we start, we need to handle |\extracolsep|. This is a right pain,
1944 % because the original version of \env{tabular} worked on total expansion,
1945 % which is a Bad Thing. On the other hand, turning |\extracolsep| into a
1946 % |\tabskip| is also a major pain.
1947 %
1948 % \begin{macrocode}
1949 \def\tab@extracol#1#2{\tab@extracol@i#1#2\extracolsep{}\extracolsep\end}
1950 \def\tab@extracol@i#1#2\extracolsep#3#4\extracolsep#5\end{%
1951 \ifx @#3@%
1952 \def\@tempa{#1{#2}}%
1953 \else%
1954 \def\@tempa{#1{#2\tabskip#3\relax#4}}%
1955 \fi%
1956 \@tempa%
1957 }
1958 % \end{macrocode}
1959 %
1960 % \end{macro}
1961 %
1962 % This is where we do the work for inserting preamble elements.
1963 %
1964 % \begin{macro}{\tabruletype}
1965 %
1966 % Inserting rules is interesting, because we have to decide where to put
1967 % them. If this is the funny initial rule, it goes in the pre-text list,
1968 % otherwise it goes in the post-text list. We work out what to do first
1969 % thing:
1970 %
1971 % \begin{macrocode}
1972 \def\tabruletype#1{\tab@extracol\tabruletype@i{#1}}%
1973 \def\tabruletype@i#1{%
1974 \iftab@initrule%
1975 \let\tab@tok\tab@pretext%
1976 \else%
1977 \let\tab@tok\tab@posttext%
1978 \fi%
1979 % \end{macrocode}
1980 %
1981 % Now if we're already in the rule state, we must have just done a rule.
1982 % This means we must put in the |\doublerulesep| space, both here and in the
1983 % shortline list. Otherwise we just stick the rule in.
1984 %
1985 % This is complicated, because |\vgap| needs to be able to remove some bits
1986 % of rule. We pass each one to a macro |\tab@ckr|, together with the column
1987 % number, which is carefully bumped at the right times, and this macro will
1988 % vet the rules and output the appropriate ones. There's lots of extreme
1989 % |\expandafter| nastiness as a result. Amazingly, this actually works.
1990 %
1991 % \begin{macrocode}
1992 \ifnum\tab@state=\tab@rulestate%
1993 \tab@append\tab@tok{\hskip\doublerulesep\begingroup#1\endgroup}%
1994 \expandafter\tab@append\expandafter\tab@shortline\expandafter{%
1995 \expandafter\hskip\expandafter\doublerulesep%
1996 \expandafter\tab@ckr\expandafter{\the\tab@columns}%
1997 {\begingroup#1\endgroup}%
1998 }%
1999 \else%
2000 \tab@setstate\tab@rulestate%
2001 \tab@append\tab@tok{\begingroup#1\endgroup}%
2002 \expandafter\tab@append\expandafter\tab@shortline\expandafter{%
2003 \expandafter\tab@ckr\expandafter{\the\tab@columns}%
2004 {\begingroup#1\endgroup}%
2005 }%
2006 \fi%
2007 % \end{macrocode}
2008 %
2009 % Finally, we say there was a rule here, so that default space gets put in
2010 % after this. Otherwise we lose lots of generality.
2011 %
2012 % \begin{macrocode}
2013 \tab@ruletrue%
2014 }
2015 % \end{macrocode}
2016 %
2017 % \end{macro}
2018 %
2019 % \begin{macro}{\tabspctype}
2020 %
2021 % We need to work out which space-state we should be in. Then we just put
2022 % the text in. Easy, really.
2023 %
2024 % \begin{macrocode}
2025 \def\tabspctype#1{\tab@extracol\tabspctype@i{#1}}%
2026 \def\tabspctype@i#1{%
2027 \tab@rulefalse%
2028 \ifnum\tab@state>\tab@prespcstate%
2029 \tab@setstate\tab@postspcstate%
2030 \let\tab@tok\tab@posttext%
2031 \else%
2032 \tab@setstate\tab@prespcstate%
2033 \let\tab@tok\tab@pretext%
2034 \fi%
2035 \tab@append\tab@tok{\begingroup#1\endgroup}%
2036 }
2037 % \end{macrocode}
2038 %
2039 % \end{macro}
2040 %
2041 % \begin{macro}{\tabcoltype}
2042 %
2043 % If we're already in the column state, we bump the state and loop round
2044 % again, to get all the appropriate default behaviour. We bump the column
2045 % counter, and add the bits of text we were given to appropriate token lists.
2046 % We also add the |\hfil| glue to the shortline list, to space out the rules
2047 % properly.
2048 %
2049 % \begin{macrocode}
2050 \def\tabcoltype#1#2{%
2051 \ifnum\tab@state=\tab@colstate%
2052 \global\advance\tab@state\@ne%
2053 \fi%
2054 \advance\tab@columns\@ne%
2055 \tab@setstate\tab@colstate%
2056 \tab@append\tab@pretext{#1}%
2057 \tab@append\tab@posttext{#2}%
2058 \tab@append\tab@shortline{\hfil}%
2059 }
2060 % \end{macrocode}
2061 %
2062 % \end{macro}
2063 %
2064 % \begin{macro}{\tabuserpretype}
2065 % \begin{macro}{\tabuserposttype}
2066 %
2067 % These are both utterly trivial.
2068 %
2069 % \begin{macrocode}
2070 \def\tabuserpretype#1{%
2071 \tab@setstate\tab@prestate%
2072 \tab@prepend\tab@userpretext{#1}%
2073 }
2074 % \end{macrocode}
2075 %
2076 % \begin{macrocode}
2077 \def\tabuserposttype#1{%
2078 \tab@setstate\tab@poststate%
2079 \tab@prepend\tab@posttext{#1}%
2080 }
2081 % \end{macrocode}
2082 %
2083 % \end{macro}
2084 % \end{macro}
2085 %
2086 %
2087 % \subsection{The colset stack}
2088 %
2089 % Let's start with something fairly easy. We'll keep a stack of column sets
2090 % so that users don't get confused by package authors changing the current
2091 % column set. This is fairly easy, really.
2092 %
2093 % \begin{macro}{\tab@push}
2094 % \begin{macro}{\tab@pop}
2095 % \begin{macro}{\tab@head}
2096 %
2097 % These are the stack management routines. The only important thing to note
2098 % is that |\tab@head| must take place \emph{only} in \TeX's mouth, so we can
2099 % use it in |\csname|\dots|\endcsname| constructions.
2100 %
2101 % \begin{macrocode}
2102 \def\tab@push#1#2{%
2103 \toks@{{#2}}%
2104 \expandafter\def\expandafter#1\expandafter{\the\expandafter\toks@#1}%
2105 }
2106 \def\tab@pop#1{\edef#1{\expandafter\@gobble#1}}
2107 \def\tab@head#1{\expandafter\tab@head@i#1\relax}
2108 \def\tab@head@i#1#2\relax{#1}
2109 % \end{macrocode}
2110 %
2111 % \end{macro}
2112 % \end{macro}
2113 % \end{macro}
2114 %
2115 % \begin{macro}{\colset}
2116 % \begin{macro}{\colpush}
2117 % \begin{macro}{\colpop}
2118 %
2119 % Now we can define the user macros.
2120 %
2121 % \begin{macrocode}
2122 \def\tab@colstack{{tabular}}
2123 \def\colset{\colpop\colpush}
2124 \def\colpush{\tab@push\tab@colstack}
2125 \def\colpop{\tab@pop\tab@colstack}
2126 % \end{macrocode}
2127 %
2128 % \end{macro}
2129 % \end{macro}
2130 % \end{macro}
2131 %
2132 % \begin{macro}{\tab@colset}
2133 %
2134 % Now we define a shortcut for reading the top item off the stack.
2135 %
2136 % \begin{macrocode}
2137 \def\tab@colset{\tab@head\tab@colstack}
2138 % \end{macrocode}
2139 %
2140 % \end{macro}
2141 %
2142 %
2143 % \subsection{The main parser routine}
2144 %
2145 % \begin{macro}{\tab@initread}
2146 %
2147 % This macro sets up lots of variables to their normal states prior to
2148 % parsing a preamble. Some things may need changing, but not many.
2149 %
2150 % \begin{macrocode}
2151 \def\tab@initread{%
2152 % \end{macrocode}
2153 %
2154 % First, reset the parser state to the start state.
2155 %
2156 % \begin{macrocode}
2157 \global\tab@state\tab@startstate%
2158 % \end{macrocode}
2159 %
2160 % We clear the token lists to sensible values, mostly. The midtext macro
2161 % contains what to put in the very middle of each template -- |\multicolumn|
2162 % will insert its argument here.
2163 %
2164 % \begin{macrocode}
2165 \tab@preamble{}%
2166 \tab@shortline{}%
2167 \def\tab@tabtext{&}%
2168 \def\tab@midtext{\ignorespaces####\@maybe@unskip}%
2169 \tab@pretext{}%
2170 \tab@userpretext{}%
2171 \tab@posttext{}%
2172 \let\tab@multicol\@empty%
2173 \def\tab@startpause{\penalty\postdisplaypenalty\medskip}%
2174 \def\tab@endpause{\penalty\predisplaypenalty\medskip}%
2175 % \end{macrocode}
2176 %
2177 % Finally, reset the column counter, don't raise errors when we loop, and set
2178 % some parser flags to their appropriate values.
2179 %
2180 % \begin{macrocode}
2181 \tab@columns\z@%
2182 \let\tab@looped\relax%
2183 \tab@ruletrue%
2184 \tab@initruletrue%
2185 \tab@firstcoltrue%
2186 }
2187 % \end{macrocode}
2188 %
2189 % \end{macro}
2190 %
2191 % \begin{macro}{\tab@readpreamble}
2192 %
2193 % This is the main macro for preamble handling. Actually, all it does is
2194 % gobble its argument's leading brace and call another macro, but it does it
2195 % with style.
2196 %
2197 % \begin{macrocode}
2198 \def\tab@readpreamble#1{%
2199 \tab@doreadpream{#1}%
2200 \iftab@initrule\global\tab@state\tab@prespcstate\fi%
2201 \tab@setstate\tab@rulestate%
2202 \tab@commit%
2203 }
2204 % \end{macrocode}
2205 %
2206 % \end{macro}
2207 %
2208 % \begin{macro}{\tab@doreadpream}
2209 %
2210 % The preamble is in an argument. Previous versions used a nasty trick using
2211 % |\let| and |\afterassignment|. Now we use an explicit end token, to allow
2212 % dodgy column type handlers to scoop up the remaining preamble tokens
2213 % and process them. Not that anyone would want to do that, oh no (see
2214 % the \lit{[} type in the \env{eqnarray} environment |;-)|).
2215 %
2216 % \begin{macrocode}
2217 \def\tab@doreadpream#1{\tab@mkpreamble#1\q@delim}
2218 % \end{macrocode}
2219 %
2220 % \end{macro}
2221 %
2222 % \begin{macro}{\tab@mkpreamble}
2223 %
2224 % This is the main parser routine. It takes each token in turn, scrutinises
2225 % it carefully, and does the appropriate thing with it.
2226 %
2227 % The preamble was given as an argument to |\tab@doreadpream|, and that has
2228 % helpfully stripped off the initial |{| character. We need to pick off the
2229 % next token (whatever it is) so we can examine it. We'll use |\futurelet|
2230 % so we can detect groups and things in funny places.
2231 %
2232 % \begin{macrocode}
2233 \def\tab@mkpreamble{\futurelet\@let@token\tab@mkpreamble@i}
2234 % \end{macrocode}
2235 %
2236 % If we find a space token, we'll go off and do something a bit special,
2237 % since spaces are sort of hard to handle. Otherwise we'll do it in the old
2238 % fashioned way.
2239 %
2240 % \begin{macrocode}
2241 \def\tab@mkpreamble@i{%
2242 \ifx\@let@token\@sptoken%
2243 \expandafter\tab@mkpreamble@spc%
2244 \else%
2245 \expandafter\tab@mkpreamble@ii%
2246 \fi%
2247 }
2248 % \end{macrocode}
2249 %
2250 % If we find a |\@@endpreamble| token, that's it and we're finished. We just
2251 % gobble it and return. Otherwise, if it's an open group character, we'll
2252 % complain because someone's probably tried to put an argument in the wrong
2253 % place. Finally, if none of the other things apply, we'll deal with the
2254 % character below.
2255 %
2256 % \begin{macrocode}
2257 \def\tab@mkpreamble@ii{%
2258 \ifx\@let@token\q@delim%
2259 \def\@tempa{\let\@let@token}%
2260 \else%
2261 \ifcat\bgroup\noexpand\@let@token%
2262 \tab@err@oddgroup%
2263 \def\@tempa##1{\tab@mkpreamble}%
2264 \else%
2265 \let\@tempa\tab@mkpreamble@iii%
2266 \fi%
2267 \fi%
2268 \@tempa%
2269 }
2270 % \end{macrocode}
2271 %
2272 % Handle a character. This involves checking to see if it's actually
2273 % defined, and then doing it. Doing things this way means we won't get
2274 % stranded in mid-preamble unless a package author has blown it.
2275 %
2276 % \begin{macrocode}
2277 \def\tab@mkpreamble@iii#1{%
2278 \@ifundefined{\tab@colset!col.\string#1}{%
2279 \tab@err@undef{#1}\tab@mkpreamble%
2280 }{%
2281 \@nameuse{\tab@colset!col.\string#1}%
2282 }%
2283 }
2284 % \end{macrocode}
2285 %
2286 % If we get given a space character, we'll look up the command name as
2287 % before. If no-one's defined the column type we'll just skip it silently,
2288 % which lets users do pretty formatting if they like.
2289 %
2290 % \begin{macrocode}
2291 \@namedef{tab@mkpreamble@spc} {%
2292 \@ifundefined{\tab@colset!col. }{%
2293 \tab@mkpreamble%
2294 }{%
2295 \@nameuse{\tab@colset!col. }%
2296 }%
2297 }
2298 % \end{macrocode}
2299 %
2300 % \end{macro}
2301 %
2302 % \begin{macro}{\coldef}
2303 %
2304 % Here's how to define column types the nice way. Some dexterity is required
2305 % to make everything work right, but it's simple really.
2306 %
2307 % \begin{macrocode}
2308 \def\coldef{\@ifnextchar[\coldef@i{\coldef@i[\tab@colset]}}
2309 \def\coldef@i[#1]#2#3#{\coldef@ii[#1]{#2}{#3}}
2310 \def\coldef@ii[#1]#2#3#4{%
2311 \expandafter\def\csname#1!col.\string#2\endcsname#3{%
2312 #4\tab@mkpreamble%
2313 }%
2314 }
2315 % \end{macrocode}
2316 %
2317 % \end{macro}
2318 %
2319 % \begin{macro}{\collet}
2320 %
2321 % We'd like to let people copy column types from other places. This is how
2322 % to do it.
2323 %
2324 % \begin{macrocode}
2325 \def\collet{\@ifnextchar[\collet@i{\collet@i[\tab@colset]}}
2326 \def\collet@i[#1]#2{%
2327 \@ifnextchar=%
2328 {\collet@ii[#1]{#2}}%
2329 {\collet@ii[#1]{#2}=}%
2330 }
2331 \def\collet@ii[#1]#2={%
2332 \@ifnextchar[%
2333 {\collet@iii[#1]{#2}}%
2334 {\collet@iii[#1]{#2}[\tab@colset]}%
2335 }
2336 \def\collet@iii[#1]#2[#3]#4{%
2337 \expandafter\let\csname#1!col.\string#2\expandafter\endcsname%
2338 \csname#3!col.\string#4\endcsname%
2339 }
2340 % \end{macrocode}
2341 %
2342 % \end{macro}
2343 %
2344 % \begin{macro}{\newcolumntype}
2345 %
2346 % We just bundle the text off to |\newcommand| and expect it to cope. It
2347 % ought to. The column type code inserts the user's tokens directly, rather
2348 % than calling |\tab@doreadpream| recursively. The magic control sequence
2349 % is the one looked up by the parser.
2350 %
2351 % There's some additional magic here for compatibility with the obscure way
2352 % that \package{array} works.
2353 %
2354 % \begin{macrocode}
2355 \def\newcolumntype#1{\@ifnextchar[{\nct@i{#1}}{\nct@i#1[0]}}
2356 \def\nct@i#1[#2]{\@ifnextchar[{\nct@ii{#1}[#2]}{\nct@iii{#1}{[#2]}}}
2357 \def\nct@ii#1[#2][#3]{\nct@iii{#1}{[#2][#3]}}
2358 \def\nct@iii#1#2#3{%
2359 \expandafter\let\csname\tab@colset!col.\string#1\endcsname\relax%
2360 \expandafter\newcommand\csname\tab@colset!col.\string#1\endcsname#2{%
2361 \tab@deepmagic{#1}%
2362 \tab@mkpreamble%
2363 #3%
2364 }%
2365 }
2366 % \end{macrocode}
2367 %
2368 % Now for some hacking for compatibility with \package{tabularx}.
2369 %
2370 % \begin{macrocode}
2371 \def\newcol@#1[#2]{\nct@iii{#1}{[#2]}}
2372 % \end{macrocode}
2373 %
2374 % And now some more. This is seriously deep magic. Hence the name.
2375 %
2376 % \begin{macrocode}
2377 \def\tab@deepmagic#1{%
2378 \csname NC@rewrite@\string#1\endcsname\NC@find\tab@@magic@@%
2379 }
2380 \def\NC@find#1\tab@@magic@@{}
2381 % \end{macrocode}
2382 %
2383 % \end{macro}
2384 %
2385 %
2386 % \subsection{Standard column types}
2387 %
2388 % First, make sure we're setting up the right columns. This also sets the
2389 % default for the user. Other packages must not use the |\colset| command
2390 % for defining columns -- they should use the stack operations defined above.
2391 %
2392 % \begin{macrocode}
2393 \colset{tabular}
2394 % \end{macrocode}
2395 %
2396 % Now do the simple alignment types. These are fairly simple. The
2397 % mysterious kern in the \lit{l} type is to stop the |\col@sep| glue from
2398 % vanishing due to the |\unskip| inserted by the standard |\tab@midtext| if
2399 % the column contains no text. (Thanks for spotting this bug go to that
2400 % nice Mr~Carlisle.)
2401 %
2402 % \begin{macrocode}
2403 \coldef l{\tabcoltype{\kern\z@\tab@bgroup}{\tab@egroup\hfil}}
2404 \coldef c{\tabcoltype{\hfil\tab@bgroup}{\tab@egroup\hfil}}
2405 \coldef r{\tabcoltype{\hfil\tab@bgroup}{\tab@egroup}}
2406 % \end{macrocode}
2407 %
2408 % Some extensions now. These are explicitly textual or mathematical
2409 % columns. Can be useful if you're providing column types for other people.
2410 % I've inserted a kern here for exactly the same reason as for the \lit{l}
2411 % column type above.
2412 %
2413 % \begin{macrocode}
2414 \coldef T#1{\tab@aligncol{#1}{\tab@btext}{\tab@etext}}
2415 \coldef M#1{\tab@aligncol{#1}{\tab@bmaths}{\tab@emaths}}
2416 \def\tab@aligncol#1#2#3{%
2417 \if#1l\tabcoltype{\kern\z@#2}{#3\hfil}\fi%
2418 \if#1c\tabcoltype{\hfil#2}{#3\hfil}\fi%
2419 \if#1r\tabcoltype{\hfil#2}{#3}\fi%
2420 }
2421 % \end{macrocode}
2422 %
2423 % Now for the default rules.
2424 %
2425 % \begin{macrocode}
2426 \coldef ${\expandafter\tab@rulewd\expandafter\tab@vrule\@gobble}
2427 \def\tab@vrule{%
2428 \expandafter\tabruletype\expandafter{%
2429 \expandafter\vrule\expandafter\@width\the\tab@rulewidth%
2430 }%
2431 \tab@mkpreamble%
2432 }
2433 \coldef |{\tabruletype{\vrule\@width\arrayrulewidth}}
2434 \coldef !#1{\tabruletype{#1}}
2435 % \end{macrocode}
2436 %
2437 % Deal with \lit{@} expressions.
2438 %
2439 % \begin{macrocode}
2440 \coldef @#1{\tabspctype{#1}}
2441 % \end{macrocode}
2442 %
2443 % And the paragraph types. I've added things to handle footnotes here.
2444 %
2445 % \begin{macrocode}
2446 \coldef p#1{\tabcoltype%
2447 {\savenotes\vtop\tab@bpar{#1}}%
2448 {\tab@epar\spewnotes\hfil}}
2449 \coldef m#1{\tabcoltype%
2450 {\savenotes$\vcenter\tab@bpar{#1}}%
2451 {\tab@epar$\spewnotes\hfil}}
2452 \coldef b#1{\tabcoltype%
2453 {\savenotes\vbox\tab@bpar{#1}}%
2454 {\tab@epar\spewnotes\hfil}}
2455 % \end{macrocode}
2456 %
2457 % Phew. Only a few more left now. The user text ones.
2458 %
2459 % \begin{macrocode}
2460 \coldef >#1{\tabuserpretype{#1}}
2461 \coldef <#1{\tabuserposttype{#1}}
2462 % \end{macrocode}
2463 %
2464 % The strange column type.
2465 %
2466 % \begin{macrocode}
2467 \coldef ##1#2{\tabcoltype{#1}{#2}}
2468 % \end{macrocode}
2469 %
2470 % And \lit{*}, which repeats a preamble spec. This is really easy, and not
2471 % at all like the original one.
2472 %
2473 % \begin{macrocode}
2474 \coldef *#1#2{%
2475 \count@#1%
2476 \loop\ifnum\count@>0\relax%
2477 \tab@doreadpream{#2}%
2478 \advance\count@\m@ne%
2479 \repeat%
2480 }
2481 % \end{macrocode}
2482 %
2483 %
2484 % \subsection{Paragraph handling}
2485 %
2486 % First of all, starting new paragraphs: the vbox token is already there, and
2487 % we have the width as an argument.
2488 %
2489 % \begin{macro}{\tab@bpar}
2490 %
2491 % There are some gymnastics to do here to support lists which form the
2492 % complete text of the parbox. One of the odd things I'll do here is to
2493 % not insert a strut on the first line: instead, I'll put the text into a
2494 % box register so that I can inspect it later. So that I have access to
2495 % the height of the first line, I'll use a |\vtop| -- I can get at the
2496 % final depth by using |\prevdepth|, so this seems to be the most general
2497 % solution.
2498 %
2499 % \begin{macrocode}
2500 \def\tab@bpar#1{%
2501 \bgroup%
2502 \setlength\hsize{#1}%
2503 \@arrayparboxrestore%
2504 \setbox\z@\vtop\bgroup%
2505 \global\@minipagetrue%
2506 \global\@noskipsecfalse%
2507 \everypar\expandafter{\the\everypar%
2508 \global\@minipagefalse%
2509 \everypar{}%
2510 }%
2511 }
2512 % \end{macrocode}
2513 %
2514 % \end{macro}
2515 %
2516 % \begin{macro}{\tab@epar}
2517 %
2518 % To end the paragraph, close the box. That sounds easy, doesn't it?
2519 % I need to space out the top and bottom of the box so that it looks as if
2520 % struts have been applied.
2521 %
2522 % \begin{macrocode}
2523 \def\tab@epar{%
2524 % \end{macrocode}
2525 %
2526 % Anyway, I should end the current paragraph if I'm still in horizontal
2527 % mode. A simple |\par| will do this nicely. I'll also remove any trailing
2528 % vertical glue (which may be left there by a list environment), because
2529 % things will look very strange otherwise.
2530 %
2531 % \begin{macrocode}
2532 \ifhmode\@maybe@unskip\par\fi%
2533 \unskip%
2534 % \end{macrocode}
2535 %
2536 % Now I'll look at the depth of the last box: if it's less deep than my
2537 % special strut, I'll cunningly backpedal by a bit, and add a box with the
2538 % appropriate depth. Since this will lie on the previous baseline, it won't
2539 % alter the effective height of the box. There's a snag here. |\prevdepth|
2540 % may be wrong for example if the last thing inserted was a rule, or the
2541 % box is just empty. Check for this specially. (Thanks to Rowland for
2542 % spotting this.)
2543 %
2544 % \begin{macrocode}
2545 \ifdim\prevdepth>-\@m\p@\ifdim\prevdepth<\dp\@arstrutbox%
2546 \kern-\prevdepth%
2547 \nointerlineskip%
2548 \vtop to\dp\@arstrutbox{}%
2549 \fi\fi%
2550 % \end{macrocode}
2551 %
2552 % I've finished the bottom of the box now: I'll close it, and start work on
2553 % the top again.
2554 %
2555 % \begin{macrocode}
2556 \egroup%
2557 % \end{macrocode}
2558 %
2559 % For top-alignment to work, the first item in the box must be another box.
2560 % (This is why I couldn't just set |\prevdepth| at the beginning.) If the
2561 % box isn't high enough, I'll add a box of the right height and then kern
2562 % backwards so that the `real' first box ends up in the right place.
2563 %
2564 % \begin{macrocode}
2565 \ifdim\ht\z@<\ht\@arstrutbox%
2566 \vbox to\ht\@arstrutbox{}%
2567 \kern-\ht\z@%
2568 \fi%
2569 \unvbox\z@%
2570 \egroup%
2571 }
2572 % \end{macrocode}
2573 %
2574 % \end{macro}
2575 %
2576 %
2577 % \subsection{Gentle persuasion}
2578 %
2579 % To persuade \package{longtable} to work, we emulate some features of
2580 % the \package{array} way of doing things. It's a shame, but we have to do
2581 % it, because \package{longtable} came first.
2582 %
2583 % Note the horribleness with the grouping here. In order to get everything
2584 % expanded at the right time, |\@preamble| just replaces itself with the (not
2585 % expanded!) preamble string, using |\the|. This means that the preamble
2586 % string must be visible in the group just above us. Now,
2587 % \package{longtable} (and \package{array} for that matter) does
2588 % |\@mkpreamble| immediately after opening a new group. So all we need to do
2589 % is close that group, do our stuff, and reopen the group again. (Evil
2590 % laughter\dots)
2591 %
2592 % \begin{macrocode}
2593 \def\@mkpream#1{%
2594 \endgroup%
2595 \colset{tabular}%
2596 \tab@initread%
2597 \def\tab@multicol{\@arstrut}%
2598 \tab@preamble{\tab@multicol}%
2599 \def\tab@midtext{\ignorespaces\@sharp\@sharp\@maybe@unskip}%
2600 \tab@readpreamble{#1}%
2601 \gdef\@preamble{\the\tab@preamble}%
2602 \let\tab@bgroup\begingroup%
2603 \let\tab@egroup\endgroup%
2604 \begingroup%
2605 }
2606 % \end{macrocode}
2607 %
2608 %
2609 % \subsection{Debugging}
2610 %
2611 % This macro just parses a preamble and displays it on the terminal. It
2612 % means I can see whether the thing's working.
2613 %
2614 % \begin{macrocode}
2615 \def\showpream#1{%
2616 \tab@initread%
2617 \tab@readpreamble{#1}%
2618 \showthe\tab@preamble%
2619 \showthe\tab@shortline%
2620 }
2621 % \end{macrocode}
2622 %
2623 % A quick macro for showing column types.
2624 %
2625 % \begin{macrocode}
2626 \def\showcol#1{%
2627 \expandafter\show\csname\tab@colset!col.\string#1\endcsname%
2628 }
2629 % \end{macrocode}
2630 %
2631 %
2632 % \subsection{The \env{tabular} and \env{array} environments}
2633 %
2634 % This is where we define the actual environments which users play with.
2635 %
2636 % \subsubsection{The environment routines}
2637 %
2638 % The real work is done in the |\@array| macro later. We just set up lots
2639 % (and I mean \emph{lots}) of parameters first, and then call |\@array|.
2640 %
2641 % \begin{macro}{\tab@array}
2642 %
2643 % The |\tab@array| macro does most of the common array things.
2644 %
2645 % \begin{macrocode}
2646 \def\tab@array{%
2647 \tab@width\z@%
2648 \let\tab@bgroup\tab@bmaths%
2649 \let\tab@egroup\tab@emaths%
2650 \@tabarray%
2651 }
2652 % \end{macrocode}
2653 %
2654 % \end{macro}
2655 %
2656 % \begin{macro}{\tab@btext}
2657 % \begin{macro}{\tab@bmaths}
2658 % \begin{macro}{\tab@etext}
2659 % \begin{macro}{\tab@emaths}
2660 %
2661 % These macros contain appropriate things to use when typesetting
2662 % text or maths macros. They're all trivial. They're here only for
2663 % later modification by funny things like the \env{smarray} environment.
2664 %
2665 % \begin{macrocode}
2666 \def\tab@btext{\begingroup}
2667 \def\tab@bmaths{$}
2668 \def\tab@etext{\endgroup}
2669 \def\tab@emaths{\m@th$}
2670 % \end{macrocode}
2671 %
2672 % \end{macro}
2673 % \end{macro}
2674 % \end{macro}
2675 % \end{macro}
2676 %
2677 % \begin{environment}{array}
2678 %
2679 % Now for the \env{array} environment. The `|$|' signs act as a group, so we
2680 % don't need to do extra grouping this time. Closing the environment is
2681 % easy.
2682 %
2683 % \begin{macrocode}
2684 \def\array{%
2685 \col@sep\arraycolsep%
2686 \let\tab@extrasep\arrayextrasep%
2687 \tab@normalstrut%
2688 \tab@array%
2689 }
2690 \def\endarray{%
2691 \crcr%
2692 \egroup%
2693 \tab@right%
2694 \tab@restorehlstate%
2695 }
2696 % \end{macrocode}
2697 %
2698 % \end{environment}
2699 %
2700 % \begin{environment}{smarray}
2701 %
2702 % Now for something a little different. The \env{smarray} environment
2703 % gives you an array with lots of small text.
2704 %
2705 % \begin{macrocode}
2706 \def\smarray{%
2707 \extrarowheight\z@%
2708 \col@sep\smarraycolsep%
2709 \let\tab@extrasep\smarrayextrasep%
2710 \def\tab@bmaths{$\scriptstyle}%
2711 \def\tab@btext{\begingroup\scriptsize}%
2712 \setbox\z@\hbox{\scriptsize\strut}%
2713 \dimen@\ht\z@\dimen@ii\dp\z@\tab@setstrut%
2714 \tab@array%
2715 }
2716 \let\endsmarray\endarray
2717 % \end{macrocode}
2718 %
2719 % \end{environment}
2720 %
2721 % \begin{macro}{\tabstyle}
2722 %
2723 % This is a little hook that document designers can use to modify the
2724 % appearance of tables throughout a document. For example, I've set it to
2725 % make the text size |\small| in all tables in this document. Macro writers
2726 % shouldn't try to use it as a hook for their own evilness, though. I've
2727 % used |\providecommand| to avoid nobbling an existing definition.
2728 %
2729 % \begin{macrocode}
2730 \providecommand\tabstyle{}
2731 % \end{macrocode}
2732 %
2733 % \end{macro}
2734 %
2735 % \begin{macro}{\@tabular}
2736 %
2737 % The two \env{tabular} environments share lots of common code, so we
2738 % separate that out. (This needs to be done better.) All we really do here
2739 % is set up the |\tab@bgroup| and |\tab@egroup| to localise things properly,
2740 % and then go.
2741 %
2742 % \begin{macrocode}
2743 \def\@tabular#1{%
2744 \tabstyle%
2745 \setlength\tab@width{#1}%
2746 \let\tab@bgroup\tab@btext%
2747 \let\tab@egroup\tab@etext%
2748 \col@sep\tabcolsep%
2749 \let\tab@extrasep\tabextrasep%
2750 \tab@normalstrut%
2751 \@tabarray%
2752 }
2753 % \end{macrocode}
2754 %
2755 % \end{macro}
2756 %
2757 % \begin{environment}{tabular}
2758 % \begin{environment}{tabular*}
2759 %
2760 % These environments just call a macro which does all the common stuff.
2761 %
2762 % \begin{macrocode}
2763 \def\tabular{\@tabular\z@}
2764 \expandafter\let\csname tabular*\endcsname\@tabular
2765 \let\endtabular\endarray
2766 \expandafter\let\csname endtabular*\endcsname\endarray
2767 % \end{macrocode}
2768 %
2769 % \end{environment}
2770 % \end{environment}
2771 %
2772 % \subsubsection{Setting the strut height}
2773 %
2774 % \begin{macro}{\tab@setstrut}
2775 %
2776 % We use a magical strut, called |\@arstrut|, which keeps the table from
2777 % collapsing around our heads. This is where we set it up.
2778 %
2779 % It bases the array strut size on the given values of |\dimen@| and
2780 % |\dimen@ii|, amended by various appropriate fiddle values added in by
2781 % various people.
2782 %
2783 % \begin{macrocode}
2784 \def\tab@setstrut{%
2785 \setbox\@arstrutbox\hbox{%
2786 \vrule%
2787 \@height\arraystretch\dimen@%
2788 \@depth\arraystretch\dimen@ii%
2789 \@width\z@%
2790 }%
2791 }
2792 % \end{macrocode}
2793 %
2794 % \end{macro}
2795 %
2796 % \begin{macro}{\tab@normalstrut}
2797 %
2798 % This sets the strut the normal way, from the size of |\strutbox|.
2799 %
2800 % \begin{macrocode}
2801 \def\tab@normalstrut{%
2802 \dimen@\ht\strutbox\advance\dimen@\extrarowheight%
2803 \dimen\tw@\dp\strutbox%
2804 \tab@setstrut%
2805 }
2806 % \end{macrocode}
2807 %
2808 % \end{macro}
2809 %
2810 % \subsubsection{Setting up the alignment}
2811 %
2812 % The following bits are mainly for other packages to hook themselves onto.
2813 %
2814 % \begin{macrocode}
2815 \let\@arrayleft\relax%
2816 \let\@arrayright\relax%
2817 % \end{macrocode}
2818 %
2819 % \begin{macrocode}
2820 \def\@tabarray{%
2821 \let\@arrayleft\relax%
2822 \let\@arrayright\relax%
2823 \@ifnextchar[\@array{\@array[c]}%
2824 }
2825 % \end{macrocode}
2826 %
2827 % \begin{macro}{\@array}
2828 %
2829 % The |\@array| macro does most of the real work for the environments. The
2830 % first job is to set up the row strut, which keeps the table rows at the
2831 % right height. We just take the normal strut box, and extend its height by
2832 % the |\extrarowheight| length parameter.
2833 %
2834 % \begin{macrocode}
2835 \def\@array[#1]#2{%
2836 % \end{macrocode}
2837 %
2838 % Sort out the hline state variable. We'll store the old value in a
2839 % control sequence to avoid wasting any more count registers.
2840 %
2841 % \begin{macrocode}
2842 \edef\tab@restorehlstate{%
2843 \global\tab@endheight\the\tab@endheight%
2844 \gdef\noexpand\tab@hlstate{\tab@hlstate}%
2845 }%
2846 \def\tab@hlstate{n}%
2847 % \end{macrocode}
2848 %
2849 % Now we read the preamble. All the clever things we've already done are
2850 % terribly useful here.
2851 %
2852 % The |\tab@setcr| sets up |\\| to be a newline even if users have changed it
2853 % using something like |\raggedright|.
2854 %
2855 % \begin{macrocode}
2856 \colset{tabular}%
2857 \tab@initread%
2858 \def\tab@midtext{\tab@setcr\ignorespaces####\@maybe@unskip}%
2859 \def\tab@multicol{\@arstrut\tab@startrow}%
2860 \tab@preamble{\tab@multicol\tabskip\z@skip}%
2861 \tab@readpreamble{#2}%
2862 % \end{macrocode}
2863 %
2864 % Set up the default tabskip glue. This is easy: there isn't any.
2865 %
2866 % \begin{macrocode}
2867 \tab@leftskip\z@skip%
2868 \tab@rightskip\z@skip%
2869 % \end{macrocode}
2870 %
2871 % Now set up the positioning of the table. This is put into a separate macro
2872 % because it's rather complicated.
2873 %
2874 % \begin{macrocode}
2875 \tab@setposn{#1}%
2876 % \end{macrocode}
2877 %
2878 % Now work out how to start the alignment.
2879 %
2880 % \begin{macrocode}
2881 \ifdim\tab@width=\z@%
2882 \def\tab@halign{}%
2883 \else%
2884 \def\tab@halign{to\tab@width}%
2885 \fi%
2886 % \end{macrocode}
2887 %
2888 % Finally, do all the normal things we need to do before an alignment. Note
2889 % that we define |\tabularnewline| first, then set |\\| from that (using
2890 % |\tab@setcr|). Since |\\| is reset in the |\tab@midtext| of every table
2891 % cell, it becomes secondary to |\tabularnewline|. Doing things this way
2892 % avoids the problems with declarations like |\raggedright| which redefine
2893 % |\\| in their own (usually rather strange) way, so you don't need to mess
2894 % about with things like the |\PreserveBackslash| command given in the
2895 % \textit{\LaTeX\ Companion}.
2896 %
2897 % \begin{macrocode}
2898 \lineskip\z@\baselineskip\z@%
2899 \m@th%
2900 \def\tabularnewline{\tab@arraycr\tab@penalty}%
2901 \tab@setcr%
2902 \let\par\@empty%
2903 \everycr{}\tabskip\tab@leftskip%
2904 \tab@left\halign\tab@halign\expandafter\bgroup%
2905 \the\tab@preamble\tabskip\tab@rightskip\cr%
2906 }
2907 % \end{macrocode}
2908 %
2909 % \end{macro}
2910 %
2911 % You've no doubt noticed the |\tab@left| and |\tab@right| macros above.
2912 % These are set up here and elsewhere to allow other things to gain control
2913 % at various points of the table (they include and take the place of the
2914 % |\@arrayleft| and |\@arrayright| hooks in \package{array}, put in for
2915 % \package{delarray}'s use.
2916 %
2917 % \subsubsection{Positioning the table}
2918 %
2919 % \begin{macro}{\tab@setposn}
2920 %
2921 % This macro sets everything up for the table's positioning. It's rather
2922 % long, but not all that complicated. Honest.
2923 %
2924 % First, we set up some defaults (for centring). If anything goes wrong, we
2925 % just do the centring things.
2926 %
2927 % \begin{macrocode}
2928 \def\tab@setposn#1{%
2929 \def\tab@left{%
2930 \savenotes%
2931 \leavevmode\hbox\bgroup$\@arrayleft\vcenter\bgroup%
2932 }%
2933 \def\tab@right{%
2934 \egroup%
2935 \m@th\@arrayright$\egroup%
2936 \spewnotes%
2937 }%
2938 \global\tab@endheight\z@%
2939 % \end{macrocode}
2940 %
2941 % For the standard positioning things, we just do appropriate boxing things.
2942 % Note that the dollar signs are important, since \package{delarray} might
2943 % want to put its delimiters in here.
2944 %
2945 % The |\if@tempswa| switch it used to decide if we're doing an unboxed
2946 % tabular. We'll set it if we find an unbox-type position code, and then
2947 % check that everything's OK for this.
2948 %
2949 % \begin{macrocode}
2950 \@tempswafalse%
2951 \let\tab@penalty\relax%
2952 \if#1t%
2953 \def\tab@left{%
2954 \savenotes%
2955 \leavevmode\setbox\z@\hbox\bgroup$\@arrayleft\vtop\bgroup%
2956 }%
2957 \def\tab@right{%
2958 \egroup%
2959 \m@th\@arrayright$\egroup%
2960 \tab@raisebase%
2961 \spewnotes%
2962 }%
2963 \gdef\tab@hlstate{t}%
2964 \global\tab@endheight\ht\@arstrutbox%
2965 \else\if#1b%
2966 \def\tab@left{%
2967 \savenotes%
2968 \leavevmode\setbox\z@\hbox\bgroup$\@arrayleft\vbox\bgroup%
2969 }%
2970 \def\tab@right{%
2971 \egroup%
2972 \m@th\@arrayright$\egroup%
2973 \tab@lowerbase%
2974 \spewnotes%
2975 }%
2976 \gdef\tab@hlstate{b}%
2977 \else%
2978 \if#1L\@tempswatrue\fi%
2979 \if#1C\@tempswatrue\fi%
2980 \if#1R\@tempswatrue\fi%
2981 \fi\fi%
2982 % \end{macrocode}
2983 %
2984 % Now for some tests to make sure we're allowed to do the unboxing. We text
2985 % for |\@arrayleft| being defined, because people trying to hook us won't
2986 % understand unboxed tabulars.
2987 %
2988 % \begin{macrocode}
2989 \if@tempswa\ifhmode%
2990 \ifinner\tab@err@unbrh\@tempswafalse\else\par\fi%
2991 \fi\fi%
2992 \if@tempswa\ifmmode\tab@err@unbmm\@tempswafalse\fi\fi%
2993 \if@tempswa\ifx\@arrayleft\relax\else%
2994 \tab@err@unbext\@tempswafalse%
2995 \fi\fi%
2996 % \end{macrocode}
2997 %
2998 % Finally, if we're still doing an unboxed alignment, we need to sort out the
2999 % spacing. We know that no-one's tried to hook on to the environment, so we
3000 % clear |\tab@left| and |\tab@right|.
3001 %
3002 % \begin{macrocode}
3003 \if@tempswa%
3004 \def\tab@left{\vskip\parskip\medskip}%
3005 \def\tab@right{\par\@endpetrue\global\@ignoretrue}%
3006 % \end{macrocode}
3007 %
3008 % Now we need to sort out the alignment. The only way we can do this is by
3009 % playing with tabskip glue. There are two possibilities:
3010 %
3011 % \begin{itemize}
3012 %
3013 % \item If this is a straight \env{tabular} or an \env{array}, we just use
3014 % infinite glue. This is reasonable, I think.
3015 %
3016 % \item If we have a width for the table, we calculate the fixed values of
3017 % glue on either side. This is fairly easy, and forces the table to
3018 % the required width.
3019 %
3020 % \end{itemize}
3021 %
3022 % First, set up the left and right glues to represent the prevailing
3023 % margins set up by \env{list} environments. I think this is the right
3024 % thing to do.
3025 %
3026 % \begin{macrocode}
3027 \tab@leftskip\@totalleftmargin%
3028 \tab@rightskip\hsize%
3029 \advance\tab@rightskip-\linewidth%
3030 \advance\tab@rightskip-\@totalleftmargin%
3031 % \end{macrocode}
3032 %
3033 % First of all, deal with the simple case. I'm using 10000\,fill glue here,
3034 % in an attempt to suppress |\extracolsep| glue from making the table the
3035 % wrong width. It can always use filll glue if it really needs to, though.
3036 %
3037 % \begin{macrocode}
3038 \ifdim\tab@width=\z@%
3039 \if#1L\else\advance\tab@leftskip\z@\@plus10000fill\fi%
3040 \if#1R\else\advance\tab@rightskip\z@\@plus10000fill\fi%
3041 % \end{macrocode}
3042 %
3043 % Now for the fun bit. This isn't too hard really. The extra space I must
3044 % add around the table adds up to $|\linewidth| - |\tab@width|$. I just
3045 % need to add this onto the appropriate sides of the table.
3046 %
3047 % \begin{macrocode}
3048 \else%
3049 \dimen@\linewidth%
3050 \advance\dimen@-\tab@width%
3051 \if#1L\advance\tab@rightskip\dimen@\fi%
3052 \if#1R\advance\tab@leftskip\dimen@\fi%
3053 \if#1C%
3054 \advance\tab@leftskip.5\dimen@%
3055 \advance\tab@rightskip.5\dimen@%
3056 \fi%
3057 \fi%
3058 % \end{macrocode}
3059 %
3060 % Don't allow page breaks. David Carlisle's wonderful \env{longtable}
3061 % package does page breaks far better than I could possibly do here, and
3062 % we're compatible with it (wahey!).
3063 %
3064 % \begin{macrocode}
3065 \def\tab@penalty{\penalty\@M}%
3066 % \end{macrocode}
3067 %
3068 % Finally, set the new width of the table, and leave.
3069 %
3070 % \begin{macrocode}
3071 \tab@width\hsize%
3072 \fi%
3073 }
3074 % \end{macrocode}
3075 %
3076 % \end{macro}
3077 %
3078 % \subsubsection{Handling tops and bottoms}
3079 %
3080 % This is how the tops and bottoms of tables are made to line up with the
3081 % text on the same line, in the presence of arbitrary rules and space. The
3082 % old method, based on the way the \package{array} package worked, wasn't
3083 % terribly good. This new version copes much better with almost anything
3084 % that gets thrown at it.
3085 %
3086 % I'll keep a state in a macro (|\tab@hlstate|), which tells me what I'm
3087 % meant to be doing. The possible values are \lit{n}, which means I don't
3088 % have to do anything, \lit{t}, which means that I'm meant to be handling
3089 % top-aligned tables, and \lit{b}, which means that I'm meant to be lining
3090 % up the bottom. There are several other `substates' which have various
3091 % magic meanings.
3092 %
3093 % \begin{macrocode}
3094 \def\tab@hlstate{n}
3095 % \end{macrocode}
3096 %
3097 % When all's said and done, I extract the box containing the table, and
3098 % play with the height and depth to try and make it correct.
3099 %
3100 % \begin{macro}{\tab@addruleheight}
3101 %
3102 % This macro is called by `inter-row' things to add their height to our
3103 % dimen register.
3104 %
3105 % Only do this if the state indicates that it's sensible.
3106 %
3107 % \begin{macrocode}
3108 \def\tab@addruleheight#1{%
3109 \if\tab@hlstate n\else%
3110 \global\advance\tab@endheight#1\relax%
3111 \fi%
3112 }
3113 % \end{macrocode}
3114 %
3115 % \end{macro}
3116 %
3117 % \begin{macro}{\tab@startrow}
3118 %
3119 % This is called at the start of a row, from within the array preamble.
3120 % Currently, this assumes that the rows aren't bigger than their struts:
3121 % this is reasonable, although slightly limiting, and it could be done better
3122 % if I was willing to rip the alignment apart and put it back together
3123 % again.
3124 %
3125 % \begin{macrocode}
3126 \def\tab@startrow{%
3127 \if\tab@hlstate t%
3128 \gdef\tab@hlstate{n}%
3129 \else\if\tab@hlstate b%
3130 \global\tab@endheight\dp\@arstrutbox%
3131 \fi\fi%
3132 }
3133 % \end{macrocode}
3134 %
3135 % \end{macro}
3136 %
3137 % \begin{macro}{\tab@raisebase}
3138 %
3139 % This macro is called at the end of it all, to set the height and depth
3140 % of the box correctly. It sets the height to |\tab@endheight|, and the
3141 % depth to everything else. The box is in |\box|~0 currently.
3142 %
3143 % \begin{macrocode}
3144 \def\tab@raisebase{%
3145 \global\advance\tab@endheight-\ht\z@%
3146 \raise\tab@endheight\box\z@%
3147 }
3148 % \end{macrocode}
3149 %
3150 % \end{macro}
3151 %
3152 % \begin{macro}{\tab@lowerbase}
3153 %
3154 % And, for symmetry's sake, here's how to set the bottom properly instead.
3155 %
3156 % \begin{macrocode}
3157 \def\tab@lowerbase{%
3158 \global\advance\tab@endheight-\dp\z@%
3159 \lower\tab@endheight\box\z@%
3160 }
3161 % \end{macrocode}
3162 %
3163 % \end{macro}
3164 %
3165 %
3166 % \subsection{Breaking tables into bits}
3167 %
3168 % Unboxed tables have a wonderful advantage over boxed ones: you can stop
3169 % halfway through and do something else for a bit. Here's how:
3170 %
3171 % \begin{macro}{\tabpause}
3172 %
3173 % I'd like to avoid forbidding catcode changes here. I'll use |\doafter|
3174 % now I've got it, to ensure that colour handling and things occur
3175 % \emph{inside} the |\noalign| (otherwise they'll mess up the alignment
3176 % very seriously). We selectively include lots of stuff from
3177 % |\arrayparboxrestore|.
3178 %
3179 % We have to be careful here to ensure that everything works correctly within
3180 % lists. (The \package{amsmath} package had this problem in its
3181 % |\intertext| macro, so I'm not alone here.)
3182 %
3183 % \begin{macrocode}
3184 \def\tabpause#{%
3185 \noalign{\ifnum0=`}\fi%
3186 \let\if@nobreak\iffalse
3187 \let\if@noskipsec\iffalse
3188 \let\par\@@par
3189 \let\-\@dischyph
3190 \let\'\@acci\let\`\@accii\let\=\@acciii
3191 \everypar{}%
3192 \lineskip\normallineskip%
3193 \let\\\@normalcr%
3194 \tab@startpause%
3195 \vskip-\parskip%
3196 \parshape\@ne\@totalleftmargin\linewidth%
3197 \noindent%
3198 \doafter\tabpause@i%
3199 }
3200 \def\tabpause@i{%
3201 \nobreak%
3202 \tab@endpause%
3203 \ifnum0=`{\fi}%
3204 }
3205 % \end{macrocode}
3206 %
3207 % \end{macro}
3208 %
3209 %
3210 % \subsection{The wonderful world of \cmd\multicolumn}
3211 %
3212 % \begin{macro}{\multicolumn}
3213 %
3214 % This is actually fantastically easy. Watch and learn. Make sure you
3215 % notice the |\long|s here: remember that some table cells can contain
3216 % paragraphs, so it seems sensible to allow |\par| into the argument.
3217 % (As far as I know, most other |\multicolumn| commands don't do this,
3218 % which seems a little silly. Then again, I forgot to do it the first
3219 % time around.)
3220 %
3221 % \begin{macrocode}
3222 \long\def\multicolumn#1#2#3{%
3223 \multispan{#1}%
3224 \begingroup%
3225 \tab@multicol%
3226 \tab@initread%
3227 \tab@preamble{}%
3228 \long\def\tab@midtext{#3}%
3229 \let\tab@looped\tab@err@multi%
3230 \tab@readpreamble{#2}%
3231 \the\tab@preamble%
3232 \endgroup%
3233 \ignorespaces%
3234 }
3235 % \end{macrocode}
3236 %
3237 % \end{macro}
3238 %
3239 %
3240 % \subsection{Interlude: range lists}
3241 %
3242 % For processing arguments to |\vgap| and |\cline|, we need to be able to
3243 % do things with lists of column ranges. To save space, and to make my
3244 % fingers do less typing, here's some routines which do range handling.
3245 %
3246 % \begin{macro}{\ranges}
3247 %
3248 % Given a macro name and a comma separated list of ranges and simple numbers,
3249 % this macro will call the macro giving it each range in the list in turn.
3250 % Single numbers~$n$ will be turned into ranges $n$--$n$.
3251 %
3252 % The first job is to read the macro to do (which may already have some
3253 % arguments attached to it). We'll also start a group to make sure that
3254 % our changes to temp registers don't affect anyone else.
3255 %
3256 % There's a space before the delimiting |\q@delim| to stop numbers being
3257 % parsed to far and expanding our quark (which will stop \TeX\ dead in its
3258 % tracks). Since we use |\@ifnextchar| to look ahead, spaces in range lists
3259 % are perfectly all right.
3260 %
3261 % \begin{macrocode}
3262 \def\ranges#1#2{%
3263 \gdef\ranges@temp{#1}%
3264 \begingroup%
3265 \ranges@i#2 \q@delim%
3266 }
3267 % \end{macrocode}
3268 %
3269 %
3270 % We're at the beginning of the list. We expect either the closing marker
3271 % (if this is an empty list) or a number, which we can scoop up into a
3272 % scratch register.
3273 %
3274 % \begin{macrocode}
3275 \def\ranges@i{%
3276 \@ifnextchar\q@delim\ranges@done{\afterassignment\ranges@ii\count@}%
3277 }
3278 % \end{macrocode}
3279 %
3280 % We've read the first number in the range. If there's another number, we'll
3281 % expect a `|-|' sign to be next. If there is no `|-|', call the user's code
3282 % with the number duplicated and then do the rest of the list.
3283 %
3284 % \begin{macrocode}
3285 \def\ranges@ii{%
3286 \@ifnextchar-\ranges@iii{\ranges@do\count@\count@\ranges@v}%
3287 }
3288 % \end{macrocode}
3289 %
3290 % Now we strip the `|-|' off and read the other number into a temporary
3291 % register.
3292 %
3293 % \begin{macrocode}
3294 \def\ranges@iii-{\afterassignment\ranges@iv\@tempcnta}
3295 % \end{macrocode}
3296 %
3297 % We have both ends of the range now, so call the user's code, passing it
3298 % both ends of the range.
3299 %
3300 % \begin{macrocode}
3301 \def\ranges@iv{\ranges@do\count@\@tempcnta\ranges@v}
3302 % \end{macrocode}
3303 %
3304 % We've finished doing an item now. If we have a `|,|' next, then start
3305 % over with the next item. Otherwise, if we're at the end of the list,
3306 % we can end happily. Finally, if we're totally confused, raise an
3307 % error.
3308 %
3309 % \begin{macrocode}
3310 \def\ranges@v{%
3311 \@ifnextchar,%
3312 \ranges@vi%
3313 {%
3314 \@ifnextchar\q@delim%
3315 \ranges@done%
3316 {\tab@err@range\ranges@vi,}%
3317 }%
3318 }
3319 % \end{macrocode}
3320 %
3321 % We had a comma, so gobble it, read the next number, and go round again.
3322 %
3323 % \begin{macrocode}
3324 \def\ranges@vi,{\afterassignment\ranges@ii\count@}
3325 % \end{macrocode}
3326 %
3327 % Here's how we call the user's code, now. We close the group, so that the
3328 % user's code doesn't have to do global things to remember its results, and
3329 % we expand the two range ends from their count registers. We also ensure
3330 % that the range is the right way round.
3331 %
3332 % \begin{macrocode}
3333 \def\ranges@do#1#2{%
3334 \ifnum#1>#2\else%
3335 \expandafter\endgroup%
3336 \expandafter\ranges@temp%
3337 \expandafter{%
3338 \the\expandafter#1%
3339 \expandafter}%
3340 \expandafter{%
3341 \the#2%
3342 }%
3343 \begingroup%
3344 \fi%
3345 }
3346 % \end{macrocode}
3347 %
3348 % And finishing the scan is really easy. We close the group after gobbling
3349 % the close token.
3350 %
3351 % \begin{macrocode}
3352 \def\ranges@done\q@delim{\endgroup}
3353 % \end{macrocode}
3354 %
3355 % \end{macro}
3356 %
3357 % \begin{macro}{\ifinrange}
3358 %
3359 % Something a little more useful, now. |\ifinrange| takes four arguments:
3360 % a number, a range list (as above), and two token lists which I'll call
3361 % \emph{then} and \emph{else}. If the number is in the list, I'll do
3362 % \emph{then}, otherwise I'll do \emph{else}.
3363 %
3364 % \begin{macrocode}
3365 \def\ifinrange#1#2{%
3366 \@tempswafalse%
3367 \count@#1%
3368 \ranges\ifinrange@i{#2}%
3369 \if@tempswa%
3370 \expandafter\@firstoftwo%
3371 \else%
3372 \expandafter\@secondoftwo%
3373 \fi%
3374 }
3375 \def\ifinrange@i#1#2{%
3376 \ifnum\count@<#1 \else\ifnum\count@>#2 \else\@tempswatrue\fi\fi%
3377 }
3378 % \end{macrocode}
3379 %
3380 % \end{macro}
3381 %
3382 %
3383 % \subsection{Horizontal rules OK}
3384 %
3385 % This is where all the gubbins for |\vgap| and friends is kept, lest it
3386 % contaminate fairly clean bits of code found elsewhere.
3387 %
3388 % \subsubsection{Common parsing for vertical rule width twiddling}
3389 %
3390 % \begin{macro}{\tab@rulewd}
3391 %
3392 % Given a macro name, set |\tab@rulewidth| to be the chosen rule thickness
3393 % and call the macro. We parse a `|*|' to mean |\arraythickrulewidth|, an
3394 % optional argument which should be something |\setlength| can understand, or
3395 % nothing, which gives the default |\arrayrulewidth|.
3396 %
3397 % \begin{macrocode}
3398 \def\tab@rulewd#1{%
3399 {\ifnum0=`}\fi\@ifstar{\tab@rulewd@star{#1}}{\tab@rulewd@what{#1}}%
3400 }
3401 \def\tab@rulewd@what#1{%
3402 \@ifnextchar[{\tab@rulewd@opt{#1}}{\tab@rulewd@done\arrayrulewidth#1}%
3403 }
3404 \def\tab@rulewd@star#1{\tab@rulewd@done\arraythickrulewidth#1}
3405 \def\tab@rulewd@opt#1[#2]{\setlength\dimen@{#2}\tab@rulewd@done\dimen@#1}
3406 \def\tab@rulewd@done#1{\global\tab@rulewidth#1\ifnum0=`{\fi}}
3407 % \end{macrocode}
3408 %
3409 % \end{macro}
3410 %
3411 % \subsubsection{Drawing horizontal rules}
3412 %
3413 % \begin{macro}{\hline}
3414 %
3415 % Note the funny use of |\noalign| to allow \TeX\ stomach ops like
3416 % |\futurelet| without starting a new table row. This lets us see if there's
3417 % another |\hline| coming up, so we can see if we need to insert extra
3418 % vertical space.
3419 %
3420 % \begin{macrocode}
3421 \def\hline{\noalign\tab@rulewd\hline@prep}
3422 \def\hline@prep{%
3423 \tab@dohline%
3424 \noalign{\ifnum0=`}\fi%
3425 \tab@penalty%
3426 \futurelet\@let@token\hline@i%
3427 }
3428 % \end{macrocode}
3429 %
3430 % We check here for another |\hline| command, and insert glue if there is.
3431 % This looks terrible, though, and |\hlx{hvh}| is much nicer. Still\dots
3432 %
3433 % \begin{macrocode}
3434 \def\hline@i{%
3435 \@tempswafalse%
3436 \ifx\@let@token\hline\@tempswatrue\fi%
3437 \ifx\@let@token\hline@prep\@tempswatrue\fi%
3438 \if@tempswa%
3439 \vskip\doublerulesep%
3440 \tab@addruleheight\doublerulesep%
3441 \fi%
3442 \ifnum0=`{\fi}%
3443 }
3444 % \end{macrocode}
3445 %
3446 % \end{macro}
3447 %
3448 % \begin{macro}{\tab@dohline}
3449 %
3450 % This is where hlines actually get drawn.
3451 % Drawing lines is more awkward than it used to be, particularly in unboxed
3452 % tables. It used to be a case simply of saying |\noalign{\hrule}|.
3453 % However, since unboxed tables are actually much wider than they look, this
3454 % would make the rules stretch right across the page and look generally
3455 % horrible.
3456 %
3457 % The solution is simple: we basically do a dirty big |\cline|.
3458 %
3459 % \begin{macrocode}
3460 \def\tab@dohline{%
3461 \multispan{\tab@columns}%
3462 \leaders\hrule\@height\tab@rulewidth\hfil%
3463 \tab@addruleheight\arrayrulewidth%
3464 \cr%
3465 }
3466 % \end{macrocode}
3467 %
3468 % \end{macro}
3469 %
3470 % \subsubsection{Vertical rules}
3471 %
3472 % I couldn't fit these in anywhere else, so they'll have to go here. I'll
3473 % provide a new optional argument which specifies the width of the rule; this
3474 % gets rid of the problem described in the \emph{Companion}, where to get
3475 % an unusually wide vertical rule, you have to play with things like
3476 % \syntax{"\\vrule width" <dimen>} which really isn't too nice.
3477 %
3478 % \begin{macro}{\vline}
3479 %
3480 % Now uses the general |\tab@rulewd| parser.
3481 %
3482 % \begin{macrocode}
3483 \def\vline{%
3484 \begingroup%
3485 \dimen@\tab@rulewidth%
3486 \tab@rulewd{%
3487 \vrule\@width\tab@rulewidth%
3488 \global\tab@rulewidth\dimen@%
3489 \endgroup%
3490 }%
3491 }
3492 % \end{macrocode}
3493 %
3494 % \end{macro}
3495 %
3496 % \subsubsection{Drawing bits of lines}
3497 %
3498 % Just for a bit of fun, here's an extended version of |\cline| which takes
3499 % a list of columns to draw lines under, rather than just a single range.
3500 %
3501 % \begin{macro}{\cline}
3502 %
3503 % Not a single line of code written yet, and we already have a dilemma on
3504 % our hands. Multiple consecutive |\cline| commands are meant to draw
3505 % on the same vertical bit of table. But horizontal lines are meant to have
3506 % thickness now. Oh, well [sigh], we'll skip back on it after all.
3507 %
3508 % Now the problem remains how best to do the job. The way I see it, there
3509 % are three possibilities:
3510 %
3511 % \begin{itemize}
3512 %
3513 % \item We can start a table row, and then for each column of the table
3514 % (as recorded in |\tab@columns|) we look to see if that column is
3515 % listed in the range list and if so draw the rule. This requires
3516 % lots of scanning of the range list.
3517 %
3518 % \item We can take each range in the list, and draw rules appropriately,
3519 % just like the old |\cline| used to do, and starting a new table row
3520 % for each.
3521 %
3522 % \item We can start a table row, and then for each range remember where we
3523 % stopped drawing the last row, move to the start of the new one, and
3524 % draw it. If we start moving backwards, we close the current row
3525 % and open a new one.
3526 %
3527 % \end{itemize}
3528 %
3529 % The last option looks the most efficient, and the most difficult. This
3530 % is therefore what I shall do |;-)|.
3531 %
3532 % The first thing to do is to add in a little negative space, and start a
3533 % table row (omitting the first item). Then scan the range list, and finally
3534 % close the table row and add some negative space again.
3535 %
3536 % We need a global count register to keep track of where we are. Mixing
3537 % local and global assignments causes all sorts of tragedy, so I shall hijack
3538 % |\tab@state|.
3539 %
3540 % \begin{macrocode}
3541 \def\cline{\noalign\tab@rulewd\cline@prep}
3542 \def\cline@prep#1{%
3543 \noalign{\kern-.5\tab@rulewidth\tab@penalty}%
3544 \omit%
3545 \global\tab@state\@ne%
3546 \ranges\cline@i{#1}%
3547 \cr%
3548 \noalign{\kern-.5\tab@rulewidth\tab@penalty}%
3549 }
3550 % \end{macrocode}
3551 %
3552 % Now for the tricky bit. When we're given a range, we look to see if the
3553 % first number is less than |\tab@state|. If so, we quickly close the
3554 % current row, kern backwards and start again with an |\omit| and reset
3555 % |\tab@state| to 1, and try again.
3556 %
3557 % \begin{macrocode}
3558 \def\cline@i#1#2{%
3559 \ifnum#1<\tab@state\relax%
3560 \tab@@cr%
3561 \noalign{\kern-\tab@rulewidth\tab@penalty}%
3562 \omit%
3563 \global\tab@state\@ne%
3564 \fi%
3565 % \end{macrocode}
3566 %
3567 % We are now either at or in front of the column position required. If
3568 % we're too far back, we must |\hfil&\omit| our way over to the correct%
3569 % column.
3570 %
3571 % \begin{macrocode}
3572 \@whilenum\tab@state<#1\do{%
3573 \hfil\tab@@tab@omit%
3574 \global\advance\tab@state\@ne%
3575 }%
3576 % \end{macrocode}
3577 %
3578 % We've found the start correctly. We must deal with a tiny problem now:
3579 % if this is not the first table cell, the left hand vertical rule is in the
3580 % column to the left, so our horizontal rule won't match up properly. So
3581 % we skip back by a bit to compensate. If there isn't actually a vertical
3582 % rule to line up with, no-one will notice, because the rules are so thin.
3583 % This adds a little touch of quality to the whole thing, which is after all
3584 % the point of this whole exercise.
3585 %
3586 % \begin{macrocode}
3587 \ifnum\tab@state>\@ne%
3588 \kern-\arrayrulewidth%
3589 \fi%
3590 % \end{macrocode}
3591 %
3592 % Now we must stretch this table cell to the correct width.
3593 %
3594 % \begin{macrocode}
3595 \@whilenum\tab@state<#2\do{%
3596 \tab@@span@omit%
3597 \global\advance\tab@state\@ne%
3598 }%
3599 % \end{macrocode}
3600 %
3601 % We're ready. Draw the rule. Note that this is |\hfill| glue, just in case
3602 % we start putting in |\hfil| glue when we step onto the next cell.
3603 %
3604 % \begin{macrocode}
3605 \leaders\hrule\@height\tab@rulewidth\hfill%
3606 }
3607 % \end{macrocode}
3608 %
3609 % Some alignment primitives are hidden inside macros so they don't get seen
3610 % at the wrong time. This is what they look like:
3611 %
3612 % \begin{macrocode}
3613 \def\tab@@cr{\cr}
3614 \def\tab@@tab@omit{&\omit}
3615 \def\tab@@span@omit{\span\omit}
3616 % \end{macrocode}
3617 %
3618 % \end{macro}
3619 %
3620 % \subsubsection{Drawing short table rows}
3621 %
3622 % Before I start on a description of more code, I think I'll briefly discuss
3623 % my reasons for leaving the |\vgap| command in its current state. There's a
3624 % reasonable case for introducing an interface between |\vgap| and
3625 % |\multicolumn|, to avoid all the tedious messing about with column
3626 % ranges. There are good reasons why I'm not going to do this:
3627 %
3628 % \begin{itemize}
3629 %
3630 % \item It's very difficult to do: it requires either postprocessing of
3631 % the table or delaying processing of each row until I know exactly
3632 % what's in it; a |\multicolumn| in a row should be able to affect
3633 % a |\vgap| before the row, which gets very nasty. This package is
3634 % probably far too large already, and adding more complexity and
3635 % running the risk of exhausting \TeX's frustratingly finite capacity
3636 % for the sake of relieving the user of a fairly trivial job doesn't
3637 % seem worthwhile.
3638 %
3639 % \item Perhaps more importantly, there are perfectly valid occasions when
3640 % it's useful to have the current vgap behaviour. For example, the
3641 % \texttt{MIX} word layout diagrams found in \emph{The Art of
3642 % Computer Programming} use the little `stub lines' to show where
3643 % data items cross byte boundaries:
3644 %
3645 % ^^A This actually looks terrifyingly similar to the original.
3646 % ^^A The leading @{} is there to stop the table looking off-centre,
3647 % ^^A because there's no left hand rule telling you where the table
3648 % ^^A starts, like there is on the right, just the \tabcolsep glue.
3649 %
3650 % \begingroup
3651 % \newcommand{\wide}[2]{\multicolumn{#1}{c|}{\ttfamily #2}}
3652 % \begin{tabular}[C]{@{} r @{\qquad} | Mc | *{5}{c|}} \hlx{c{2-7} v}
3653 % empty & - & 1 & 0 & 0 & 0 & 0 \\ \hlx{v c{2-7} v}
3654 % occupied & + & \wide{2}{LINK} & \wide{3}{KEY} \\ \hlx{v c{2-7}}
3655 % \end{tabular}
3656 % \endgroup
3657 %
3658 % \end{itemize}
3659 %
3660 % That's my excuses out of the way; now I'll press on with the actual
3661 % programming.
3662 %
3663 % \begin{macro}{\tab@checkrule}
3664 %
3665 % We have a range list in |\tab@xcols| and a number as an argument. If we
3666 % find the number in the list, we just space out the following group,
3667 % otherwise we let it be.
3668 %
3669 % \begin{macrocode}
3670 \def\tab@checkrule#1{%
3671 \count@#1\relax%
3672 \expandafter\ifinrange%
3673 \expandafter\count@%
3674 \expandafter{\tab@xcols}%
3675 {\tab@checkrule@i}%
3676 {}%
3677 }
3678 \def\tab@checkrule@i#1{\setbox\z@\hbox{#1}\hb@xt@\wd\z@{}}
3679 % \end{macrocode}
3680 %
3681 % \end{macro}
3682 %
3683 % \begin{macro}{\vgap}
3684 %
3685 % We must tread carefully here. A single misplaced stomach operation can
3686 % cause error messages. We therefore start with an |\omit| so we can search
3687 % for optional arguments.
3688 %
3689 % So that |\hlx| can get control after |\vgap| has finished, we provide a
3690 % hook called |\vgap@after| which is expanded after |\vgap| has finished.
3691 % Here we make it work like |\@empty|, which expands to nothing. (Note that
3692 % |\relax| will start a new table row, so we can't use that.) There are
3693 % some penalty items here to stick the |\vgap| row to the text row and
3694 % |\hline| that are adjacent to it. The \package{longtable} package will
3695 % split an |\hline| in half, so this is the correct thing to do.
3696 %
3697 % \begin{macrocode}
3698 \def\vgap{%
3699 \noalign{\nobreak}%
3700 \omit%
3701 \global\let\vgap@after\@empty%
3702 \iffalse{\fi\ifnum0=`}\fi%
3703 \@ifnextchar[\vgap@i\vgap@simple%
3704 }
3705 % \end{macrocode}
3706 %
3707 % We set up two different sorts of |\vgap| -- a simple one which allows all
3708 % rules to be passed through, and a specific one which carefully vets each
3709 % one (and is therefore slower). We decide which to so based on the presence
3710 % of an optional argument.
3711 %
3712 % The optional argument handler just passes its argument to an interface
3713 % routine which is used by |\hlx|.
3714 %
3715 % \begin{macrocode}
3716 \def\vgap@i[#1]{\vgap@spec{#1}}
3717 % \end{macrocode}
3718 %
3719 % Now we handle specified columns. Since we're in an omitted table cell, we
3720 % must set things up globally. Assign the column spec to a macro, and set up
3721 % vetting by the routine above. Then just go and do the job.
3722 %
3723 % \begin{macrocode}
3724 \def\vgap@spec#1#2{%
3725 \gdef\tab@xcols{#1}%
3726 \global\let\tab@ckr\tab@checkrule%
3727 \vgap@do{#2}%
3728 }
3729 % \end{macrocode}
3730 %
3731 % Handle all columns. Just gobble the column number for each rule, and let
3732 % the drawing pass unharmed. Easy.
3733 %
3734 % \begin{macrocode}
3735 \def\vgap@simple#1{%
3736 \global\let\tab@ckr\@gobble%
3737 \vgap@do{#1}%
3738 }
3739 % \end{macrocode}
3740 %
3741 % This is where stuff actually gets done. We set the |\vgap| flag on while
3742 % we do the short row. Then just expand the token list we built while
3743 % scanning the preamble.
3744 %
3745 % Note that the flag is cleared at the end of the last column, to allow other
3746 % funny things like |\noalign| and |\omit| before a new row is started.
3747 %
3748 % \begin{macrocode}
3749 \def\vgap@do#1{%
3750 \ifnum0=`{}\fi%
3751 \global\tab@vgaptrue%
3752 \the\tab@shortline%
3753 \vrule\@height#1\@width\z@%
3754 \global\tab@vgapfalse
3755 \tab@addruleheight{#1}%
3756 \cr%
3757 \noalign{\nobreak}%
3758 \vgap@after%
3759 }
3760 % \end{macrocode}
3761 %
3762 % \end{macro}
3763 %
3764 % \subsubsection{Prettifying syntax}
3765 %
3766 % \begin{macro}{\hlx}
3767 %
3768 % This is like a poor cousin to the preamble parser. The whole loop is
3769 % carefully written to take place \emph{only} in \TeX's mouth, so the
3770 % alignment handling bits half way down the gullet don't see any of this.
3771 %
3772 % First, pass the string to another routine.
3773 %
3774 % \begin{macrocode}
3775 \def\hlx{\noalign\tab@rulewd\hlx@prep}
3776 \def\hlx@prep#1{\hlx@loop#1\q@delim}
3777 % \end{macrocode}
3778 %
3779 % Now peel off a token, and dispatch using |\csname|. We handle
3780 % undefinedness of the command in a fairly messy way, although it probably
3781 % works. Maybe.
3782 %
3783 % \begin{macrocode}
3784 \def\hlx@loop#1{%
3785 \ifx#1\q@delim\else%
3786 \@ifundefined{hlx@cmd@\string#1}{%
3787 \expandafter\hlx@loop%
3788 }{%
3789 \csname hlx@cmd@\string#1\expandafter\endcsname%
3790 }%
3791 \fi%
3792 }
3793 % \end{macrocode}
3794 %
3795 % \end{macro}
3796 %
3797 % \begin{macro}{\hlxdef}
3798 %
3799 % New |\hlx| commands can be defined using |\hlxdef|. This is a simple
3800 % abbreviation.
3801 %
3802 % \begin{macrocode}
3803 \def\hlxdef#1{\@namedef{hlx@cmd@#1}}
3804 % \end{macrocode}
3805 %
3806 % \end{macro}
3807 %
3808 % \begin{macro}{\hlx h}
3809 %
3810 % Handle an \lit{h} character. Just do an |\hline| and return to the loop.
3811 % We look ahead to see if there's another \lit{h} coming up, and if so
3812 % insert two |\hline| commands. This strange (and inefficient) behaviour
3813 % keeps packages which redefine |\hline| happy.
3814 %
3815 % \begin{macrocode}
3816 \hlxdef h#1{%
3817 \noalign{%
3818 \ifx#1h%
3819 \def\@tempa{\hline@prep\hline@prep\hlx@loop}%
3820 \else%
3821 \def\@tempa{\hline@prep\hlx@loop#1}%
3822 \fi%
3823 \expandafter
3824 }%
3825 \@tempa%
3826 }
3827 % \end{macrocode}
3828 %
3829 % \end{macro}
3830 %
3831 % \begin{macro}{\hlx b}
3832 %
3833 % The \lit{b} character does a nifty backspace, for \package{longtable}'s
3834 % benefit.
3835 %
3836 % \begin{macrocode}
3837 \hlxdef b{\noalign{\kern-\arrayrulewidth}\hlx@loop}
3838 % \end{macrocode}
3839 %
3840 % \end{macro}
3841 %
3842 % \begin{macro}{\hlx /}
3843 %
3844 % The `"/"' character allows a page break at the current position.
3845 %
3846 % \begin{macrocode}
3847 \hlxdef /{%
3848 \noalign{\ifnum0=`}\fi%
3849 \@ifnextchar[\hlx@cmd@break@i{\hlx@cmd@break@i[0]}%
3850 }
3851 \def\hlx@cmd@break@i[#1]{\ifnum0=`{\fi}\pagebreak[0]\hlx@loop}
3852 % \end{macrocode}
3853 %
3854 % \end{macro}
3855 %
3856 % \begin{macro}{\hlx v}
3857 %
3858 % Handle a \lit{v} character. This is rather like the |\vgap| code above,
3859 % although there are syntactic differences.
3860 %
3861 % \begin{macrocode}
3862 \hlxdef v{%
3863 \noalign{\nobreak}%
3864 \omit%
3865 \iffalse{\fi\ifnum0=`}\fi%
3866 \global\let\vgap@after\hlx@loop%
3867 \@ifnextchar[\hlx@vgap@i{\hlx@vgap@ii\vgap@simple}%
3868 }
3869 \def\hlx@vgap@i[#1]{%
3870 \ifx!#1!%
3871 \def\@tempa{\hlx@vgap@ii\vgap@simple}%
3872 \else%
3873 \def\@tempa{\hlx@vgap@ii{\vgap@spec{#1}}}%
3874 \fi%
3875 \@tempa%
3876 }
3877 \def\hlx@vgap@ii#1{%
3878 \@ifnextchar[{\hlx@vgap@iii{#1}}{\hlx@vgap@iii{#1}[\doublerulesep]}%
3879 }
3880 \def\hlx@vgap@iii#1[#2]{#1{#2}}
3881 % \end{macrocode}
3882 %
3883 % \end{macro}
3884 %
3885 % \begin{macro}{\hlx s}
3886 %
3887 % Allow the user to leave a small gap using the \lit{s} command.
3888 %
3889 % \begin{macrocode}
3890 \hlxdef s{%
3891 \noalign{\ifnum0=`}\fi%
3892 \nobreak%
3893 \@ifnextchar[\hlx@space@i{\hlx@space@i[\doublerulesep]}%
3894 }
3895 \def\hlx@space@i[#1]{%
3896 \vskip#1%
3897 \tab@addruleheight{#1}%
3898 \ifnum0=`{\fi}%
3899 \hlx@loop%
3900 }
3901 % \end{macrocode}
3902 %
3903 % \end{macro}
3904 %
3905 % \begin{macro}{\hlx c}
3906 %
3907 % We might as well allow a \lit{c} command to do a |\cline|.
3908 %
3909 % \begin{macrocode}
3910 \hlxdef c#1{\cline@prep{#1}\hlx@loop}
3911 % \end{macrocode}
3912 %
3913 % \end{macro}
3914 %
3915 % \begin{macro}{\hlx .}
3916 %
3917 % The \lit{.} character forces a start of the new column. There's a little
3918 % problem here. Since the \lit{.} character starts the next column, we need
3919 % to gobble any spaces following the |\hlx| command before the cell contents
3920 % actually starts. Unfortunately, |\ignorespaces| will start the column for
3921 % us, so we can't put it in always. We'll handle it here, then. We'll take
3922 % the rest of the `preamble' string, and warn if it's not empty. Then we'll
3923 % |\ignorespaces| -- this will start the column for us, so we don't need to
3924 % |\relax| any more.
3925 %
3926 % \begin{macrocode}
3927 \hlxdef .#1\q@delim{%
3928 \ifx @#1@\else%
3929 \PackageWarning{mdwtab}{%
3930 Ignoring \protect\hlx\space command characters following a
3931 `.'\MessageBreak command%
3932 }%
3933 \fi%
3934 \ignorespaces%
3935 }
3936 % \end{macrocode}
3937 %
3938 % \end{macro}
3939 %
3940 %
3941 % \subsection{Starting new table rows}
3942 %
3943 % We take a break from careful mouthery at last, and start playing with
3944 % newlines. The standard one allows pagebreaks in unboxed tables, which
3945 % isn't really too desirable.
3946 %
3947 % Anyway, we'll try to make this macro rather more reusable than the standard
3948 % one. Here goes.
3949 %
3950 % \begin{macro}{\@arraycr}
3951 %
3952 % We pass lots of information to a main parser macro, and expect it to cope.
3953 %
3954 % \begin{macrocode}
3955 \def\@arraycr{\tab@arraycr{}}
3956 \def\tab@arraycr#1{\tab@cr{\tab@tabcr{#1}}{}{}}
3957 % \end{macrocode}
3958 %
3959 % Now to actually do the work. |\tab@cr| passes us the skip size, and the
3960 % appropriate one of the two arguments given above (both of which are empty)
3961 % depending on the presence of the $*$.
3962 %
3963 % \begin{macrocode}
3964 \def\tab@tabcr#1#2{%
3965 % \end{macrocode}
3966 %
3967 % If the total height I need to add between rows (from the optional argument
3968 % and the `extrasep' parameter) is greater than zero, I'll handle this by
3969 % extending the strut slightly. I'm not actually sure whether this is the
3970 % right thing to do, to be honest, although it's easier than trying to
3971 % to an automatic |\vgap|, because I need to know which columns to skip.
3972 % If the space is less than zero, I'll just insert the vertical space with
3973 % in a |\noalign|.
3974 %
3975 % First, to calculate how much space needs adding.
3976 %
3977 % \begin{macrocode}
3978 \setlength\dimen@{#2}%
3979 \advance\dimen@\tab@extrasep%
3980 % \end{macrocode}
3981 %
3982 % If the height is greater than zero, I need to play with the strut. I must
3983 % bear in mind that the current table cell (which I'm still in, remember)
3984 % may be in vertical mode, and I may or may not be in a paragraph.
3985 %
3986 % If I am in vertical mode, I'll backpedal to the previous box and put the
3987 % strut in an hbox superimposed on the previous baseline. Otherwise, I can
3988 % just put the strut at the end of the text. (This works in either LR
3989 % or paragraph mode as long as I'm not between paragraphs.) Again, Rowland's
3990 % empty cell bug strikes. (See |\tab@epar| for details.)
3991 %
3992 % \begin{macrocode}
3993 \ifdim\dimen@>\z@%
3994 \ifvmode%
3995 \unskip\ifdim\prevdepth>-\@m\p@\kern-\prevdepth\fi%
3996 \nointerlineskip\expandafter\hbox%
3997 \else%
3998 \@maybe@unskip\expandafter\@firstofone%
3999 \fi%
4000 {\advance\dimen@\dp\@arstrutbox\vrule\@depth\dimen@\@width\z@}%
4001 \fi%
4002 % \end{macrocode}
4003 %
4004 % This table cell works as a group (which is annoying here). I'll copy the
4005 % interrow gap into a global register so that I can use it in the |\noalign|.
4006 %
4007 % \begin{macrocode}
4008 \global\dimen\@ne\dimen@%
4009 \cr%
4010 \noalign{%
4011 #1%
4012 \ifdim\dimen\@ne<\z@\vskip\dimen\@ne\relax\fi%
4013 }%
4014 \@gobble%
4015 }
4016 % \end{macrocode}
4017 %
4018 % \end{macro}
4019 %
4020 % \begin{macro}{\tab@setcr}
4021 %
4022 % To set the |\\| command correctly in each table cell, we make it a part of
4023 % the preamble (in |\tab@midtext|) to call this routine. It's easy -- just
4024 % saves the preamble from being huge.
4025 %
4026 % \begin{macrocode}
4027 \def\tab@setcr{\let\\\tabularnewline}
4028 % \end{macrocode}
4029 %
4030 % \end{macro}
4031 %
4032 % \begin{macro}{\tab@cr}
4033 %
4034 % Now we do the parsing work. This is fun. Note the revenge of the funny
4035 % braces here. Nothing to worry about, honest. The tricky bit is to keep
4036 % track of which arguments are which. (Thanks to David Carlisle for pointing
4037 % out that I'd missed out the |\relax| here.)
4038 %
4039 % \begin{macrocode}
4040 \def\tab@cr#1#2#3{%
4041 \relax%
4042 \iffalse{\fi\ifnum0=`}\fi%
4043 \@ifstar{\tab@cr@i{#1}{#3}}{\tab@cr@i{#1}{#2}}%
4044 }
4045 \def\tab@cr@i#1#2{%
4046 \@ifnextchar[{\tab@cr@ii{#1}{#2}}{\tab@cr@ii{#1}{#2}[\z@]}%
4047 }
4048 \def\tab@cr@ii#1#2[#3]{%
4049 \ifnum0=`{}\fi%
4050 #1{#3}{#2}%
4051 }
4052 % \end{macrocode}
4053 %
4054 % \end{macro}
4055 %
4056 %
4057 % \subsection{Gratuitous grotesquery}
4058 %
4059 % So far we've had an easy-ish ride (or should that be \emph{queasy}?). Now
4060 % for something unexplainably evil. We convince \LaTeX\ that it's loaded the
4061 % \package{array} package, so that packages which need it think they've got
4062 % it.
4063 %
4064 % The bogus date is the same as the date for the \package{array} package I've
4065 % got here -- this will raise a warning if Frank updates his package which
4066 % should filter back to me telling me that there's something I need to
4067 % know about.
4068 %
4069 % The messing with |\xdef| and the funny parsing ought to insert the current
4070 % \package{mdwtab} version and date into the fake \package{array} version
4071 % string, giving a visible clue to the user that this isn't the real
4072 % \package{array} package.
4073 %
4074 % \begin{macrocode}
4075 \begingroup
4076 \catcode`.=11
4077 \def\@tempa#1 #2 #3\@@{#1 #2}
4078 \xdef\ver@array.sty
4079 {1995/11/19 [mdwtab.sty \expandafter\@tempa\ver@mdwtab.sty\@@]}
4080 \endgroup
4081 % \end{macrocode}
4082 %
4083 %
4084 % \subsection{Error messages}
4085 %
4086 % I've put all the error messages together, where I can find them, translate
4087 % them or whatever.
4088 %
4089 % First, some token-space saving (which also saves my fingers):
4090 %
4091 % \begin{macrocode}
4092 \def\tab@error{\PackageError{mdwtab}}
4093 % \end{macrocode}
4094 %
4095 % Now do the error messages.
4096 %
4097 % \begin{macrocode}
4098 \def\tab@err@misscol{%
4099 \tab@error{Missing column type}{%
4100 I'm lost. I was expecting something describing^^J%
4101 the type of the current column, but you seem to^^J%
4102 have missed it out. I've inserted a type `l'^^J%
4103 column here in the hope that this makes sense.%
4104 }%
4105 }
4106 % \end{macrocode}
4107 %
4108 % \begin{macrocode}
4109 \def\tab@err@oddgroup{%
4110 \tab@error{Misplaced group in table preamble}{%
4111 I've found an open brace character in your preamble^^J%
4112 when I was expecting a specifier character. I'm^^J%
4113 going to gobble the whole group and carry on as if^^J%
4114 I'd never seen it.%
4115 }%
4116 }
4117 % \end{macrocode}
4118 %
4119 % \begin{macrocode}
4120 \def\tab@err@undef#1{%
4121 \tab@error{Unknown `\tab@colset' preamble character `\string#1'}{%
4122 I don't understand what you meant by typing this^^J%
4123 character. Anyway, I'll ignore it this time around.^^J%
4124 Just don't you do it again.%
4125 }%
4126 }
4127 % \end{macrocode}
4128 %
4129 % \begin{macrocode}
4130 \def\tab@err@unbrh{%
4131 \tab@error{Can't use unboxed tabular in LR mode}{%
4132 You've asked for a tabular or array environment with^^J%
4133 `L', `C' or `R' as the position specifier, but you're^^J%
4134 in LR (restricted horizontal) mode, so it won't work.^^J%
4135 I'll assume you really meant `c' and soldier on.%
4136 }%
4137 }
4138 % \end{macrocode}
4139 %
4140 % \begin{macrocode}
4141 \def\tab@err@unbmm{%
4142 \tab@error{Can't use unboxed tabular in maths mode}{%
4143 You've asked for a tabular or array environment with^^J%
4144 `L', `C' or `R' as the position specifier, but you're^^J%
4145 in maths mode, so it won't work. I'll pretend that^^J%
4146 you really typed `c', and that this is all a bad dream.%
4147 }%
4148 }
4149 % \end{macrocode}
4150 %
4151 % \begin{macrocode}
4152 \def\tab@err@unbext{%
4153 \tab@error{Can't extend unboxed tabulars}{%
4154 You're trying to use kludgy extensions (e.g.,^^J%
4155 `delarray') on an array or tabular with `L', `C'^^J%
4156 or `R' as the position specifier. I'll assume you^^J%
4157 subconsciously wanted a `c' type all along.%
4158 }%
4159 }
4160 % \end{macrocode}
4161 %
4162 % \begin{macrocode}
4163 \def\tab@err@multi{%
4164 \tab@error{More than one column in a \protect\multicolumn}{%
4165 You've put more than one column into a \string\multicolumn^^J%
4166 descriptor. It won't work. I have no idea what^^J%
4167 will happen, although it won't be pleasant. Hold^^J%
4168 on tight now...%
4169 }%
4170 }
4171 % \end{macrocode}
4172 %
4173 % \begin{macrocode}
4174 \def\tab@err@range{%
4175 \tab@error{Expected `,' or `<end>' in range list}{%
4176 I was expecting either the end of the range list,^^J%
4177 or a comma, followed by another range. I've^^J%
4178 inserted a comma to try and get me back on track.^^J%
4179 Good luck.%
4180 }%
4181 }
4182 % \end{macrocode}
4183 %
4184 % That's it. No more. Move along please.
4185 %
4186 % \begin{macrocode}
4187 %</mdwtab>
4188 % \end{macrocode}
4189 %
4190 %
4191 %^^A-------------------------------------------------------------------------
4192 % \section{Implementation of \package{mathenv}}
4193 %
4194 %
4195 % This is in a separate package, mainly to avoid wasting people's memory.
4196 %
4197 % \begin{macrocode}
4198 %<*mathenv>
4199 % \end{macrocode}
4200 %
4201 %
4202 % \subsection{Options handling}
4203 %
4204 % We need to be able to cope with \textsf{fleqn} and \textsf{leqno} options.
4205 % This will adjust our magic modified \env{eqnarray} environment
4206 % appropriately.
4207 %
4208 % \begin{macrocode}
4209 \newif\if@fleqn
4210 \newif\if@leqno
4211 \DeclareOption{fleqn}{\@fleqntrue}
4212 \DeclareOption{leqno}{\@leqnotrue}
4213 \ProcessOptions
4214 % \end{macrocode}
4215 %
4216 % We use the \package{mdwtab} package for all its nice table handling things.
4217 % (Oh, and to inflict it on users who want to do nice equations and don't
4218 % care about our tables.)
4219 %
4220 % \begin{macrocode}
4221 \RequirePackage{mdwtab}
4222 % \end{macrocode}
4223 %
4224 %
4225 % \subsection{Some useful registers}
4226 %
4227 % The old \LaTeX\ version puts the equation numbers in by keeping a count of
4228 % where it is in the alignment. Since I don't know how may columns there are
4229 % going to be, I'll just use a switch in the preamble to tell me to stop
4230 % tabbing.
4231 %
4232 % \begin{macrocode}
4233 \newif\if@eqalast
4234 % \end{macrocode}
4235 %
4236 % Now define some useful length parameters. First allocate them:
4237 %
4238 % \begin{macrocode}
4239 \newskip\eqaopenskip
4240 \newskip\eqacloseskip
4241 \newskip\eqacolskip
4242 \newskip\eqainskip
4243 \newskip\splitleft
4244 \newskip\splitright
4245 % \end{macrocode}
4246 %
4247 % Now assign some default values. Users can play with these if they really
4248 % want although I can't see the point myself.
4249 %
4250 % \begin{macrocode}
4251 \AtBeginDocument{%
4252 \eqacloseskip\@centering%
4253 \eqacolskip1.5em\@plus\@m\p@
4254 \eqainskip\z@%
4255 \if@fleqn%
4256 \eqaopenskip\mathindent%
4257 \splitleft\mathindent\relax%
4258 \splitright\mathindent\@minus\mathindent\relax%
4259 \else%
4260 \eqaopenskip\@centering%
4261 \splitleft2.5em\@minus2.5em%
4262 \splitright\splitleft%
4263 \fi%
4264 \relax%
4265 }
4266 % \end{macrocode}
4267 %
4268 %
4269 % \subsection{A little display handling}
4270 %
4271 % I'm probably going a little far here, and invading territory already
4272 % claimed by the \package{amsmath} stuff (and done a good deal better than
4273 % I can be bothered to do), but just for completeness, this is how we handle
4274 % attempts to put displays inside other displays without screwing up the
4275 % spacing.
4276 %
4277 % \begin{macro}{\dsp@startouter}
4278 %
4279 % This is how we start an outermost display. It's fairly easy really. We
4280 % make |\dsp@start| start an inner display, and make |\dsp@end| close the
4281 % outer display.
4282 %
4283 % \begin{macrocode}
4284 \def\dsp@startouter{%
4285 \let\dsp@end\dsp@endouter%
4286 $$%
4287 }
4288 % \end{macrocode}
4289 %
4290 % \end{macro}
4291 %
4292 % \begin{macro}{\dsp@endouter}
4293 %
4294 % Ending the outer display is utterly trivial.
4295 %
4296 % \begin{macrocode}
4297 \def\dsp@endouter{$$}
4298 % \end{macrocode}
4299 %
4300 % \end{macro}
4301 %
4302 % \begin{macro}{\dsp@startinner}
4303 %
4304 % Starting inner displays is done in a vbox (actually I choose |\vbox| or
4305 % |\vtop| depending on the setting of \textsf{leqno} to put the equation
4306 % number the right way round).
4307 %
4308 % \begin{macrocode}
4309 \def\dsp@startinner{%
4310 \let\dsp@end\dsp@endinner%
4311 \if@fleqn\kern-\mathindent\fi%
4312 \if@leqno\vtop\else\vtop\fi\bgroup%
4313 }
4314 % \end{macrocode}
4315 %
4316 % \end{macro}
4317 %
4318 % \begin{macro}{\dsp@endinner}
4319 %
4320 % Ending an inner display is also really easy.
4321 %
4322 % \begin{macrocode}
4323 \def\dsp@endinner{\egroup}
4324 % \end{macrocode}
4325 %
4326 % \end{macro}
4327 %
4328 % \begin{macro}{\dsp@start}
4329 %
4330 % This is what other bits of code uses to start displays. It's one of the
4331 % start macros up above, and outer by default.
4332 %
4333 % \begin{macrocode}
4334 \def\dsp@start{%
4335 \ifmmode%
4336 %\ifinner\mth@err@mdsp\fi%
4337 \expandafter\dsp@startinner%
4338 \else%
4339 \ifhmode\ifinner\mth@err@hdsp\fi\fi%
4340 \expandafter\dsp@startouter%
4341 \fi%
4342 }
4343 % \end{macrocode}
4344 %
4345 % \end{macro}
4346 %
4347 % \begin{macro}{\dsp@tabpause}
4348 %
4349 % This sets up the correct pre- and postambles for the |\tabpause| macro in
4350 % maths displays. This is fairly simple stuff.
4351 %
4352 % \begin{macrocode}
4353 \def\dsp@tabpause{%
4354 \def\tab@startpause%
4355 {\penalty\postdisplaypenalty\vskip\belowdisplayskip}%
4356 \def\tab@endpause%
4357 {\penalty\predisplaypenalty\vskip\abovedisplayskip}%
4358 }
4359 % \end{macrocode}
4360 %
4361 % \end{macro}
4362 %
4363 %
4364 % \subsection{The \env{eqnarray} environment}
4365 %
4366 % We allow the user to play with the style if this is really wanted. I dunno
4367 % why, really. Maybe someone wants very small alignments.
4368 %
4369 % \begin{macrocode}
4370 \let\eqastyle\displaystyle
4371 % \end{macrocode}
4372 %
4373 % \subsubsection{The main environments}
4374 %
4375 % \begin{environment}{eqnarray}
4376 % \begin{environment}{eqnarray*}
4377 %
4378 % We define the toplevel commands here. They just add in default arguments
4379 % and then call |\@eqnarray| with a preamble string. We handle equation
4380 % numbers by setting up a default (|\eqa@defnumber|) which is put into
4381 % the final column. At the beginning of each row, we globally |\let|
4382 % |\eqa@number| equal to |\eqa@defnumber|. The |\eqnumber| macro just
4383 % changes |\eqa@number| as required. Since |\eqa@number| is changed globally
4384 % we must save it in this environment.
4385 %
4386 % First, we must sort out the optional arguments and things. This is really
4387 % easy. The only difference between the starred and non-starred environments
4388 % is the default definition of |\eqa@defnumber|.
4389 %
4390 % \begin{macrocode}
4391 \def\eqnarray{%
4392 \eqnarray@i\eqa@eqcount%
4393 }
4394 \@namedef{eqnarray*}{\eqnarray@i{}}
4395 \def\eqnarray@i#1{\@ifnextchar[{\eqnarray@ii{#1}}{\eqnarray@ii{#1}[rcl]}}
4396 % \end{macrocode}
4397 %
4398 % Right. Now for the real work. The first argument is the default numbering
4399 % tokens; the second is the preamble string.
4400 %
4401 % \begin{macrocode}
4402 \def\eqnarray@ii#1[#2]{%
4403 % \end{macrocode}
4404 %
4405 % Set up the equation counter and labels correctly.
4406 %
4407 % \medskip\par\noindent|\begin{rant}|\par
4408 % The hacking with |\@currentlabel| is here because (in the author's opinion)
4409 % \LaTeX's |\refstepcounter| macro is broken. It's currently defined as
4410 % \begin{listing}
4411 %\def\refstepcounter#1{%
4412 % \stepcounter{#1}%
4413 % \protected@edef\@currentlabel%
4414 % {\csname p@#1\endcsname\csname the#1\endcsname}%
4415 %}
4416 % \end{listing}
4417 % which means that the current label gets `frozen' as soon as you do the
4418 % counter step. By redefining the macro as
4419 % \begin{listing}
4420 %\def\refstepcounter#1{%
4421 % \stepcounter{#1}%
4422 % \edef\@currentlabel{%
4423 % \expandafter\noexpand\csname p@#1\endcsname%
4424 % \expandafter\noexpand\csname the#1\endcsname%
4425 % }%
4426 %}
4427 % \end{listing}
4428 % these sorts of problems would be avoided, without any loss of functionality
4429 % or compatibility that I can see.
4430 % \par\noindent|\end{rant}|\par
4431 %
4432 % \begin{macrocode}
4433 \stepcounter{equation}%
4434 \def\@currentlabel{\p@equation\theequation}%
4435 % \end{macrocode}
4436 %
4437 % The next step is to set up the numbering. I must save the old numbering
4438 % so I can restore it later (once in the alignment, I must assign these
4439 % things globally).
4440 %
4441 % \begin{macrocode}
4442 \let\eqa@oldnumber\eqa@number%
4443 \def\eqa@defnumber{#1}%
4444 \global\let\eqa@number\eqa@defnumber%
4445 % \end{macrocode}
4446 %
4447 % The |\if@eqalastfalse| switch is false everywhere except when we're in the
4448 % final column.
4449 %
4450 % \begin{macrocode}
4451 \@eqalastfalse%
4452 % \end{macrocode}
4453 %
4454 % Remove the |\mathsurround| kerning, since it will look very odd inside
4455 % the display. We have our own spacing parameters for configuring these
4456 % things, so |\mathsurround| is unnecessary.
4457 %
4458 % \begin{macrocode}
4459 \m@th%
4460 % \end{macrocode}
4461 %
4462 % Time to parse the preamble string now. I must choose the correct column
4463 % set, initialise the preamble parser and set up the various macros. The%
4464 % extra `|@{\tabskip\eqacloseskip}|' item sets up the tabskip glue to centre
4465 % the alignment properly.
4466 %
4467 % \begin{macrocode}
4468 \colset{eqnarray}%
4469 \tab@initread%
4470 \def\tab@tabtext{&\tabskip\z@skip}%
4471 \tab@preamble{\tabskip\z@skip}%
4472 \tab@readpreamble{#2@{\tabskip\eqacloseskip}}%
4473 \dsp@tabpause%
4474 % \end{macrocode}
4475 %
4476 % Now for some final setting up. The column separation is set from the
4477 % user's parameter, the |\everycr| tokens are cleared, and I set up the
4478 % newline command appropriately.
4479 %
4480 % \begin{macrocode}
4481 \col@sep.5\eqainskip%
4482 \everycr{}%
4483 \let\\\@eqncr%
4484 % \end{macrocode}
4485 %
4486 % Now start a maths display and do the alignment. Set up the left hand
4487 % tabskip glue to centre the alignment, and do the actual alignment.
4488 % The preamble used is mainly that generated from the user's string, although
4489 % the stuff at the end is how we set up the equation number -- it repeats
4490 % appropriately so we can always find it.
4491 %
4492 % \begin{macrocode}
4493 \dsp@start%
4494 \tabskip\eqaopenskip%
4495 \halign to\displaywidth\expandafter\bgroup%
4496 \the\tab@preamble%
4497 &&\eqa@lastcol\hb@xt@\z@{\hss##}\tabskip\z@\cr%
4498 }
4499 % \end{macrocode}
4500 %
4501 % Now for the end of the environment. This is really easy. Set the final
4502 % equation number, close the |\halign|, tidy up the equation counter (it's
4503 % been stepped once too many times) and close the display.
4504 %
4505 % \begin{macrocode}
4506 \def\endeqnarray{%
4507 \eqa@eqnum%
4508 \egroup%
4509 \dsp@end%
4510 \global\let\eqa@number\eqa@oldnumber%
4511 \global\@ignoretrue%
4512 \global\advance\c@equation\m@ne%
4513 }
4514 \expandafter\let\csname endeqnarray*\endcsname\endeqnarray
4515 % \end{macrocode}
4516 %
4517 % \end{environment}
4518 % \end{environment}
4519 %
4520 % Now we can define the column types.
4521 %
4522 % \begin{macrocode}
4523 \colpush{eqnarray}
4524 % \end{macrocode}
4525 %
4526 % Note the positioning of ord atoms in the stuff below. This will space out
4527 % relations and binops correctly when they occur at the edges of columns, and
4528 % won't affect ord atoms at the edges, because ords pack closely.
4529 %
4530 % First the easy ones. Just stick |\hfil| in the right places and
4531 % everything will be all right.
4532 %
4533 % \begin{macrocode}
4534 \coldef r{\tabcoltype{\hfil$\eqastyle}{{}$}}
4535 \coldef c{\tabcoltype{\hfil$\eqastyle{}}{{}$\hfil}}
4536 \coldef l{\tabcoltype{$\eqastyle{}}{$\hfil}}
4537 \coldef x{\tabcoltype{\if@fleqn\else\hfil\fi$\eqastyle}{$\hfil}}
4538 % \end{macrocode}
4539 %
4540 % Now for the textual ones. This is also fairly easy.
4541 %
4542 % \begin{macrocode}
4543 \collet T [tabular]T
4544 % \end{macrocode}
4545 %
4546 % Sort of split types of equations. I mustn't use |\rlap| here, or
4547 % everything goes wrong -- |\\| doesn't get noticed by \TeX\ in the same way
4548 % as |\cr| does.
4549 %
4550 % \begin{macrocode}
4551 \coldef L{\tabcoltype{\hb@xt@2em\bgroup$\eqastyle}{$\hss\egroup}}
4552 % \end{macrocode}
4553 %
4554 % The \lit{:} column type is fairly simple.
4555 %
4556 % \begin{macrocode}
4557 \coldef :{\tabspctype{\tabskip\eqacolskip}}
4558 \coldef q{\tabspctype{\quad}}
4559 % \end{macrocode}
4560 %
4561 % The other column types just insert given text in an appropriate way.
4562 %
4563 % \begin{macrocode}
4564 \collet > [tabular]>
4565 \collet < [tabular]<
4566 \collet * [tabular]*
4567 \collet @ [tabular]@
4568 % \end{macrocode}
4569 %
4570 % Finally, the magical `|\magic|' column type, which sets the equation
4571 % number. We set up the |\tabskip| glue properly, tab on, and set the flag
4572 % which marks the final column. The |\eqa@lastcol| command is there to
4573 % raise an error if the user tabs over to this column. I'll temporarily
4574 % redefine it to |\@eqalasttrue| when I enter this column legitimately.
4575 % The extra magical bits here will make the final column repeat, so that we
4576 % can find it if necessary. Well is this column type named.
4577 %
4578 % That's it. We can return to normal now.
4579 %
4580 % \begin{macrocode}
4581 \colpop
4582 % \end{macrocode}
4583 %
4584 % \subsubsection{Newline codes}
4585 %
4586 % Newline sequences (|\\|) get turned into calls of |\@eqncr|. The job is
4587 % fairly simple, really.
4588 %
4589 % \begin{macrocode}
4590 \def\@eqncr{\tab@cr\eqacr@i\interdisplaylinepenalty\@M}%
4591 \def\eqacr@i#1#2{%
4592 \eqa@eqnum%
4593 \noalign{\penalty#2\vskip\jot\vskip#1}%
4594 }
4595 % \end{macrocode}
4596 %
4597 % \subsubsection{Setting equation numbers}
4598 %
4599 % \begin{macro}{\eqa@eqpos}
4600 %
4601 % Before we start, we need to generalise the flush-left number handling bits.
4602 % The macro |\eqa@eqpos| will put its argument in the right place.
4603 %
4604 % \begin{macrocode}
4605 \if@leqno
4606 \def\eqa@eqpos#1{%
4607 \hb@xt@.01\p@{}\rlap{\normalfont\normalcolor\hskip-\displaywidth#1}%
4608 }
4609 \else
4610 \def\eqa@eqpos#1{\normalfont\normalcolor#1}
4611 \fi
4612 % \end{macrocode}
4613 %
4614 % \end{macro}
4615 %
4616 % \begin{macro}{\eqa@eqnum}
4617 %
4618 % Here we typeset an equation number in roughly the right place. First I'll
4619 % redefine |\eqa@lastcol| so that it tells me I'm in the right place, and
4620 % start a loop to find that place.
4621 %
4622 % \begin{macrocode}
4623 \def\eqa@eqnum{%
4624 \global\let\eqa@lastcol\@eqalasttrue%
4625 \eqa@eqnum@i%
4626 }
4627 % \end{macrocode}
4628 %
4629 % Now for the loop. The |\relax| here is absolutely vital -- it starts the
4630 % table column, inserting useful tokens like `|\eqa@lastcol|' which tell
4631 % me where I am in the alignment. Then, if I've reached the end, I can
4632 % typeset the equation number; otherwise I go off into another macro and
4633 % step on to the next column.
4634 %
4635 % \begin{macrocode}
4636 \def\eqa@eqnum@i{%
4637 \relax%
4638 \if@eqalast%
4639 \expandafter\eqa@eqnum@ii%
4640 \else%
4641 \expandafter\eqa@eqnum@iii%
4642 \fi%
4643 }
4644 \def\eqa@eqnum@ii{%
4645 \eqa@eqpos\eqa@number%
4646 \global\let\eqa@number\eqa@defnumber%
4647 \global\let\eqa@lastcol\eqa@@lastcol%
4648 \cr%
4649 }
4650 \def\eqa@eqnum@iii{&\eqa@eqnum@i}
4651 % \end{macrocode}
4652 %
4653 % \end{macro}
4654 %
4655 % \begin{macro}{\eqa@lastcol}
4656 %
4657 % This is used as a marker for the final column in an \env{eqnarray}
4658 % environment. By default it informs the user that they've been very
4659 % silly and swallows the contents of the column. I'll redefine it to
4660 % something more useful at appropriate times, and then turn it back again.
4661 %
4662 % \begin{macrocode}
4663 \def\eqa@@lastcol{\mth@err@number\setbox\z@}
4664 \let\eqa@lastcol\eqa@@lastcol
4665 % \end{macrocode}
4666 %
4667 % \end{macro}
4668 %
4669 % \subsubsection{Numbering control}
4670 %
4671 % \begin{macro}{\eqnumber}
4672 %
4673 % The |\eqnumber| command sets the equation number on the current equation.
4674 % This is really easy, actually.
4675 %
4676 % \begin{macrocode}
4677 \newcommand\eqnumber[1][\eqa@eqcount]{\gdef\eqa@number{#1}}
4678 % \end{macrocode}
4679 %
4680 % \end{macro}
4681 %
4682 % \begin{macro}{\eqa@eqcount}
4683 %
4684 % This is how a standard equation number is set, stepping the counter and
4685 % all. It's really easy and obvious.
4686 %
4687 % \begin{macrocode}
4688 \def\eqa@eqcount{(\theequation)\global\advance\c@equation\@ne}
4689 % \end{macrocode}
4690 %
4691 % \end{macro}
4692 %
4693 % \begin{macro}{\nonumber}
4694 %
4695 % The \LaTeX\ |\nonumber| command could be defined by saying
4696 % \begin{listing}
4697 %\renewcommand{\nonumber}{\eqnumber[]}
4698 % \end{listing}
4699 % but I'll be slightly more efficient and redefine |\eqa@number| directly.
4700 %
4701 % \begin{macrocode}
4702 \def\nonumber{\global\let\eqa@number\@empty}
4703 % \end{macrocode}
4704 %
4705 % \end{macro}
4706 %
4707 % \subsubsection{The \env{eqnalign} environment}
4708 %
4709 % As a sort of companion to \env{eqnarray}, here's an environment which does
4710 % similar things inside a box, rather than taking up the whole display width.
4711 % It uses the same column types that we've already created, so there should
4712 % be no problems.
4713 %
4714 % \begin{environment}{eqnalign}
4715 %
4716 % First, sort out some simple things like optional arguments.
4717 %
4718 % \begin{macrocode}
4719 \def\eqnalign{\@ifnextchar[\eqnalign@i{\eqnalign@i[rcl]}}
4720 \def\eqnalign@i[#1]{%
4721 \@ifnextchar[{\eqnalign@ii{#1}}{\eqnalign@ii{#1}[c]}%
4722 }
4723 % \end{macrocode}
4724 %
4725 % Now we actually do the environment. This is fairly easy, actually.
4726 %
4727 % \begin{macrocode}
4728 \def\eqnalign@ii#1[#2]{%
4729 \let\\\eqn@cr%
4730 \colset{eqnarray}%
4731 \tab@initread%
4732 \def\tab@tabtext{&\tabskip\z@skip}%
4733 \tabskip\z@skip%
4734 \col@sep.5\eqainskip%
4735 \tab@readpreamble{#1}%
4736 \everycr{}%
4737 \if#2t\vtop\else%
4738 \if#2b\vbox\else%
4739 \vcenter%
4740 \fi%
4741 \fi%
4742 \bgroup%
4743 \halign\expandafter\bgroup\the\tab@preamble\cr%
4744 }
4745 % \end{macrocode}
4746 %
4747 % Finishing the environment is even simpler.
4748 %
4749 % \begin{macrocode}
4750 \def\endeqnalign{%
4751 \crcr%
4752 \egroup%
4753 \egroup%
4754 }
4755 % \end{macrocode}
4756 %
4757 % \end{environment}
4758 %
4759 % \begin{macro}{\eqn@cr}
4760 %
4761 % Newlines are really easy here.
4762 %
4763 % \begin{macrocode}
4764 \def\eqn@cr{\tab@cr\eqn@cr@i{}{}}
4765 \def\eqn@cr@i#1{\cr\noalign{\vskip\jot\vskip#1}\@gobble}
4766 % \end{macrocode}
4767 %
4768 % \end{macro}
4769 %
4770 %
4771 % \subsection{Simple multiline equations}
4772 %
4773 % As a sort of example and abbreviation, here's a multiline display
4774 % environment which just centres everything.
4775 %
4776 % \begin{environment}{eqlines}
4777 %
4778 % We just get |\eqnarray| to do everything for us. This is really easy.
4779 %
4780 % \begin{macrocode}
4781 \def\eqlines{\eqnarray[x]}
4782 \let\endeqlines\endeqnarray
4783 % \end{macrocode}
4784 %
4785 % \end{environment}
4786 %
4787 % \begin{environment}{eqlines*}
4788 %
4789 % There's a $*$ version which omits numbers. This is easy too. Lots of
4790 % hacking with expansion here to try and reduce the number of tokens being
4791 % used. Is it worth it?
4792 %
4793 % \begin{macrocode}
4794 \expandafter\edef\csname eqlines*\endcsname{%
4795 \expandafter\noexpand\csname eqnarray*\endcsname[x]%
4796 }
4797 \expandafter\let\csname endeqlines*\expandafter\endcsname
4798 \csname endeqnarray*\endcsname
4799 % \end{macrocode}
4800 %
4801 % \end{environment}
4802 %
4803 %
4804 % \subsection{Split equations}
4805 %
4806 % Based on an idea from \textit{The \TeX book}, we provide some simple
4807 % environments for doing split equations. There's plenty of scope for
4808 % improvement here, though.
4809 %
4810 % \begin{environment}{spliteqn}
4811 % \begin{environment}{spliteqn*}
4812 %
4813 % The only difference between these two is that the $*$-version doesn't put
4814 % in an equation number by default (although this behaviour can be
4815 % changed by |\eqnumber|).
4816 %
4817 % The fun here mainly concerns putting in the equation number at the right
4818 % place -- for |leqno| users, we need to put the number on the first line;
4819 % otherwise we put it on the last line.
4820 %
4821 % The way we handle this is to have two macros, |\\| (which clearly does
4822 % all the user line breaks) and |\seq@lastcr| which is used at the end of
4823 % the environment to wrap everything up. The |\seq@eqnocr| macro puts an
4824 % equation number on the current line and then does a normal |\\|. It also
4825 % resets |\\| and |\seq@lastcr| so that they don't try to put another
4826 % equation number in. This must be done globally, although anyone who tries
4827 % to nest maths displays will get what they deserve.
4828 %
4829 % For the non-$*$ environment, then, we need to step the equation counter,
4830 % and set |\\| to |\seq@cr| or |\seq@eqnocr| as appropriate for the setting
4831 % of the |leqno| flag -- |\seq@lastcr| always gets set to put an equation
4832 % number in (because it will be reset if the number actually gets done
4833 % earlier -- this catches stupid users trying to put a single row into
4834 % a split environment).
4835 %
4836 % \begin{macrocode}
4837 \def\spliteqn{%
4838 \let\eqa@oldnumber\eqa@number%
4839 \global\let\eqa@number\eqa@eqcount%
4840 \spliteqn@i%
4841 }
4842 % \end{macrocode}
4843 %
4844 % For the $*$ variant, we don't need to bother with equation numbering, so
4845 % this is really easy.
4846 %
4847 % \begin{macrocode}
4848 \@namedef{spliteqn*}{%
4849 \let\eqa@oldnumber\eqa@number%
4850 \gdef\eqa@number{}%
4851 \spliteqn@i%
4852 }
4853 % \end{macrocode}
4854 %
4855 % Ending the environments is easy. Most of the stuff here will be described
4856 % later.
4857 %
4858 % \begin{macrocode}
4859 \def\endspliteqn{%
4860 \hfilneg\seq@lastcr%
4861 \egroup%
4862 \dsp@end%
4863 \global\let\eqa@number\eqa@oldnumber%
4864 \global\advance\c@equation\m@ne%
4865 }
4866 \expandafter\let\csname endspliteqn*\endcsname\endspliteqn
4867 % \end{macrocode}
4868 %
4869 % \end{environment}
4870 % \end{environment}
4871 %
4872 % \begin{macro}{\spliteqn@i}
4873 %
4874 % Here we handle the full display splits. Start a maths display, and make
4875 % each row of the alignment take up the full display width.
4876 %
4877 % The macro |\seq@dosplit| does most of the real work for us -- setting up
4878 % the alignment and so forth. The template column is interesting. There
4879 % are two items glue on both sides of the actual text:
4880 %
4881 % \begin{itemize}
4882 %
4883 % \item Some glue which can shrink. This keeps the display from the edges
4884 % of the page unless we get a really wide item.
4885 %
4886 % \item An |\hfil| to do the alignment. By default, this centres the
4887 % equations. On the first line, however, we put a leading |\hfilneg|
4888 % which cancels the first |\hfil|, making the first row left aligned.
4889 % Similarly, at the end, we put an |\hfilneg| after the last equation
4890 % to right align the last line.
4891 %
4892 % \end{itemize}
4893 %
4894 % We pass this information on as an argument. It's easy really.
4895 %
4896 % \begin{macrocode}
4897 \def\spliteqn@i{%
4898 % \end{macrocode}
4899 %
4900 % First, set up equation numbering properly. See my rant about
4901 % |\refstepcounter| above.
4902 %
4903 % \begin{macrocode}
4904 \stepcounter{equation}%
4905 \def\@currentlabel{\p@equation\theequation}%
4906 % \end{macrocode}
4907 %
4908 % Right; now to sort out the numbering and newline handling. If the number's
4909 % meant to be on the first line (for \textsf{leqno} users), then it gets
4910 % typeset on the first like; otherwise we just do a normal newline on
4911 % all lines except the first. Once |\seq@eqnocr| has done its stuff, it
4912 % redefines all the newline handling not to insert another number.
4913 %
4914 % \begin{macrocode}
4915 \if@leqno%
4916 \global\let\seq@docr\seq@eqnocr%
4917 \else%
4918 \global\let\seq@docr\seq@cr%
4919 \fi%
4920 \global\let\seq@lastcr\seq@eqnocr%
4921 % \end{macrocode}
4922 %
4923 % For my next trick, I'll do some display handling -- start a (possibly
4924 % nested) maths display, set up the |\tabpause| macro appropriately, and
4925 % set the newline command to do the right thing.
4926 %
4927 % \begin{macrocode}
4928 \dsp@start%
4929 \dsp@tabpause%
4930 \def\\{\seq@docr}%
4931 % \end{macrocode}
4932 %
4933 % Finally, call another macro to do the remaining bits of setting up.
4934 %
4935 % \begin{macrocode}
4936 \seq@dosplit%
4937 {\hb@xt@\displaywidth{%
4938 \hskip\splitleft\hfil$\displaystyle##$%
4939 \hfil\hskip\splitright}}%
4940 {\hfilneg}%
4941 }
4942 % \end{macrocode}
4943 %
4944 % \end{macro}
4945 %
4946 % \begin{environment}{subsplit}
4947 %
4948 % For doing splits in the middle of equations, we provide a similar
4949 % environment. Here, we make |\\| just start a new line. We also use
4950 % a |\vcenter| rather than a full maths display. The glue items are also
4951 % a bit different: we use plain double-quads on each side of the item, and
4952 % we need to remove them by hand at the extremities of the environment.
4953 %
4954 % \begin{macrocode}
4955 \def\subsplit{%
4956 \let\\\seq@cr%
4957 \vcenter\bgroup%
4958 \seq@dosplit{\hfil\qquad$##$\qquad\hfil}{\hfilneg\hskip-2em}%
4959 }
4960 % \end{macrocode}
4961 %
4962 % Ending the environment is fairly easy. We remove the final glue item,
4963 % and close the alignment and the vbox.
4964 %
4965 % \begin{macrocode}
4966 \def\endsubsplit{%
4967 \hfilneg\hskip-2em\cr%
4968 \egroup\egroup%
4969 }
4970 % \end{macrocode}
4971 %
4972 % \end{environment}
4973 %
4974 % \begin{macro}{\seq@dosplit}
4975 %
4976 % Here we do most of the real work. Actually, since the preamble is passed
4977 % in as an argument, most of the work is already done. The only thing to
4978 % really note is the template for subsequent columns. To stop users putting
4979 % in extra columns (which is where we put the equation number) we raise an
4980 % error and discard the input in a scratch box register. This template is
4981 % repeated infinitely so as to allow us to put the equation number in nicely.
4982 % However, the final negative glue item won't work properly, so the equation
4983 % will look awful.
4984 %
4985 % \begin{macrocode}
4986 \def\seq@dosplit#1#2{%
4987 \halign\bgroup%
4988 #1&&\mth@err@number\setbox\z@\hbox{##}\cr%
4989 #2\relax%
4990 }
4991 % \end{macrocode}
4992 %
4993 % \end{macro}
4994 %
4995 % \begin{macro}{\seq@eqnocr}
4996 %
4997 % Here's how we set equation numbers. Since the column provided raises
4998 % errors as soon as a token finds its way into it, we start with a |&\omit|.
4999 % Then we just put the equation number in a zero-width box. Finally, we
5000 % reset the newline commands to avoid putting in more than one equation
5001 % number, and do normal newline things.
5002 %
5003 % \begin{macrocode}
5004 \def\seq@eqnocr{%
5005 &\omit%
5006 \hb@xt@\z@{\hss\eqa@eqpos\eqa@number}%
5007 \global\let\seq@docr\seq@cr%
5008 \global\let\seq@lastcr\seq@cr%
5009 \seq@cr%
5010 }
5011 % \end{macrocode}
5012 %
5013 % \end{macro}
5014 %
5015 % \begin{macro}{\seq@cr}
5016 %
5017 % Newlines are very easy. We add a |\jot| of extra space, since this is
5018 % a nice thing to do.
5019 %
5020 % \begin{macrocode}
5021 \def\seq@cr{\tab@cr\seq@cr@i\interdisplaylinepenalty\@M}
5022 \def\seq@cr@i#1#2{\cr\noalign{\penalty#2\vskip\jot\vskip#1}}
5023 % \end{macrocode}
5024 %
5025 % \end{macro}
5026 %
5027 %
5028 % \subsection{Matrix handling}
5029 %
5030 % There's been a complete and total overhaul of the spacing calculations
5031 % for matrices here. The vertical spacing now bears an uncanny similarity
5032 % to the rules \TeX\ uses to space out |\atop|-like fractions, the difference
5033 % being that you can have more than one column in a matrix. This has the
5034 % interesting side-effect that we get an \package{amsmath}-style
5035 % sub/superscript environment almost free of charge with the matrix handling
5036 % (it just ends up being a script-size single-column matrix).
5037 %
5038 % What is rather gratifying is that our \env{matrix} environment looks
5039 % rather nicer than \package{amsmath}'s (which is based directly on
5040 % \env{array}, giving it nasty restrictions on the numbers of columns and
5041 % so on); in particular, the version here gives the `correct' result for
5042 % Knuth's exercise~18.42 (which states categorically that a |\smallskip|
5043 % should be placed between the rows of the big matrix).
5044 %
5045 % The reason the interrow space doesn't come out in the AMS version is
5046 % that \env{array} inserts extra vertical space by extending the depth of
5047 % the final row using a strut: the big matrix already extends deeper than
5048 % this, so the strut doesn't make any difference. If the space was added
5049 % by |\hlx{s[\smallskipamount]}| instead of the |\\| command, things would
5050 % be different.
5051 %
5052 % \begin{figure}
5053 %
5054 % ^^A This is essentially what amsmath (version 1.2b) does. The real
5055 % ^^A implementation requires a counter MaxMatrixCols, and has fewer braces:
5056 % ^^A that's all the difference. Oh, and I turn off \arrayextrasep here,
5057 % ^^A since amsmath doesn't expect it to be there (accurate emulation, see?)
5058 % ^^A and I've used \hspace instead of \hskip since everything else is
5059 % ^^A `proper' LaTeX stuff.
5060 %
5061 % \newenvironment{ams-pmatrix}{^^A
5062 % \setlength{\arrayextrasep}{0pt}^^A
5063 % \left(^^A
5064 % \hspace{-\arraycolsep}^^A
5065 % \begin{array}{*{10}{c}}^^A
5066 % }{^^A
5067 % \end{array}^^A
5068 % \hspace{-\arraycolsep}^^A
5069 % \right)^^A
5070 % }
5071 %
5072 % \begin{demo}{Exercise 18.42 from \emph{The \TeX book}}
5073 %\newcommand{\domatrix}[1]{
5074 % \def\mat##1
5075 % {\begin{#1}##1\end{#1}}
5076 % \[ \begin{#1}
5077 % \mat{a & b \\ c & d} &
5078 % \mat{e & f \\ g & h}
5079 % \\[\smallskipamount]
5080 % 0 &
5081 % \mat{i & j \\ k & l}
5082 % \end{#1}
5083 % \]
5084 %}
5085 %\domatrix{pmatrix}
5086 %\domatrix{ams-pmatrix}
5087 % \end{demo}
5088 %
5089 % \end{figure}
5090 %
5091 % \begin{environment}{genmatrix}
5092 %
5093 % The first job is to store my maths style and font away, because I'll be
5094 % needing it lots later.
5095 %
5096 % \begin{macrocode}
5097 \def\genmatrix#1#2#3#4#5{%
5098 \let\mat@style#1%
5099 \ifx#2\scriptstyle%
5100 \let\mat@font\scriptfont%
5101 \else\ifx#2\scriptscriptstyle%
5102 \let\mat@font\scriptscriptfont%
5103 \else%
5104 \let\mat@font\textfont%
5105 \fi\fi%
5106 % \end{macrocode}
5107 %
5108 % Now to cope with inserted text. This is easy.
5109 %
5110 % \begin{macrocode}
5111 \ifx\mat@style\scriptstyle%
5112 \let\mat@textsize\scriptsize%
5113 \else\ifx\mat@style\scriptscriptstyle%
5114 \let\mat@textsize\scriptscriptsize%
5115 \else%
5116 \let\mat@textsize\relax%
5117 \fi\fi%
5118 % \end{macrocode}
5119 %
5120 % Now for some fun. I'll remember how to start and end the matrix in a
5121 % couple of macros |\mat@left| and |\mat@right|. I haven't yet worked out
5122 % exactly what needs to be in |\mat@right| yet, though, so I'll build that
5123 % up in a scratch token list while I'm making my mind up.
5124 %
5125 % Initially, I want to open a group (to trap the style changes), set the
5126 % maths style (to get the right spacing), insert the left delimiter, insert
5127 % some spacing around the matrix, and start a centred box. The ending just
5128 % closes all the groups and delimiters I opened.
5129 %
5130 % \begin{macrocode}
5131 \def\mat@left{\bgroup\mat@style\left#4#3\vcenter\bgroup}%
5132 \toks@{\egroup#3\right#5\egroup}%
5133 % \end{macrocode}
5134 %
5135 % Now comes a slightly trickier bit. If the maths style is script or
5136 % scriptscript, then I need to raise the box by a little bit to make it look
5137 % really good. The right amount is somewhere around \smallf 3/4\,pt, I
5138 % think, so that's what I'll use.
5139 %
5140 % \begin{macrocode}
5141 \@tempswatrue%
5142 \ifx\mat@style\displaystyle\else\ifx\mat@style\textstyle\else%
5143 \@tempswafalse%
5144 \setbox\z@\hbox\bgroup$%
5145 \toks@\expandafter{\the\toks@$\m@th\egroup\raise.75\p@\box\z@}%
5146 \fi\fi%
5147 % \end{macrocode}
5148 %
5149 % If I'm not in maths mode right now, then I should enter maths mode, and
5150 % remember to leave it later.
5151 %
5152 % \begin{macrocode}
5153 \if@tempswa\ifmmode\else%
5154 $\m@th%
5155 \toks@\expandafter{\the\toks@$}%
5156 \fi\fi%
5157 % \end{macrocode}
5158 %
5159 % Now I've sorted out how to end the environment properly, so I can set up
5160 % the macro, using |\edef|.
5161 %
5162 % \begin{macrocode}
5163 \edef\mat@right{\the\toks@}%
5164 % \end{macrocode}
5165 %
5166 % Now see if there's an optional argument. If not, create lots of centred
5167 % columns.
5168 %
5169 % \begin{macrocode}
5170 \@ifnextchar[\genmatrix@i{\genmatrix@i[[c]}%
5171 }
5172 % \end{macrocode}
5173 %
5174 % Now to sort out everything else.
5175 %
5176 % \begin{macrocode}
5177 \def\genmatrix@i[#1]{%
5178 % \end{macrocode}
5179 %
5180 % Some initial setting up: choose the correct column set, and set up some
5181 % variables for reading the preamble.
5182 %
5183 % \begin{macrocode}
5184 \colset{matrix}%
5185 \tab@initread%
5186 % \end{macrocode}
5187 %
5188 % Now comes some of the tricky stuff. The space between columns should be
5189 % 12\,mu (by trial and error). We put the space in a box so we can measure
5190 % it in the correct mathstyle.
5191 %
5192 % \begin{macrocode}
5193 \setbox\z@\hbox{$\mat@style\mskip12mu$}%
5194 \edef\tab@tabtext{&\kern\the\wd\z@}%
5195 \tab@readpreamble{#1}%
5196 % \end{macrocode}
5197 %
5198 % Now we need to decide how to space out the rows. The code here is based
5199 % on the information in appendix~G of \emph{The \TeX book}: I think it'd be
5200 % nice if my matrices were spaced out in the same way as normal fractions
5201 % (particularly |\choose|y things). The standard |\baselineskip| and
5202 % |\lineskip| parameters come in really handy here.
5203 %
5204 % The parameters vary according to the size of the text, so I need to see
5205 % if we have scriptsize or less, or not. The tricky |\if| sorts this out.
5206 %
5207 % \begin{macrocode}
5208 \if1\ifx\mat@style\scriptstyle1\else%
5209 \ifx\mat@style\scriptscriptstyle1\else0\fi\fi%
5210 \baselineskip\fontdimen10\mat@font\tw@%
5211 \advance\baselineskip\fontdimen12\mat@font\tw@%
5212 \lineskip\thr@@\fontdimen8\mat@font\thr@@%
5213 \else%
5214 \baselineskip\fontdimen8\mat@font\tw@%
5215 \advance\baselineskip\fontdimen11\mat@font\tw@%
5216 \lineskip7\fontdimen8\mat@font\thr@@%
5217 \fi%
5218 \lineskiplimit\lineskip%
5219 % \end{macrocode}
5220 %
5221 % Now actually set up for the alignment. Assign |\\| to the correct value.
5222 % Set up the |\tabskip|. Do the appropriate |\mat@left| thing set up above.
5223 % And then start the alignment.
5224 %
5225 % \begin{macrocode}
5226 \let\\\mat@cr%
5227 \tabskip\z@skip%
5228 \col@sep\z@%
5229 \mat@left%
5230 \halign\expandafter\bgroup\the\tab@preamble\tabskip\z@skip\cr%
5231 % \end{macrocode}
5232 %
5233 % Now for a little hack to make the spacing consistent between matrices of
5234 % the same height. This comes directly from \PlainTeX. This appears to
5235 % make the spacing \emph{exactly} the same as the \TeX\ primitives, oddly
5236 % enough.
5237 %
5238 % \begin{macrocode}
5239 \ifx\mat@font\textfont%
5240 \omit$\mat@style\mathstrut$\cr\noalign{\kern-\baselineskip}%
5241 \fi%
5242 }
5243 % \end{macrocode}
5244 %
5245 % Finishing the environment is really easy. We do the spacing hack again
5246 % at the bottom, close the alignment and then tidy whatever we started in
5247 % |\mat@left|.
5248 %
5249 % \begin{macrocode}
5250 \def\endgenmatrix{%
5251 \crcr%
5252 \ifx\mat@font\textfont%
5253 \omit$\mat@style\mathstrut$\cr\noalign{\kern-\baselineskip}%
5254 \fi%
5255 \egroup%
5256 \mat@right%
5257 }
5258 % \end{macrocode}
5259 %
5260 % \end{environment}
5261 %
5262 % \begin{macro}{\mat@cr}
5263 %
5264 % Newlines are really easy. The $*$-form means nothing here, so we ignore
5265 % it.
5266 %
5267 % \begin{macrocode}
5268 \def\mat@cr{\tab@cr\mat@cr@i{}{}}
5269 \def\mat@cr@i#1{\cr\noalign{\vskip#1}\@gobble}
5270 % \end{macrocode}
5271 %
5272 % \end{macro}
5273 %
5274 % \begin{macro}{\newmatrix}
5275 %
5276 % This is how we define new matrix environments. It's simple fun with
5277 % |\csname| and |\expandafter|.
5278 %
5279 % \begin{macrocode}
5280 \def\newmatrix#1#2{%
5281 \@namedef{#1}{\genmatrix#2}%
5282 \expandafter\let\csname end#1\endcsname\endgenmatrix%
5283 }
5284 % \end{macrocode}
5285 %
5286 % \end{macro}
5287 %
5288 % \begin{environment}{matrix}
5289 % \begin{environment}{pmatrix}
5290 % \begin{environment}{dmatrix}
5291 % \begin{environment}{smatrix}
5292 % \begin{environment}{spmatrix}
5293 % \begin{environment}{sdmatrix}
5294 % \begin{environment}{smatrix*}
5295 % \begin{environment}{spmatrix*}
5296 % \begin{environment}{sdmatrix*}
5297 %
5298 % Now we define all the other environments we promised. This is easy.
5299 %
5300 % \begin{macrocode}
5301 \newmatrix{matrix}{{\textstyle}{\textstyle}{\,}{.}{.}}
5302 \newmatrix{pmatrix}{{\textstyle}{\textstyle}{\,}{(}{)}}
5303 \newmatrix{dmatrix}{{\textstyle}{\textstyle}{\,}}
5304 \newmatrix{smatrix}{{\scriptstyle}{\scriptstyle}{}{.}{.}}
5305 \newmatrix{spmatrix}{{\scriptstyle}{\scriptstyle}{}{(}{)}}
5306 \newmatrix{sdmatrix}{{\scriptstyle}{\scriptstyle}{}}
5307 \newmatrix{smatrix*}{{\scriptstyle}{\textstyle}{}{.}{.}}
5308 \newmatrix{spmatrix*}{{\scriptstyle}{\textstyle}{}{(}{)}}
5309 \newmatrix{sdmatrix*}{{\scriptstyle}{\textstyle}{}}
5310 % \end{macrocode}
5311 %
5312 % \end{environment}
5313 % \end{environment}
5314 % \end{environment}
5315 % \end{environment}
5316 % \end{environment}
5317 % \end{environment}
5318 % \end{environment}
5319 % \end{environment}
5320 % \end{environment}
5321 %
5322 % \begin{environment}{script}
5323 %
5324 % Now for superscripts and subscripts. This is fairly easy, because I
5325 % took so much care over the matrix handling.
5326 %
5327 % \begin{macrocode}
5328 \def\script{%
5329 \let\mat@style\scriptstyle%
5330 \def\mat@left{\vcenter\bgroup}%
5331 \def\mat@right{\egroup}%
5332 \let\mat@font\scriptfont%
5333 \let\mat@textsize\scriptsize%
5334 \@ifnextchar[\genmatrix@i{\genmatrix@i[c]}%
5335 }
5336 \let\endscript\endgenmatrix
5337 % \end{macrocode}
5338 %
5339 % \end{environment}
5340 %
5341 % Now define the column types.
5342 %
5343 % \begin{macrocode}
5344 \colpush{matrix}
5345 \coldef l{\tabcoltype{\kern\z@$\mat@style}{\m@th$\hfil}}
5346 \coldef c{\tabcoltype{\hfil$\mat@style}{\m@th$\hfil}}
5347 \coldef r{\tabcoltype{\hfil$\mat@style}{\m@th$}}
5348 \coldef T#1{\tab@aligncol{#1}{\begingroup\mat@textsize}{\endgroup}}
5349 \collet > [tabular]>
5350 \collet < [tabular]<
5351 \collet * [tabular]*
5352 \collet @ [tabular]@
5353 % \end{macrocode}
5354 %
5355 % The repeating type is more awkward. Things will go wrong if this is
5356 % given before the first column, so we must do a whole repeat by hand. We
5357 % can tell if we haven't contributed a column yet, since |\tab@column| will
5358 % be zero. Otherwise, we fiddle the parser state to start a new column, and
5359 % insert the |&| character to make \TeX\ repeat the preamble.
5360 %
5361 % \begin{macrocode}
5362 \coldef {[}{%
5363 \@firstoftwo{%
5364 \ifnum\tab@columns=\z@%
5365 \def\@tempa##1\q@delim{%
5366 \tab@mkpreamble##1[##1\q@delim%
5367 }%
5368 \expandafter\@tempa%
5369 \else%
5370 \tab@setstate\tab@prestate%
5371 \tab@append\tab@preamble{&}%
5372 \expandafter\tab@mkpreamble%
5373 \fi%
5374 }%
5375 }
5376 % \end{macrocode}
5377 %
5378 % We're done defining columns now.
5379 %
5380 % \begin{macrocode}
5381 \colpop
5382 % \end{macrocode}
5383 %
5384 %
5385 % \subsection{Dots\dots}
5386 %
5387 % Nothing whatsoever to do with alignments, although vertical and diagonal
5388 % dots in small matrices look really silly. The following hacky definitions
5389 % work rather better.
5390 %
5391 % \begin{macro}{\mdw@dots}
5392 %
5393 % First of all, here's some definitions common to both of the dots macros.
5394 % The macro takes as an argument the actual code to draw the dots, passing
5395 % it the scaled size of a point in the scratch register |\dimen@|; the
5396 % register |\box 0| is set to contain a dot of the appropriate size.
5397 %
5398 % \begin{macrocode}
5399 \def\mdw@dots#1{\ensuremath{\mathpalette\mdw@dots@i{#1}}}
5400 \def\mdw@dots@i#1#2{%
5401 \setbox\z@\hbox{$#1\mskip1.8mu$}%
5402 \dimen@\wd\z@%
5403 \setbox\z@\hbox{$#1.$}%
5404 #2%
5405 }
5406 % \end{macrocode}
5407 %
5408 % \end{macro}
5409 %
5410 % \begin{macro}{\vdots}
5411 %
5412 % I'll start with the easy one. This is a simple translation of the original
5413 % implementation.
5414 %
5415 % \begin{macrocode}
5416 \def\vdots{%
5417 \mdw@dots{\vbox{%
5418 \baselineskip4\dimen@%
5419 \lineskiplimit\z@%
5420 \kern6\dimen@%
5421 \copy\z@\copy\z@\box\z@%
5422 }}%
5423 }
5424 % \end{macrocode}
5425 %
5426 % \end{macro}
5427 %
5428 % \begin{macro}{\ddots}
5429 %
5430 % And I'll end with the other easy one\dots
5431 %
5432 % \begin{macrocode}
5433 \def\ddots{%
5434 \mdw@dots{\mathinner{%
5435 \mkern1mu%
5436 \raise7\dimen@\vbox{\kern7\dimen@\copy\z@}%
5437 \mkern2mu%
5438 \raise4\dimen@\copy\z@%
5439 \mkern2mu%
5440 \raise\dimen@\box\z@%
5441 \mkern1mu%
5442 }}%
5443 }
5444 % \end{macrocode}
5445 %
5446 % \end{macro}
5447 %
5448 %
5449 % \subsection{Lucky dip}
5450 %
5451 % Time to round off with some trivial environments, just to show how easy
5452 % this stuff is.
5453 %
5454 % \begin{environment}{cases}
5455 % \begin{environment}{smcases}
5456 %
5457 % These are totally and utterly trivial.
5458 %
5459 % \begin{macrocode}
5460 \def\cases{\left\{\,\array{@{}lTl@{}}}
5461 \def\endcases{\endarray\,\right.}
5462 \def\smcases{\left\{\smarray{@{}lTl@{}}}
5463 \def\endsmcases{\endsmarray\,\right.}
5464 % \end{macrocode}
5465 %
5466 % \end{environment}
5467 % \end{environment}
5468 %
5469 % \subsection{Error messages}
5470 %
5471 % Some token saving:
5472 %
5473 % \begin{macrocode}
5474 \def\mth@error{\PackageError{mathenv}}
5475 % \end{macrocode}
5476 %
5477 % Now for the error messages.
5478 %
5479 % \begin{macrocode}
5480 \def\mth@err@number{%
5481 \mth@error{Too many `&' characters found}{%
5482 You've put too many `&' characters in an alignment^^J%
5483 environment (like `eqnarray' or `spliteqn') and wandered^^J%
5484 into trouble. I've gobbled the contents of that column^^J%
5485 and hopefully I can recover fairly easily.%
5486 }%
5487 }
5488 % \end{macrocode}
5489 %
5490 % \begin{macrocode}
5491 \def\mth@err@mdsp{%
5492 \mth@error{Can't do displays in nondisplay maths mode}{%
5493 You're trying to start a display environment, but you're^^J%
5494 in nondisplay maths mode. The display will appear but^^J%
5495 don't blame me when it looks horrible.%
5496 }%
5497 }
5498 % \end{macrocode}
5499 %
5500 % \begin{macrocode}
5501 \def\mth@err@hdsp{%
5502 \mth@error{Can't do displays in LR mode}{%
5503 You're trying to start a display environment, but you're^^J%
5504 in LR (restricted horizontal) mode. Everything will go^^J%
5505 totally wrong, so your best bet is to type `X', fix the^^J%
5506 mistake and start again.%
5507 }%
5508 }
5509 % \end{macrocode}
5510 %
5511 % \vskip\parskip\vbox{ ^^A The best way I could find of keeping this lot
5512 % ^^A together, I'm afraid.
5513 % That's all there is. Byebye.
5514 %
5515 % \begin{macrocode}
5516 %</mathenv>
5517 % \end{macrocode}
5518 % \nopagebreak
5519 %
5520 % \hfill Mark Wooding, \today
5521 % }
5522 %
5523 % \Finale
5524 %
5525 \endinput