diff options
author | Karl Berry <karl@freefriends.org> | 2010-10-08 22:55:52 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2010-10-08 22:55:52 +0000 |
commit | 0defb3a486d0ea4acc281201f2fe3dfb1fe58677 (patch) | |
tree | b131bfc838dce3c5248b8cafc79728ca2ea348ee /Master/texmf-dist/source/latex/cals/rowsep.dtx | |
parent | 642d21e6f53417257b6ff173b9216d3862139fe1 (diff) |
new latex pkg cals (8oct01)
git-svn-id: svn://tug.org/texlive/trunk@20025 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/cals/rowsep.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/cals/rowsep.dtx | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/cals/rowsep.dtx b/Master/texmf-dist/source/latex/cals/rowsep.dtx new file mode 100644 index 00000000000..c3c0174c2d2 --- /dev/null +++ b/Master/texmf-dist/source/latex/cals/rowsep.dtx @@ -0,0 +1,360 @@ +% \subsection{Row separation (rowsep)} + +% \subsubsection{Data presentation} + +% A horizontal line between table rows can't appear in the output +% immediately. Its formatting should be postponed until the next +% row and its context are known. Two basic cases: +% \begin{itemize} +% \item The default cell formatting is to have a border around cells. +% For some cell \textit{A} in the middle of a table, the user has +% overridden formatting to no borders. To imlement the user's wish, +% we should not create the bottom border for the cell \textit{B} +% which is above the \textit{A}. But we don't know about the wish +% for \textit{A} while processing \textit{B}. Therefore, the border +% between two rows can be established only after processing the +% both rows. +% \item The default cell border is 1pt, but a border between +% a body and a header or a footer row is 2pt. It means that the +% border between two rows should be created only after we sure +% that there is no table break. +% \end{itemize} +% Our approach is to define the desired formatting of a rowsep +% as a set of parameters in a token list. Later we can join two +% rowseps or a rowsep and context to a final rowsep. +% +% A rowsep token list consist of several items, each +% item is a list of tokens or token groups: +% \begin{enumerate} +% \item length +% \item left-border +% \item right-border +% \item user-specified thickness +% \end{enumerate} +% Values \textit{left-border} and \textit{right-border} are +% required to get a nice rectangle border around a cell. Without length +% correction, using the cell dimension, the border could look like: +% \begin{verbatim} +% xxxxxxxx +% xxx cell xxx +% xxxxxxxx +% \end{verbatim} +% With length correction, we get the correct result: +% \begin{verbatim} +% xxxxxxxxxxxx +% xxx cell xxx +% xxxxxxxxxxxx +% \end{verbatim} +% +% Here is an example of a rowsep specification. It consist of three items. +% The first item: length is 5cm, width 2pt, borders are 2mm. +% The second item: length is 9cm, borders are 2mm, no rule at all. +% The third item: length 2cm, default width, borders are 2pt. +% The token list for this specification: +% \begin{verbatim} +% { {5cm} {2mm} {2mm} {2pt} } +% { {9cm} {2mm} {2mm} {0pt} } +% { {2cm} {2pt} {2pt} \relax } +% \end{verbatim} +% +% Cell length and the left and right borders should be the correct lengths, +% the rule thickness can be |\relax|, in this case the actual thickness +% will be calculated during output. +% +% \begin{macro}{\cals@rs@pack} +% Construct a rowsep fragment from the arguments 2-5 and +% put it to the macro 1. +% \begin{macrocode} +\newcommand\cals@rs@pack[5]{% +\edef#1{\noexpand{#2\noexpand}\noexpand{#3\noexpand}\noexpand{#4\noexpand}% + \ifx \relax#5\relax \else \noexpand{#5\noexpand}\fi }} +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\cals@rs@unpack} +% The reverse for |\cals@rs@pack|. The first argument is a rowsep +% fragment (without enclosing curly braces), arguments 2-5 is macro +% names where to put the results. +% \begin{macrocode} +\newcommand\cals@rs@unpack[5]{% +\def\cals@tmp##1##2##3##4{\edef#2{##1}\edef#3{##2}\edef#4{##3}% + \ifx\relax##4\let#5=\relax \else \edef#5{##4}\fi}% +\expandafter\cals@tmp#1} +% \end{macrocode} +% \end{macro} + +% +% ^^A ----------------------------------------------------- +% +% \subsubsection{From individual decorations to rowsep specification} + +% The rowsep specifications are created cell-by-cell and stored +% in the macros |\cals@current@rs@above| and |\cals@current@rs@below|. +% The construction happens with delay because we don't know +% the exact value of the right border until the next cell is processed. + +% \begin{macro}{\cals@rs@spec@begin} +% Initializes |\cals@current@rs@above|, |\cals@current@rs@below| +% and set the flag of a new row. +% \begin{macrocode} +\newcommand\cals@rs@spec@begin{% +\def\cals@current@rs@above{}% +\def\cals@current@rs@below{}% +\let\cals@rs@spec@ll=\relax} +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\cals@rs@spec@next} +% \begin{macro}{\cals@rs@spec@nextII} +% Finalizes the decorations for the previous cell by using the left border +% of the current as the right border for the previous. Then +% remembers the decorations of the current cell --- +% the left border width, +% the widths of the top and bottom borders (|\relax| is ok) --- +% in the macros |\cals@rs@spec@ll|, |...@bl|, |...@bt|, |...@bb|. +% All the arguments much be macros. +% \begin{macrocode} +\newcommand\cals@rs@spec@next[4]{ +\cals@rs@spec@nextII#2 +\let\cals@rs@spec@ll=#1% +\let\cals@rs@spec@bl=#2% +\let\cals@rs@spec@bt=#3% +\let\cals@rs@spec@bb=#4% +} + +\newcommand\cals@rs@spec@nextII[1]{% +\ifx \relax\cals@rs@spec@ll \else + \cals@rs@pack\cals@tmp\cals@rs@spec@ll\cals@rs@spec@bl#1\cals@rs@spec@bt + \llt@snoc\cals@current@rs@above\cals@tmp + \cals@rs@pack\cals@tmp\cals@rs@spec@ll\cals@rs@spec@bl#1\cals@rs@spec@bb + \llt@snoc\cals@current@rs@below\cals@tmp +\fi +} +% \end{macrocode} +% \end{macro} +% \end{macro} + +% \begin{macro}{\cals@rs@spec@end} +% Finishes the rowsep specification by putting the last cell to it. +% The only implicit argument (|\cals@lastLeftWidth|) is the width +% of the right border of the last cell. +% \begin{macrocode} +\newcommand\cals@rs@spec@end[1]{} +\let\cals@rs@spec@end=\cals@rs@spec@nextII +% \end{macrocode} +% \end{macro} + +% +% ^^A ----------------------------------------------------- +% +% \subsubsection{``Waiting'' rowsep} +% +% \begin{macro}{\cals@rs@sofar@length} +% \begin{macro}{\cals@rs@sofar@borderl} +% \begin{macro}{\cals@rs@sofar@borderr} +% \begin{macro}{\cals@rs@sofar@width} +% Typesetting a row separator is not an easy task, especially +% because we support border-widths. Indeed, consider the worst +% case: four cells and all the borders are different. +% Our solution is an optimizer for a good case. We do not typeset +% a fragment of the rule immediately. Instead, we remember the +% parameters. If the next fragment is of the same width, +% we increase the length of the ``waiting'' fragment. +% Otherwise, we output the waiting fragment and the new fragment +% becomes the new waiting fragment. +% \begin{macrocode} +\newcommand\cals@rs@sofar@length{} +\newcommand\cals@rs@sofar@borderl{} +\newcommand\cals@rs@sofar@borderr{} +\newcommand\cals@rs@sofar@width{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} + +% \begin{macro}{\cals@rs@sofar@reset} +% Sets a flag that a new waiting rule should be started. +% \begin{macrocode} +\newcommand\cals@rs@sofar@reset{\let\cals@rs@sofar@width=\relax} +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\cals@rs@sofar@end} +% Prints the waiting rule, if exists. +% \begin{macrocode} +\newcommand\cals@rs@sofar@end{\ifx\relax\cals@rs@sofar@width + \else\cals@rs@sofar@out\fi} +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\cals@rs@sofar@next} +% Enlarges the current waiting rule, or typesets it and +% starts new if the widths do not match. All the parameters +% must be macro names. In order: length, left border, right +% border, width. +% \begin{macrocode} +\newcommand\cals@rs@sofar@next[4]{% +\ifx\relax\cals@rs@sofar@width +% \end{macrocode} +% Starts a new waiting rule. +% \begin{macrocode} + \let\cals@rs@sofar@length=#1% + \let\cals@rs@sofar@borderl=#2% + \let\cals@rs@sofar@borderr=#3% + \let\cals@rs@sofar@width=#4% +\else + \ifdim \cals@rs@sofar@width=#4\relax +% \end{macrocode} +% Enlarges the waiting rule. +% \begin{macrocode} + \dimen0=\cals@rs@sofar@length\relax + \advance\dimen0 by #1\relax + \edef\cals@rs@sofar@length{\the\dimen0}% + \let\cals@rs@sofar@borderr=#3% + \else +% \end{macrocode} +% Typesets the current and start a new waiting rule. +% \begin{macrocode} + \cals@rs@sofar@out + \let\cals@rs@sofar@length=#1% + \let\cals@rs@sofar@borderl=#2% + \let\cals@rs@sofar@borderr=#3% + \let\cals@rs@sofar@width=#4% + \fi +\fi} +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\cals@rs@sofar@over} +% Repeats the last rowsep fragment, probably with another settings. +% Arguments are like in |\cals@rs@sofar@next|. +% \begin{macrocode} +\newcommand\cals@rs@sofar@over[4]{% +\ifdim 0pt=#4 + \relax +\else + \ifdim \cals@rs@sofar@width=#4\relax +% \end{macrocode} +% The width is not changed. We probably need to enlarge the right border +% and probably the left border too. The latter is a bit harder because +% we don't want to change it if the line continues from another cell +% (so, change only if |length|+|borderl|\textgreater |sofar@length|+|sofar@borderl|). +% \begin{macrocode} + \ifdim #3>\cals@rs@sofar@borderr\relax + \edef\cals@rs@sofar@borderr{#3}% + \fi + \dimen0=\cals@rs@sofar@length + \advance\dimen0 by \cals@rs@sofar@borderl\relax + \advance\dimen0 by -#2\relax + \ifdim #1>\dimen0 \relax + \edef\cals@rs@sofar@borderl{#2}% + \fi + \else +% \end{macrocode} +% Typesets the current and start a new waiting rule. +% \begin{macrocode} + \cals@rs@sofar@out + \hskip-#1\relax + \let\cals@rs@sofar@length=#1% + \let\cals@rs@sofar@borderl=#2% + \let\cals@rs@sofar@borderr=#3% + \let\cals@rs@sofar@width=#4% + \fi +\fi} +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\cals@rs@sofar@out} +% Typesets the waiting rule +% \begin{macrocode} +\newcommand\cals@rs@sofar@out{% +\ifdim 0pt=\cals@rs@sofar@width\relax + \hskip\cals@rs@sofar@length\relax +\else + \cals@halfWidthToDimen0\cals@rs@sofar@borderl + \hskip-\dimen0\relax + \cals@halfWidthToDimen2\cals@rs@sofar@borderr + \dimen4=\cals@rs@sofar@length\relax + \advance\dimen4 by \dimen0\relax \advance\dimen4 by \dimen2\relax + \cals@halfWidthToDimen6\cals@rs@sofar@width + \vrule height\dimen6 depth\dimen6 width\dimen4\relax + \hskip-\dimen2\relax +\fi} +% \end{macrocode} +% \end{macro} + +% ^^A ----------------------------------------------------- +% +% \subsubsection{From rowsep specification to typesetting} + +% \begin{macro}{\cals@rs@joinTwo} +% Join and typeset two rowseps (arguments 2 and 3, must be macro names). +% The number and the lengths of the fragments in the rowseps +% should match. +% The argument 1 (also a macro name) is the default width. +% Corrupts the macros 2 and 3. +% Call this macro inside |sofar@reset|...|@end| group. +% \begin{macrocode} +\newcommand\cals@rs@joinTwo[3]{% +% \end{macrocode} +% The loop function. +% \begin{macrocode} +\def\next##1{% +\ifx \eol##1\let\next=\relax +\else + \toks0=\expandafter{##1}% + \edef\cals@tmpII{\the\toks0}% + \llt@decons#3% +% \end{macrocode} +% Now |\cals@tmpII| contains a current fragment of the first rowsep, +% and |\llt@car| of the second. Unpack the individual parameters. +% \begin{macrocode} + \cals@rs@unpack\cals@tmpII\cals@tmpLI \cals@tmpBlI \cals@tmpBrI \cals@tmpWI + \cals@rs@unpack\llt@car \cals@tmpLII\cals@tmpBlII\cals@tmpBrII\cals@tmpWII +% \end{macrocode} +% The special case is when we should not typeset a rowsep fragment. +% \begin{macrocode} + \let\cals@tmp=\cals@iftrue + \cals@maxWidth\cals@tmpWI\cals@tmpWII + \ifx \relax\cals@width\else \ifdim \cals@width=0pt % + \cals@rs@sofar@next\cals@tmpLI\cals@tmpBlI\cals@tmpBrI\cals@width + \let\cals@tmp=\cals@iffalse + \fi\fi +% \end{macrocode} +% Not the special case. Put the both definitions, and let the +% underlying functions take care of calculations. +% \begin{macrocode} + \cals@tmp\ifvoid + \cals@widthII#1\cals@tmpWI + \cals@rs@sofar@next\cals@tmpLI\cals@tmpBlI\cals@tmpBrI\cals@width + \cals@widthII#1\cals@tmpWII + \cals@rs@sofar@over\cals@tmpLII\cals@tmpBlII\cals@tmpBrII\cals@width + \fi +\fi +% \end{macrocode} +% End of |\next| definition: continue the loop. +% End of |\cals@rs@joinTwo| definition: start the loop. +% \begin{macrocode} +\next}% +\expandafter\next#2\eol} +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\cals@rs@joinOne} +% A simplified version of the previous macro. We have only one rowsep, +% and want to join and typeset it with regard to some width, +% given as the first macro parameter. Call this macro inside +% |sofar@reset|...|@end| group. +% \begin{macrocode} +\newcommand\cals@rs@joinOne[2]{% +\def\next##1{\ifx\eol##1\let\next=\relax\else + \toks0=\expandafter{##1}% + \edef\cals@tmpII{\the\toks0}% + \cals@rs@unpack\cals@tmpII\cals@tmpL\cals@tmpBl\cals@tmpBr\cals@tmpW + \cals@widthII#1\cals@tmpW + \cals@rs@sofar@next\cals@tmpL\cals@tmpBl\cals@tmpBr\cals@width +\fi\next}% +\expandafter\next#2\eol} +% \end{macrocode} +% \end{macro} |