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