The xtab package^{∗}

Peter Wilson Catholic University of America^{†}

             Now at peter.r.wilson@boeing.com

1998/10/14

Abstract The xtab package enables long tables to be automatically broken at page boundaries. It is an extension of the supertabular package and also reduces or eliminates some of its weaknesses.

Contents

1 Introduction 1

2 The xtab package 2 2.1 Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3 The implementation 6

List of Tables

1 The principal xtab package commands . . . . . . . . . . . . . . . . 2

1 Introduction

Although the xtab package was originally developed as part of a suite for typesetting ISO international standards [Wil96], it is also applicable for use with the L^{A}TEX standard classes. The package is an extension of the supertabular package developed by Johannes Braams and Theo Jurriens.^{1} It reduces some of the weaknesses noted in the supertabular documentation and provides additional functionality.

Section 2 provides the user manual for the package which enables long tables to be automatically broken across multiple pages. Section 3 describes the implementation.

This manual is typeset according to the conventions of the L^{A}TEX docstrip utility which enables the automatic extraction of the L^{A}TEX macro source files [GMS94].

∗This file has version number v2.2, last revised 1998/10/14.

†This work was originally performed as a Guest Researcher at the National Institute of Standards and Technology.

1supertabular.sty, version 4.1c, 7 November 1997.

2 The xtab package

The supertabular package provides for the automatic breaking of a long table across page boundaries. The extension provided here enables the heading on the table on the last page to differ from those on earlier pages of the table. The downside of the extension is that L^{A}TEX has to be run twice if the document contains a supertabular. However, L^{A}TEX is usually run at least twice for any but the simplest document in order to get cross-references and Table of Contents, etc., resolved correctly.

The current version of the extension also either cures or reduces following weaknesses in the supertabular package.^{2}

1. Sometimes the top caption of a supertabular is printed on one page and the body is printed on the following page(s). That is, there is a lonely caption.

2. Sometimes the last page of a supertabular consists of an empty table. That is, just the head and foot of the table are printed.

3. If the number of lines in the first header for the table differs from the number of lines in subsequent headers, then the continuation pages of the table may be too short or, more troubling, too long.

The weaknesses are caused by trying to guess where TEX will put a page break. The package has to guesstimate how long the next entry will be in the table and, if it is too long for the available space, it puts in its own page break. If its guess is off too much in one direction, TEX will break the page unexpectadly; if it’s off in the other direction supertabular will put in an unnecessary page break.

The xtab package has reduced, but perhaps not entirely eliminated, these weaknesses. Some hand tuning may still be required.

The principal commands available are given in Table 1.

Table 1: The principal xtab package commands

Command  Effect

\begin{xtabular}{...} This is equivalent to the normal

                             \begin{tabular}{...} environment.

You supply the specification of the columns just as for the normal tabular environment. All commands that can be used within a tabular environment can also be used within the xtabular environment. Unlike the tabular environment which prevents page breaking within the tabular, the xtabular allows page breaking, so that tabulars can extend automatically across several pages.

Continued on next page

2I have corresponded with the authors of supertabular about these.

Table 1 – continued from previous page

Command  Effect

xtabular starts off with a tabular environment and checks the amount of space left on the page as it adds each row to the tabulation. If the space left on the page is too short for another row, then it ends the current tabular, performs a page break and starts another tabular on the following page. This process is repeated until all the rows have been output. There are special commands for captioning an xtabular as a table, and also elements can be automatically inserted after each (internal) \begin{tabular} and immediately before each \end{tabular}. Do not put a xtabular in a table environment, as the table environment keeps its contents on a single page (presumably you are using xtabular because its contents are longer than one page).

\end{xtabular}  End the xtabular environment.
\begin{mpxtabular} Like the xtabular environment except

that each ‘page’ is put into a minipage first. Thus it is possible to have footnotes inside an mpxtabular. The footnote text is printed at the end of each page.

\end{mpxtabular}  End the mpxtabular environment.

Note: If any of the following commands are used, then they should be placed before the particular xtabular environment that they apply to.

\topcaption{...} A command to provide a caption for the table. The caption is placed at the top of the table.

\bottomcaption{...} A command to provide a caption for the table. The caption is placed at the bottom of the table.

\tablecaption{...} A command to provide a caption for the table. The caption is placed at the default position, which is at the top of the table.

Continued on next page

Table 1 – continued from previous page

Command  Effect

Notes: You cannot use the \caption command but you can put a label after any of these captioning commands. If you want captioning, the command must be specified before the start of the supertabular environment. The \...caption{} command(s) remain in effect until changed by another

\...caption command.

\tablefirsthead{...} Defines the contents of the first occurence of the tabular head. The tabular head is some special treatment of the first row in the table. This command is optional. If used, the header must be closed by the end of line command for tabulars (e.g.,

\\).

\tablehead{...} Defines the contents of the table head on subsequent pages. For example, you might want to note that this is a continuation of the table on the previous page, as well as repeating any column headings that were given at the start of the xtabular by

\tablefirsthead.

The header must be closed like the

\tablefirsthead command.

\tablelasthead{...} Defines the contents of the table head on the last page of the table. For example, you might want to note that the table is concluded on this page. The header must be closed like the

\tablefirsthead command.
\notablelasthead  Switches off the last \tablelasthead.

A \tablelasthead stays in effect until overwritten by a new \tablelasthead or cancelled by this command.

\tabletail{...} The contents of this command are inserted before the (internal) \end{tabular} on each page except for the last page of the table.

Continued on next page

Table 1 – concluded from previous page

Command  Effect

For example, you might want to note that the table is continued on the next page.

\tablelasttail{...} The contents of this command are inserted before the final (internal)

                           \end{tabular} of the table.

For example, you might want to note that this is where the table ends.

As well as the xtabular and mpxtabular environments there are the corresponding starred versions (i.e., xtabular* and mpxtabular* for use in two column mode where the table is meant to span both columns.

Table 1 was produced by code similar to the following:

\topcaption{The principal xtab package commands} \label{tab:xtab}
\tablefirsthead{\hline \multicolumn{1}{|c|}{\textbf{Command}} &
                       \multicolumn{1}{c|}{\textbf{Effect}} \\ \hline }
\tablehead{\multicolumn{2}{c}%
           {{\captionsize\bfseries \tablename\ \thetable{} --
             continued from previous page}} \\
  \hline   \multicolumn{1}{|c|}{\textbf{Command}} &
           \multicolumn{1}{c|}{\textbf{Effect}} \\ \hline }
\tablelasthead{\multicolumn{2}{c}%
           {{\captionsize\bfseries \tablename\ \thetable{} --
             concluded from previous page}} \\
  \hline   \multicolumn{1}{|c|}{\textbf{Command}} &
           \multicolumn{1}{c|}{\textbf{Effect}} \\ \hline }
\tabletail{\hline \multicolumn{2}{|r|}{{Continued on next page}} \\ \hline}
\tablelasttail{\hline \hline}
\begin{center}
\begin{xtabular}{|l|p{0.5\textwidth}|}
\verb|\begin{xtabular}{...}| & This is equivalent to the normal
                         \verb|\begin{tabular}{...}| environment.
                         You supply the specification of the columns
                         just as for the normal \Lenv{tabular} environment.
 \\
 &
                         All commands that can be used within a \Lenv{tabular}
                         environment can also be used within
                         the \Lenv{xtabular} environment.
 \\
 &
    Unlike the \Lenv{tabular} environment which prevents page breaking
within the tabular, the \Lenv{xtabular} allows page breaking, so that
tabulars can extend automatically across several pages.
... ... ...
\verb|\tablelasttail{...}| & The contents of this command are inserted before
                         the final (internal) \verb|\end{tabular}| of the table.
 \\
 &
    For example, you might want to note that  this is where
the table ends.

  \\
 \end{xtabular}
 \end{center}

The table is only broken between rows — a row will not be split across pages. This can lead to some bad page breaks, especially if there are rows with a large vertical height (like some in Table 1). It is best to keep rows not too tall.

Unkike the table environment which floats, an xtabular environment is typeset at the point in the document where the environment is specified. It is best not to start an xtabular too close to the bottom of a page otherwise there might be an ugly page break.

The command \shrinkheight{⟨length⟩} may be used after the first \\ in the table to modify the allowed height of the table on each page. A positive ⟨length⟩ decreases the allowed space per page and a negative ⟨length⟩ increases the allowed space.

For example:

\shrinkheight{2\baselineskip} decreases the space per page by two lines. \shrinkheight{-\baselineskip} increases the space per page by one line. You may specify the font used for the \tablehead and \tablelasthead your-

self.

Note: Within ISO documents, captions shall be in bold font. The iso class also provides a command for setting the size of the font used in captions, namely \captionsize. The default value for this is set by the iso class. For the curious, the default definition is:

   \newcommand{\captionsize}{\normalsize}

2.1 Options

The xtab package has three options which control the amount of information that is written to the .log file. The options are:

1. The option errorshow (the default) does not write any extra information;

2. The option pageshow writes information about when and why xtab decides to produce a new page;

3. The option debugshow, which also includes pageshow, additionally writes information about each line that is added to the table.

Under normal circumstances xtab is used without invoking any option. The pageshow option may be useful when attempting to cure a bad page break. The debugshow option, as its name implies, is principally of use to the xtab developer.

Independently of the options, the command \sstraceon may be used at any point in the document to turn on printing of debugshow data. This can be turned off later by the \sstraceoff command, which will stop all … show printing.

3 The implementation

The xtab package provides an extension to the supertabular package written by Johannes Braams and Theo Jurriens.^{3} The major portion of the following documentation is taken from supertabular.dtx. The package is designed to be used with the iso class in addition to the usual article, etc., classes.

3supertabular.sty, version 4.1c, 7 November 1997.

The extension provided here enables the heading on the table on the last page to differ from those on earlier pages of the table. The implementation of the extension is based on ideas in David Carlisle’s longtable package. The downside of the extension is that L^{A}TEX has to be run twice if the document contains a supertabular. However, L^{A}TEX is usually run at least twice for any but the simplest document in order to get cross-references and Table of Contents, etc., resolved correctly.

The current version of the extension also either cures or reduces following weaknesses in the supertabular package.^{4}

1. Sometimes the top caption of a supertabular is printed on one page and the body is printed on the following page(s). That is, there is a lonely caption.

2. Sometimes the last page of a supertabular consists of an empty table. That is, just the head and foot of the table are printed.

3. If the number of lines in the first header for the table differs from the number of lines in subsequent headers, then the continuation pages of the table may be too short or, more troubling, too long.

The first version of xtab imported much of the code from the supertabular package (version 3.7) but I found that this did not work well because there were incompatible coded versions of supertabular available on CTAN. Further, I found that there were some problems with the original supertabular code in any case.^{5} I have to make the assumption that other users may have dissimilar or problematic versions, so include all the code here, and thus any errors can now be laid at my door.

The requirement for compatibilty with the iso class is achieved by modifications to the \ST@caption command only. Effectively this is orthogonal to the code required to implement the extension.

Now for the code itself. As syntactic sugar, all new macros for the extension have the prefix ‘PWST’ to distinguish them from the original macros. I have also denoted all extensions to the original supertabular by introducing them as Extension:.

Announce the name and version of the package, which requires L^{A}TEX 2ε.

1 ⟨∗xtab⟩

 2 \NeedsTeXFormat{LaTeX2e}
 3 \ProvidesPackage{xtab}[1998/04/13 v2 Extended supertabular package]

\c@tracingst There are three options with the package which control the amount of information written to the log file:

1. errorshow (the default) no extra information

2. pageshow writes information about page breaking

3. debugshow adds information about each line that is added to the tabular

4Only the first two of these have been recognised by the authors of supertabular.

5I also found a bug in the 4.1b version which the authors kindly fixed in version 4.1c.

 4 \newcount\c@tracingst
 5 \DeclareOption{errorshow}{\c@tracingst\z@}

Extension: The next line in the original code did not do what the authors intended; the number should have been 3 rather than 2.

 6 %%%%\DeclareOption{pageshow}{\c@tracingst\tw@}
 7 \DeclareOption{pageshow}{\c@tracingst\thr@@}
 8 \DeclareOption{debugshow}{\c@tracingst5\relax}
 9 \ProcessOptions
\if@topcaption \topcaption \bottomcaption The user-commands \topcaption and \bottomcaption set the flag @topcaption

to determine where to put the tablecaption. The default is to put the caption on the top of the table

10 \newif\if@topcaption \@topcaptiontrue
11 \def\topcaption{\@topcaptiontrue\tablecaption}
12 \def\bottomcaption{\@topcaptionfalse\tablecaption}

\PWST@thecaption \PWSTcapht Extension: \PWST@thecaption is used to store the text of the table’s caption. The vertical space required by a caption is stored in \PWSTcapht.

13 \gdef\PWST@thecaption{}
14 \newdimen\PWSTcapht

\tablecaption \@xtablecaption This command has to function exactly like \caption does except it has to store its argument (and the optional argument) for later processing within the supertabular environment.

15 \long\def\tablecaption{%
16 \refstepcounter{table}\@dblarg{\@xtablecaption}}
17 \long\def\@xtablecaption[#1]#2{%

Extension: I store the caption text for later measurement.

18 \long\gdef\PWST@thecaption{#2}%

Finish up with the original code.

19 \long\gdef\@process@tablecaption{\ST@caption{table}[#1]{#2}}}
20 \global\let\@process@tablecaption\relax

\ifST@star This switch is used in the internal macros to remember which kind of environment was started.

21 \newif\ifST@star

\ifST@mp This flag is used in the internal macros to remember if the tabular is to be put in a minipage.

22 \newif\ifST@mp

\ST@wd For the supertabular* environment it is necessary to store the intended width of the tabular.

23 \newdimen\ST@wd
\ST@rightskip \ST@leftskip \ST@parfillskip For the mpsupertabular environments we need special versions of \leftskip,
\rightskip and \parfillskip.
24 \newskip\ST@rightskip
25 \newskip\ST@leftskip
26 \newskip\ST@parfillskip

\ST@caption This is a redefinition of LaTeX’s \@caption, \@makecaption is called within a group so as not to return to \normalsize globally. Also, a fix is made for the ‘feature’ of the \@makecaption of article.sty and friends that a caption always gets a \vskip 10pt at the top and none at the bottom. If a user wants to precede his table with a caption this results in a collision.

27 \long\def\ST@caption#1[#2]#3{\par%
28 \addcontentsline{\csname ext@#1\endcsname}{#1}%
29  {\protect\numberline{%
30  \csname the#1\endcsname}{\ignorespaces #2}}
31 \begingroup
32  \@parboxrestore
33  \normalsize
34  \if@topcaption \vskip -10\p@ \fi
35  \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
36  \if@topcaption \vskip 10\p@ \fi
37 \endgroup}

Extension: For use with the iso class, I need a different definition of \ST@caption. This definition includes the command \iftabs which is not in any of the standard classes.

\iftabs It has to be defined in this package otherwise the

   \ifx\rectoisotitlehead\undefined
      ...

gets confused when it reaches the matching \fi to \iftabs. I also discovered that I could not use \newif\iftabs within the \ifx\... as that merely changed the location of the point of confusion. Therefore …

38 \@ifundefined{iftabs}{%
39 \newif\iftabs}{}

Now I can define the iso version of \ST@caption if it is required.

40 \ifx\rectoisotitlehead\undefined\else
41 \typeout{xtab using iso captions}
42 \long\def\ST@caption#1[#2]#3{\par%

For iso use I need to make sure that the lot file is set up.

43  \iftabs\else\tabstrue
44  \if@filesw\immediate\write\@mainaux{%
45  \string\gdef\string\settabs{%
46  \string\floatlist{\listtablename}{lot}}}
47  \fi
48  \fi

In the iso class the default is to put a skip both before and after a caption (in any case, top captions on tables look bad if there is no skip after the caption!). So, the original skips are modified.

49  \addcontentsline{\csname ext@#1\endcsname}{#1}%
50  {\protect\numberline{%
51  \csname the#1\endcsname}{\ignorespaces #2}}
52  \begingroup
53  \@parboxrestore
54  \normalsize
55  \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
56  \if@topcaption \vskip -10pt \fi

57  \endgroup}
58 \fi
\tablehead \tablefirsthead  \tablehead activates the new tabular \cr commands.
59 \newcommand\tablehead[1]{%
60 \gdef\@tablehead{%
61 \noalign{%
62  \global\let\@savcr=\\
63  \global\let\\=\org@tabularcr}%
64 #1%
65 \noalign{\global\let\\=\@savcr}}}
66 \tablehead{}
67 \newcommand\tablefirsthead[1]{\gdef\@table@first@head{#1}}
\c@PWSTtable \PWSTlastpage \PWSTcurpage \PWSTpenultimate \PWSTtempc \PWSTlines \PWSThead \PWSTlasthead Extension: These are counters for the supertabular extension. c@PWSTtable

counts the number of supertabulars in case one or more are not captioned. PW-STlastpage is a counter holding the number of pages that a supertabular uses and PWSTpenultimate is the penultimate page. PWSTcurpage counts the current number of supertabular pages processed. PWSTtempc is a scratch counter for page processing.

68 \newcounter{PWSTtable}
69 \newcount\PWSTlastpage
70 \newcount\PWSTpenultimate
71 \newcount\PWSTcurpage
72 \newcount\PWSTtempc

Extension: PWSTlines is used to count the number of supertabular entry lines on a page. Estimates of the number of lines in the normal table heading is held by PWSThead, and similarly PWSTlasthead is for the number of lines in the last heading.

73 \newcount\PWSTlines
74 \newcount\PWSThead
75 \newcount\PWSTlasthead

\iffirstcall Extension: This is used by the extension code to flag if the presumed last page overflows. If overflow occurs, then firstcall is set to false.

76 \newif\iffirstcall

\PWST@lastht \PWST@generalht \PWST@ht Extension: The estimated height of a table header and tail (i.e., the height of an empty table) for the last page of a supertabular is stored in \PWSTlastht. Similarly, the corresponding height of an empty table on a general page (neither the first nor the last) is stored in \PWSTgeneralht. \PWST@ht is a scratch variable.

77 \newdimen\PWST@lastht
78 \newdimen\PWST@generalht
79 \newdimen\PWST@ht
\tablelasthead \@table@last@head \notablelasthead Extension: \tablelasthead is the extension user command to specify the heading

for the last page of a supertabular. The command \notablelasthead switches off the last heading. This has to be used if a last headed table precedes one that does not have a special last head.

80 \newcommand{\tablelasthead}[1]{\gdef\@table@last@head{#1}}
81 \newcommand{\notablelasthead}{\let\@table@last@head\relax}

Now initialize these commands.

82 \tablelasthead{}
83 \notablelasthead

\tabletail \tablelasttail \tabletail is the user command to specify the appearance of the bottom of each tabular on a page. Special treatment is given to the end of the supertabular via

the \tablelasttail command.

If the user uses an extra amount of tabular-data (like \multicolumn) in \tabletail TEX starts looping because of the definition of \nextline. So make \\ act like just a \cr inside this tail to prevent the loop. Save and restore the value of \\

84 \newcommand\tabletail[1]{%
85 \gdef\@tabletail{%
86  \noalign{%
87  \global\let\@savcr=\\
88  \global\let\\=\org@tabularcr}%
89  #1%
90  \noalign{\global\let\\=\@savcr}}}
91 \tabletail{}
92 \newcommand\tablelasttail[1]{\gdef\@table@last@tail{#1}}
93 \tablelasttail{}

\sttraceon \sttraceoff The original supertabular included a tracing mechanism to follow the decisions supertabular made about page breaking. This is now also used as a debugging mechanism for the extension.

94 \newcommand\sttraceon{\c@tracingst5\relax}
95 \newcommand\sttraceoff{\c@tracingst\z@}

\ST@trace A macro that gets the trace message as its argument

96 \newcommand\ST@trace[2]{%
97 \ifnum\c@tracingst>#1\relax
98  \GenericWarning
99  {(xtab)\@spaces\@spaces}
100  {Package xtab: #2}%
101 \fi

102 }

\ST@pageleft This register holds the estimate of the amount of space left over on the current page. This is used in the decision when to start a new page.

103 \newdimen\ST@pageleft
\shrinkheight \setSTheight  \shrinkheight is a command to diminish the value of \ST@pageleft if necessary.

\setSTheight sets the value of \ST@pageleft if necessary.

104 \newcommand*\shrinkheight[1]{%
105 \noalign{\global\advance\ST@pageleft-#1\relax}}
106 \newcommand*\setSTheight[1]{%
107 \noalign{\global\ST@pageleft=#1\relax}}
\ST@headht \ST@tailht The register \ST@headht holds the height of the first head of a supertabular.

The register \ST@tailht holds the height of the tail.

108 \newdimen\ST@headht
109 \newdimen\ST@tailht

\ST@pagesofar Register \ST@pagesofar stores the estimate of the amount of the page already filled up.

110 \newdimen\ST@pagesofar

\ST@pboxht The measured (total) height of a parbox argument.

111 \newdimen\ST@pboxht

\ST@lineht \ST@stretchht \ST@prevht The estimated height of a normal line is stored in \ST@lineht. The register \ST@stretchht is used to store the difference between the normal line height and the line height when \arraystretch has a non-standard value. This is used in the case when p-box entries are added to the tabular. \ST@prevht stores the height of the previous line to use it as an estimate for the height of the next line. This is needed for a better estimate of when to break the tabular.

112 \newdimen\ST@lineht
113 \newdimen\ST@stretchht
114 \newdimen\ST@prevht

\ST@toadd When a tabular row is ended with \\[...] we need to temporarily store the optional argument in \ST@toadd.

115 \newdimen\ST@toadd

\ST@dimen A private scratch dimension register.

116 \newdimen\ST@dimen

\ST@pbox A box register to store the contents of a parbox.

117 \newbox\ST@pbox
\ST@tabularcr \ST@xtabularcr \ST@argtabularcr These are redefinitions of \@tabularcr and \@xtabularcr. This is needed to

include \ST@cr in the definition of \@xtabularcr.

All redefined macros have names that are similar to the original names, except with a leading ‘ST’.

118 \def\ST@tabularcr{%
119 {\ifnum0=`}\fi
120 \@ifstar{\ST@xtabularcr}{\ST@xtabularcr}}
121 \def\ST@xtabularcr{%
122 \@ifnextchar[%]
123  {\ST@argtabularcr}%
124  {\ifnum0=`{\fi}\cr\ST@cr}}
125 \def\ST@argtabularcr[#1]{%
126 \ifnum0=`{\fi}%
127 \ifdim #1>\z@
128  \unskip\ST@xargarraycr{#1}
129 \else
130  \ST@yargarraycr{#1}%
131 \fi}

\ST@xargarraycr \ST@yargarraycr In this case we need to copy the value of the optional argument of \\ in our private

register \ST@toadd.
132 \def\ST@xargarraycr#1{%
133 \@tempdima #1\advance\@tempdima \dp \@arstrutbox
134 \vrule \@height\z@ \@depth\@tempdima \@width\z@ \cr
135 \noalign{\global\ST@toadd=#1}\ST@cr}

Here we need to insert \ST@cr

136 \def\ST@yargarraycr#1{%
137 \cr\noalign{\vskip #1\global\ST@toadd=#1}\ST@cr}

\ST@startpbox The macros that deal with parbox columns need to be redefined, because we need to know the size of the parbox.

138 \def\ST@startpbox#1{%

To achieve our goal we need to save the text in box.

139 \setbox\ST@pbox\vtop\bgroup\hsize#1\@arrayparboxrestore}
\ST@astartpbox supertabular version of \@astartpbox.
140 \def\ST@astartpbox#1{%
141 \bgroup\hsize#1%
142 \setbox\ST@pbox\vtop\bgroup\hsize#1\@arrayparboxrestore}
\ST@endpbox \ST@aendpbox supertabular versions of \@endpbox and \@aendpbox.
143 \def\ST@endpbox{%
144 \@finalstrut\@arstrutbox\par\egroup
145 \ST@dimen=\ht\ST@pbox
146 \advance\ST@dimen by \dp\ST@pbox
147 \ifnum\ST@pboxht<\ST@dimen
148  \global\ST@pboxht=\ST@dimen
149 \fi
150 \ST@dimen=\z@
151 \box\ST@pbox\hfil}
152 \def\ST@aendpbox{%
153 \@finalstrut\@arstrutbox\par\egroup
154 \ST@dimen=\ht\ST@pbox
155 \advance\ST@dimen by \dp\ST@pbox
156 \ifnum\ST@pboxht<\ST@dimen
157  \global\ST@pboxht=\ST@dimen
158 \fi
159 \ST@dimen=\z@
160 \unvbox\ST@pbox\egroup\hfil}

\estimate@lineht Estimates the height of normal line taking \arraystretch into account. Also computes the difference between a ‘normal’ line and a stretched one.

161 \def\estimate@lineht{%
162 \ST@lineht=\arraystretch \baselineskip
163 \global\advance\ST@lineht by 1\p@
164 \ST@stretchht\ST@lineht\advance\ST@stretchht-\baselineskip
165 \ifdim\ST@stretchht<\z@\ST@stretchht\z@\fi
166 \ST@trace\tw@{Average line height: \the\ST@lineht}%
167 \ST@trace\tw@{Stretched line height: \the\ST@stretchht}%

168 }

\@calfirstpageht Estimates the space left on the current page and decides whether the tabular can be started on this page or on a new page. Aspects of the original code are modified for the extension.

169 \def\@calfirstpageht{%
170 \ST@trace\tw@{Calculating height of tabular on first page}%

The TEX register \pagetotal contains the height of the page sofar, the L^{A}TEX register \@colroom contains the height of the column.

171 \global\ST@pagesofar\pagetotal
172 \global\ST@pageleft\@colroom
173 \ST@trace\tw@{Height of text = \the\pagetotal; \MessageBreak
174  Height of page = \the\ST@pageleft}%

When we are in twocolumn mode TEX may still be collecting material for the first column although there seems to be no space left. In this case we have to check against two times \ST@pageleft.

175 \if@twocolumn
176  \ST@trace\tw@{two column mode}%
177  \if@firstcolumn
178  \ST@trace\tw@{First column}%
179  \ifnum\ST@pagesofar > \ST@pageleft
180  \global\ST@pageleft=2\ST@pageleft
181  \ifnum\ST@pagesofar > \ST@pageleft
182  \newpage\@calnextpageht
183  \ST@trace\tw@{starting new page}%
184  \else

In this case we’re in the second column, so we have to compensate for the material in the first column.

185  \ST@trace\tw@{Second column}%
186  \global\advance\ST@pageleft -\ST@pagesofar
187  \global\advance\ST@pageleft -\@colroom
188  \fi

When \ST@pagesofar is smaller than \ST@pageleft TEX is still collecting material for the first column, so we can start a new tabular environment like we do on a single column page.

189  \else
190  \global\advance\ST@pageleft by -\ST@pagesofar
191  \global\ST@pagesofar\z@
192  \fi
193  \else

When we end up here, TEX has already decided it had enough material for the first column and is building the second column.

194  \ST@trace\tw@{Second column}%
195  \ifnum\ST@pagesofar > \ST@pageleft
196  \ST@trace\tw@{starting new page}%
197  \newpage\@calnextpageht
198  \else
199  \global\advance\ST@pageleft by -\ST@pagesofar
200  \global\ST@pagesofar\z@
201  \fi
202  \fi
203 \else

In one column mode there is a simple decision.

204  \ST@trace\tw@{one column mode}%
205  \ifnum\ST@pagesofar > \ST@pageleft
206  \ST@trace\tw@{starting new page}%
207  \newpage\@calnextpageht

When we are not starting a new page subtract the size of the material already on it from the available space.

208  \else
209  \global\advance\ST@pageleft by -\ST@pagesofar
210  \global\ST@pagesofar\z@
211  \fi
212 \fi
213 \ST@trace\tw@{Available height: \the\ST@pageleft}%

Now we need to know the height of the head of the table. In order to measure this we typeset it in a normal tabular environment.

214 \ifx\@@tablehead\@empty
215  \ST@headht=\z@
216 \else
217  \setbox\@tempboxa=\vbox{\@arrayparboxrestore
218  \ST@restore
219  \expandafter\tabular\expandafter{\ST@tableformat}%
220  \@@tablehead\endtabular}%
221  \ST@headht=\ht\@tempboxa\advance\ST@headht\dp\@tempboxa
222 \fi
223 \ST@trace\tw@{Height of head: \the\ST@headht}%

To decide when to start a new page, we need to know the vertical size of the tail of the table.

224 \ifx\@tabletail\@empty
225  \ST@tailht=\z@
226 \else
227  \setbox\@tempboxa=\vbox{\@arrayparboxrestore
228  \ST@restore
229  \expandafter\tabular\expandafter{\ST@tableformat}
230  \@tabletail\endtabular}
231  \ST@tailht=\ht\@tempboxa\advance\ST@tailht\dp\@tempboxa
232 \fi

We add the average height of a line to this because when we decide to continue the tabular we need to have enough space left for one line and the tail.

233 \advance\ST@tailht by \ST@lineht
234 \ST@trace\tw@{Height of tail: \the\ST@tailht}%
235 \ST@trace\tw@{Maximum height of tabular: \the\ST@pageleft}%

Now we decide whether we can continue on the current page or whether we need to start a new page. We assume that the minimum height of a tabular is the height of the head and tail and one line of data. If that doesn’t fit, start a new page.

236 \@tempdima\ST@headht
237 \advance\@tempdima\ST@lineht
238 \advance\@tempdima\ST@tailht

Extension: I also add the height of the caption to the required space. The amount to be added depends on whether it is a top or bottom caption. Allowance is also made for skips around the caption.

239 \if@topcaption
240  \setbox\@tempboxa=\vbox{\PWST@thecaption}
241  \PWSTcapht=\ht\@tempboxa\advance\PWSTcapht\dp\@tempboxa

242  \advance\PWSTcapht by 20\p@
243 \else
244  \PWSTcapht = 10\p@
245 \fi
246 \ST@trace\tw@{Caption height: \the\PWSTcapht}%
247 \advance\@tempdima\PWSTcapht

Continue with the original code.

248 \ST@trace\tw@{Minimum height of tabular: \the\@tempdima}%
249 \ifnum\@tempdima>\ST@pageleft
250  \ST@trace\tw@{starting new page}%

Extension: The next line in the original code is \newpage\@calnextpageht. I need to start a new page, making allowance for the space required by the caption.

251  \newpage
252  \global\ST@pageleft\@colroom
253  \global\advance\ST@pageleft by -\PWSTcapht
254  \global\ST@pagesofar=\z@

Finish up with the original code.

255 \fi

256 }

\@calnextpageht This calculates the maximum height of the tabular on all subsequent pages of the supertabular environment.

257 \def\@calnextpageht{%
258 \ST@trace\tw@{Calculating height of tabular on next page}%
259 \global\ST@pageleft\@colroom
260 \global\ST@pagesofar=\z@
261 \ST@trace\tw@{Maximum height of tabular: \the\ST@pageleft}%

262 }

\PWSTcalchtlines Extension: A macro to calculate the space required by an empty table and the number of lines in an empty table. I am only concerned with the number of lines on an empty table on the last page.

The appropriate heads and tails are typeset in a temporary box so we can measure them.

263 \newcommand{\PWSTcalchtlines}{%

Measure the lasttail.

264 \setbox\@tempboxa=\vbox{\@arrayparboxrestore
265  \ST@restore
266  \expandafter\tabular\expandafter{\ST@tableformat}%
267  \@table@last@tail\endtabular}%
268 \PWST@ht=\ht\@tempboxa\advance\PWST@ht\dp\@tempboxa
269 \global\PWST@lastht = \PWST@ht

Calculate the number of lines for the lasttail.

270 \PWSTlines = \PWST@ht
271 \divide\PWSTlines by \baselineskip
272 \global\PWSTlasthead = \PWSTlines
273 \global\PWSThead = \PWSTlasthead

And repeat for the lasthead.

274 \setbox\@tempboxa=\vbox{\@arrayparboxrestore
275  \ST@restore

276  \expandafter\tabular\expandafter{\ST@tableformat}%
277  \@table@last@head\endtabular}%
278 \PWST@ht = \ht\@tempboxa\advance\PWST@ht\dp\@tempboxa
279 \global\advance\PWST@lastht by \PWST@ht
280 \ST@trace\tw@{Height of last empty table = \the\PWST@lastht}%
281 \PWSTlines = \PWST@ht
282 \divide\PWSTlines by \baselineskip
283 \global\advance\PWSTlasthead by \PWSTlines

\PWSTlasthead now holds the number of lines required for printing the last head and tail. I add one to this as later I want to do a ‘less than or equal to’ test against this number of lines.

284 \global\advance\PWSTlasthead \@ne
285 \ST@trace\tw@{Number of lines + 1 in last empty table = \the\PWSTlasthead}%

Now repeat pretty well all of the above for a general table (i.e., one that is not on the first page nor the designated last page).

First the tail.

286 \setbox\@tempboxa=\vbox{\@arrayparboxrestore
287  \ST@restore
288  \expandafter\tabular\expandafter{\ST@tableformat}%
289  \@tabletail\endtabular}%
290 \PWST@ht=\ht\@tempboxa\advance\PWST@ht\dp\@tempboxa
291 \global\PWST@generalht = \PWST@ht

I don’t need the number of lines used by the general tail, so move on to the general head.

292 \setbox\@tempboxa=\vbox{\@arrayparboxrestore
293  \ST@restore
294  \expandafter\tabular\expandafter{\ST@tableformat}%
295  \@tablehead\endtabular}%
296 \PWST@ht = \ht\@tempboxa\advance\PWST@ht\dp\@tempboxa
297 \global\advance\PWST@generalht by \PWST@ht
298 \ST@trace\tw@{Height of general empty table = \the\PWST@generalht}%

Calculate the number of lines required if this table is on an actual, but not calculated, last page.

299 \PWSTlines = \PWST@ht
300 \divide\PWSTlines by \baselineskip
301 \global\advance\PWSThead by \PWSTlines
302 \global\advance\PWSThead \@ne
303 \ST@trace\tw@{Number of lines + 1 in general empty table = \the\PWSThead}%

304 }

\PWSTcalnextpageht Extension: From some experiments that I ran it appeared as though the supertabular package ignored the possibility that the space required for the table header and tail on pages after the first one might be different. If the subsequent head/tail combination were longer (i.e., took more vertical space) then the table could overflow the page. This is an attempt to fix this problem by calculating the actual minimum space required after the first page.

The calculations are similar to, but simpler, than those for \@calfirstpageht.

305 \newcommand{\PWSTcalnextpageht}{%
306 \ifnum\PWSTcurpage = \PWSTpenultimate
307  \ST@trace\tw@{Calculating height of tabular on last page}%

We are on the penultimate page, so get the height of the last head/tail.

308  \PWST@ht=\PWST@lastht

Otherwise I need the general page data.

309 \else
310  \ST@trace\tw@{Calculating height of tabular on next general page}%
311  \PWST@ht=\PWST@generalht
312 \fi

Having dealt with the two cases, I can now calculate the minimum space for a supertabular on the following page.

313 \global\ST@pageleft\@colroom
314 \global\advance\ST@pageleft -\PWST@ht
315 \global\ST@pagesofar=\z@
316 \ST@trace\tw@{Maximum height of tabular: \the\ST@pageleft}%

317 }

\x@supertabular The various supertabular environments share a lot of code. Thus, to avoid needless

repetition, the shared code is defined in this macro.

This macro has been modified as part of the supertabular extension.

318 \def\x@supertabular{%

First save the original definition of \tabular and then make it point to \inner@tabular. This is done to enable supertabular cells to contain a tabular environment without getting unexpected results when the supertabular would be split across this inner tabular environment.

319 \let\org@tabular\tabular
320 \let\tabular\inner@tabular

The same has to be done for the tabular* environment. The coding is more verbose.

321 \expandafter\let
322  \csname org@tabular*\expandafter\endcsname
323  \csname tabular*\endcsname
324 \expandafter\let\csname tabular*\expandafter\endcsname
325  \csname inner@tabular*\endcsname

Extension: The original code printed out the top caption at this point. If there is too little space on the first page of the table, the tabular data is printed on the following page. If this is the case (and its not known yet whether it is), then the caption should also be printed on the following page.

326 %%%%  \if@topcaption \@process@tablecaption \fi

Back to the original code. Save the original definition of \\.

327 \global\let\@oldcr=\\

Save the current value of \baselineskip, as we need it in the calculation of the average height of a line.

328 \def\baslineskp{\baselineskip}%

We have to check whether array.sty was loaded, because some of the internal macros have different names.

329 \ifx\undefined\@classix

Save old \@tabularcr and insert the definition of \@stabularcr.

330  \let\org@tabularcr\@tabularcr
331  \let\@tabularcr\ST@tabularcr

Activate the new parbox algorithm.

332  \let\org@startpbox=\@startpbox
333  \let\org@endpbox=\@endpbox
334  \let\@@startpbox=\ST@startpbox
335  \let\@@endpbox=\ST@endpbox
336 \else

When array.sty was loaded things are a bit different.

337  \let\org@tabularcr\@arraycr
338  \let\@arraycr\ST@tabularcr
339  \let\org@startpbox=\@startpbox
340  \let\org@endpbox=\@endpbox
341  \let\@startpbox=\ST@astartpbox
342  \let\@endpbox=\ST@aendpbox
343 \fi

Check if the head of the table should be different for the first and subsequent pages.

344 \ifx\@table@first@head\undefined
345  \let\@@tablehead=\@tablehead
346 \else
347  \let\@@tablehead=\@table@first@head
348 \fi

The first part of a supertabular may be moved to the next page if it doesn’t fit on the current page. Subsequent parts can not be moved; therefore we will have to switch the definition of \ST@skippart around.

349 \let\ST@skippage\ST@skipfirstpart

Now we can estimate the average line height and the height of the first page of the supertabular.

350 \estimate@lineht
351 \@calfirstpageht

Extension: Call the macro to initialize the extension code for this table.

352 \PWSTinit

Extension: At this point I know, and have adjusted for, the page on which the first part of the table will be printed. It should now be safe to print the top caption, if any. Unfortunately, in spite of everthing, the TEX page breaking mechanism might still think that there is too little space left.

353 \if@topcaption \@process@tablecaption \fi

And finish off per the original code.

354 \noindent

355 }

\PWSTinit Extension: This routine initialises the extension data.

356 \newcommand{\PWSTinit}{%

At the end of processing each supertabular (see later) the number of pages consumed by the supertabular is written to the .aux file. At the start of a supertabular, after incrementing the number of supertabulars processed, the prior number of pages are read from the file. These are stored in PWSTlastpage.

357 \global\advance\c@PWSTtable\@ne
358 \global\expandafter\let\expandafter\PWSTtempc
359  \csname PWST@\romannumeral\c@PWSTtable\endcsname

I have to take account of the fact that there might be no entry in the .aux file, and hence the lastpage number might not be set.

360 \ifx\PWSTtempc\relax
361  \ST@trace\tw@{Table \the\c@PWSTtable: Processing for the first time}%
362  \PWSTlastpage=\@m % = 1000
363 \else
364  \PWSTlastpage=\PWSTtempc
365 \fi
366 \ST@trace\tw@{Table \the\c@PWSTtable: last page set to \the\PWSTlastpage}%

Set the current page counter to unity.

367 \PWSTcurpage=\@ne

Perform the calculations for the empty table data.

368 \PWSTcalchtlines

Initialise the line counter and set firstcall to TRUE.

369 \global\PWSTlines=\z@
370 \global\firstcalltrue

If we have the iso class, then I have to flag that we are in a ‘float’.

371 \ifx\rectoisotitlehead\undefined\else
372  \infloattrue
373 \fi

374 }

\xtabular \supertabular We start by looking for an optional argument, which will be duly ignored as it

seems to make no sense to try to align a multipage table in the middle...

Extension: Use xtabular instead of supertabular, but for backward compatibility retain supertabular as deprecated. I will do similar renaming for all the environments, so this will not be mentioned explicitly again.

375 \def\xtabular{%
376 \@ifnextchar[{\@supertabular}%]
377  {\@supertabular[]}}
378 \def\supertabular{%
379 \PackageWarning{xtab}{supertabular is deprecated. Use xtabular instead.}%
380 \@ifnextchar[{\@supertabular}%]
381  {\@supertabular[]}}

\@supertabular We can now save the preamble of the tabular in a macro.

382 \def\@supertabular[#1]#2{%
383 \def\ST@tableformat{#2}
384 \ST@trace\tw@{Starting a new supertabular}%

Then remember that this is not a supertabular* environment.

385 \global\ST@starfalse

Don’t use minipages.

386 \global\ST@mpfalse

Most of the following code is shared between the supertabbular and supertabular* environments. So to avoid duplication it is stored in a macro.

387 \x@supertabular

Finally start a normal tabular environment.

388 \expandafter\org@tabular\expandafter{\ST@tableformat}%
389 \@@tablehead}

\xtabular* \supertabular* We start by looking for the optional argument of the tabular environment.

390 \@namedef{xtabular*}#1{%
391 \@ifnextchar[{\@nameuse{@supertabular*}{#1}}%
392  {\@nameuse{@supertabular*}{#1}[]}%]

393 }

394 \@namedef{supertabular*}#1{%
395 \PackageWarning{xtab}{supertabular* is deprecated. Use xtabular* instead.}%
396 \@ifnextchar[{\@nameuse{@supertabular*}{#1}}%
397  {\@nameuse{@supertabular*}{#1}[]}%]

398 }

We start by saving the intended width and the preamble of the tabular*.

399 \@namedef{@supertabular*}#1[#2]#3{%
400 \ST@trace\tw@{Starting a new supertabular*}%
401 \def\ST@tableformat{#3}%
402 \ST@wd=#1\relax
403 \global\ST@startrue
404 \global\ST@mpfalse

Now we can call the common code for both environments.

405 \x@supertabular

And we can start a normal tabular* environment.

406 \expandafter\csname org@tabular*\expandafter\endcsname
407 \expandafter{\expandafter\ST@wd\expandafter}%
408 \expandafter{\ST@tableformat}%
409 \@@tablehead}%

\mpxtabular \mpsupertabular This version of the supertabular environment puts each tabular into a minipage, thus making footnotes possible. We start by looking for an optional argument, which will be ignored as it makes no sense to try and align a multipage table in the middle…

410 \def\mpxtabular{%
411 \@ifnextchar[{\@mpsupertabular}%]
412  {\@mpsupertabular[]}}
413 \def\mpsupertabular{%
414 \PackageWarning{xtab}{mpsupertabular is deprecated. Use mpxtabular instead.}%
415 \@ifnextchar[{\@mpsupertabular}%]
416  {\@mpsupertabular[]}}

We can now save the preamble in a macro.

417 \def\@mpsupertabular[#1]#2{%
418 \def\ST@tableformat{#2}%
419 \ST@trace\tw@{Starting a new mpsupertabular}%

Remember that this is not a mpsupertabular* environment and also note we have to close the minipage later.

420 \global\ST@starfalse
421 \global\ST@mptrue

Since we are about to start a minipage of \columnwidth the horizontal alignment will not work. We have to remember the values and then restore them inside the minipage.

422 \ST@rightskip \rightskip
423 \ST@leftskip \leftskip
424 \ST@parfillskip \parfillskip

Call the code that is common to all the environments.

425 \x@supertabular

Finally, start a normal tabular

426 \minipage{\columnwidth}%
427 \parfillskip\ST@parfillskip
428 \rightskip \ST@rightskip
429 \leftskip \ST@leftskip
430 \noindent\expandafter\org@tabular\expandafter{\ST@tableformat}%
431 \@@tablehead}

\mpxtabular* \mpsupertabular* We start by looking for the optional argument of the tabular environment.

432 \@namedef{mpxtabular*}#1{%
433 \@ifnextchar[{\@nameuse{@mpsupertabular*}{#1}}%
434  {\@nameuse{@mpsupertabular*}{#1}[]}%]

435 }

436 \@namedef{mpsupertabular*}#1{%
437 \PackageWarning{xtab}{mpsupertabular* is deprecated. Use mpxtabular* instead.}%
438 \@ifnextchar[{\@nameuse{@mpsupertabular*}{#1}}%
439  {\@nameuse{@mpsupertabular*}{#1}[]}%]

440 }

Now we can save the intended width and the preamble of the tabular*.

441 \@namedef{@mpsupertabular*}#1[#2]#3{%
442 \ST@trace\tw@{Starting a new mpsupertabular*}%
443 \def\ST@tableformat{#3}%
444 \ST@wd=#1\relax
445 \global\ST@startrue
446 \global\ST@mptrue
447 \ST@rightskip \rightskip
448 \ST@leftskip \leftskip
449 \ST@parfillskip \parfillskip

Now is the time to call the common code for both environments.

450 \x@supertabular

And we can start a normal tabular* environment.

451 \minipage{\columnwidth}%
452 \parfillskip\ST@parfillskip
453 \rightskip \ST@rightskip
454 \leftskip \ST@leftskip
455 \noindent\expandafter\csname org@tabular*\expandafter\endcsname
456 \expandafter{\expandafter\ST@wd\expandafter}%
457 \expandafter{\ST@tableformat}%
458 \@@tablehead}%
\endxtabular \endxtabular* \endsupertabular \endsupertabular* These close the supertabular and supertabular* environments.

For the extension, this macro has been modified to write out to the .aux file the number of pages used for the supertabular.

459 \def\endxtabular{%
460 \ifx\@table@last@tail\undefined
461  \@tabletail
462 \else
463  \@table@last@tail

464 \fi
465 \csname endtabular\ifST@star*\fi\endcsname

While studying the original code to determine where additions were needed for the extension, I realized that the last part of the \end... code was common to all the environments. I have broken it out into a seperate routine which also includes the modification needed for the extension.

466 \x@endsupertabular

And back to the original code.

467 \ST@trace\tw@{Ended a supertabular\ifST@star*\fi}%

468 }

469 \def\endsupertabular{\endxtabular}
470 %    The definition of the ending of the \Lenv{supertabular*}
471 %    environment is simple:
472 %    \begin{macrocode}
473 \expandafter\let\csname endxtabular*\endcsname\endxtabular
474 \expandafter\let\csname endsupertabular*\endcsname\endsupertabular

\x@endsupertabular This macro contains the code that is common to all the \end... commands. It includes the modification required for the extension.

475 \newcommand{\x@endsupertabular}{%

Restore the original definition of \@tabularcr

476 \ST@restore

Check if we have to insert a caption and restore to default behaviour of putting captions at the top.

477 \if@topcaption
478 \else
479  \@process@tablecaption
480  \global\@topcaptiontrue
481 \fi

Restore the meaning of \\ to the one it had before the start of this environment. Also re-initialize some control-sequences

482 \global\let\\=\@oldcr
483 \global\let\@table@first@head\undefined
484 \global\let\@table@last@tail\undefined
485 \global\let\@process@tablecaption\relax

Extension: For the extension, write the number of the last page to the .aux file. Also, if we are in the iso class, reset the ‘float’ flag.

486 \PWSToplastpagenum
487 \ifx\rectoisotitlehead\undefined\else
488  \infloatfalse
489 \fi

490 }

\PWSToplastpagenum Extension: This routine is responsible for writing the number of the last page of

the supertabular to the .aux file.

What gets written is \PWST@vi{4}, assuming that the value of c@PWSTtable is 6 and the value of PWSTcurpage is 4.

491 \newcommand{\PWSToplastpagenum}{%

There are a number of cases to consider. The first decision is whether the current page is the previously calculated last page.

492 \ifnum\PWSTcurpage=\PWSTlastpage

The current table ends on the calculated last page. There are four cases to consider:

1. The table has not overflowed (firstcall is TRUE) and the table is not empty — this page is still the last page.

2. The table has not overflowed (firstcall is TRUE) and the table is empty — this page is after the actual last page, so decrease the page number.

3. The table has overflowed (firstcall is FALSE) and the overflow is large enough to generate a non-empty table on the next page — increment the page number.

4. The table has overflowed (firstcall is FALSE) and the overflow is small enough to generate an empty table on the next page — this page is still the last page.

493  \iffirstcall  % on last, no overflow
494  \ifnum\PWSTlines < \PWSTlasthead % this table is empty
495  \global\advance\PWSTcurpage \m@ne
496  \fi
497  \else % overflow
498  \ifnum\PWSTlines > \tw@ % enough for another page
499  \global\advance\PWSTcurpage \@ne
500  \fi
501  \fi
502 \else

The table has ended on a page that is not the calculated last page. If the table is empty, then decrement the page number, else this is the last page.

503  \ifnum\PWSTlines < \PWSThead % empty table
504  \global\advance\PWSTcurpage \m@ne
505  \fi
506 \fi

Finally, write out the ‘new’ last page number.

507 \if@filesw\immediate\write\@auxout%
508  {\gdef\string\PWST@\romannumeral\c@PWSTtable{\the\PWSTcurpage}}
509  \ST@trace\tw@{Table \the\c@PWSTtable: wrote \the\PWSTcurpage\space as the last page}%
510 \fi

511 }

\endmpxtabular \endmpxtabular* \endmpsupertabular \endmpsupertabular* These close the mpsupertabular and mpsupertabular environments.
512 \def\endmpxtabular{%
513 \ifx\@table@last@tail\undefined
514  \@tabletail
515 \else
516  \@table@last@tail
517 \fi
518 \csname endtabular\ifST@star*\fi\endcsname
519 \endminipage

Now call the common code for all \end....

520 \x@endsupertabular

Finish per the original code.

521 \ST@trace\tw@{Ended an mpsupertabular\ifST@star*\fi}%

522 }

523 \def\endmpsupertabular{\endmpxtabular}

524 %

525 %    The definition of the ending of the \Lenv{mpsupertabular*}
526 %    environment is simple:
527 %    \begin{macrocode}
528 \expandafter\let\csname endmpxtabular*\endcsname\endmpxtabular
529 \expandafter\let\csname endmpsupertabular*\endcsname\endmpsupertabular

\ST@restore This macro restores the original definitions of the macros that handle parbox entries and the ‘end of row’ macros.

530 \def\ST@restore{%
531 \ifx\undefined\@classix
532  \let\@tabularcr\org@tabularcr
533 \else
534  \let\@arraycr\org@tabularcr
535 \fi
536 \let\@startpbox\org@startpbox
537 \let\@endpbox\org@endpbox

538 }

\inner@tabular \inner@tabular* In order to facilitate complete tabular environments to be in a cell of a supertabular we need to adapt the definition of the original environments. For the inner tabular a number of definitions have to be restored.

539 \def\inner@tabular{%
540 \ST@restore
541 \let\\=\@oldcr
542 \noindent
543 \org@tabular}
544 \@namedef{inner@tabular*}{%
545 \ST@restore
546 \let\\=\@oldcr
547 \noindent
548 \csname org@tabular*\endcsname}

\ST@cr This macro is called by each \\ inside the tabular environment. It updates the estimate of the amount of space left on the current page and starts a new page if necessary.

549 \def\ST@cr{%
550 \noalign{%
551  \ST@trace\thr@@{Parbox height: \the\ST@pboxht \space\space Line height: \the\ST@lineht}%
552  \ifnum\ST@pboxht<\ST@lineht

If there is a non-empty line, but an empty parbox, then \ST@pboxht might be non-zero, but too small thereby breaking the algorithm. Therefore we estimate the height of the line to be \ST@lineht in this case, and store it in \ST@prevht.

553  \global\advance\ST@pageleft -\ST@lineht
554  \global\ST@prevht\ST@lineht
555  \else

When the parbox is not empty we take its height into account (plus a little extra).

556  \ST@trace\thr@@{Added par box with height \the\ST@pboxht}%
557  \global\advance\ST@pageleft -\ST@pboxht
558  \global\advance\ST@pageleft -0.1\ST@pboxht
559  \global\advance\ST@pageleft -\ST@stretchht
560  \global\ST@prevht\ST@pboxht
561  \global\ST@pboxht\z@
562  \fi

\ST@toadd is the value of the optional argument of \\.

563  \global\advance\ST@pageleft -\ST@toadd
564  \global\ST@toadd=\z@
565  \ST@trace\thr@@{Space left for tabular: \the\ST@pageleft}%

Extension: Increment the line number at this point.

566  \global\advance\PWSTlines \@ne
567  \ST@trace\thr@@{Line counter incremented by one to: \the\PWSTlines}%
568 } % end of noalign

In general, when the \ST@pageleft has become negative, the last row was so high that the supertabular doesn’t fit on the current page. In this case we skip the current page and start at the top of the next one; otherwise TEX will move this part of the table to a new page anyway, probably with a message about an overfull

\vbox.

Extension: For the extension I do some special handling if we are on the last page. Essentially the idea is not to start a new page, but to continue on the current page, noting any overflow.

569 \ifnum\PWSTcurpage=\PWSTlastpage
570  \PWST@lastpagecr
571 \else

Execute the original code.

572  \ifnum\ST@pageleft<\z@
573  \ST@skippage
574  \else

When there is not enough space left on the current page, we start a new page. To compute the amount of space needed we use the height of the previous line (\ST@prevht) as an estimate of the height of the next line. If we are processing an mpsupertabular we also need to take the height of the footnotes into account.

575  \noalign{\global\@tempdima\ST@tailht
576  \global\advance\@tempdima\ST@prevht
577  \ifST@mp
578  \ifvoid\@mpfootins\else
579  \global\advance\@tempdima\ht\@mpfootins
580  \global\advance\@tempdima 3pt
581  \fi
582  \fi} % end noalign
583  \ifnum\ST@pageleft<\@tempdima
584  \ST@newpage
585  \else

This line is necessary because the tablehead has to be inserted after the \if\else\fi-clause. For this purpose \ST@next is used. In the middle of tableprocessing it should be an empty macro (not \relax).

586  \noalign{\global\let\ST@next\@empty}%
587  \fi
588  \fi

Extension: Close off the \iflastpage;

589 \fi

and finish per the original code.

590 \ST@next}

\PWST@lastpagecr Extension: This routine handles newlines on the last page of a supertabular. The idea is that when we are on the last page the table continues to be processed until the end without calling for a newpage even if the table will be too long. I do need to record whether or not the table has ‘overflowed’ the allowable space on the page. The code is very similar to the last part of the code for \ST@cr.

591 \newcommand{\PWST@lastpagecr}{%
592 \noalign{%
593  \ifnum\ST@pageleft<\z@

The table has overflowed, so record the fact.

594  \PWST@setfirstcall
595  \fi

Now continue along the lines of \ST@cr.

596  \global\@tempdima\ST@tailht
597  \global\advance\@tempdima\ST@prevht
598  \ifST@mp
599  \ifvoid\@mpfootins\else
600  \global\advance\@tempdima\ht\@mpfootins
601  \global\advance\@tempdima 3pt
602  \fi
603  \fi
604  \ifnum\ST@pageleft<\@tempdima

Again, the table has overflowed.

605  \PWST@setfirstcall
606  \fi

Finish like \ST@cr.

607  \global\let\ST@next\@empty
608  } % end noalign

609 }

\PWST@setfirstcall Extension: This routine records that a table on the last page has overflowed by setting firstcall to FALSE. If it is the first such overflow it also zeroes the line counter.

610 \newcommand{\PWST@setfirstcall}{%
611 \iffirstcall
612  \global\firstcallfalse
613  \global\PWSTlines=\z@
614  \ST@trace\thr@@{Overflow on last page. Line counter zeroed to \the\PWSTlines}%
615 \fi

616 }

\ST@skipfirstpart This macro skips the current page and moves the entire supertabular that has been built so far to the next page.

617 \def\ST@skipfirstpart{%
618 \noalign{%
619  \ST@trace\tw@{Tabular too high, moving to next page}%

In order for this to work properly we need to adapt the value of \ST@pageleft. When this macro is called it has a negative value. We should add the height of the next page to that (\@colroom). From the result the ‘normal’ height of the supertabular should be subtracted (\@colroom - \pagetotal). This could be coded as follows:

      \ST@dimen\@colroom
      \advance\ST@dimen-\pagetotal
      \global\advance\ST@pageleft\@colroom
      \global\advance\ST@pageleft-\ST@dimen

However, note that \@colroom is added and subtracted. Thus the code can be simplified to:

620  \global\advance\ST@pageleft\pagetotal

Then we can set \ST@pagesofar to zero and start the new page.

621  \global\ST@pagesofar\z@
622  \newpage

Finally we make sure that this macro can only be executed once for each supertabular by changing the definition of \ST@skippage.

623  \global\let\ST@skippage\ST@newpage

624 } 625 }

\ST@newpage This macro performs the actions necessary to start a new page. This macro is also modified for the extension to supertabluar.

626 \def\ST@newpage{%
627 \noalign{\ST@trace\tw@{Starting new page, writing tail}}%

Output \tabletail, close the tabular environment, close a minipage if necessary, output all material and start a fresh new page.

628 \@tabletail
629 \ifST@star
630  \csname endtabular*\endcsname
631 \else
632  \endtabular
633 \fi
634 \ifST@mp
635  \endminipage
636 \fi

Then we make sure that \ST@skippage can no longer be executed for this supertabular by changing its definition.

637 \global\let\ST@skippage\ST@newpage

On with the output.

Extension: The original code had the next line as \newpage\@calnextpageht. However, if the general header has a vertical height that differs from the first header, then the table on the continuation pages may run short or, more disconcerting, long. The extension, I think, cures that by using a different algorithm to calculate the height on the next page.

638 %%%%  \newpage\@calnextpageht
639 \newpage\PWSTcalnextpageht
640 \ST@trace\tw@{writing head}%

Extension: The original code just let \ST@next to \@tablehead. The extension has to handle the special case of of the heading on the last page.

641 %%%%  \let\ST@next\@tablehead
642 \PWSTsethead

Now we are back to the original supertabular code.

643 \ifST@mp
644  \noindent\minipage{\columnwidth}%
645  \parfillskip\ST@parfillskip
646  \rightskip \ST@rightskip
647  \leftskip \ST@leftskip
648 \fi
649 \noindent
650 \ifST@star
651  \expandafter\csname org@tabular*\expandafter\endcsname
652  \expandafter{\expandafter\ST@wd\expandafter}%
653  \expandafter{\ST@tableformat}%
654 \else
655  \expandafter\org@tabular\expandafter{\ST@tableformat}%
656 \fi}

\PWSTsethead Extension: This is more extension code for use within \ST@newpage. It provides the proper table head for the page about to be processed.

657 \newcommand{\PWSTsethead}{%

First the line counter is zeroed.

658 \global\PWSTlines=\z@
659 \ST@trace\thr@@{Newpage, line counter zeroed to: \the\PWSTlines}%

The current page counter is incremented and it is checked against the old page counter to see if this is the last page of this supertabular.

660 \global\advance\PWSTcurpage\@ne
661 \ST@trace\tw@{Table \the\c@PWSTtable: current page = \the\PWSTcurpage,
662  last page = \the\PWSTlastpage}%
663 \ifnum\PWSTcurpage=\PWSTlastpage
664  \ST@trace\tw@{Newpage is the last page}%

We are on the last page. If there are more than one pages and the last table heading has been specified, then the heading is set to \@table@last@head, otherwise it is

 set to \@tablehead.
665  \ifnum\PWSTcurpage>\@ne
666  \ifx\@table@last@head\relax
667  \let\ST@next\@tablehead
668  \ST@trace\tw@{Set heading to tablehead}%
669  \else
670  \let\ST@next\@table@last@head
671  \ST@trace\tw@{Set heading to tablelasthead}%
672  \fi

673  \fi
674 \else

We are not on the last page, so just set the heading to \@tablehead.

675  \let\ST@next\@tablehead
676  \ST@trace\tw@{Set heading to tablehead}%
677 \fi

678 }

The end of this package

679 ⟨/xtab⟩

References

[GMS94] Michel Goossens, Frank Mittelbach, and Alexander Samarin. The LaTeX Companion. Addison-Wesley Publishing Company, 1994.

[Wil96] Peter R. Wilson. LaTeX for standards: The LaTeX package files user manual. NIST Report NISTIR, June 1996.

Index

Numbers written in italic refer to the page where the corresponding entry is described, the ones underlined to the code line of the definition, the rest to the code lines where the entry is used.

Symbols

\@@endpbox . . . . . . . 335
\@@startpbox . . . . . . 334
\@@tablehead . . 214,

220, 345, 347, 389, 409, 431, 458

\@arraycr . 337, 338, 534

\@arrayparboxrestore

. . . . . . . . 139, 142, 217, 227, 264, 274, 286, 292

\@arstrutbox . . . . . .

…. 133, 144, 153 \@auxout . . . . . . . . . 507

\@calfirstpageht . .

. . . . . . . . \underline{169}, 351

\@calnextpageht 182,

197, 207, \underline{257}, 638 \@classix …. 329, 531

\@colroom . . . . 172,

187, 252, 259, 313 \@dblarg . . . . . . . . . 16 \@depth . . . . . . . . . . 134

\@endpbox . . . . . . . .

. 333, 340, 342, 537

\@finalstrut . . 144, 153

\@height . . . . . . . . . 134

                          \@ifnextchar 122, 376,

380, 391, 396, 411, 415, 433, 438

\@ifstar . . . . . . . . . 120

                          \@ifundefined . . . . . 38

\@mainaux . . . . . . . . 44

                          \@makecaption . . . 35, 55
                          \@mpfootins . . . . . . .

. 578, 579, 599, 600

                          \@mpsupertabular . .

. 411, 412, 415–417

                          \@namedef . . . . . . . .

. 390, 394, 399, 432, 436, 441, 544

                          \@nameuse . . . . 391,

392, 396, 397, 433, 434, 438, 439

\@oldcr 327, 482, 541, 546

                          \@parboxrestore . 32, 53
                          \@process@tablecaption

. . . . . . 19, 20, 326, 353, 479, 485

\@savcr . . 62, 65, 87, 90 \@spaces . . . . . . . . . 99

                                                   \@startpbox . . . . . . .

. 332, 339, 341, 536

                                                   \@supertabular 376,

377, 380, 381, \underline{382}

                                                   \@table@first@head .

. 67, 344, 347, 483

                                                   \@table@last@head .

. \underline{80}, 277, 666, 670

                                                   \@table@last@tail .

. . 92, 267, 460, 463, 484, 513, 516

                                                   \@tablehead . 60, 295,

345, 641, 667, 675

                                                   \@tabletail . . . . . . .

. . 85, 224, 230, 289, 461, 514, 628

                                                   \@tabularcr 330, 331, 532
                                                   \@topcaptionfalse . 12
                                                   \@topcaptiontrue . .

. . . . . . 10, 11, 480 \@width . . . . . . . . . . 134

                                                   \@xtablecaption . . . \underline{15}

A

                                                   \addcontentsline 28, 49
                                                   \arraystretch . . . . . 162

B

\baselineskip . . . . .

…. 162, 164, 271, 282, 300, 328

\baslineskp . . . . . . . 328
\bottomcaption . . . . \underline{10}

C

\c@PWSTtable . . . \underline{68},

357, 359, 361, 366, 508, 509, 661

\c@tracingst \underline{4}, 94, 95, 97
\columnwidth . . . . . .

…. 426, 451, 644 \csname . . 28, 30, 35,

49, 51, 55, 322– 325, 359, 406, 455, 465, 473, 474, 518, 528, 529, 548, 630, 651

D

\dp . . 133, 146, 155, 221, 231, 241, 268, 278, 290, 296

E

\endcsname 28, 30, 35,

49, 51, 55, 322– 325, 359, 406, 455, 465, 473, 474, 518, 528, 529, 548, 630, 651

\endminipage . . 519, 635
\endmpsupertabular . \underline{512}
\endmpsupertabular*  \underline{512}
\endmpxtabular . . . . \underline{512}
\endmpxtabular* . . . \underline{512}
\endsupertabular . . \underline{459}
\endsupertabular* . \underline{459}
\endtabular . . . . . . .

. 220, 230, 267, 277, 289, 295, 632

\endxtabular . . . . . . \underline{459}
\endxtabular* . . . . . \underline{459}
\estimate@lineht . .

. . . . . . . . \underline{161}, 350

F

\firstcallfalse . . . 612
\firstcalltrue . . . . 370
\floatlist . . . . . . . 46

G

\GenericWarning . . . 98

H

\ht 145, 154, 221, 231, 241, 268, 278, 290, 296, 579, 600

I

\if@filesw . . . . 44, 507
\if@firstcolumn . . . 177
\if@topcaption . . . .

. \underline{10}, 34, 36, 56, 239, 326, 353, 477

\if@twocolumn . . . . . 175
\iffirstcall \underline{76}, 493, 611

\ifST@mp . . . . . . \underline{22},

577, 598, 634, 643

\ifST@star . . . . . . .

. . \underline{21}, 465, 467, 518, 521, 629, 650

\iftabs . . . . . . . . \underline{38}, 43 \ifvoid . . . . . . 578, 599

\ignorespaces . . . . .

…. 30, 35, 51, 55

\immediate . . . . 44, 507
\infloatfalse . . . . . 488
\infloattrue . . . . . . 372
\inner@tabular 320, \underline{539}
\inner@tabular* . . . \underline{539}

L

\leftskip . . . . 423,

429, 448, 454, 647 \Lenv . . . . . . . . 470, 525

\listtablename . . . . 46

M

\MessageBreak . . . . . 173

\minipage . 426, 451, 644

\mpsupertabular . . . \underline{410}
\mpsupertabular* . . \underline{432}
\mpxtabular . . . . . . . \underline{410}
\mpxtabular* . . . . . . \underline{432}

N

\newbox . . . . . . . . . . 117 \newcount …. 4, 69–75 \newif . 10, 21, 22, 39, 76 \newskip . . . . . . . 24–26 \noalign 61, 65, 86, 90,

105, 107, 135, 137, 550, 575, 586, 592, 618, 627

\normalsize . . . . . 33, 54
\notablelasthead . . \underline{80}

O

                          \org@endpbox . . . . . .

…. 333, 340, 537

                          \org@startpbox . . . .

…. 332, 339, 536

                          \org@tabular . . 319,

388, 430, 543, 655

                          \org@tabularcr 63, 88,

330, 337, 532, 534

P

                          \PackageWarning . . .

. 379, 395, 414, 437 \pagetotal 171, 173, 620

                          \ProvidesPackage . . . 3

\PWST@ . . . . . . . . . . . 508

                          \PWST@generalht   \underline{77},

291, 297, 298, 311 \PWST@ht . . . . . . \underline{77},

268–270, 278, 279, 281, 290, 291, 296, 297, 299, 308, 311, 314

                          \PWST@lastht . . . \underline{77},

269, 279, 280, 308

                          \PWST@lastpagecr . .

. . . . . . . . 570, \underline{591}

                          \PWST@setfirstcall .

…. 594, 605, \underline{610}

                          \PWST@thecaption . .

. . . . . . \underline{13}, 18, 240

                          \PWSTcalchtlines . .

. . . . . . . . \underline{263}, 368

                          \PWSTcalnextpageht .

. . . . . . . . \underline{305}, 639

                          \PWSTcapht . . . . . . .

. . \underline{13}, 241, 242, 244, 246, 247, 253

                          \PWSTcurpage . . . \underline{68},

306, 367, 492, 495, 499, 504, 508, 509, 569, 660, 661, 663, 665

                          \PWSThead . . . . . \underline{68},

273, 301–303, 503 \PWSTinit …. 352, \underline{356}

                          \PWSTlasthead \underline{68}, 272,

273, 283–285, 494

                          \PWSTlastpage . . \underline{68},

362, 364, 366, 492, 569, 662, 663

                          \PWSTlines . . . . \underline{68},

270–272, 281– 283, 299–301, 369, 494, 498, 503, 566, 567, 613, 614, 658, 659

\PWSToplastpagenum .

. . . . . . . . 486, \underline{491}

\PWSTpenultimate  \underline{68}, 306
\PWSTsethead . . 642, \underline{657}
\PWSTtempc . . . . . . .

. \underline{68}, 358, 360, 364

R

\rectoisotitlehead .

. . . . . 40, 371, 487

\romannumeral . 359, 508

S

\setSTheight . . . . . . \underline{104}

\settabs . . . . . . . . . 45

\shrinkheight . . . . . \underline{104}
\ST@aendpbox . . \underline{143}, 342
\ST@argtabularcr . . \underline{118}
\ST@astartpbox   \underline{140}, 341
\ST@caption . . . . . 19, \underline{27}

\ST@cr 124, 135, 137, \underline{549}

\ST@dimen . . . . . . . .

. \underline{116}, 145–148, 150, 154–157, 159

\ST@endpbox . . . \underline{143}, 335
\ST@headht . . . \underline{108},

215, 221, 223, 236

\ST@leftskip  \underline{24}, 423,

429, 448, 454, 647

\ST@lineht . . . \underline{112},

162–164, 166, 233, 237, 551–554

\ST@mpfalse . . . 386, 404
\ST@mptrue . . . 421, 446
\ST@newpage 584, 623, \underline{626}

\ST@next 586, 590, 607,

641, 667, 670, 675

\ST@pageleft . . . . . .

. \underline{103}, 105, 107, 172, 174, 179– 181, 186, 187, 190, 195, 199, 205, 209, 213, 235, 249, 252, 253, 259, 261, 313, 314, 316, 553, 557–559, 563, 565, 572, 583, 593, 604, 620

\ST@pagesofar . \underline{110},

171, 179, 181, 186, 190, 191, 195, 199, 200, 205, 209, 210, 254, 260, 315, 621

\ST@parfillskip . . .

. . . . . \underline{24}, 424, 427, 449, 452, 645

\ST@pbox . . \underline{117}, 139, 142, 145, 146, 151, 154, 155, 160

\ST@pboxht . . . \underline{111},

147, 148, 156, 157, 551, 552, 556–558, 560, 561

\ST@prevht . . . \underline{112},

554, 560, 576, 597

\ST@restore . . . . . . .

. 218, 228, 265, 275, 287, 293, 476, \underline{530}, 540, 545

\ST@rightskip \underline{24}, 422,

428, 447, 453, 646

\ST@skipfirstpart .

. . . . . . . . 349, \underline{617}

\ST@skippage . . . . . .

. 349, 573, 623, 637

\ST@starfalse . 385, 420
\ST@startpbox . \underline{138}, 334
\ST@startrue . . 403, 445
\ST@stretchht . \underline{112},

164, 165, 167, 559

\ST@tableformat . . .

. 219, 229, 266, 276, 288, 294, 383, 388, 401, 408, 418, 430, 443, 457, 653, 655

\ST@tabularcr . . . . .

…. \underline{118}, 331, 338

\ST@tailht . . . \underline{108},

225, 231, 233, 234, 238, 575, 596

\ST@toadd . . . . \underline{115},

135, 137, 563, 564 \ST@trace \underline{96}, 166, 167,

170, 173, 176, 178, 183, 185, 194, 196, 204, 206, 213, 223, 234, 235, 246, 248, 250, 258, 261, 280, 285, 298, 303, 307, 310, 316, 361, 366, 384, 400, 419, 442, 467, 509, 521, 551, 556, 565, 567, 614, 619, 627, 640, 659, 661, 664, 668, 671, 676

\ST@wd . . . . . \underline{23}, 402,

407, 444, 456, 652

                   \ST@xargarraycr 128, \underline{132}
                   \ST@xtabularcr . . . . \underline{118}
                   \ST@yargarraycr 130, \underline{132}

\string …. 45, 46, 508

                   \sttraceoff . . . . . . . \underline{94}
                   \sttraceon . . . . . . . \underline{94}
                   \supertabular . . . . . \underline{375}
                   \supertabular* . . . . \underline{390}

T

                   \tablecaption 11, 12, \underline{15}
                   \tablefirsthead . . . \underline{59}
                   \tablehead . . . . . . . \underline{59}
                   \tablelasthead . . . . \underline{80}
                   \tablelasttail . . . . \underline{84}
                   \tabletail . . . . . . . \underline{84}

\tabstrue . . . . . . . . 43 \tabular . . . . . 219,

229, 266, 276, 288, 294, 319, 320

\thr@@ . . 7, 551, 556,

565, 567, 614, 659

                   \topcaption . . . . . . . \underline{10}

U \unskip . . . . . . . . . . 128 \unvbox . . . . . . . . . . 160

V \vbox . 217, 227, 240,

264, 274, 286, 292 \vrule . . . . . . . . . . . 134 \vtop . . . . . . . . 139, 142

W \write . . . . . . . . 44, 507

X

                   \x@endsupertabular .

…. 466, \underline{475}, 520

                   \x@supertabular  \underline{318},

387, 405, 425, 450 \xtabular . . . . . . . . \underline{375}

                   \xtabular* . . . . . . . \underline{390}