Only try to patch XeTeX-specific code when XeTeX is in use!
[latex2e.git] / latex2e-20151001 / base / lttab.dtx
blob3735baa2b03530f0ee814a7291c8724e7bfdd1ac
1 % \iffalse meta-comment
3 % Copyright 1993-2015
4 % The LaTeX3 Project and any individual authors listed elsewhere
5 % in this file.
7 % This file is part of the LaTeX base system.
8 % -------------------------------------------
10 % It may be distributed and/or modified under the
11 % conditions of the LaTeX Project Public License, either version 1.3c
12 % of this license or (at your option) any later version.
13 % The latest version of this license is in
14 %    http://www.latex-project.org/lppl.txt
15 % and version 1.3c or later is part of all distributions of LaTeX
16 % version 2005/12/01 or later.
18 % This file has the LPPL maintenance status "maintained".
20 % The list of all files belonging to the LaTeX base distribution is
21 % given in the file `manifest.txt'. See also `legal.txt' for additional
22 % information.
24 % The list of derived (unpacked) files belonging to the distribution
25 % and covered by LPPL is defined by the unpacking scripts (with
26 % extension .ins) which are part of the distribution.
28 % \fi
30 % \iffalse
31 %%% From File: lttab.dtx
32 %<*driver>
33 % \fi
34 \ProvidesFile{lttab.dtx}[2015/02/21 v1.1n LaTeX Kernel (Columns)]
35 % \iffalse
36 \documentclass{ltxdoc}
37 \GetFileInfo{lttab.dtx}
38 \title{\filename}
39 \date{\filedate}
40  \author{%
41   Johannes Braams\and
42   David Carlisle\and
43   Alan Jeffrey\and
44   Leslie Lamport\and
45   Frank Mittelbach\and
46   Chris Rowley\and
47   Rainer Sch\"opf}
49 \begin{document}
50  \MaintainedByLaTeXTeam{latex}
51  \maketitle
52  \DocInput{\filename}
53 \end{document}
54 %</driver>
55 % \fi
58 % \CheckSum{1127}
60 % \changes{v1.0l}{1995/05/07}{Use \cs{hb@xt@}}
61 % \changes{v1.1a}{1995/05/22}{Support autoloading feature}
62 % \changes{v1.1b}{1995/06/14}{Use \cs{ProvidesFile} in autoload}
63 % \changes{v1.1d}{1995/10/04}{Modify autoload support}
64 % \changes{v1.1k}{1998/06/18}{Small addition to documentation}
65 % \changes{v1.1l}{1998/07/06}{Small correction to documentation}
66 % \changes{v1.1n}{2015/02/21}{Removed autoload code}
68 % \section{Tabbing, Tabular and Array Environments}
69 % This section deals with `Lining It Up in Columns'. First the
70 % |tabbing| environment is defined, and then in second part, |tabular|
71 % together with its variants, |tabular*| and |array|.
73 % Note that the |tabular| defined here is essentially the original
74 % \LaTeX~2.09 version, not the extended version described in \emph{The
75 % \LaTeX\ Companion}. Use the |array| package to obtain the extended
76 % version.
78 % \StopEventually{}
81 % \changes{v1.0a}{1994/03/04}{Initial version, split from latex.dtx}
82 % \changes{v1.0a}{1994/03/07}{Long lines wrapped to 72 columns}
83 % \changes{v1.0b}{1994/03/28}{Improve documentation}
84 % \changes{v1.0c}{1994/05/07}{Removed definition of \cs{+}}
85 % \changes{v1.0c}{1994/05/07}{Removed surplus braces from
86 %                             \cs{@ifnextchar} constructs}
87 % \changes{v1.0f}{1994/05/21}{Use new error commands}
88 % \changes{v1.0j}{1994/11/17}
89 %         {\cs{@tempa} to \cs{reserved@a}}
91 % \subsection{tabbing}
93 % \begin{oldcomments}
95 %  \dimen(\@firsttab + i) = distance of tab stop i from left margin
96 %         0 <= i <= 15 (?).
98 %  \dimen\@firsttab is initialized to \@totalleftmargin, so it starts
99 %      at the prevailing left margin.
101 %  \@maxtab          = number of highest defined tab register
102 %                       probably = \@firsttab + 12
103 %  \@nxttabmar = tab stop number of next line's left margin
104 %  \@curtabmar = tab stop number of current line's left margin
105 %  \@curtab    = number of the current tab. At start of line,
106 %                      it equals \@curtabmar
107 %  \@hightab   = largest tab number currently defined.
108 %  \@tabpush   = depth of \pushtab's
110 %  \box\@curline     = contents of current line, excluding left margin
111 %                       skip, and excluding contents of current field
112 %  \box\@curfield    = contents of current field
114 %  @rjfield          = switch: T iff the last field of the line should
115 %                       be right-justified at the right margin.
117 %  \tabbingsep          = distance left by the \' command between the
118 %                       current position and the field that is
119 %                       ``left-shifted''.
121 %  UTILITY MACROS
122 %   \@stopfield  : closes the current field
123 %   \@addfield   : adds the current field to the current line.
124 %   \@contfield  : continues the current field
125 %   \@startfield : begins the next field
126 %   \@stopline   : closes the current line and outputs it
127 %   \@startline  : starts the next line
128 %   \@ifatmargin : an \if that is true iff the current line.
129 %                  has width zero
131 % \@startline ==
132 %  BEGIN
133 %   \@curtabmar :=G \@nxttabmar
134 %   \@curtab :=G \@curtabmar
135 %   \box\@curline :=G null
136 %   \@startfield
137 %   \strut
138 %  END
140 % \@stopline ==
141 %  BEGIN
142 %   \unskip
143 %   \@stopfield
144 %   if @rjfield = T
145 %     then  @rjfield :=G F
146 %           \@tempdima := \@totalleftmargin + \linewidth
147 %           \hb@xt@ \@tempdima{\@itemfudge
148 %                               \hskip \dimen\@curtabmar
149 %                               \box\@curline
150 %                               \hfil
151 %                               \box\@curfield}
152 %     else \@addfield
153 %          \hbox {\@itemfudge
154 %                 \hskip \dimen\@curtabmar
155 %                 \box\@curline}
156 %   fi
157 %  END
159 % \@startfield ==
160 %  BEGIN
161 %    \box\@curfield :=G \hbox {
162 %  END
164 % \@stopfield ==
165 %  BEGIN
166 %     }
167 %  END
169 % \@contfield ==
170 %  BEGIN
171 %   \box\@curfield :=G \hbox { \unhbox\@currfield  %%} brace matching
172 %  END
173 % \@addfield ==
174 %  BEGIN
175 %   \box\@curline :=G \unbox\@curline * \unbox\@curfield
176 %  END
178 % \@ifatmargin ==
179 %  BEGIN
180 %   if  dim of box\@curline = 0pt  then
181 %  END
184 % \tabbing ==
185 %  BEGIN
186 %   \lineskip :=L 0pt
187 %   \> == \@rtab
188 %   \< == \@ltab
189 %   \= == \@settab
190 %   \+ == \@tabplus
191 %   \- == \@tabminus
192 %   \` == \@tabrj
193 %   \' == \@tablab
194 %   \\ == BEGIN \@stopline \@startline END
195 %   \\[DIST] == BEGIN
196 %                \@stopline \vskip DIST \@startline\ignorespaces END
197 %   \\* == BEGIN \@stopline \penalty 10000 \@startline END
198 %   \\*[DIST] == BEGIN \@stopline \penalty 10000 \vskip DIST
199 %                      \@startline\ignorespaces               END
200 %   \@hightab :=  \@nxttabmar :=G \@firsttab
201 %   \@tabpush :=G 0
202 %   \dimen\@firsttab := \@totalleftmargin
203 %   @rjfield :=G F
204 %   \trivlist  \item\relax
205 %   if @minipage = F then \vskip \parskip fi
206 %   \box\@tabfbox = \rlap{\indent\the\everypar}
207 %                          % note: \the\everypar sets @inlabel :=G F
208 %   \@itemfudge == BEGIN \box\@tabfbox END
209 %   \@startline
210 %   \ignorespaces
211 %  END
213 % \@endtabbing ==
214 %  BEGIN
215 %   \@stopline
216 %   if \@tabpush > 0 then error message: ''unmatched \poptabs'' fi
217 %   \endtrivlist
218 %  END
220 % \@rtab ==
221 %  BEGIN
222 %   \@stopfield
223 %   \@addfield
224 %   if \@curtab < \@hightab
225 %     then \@curtab :=G \@curtab + 1
226 %     else error message ``Undefined Tab''   fi
227 %   \@tempdima := \dimen\@curtab - \dimen\@curtabmar
228 %                        - width of box \@curline
229 %   \box\@curline :=G \hbox{\unhbox\@curline + \hskip\@tempdima}
230 %   \@startfield
231 %  END
233 % \@settab ==
234 %  BEGIN
235 %   \@stopfield
236 %   \@addfield
237 %   if \@curtab < \@maxtab
238 %     then \@curtab :=G \@curtab+1
239 %     else error message: ``Too many tabs''    fi
240 %   if \@curtab > \@hightab
241 %     then \@hightab :=L \@curtab    fi
242 %   \dimen\@curtab :=L \dimen\@curtabmar + width of \box\@curline
243 %   \@startfield
244 %  END
246 % \@ltab ==
247 %  BEGIN
248 %   \@ifatmargin
249 %     then if \@curtabmar > \@firsttab
250 %            then \@curtab :=G \@curtab - 1
251 %                 \@curtabmar :=G \@curtabmar - 1
252 %            else error message ``Too many untabs''      fi
253 %     else error message ``Left tab in middle of line''
254 %   fi
255 %  END
257 % \@tabplus ==
258 %  BEGIN
259 %        if  \@nxttabmar < \@hightab
260 %           then \@nxttabmar :=G \@nxttabmar+1
261 %           else error message ``Undefined tab''
262 %        fi
263 %  END
265 % \@tabminus ==
266 %  BEGIN
267 %        if \@nxttabmar > \@firsttab
268 %           then \@nxttabmar :=G \@nxttabmar-1
269 %           else error message ``Too many untabs''
270 %        fi
271 %  END
273 % \@tabrj ==
274 %  BEGIN \@stopfield
275 %        \@addfield
276 %        @rjfield :=G T
277 %        \@startfield
278 %  END
280 % \@tablab ==
281 %  BEGIN \@stopfield
282 %      \box\@curline G:= \hbox{\box\@curline %% `G' added 17 Jun 86
283 %                              \hskip - width of \box\@curfield
284 %                              \hskip -\tabbingsep
285 %                              \box\@curfield
286 %                              \hskip \tabbingsep }
287 %        \@startfield
288 %  END
290 % \pushtabs ==
291 %   BEGIN
292 %     \@stopfield
293 %     \@tabpush :=G \@tabpush + 1
294 %     \begingroup
295 %     \@contfield
296 %   END
298 % \poptabs ==
299 %  BEGIN
300 %    \@stopfield
301 %    if \@tabpush > 0
302 %      then \endgroup
303 %           \@tabpush :=G \@tabpush - 1
304 %      else error message: ``Too many \poptabs''
305 %    fi
306 %    \@contfield
307 %  END
309 % \end{oldcomments}
311 % \begin{macro}{\a}
312 % The accents |\`| , |\'| , and |\=| that have been redefined inside a
313 % tabbing environment can be called by typing |\a`| , |\a'| , and |\a=|.
314 % The macro |\a| is defined in |ltoutenc.dtx|.
315 % \changes{v1.0d}{1994/05/13}
316 %         {moved to ltoutenc}
317 % \end{macro}
320 % The `2ekernel' code ensures that a |\usepackage{autotabg}| is
321 % essentially ignored if a `full' format is being used that has
322 % picture mode already in the format.
323 %    \begin{macrocode}
324 %<2ekernel>\expandafter\let\csname ver@autotabg.sty\endcsname\fmtversion
325 %    \end{macrocode}
327 % \begin{macro}{\@firsttab}
328 % \begin{macro}{\@maxtab}
329 % \changes{v1.0c}{1994/05/07}{Changed \cs{@firsttab} to \cs{chardef}}
330 % \changes{v1.0c}{1994/05/07}{Changed \cs{@maxtab} to \cs{chardef}}
331 %    \begin{macrocode}
332 %<*2ekernel>
333 \newdimen\@gtempa
334 \chardef\@firsttab=\the\allocationnumber
335 \newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa
336 \newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa
337 \newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa
338 \newdimen\@gtempa
339 \chardef\@maxtab=\the\allocationnumber
340 \dimen\@firsttab=0pt
341 %    \end{macrocode}
342 % \end{macro}
343 % \end{macro}
345 % \begin{macro}{\@nxttabmar}
346 % \begin{macro}{\@curtabmar}
347 % \begin{macro}{\@curtab}
348 % \begin{macro}{\@hightab}
349 % \begin{macro}{\@tabpush}
350 %    \begin{macrocode}
351 \newcount\@nxttabmar
352 \newcount\@curtabmar
353 \newcount\@curtab
354 \newcount\@hightab
355 \newcount\@tabpush
356 %    \end{macrocode}
357 % \end{macro}
358 % \end{macro}
359 % \end{macro}
360 % \end{macro}
361 % \end{macro}
363 % \begin{macro}{\@curline}
364 % \begin{macro}{\@curfield}
365 % \begin{macro}{\@tabfbox}
366 %    \begin{macrocode}
367 \newbox\@curline
368 \newbox\@curfield
369 \newbox\@tabfbox
370 %    \end{macrocode}
371 % \end{macro}
372 % \end{macro}
373 % \end{macro}
376 % \begin{macro}{\if@rjfield}
377 %    \begin{macrocode}
378 \newif\if@rjfield
379 %    \end{macrocode}
380 % \end{macro}
382 % \begin{macro}{\@startline}
383 % \changes{v1.1f}{1995/10/23}{(CAR)Ensure that \cs{@nxttabmar} is never
384 % larger than \cs{@hightab}}
385 %    It is, in some sense, an error if the current margin
386 %    tab setting is higher than the value of |\@hightab| (which is
387 %    a local variable).  That this is allowed is a fundamental design
388 %    flaw which is not going to be corrected now.
389 %    \begin{macrocode}
390 \gdef\@startline{%
391      \ifnum \@nxttabmar >\@hightab
392        \@badtab
393        \global\@nxttabmar \@hightab
394      \fi
395      \global\@curtabmar \@nxttabmar
396      \global\@curtab \@curtabmar
397      \global\setbox\@curline \hbox {}%
398      \@startfield
399      \strut}
400 %    \end{macrocode}
401 % \end{macro}
403 % \begin{macro}{\@stopline}
404 %    \begin{macrocode}
405 \gdef\@stopline{%
406   \unskip
407   \@stopfield
408   \if@rjfield
409     \global\@rjfieldfalse
410     \@tempdima\@totalleftmargin
411     \advance\@tempdima\linewidth
412     \hb@xt@\@tempdima{%
413       \@itemfudge\hskip\dimen\@curtabmar
414       \box\@curline
415       \hfil
416       \box\@curfield}%
417   \else
418     \@addfield
419     \hbox{\@itemfudge\hskip\dimen\@curtabmar\box\@curline}%
420   \fi}
421 %    \end{macrocode}
422 % \end{macro}
424 % \begin{macro}{\@startfield}
425 % \changes{v1.0d}{1994/05/13}
426 %         {Colour support}
427 %    \begin{macrocode}
428 \gdef\@startfield{%
429   \global\setbox\@curfield\hbox\bgroup\color@begingroup}
430 %    \end{macrocode}
431 % \end{macro}
433 % \begin{macro}{\@stopfield}
434 % \changes{v1.0d}{1994/05/13}
435 %         {Colour support}
436 %    \begin{macrocode}
437 \gdef\@stopfield{%
438   \color@endgroup\egroup}
439 %    \end{macrocode}
440 % \end{macro}
442 % \begin{macro}{\@contfield}
443 % \changes{v1.0d}{1994/05/13}
444 %         {Colour support}
445 %    \begin{macrocode}
446 \gdef\@contfield{%
447   \global\setbox\@curfield\hbox\bgroup\color@begingroup
448   \unhbox\@curfield}
449 %    \end{macrocode}
450 % \end{macro}
452 % \begin{macro}{\@addfield}
453 %    \begin{macrocode}
454 \gdef\@addfield{\global\setbox\@curline\hbox{\unhbox
455      \@curline\unhbox\@curfield}}
456 %    \end{macrocode}
457 % \end{macro}
459 % \begin{macro}{\@ifatmargin}
460 %    \begin{macrocode}
461 \gdef\@ifatmargin{\ifdim \wd\@curline =\z@}
462 %    \end{macrocode}
463 % \end{macro}
465 % \begin{macro}{\@tabcr}
466 %    \begin{macrocode}
467 \gdef\@tabcr{\@stopline \@ifstar{\penalty \@M \@xtabcr}\@xtabcr}
468 %    \end{macrocode}
469 % \end{macro}
471 % \begin{macro}{\@xtabcr}
472 %    \begin{macrocode}
473 \gdef\@xtabcr{\@ifnextchar[\@itabcr{\@startline\ignorespaces}}
474 %    \end{macrocode}
475 % \end{macro}
477 % \begin{macro}{\@itabcr}
478 %    \begin{macrocode}
479 \gdef\@itabcr[#1]{\vskip #1\@startline\ignorespaces}
480 %    \end{macrocode}
482 %    \begin{macrocode}
483 \gdef\kill{\@stopfield\@startline\ignorespaces}
484 %    \end{macrocode}
485 % \end{macro}
487 % \begin{macro}{\tabbing}
488 % \changes{v1.1f}{1995/10/23}{(CAR)Make \cs{@hightab} consistently a
489 % local variable}
490 % \changes{latex2e}{1993/12/13}{Removed optional argument of \cs{item}}
491 %    We use |\relax| to prevent |\item| from scanning too far.
492 %    \begin{macrocode}
493 \gdef\tabbing{\lineskip \z@skip\let\>\@rtab\let\<\@ltab\let\=\@settab
494      \let\+\@tabplus\let\-\@tabminus\let\`\@tabrj\let\'\@tablab
495      \let\\=\@tabcr
496      \@hightab\@firsttab
497      \global\@nxttabmar\@firsttab
498      \dimen\@firsttab\@totalleftmargin
499      \global\@tabpush\z@ \global\@rjfieldfalse
500      \trivlist \item\relax
501      \if@minipage\else\vskip\parskip\fi
502 %    \end{macrocode}
503 % \changes{v1.1i}{1996/10/21}{Moved the \cs{indent} so that the
504 % \cs{everypar} can remove it when necessary; this is needed because
505 % the code for items in lists has changed (see pr/22111)}
506 %    \begin{macrocode}
507      \setbox\@tabfbox\hbox{%
508        \rlap{\hskip\@totalleftmargin\indent\the\everypar}}%
509      \def\@itemfudge{\box\@tabfbox}%
510      \@startline\ignorespaces}
511 %    \end{macrocode}
512 % \end{macro}
514 % \begin{macro}{\endtabbing}
515 %    \begin{macrocode}
516 \gdef\endtabbing{%
517   \@stopline\ifnum\@tabpush >\z@ \@badpoptabs \fi\endtrivlist}
518 %    \end{macrocode}
519 % \end{macro}
521 % \begin{macro}{\@rtab}
522 % Omitted |\global| added to |\@rtab| 17 Jun 86
523 %    \begin{macrocode}
524 \gdef\@rtab{\@stopfield\@addfield\ifnum \@curtab<\@hightab
525       \global\advance\@curtab \@ne \else\@badtab\fi
526       \@tempdima\dimen\@curtab
527       \advance\@tempdima -\dimen\@curtabmar
528       \advance\@tempdima -\wd\@curline
529       \global\setbox\@curline\hbox{\unhbox\@curline\hskip\@tempdima}%
530       \@startfield\ignorespaces}
531 %    \end{macrocode}
532 % \end{macro}
534 % \begin{macro}{\@settab}
535 % \changes{v1.1f}{1995/10/23}{(CAR)Ensure that \cs{@hightab} increases
536 % by at most one}
537 %    \begin{macrocode}
538 \gdef\@settab{\@stopfield\@addfield
539   \ifnum \@curtab <\@maxtab
540     \ifnum\@curtab =\@hightab
541       \advance\@hightab \@ne
542     \fi
543     \global\advance\@curtab \@ne
544   \else
545     \@latex@error{Tab overflow}\@ehd
546   \fi
547   \dimen\@curtab \dimen\@curtabmar
548   \advance\dimen\@curtab \wd\@curline
549   \@startfield
550   \ignorespaces}
551 %    \end{macrocode}
552 % \end{macro}
554 % \begin{macro}{\@ltab}
555 %    \begin{macrocode}
556 \gdef\@ltab{\@ifatmargin\ifnum\@curtabmar >\@firsttab
557       \global\advance\@curtab \m@ne \global\advance\@curtabmar\m@ne\else
558       \@badtab\fi\else
559       \@latex@error{\string\<\space in mid line}\@ehd\fi\ignorespaces}
560 %    \end{macrocode}
561 % \end{macro}
563 % \begin{macro}{\@tabplus}
564 %    \begin{macrocode}
565 \gdef\@tabplus{%
566   \ifnum\@nxttabmar<\@hightab
567     \global\advance\@nxttabmar\@ne
568   \else
569     \@badtab
570   \fi
571   \ignorespaces}
572 %    \end{macrocode}
573 % \end{macro}
575 % \begin{macro}{\@tabminus}
576 %    \begin{macrocode}
577 \gdef\@tabminus{%
578   \ifnum\@nxttabmar>\@firsttab
579     \global\advance\@nxttabmar\m@ne
580   \else
581     \@badtab
582   \fi
583   \ignorespaces}
584 %    \end{macrocode}
585 % \end{macro}
587 % \begin{macro}{\@tabrj}
588 %    \begin{macrocode}
589 \gdef\@tabrj{%
590   \@stopfield\@addfield\global\@rjfieldtrue\@startfield\ignorespaces}
591 %    \end{macrocode}
592 % \end{macro}
594 % \begin{macro}{\@tablab}
595 % |\setbox\@curline| made |\global| in |\@tablab|. 17 Jun 86
596 %    \begin{macrocode}
597 \gdef\@tablab{%
598   \@stopfield
599   \global\setbox\@curline\hbox{%
600     \box\@curline
601     \hskip-\wd\@curfield \hskip-\tabbingsep
602     \box\@curfield
603     \hskip\tabbingsep}%
604   \@startfield
605   \ignorespaces}
606 %    \end{macrocode}
607 % \end{macro}
609 % \begin{macro}{\pushtabs}
610 %    \begin{macrocode}
611 \gdef\pushtabs{%
612   \@stopfield\@addfield\global\advance\@tabpush \@ne \begingroup
613        \@contfield}
614 %    \end{macrocode}
615 % \end{macro}
617 % \begin{macro}{\poptabs}
618 % \changes{v1.1f}{1995/10/23}{(CAR)Ensure that \cs{@curtab} is never
619 % larger than \cs{@hightab}}
620 %    It is, in some sense, an error if, after the endgroup, the current
621 %    tab setting is higher than the new value of |\@hightab| (which is
622 %    a local variable).  That this is allowed is a fundamental design
623 %    flaw which is not going to be corrected now.
624 %    \begin{macrocode}
625 \gdef\poptabs{\@stopfield\@addfield
626   \ifnum \@tabpush >\z@
627     \endgroup
628     \global\advance\@tabpush \m@ne
629     \ifnum \@curtab >\@hightab
630       \global \@curtab \@hightab
631       \@badtab
632     \fi
633   \else
634     \@badpoptabs
635   \fi
636   \@contfield}
637 %    \end{macrocode}
638 % \end{macro}
641 % \begin{macro}{\tabbingsep}
642 %    \begin{macrocode}
643 \newdimen\tabbingsep
644 %    \end{macrocode}
645 % \end{macro}
649 % \subsection{array and tabular environments}
651 % \begin{oldcomments}
653 % ARRAY PARAMETERS:
654 %  \arraycolsep
655 %       : half the width separating columns in an array environment
656 %  \tabcolsep
657 %       : half the width separating columns in a tabular environment
658 %  \arrayrulewidth
659 %       : width of rules
660 %  \doublerulesep
661 %       : space between adjacent rules in array or tabular
662 %  \arraystretch
663 %       : line spacing in array and tabular environments is done by
664 %         placing a strut in every row of height and depth
665 %         \arraystretch times the height and depth of the strut
666 %         produced by an ordinary \strut command.
668 % PREAMBLE:
669 %  The PREAMBLE argument of an array or tabular environment can
670 %  contain the following:
671 %    l,r,c  : indicate where entry is to be placed.
672 %    |      : for vertical rule
673 %    @{EXP} : inserts the text EXP in every column.
674 %              \arraycolsep or \tabcolsep  spacing is suppressed.
675 %    *{N}{PRE} : equivalent to writing N copies of PRE in the preamble.
676 %                PRE may contain *{N'}{EXP'} expressions.
677 %    p{LEN} : makes entry in parbox of width LEN.
679 % SPECIAL ARRAY COMMANDS:
680 %   \multicolumn{N}{FORMAT}{ITEM} : replaces the next N column
681 %    items by ITEM, formatted according to FORMAT.
682 %    FORMAT should contain at most one l,r or c.
683 %    If it contains none, then ITEM is ignored.
685 %   \vline : draws a vertical line the height of the current row.  May
686 %            appear in an array element entry.
687 %   \hline : draws a horizontal line between rows.  Must appear either
688 %            before the first entry (to appear above the first row) or
689 %             right after a \\ command.  If followed by another \hline,
690 %             then adds a \vskip of \doublerulesep.
692 %   \cline[i-j] : draws horizontal lines between rows covering columns
693 %                 i through j, inclusive.  Multiple commands may follow
694 %                 one another to provide lines covering several disjoint
695 %                 columns
696 %   \extracolsep{WIDTH} : for use inside an @ in the preamble.  Causes
697 %               a WIDTH space to be added between columns for the rest
698 %                of the columns.  This is in addition to the ordinary
699 %                intercolumn space.
701 %  \array ==
702 %    BEGIN
703 %      \@acol    == \@arrayacol
704 %      \@classz  == \@arrayclassz
705 %      \@classiv == \@arrayclassiv
706 %      \\        == \@arraycr
707 %      \@halignto == NULL
708 %      \@tabarray
709 %    END
711 %  \endarray{NAME} ==  BEGIN  \crcr }}  END
713 %  \tabular  ==
714 %    BEGIN
715 %      \@halignto == NULL
716 %      \@tabular
717 %    END
719 %  \tabular*{WIDTH} ==
720 %    BEGIN
721 %      \@halignto == to WIDTH
722 %      \@tabular
723 %    END
725 %  \@tabular ==
726 %    BEGIN
727 %      \leavevmode
728 %      \hbox { $
729 %         \@acol    == \@tabacol
730 %         \@classz  == \@tabclassz
731 %         \@classiv == \@tabclassiv
732 %         \\        == \@tabularcr
733 %         \@tabarray
734 %    END
736 %  \endtabular == BEGIN \crcr}} $} END
738 %  \@tabarray == if next char = [ then \@array else \@array[c] fi
740 %  \@array[POS]{PREAMBLE} ==
741 %    BEGIN
742 %      define \@arstrutbox to make \@arstrut produce strut of height
743 %        and depth \arraystretch times the height and
744 %        depth of a normal strut.
745 %      \@mkpream{PREAMBLE}
746 %      \@preamble == \halign \@halignto {\tabskip=0pt\@arstrut
747 %                              eval{\@preamble}\tabskip = 0pt\cr %%}
748 %      \@startpbox == \@@startpbox
749 %      \@endpbox == \@@endpbox
750 %      if POS = t then \vtop
751 %                 else if POS = b then \vbox
752 %                                 else \vcenter
753 %      fi              fi
754 %     {
755 %      \par          ==L {} % changed 92/09/18
756 %      \@sharp       == #
757 %      \protect      == \relax
758 %      \lineskip     :=L 0pt
759 %      \baselineskip :=L 0pt
760 %      \@preamble
761 %    END
764 %  \@arraycr ==
765 %   BEGIN
766 %     $              %% Prevents extra space at end of row's last entry.
767 %     if next char = [
768 %      then  \@argarraycr
769 %      else  $ \cr         %% Needed to balance $
770 %   END
772 %  \@argarraycr[LENGTH] ==
773 %   BEGIN
774 %     $                    %% Needed to balance $ of \@arraycr
775 %     if LENGTH > 0
776 %       then  \@tempdima := depth of \@arstrutbox + LENGTH
777 %             \vrule height 0pt width 0pt depth \@tempdima
778 %             \cr
779 %       else  \cr \noalign{\vskip LENGTH}
780 %   END
782 %  \@tabularcr and \@argtabularcr  same as \@arraycr and \@argarraycr
783 %  except without the extra $'s.
784 % \end{oldcomments}
787 % \begin{macro}{\extracolsep}
788 %    \begin{macrocode}
789 \def\extracolsep#1{\tabskip #1\relax}
790 %    \end{macrocode}
791 % \end{macro}
793 % \begin{macro}{\array}
794 %    \begin{macrocode}
795 \def\array{\let\@acol\@arrayacol \let\@classz\@arrayclassz
796  \let\@classiv\@arrayclassiv
797  \let\\\@arraycr\let\@halignto\@empty\@tabarray}
798 %    \end{macrocode}
799 % \end{macro}
801 % \begin{macro}{\endarray}
802 % \begin{macro}{\endtabular}
803 % \begin{macro}{\endtabular*}
804 %    \begin{macrocode}
805 \def\endarray{\crcr\egroup\egroup}
806 \def\endtabular{\crcr\egroup\egroup $\egroup}
807 \expandafter \let \csname endtabular*\endcsname = \endtabular
808 %    \end{macrocode}
809 % \end{macro}
810 % \end{macro}
811 % \end{macro}
813 % \begin{macro}{\tabular}
814 %    \begin{macrocode}
815 \def\tabular{\let\@halignto\@empty\@tabular}
816 %    \end{macrocode}
817 % \end{macro}
819 % \begin{macro}{\tabular*}
820 % \changes{v1.1j}{1998/05/18}{Use \cs{setlength}, so that
821 %           calc extensions apply.}
822 %    Note that the change to use |\setlength| slightly alters the
823 %    timing of the expansion and use of the length in |#1| but this is
824 %    very unlikely to have any practical effect.
825 % \changes{latex2e}{1993/08/05}{Replaced \cs{expandafter}\cs{def}
826 %             by \cs{@namedef}.}
827 %    \begin{macrocode}
828 \@namedef{tabular*}#1{%
829  \setlength\dimen@{#1}%
830    \edef\@halignto{to\the\dimen@}\@tabular}
831 %    \end{macrocode}
832 % \end{macro}
834 % \begin{macro}{\@tabular}
835 %    \begin{macrocode}
836 \def\@tabular{\leavevmode \hbox \bgroup $\let\@acol\@tabacol
837    \let\@classz\@tabclassz
838    \let\@classiv\@tabclassiv \let\\\@tabularcr\@tabarray}
839 %    \end{macrocode}
840 % \end{macro}
842 % \begin{macro}{\@tabarray}
843 % RmS 91/11/04 added |\m@th|.
844 %    \begin{macrocode}
845 \def\@tabarray{\m@th\@ifnextchar[\@array{\@array[c]}}
846 %    \end{macrocode}
847 % \end{macro}
849 % RmS 1993/11/03 changed |\halign| to |\ialign| and removed superfluous
850 %              |\tabskip| assignment
853 % \changes{v1.1i}{1996/10/21}{Moved the code associated with
854 % \cs{@mkpream} into the group provided by the box, for robustness
855 % (latex/2183)}
856 % \begin{macro}{\@array}
857 %    \begin{macrocode}
858 \def\@array[#1]#2{%
859   \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi
860 %    \end{macrocode}
861 % \changes{LaTeX2.09}{1992/09/18}
862 %     {Changed \cs{par} to \cs{@empty} to avoid starting new row
863 %               e.g. after \cs{hline}}
864 %    \begin{macrocode}
865   \bgroup
866 %    \end{macrocode}
867 % This next bit of code sets up the strut and then builds the halign
868 % and its preamble according to the specification in the second
869 % argument.
871 % This code has been moved inside the box.
872 % A side effect of this has been to expose what was a buglet in the
873 % previous version: since the |\@arstrut| below is expanded and
874 % contains an |\ifmmode| then it could produce an unnecessary extra
875 % box in every row, thus wasting `lots of' main memory.
876 %    \begin{macrocode}
877   \setbox\@arstrutbox\hbox{%
878     \vrule \@height\arraystretch\ht\strutbox
879            \@depth\arraystretch \dp\strutbox
880            \@width\z@}%
881   \@mkpream{#2}%
882   \edef\@preamble{%
883     \ialign \noexpand\@halignto
884       \bgroup \@arstrut \@preamble \tabskip\z@skip \cr}%
885 %    \end{macrocode}
886 % That is the end of setting up the preamble; now we reset
887 % things before executing the halign built-up in |\@preamble|.
888 % The restorations could be done by introducing an extra group,
889 % thus saving tokens.
890 % \changes{v1.0k}{1994/12/08}{Add \cs{tabularnewline}}
891 % \changes{v1.1i}{1996/10/21}{Use \cs{set@typeset@protect}}
892 %    \begin{macrocode}
893   \let\@startpbox\@@startpbox \let\@endpbox\@@endpbox
894   \let\tabularnewline\\%
895     \let\par\@empty
896     \let\@sharp##%
897     \set@typeset@protect
898     \lineskip\z@skip\baselineskip\z@skip
899 %    \end{macrocode}
900 %    If the parsing of the preamble goes wrong there my be some
901 %    characters left which \TeX{} then tries to typeset, i.e., we
902 %    would be in horizontal mode. That would produce an endless loop
903 %    because the |\halign| expects vertical mode thus issues a |\par|
904 %    but that is a no-op at this point. So we better test this case
905 %    issue some error message and make a crude recovery by ending that
906 %    horizontal mode with force.
907 %    A better fix would be to ensure that we never pick up more than a
908 %    single character token (not done).
909 % \changes{v1.1m}{1998/11/13}{Check for hmode to see if something
910 %     went wrong during parsing (pr/2884)}
911 %    \begin{macrocode}
912     \ifhmode \@preamerr\z@ \@@par\fi
913     \@preamble}
914 %    \end{macrocode}
915 % \end{macro}
917 %  \begin{macro}{\@arraycr}
918 % Array version of |\\|.
919 %    \begin{macrocode}
920 \def\@arraycr{%
921   ${\ifnum0=`}\fi\@ifstar\@xarraycr\@xarraycr}
922 %    \end{macrocode}
923 % \end{macro}
925 %  \begin{macro}{\@arraycr}
926 %    \begin{macrocode}
927 \def\@xarraycr{\@ifnextchar[\@argarraycr{\ifnum0=`{\fi}${}\cr}}
928 %    \end{macrocode}
929 % \end{macro}
931 %  \begin{macro}{\@argarraycr}
932 %    \begin{macrocode}
933 \def\@argarraycr[#1]{%
934   \ifnum0=`{\fi}${}\ifdim #1>\z@ \@xargarraycr{#1}\else
935    \@yargarraycr{#1}\fi}
936 %    \end{macrocode}
937 % \end{macro}
939 %  \begin{macro}{\tabularnewline}
940 % \changes{v1.0i}{1994/11/14}{(DPC) Macro added}
941 % \changes{v1.0k}{1994/12/08}{(DPC) Made it \cs{relax}}
942 % Tabular version of |\\|.
943 %    \begin{macrocode}
944 \let\tabularnewline\relax
945 %    \end{macrocode}
946 % \end{macro}
948 %  \begin{macro}{\@tabularcr}
949 %    \begin{macrocode}
950 \def\@tabularcr{%
951   {\ifnum0=`}\fi\@ifstar\@xtabularcr\@xtabularcr}
952 %    \end{macrocode}
953 % \end{macro}
955 %  \begin{macro}{\@xtabularcr}
956 %    \begin{macrocode}
957 \def\@xtabularcr{\@ifnextchar[\@argtabularcr{\ifnum0=`{\fi}\cr}}
958 %    \end{macrocode}
959 % \end{macro}
961 %  \begin{macro}{\@argtabularcr}
962 %    \begin{macrocode}
963 \def\@argtabularcr[#1]{%
964   \ifnum0=`{\fi}%
965     \ifdim #1>\z@
966       \unskip\@xargarraycr{#1}%
967     \else
968       \@yargarraycr{#1}%
969     \fi}
970 %    \end{macrocode}
971 % \end{macro}
973 %  \begin{macro}{\@xargarraycr}
974 %    \begin{macrocode}
975 \def\@xargarraycr#1{\@tempdima #1\advance\@tempdima \dp \@arstrutbox
976    \vrule \@height\z@ \@depth\@tempdima \@width\z@ \cr}
977 %    \end{macrocode}
978 % \end{macro}
980 %  \begin{macro}{\@yargarraycr}
981 %    \begin{macrocode}
982 \def\@yargarraycr#1{\cr\noalign{\vskip #1}}
983 %    \end{macrocode}
984 % \end{macro}
986 %  \begin{macro}{\multicolumn}
987 % \begin{oldcomments}
988 % \multicolumn{NUMBER}{FORMAT}{ITEM} ==
989 %  BEGIN
990 %  \multispan{NUMBER}
991 %  \begingroup
992 %  \@addamp == null
993 %  \@mkpream{FORMAT}
994 %  \@sharp == ITEM
995 %  \protect == \relax
996 %  \@startpbox == \@@startpbox
997 %  \@endpbox == \@@endpbox
998 %  \@arstrut
999 %  \@preamble
1000 %  \endgroup
1001 %  END
1002 % \end{oldcomments}
1004 % The command |\def\@addamp{}| was removed from |\multicolumn| on
1005 % 6 Dec 86 because it caused embedded array environments not to work.  I
1006 % think that it was included originally to prevent an error message if
1007 % the 2nd argument to the |\multicolumn| command had two column
1008 % specifiers.
1010 % 8 Feb 89 --- |\hbox{}| added after |\@preamble| to correct bug that
1011 %            occurred if |\multicolumn| preceded |\\[D]| with |D > 0|,
1012 %            caused by |\\[]| command doing an |\unskip|, which removed
1013 %            |\tabcolsep| glue inserted by |\multicolumn|.
1016 % \changes{v1.0h}{1994/11/04}{(ASAJ) added \cs{set@typeset@protect}.}
1017 % \changes{v1.1i}{1996/10/21}{Make \cs{multicolumn} long (latex/2180)}
1018 % This has been made long so that, for example, a |p|-column can
1019 % contain multiple paragraphs; maybe the arguments of |@|-expressions
1020 % should also be able to contain multiple paragraphs.
1021 %    \begin{macrocode}
1022 \long\def\multicolumn#1#2#3{\multispan{#1}\begingroup
1023   \@mkpream{#2}%
1024   \def\@sharp{#3}\set@typeset@protect
1025   \let\@startpbox\@@startpbox\let\@endpbox\@@endpbox
1026   \@arstrut \@preamble\hbox{}\endgroup\ignorespaces}
1027 %    \end{macrocode}
1028 % \end{macro}
1030 % \begin{oldcomments}
1031 % Codes for classes and character numbers of array, tabular and
1032 % multicolumn arguments.
1034 %    Character     Class       Number
1035 %    ---------     -----       ------
1036 %        c           0           0
1037 %        l           0           1
1038 %        r           0           2
1040 %        |           1           -
1041 %        @           2           -
1042 %        p           3           -
1043 %      {@-exp}       4           -
1044 %      {p-arg}       5           -
1046 % \@testpach \foo : expands \foo, which should be an array parameter
1047 %           token, and sets \@chclass and \@chnum to its class and
1048 %           number. Uses \@lastchclass to distinguish 4 and 5
1050 % Preamble error codes
1051 %    0: 'illegal character'
1052 %    1: 'Missing @-exp'
1053 %    2: 'Missing p-arg'
1055 % \@addamp ==
1056 %   BEGIN if @firstamp = true then @firstamp := false
1057 %                             else &                     fi
1058 %   END
1060 % \@mkpream TOKENLIST ==
1061 %   BEGIN
1062 %    @firstamp     := T
1063 %    \@lastchclass := 6
1064 %    \@preamble    == null
1065 %    \@sharp       == \relax
1066 %    \protect      == BEGIN \noexpand\protect\noexpand END
1067 %    \@startpbox   == \relax
1068 %    \@endpbox     == \relax
1069 %    \@expast{TOKENLIST}
1070 %    for \@nextchar := expand(\reserved@a)
1071 %      do  \@testpach{\@nextchar}
1072 %          case of \@chclass
1073 %            0 -> \@classz
1074 %            1 -> \@classi
1075 %              ...
1076 %            5 -> \@classv
1077 %          end case
1078 %          \@lastchclass := \@chclass
1079 %      od
1080 %      case of \@lastchclass
1081 %         0 -> \hskip \arraycolsep             % lrc
1082 %         1 ->                                  % |
1083 %         2 -> \@preamerr1 % 'Missing @-exp'    % @
1084 %         3 -> \@preamerr2 % 'Missing p-arg'    % p
1085 %         4 ->                                  % @-exp
1086 %         5 -> \hskip \arraycolsep             % p-exp
1087 %      end case
1088 %   END
1090 %  \@arrayclassz ==
1091 %    BEGIN
1092 %      \@preamble := \@preamble *
1093 %               case of \@lastchclass
1094 %                  0 -> \hskip \arraycolsep \@addamp \hskip \arraycolsep
1095 %                  1 -> \@addamp \hskip \arraycolsep
1096 %                  2 ->  % impossible
1097 %                  3 ->  % impossible
1098 %                  4 -> \@addamp
1099 %                  5 -> \hskip \arraycolsep \@addamp \hskip \arraycolsep
1100 %                  6 -> \@addamp \hskip \arraycolsep
1101 %                end case
1102 %              * case of \@chnum
1103 %                   0 -> \hfil$\relax\@sharp$\hfil
1104 %                   1 -> $\relax\@sharp$\hfil
1105 %                   2 -> \hfil$\relax\@sharp$
1106 %                end case
1107 %    END
1109 % \@tabclassz == similar to \@arrayclassz
1111 % \@classi ==
1112 %  BEGIN
1113 %    \@preamble := \@preamble *
1114 %                  case of \@lastchclass
1115 %                     0 -> \hskip \arraycolsep \@arrayrule
1116 %                     1 -> \hskip \doublerulesep \@arrayrule
1117 %                     2 -> % impossible
1118 %                     3 -> % impossible
1119 %                     4 -> \@arrayrule
1120 %                     5 -> \hskip \arraycolsep \@arrayrule
1121 %                     6 -> \@arrayrule
1122 %                  end case
1123 %  END
1125 % \@classii ==
1126 %  BEGIN
1127 %    \@preamble := \@preamble *
1128 %                  case of \@lastchclass
1129 %                     0    ->
1130 %                     1    -> \hskip .5\arrayrulewidth
1131 %                     2    -> % impossible
1132 %                     else ->
1133 %                  end case
1134 %  END
1136 % \@classiii ==
1137 %  BEGIN
1138 %    \@preamble := \@preamble *
1139 %               case of \@lastchclass
1140 %                  0 -> \hskip \arraycolsep \@addamp \hskip \arraycolsep
1141 %                  1 -> \@addamp \hskip \arraycolsep
1142 %                  2 -> % impossible
1143 %                  3 -> % impossible
1144 %                  4 -> \@addamp
1145 %                  5 -> \hskip \arraycolsep \@addamp \hskip \arraycolsep
1146 %                  6 -> \@addamp \hskip \arraycolsep
1147 %                end case
1148 %  END
1150 % \@arrayclassiv  ==
1151 %      BEGIN  \@preamble := \@preamble * $ \@nextchar$  END
1153 % \@tabclassiv   == same as \@arrayclassv except without the $ ... $
1155 % \@classv ==
1156 %   BEGIN
1157 %    \@preamble :=
1158 %        \@preamble * \@startpbox{\@nextchar}\ignorespaces\@sharp
1159 %                               \@endpbox
1160 %   END
1162 % \@expast{S}:
1163 %  Sets \reserved@a := S with all instances of *{N}{STRING}
1164 %  replaced by N copies of STRING, where N > 0.  An *
1165 %  appearing inside braces is ignored, but *-expressions
1166 %  inside STRING are expanded, so nested *-expressions are
1167 %  handled properly.
1169 % \@expast{S} == BEGIN  \@xexpast S *0x\@@  END
1171 % \@xexpast S1 *{N}{S2} S3 \@@ ==
1172 %  BEGIN
1173 %    \reserved@a   := S1
1174 %    \@tempcnta := N
1175 %    if \@tempcnta > 0
1176 %      then  while \@tempcnta > 0 do \reserved@a   := \reserved@a S2
1177 %                                   \@tempcnta := \@tempcnta - 1 od
1178 %            \reserved@b == \@xexpast
1179 %      else  \reserved@b == \@xexnoop
1180 %    fi
1181 %    \expandafter \reserved@b \reserved@a S3 \@@
1182 %  END
1183 % \end{oldcomments}
1186 %  \begin{macro}{\@xexnoop}
1187 %    \begin{macrocode}
1188 \def\@xexnoop #1\@@{}
1189 %    \end{macrocode}
1190 % \end{macro}
1192 %  \begin{macro}{\@expast}
1193 %    \begin{macrocode}
1194 \def\@expast#1{\@xexpast #1*0x\@@}
1195 %    \end{macrocode}
1196 % \end{macro}
1198 %  \begin{macro}{\@xexpast}
1199 %    \begin{macrocode}
1200 \def\@xexpast#1*#2#3#4\@@{%
1201   \edef\reserved@a{#1}%
1202   \@tempcnta#2\relax
1203   \ifnum\@tempcnta>\z@
1204     \@whilenum\@tempcnta>\z@\do
1205        {\edef\reserved@a{\reserved@a#3}\advance\@tempcnta \m@ne}%
1206     \let\reserved@b\@xexpast
1207   \else
1208     \let\reserved@b\@xexnoop
1209   \fi
1210   \expandafter\reserved@b\reserved@a #4\@@}
1211 %    \end{macrocode}
1212 % \end{macro}
1214 %  \begin{macro}{\if@firstamp}
1215 %  \begin{macro}{\@addamp}
1216 %    \begin{macrocode}
1217 \newif\if@firstamp
1218 %    \end{macrocode}
1220 %    \begin{macrocode}
1221 \def\@addamp{%
1222   \if@firstamp
1223     \@firstampfalse
1224   \else
1225     \edef\@preamble{\@preamble &}%
1226   \fi}
1227 %    \end{macrocode}
1228 % \end{macro}
1229 % \end{macro}
1231 %  \begin{macro}{\@arrayacol}
1232 %  \begin{macro}{\@tabacol}
1233 %  \begin{macro}{\@ampacol}
1234 %  \begin{macro}{\@acolampacol}
1235 %    \begin{macrocode}
1236 \def\@arrayacol{\edef\@preamble{\@preamble \hskip \arraycolsep}}
1237 \def\@tabacol{\edef\@preamble{\@preamble \hskip \tabcolsep}}
1238 \def\@ampacol{\@addamp \@acol}
1239 \def\@acolampacol{\@acol\@addamp\@acol}
1240 %    \end{macrocode}
1241 % \end{macro}
1242 % \end{macro}
1243 % \end{macro}
1244 % \end{macro}
1246 %  \begin{macro}{\@mkpream}
1247 % \changes{v1.0h}{1994/11/04}{(ASAJ) Added \cs{@unexpandable@protect}
1248 %    to \cs{@mkpream}.}
1249 %    \begin{macrocode}
1250 \def\@mkpream#1{\@firstamptrue\@lastchclass6
1251   \let\@preamble\@empty
1252   \let\protect\@unexpandable@protect
1253   \let\@sharp\relax
1254   \let\@startpbox\relax\let\@endpbox\relax
1255   \@expast{#1}%
1256   \expandafter\@tfor \expandafter
1257     \@nextchar \expandafter:\expandafter=\reserved@a\do
1258        {\@testpach\@nextchar
1259     \ifcase \@chclass \@classz \or \@classi \or \@classii \or \@classiii
1260       \or \@classiv \or\@classv \fi\@lastchclass\@chclass}%
1261   \ifcase \@lastchclass \@acol
1262       \or \or \@preamerr \@ne\or \@preamerr \tw@\or \or \@acol \fi}
1263 %    \end{macrocode}
1264 % \end{macro}
1266 %  \begin{macro}{\@arrayclassz}
1267 %    \begin{macrocode}
1268 \def\@arrayclassz{\ifcase \@lastchclass \@acolampacol \or \@ampacol \or
1269    \or \or \@addamp \or
1270    \@acolampacol \or \@firstampfalse \@acol \fi
1271 \edef\@preamble{\@preamble
1272   \ifcase \@chnum
1273      \hfil$\relax\@sharp$\hfil \or $\relax\@sharp$\hfil
1274     \or \hfil$\relax\@sharp$\fi}}
1275 %    \end{macrocode}
1276 % \end{macro}
1278 %  \begin{macro}{\@tabclassz}
1279 % RmS 91/08/14 inserted extra braces around entry for NFSS
1280 %    \begin{macrocode}
1281 \def\@tabclassz{%
1282   \ifcase\@lastchclass
1283     \@acolampacol
1284   \or
1285     \@ampacol
1286   \or
1287   \or
1288   \or
1289     \@addamp
1290   \or
1291     \@acolampacol
1292   \or
1293     \@firstampfalse\@acol
1294   \fi
1295   \edef\@preamble{%
1296     \@preamble{%
1297       \ifcase\@chnum
1298         \hfil\ignorespaces\@sharp\unskip\hfil
1299       \or
1300 %    \end{macrocode}
1301 % \changes{v1.1g}{1996/04/22}
1302 %     {(DPC) Extra \cs{hskip} keeps tabcolsep in empty columns
1303 %             internal/2122}
1304 % \changes{v1.1h}{1996/06/14}
1305 %     {(DPC) Change both\cs{z@skip} to 1sp for latex/2160}
1306 %    \begin{macrocode}
1307         \hskip1sp\ignorespaces\@sharp\unskip\hfil
1308       \or
1309         \hfil\hskip1sp\ignorespaces\@sharp\unskip
1310       \fi}}}
1311 %    \end{macrocode}
1312 % \end{macro}
1314 %  \begin{macro}{\@classi}
1315 %    \begin{macrocode}
1316 \def\@classi{%
1317   \ifcase\@lastchclass
1318     \@acol\@arrayrule
1319   \or
1320     \@addtopreamble{\hskip \doublerulesep}\@arrayrule
1321   \or
1322   \or
1323   \or
1324     \@arrayrule
1325   \or
1326     \@acol\@arrayrule
1327   \or
1328     \@arrayrule
1329   \fi}
1330 %    \end{macrocode}
1331 % \end{macro}
1333 %  \begin{macro}{\@classii}
1334 %    \begin{macrocode}
1335 \def\@classii{%
1336   \ifcase\@lastchclass
1337   \or
1338     \@addtopreamble{\hskip .5\arrayrulewidth}%
1339   \fi}
1340 %    \end{macrocode}
1341 % \end{macro}
1343 %  \begin{macro}{\@classiii}
1344 %    \begin{macrocode}
1345 \def\@classiii{\ifcase \@lastchclass \@acolampacol \or
1346    \@addamp\@acol \or
1347    \or \or \@addamp \or
1348    \@acolampacol \or \@ampacol \fi}
1349 %    \end{macrocode}
1350 % \end{macro}
1352 %  \begin{macro}{\@tabclassiv}
1353 %    \begin{macrocode}
1354 \def\@tabclassiv{\@addtopreamble\@nextchar}
1355 %    \end{macrocode}
1356 % \end{macro}
1358 %  \begin{macro}{\@arrayclassiv}
1359 %    \begin{macrocode}
1360 \def\@arrayclassiv{\@addtopreamble{$\@nextchar$}}
1361 %    \end{macrocode}
1362 % \end{macro}
1364 %  \begin{macro}{\@classv}
1365 %    \begin{macrocode}
1366 \def\@classv{\@addtopreamble{\@startpbox{\@nextchar}\ignorespaces
1367 \@sharp\@endpbox}}
1368 %    \end{macrocode}
1369 % \end{macro}
1371 % \begin{macro}{\@addtopreamble}
1372 %    \begin{macrocode}
1373 \def\@addtopreamble#1{\edef\@preamble{\@preamble #1}}
1374 %    \end{macrocode}
1375 % \end{macro}
1377 % \begin{macro}{\@chclass}
1378 % \begin{macro}{\@lastchclass}
1379 % \begin{macro}{\@chnum}
1380 %    \begin{macrocode}
1381 \newcount\@chclass
1382 \newcount\@lastchclass
1383 \newcount\@chnum
1384 %    \end{macrocode}
1385 % \end{macro}
1386 % \end{macro}
1387 % \end{macro}
1389 % \begin{macro}{\arraycolsep}
1390 % \begin{macro}{\tabcolsep}
1391 % \begin{macro}{\arrayrulewidth}
1392 % \begin{macro}{\doublerulesep}
1393 %    \begin{macrocode}
1394 \newdimen\arraycolsep
1395 \newdimen\tabcolsep
1396 \newdimen\arrayrulewidth
1397 \newdimen\doublerulesep
1398 %    \end{macrocode}
1399 % \end{macro}
1400 % \end{macro}
1401 % \end{macro}
1402 % \end{macro}
1404 % \begin{macro}{\arraystretch}
1405 %    \begin{macrocode}
1406 \def\arraystretch{1}    % Default value.
1407 %    \end{macrocode}
1408 % \end{macro}
1410 % \begin{macro}{\@arstrutbox}
1411 % \begin{macro}{\@arstrut}
1412 %    \begin{macrocode}
1413 \newbox\@arstrutbox
1414 %    \end{macrocode}
1416 %    \begin{macrocode}
1417 \def\@arstrut{%
1418   \relax\ifmmode\copy\@arstrutbox\else\unhcopy\@arstrutbox\fi}
1419 %    \end{macrocode}
1420 % \end{macro}
1421 % \end{macro}
1423 % \begin{macro}{\@arrayrule}
1424 %    \begin{macrocode}
1425 \def\@arrayrule{\@addtopreamble{\hskip -.5\arrayrulewidth
1426    \vrule \@width \arrayrulewidth\hskip -.5\arrayrulewidth}}
1427 %    \end{macrocode}
1428 % \end{macro}
1430 % \begin{macro}{\@testpatch}
1431 %    \begin{macrocode}
1432 \def\@testpach#1{\@chclass \ifnum \@lastchclass=\tw@ 4 \else
1433     \ifnum \@lastchclass=3 5 \else
1434      \z@ \if #1c\@chnum \z@ \else
1435                               \if #1l\@chnum \@ne \else
1436                               \if #1r\@chnum \tw@ \else
1437           \@chclass \if #1|\@ne \else
1438                     \if #1@\tw@ \else
1439                     \if #1p3 \else \z@ \@preamerr 0\fi
1440   \fi  \fi  \fi  \fi  \fi  \fi
1441 \fi}
1442 %    \end{macrocode}
1443 % \end{macro}
1445 % \begin{macro}{\hline}
1446 %    \begin{macrocode}
1447 \def\hline{%
1448   \noalign{\ifnum0=`}\fi\hrule \@height \arrayrulewidth \futurelet
1449    \reserved@a\@xhline}
1450 %    \end{macrocode}
1451 % \end{macro}
1453 % \begin{macro}{\@xhline}
1454 %    \begin{macrocode}
1455 \def\@xhline{\ifx\reserved@a\hline
1456                \vskip\doublerulesep
1457 %    \end{macrocode}
1458 %    Measure from the middle of the rules.
1459 % \changes{latex2e}{1993/12/16}{Measure from middle of vertical rules}
1460 %    \begin{macrocode}
1461                \vskip-\arrayrulewidth
1462              \fi
1463       \ifnum0=`{\fi}}
1464 %    \end{macrocode}
1465 % \end{macro}
1467 % \begin{macro}{\vline}
1468 %    \begin{macrocode}
1469 \def\vline{\vrule \@width \arrayrulewidth}
1470 %    \end{macrocode}
1471 % \end{macro}
1473 % \begin{macro}{\cline}
1474 % \changes{v1.1c}{1995/09/14}
1475 %     {(DPC) New implementation}
1476 % \begin{macro}{\@cline}
1477 % The old \LaTeX2.09 implementation of |\cline| used up quite
1478 % a lot of memory and two precious count registers.
1479 % This new (1995/09/14) implementation does not use any count registers.
1480 % It is coded in a way that depends heavily on the definition of
1481 % |\multispan| so that command has been moved here from the file
1482 % |ltplain.dtx|.
1484 % These counters are no longer declared.
1485 %\begin{verbatim}
1486 % \newcount\@cla
1487 % \newcount\@clb
1488 %\end{verbatim}
1490 %    \begin{macrocode}
1491 \def\cline#1{\@cline#1\@nil}
1492 %    \end{macrocode}
1494 % \changes{v1.1e}{1995/10/17}
1495 %     {(DPC) Use \cs{@multicnt}}
1496 %    \begin{macrocode}
1497 \def\@cline#1-#2\@nil{%
1498   \omit
1499 %    \end{macrocode}
1500 % Use the counter from |\multispan|.
1501 %    \begin{macrocode}
1502   \@multicnt#1%
1503   \advance\@multispan\m@ne
1504   \ifnum\@multicnt=\@ne\@firstofone{&\omit}\fi
1505   \@multicnt#2%
1506   \advance\@multicnt-#1%
1507   \advance\@multispan\@ne
1508 %    \end{macrocode}
1509 % The original had |\unskip| at this point,
1510 % but how could a skip get here ???
1511 %    \begin{macrocode}
1512   \leaders\hrule\@height\arrayrulewidth\hfill
1513   \cr
1514 %    \end{macrocode}
1515 % This is back spacing is fairly horrible,
1516 % but it is what happened in the old version\ldots\
1517 % An alternative would be to make |\cline| look ahead for a following
1518 % |\cline| as does |\hline|. This would alter the spacing in existing
1519 % documents so keep the old version in the kernel. Perhaps a package
1520 % should do this differently.
1521 %    \begin{macrocode}
1522   \noalign{\vskip-\arrayrulewidth}}
1523 %    \end{macrocode}
1524 % \end{macro}
1525 % \end{macro}
1527 % \begin{macro}{\mscount}
1528 % The |\mscount| counter is no longer declared, saving a csname and a
1529 % register. It is declared in compatibility mode.
1530 % \end{macro}
1532 % \begin{macro}{\multispan}
1533 % \begin{macro}{\@multispan}
1534 % \changes{v1.1e}{1995/10/17}
1535 %     {(DPC) Macro added.}
1536 % \begin{macro}{\sp@n}
1537 % Modify |\multispan| slightly from its plain \TeX\ definition
1538 % to allow more efficient code sharing with |\multicolumn|.
1539 % Also share a count register with |\multiput|.
1540 %    \begin{macrocode}
1541 \def\multispan{\omit\@multispan}
1542 %    \end{macrocode}
1544 %    \begin{macrocode}
1545 \def\@multispan#1{%
1546   \@multicnt#1\relax
1547   \loop\ifnum\@multicnt>\@ne \sp@n\repeat}
1548 %    \end{macrocode}
1550 %    \begin{macrocode}
1551 \def\sp@n{\span\omit\advance\@multicnt\m@ne}
1552 %    \end{macrocode}
1553 %  \end{macro}
1554 %  \end{macro}
1555 %  \end{macro}
1558 % \begin{macro}{\@startpbox}
1559 % \begin{macro}{\@endpbox}
1560 % Helper macros for `p' columns.
1562 % |\@startpbox|\marg{width} \emph{text} |\egroup| is essentially
1563 % |\parbox|\marg{width}\marg{text}
1565 % |\@endpbox| is essentially  |\unskip \strut \par \egroup\hfil|
1566 %  (Changed 14 Jan 89) (changed again 1994/05/13)
1568 % \changes{v1.0d}{1994/05/03}
1569 %     {Use \cs{@finalstrut} based on depth of \cs{@arstrutbox}}
1571 % \changes{v1.1j}{1998/05/18}{Use \cs{setlength} to set \cs{hsize},
1572 %      so that the changes in the calc package apply here.}
1573 %    \begin{macrocode}
1574 \def\@startpbox#1{\vtop\bgroup \setlength\hsize{#1}\@arrayparboxrestore}
1575 %    \end{macrocode}
1577 %    \begin{macrocode}
1578 \def\@endpbox{\@finalstrut\@arstrutbox\par\egroup\hfil}
1579 %    \end{macrocode}
1581 % 14 Jan 89: Def of |\@endpbox| changed from\\
1582 %    |\def\@endpbox{\par\vskip\dp\@arstrutbox\egroup\hfil}|\\
1583 % so vertical spacing works out right if the last line of a `p' entry
1584 % has a descender.
1585 % \end{macro}
1586 % \end{macro}
1588 % \begin{macro}{\@@startpbox}
1589 % \begin{macro}{\@@endpbox}
1590 %    \begin{macrocode}
1591 \let\@@startpbox=\@startpbox
1592 \let\@@endpbox=\@endpbox
1593 %    \end{macrocode}
1594 % \end{macro}
1595 % \end{macro}
1597 %    \begin{macrocode}
1598 %</2ekernel>
1599 %    \end{macrocode}
1601 % \Finale