/pkg/vignettes/threeparttable.sty

https://code.google.com/ · TeX · 381 lines · 213 code · 48 blank · 120 comment · 3 complexity · b1f6939603eb591618cae0d45a28d460 MD5 · raw file

  1. % threeparttable.sty (or 3parttable) (or 3parttab on DOS)
  2. % by Donald Arseneau Updated on June 13, 2003.
  3. % Three part tables: title, tabular environment, notes
  4. %
  5. % This file may be distributed, modified, and used in other works with just
  6. % one restriction: modified versions must clearly indicate the modification
  7. % (a name change, or a displayed message, or ?).
  8. %
  9. % This package facilitates tables with titles (captions) and notes. The
  10. % title and notes are given a width equal to the body of the table (a
  11. % tabular environment). By itself, a threeparttable does not float, but
  12. % you can put it in a {table} or a {table*} or some other environment.
  13. % (This causes extra typing, but gives more flexibility.)
  14. %
  15. % Inside a threeparttable there should be a caption, followed by a tabular
  16. % environment (tabular, tabular* or tabularx), possibly followed by a series
  17. % of itemized "tablenotes". The caption can also go after the tabular.
  18. %
  19. % \begin{table}
  20. % \begin{threeparttable}[b]
  21. % \caption{...}
  22. % \begin{tabular}...% or {tabular*}
  23. % ...42\tnote{1}&....
  24. % ...
  25. % \end{tabular}
  26. % \begin{tablenotes}
  27. % \item [1] the first note
  28. % ...
  29. % \end{tablenotes}
  30. % \end{threeparttable}
  31. % \end{table}
  32. %
  33. % The {threeparttable} environment takes an optional vertical-placement
  34. % parameter, [t], [b], or [c]; the default is [t].
  35. %
  36. % At present, there is nothing automatic about the notes; you must specify the
  37. % identifier in the body of the table ("\tnote{a}") and in the notes below
  38. % ("\item[a]..."). I chose this method because automatic numbering with
  39. % \footnote would be very hard to use, particularly because many tables make
  40. % repeated reference to a single note. If someone has a convenient, elegant,
  41. % automatic system, I'll listen! \tnote commands can be given in the caption
  42. % too, and they will *NOT* appear in the list of tables.
  43. %
  44. % There are several commands which should be redefined for customizing the
  45. % behavior of threeparttable, especially the table notes. Some options
  46. % are provided for common variations of the table notes.
  47. %
  48. % Options:
  49. % [para] Notes come one-after-another without line breaks
  50. % [flushleft] No hanging indentation on notes
  51. % [online] \item tag is printed normal size, not superscript
  52. % [normal] restores default formatting
  53. %
  54. % These options can be given to the \usepackage command or to each individual
  55. % {tablenotes} environment. The [normal] option is intended to reverse the
  56. % whole-document options for a particular table; e.g.
  57. %
  58. % \usepackage[para]{threeparttable}
  59. % ... much document ...
  60. % \begin{tablenotes}[normal,flushleft]
  61. %
  62. % These few options are unlikely to give you a desired specified format,
  63. % so you should expect to redefine one or more of the configuration
  64. % commands. Note that mixing options with redefinitions is unlikely
  65. % to work smoothly. Please submit your redefinitions to be used as
  66. % options in future versions!
  67. %
  68. % Configuration commands:
  69. % \TPTminimum: command telling minimum caption width. Default "4em";
  70. % change with \def or \renewcommnd.
  71. % \TPTrlap: A command with one argument, to make notes go out of
  72. % the column, into the column separation (for right-aligning)
  73. % \TPTtagStyle: Command with one argument to set appearance of the tag
  74. % (number) in \tnote{tag}. It defaults to nil. It could be \textit.
  75. % \tnote: Yes, you can redefine the \tnote command.
  76. % \TPTnoteLabel: Command with one argument to format the item label in
  77. % the tablenotes list (\makelabel); default uses \tnote.
  78. % \TPTnoteSettings: A command to issue all the list-environment setup
  79. % commands for the tablenotes.
  80. % \tablenotes or \TPTdoTablenotes: Yes, you can redefine the whole
  81. % tablenotes environment. (\tablenotes processes optional
  82. % parameters, then invokes \TPTdoTablenotes; the [para] option
  83. % replaces \TPTdoTablenotes.)
  84. %
  85. % For figures, there is an equivalent "measuredfigure" environment. It
  86. % is fairly fragile though, and should be used only for a single graphic
  87. % above a single caption.
  88. %
  89. % Note that the \caption formatting is *not* adjusted by threeparttable.
  90. % You should use one of the caption-control packages to get captions
  91. % that work well as table titles. In truth, threeparttable sets
  92. % \abovecaptionskip to zero for captions above the table, but more
  93. % complete changes are called for.
  94. \ProvidesPackage{threeparttable}[2003/06/13 \space v 3.0]
  95. \edef\TPTminimum % make a scratch macro for restoring catcodes
  96. {\catcode\string `\string @=\the\catcode\string`\@
  97. \catcode\string `\string :=\the\catcode\string`\:
  98. \catcode\string `\string *=\the\catcode\string`\*}
  99. \catcode`\@=11
  100. \catcode`\:=12
  101. \catcode`\*=11
  102. \@ifundefined{@tempboxb}{\@nameuse{newbox}\@tempboxb}{}
  103. \newenvironment{threeparttable}[1][t]{%
  104. \relax \ifvmode \noindent \fi
  105. \TPT@common{threeparttable}{#1}%
  106. \@ifundefined{@captype}{\def\@captype{table}}{}%
  107. \let\TPT@LA@label\label
  108. \let\TPT@LA@caption\@caption \let\@caption\TPT@caption
  109. \let\TPT@begintabhook\TPT@begintabbox
  110. \let\TPT@tabarghook\TPT@tabargset
  111. \TPT@hookin{tabular}%
  112. \TPT@hookarg{tabular*}%
  113. \TPT@hookarg{tabularx}%
  114. \let\TPToverlap\relax}%
  115. {\TPT@close}
  116. \newenvironment{measuredfigure}[1][t]{%
  117. \relax \ifvmode \noindent \fi
  118. \TPT@common{measuredfigure}{#1}%
  119. \let\TPT@figfix\TPT@close % Provide closure if no caption
  120. \@ifundefined{@captype}{\def\@captype{figure}}{}%
  121. \let\TPT@LA@caption\@caption \let\@caption\TPT@gr@caption
  122. \setbox\@tempboxb\hbox\bgroup
  123. \aftergroup\TPT@measurement
  124. \color@begingroup\spacefactor994\ignorespaces}
  125. {\TPT@close \TPT@figfix}
  126. \def\TPT@close{\ifhmode \unskip \fi \color@endgroup \egroup}
  127. \def\TPT@figfix{}
  128. % Caption for figures:
  129. \def\TPT@gr@caption#1[#2]#3{\relax
  130. \ifnum\spacefactor=994\relax % Caption listed first; hold on to it
  131. \abovecaptionskip\z@skip
  132. \let\TPT@hsize\@empty % double sure
  133. \else % Have something to measure, and caption below
  134. \TPT@close % close hbox. Measurement happens here automatically
  135. \fi
  136. \TPT@caption{#1}[{#2}]{#3}%
  137. }
  138. % "begin" code common for tables and figures
  139. \def\TPT@common#1#2{%
  140. \ifx\TPT@LA@caption\relax\else
  141. \PackageError{threeparttable}%
  142. {Illegal nested #1 environments}%
  143. {Maybe you have a missing \string\end{#1}?^^J%
  144. This cannot work, so type \string"x\string" and fix the problem now.}%
  145. \fi
  146. \let\TPT@docapt\@undefined
  147. \if b#2\relax\vbox\bgroup\else
  148. \if c#2\relax$\vcenter\bgroup\aftergroup$\else
  149. \vtop\bgroup \fi\fi
  150. \parindent\z@
  151. \color@begingroup
  152. \def\TPT@sethsize{\TPT@hsize\par}%
  153. \topsep\z@
  154. \@enumdepth\z@
  155. \global\let\TPT@hsize\@empty
  156. }
  157. % "hookin" hooks into tabular to set the alignment in a box
  158. % and measure the box.
  159. % For tabular* and tabularx, we can simply use the supplied "width"
  160. % argument (using \TPT@hookarg), but for ordinary tabular environments
  161. % we need to measure the typeset tabular body, using hooks in both the
  162. % begin and the end code (using \TPT@hookin). The hook-in is defined
  163. % generically so it is easy to add new supported environments.
  164. %
  165. % I will add \TPT@begintabhook and \TPT@endtabhook to \tabular and
  166. % \endtabular. These will do the measurement at the outer level,
  167. % but will be no-ops inside.
  168. \def\TPT@unhook{%
  169. \let\TPT@begintabhook\bgroup
  170. \let\TPT@tabarghook\@gobble
  171. }
  172. \let\TPT@endtabhook\egroup
  173. % This is simple -- Hook into tabular types that are given explicit width
  174. \def\TPT@hookarg#1{% #1 = width
  175. \expandafter\let\csname TPTsav@#1\expandafter\endcsname\csname #1\endcsname
  176. \expandafter\edef\csname #1\endcsname##1{\noexpand\TPT@tabarghook{##1}%
  177. \expandafter\noexpand\csname TPTsav@#1\endcsname{\hsize}}%
  178. }
  179. \def\TPT@tabargset#1{% Alias \TPT@tabarghook
  180. \TPT@unhook
  181. \setlength\hsize{#1}%
  182. \xdef\TPT@hsize{\hsize\the\hsize \parindent 1em \noexpand\@parboxrestore}%
  183. \TPT@hsize
  184. \ifx\TPT@docapt\@undefined\else \TPT@docapt \vskip.2\baselineskip \fi
  185. \par \aftergroup\TPT@sethsize
  186. }
  187. % Harder -- Hook into tabular/endtabular to measure the width
  188. \def\TPT@hookin#1{%
  189. \expandafter\let\csname TPTsav@#1\expandafter\endcsname\csname #1\endcsname
  190. \expandafter\let\csname TPTsav@end#1\expandafter\endcsname\csname end#1\endcsname
  191. \expandafter\edef\csname #1\endcsname{\noexpand\TPT@begintabhook
  192. \expandafter\noexpand\csname TPTsav@#1\endcsname}%
  193. \expandafter\edef\csname end#1\endcsname{%
  194. \expandafter\noexpand\csname TPTsav@end#1\endcsname \TPT@endtabhook}%
  195. }
  196. \def\TPT@begintabbox{% alias \TPT@begintabhook
  197. \begingroup
  198. \TPT@unhook
  199. \setbox\@tempboxb\hbox\bgroup \aftergroup\TPT@endtabbox
  200. \let\TPToverlap\TPTrlap % Just \rlap now, but could be smarter
  201. }
  202. \def\TPT@endtabbox{% Inserted after ending \@tempboxb
  203. \TPT@measurement
  204. \endgroup
  205. \TPT@hsize \aftergroup\TPT@sethsize
  206. \@ignoretrue
  207. }
  208. \def\TPT@measurement{%
  209. \ifdim\wd\@tempboxb<\TPTminimum
  210. \hsize \TPTminimum
  211. \else
  212. \hsize\wd\@tempboxb
  213. \fi
  214. \xdef\TPT@hsize{\hsize\the\hsize \noexpand\@parboxrestore}\TPT@hsize
  215. \ifx\TPT@docapt\@undefined\else
  216. \TPT@docapt \vskip.2\baselineskip
  217. \fi \par \box\@tempboxb
  218. \ifvmode \prevdepth\z@ \fi
  219. }
  220. \gdef\TPT@hsize{}
  221. \def\TPT@sethsize{}% Used with \aftergroup, so do this to cover for when a
  222. % \TPT@sethsize escapes from threeparttable.
  223. % Collecting caption for tables:
  224. \def\TPT@caption#1[#2]#3{\gdef\TPT@docapt
  225. {\par\global\let\TPT@docapt\@undefined \TPT@LA@caption{#1}[{#2}]%
  226. {\strut\ignorespaces#3\ifhmode\unskip\@finalstrut\strutbox\fi}}%
  227. \ifx\TPT@hsize\@empty \let\label\TPT@gatherlabel \abovecaptionskip\z@skip
  228. \else \TPT@docapt \fi \ignorespaces}
  229. \let\TPT@LA@caption\relax
  230. % Must also collect any \label that appears after a collected \caption
  231. \def\TPT@gatherlabel#1{%
  232. \ifx\TPT@docapt\@undefined \TPT@LA@label{#1}\else
  233. \g@addto@macro\TPT@docapt{\label{#1}}\fi
  234. }
  235. \def\tablenotes{\TPT@defaults
  236. \@ifnextchar[\TPT@setuptnotes\TPTdoTablenotes} % ]
  237. \let\endtablenotes\endlist
  238. \def\TPT@setuptnotes [#1]{% process formatting options
  239. \@for\@tempa:=#1\do{\@nameuse{TPT@opt@\romannumeral-`a\@tempa}}%
  240. \TPTdoTablenotes
  241. }
  242. \def\TPTdoTablenotes{%
  243. \par \prevdepth\z@ \TPT@hsize
  244. \list{}{\topsep\z@skip \partopsep\z@skip
  245. \itemsep\z@ \parsep\z@ \itemindent\z@
  246. \TPTnoteSettings
  247. \let\makelabel\TPTnoteLabel
  248. }}
  249. % \TPToverlap is a hook, to be used in \tnote, for making the note tag
  250. % hang over the right-edge of the column. It takes different meanings
  251. % at different places, and it should disappear, like this, outside of
  252. % a threeparttable environment.
  253. %
  254. \def\TPToverlap#1{} % notes in caption will disappear in list of tables!
  255. % \TPTrlap is the meaning of \TPToverlap within the tabular environment.
  256. % I could do some fancy definition so that it only acts at the right-edge
  257. % of a column, but it is left simple for compatibility and sanity.
  258. \let\TPTrlap\rlap
  259. \def\tnote#1{\protect\TPToverlap{\textsuperscript{\TPTtagStyle{#1}}}}%
  260. \def\TPTtagStyle#1{#1}
  261. \def\TPTnoteSettings{%
  262. \setlength\leftmargin{1.5em}%
  263. \setlength\labelwidth{.5em}%
  264. \setlength\labelsep{.2em}%
  265. \rightskip\tabcolsep \leftskip\tabcolsep
  266. }
  267. \def\TPTnoteLabel#1{\tnote{#1}\hfil}
  268. % Package and tablenotes options
  269. \def\TPT@opt@normal{\gdef\TPT@defaults{}}
  270. \TPT@opt@normal
  271. \DeclareOption{normal}{}
  272. \def\TPT@opt@online{%
  273. \def\TPTnoteSettings{\leftmargin1.5em \labelwidth1em \labelsep.5em\relax}%
  274. \def\TPTnoteLabel##1{\TPTtagStyle{##1}\hfil}%
  275. }
  276. \DeclareOption{online}{\g@addto@macro\TPT@defaults{\TPT@opt@online}}
  277. \def\TPT@opt@flushleft{%
  278. \def\TPTnoteSettings{\labelsep.2em \leftmargin\z@ \labelwidth\z@}%
  279. \def\TPTnoteLabel##1{\hspace\labelsep\tnote{##1}\hfil}%
  280. \rightskip\z@skip \leftskip\z@skip
  281. }
  282. \DeclareOption{flushleft}{\g@addto@macro\TPT@defaults{\TPT@opt@flushleft}}
  283. \def\TPT@opt@para{\let\TPTdoTablenotes\TPT@doparanotes}
  284. \def\TPT@doparanotes{\par
  285. \prevdepth\z@ \TPT@hsize
  286. \TPTnoteSettings
  287. \parindent\z@ \pretolerance 8
  288. \linepenalty 200
  289. \renewcommand\item[1][]{\relax\ifhmode \begingroup
  290. \unskip
  291. \advance\hsize 10em % \hsize is scratch register, based on real hsize
  292. \penalty -45 \hskip\z@\@plus\hsize \penalty-19
  293. \hskip .15\hsize \penalty 9999 \hskip-.15\hsize
  294. \hskip .01\hsize\@plus-\hsize\@minus.01\hsize
  295. \hskip 1em\@plus .3em
  296. \endgroup\fi
  297. \tnote{##1}\,\ignorespaces}%
  298. \let\TPToverlap\relax
  299. \def\endtablenotes{\par}%
  300. }
  301. \DeclareOption{para}{\g@addto@macro\TPT@defaults{\TPT@opt@para}}
  302. \ProcessOptions
  303. \TPTminimum % restore catcode of @, : and * to starting value
  304. \def\TPTminimum{4em}
  305. \endinput
  306. Example:
  307. Here is some paragraph before the table. Note that this table does not
  308. float because it is not in a {table} or {table*} environment.
  309. \begin{center}
  310. \begin{threeparttable}
  311. \caption{The Skewing Angles ($\beta$) for $\fam0 Mu(H)+X_2$ and
  312. $\fam0 Mu(H)+HX$~\tnote{a}}
  313. \begin{tabular}{rlcc}
  314. \hline
  315. & & $\fam0 H(Mu)+F_2$ & $\fam0 H(Mu)+Cl_2$ \\
  316. \hline
  317. &$\beta$(H) & $80.9^\circ\tnote{b}$ & $83.2^\circ$ \\
  318. &$\beta$(Mu) & $86.7^\circ$ & $87.7^\circ$ \\
  319. \hline
  320. \end{tabular}
  321. \begin{tablenotes}
  322. \item[a] for the abstraction reaction, $\fam0 Mu+HX \rightarrow MuH+X$.
  323. \item[b] 1 degree${} = \pi/180$ radians.
  324. \end{tablenotes}
  325. \end{threeparttable}
  326. \end{center}
  327. Notes:
  328. May 15, 2001: changed hook-in to use \setbox in a wrapper macro (or
  329. explicit width of tabular*). I don't remember why I used \everyhbox
  330. and \lastbox before. Something may break now. At least it works with
  331. tabularx.
  332. June 13, 2003: Re-wrote a lot, particularly the hook mechanism. Use macros
  333. and package/environment options for formatting control. Add measuredfigure.