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