lttab.dtx

Johannes Braams  David Carlisle  Alan Jeffrey
Leslie Lamport  Frank Mittelbach  Chris Rowley

Rainer Schöpf

1995/10/23

1 Tabbing, Tabular and Array Environments

This section deals with ‘Lining It Up in Columns’. First the tabbing environment is defined, and then in second part, tabular together with its variants, tabular*

and array.

Note that the tabular defined here is essentially the original L^{A}TEX 2.09 version, not the extended version described in The L^{A}TEX Companion. Use the array package to obtain the extended version.

1.1 tabbing

\dimen(\@firsttab + i) = distance of tab stop i from left margin 0 <= i <= 15 (?).

\dimen\@firsttab is initialized to \@totalleftmargin, so it starts

at the prevailing left margin.

\@maxtab = number of highest defined tab register

probably = \@firsttab + 12

\@nxttabmar = tab stop number of next line’s left margin \@curtabmar = tab stop number of current line’s left margin \@curtab = number of the current tab. At start of line,

                    it equals \@curtabmar

\@hightab = largest tab number currently defined.

\@tabpush = depth of \pushtab's

\box\@curline = contents of current line, excluding left margin

skip, and excluding contents of current field

\box\@curfield = contents of current field

@rjfield = switch: T iff the last field of the line should be right-justified at the right margin.

\tabbingsep = distance left by the \' command between the current position and the field that is “left-shifted”.

UTILITY MACROS \@stopfield : closes the current field \@addfield : adds the current field to the current line. \@contfield : continues the current field \@startfield : begins the next field \@stopline : closes the current line and outputs it \@startline : starts the next line \@ifatmargin : an \if that is true iff the current line.

has width zero

\@startline ==

BEGIN

\@curtabmar :=G \@nxttabmar
\@curtab :=G \@curtabmar
\box\@curline :=G null
\@startfield
\strut

END

\@stopline ==

BEGIN

\unskip
\@stopfield

if @rjfield = T

then @rjfield :=G F

        \@tempdima := \@totalleftmargin + \linewidth
        \hb@xt@ \@tempdima{\@itemfudge
                            \hskip \dimen\@curtabmar
                            \box\@curline
                            \hfil
                            \box\@curfield}
  else \@addfield
       \hbox {\@itemfudge
              \hskip \dimen\@curtabmar
              \box\@curline}

fi END

\@startfield ==

BEGIN

 \box\@curfield :=G \hbox {

END

\@stopfield ==

BEGIN

  }

END

\@contfield ==

BEGIN

\box\@curfield :=G \hbox { \unhbox\@currfield  %%} brace

matching END

\@addfield ==

BEGIN

\box\@curline :=G \unbox\@curline * \unbox\@curfield

END

\@ifatmargin ==

BEGIN if dim of box\@curline = 0pt then END

\tabbing ==

BEGIN

\lineskip :=L 0pt
\> == \@rtab
\< == \@ltab
\= == \@settab
\+ == \@tabplus
\- == \@tabminus
\` == \@tabrj
\' == \@tablab
\\ == BEGIN \@stopline \@startline END

\\[DIST] == BEGIN

             \@stopline \vskip DIST \@startline\ignorespaces

END

\\* == BEGIN \@stopline \penalty 10000 \@startline END
\\*[DIST] == BEGIN \@stopline \penalty 10000 \vskip DIST
                   \@startline\ignorespaces  END
\@hightab := \@nxttabmar :=G \@firsttab
\@tabpush :=G 0
\dimen\@firsttab := \@totalleftmargin

@rjfield :=G F

\trivlist  \item\relax

if @minipage = F then \vskip \parskip fi

\box\@tabfbox = \rlap{\indent\the\everypar}

% note: \the\everypar sets @inlabel :=G F

\@itemfudge == BEGIN \box\@tabfbox END
\@startline
\ignorespaces

END

\@endtabbing ==

BEGIN

\@stopline

if \@tabpush > 0 then error message: ”unmatched \poptabs'’ fi

\endtrivlist

END

\@rtab ==

BEGIN

\@stopfield
\@addfield
if \@curtab < \@hightab
  then \@curtab :=G \@curtab + 1

else error message “Undefined Tab” fi

\@tempdima := \dimen\@curtab - \dimen\@curtabmar

- width of box \@curline

\box\@curline :=G \hbox{\unhbox\@curline + \hskip\@tempdima}
\@startfield

END

\@settab ==

BEGIN

\@stopfield
\@addfield
if \@curtab < \@maxtab
  then \@curtab :=G \@curtab+1

else error message: “Too many tabs” fi

if \@curtab > \@hightab
  then \@hightab :=L \@curtab  fi
\dimen\@curtab :=L \dimen\@curtabmar + width of \box\@curline
\@startfield

END

\@ltab ==

BEGIN

\@ifatmargin
  then if \@curtabmar > \@firsttab
         then \@curtab :=G \@curtab - 1
              \@curtabmar :=G \@curtabmar - 1

else error message “Too many untabs” fi else error message “Left tab in middle of line”

fi END

\@tabplus ==

BEGIN

      if \@nxttabmar < \@hightab
         then \@nxttabmar :=G \@nxttabmar+1

else error message “Undefined tab” fi

END

\@tabminus ==

BEGIN

      if \@nxttabmar > \@firsttab
         then \@nxttabmar :=G \@nxttabmar-1

else error message “Too many untabs” fi

END

\@tabrj ==
BEGIN \@stopfield
      \@addfield

@rjfield :=G T

      \@startfield

END

\@tablab ==
BEGIN \@stopfield
    \box\@curline G:= \hbox{\box\@curline %% ‘G’ added 17 Jun 86
                            \hskip - width of \box\@curfield
                            \hskip -\tabbingsep
                            \box\@curfield
                            \hskip \tabbingsep }
      \@startfield

END

\pushtabs ==

BEGIN

   \@stopfield
   \@tabpush :=G \@tabpush + 1
   \begingroup
   \@contfield

END

 \poptabs ==

BEGIN

    \@stopfield
    if \@tabpush > 0
      then \endgroup
           \@tabpush :=G \@tabpush - 1

else error message: “Too many \poptabs'’ fi

    \@contfield

END

\a The accents \` , \' , and \= that have been redefined inside a tabbing environment can be called by typing \a` , \a' , and \a=. The macro \a is defined in

ltoutenc.dtx.

The ‘2ekernel’ code ensures that a \usepackage{autotabg} is essentially ignored if a ‘full’ format is being used that has picture mode already in the format.

 1 ⟨2ekernel⟩\expandafter\let\csname ver@autotabg.sty\endcsname\fmtversion
\@firsttab \@maxtab

2 ⟨∗2ekernel | autoload⟩

 3 \newdimen\@gtempa
 4 \chardef\@firsttab=\the\allocationnumber
 5 \newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa
 6 \newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa
 7 \newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa\newdimen\@gtempa
 8 \newdimen\@gtempa
 9 \chardef\@maxtab=\the\allocationnumber
10 \dimen\@firsttab=0pt
\@nxttabmar \@curtabmar \@curtab \@hightab \@tabpush
11 \newcount\@nxttabmar
12 \newcount\@curtabmar
13 \newcount\@curtab
14 \newcount\@hightab
15 \newcount\@tabpush
\@curline \@curfield \@tabfbox
16 \newbox\@curline
17 \newbox\@curfield
18 \newbox\@tabfbox

19 ⟨/2ekernel | autoload⟩ 20 ⟨∗2ekernel | def⟩

\if@rjfield
21 \newif\if@rjfield

\@startline It is, in some sense, an error if the current margin tab setting is higher than the value of \@hightab (which is a local variable). That this is allowed is a fundamental design flaw which is not going to be corrected now.

22 \gdef\@startline{%
23  \ifnum \@nxttabmar >\@hightab
24  \@badtab
25  \global\@nxttabmar \@hightab
26  \fi
27  \global\@curtabmar \@nxttabmar
28  \global\@curtab \@curtabmar
29  \global\setbox\@curline \hbox {}%
30  \@startfield
31  \strut

32 }

\@stopline
33 \gdef\@stopline{\unskip\@stopfield\if@rjfield \global\@rjfieldfalse
34 \@tempdima\@totalleftmargin \advance\@tempdima\linewidth
35 \hb@xt@\@tempdima{\@itemfudge\hskip\dimen\@curtabmar
36 \box\@curline\hfil\box\@curfield}\else\@addfield
37 \hbox{\@itemfudge\hskip\dimen\@curtabmar\box\@curline}\fi}
\@startfield
38 \gdef\@startfield{%
39 \global\setbox\@curfield\hbox\bgroup\color@begingroup}
\@stopfield
40 \gdef\@stopfield{%
41 \color@endgroup\egroup}
\@contfield
42 \gdef\@contfield{%
43 \global\setbox\@curfield\hbox\bgroup\color@begingroup
44 \unhbox\@curfield}
\@addfield
45 \gdef\@addfield{\global\setbox\@curline\hbox{\unhbox
46  \@curline\unhbox\@curfield}}
\@ifatmargin
47 \gdef\@ifatmargin{\ifdim \wd\@curline =\z@}
\@tabcr
48 \gdef\@tabcr{\@stopline \@ifstar{\penalty \@M \@xtabcr}\@xtabcr}
\@xtabcr
49 \gdef\@xtabcr{\@ifnextchar[\@itabcr{\@startline\ignorespaces}}

\@itabcr
50 \gdef\@itabcr[#1]{\vskip #1\@startline\ignorespaces}
51 \gdef\kill{\@stopfield\@startline\ignorespaces}

\tabbing We use \relax to prevent \item from scanning too far.

52 \gdef\tabbing{\lineskip \z@skip\let\>\@rtab\let\<\@ltab\let\=\@settab
53  \let\+\@tabplus\let\-\@tabminus\let\`\@tabrj\let\'\@tablab
54  \let\\=\@tabcr
55  \@hightab\@firsttab
56  \global\@nxttabmar\@firsttab
57  \dimen\@firsttab\@totalleftmargin
58  \global\@tabpush\z@ \global\@rjfieldfalse
59  \trivlist \item\relax
60  \if@minipage\else\vskip\parskip\fi
61  \setbox\@tabfbox\hbox{\rlap{\indent\hskip\@totalleftmargin
62  \the\everypar}}\def\@itemfudge{\box\@tabfbox}%
63  \@startline\ignorespaces}
\endtabbing
64 \gdef\endtabbing{%
65 \@stopline\ifnum\@tabpush >\z@ \@badpoptabs \fi\endtrivlist}

\@rtab Omitted \global added to \@rtab 17 Jun 86

66 \gdef\@rtab{\@stopfield\@addfield\ifnum \@curtab<\@hightab
67  \global\advance\@curtab \@ne \else\@badtab\fi
68  \@tempdima\dimen\@curtab
69  \advance\@tempdima -\dimen\@curtabmar
70  \advance\@tempdima -\wd\@curline
71  \global\setbox\@curline\hbox{\unhbox\@curline\hskip\@tempdima}%
72  \@startfield\ignorespaces}
\@settab
73 \gdef\@settab{\@stopfield\@addfield
74 \ifnum \@curtab <\@maxtab
75  \ifnum\@curtab =\@hightab
76  \advance\@hightab \@ne
77  \fi
78  \global\advance\@curtab \@ne
79 \else
80  \@latex@error{Tab overflow}\@ehd
81 \fi
82 \dimen\@curtab \dimen\@curtabmar
83 \advance\dimen\@curtab \wd\@curline
84 \@startfield
85 \ignorespaces

86 }

\@ltab

 87 \gdef\@ltab{\@ifatmargin\ifnum\@curtabmar >\@firsttab
 88  \global\advance\@curtab \m@ne \global\advance\@curtabmar\m@ne\else
 89  \@badtab\fi\else
 90  \@latex@error{\string\<\space in mid line}\@ehd\fi\ignorespaces}
\@tabplus
 91 \gdef\@tabplus {\ifnum \@nxttabmar <\@hightab
 92  \global\advance\@nxttabmar \@ne \else
 93  \@badtab\fi\ignorespaces}
\@tabminus
 94 \gdef\@tabminus{\ifnum\@nxttabmar >\@firsttab
 95  \global\advance\@nxttabmar \m@ne \else
 96  \@badtab\fi\ignorespaces}
\@tabrj
 97 \gdef\@tabrj{%
 98 \@stopfield\@addfield\global\@rjfieldtrue\@startfield\ignorespaces}
\@tablab  \setbox\@curline made \global in \@tablab. 17 Jun 86
 99 \gdef\@tablab{\@stopfield\global\setbox\@curline\hbox{\box\@curline
100  \hskip -\wd\@curfield \hskip -\tabbingsep \box\@curfield
101  \hskip \tabbingsep}\@startfield\ignorespaces}
\pushtabs
102 \gdef\pushtabs{%
103 \@stopfield\@addfield\global\advance\@tabpush \@ne \begingroup
104  \@contfield}

\poptabs It is, in some sense, an error if, after the endgroup, the current tab setting is higher than the new value of \@hightab (which is a local variable). That this is allowed is a fundamental design flaw which is not going to be corrected now.

105 \gdef\poptabs{\@stopfield\@addfield
106 \ifnum \@tabpush >\z@
107  \endgroup
108  \global\advance\@tabpush \m@ne
109  \ifnum \@curtab >\@hightab
110  \global \@curtab \@hightab
111  \@badtab
112  \fi
113 \else
114  \@badpoptabs
115 \fi
116 \@contfield

117 }

118 ⟨/2ekernel | def⟩

\tabbingsep

119 ⟨∗2ekernel | autoload⟩

120 \newdimen\tabbingsep

121 ⟨/2ekernel | autoload⟩

\tabbing

122 ⟨∗autoload⟩

123 \def\tabbing{\@autoload{tabg}\tabbing}

124 ⟨/autoload⟩

1.2 array and tabular environments

ARRAY PARMETERS:

\arraycolsep

: half the width separating columns in an array environment

\tabcolsep

: half the width separating columns in a tabular environment

\arrayrulewidth

: width of rules

\doublerulesep

: space between adjacent rules in array or tabular

\arraystretch

: line spacing in array and tabular environments is done by placing a strut in every row of height and depth \arraystretch times the height and depth of the strut produced by an ordinary \strut commmand.

PREAMBLE: The PREAMBLE argument of an array or tabular environment can contain the following:

l,r,c : indicate where entry is to be placed. | : for vertical rule @{EXP} : inserts the text EXP in every column.

          \arraycolsep or \tabcolsep spacing is suppressed.

*{N}{PRE} : equivalent to writing N copies of PRE in the preamble.

PRE may contain *{N’}{EXP’} expressions.

p{LEN} : makes entry in parbox of width LEN.

SPECIAL ARRAY COMMANDS: \multicolumn{N}{FORMAT}{ITEM} : replaces the next N column items by ITEM, formatted according to FORMAT. FORMAT should contain at most one l,r or c. If it contains none, then ITEM is ignored.

\vline : draws a vertical line the height of the current row. May appear in an array element entry.

\hline : draws a horizontal line between rows. Must appear either before the first entry (to appear above the first row) or right after a \\ command. If followed by another \hline,

       then adds a \vskip of \doublerulesep.

\cline[i-j] : draws horizontal lines between rows covering columns i through j, inclusive. Multiple commands may follow one another to provide lines covering several disjoint columns

\extracolsep{WIDTH} : for use inside an @ in the preamble. Causes a WIDTH space to be added between columns for the rest of the columns. This is in addition to the ordinary intercolumn space.

\array ==

BEGIN

\@acol  == \@arrayacol
\@classz == \@arrayclassz
\@classiv == \@arrayclassiv
\\  == \@arraycr
\@halignto == NULL
\@tabarray

END

\endarray{NAME} == BEGIN \crcr }} END
\tabular ==

BEGIN

\@halignto == NULL
\@tabular

END

\tabular*{WIDTH} ==

BEGIN

\@halignto == to WIDTH
\@tabular

END

\@tabular ==

BEGIN

\leavevmode
\hbox { $
   \@acol  == \@tabacol
   \@classz == \@tabclassz
   \@classiv == \@tabclassiv
   \\  == \@tabularcr

   \@tabarray

END

\endtabular == BEGIN \crcr}} $} END
\@tabarray == if next char = [ then \@array else \@array[c] fi

\@array[POS]{PREAMBLE} ==

BEGIN

define \@arstrutbox to make \@arstrut produce strut of height and depth \arraystretch times the height and depth of a normal strut.

\@mkpream{PREAMBLE}
\@preamble == \halign \@halignto {\tabskip=0pt\@arstrut
                        eval{\@preamble}\tabskip = 0pt\cr %%}
\@startpbox == \@@startpbox
\@endpbox == \@@endpbox

if POS = t then \vtop

else if POS = b then \vbox

                           else \vcenter

fi fi

{

\par ==L {} % changed 92/09/18

\@sharp  == #
\protect  == \relax
\lineskip  :=L 0pt
\baselineskip :=L 0pt
\@preamble

END

\@arraycr ==

BEGIN $ %% Prevents extra space at end of row’s last entry. if next char = [

then \@argarraycr

else $ \cr %% Needed to balance $ END

\@argarraycr[LENGTH] ==

BEGIN $ %% Needed to balance $ of \@arraycr if LENGTH > 0

 then \@tempdima := depth of \@arstrutbox + LENGTH

\vrule height 0pt width 0pt depth \@tempdima

       \cr

        else \cr \noalign{\vskip LENGTH}

END

   \@tabularcr and \@argtabularcr same as \@arraycr and
 \@argarraycr

except without the extra $’s.

125 ⟨∗2ekernel | autoload⟩

\extracolsep
126 \def\extracolsep#1{\tabskip #1\relax}
\array
127 \def\array{\let\@acol\@arrayacol \let\@classz\@arrayclassz
128 \let\@classiv\@arrayclassiv
129 \let\\\@arraycr\let\@halignto\@empty\@tabarray}
\endarray
\endtabular
\endtabular*

130 \def\endarray{\crcr\egroup\egroup}
131 \def\endtabular{\crcr\egroup\egroup $\egroup}
132 \expandafter \let \csname endtabular*\endcsname = \endtabular
\tabular
133 \def\tabular{\let\@halignto\@empty\@tabular}
\tabular* RmS 93/08/05: Replaced \expandafter\def by \@namedef.
134 \@namedef{tabular*}#1{\def\@halignto{to#1}\@tabular}
\@tabular
135 \def\@tabular{\leavevmode \hbox \bgroup $\let\@acol\@tabacol
136 \let\@classz\@tabclassz
137 \let\@classiv\@tabclassiv \let\\\@tabularcr\@tabarray}

\@tabarray RmS 91/11/04 added \m@th.

138 \def\@tabarray{\m@th\@ifnextchar[\@array{\@array[c]}}

RmS 1993/11/03 changed \halign to \ialign and removed superfluous \tabskip assignment

\array
139 \def\@array[#1]#2{\setbox\@arstrutbox\hbox{\vrule
140  \@height\arraystretch \ht\strutbox
141  \@depth\arraystretch \dp\strutbox
142  \@width\z@}\@mkpream{#2}\edef\@preamble{\ialign \noexpand\@halignto
143  \bgroup \@arstrut \@preamble \tabskip\z@skip \cr}%
144  \let\@startpbox\@@startpbox \let\@endpbox\@@endpbox
145  \let\tabularnewline\\%
146  \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi

147  \bgroup \let\par\@empty
148  \let\@sharp##\let\protect\relax
149  \lineskip\z@skip\baselineskip\z@skip\@preamble}

\@arraycr array version of \\.

150 \def\@arraycr{%
151 ${\ifnum0=`}\fi\@ifstar\@xarraycr\@xarraycr}
\@arraycr
152 \def\@xarraycr{\@ifnextchar[\@argarraycr{\ifnum0=`{\fi}${}\cr}}
\@argarraycr
153 \def\@argarraycr[#1]{%
154 \ifnum0=`{\fi}${}\ifdim #1>\z@ \@xargarraycr{#1}\else
155 \@yargarraycr{#1}\fi}
\tabularnewline \@tabularcr Tabular version of \\.
156 \def\@tabularcr{%
157 {\ifnum0=`}\fi\@ifstar\@xtabularcr\@xtabularcr}
158 \let\tabularnewline\relax
\@xtabularcr
159 \def\@xtabularcr{\@ifnextchar[\@argtabularcr{\ifnum0=`{\fi}\cr}}
\@argtabularcr
160 \def\@argtabularcr[#1]{\ifnum0=`{\fi}\ifdim #1>\z@
161 \unskip\@xargarraycr{#1}\else \@yargarraycr{#1}\fi}
\@xargarraycr
162 \def\@xargarraycr#1{\@tempdima #1\advance\@tempdima \dp \@arstrutbox
163 \vrule \@height\z@ \@depth\@tempdima \@width\z@ \cr}
\@yargarraycr
164 \def\@yargarraycr#1{\cr\noalign{\vskip #1}}
\multicolumn   \multicolumn{NUMBER}{FORMAT}{ITEM} ==

BEGIN

   \multispan{NUMBER}
   \begingroup
   \@addamp == null
   \@mkpream{FORMAT}
   \@sharp == ITEM
   \protect == \relax
   \@startpbox == \@@startpbox
   \@endpbox == \@@endpbox
   \@arstrut
   \@preamble
   \endgroup

END The command \def\@addamp{} was removed from \multicolumn on 6 Dec

86 because it caused embedded array environments not to work. I think that it was included originally to prevent an error message if the 2nd argument to the \multicolumn command had two column specifiers.

8 Feb 89 — \hbox{} added after \@preamble to correct bug that occurred if \multicolumn preceded \\[D] with D > 0, caused by \\[] command doing an

\unskip, which removed \tabcolsep glue inserted by \multicolumn.
165 \def\multicolumn#1#2#3{\multispan{#1}\begingroup
166 \@mkpream{#2}%
167 \def\@sharp{#3}\set@typeset@protect
168 \let\@startpbox\@@startpbox\let\@endpbox\@@endpbox
169 \@arstrut \@preamble\hbox{}\endgroup\ignorespaces}

Codes for classes and character numbers of array, tabular and multicolumn arguments.

Character  Class  Number
———  —–  ——
c  0  0
l  0  1
r  0  2
|  1  -
@  2  -
p  3  -
{@-exp}  4  -
{p-arg}  5  -

\@testpach \foo : expands \foo, which should be an array parameter token, and sets \@chclass and \@chnum to its class and number. Uses \@lastchclass to distinguish 4 and 5

Preamble error codes 0: ’illegal character’ 1: ’Missing @-exp’ 2: ’Missing p-arg’

\@addamp ==

BEGIN if @firstamp = true then @firstamp := false

else & fi

END

\@mkpream TOKENLIST == BEGIN @firstamp := T

\@lastchclass := 6
\@preamble  == null
\@sharp  == \relax
\protect  == BEGIN \noexpand\protect\noexpand END
\@startpbox == \relax
\@endpbox  == \relax
\@expast{TOKENLIST}
for \@nextchar := expand(\reserved@a)
  do \@testpach{\@nextchar}
      case of \@chclass
        0 -> \@classz
        1 -> \@classi

...

        5 -> \@classv

end case

      \@lastchclass := \@chclass

od

  case of \@lastchclass
     0 -> \hskip \arraycolsep             % lrc
     1 ->                                  % |

2 -> \@preamerr1 % ’Missing @-exp’ % @ 3 -> \@preamerr2 % ’Missing p-arg’ % p 4 -> % @-exp

     5 -> \hskip \arraycolsep             % p-exp

end case END

\@arrayclassz ==

BEGIN

  \@preamble := \@preamble *
           case of \@lastchclass
              0 -> \hskip \arraycolsep \@addamp \hskip
\arraycolsep
              1 -> \@addamp \hskip \arraycolsep

2 -> % impossible 3 -> % impossible

              4 -> \@addamp
              5 -> \hskip \arraycolsep \@addamp \hskip
\arraycolsep
              6 -> \@addamp \hskip \arraycolsep

end case

          * case of \@chnum
               0 -> \hfil$\relax\@sharp$\hfil
               1 -> $\relax\@sharp$\hfil
               2 -> \hfil$\relax\@sharp$

end case

END

\@tabclassz == similar to \@arrayclassz
\@classi ==

BEGIN

\@preamble := \@preamble *
case of \@lastchclass
   0 -> \hskip \arraycolsep \@arrayrule
   1 -> \hskip \doublerulesep \@arrayrule

2 -> % impossible

3 -> % impossible

   4 -> \@arrayrule
   5 -> \hskip \arraycolsep \@arrayrule
   6 -> \@arrayrule

end case

END

\@classii ==

BEGIN

\@preamble := \@preamble *
case of \@lastchclass

0 ->

   1  -> \hskip .5\arrayrulewidth

2 -> % impossible

else -> end case

END

\@classiii ==

BEGIN

\@preamble := \@preamble *
case of \@lastchclass
0 -> \hskip \arraycolsep \@addamp \hskip
\arraycolsep
1 -> \@addamp \hskip \arraycolsep

2 -> % impossible 3 -> % impossible

4 -> \@addamp
5 -> \hskip \arraycolsep \@addamp \hskip
\arraycolsep
6 -> \@addamp \hskip \arraycolsep

end case

END

\@arrayclassiv ==

    BEGIN \@preamble := \@preamble * $ \@nextchar$ END
\@tabclassiv == same as \@arrayclassv except without the $ ... $
\@classv ==

BEGIN

  \@preamble :=
      \@preamble * \@startpbox{\@nextchar}\ignorespaces\@sharp
                             \@endpbox

END

\@expast{S}:

Sets \reserved@a := S with all instances of *{N}{STRING} replaced by N copies of STRING, where N > 0. An * appearing inside braces is ignored, but *-expressions inside STRING are expanded, so nested *-expressions are handled properly.

\@expast{S} == BEGIN \@xexpast S *0x\@@ END
\@xexpast S1 *{N}{S2} S3 \@@ ==

BEGIN

  \reserved@a := S1
  \@tempcnta := N
  if \@tempcnta > 0
    then while \@tempcnta > 0 do \reserved@a := \reserved@a S2
                                 \@tempcnta := \@tempcnta - 1 od
          \reserved@b == \@xexpast
    else \reserved@b == \@xexnoop

fi

  \expandafter \reserved@b \reserved@a S3 \@@

END

\@xexnoop
170 \def\@xexnoop #1\@@{}
\@expast
171 \def\@expast#1{\@xexpast #1*0x\@@}
\@xexpast
172 \def\@xexpast#1*#2#3#4\@@{\edef\reserved@a{#1}\@tempcnta#2\relax
173  \ifnum\@tempcnta >\z@ \@whilenum\@tempcnta >\z@\do
174  {\edef\reserved@a{\reserved@a#3}\advance\@tempcnta \m@ne}%
175  \let\reserved@b\@xexpast
176  \else \let\reserved@b\@xexnoop\fi
177  \expandafter\reserved@b \reserved@a #4\@@}

\if@firstamp
\@addamp
178 \newif\if@firstamp
179 \def\@addamp{\if@firstamp \@firstampfalse \else
180  \edef\@preamble{\@preamble &}\fi}
\@arrayacol
\@tabacol
\@ampacol
\@acolampacol

181 \def\@arrayacol{\edef\@preamble{\@preamble \hskip \arraycolsep}}
182 \def\@tabacol{\edef\@preamble{\@preamble \hskip \tabcolsep}}
183 \def\@ampacol{\@addamp \@acol}
184 \def\@acolampacol{\@acol\@addamp\@acol}
\@mkpream
185 \def\@mkpream#1{\@firstamptrue\@lastchclass6
186 \let\@preamble\@empty
187 \let\protect\@unexpandable@protect
188 \let\@sharp\relax
189 \let\@startpbox\relax\let\@endpbox\relax
190 \@expast{#1}%
191 \expandafter\@tfor \expandafter
192  \@nextchar \expandafter:\expandafter=\reserved@a\do
193  {\@testpach\@nextchar
194  \ifcase \@chclass \@classz \or \@classi \or \@classii \or \@classiii
195  \or \@classiv \or\@classv \fi\@lastchclass\@chclass}%
196 \ifcase \@lastchclass \@acol
197  \or \or \@preamerr \@ne\or \@preamerr \tw@\or \or \@acol \fi}
\@arrayclassz
198 \def\@arrayclassz{\ifcase \@lastchclass \@acolampacol \or \@ampacol \or
199 \or \or \@addamp \or
200 \@acolampacol \or \@firstampfalse \@acol \fi
201 \edef\@preamble{\@preamble
202 \ifcase \@chnum
203  \hfil$\relax\@sharp$\hfil \or $\relax\@sharp$\hfil
204  \or \hfil$\relax\@sharp$\fi}}

\@tabclassz RmS 91/08/14 inserted extra braces around entry for NFSS

205 \def\@tabclassz{\ifcase \@lastchclass \@acolampacol \or \@ampacol \or
206 \or \or \@addamp \or
207 \@acolampacol \or \@firstampfalse \@acol \fi
208 \edef\@preamble{\@preamble{%
209 \ifcase \@chnum
210  \hfil\ignorespaces\@sharp\unskip\hfil
211  \or \ignorespaces\@sharp\unskip\hfil
212  \or \hfil\hskip\z@skip \ignorespaces\@sharp\unskip\fi}}}
\@classi
213 \def\@classi{\ifcase \@lastchclass \@acol \@arrayrule \or
214 \@addtopreamble{\hskip \doublerulesep}\@arrayrule\or
215 \or \or \@arrayrule \or
216 \@acol \@arrayrule \or \@arrayrule \fi}

\@classii
217 \def\@classii{\ifcase \@lastchclass \or
218 \@addtopreamble{\hskip .5\arrayrulewidth}\fi}
\@classiii
219 \def\@classiii{\ifcase \@lastchclass \@acolampacol \or
220 \@addamp\@acol \or
221 \or \or \@addamp \or
222 \@acolampacol \or \@ampacol \fi}
\@tabclassiv
223 \def\@tabclassiv{\@addtopreamble\@nextchar}
\@arrayclassiv
224 \def\@arrayclassiv{\@addtopreamble{$\@nextchar$}}
\@classv
225 \def\@classv{\@addtopreamble{\@startpbox{\@nextchar}\ignorespaces
226 \@sharp\@endpbox}}
\@addtopreamble
227 \def\@addtopreamble#1{\edef\@preamble{\@preamble #1}}
\@chclass
\@lastchclass
\@chnum

228 \newcount\@chclass
229 \newcount\@lastchclass
230 \newcount\@chnum
\arraycolsep
\tabcolsep
\arrayrulewidth
\doublerulesep

231 \newdimen\arraycolsep
232 \newdimen\tabcolsep
233 \newdimen\arrayrulewidth
234 \newdimen\doublerulesep
\arraystretch
235 \def\arraystretch{1}    % Default value.
\@arstrutbox
\@arstrut
236 \newbox\@arstrutbox
237 \def\@arstrut{%
238 \relax\ifmmode\copy\@arstrutbox\else\unhcopy\@arstrutbox\fi}
\@arrayrule
239 \def\@arrayrule{\@addtopreamble{\hskip -.5\arrayrulewidth
240 \vrule \@width \arrayrulewidth\hskip -.5\arrayrulewidth}}

\@testpatch
241 \def\@testpach#1{\@chclass \ifnum \@lastchclass=\tw@ 4 \else
242  \ifnum \@lastchclass=3 5 \else
243  \z@ \if #1c\@chnum \z@ \else
244  \if #1l\@chnum \@ne \else
245  \if #1r\@chnum \tw@ \else
246  \@chclass \if #1|\@ne \else
247  \if #1@\tw@ \else
248  \if #1p3 \else \z@ \@preamerr 0\fi
249 \fi  \fi  \fi  \fi  \fi  \fi
250 \fi}
\hline
251 \def\hline{%
252 \noalign{\ifnum0=`}\fi\hrule \@height \arrayrulewidth \futurelet
253 \reserved@a\@xhline}
\@xhline
254 \def\@xhline{\ifx\reserved@a\hline
255  \vskip\doublerulesep

Measure from the middle of the rules.

256  \vskip-\arrayrulewidth
257  \fi
258  \ifnum0=`{\fi}}
\vline
259 \def\vline{\vrule \@width \arrayrulewidth}

\cline \@cline The old L^{A}TEX2.09 implementation of \cline used up quite a lot of memory and two precious count registers. This new (1995/09/14) implementation does not use any count registers. It is coded in a way that depends heavily on the definition of \multispan so that command has been moved here from the file ltplain.dtx.

These counters are no longer declared.

  \newcount\@cla
  \newcount\@clb
260 \def\cline#1{\@cline#1\@nil}
261 \def\@cline#1-#2\@nil{%
262 \omit

Use the counter from \multispan.

263 \@multicnt#1%
264 \advance\@multispan\m@ne
265 \ifnum\@multicnt=\@ne\@firstofone{&\omit}\fi
266 \@multicnt#2%
267 \advance\@multicnt-#1%
268 \advance\@multispan\@ne

The original had \unskip at this point, but how could a skip get here ???

269 \leaders\hrule\@height\arrayrulewidth\hfill
270 \cr

This is back spacing is fairly horrible, but it is what happened in the old version… An alternative would be to make \cline look ahead for a following \cline as does \hline. This would alter the spacing in existing documents so keep the old version in the kernel. Perhaps a package should do this differently.

271 \noalign{\vskip-\arrayrulewidth}}

\mscount The \mscount counter is no longer declared, saving a csname and a register. It is declared in compatibility mode.

\multispan \@multispan \sp@n Modify \multispan slightly from its plain TEX definition to allow more efficient code sharing with \multicolumn. Also share a count register with \multiput.

272 \def\multispan{\omit\@multispan}
273 \def\@multispan#1{%
274 \@multicnt#1\relax
275 \loop\ifnum\@multicnt>\@ne \sp@n\repeat}
276 \def\sp@n{\span\omit\advance\@multicnt\m@ne}

\@startpbox \@endpbox Helper macros for ‘p’ columns.

\@startpbox{⟨width⟩} text \egroup is essentially \parbox{⟨width⟩}{⟨text⟩}

   \@endpbox is essentially \unskip \strut \par \egroup\hfil (Changed 14

Jan 89) (changed again 1994/05/13)

277 \def\@startpbox#1{\vtop\bgroup \hsize #1\@arrayparboxrestore}
278 \def\@endpbox{\@finalstrut\@arstrutbox\par\egroup\hfil}

14 Jan 89: Def of \@endpbox changed from

\def\@endpbox{\par\vskip\dp\@arstrutbox\egroup\hfil}

so vertical spacing works out right if the last line of a ‘p’ entry has a descender.

\@@startpbox
\@@endpbox
279 \let\@@startpbox=\@startpbox
280 \let\@@endpbox=\@endpbox

281 ⟨/2ekernel | autoload⟩