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