% File: tabularht.sty % Version: 2005/10/18 v2.1 % Author: Heiko Oberdiek % Email: % % Copyright: Copyright (C) 2005 Heiko Oberdiek. % % This work may be distributed and/or modified under % the conditions of the LaTeX Project Public License, % either version 1.3 of this license or (at your option) % any later version. The latest version of this license % is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions % of LaTeX version 2003/12/01 or later. % % This work has the LPPL maintenance status "maintained". % % This Current Maintainer of this work is Heiko Oberdiek. % % Function: This package defines some environments that adds % a height specification to tabular and array. % % Use: \usepackage{tabularht} % % The package provides the following environments % that extend the tabular/array environment by % a height specification as first argument: % * tabularht, tabularht* % * arrayht % * tabularxht, tabularxht* % (if package tabularx is loaded) % % The height argument allows a length specification, % package calc is supported if used. This means, % the tabular will have the specified height. % You can also use the prefixes "to=" and "spread=". % "to=" is the default, "spread=" means, the natural % height of the tabular box is changed by the length % after "spread=". % Examples: % \begin{tabularht}{1in} -> height is 1in % \begin{tabularht}{to=1in} -> height is 1in % \begin{tabularht}{spread=0pt} % -> natural height, same as \begin{tabular} % \begin{tabularht}{spread=1in} % -> natural height increased by 1in % % \interrowspace{...} % Adds space between table rows. It is essentially % the same as \noalign{\vspace{...}}. % \interrowfill % Short for \interrowspace{\fill} % \interrowstart ...\interrowstop % Marker commands, useful for option `vlines'. % % Option `vlines'. % % Vertical lines are interrupted, if space is inserted % in \noalign, \interrowspace, \addlinespace (booktabs), % between double \hlines. This option tries to detect % and add the vertical lines. The lines in a tabular % with tabularht support (environments of this package) % are numbered from left to right. The gap that is % controlled by \interrowspace or inbetween \interrowstart % and \interrowstop is then filled with the detected % vertical lines. % If only a limited selection of the lines should be % drawn, the commands know an optional argument with a % list of line numbers, e.g. % \begin{tabularht}{50mm}{|l|l|} % Hello & World\\ % \interrowfill[1,3] % Foo & Bar % \end{tabularht} % There are three lines, but the middle line is not drawn % in the gap between the first and second row. % Zero can be used to suppress all lines: % \interrowspace[0]{10mm} % The syntax of the commands with the optional argument % with the line number list . is a comma % separated list of numbers, means the % height specification described above with the optional % prefixes "to=" or "spread=". % \interrowspace[]{} % \interrowfill[] % \interrowstart[]...\interrowstop % % Option `vlines' is driver dependent and uses eTeX features. % * `pdftex': pdfTeX in PDF mode. % Here the positions of the lines are written with the % help of the \pdfsavepos feature into the .aux file(s). % Therefore you need two LaTeX runs to get the lines. % * `dvips': % Here, PostScript's currentpoint it used to get % the line positions. The lines are then drawn at the end % of the page. Thus one LaTeX/dvips run is sufficient % for this option. % * Other drivers: % * PostScript drivers: probably possible, an end of page % hook would be nice. % * VTeX: with GeX (PostScript interpreter) probably possible. % * dvipdfm: no idea. The big problem is, how to get the % current position? % % Hint: See also package `tabularkv', it provides an interface, % where most parameters for the environments can be given % by key-value pairs. % % Caution: At last a caution warning, the package, especially the % stuff of option `vlines' is experimental. % % Example 1: % \documentclass{article} % \usepackage{tabularht} % % \begin{document} % \fbox{% % \begin{tabularht*}{1in}{4in}{@{}l@{\extracolsep{\fill}}r@{}} % upper left corner & upper right corner\\% % \noalign{\vfill}% % \multicolumn{2}{@{}c@{}}{bounding box}\\ % \noalign{\vfill}% % lower left corner & lower right corner\\ % \end{tabularht*}% % } % \end{document} % % Example 2: % \documentclass{article} % \usepackage{booktabs} % \usepackage[dvips,vlines]{tabularht} % % \begin{document} % % \begin{tabularht}{spread=0pt}{|l|l|} % \hline % First&Line\\ % \hline % \interrowstart % \addlinespace[10mm] % \interrowstop % \hline % Second&Line\\ % \interrowstart % \hline % \hline % \interrowstop % Third&Line\\ % \hline % \interrowspace{10mm} % \hline % Fourth&Line\\ % \hline % \end{tabularht} % % \end{document} % % Limitations: % * Vertical lines are interrupted by \noalign{\vfill}. % % Compatibility: % * array, delarray, tabularx are supported. % * There can be problems with packages that % redefine \@array (or \@@array, \@tabarray) and % \@arrayrule (for option vlines). % * colortbl: it should at least work, but there isn't % support for filling the gaps with color, neither % the rules nor the backgrounds % % Installation: % CTAN location: CTAN:macros/latex/contrib/oberdiek/tabularht.sty % TDS location: TDS:tex/latex/oberdiek/tabularht.sty % % History: 2005/09/22 v1.0: % * first public version % 2005/10/16 v2.0: % * height specification allows % "to=..." or "spread=...", default is "to=". % * option vlines added, drivers pdftex and dvips % * \interrowspace, \interrowfil, and % \interrowstart ...\interrowstop added % 2005/10/18 v2.1: % * fix for package colortbl, but the colors % of colortbl remain unsupported. % \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{tabularht}% [2005/10/18 v2.1 Tabular with height specification] \let\@toarrayheight\@empty \let\tabH@array@init\@empty \toks@={% \begingroup \long\def\x#1\vcenter\fi\fi\bgroup#2\@sharp#3#4\@nil{% \endgroup \gdef\@array[##1]##2{% \tabH@array@init #1% \vcenter\fi\fi \@toarrayheight \bgroup \let\@toarrayheight\@empty #2\@sharp###3#4% }% }% \expandafter\x\@array[#1]{#2}\@nil } \edef\tabH@patch@array{\the\toks@} \def\tabH@patch@@array{% \ifx\@array\@@array \def\reserved@a{\let\@@array\@array}% \else \let\reserved@a\relax \fi \tabH@patch@array \reserved@a } \tabH@patch@@array \@ifpackageloaded{array}{}{% \AtBeginDocument{% \@ifpackageloaded{array}{% \tabH@patch@@array }{}% }% } \def\tabH@setheight#1{% \tracingmacros=1 \tabH@@setheight#1==\@nil } \def\tabH@@setheight#1=#2=#3\@nil{% \ifx\\#2#3\\% \setlength{\dimen@}{#1}% \edef\@toarrayheight{to\the\dimen@}% \else \edef\tabH@temp{\zap@space#1 \@empty}% \ifx\tabH@temp\tabH@to \else \ifx\tabH@temp\tabH@spread \else \PackageError{tabularht}{% Unknown height specifier % `\expandafter\strip@prefix\meaning\tabH@temp'% }{% The height dimension for tabular height can be prefixed% \MessageBreak with `to=' or `spread=', default is `to='.% }% \let\tabH@temp\tabH@to \fi \fi \setlength{\dimen@}{#2}% \edef\@toarrayheight{\tabH@temp\the\dimen@}% \fi } \def\tabH@to{to} \def\tabH@spread{spread} % First argument is the height of the table, % then the orignal arguments for tabular follow. \newenvironment{tabularht}[1]{% \tabH@setheight{#1}% \tabular }{% \endtabular } \newenvironment{tabularht*}[1]{% \tabH@setheight{#1}% \@nameuse{tabular*}% }{% \@nameuse{endtabular*}% } \newenvironment{tabularhtx}[1]{% \tabH@setheight{#1}% \tabularx }{% \endtabularx } \newenvironment{arrayht}[1]{% \tabH@setheight{#1}% \array }{% \endarray } \def\interrowspace{% \noalign\bgroup \tabH@interrowspace } \newcommand*{\tabH@interrowspace}[2][]{% \tabH@vspace{#1}{#2}% \egroup } \def\interrowfill{% \noalign\bgroup \tabH@interrowfill } \newcommand*{\tabH@interrowfill}[1][]{% \tabH@vspace{#1}{\fill}% \egroup } \def\tabH@vspace#1#2{% \tabH@vspace@start{#1}% \vspace{#2}% \tabH@vspace@stop } \let\tabH@vspace@start\@gobble \let\tabH@vspace@stop\@empty \newcommand*{\interrowstart}{% \noalign\bgroup \tabH@interrowstart } \newcommand*{\tabH@interrowstart}[1][]{% \tabH@vspace@start{#1}% \egroup } \newcommand*{\interrowstop}{% \noalign{\tabH@vspace@stop}% } %%% Options \providecommand*{\tabH@driver}{} \DeclareOption{vlines}{% \let\tabH@temp\relax } \DeclareOption{pdftex}{} \DeclareOption{dvips}{% \def\tabH@driver{dvips}% } \ProcessOptions*\relax \ifx\tabH@temp\relax \else \expandafter\endinput \fi \begingroup \@ifundefined{eTeXversion}{% \PackageError{tabularht}{% Option `vlines' requires eTeX% }{% Use of eTeX is recommended for LaTeX, see ltnews16.% }% \endgroup \endinput }{}% \endgroup %%% Option vlines, driver independent stuff \newcounter{tabH@unique} \setcounter{tabH@unique}{0} \let\tabH@currenttab\@empty \def\tabH@array@init{% \ifx\@toarrayheight\@empty % ignore vertical lines of nested tabular environments \let\tabH@currenttab\@empty \else \stepcounter{tabH@unique}% \edef\tabH@currenttab{\the\c@tabH@unique}% \fi } \renewcommand*{\@arrayrule}{% \@addtopreamble{% \hskip -.5\arrayrulewidth \ifx\tabH@currenttab\@empty \else \tabH@vrule{\tabH@currenttab}% \fi \begingroup \csname CT@arc@\endcsname\vline \endgroup \hskip -.5\arrayrulewidth }% } \let\tabH@arrayrule\@arrayrule \AtBeginDocument{% \@ifpackageloaded{colortbl}{% \let\@arrayrule\tabH@arrayrule }{}% } \let\tabH@vrule\@gobble %%% Driver pdftex \RequirePackage{ifpdf} \ifpdf \begingroup \@ifundefined{pdfsavepos}{% \PackageError{tabularht}{% Your pdfTeX is too old% }{% \string\pdfsavepos\space is missing.% }% \endgroup \csname fi\endcsname \endinput }{}% \let\on@line\@empty \PackageInfo{tabularht}{% Using driver `pdftex' because of pdfTeX in PDF mode% }% \endgroup \protected\def\tabH@vrule#1{% \if@filesw \pdfsavepos \protected@write\@auxout{% \let\tabH@lastxpos\relax }{% \tabH@aux@vrule{#1}{\tabH@lastxpos}% }% \fi } \def\tabH@lastxpos{\the\pdflastxpos} \def\tabH@lastypos{\the\pdflastypos} % The .aux file contains three commands: % \tabH@aux@vrule{tabular id}{x position} % \tabH@aux@vstart{tabular id}{row id}{x position}{y position} % \tabH@aux@vstop{y position} % \AtBeginDocument{% % The .aux files are read the first time before % \AtBeginDocument and later at \end{document}. % \tabH@aux@done is a marker to distinguish % between these two readings. Only in the first % case we need the \tabH@aux@... commands. \let\tabH@aux@done\@empty \if@filesw \immediate\write\@mainaux{% \@percentchar\@percentchar BeginProlog: tabularht }% % items in the aux file are executed, % if tabularht is loaded % and during the aux file read at \begin{document} only \immediate\write\@mainaux{% \detokenize{% % the \tabH@aux@... commands are needed only if % tabularht is loaded with driver pdftex. \@ifundefined{tabH@aux@vrule}\@secondoftwo\@firstofone {% % disable commands except for the first .aux files reading \@ifundefined{tabH@aux@done}\@gobble\@firstofone }% {% \let\tabH@aux@vrule\@gobbletwo \let\tabH@aux@vstart\@gobblefour \let\tabH@aux@vstop\@gobble }% }% }% \immediate\write\@mainaux{% \@percentchar\@percentchar EndProlog: tabularht }% \fi } % the x positions of vrules are stored in % \tabH@list with distinct values \protected\def\tabH@aux@vrule#1#2{% \@ifundefined{tabH@#1list}{% \expandafter\xdef\csname tabH@#1list\endcsname{% \noexpand\do{#2}% }% }{% \begingroup \def\x{#2}% \let\y\@undefined \let\do\tabH@do@add \expandafter\xdef\csname tabH@#1list\endcsname{% \csname tabH@#1list\endcsname\@empty \ifx\y\@undefined \noexpand\do{\x}% \fi }% \endgroup }% } \def\tabH@do@add#1{% \ifx\y\@undefined \ifnum#1<\x\space \else \expandafter\ifx\csname y\endcsname\relax\fi \ifnum#1>\x\space \noexpand\do{\x}% \fi \fi \fi \noexpand\do{#1}% } \def\tabH@vspace@start#1{% \if@filesw \stepcounter{tabH@unique}% \edef\tabH@currentrow{\the\c@tabH@unique}% \pdfsavepos \protected@write\@auxout{% \let\tabH@lastxpos\relax \let\tabH@lastypos\relax }{% \tabH@aux@vstart{\tabH@currenttab}{\tabH@currentrow}% {\tabH@lastxpos}{\tabH@lastypos}% }% \fi \begingroup \edef\a{tabH@\tabH@currenttab row\tabH@currentrow}% \expandafter\let\expandafter\x\csname\a x\endcsname \ifx\x\relax \else \expandafter\let\expandafter\y\csname\a y\endcsname \expandafter\let\expandafter\l \csname tabH@\tabH@currenttab list\endcsname \ifx\l\relax \else \def\f{#1}% \ifx\f\@empty \let\do\tabH@do@set \else \count@=\z@ \let\do\tabH@do@filter \fi \setbox\z@=\hbox{\l}% \wd\z@=\z@ \dp\z@=\z@ \copy\z@ \fi \fi \endgroup }% \def\tabH@vspace@stop{% \if@filesw \pdfsavepos \protected@write\@auxout{% \let\tabH@lastypos\relax }{% \tabH@aux@vstop{\tabH@lastypos}% }% \fi } \def\tabH@do@set#1{% \hbox to \z@{% \hskip \dimexpr #1sp - \x sp\relax \vrule \@width\arrayrulewidth \@depth\dimexpr \y sp\relax \hss }% } \def\tabH@do@filter{% \@tempswafalse \advance\count@\@ne \@for\e:=\f\do{% \ifnum\e=\count@ \@tempswatrue \fi }% \if@tempswa \expandafter\tabH@do@set \else \expandafter\@gobble \fi } \protected\def\tabH@aux@vstart#1#2#3#4{% \def\tabH@current@vstart{{#1}{#2}{#3}{#4}}% } \protected\def\tabH@aux@vstop{% \expandafter\tabH@aux@v\tabH@current@vstart } \def\tabH@aux@v#1#2#3#4#5{% \expandafter\gdef\csname tabH@#1row#2x\endcsname{#3}% \expandafter\xdef\csname tabH@#1row#2y\endcsname{% \the\numexpr #4 - #5\relax }% } \csname fi\endcsname \endinput \fi %%% DVI drivers \ifx\tabH@driver\@empty \PackageError{tabularht}{% Missing DVI driver, option `vlines' disabled% }{% Supported DVI drivers: dvips.% }% \expandafter\endinput \fi \def\tabH@driver@dvips{% \def\tabH@literalps##1{\special{ps:SDict begin ##1 end}}% \def\tabH@headerps##1{\special{! ##1}}% } \@onelevel@sanitize\tabH@driver \@ifundefined{tabH@driver@\tabH@driver}{% \PackageError{tabularht}{% Unsupported driver `\tabH@driver'% }{% Supported DVI drivers: dvips.% }% \endinput }{} \begingroup \let\on@line\@empty \PackageInfo{tabularht}{% Using driver `\tabH@driver'% }% \endgroup \csname tabH@driver@\tabH@driver\endcsname \protected\def\tabH@vrule#1#2\vrule#3\arrayrulewidth{% #2% \fi or empty % hack to get rid of maxdrift rounding of dvips, % thus simulate a large motion \kern1in\relax \tabH@literalps{% #1 tabH.vrule Resolution neg 0 translate% }% \vrule#3\arrayrulewidth \tabH@literalps{Resolution 0 translate}% \kern-1in\relax } \def\tabH@vspace@start#1{% \begingroup \let\y\@empty \@for\x:=#1\do{% \ifx\y\@empty \edef\y{\x}% \else \edef\y{\y\space\x}% \fi }% \tabH@literalps{\tabH@currenttab[\y]currentpoint exch pop}% \endgroup } \def\tabH@vspace@stop{% \tabH@literalps{% currentpoint exch pop % \number\dimexpr\arrayrulewidth\relax\space tabH.vspace% }% } \tabH@headerps{% userdict begin /tabH.list 10 dict def /tabH.job [] def end% /tabH.vrule{% 10 string cvs cvn dup tabH.list exch known{% tabH.list exch dup [ exch tabH.list exch get currentpoint pop round exch true exch{% % tabH.list key [ ... x true i % tabH.list key [ ... false i exch{% % ... [ ... x i 2 copy lt{false}{% 2 copy eq{pop false}{exch true}ifelse% }ifelse }{false}ifelse }forall pop% ]put% }{% tabH.list exch[currentpoint pop round]put }ifelse }bind def % /tabH.vspace{% userdict begin 10 dict dup begin exch 65536 div Resolution mul 72.27 div % dvips uses a poor man's ceil function % see dopage.c before "drawrule": (int)(... + 0.9999999) 0.9999999 add truncate% /rulewidth exch def exch/ybottom exch def exch/ytop exch def exch/cols exch def exch/tabkey exch 10 string cvs cvn def end /tabH.job exch[exch userdict/tabH.job get aload pop]def end% }bind def % Now we do the work at the end of the page. % Unhappily "eop-hook" cannot be used, because "eop" % executes "restore" before, so that all data are lost. TeXDict begin% /eop% [% {% tabH.job{% begin% /colarray tabH.list tabkey known{tabH.list tabkey get}{[]}ifelse def cols length 0 eq not{% /colarray[% cols{1 sub dup 0 lt{pop}{% dup colarray length ge{pop}{% colarray exch get% }ifelse% }ifelse% }forall% ]def% }if colarray{% % (rulewidth) == rulewidth == % debug Resolution sub ytop rulewidth ytop ybottom sub v }forall end }forall % tabH.list{== ==}forall % debug }bind aload pop TeXDict /eop get aload pop ]cvx def end% } \endinput