diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/sauerj/parcolumns.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/sauerj/parcolumns.dtx | 1090 |
1 files changed, 1090 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/sauerj/parcolumns.dtx b/Master/texmf-dist/source/latex/sauerj/parcolumns.dtx new file mode 100644 index 00000000000..f898e43aaef --- /dev/null +++ b/Master/texmf-dist/source/latex/sauerj/parcolumns.dtx @@ -0,0 +1,1090 @@ +% \iffalse meta-comment +% Line endings: UNIX +% Tab size: 4 +% +% Copyright 2004 Jonathan Sauer +% +% 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". +% +% The Current Maintainer of this work is Jonathan Sauer +% (<jonathan.sauer@gmx.de>). +% +% This work consists of the files parcolumns.dtx and parcolumns.ins +% and the derived file parcolumns.sty. +% +% \fi +% +% \iffalse +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{parcolumns} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +% Modification of verbatim for tabs in listings +\makeatletter +{\catcode`\ =\active% +\catcode`\^^I=\active% +\gdef\@vobeyspaces{% +\catcode`\ \active\let \@xobeysp% +\catcode`\^^I\active\def^^I{~~}% +}}% +\makeatother +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% +%<package>\NeedsTeXFormat{LaTeX2e} +%<package>\ProvidesPackage{parcolumns} +%<package> [2004/11/25 v1.2 Typeset multiple parallel columns] +%<package>\RequirePackage{processkv}[2004/08/05] +% +% \fi +% +% \CheckSum{368} +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} +% +% \DoNotIndex{\@clubpenalty,\@doendpe,\@ehc,\@ifundefined,\@M,\@ne} +% \DoNotIndex{\@one,\@nobreakfalse,\@plus,\@tempa,\@tempb,\@tempboxa} +% \DoNotIndex{\@tempcnta,\@tempdima,\@tempdimb,\@tempdimc} +% \DoNotIndex{\@tempswafalse,\@testopt,\advance,\afterassignment} +% \DoNotIndex{\box,\brokenpenalty,\clubpenalty,\count@,\csname} +% \DoNotIndex{\def,\define@key,\displaywidowpenalty,\divide,\dp,\edef} +% \DoNotIndex{\else,\endcsname,\endgraf,\everypar,\expandafter} +% \DoNotIndex{\fi,\global,\hbadness,\hb@xt@,\hfill,\hsize,\hskip} +% \DoNotIndex{\if@tempswa,\ifnum,\ifvoid,\ifx,\interlinepenalty} +% \DoNotIndex{\lastbox,\leavevmode,\let,\linewidth,\long,\loop} +% \DoNotIndex{\m@ne,\multiply,\newbox,\newcommand,\newcount} +% \DoNotIndex{\newdimen,\newenvironment,\newif,\newtoks} +% \DoNotIndex{\number,\PackageError,\PackageInfo,\processkeyvalues} +% \DoNotIndex{\relax,\repeat,\setbox,\setkeys,\space,\spaceskip} +% \DoNotIndex{\splittopsep,\splittopskip,\strut,\strutbox,\the} +% \DoNotIndex{\toks@,\tolerance,\unvbox,\vbadness,\vbox,\vfuzz} +% \DoNotIndex{\vrule,\vsplit,\widowpenalty,\z@,\z@skip,\\} +% +% \GetFileInfo{\jobname.sty} +% +% \title{The \textsf{parcolumns} package\thanks{This document +% corresponds to \textsf{\filename}~\fileversion, dated \filedate.}} +% +% \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}} +% +% \date{\filedate} +% +% \maketitle +% +% \begin{abstract} +% This file describes the \textsf{parcolumns} package that provides an +% environment for typesetting text in two or more columns columns in +% parallel. +% +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% Sometimes it is necessary to typeset text in two or more columns in +% parallel, i.e. when typesetting a text in its original language and +% in its translation(s). This package provides the \verb|parcolumns| +% environment for typesetting text in several columns, where the text +% of all columns is aligned vertically. +% +% Text in the |parcolums| environment is typeset in chunks, where the +% chunks of one row are aligned vertically. A chunk consists of one or +% more paragraphs of text, including \TeX\ macros. +% +% +% \section{Usage}\label{sec:Usage} +% +% \DescribeEnv{parcolumns} Usage: |parcolumns| \oarg{options} +% \marg{number of colums}. +% +% Inside the |parcolumns| environment text can be typeset in two or +% more columns in parallel via the |\parchunk| macro. Normal text can +% also be included. +% +% The \verb|parcolumns| environment takes an optional parameter that +% specifies the options for the environment using the \textsf{keyval} +% and \textsf{processkv} packages. The following options exist: +% +% \begin{description} +% \item[\emph{colwidths}] Sets the widths of the columns. The +% widths are specified as key-values, +% \meta{columnnumber}=\meta{width}. +% Columns start at `1'. Note that in +% order to be ignored by the +% \textsf{keyval} package, the complete +% value has to be surrounded by braces, +% i.e. `|colwidths={1=2cm,3=5cm,4=2cm}|' +% to set the first column to a width of +% 2~cm, the third to 5~cm and the fourth +% to 2~cm. (the second column is +% calculated) +% +% Columns not set this way will be +% distributed evenly across the remaining +% horizontal space of the page. +% +% \item[distance] Sets the distance between two columns. +% If omitted set to \verb|2em|. +% +% \item[rulebetween] (Flag)\footnote{Meaning that if you +% just say \texttt{rulebetween}, you set the +% flag, as well as when you say +% \texttt{rulebetween=true}. Saying +% \texttt{rulebetween=false} clears the flag, +% even though this does not make much sense, +% as it is the default.} +% Typeset a vertical bar between two +% columns. +% +% |false| if omitted. +% +% \item[nofirstindent] (Flag) Suppress the indentation of the first +% paragraph in the environment. +% +% |false| if omitted. +% +% \item[sloppy] (Flag) Typeset text in the columns in a +% more sloppy way, preventing overfull +% hboxes at the cost of larger +% interword spacing. +% +% |false| if omitted. +% +% \item[sloppyspaces] (Flag) Makes spaces in the columns +% stretchable, preventing overfull +% hboxes at the cost of even larger +% interword spacing that |sloppy|. +% +% |false| if omitted. +% +% \end{description} +% +% +% \DescribeMacro{\colchunk} Usage: |\colchunk| \oarg{column} +% \marg{chunk}. +% +% The macro |\colchunk| sets a chunk of text for the next column. You +% don't have to set chunks for all columns; the colums not set remain +% empty. However, the columns are filled from left to right, so if a +% column inbetween should remain empty, you must say |\colchunk{}| or +% specify the column to set using the optional parameter (columns +% start at 1): |\colchunk[2]{|\ldots|}| sets the text of the second +% column. Following calls to |\colchunk| without optional parameter +% fill the third, fourth et cetera column. +% +% After a call to |\colplacechunks|, the column number is reset to +% one. +% +% +% +% \DescribeMacro{\colplacechunks} Usage: |\colplacechunks|. +% +% The macro |\colplacechunks| places the chunks added with |\colchunk| +% on the page. If there are no chunks to place, it does nothing. +% +% +% +% \section{Examples} +% +% Two columns, option |rulebetween=true| (which is the same as +% just saying |rulebetween|): +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[rulebetween=true]{2} +% \colchunk{Erwarten Sie von mir, dass ich rede? -- Nein, Mister +% Bond, ich erwarte von Ihnen, dass Sie sterben!} +% +% \colchunk{Do you expect me to talk? -- No, Mister Bond, I expect you +% to die!} +% +% \colplacechunks +% +% \colchunk{Erwarten Sie von mir, dass ich rede? -- Nein, Mister +% Bond, ich erwarte von Ihnen, dass Sie sterben!} +% +% \colchunk{Do you expect me to talk? -- No, Mister Bond, I expect you +% to die!} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% As the german text is slightly longer, let's make the left column +% alittle bit larger using |colwidths={1=.55\linewidth}|: +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[rulebetween=true,colwidths={1=.55\linewidth}]{2} +% \colchunk{Erwarten Sie von mir, dass ich rede? -- Nein, Mister +% Bond, ich erwarte von Ihnen, dass Sie sterben!} +% +% \colchunk{Do you expect me to talk? -- No, Mister Bond, I expect you +% to die!} +% +% \colplacechunks +% +% \colchunk{Erwarten Sie von mir, dass ich rede? -- Nein, Mister +% Bond, ich erwarte von Ihnen, dass Sie sterben!} +% +% \colchunk{Do you expect me to talk? -- No, Mister Bond, I expect you +% to die!} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% Three columns, option |nofirstindent=true|: +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[nofirstindent]{3} +% \colchunk{This is just a short english text, just long enough to fill +% a few lines.} +% +% \colchunk{Dies ist nur ein kurzer deutscher Text, gerade lang genug, +% um ein paar Zeilen zu fuellen.} +% +% \colchunk{This is another short english text, as my french is not +% that good anymore.} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% There was an overfull |\hbox| in the previous text. Let's +% try that again with the option |sloppy|: +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[nofirstindent,sloppy]{3} +% \colchunk{This is just a short english text, just long enough to fill +% a few lines.} +% +% \colchunk{Dies ist nur ein kurzer deutscher Text, gerade lang genug, +% um ein paar Zeilen zu fuellen.} +% +% \colchunk{This is another short english text, as my french is not +% that good anymore.} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% No overfull hbox this time, but the spacing in the first column +% is not optimal. You just have to pick what's better. Or you could +% try the interword spacing provided by the \textsf{soul} package. +% +% \addvspace{\baselineskip}\noindent Maybe we do not want to fill the +% first column, but do not want to type |\colchunk{}| either. Then we +% can say |\colchunk[2]| to directly start with the second column +% (note that we are using the option |sloppy|, too): +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[nofirstindent,sloppy]{3} +% \colchunk[2]{This is just a short english text, just long enough to fill +% a few lines.} +% +% \colchunk{Dies ist nur ein kurzer deutscher Text, gerade lang genug, +% um ein paar Zeilen zu fuellen.} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% Note that \texttt{parcolumns} does not insert vertical space +% before or after the environment! In these examples, the space has +% manually been added with |\addvspace|. +% +% +% +% \section{Notes}\label{sec:Notes} +% +% \begin{itemize} +% \item The columns will always fill the complete width of the +% page by stretching or shrinking the space between the columns. +% That means that if the total width of all columns is set +% to about half the page width, the space between the columns +% will take up the rest, ignoring whatever was set with the +% key |distance|.\footnote{The key \texttt{distance} is only +% used for calculating the width of the columns and is ignored +% afterwards.} +% +% \item Footnotes are not set in columns. +% +% \item \textsf{parcolumns} does not work very well with displayed +% formula. The best way to typeset a |displaymath| et.al. +% environment is to include it in separate |\colchunk| +% commands, i.e. (assuming two columns and the same formula +% in both): +% +% \begin{verbatim} +% ... some text placed using \colchunk ... +% \colchunk{ % Left column +% \begin{displaymath} +% x^2 + y^2 = z^2 +% \end{displaymath} +% } +% \colchunk{ % Right column +% \begin{displaymath} +% x^2 + y^2 = z^2 +% \end{displaymath} +% } +% \colplacechunks +% ... some more text placed using \colchunk ... +% \end{verbatim} +% +% \end{itemize} +% +% +% +% \StopEventually{} +% +% \section{Implementation} +% +% \subsection{Allocation} +% +% The current column (starting with one): +% +% \begin{macrocode} +\newcount\pc@columnctr +% \end{macrocode} +% +% The total number of columns in the current |parcolums| environment. +% +% \begin{macrocode} +\newcount\pc@columncount +% \end{macrocode} +% +% Place a vertical rule between two columns? +% +% \begin{macrocode} +\newif\ifpc@rulebetween +% \end{macrocode} +% +% Stores |\everypar| for use in |\parparagraphs|. +% +% \begin{macrocode} +\newtoks\pc@everypar +% \end{macrocode} +% +% Note that additional allocations are performed later on-demand in +% |\pc@alloccolumns|. +% +% +% +% \subsection{\textsf{keyvalue} keys} +% +% \begin{macro}{\pc@boolkey} +% +% Sets an \verb|if|-condition in \marg{\#1} to the value passed as +% \marg{\#2}. If \verb|#2| is \verb|false|, set \verb|if#1| to +% \verb|false|, else (any other value) to \verb|true|. +% +% Usage: |\pc@boolkey| \marg{ifcondition} \marg{value} +% +% \begin{macrocode} +\def\pc@boolkey#1#2{% + \edef\@tempa{#2}% + \edef\@tempb{false}% + \ifx\@tempa\@tempb% + \csname #1false\endcsname% + \else% + \csname #1true\endcsname% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% Define the keys for the options of |parcolumns|. +% +% \begin{macrocode} +\define@key{parcolumns}{distance}{% + \@tempdimc#1\relax% +} +\define@key{parcolumns}{rulebetween}[true]{% + \pc@boolkey{pc@rulebetween}{#1}% +} +\define@key{parcolumns}{nofirstindent}[true]{% + \pc@boolkey{@tempswa}{#1}% +% \end{macrocode} +% +% If the indentation of the first line of the first paragraph should +% be suppressed, change |\pc@everypar| accordingly. The token register +% is reset after the placing of the first row of chunks in +% |\colplacechunks|. +% +% What exactly are we doing? First we assign box 0 the contents of +% |\lastbox|. At the beginning of a paragraph |\lastbox| contains +% the glue inserted for the indentation of the first line. By +% assigning this box to box 0, we remove the indentation. We do +% this in a group as not to change the contents of box 0. +% +% Afterwards we set |\everypar| to nothing. This is necessary because +% we only want to suppress the indentation for the first paragraph of +% the |parcolumns| environment, not every paragraph. We set +% |\everypar| and not |\pc@everypar| to nothing, because +% |\pc@everypar| is only a temporary storage that will be assigned to +% |\everypar| when used. +% +% \begin{macrocode} + \if@tempswa\pc@everypar{{\setbox\z@\lastbox}\everypar{}}\fi% +} +\define@key{parcolumns}{sloppy}[true]{% + \pc@boolkey{@tempswa}{#1}% +% \end{macrocode} +% +% If sloppy typesetting is asked for, we set |\hbadness| and +% |\tolerance| to 10000, so that \TeX\ breaks lines whenever possible, +% even if this means high interword spacing. +% +% \begin{macrocode} + \if@tempswa% + \hbadness\@M% + \tolerance\@M% + \fi% +} +\define@key{parcolumns}{sloppyspaces}[true]{% + \pc@boolkey{@tempswa}{#1}% +% \end{macrocode} +% +% If sloppy spaces are asked for, we make the space stretchable: +% +% \begin{macrocode} + \if@tempswa% + \spaceskip.3333em\@plus1em % + \fi% +} +% \end{macrocode} +% +% +% We save the key-value-list containing widths of the columns in +% |\toks@| for later use in |\pc@setcolumnwidths|. +% +% \begin{macrocode} +\define@key{parcolumns}{colwidths}{% + \toks@{#1}% +} +% \end{macrocode} +% +% +% \subsection{Main environments and macros} +% +% \begin{environment}{parcolumns} +% +% Environment for a number of columns of text set in parallel (see +% section \ref{sec:Usage} on page \pageref{sec:Usage} for the possible +% options) +% +% Usage: |\begin{parcolumns}| \oarg{options} \marg{number of columns} +% \ldots\ |\end{parcolums}| +% +% \begin{macrocode} +\newenvironment{parcolumns}[2][]{% + \pc@rulebetweenfalse% +% \end{macrocode} +% +% |\if@tempswa| is |true|, if the indentation of the first line +% should be suppressed, otherwise |false|. Default is |false|: +% +% \begin{macrocode} + \@tempswafalse% +% \end{macrocode} +% +% |\@tempdimc| contains the space between two columns. Default +% is |2em|: +% +% \begin{macrocode} + \@tempdimc2em\relax% +% \end{macrocode} +% +% We set the options: +% +% \begin{macrocode} + \toks@{}% + \setkeys{parcolumns}{#1}% +% \end{macrocode} +% +% We store the total number of columns and reset the counter for +% the current column: +% +% \begin{macrocode} + \pc@columncount#2 % + \pc@columnctr\z@% +% \end{macrocode} +% +% We allocate the columns and set their widths: +% +% \begin{macrocode} + \pc@alloccolumns% + \pc@setcolumnwidths% +% \end{macrocode} +% +% We switch to vertical mode: +% +% \begin{macrocode} + \endgraf% +% \end{macrocode} +% +% As we are changing |\everypar|, we need to make sure that the most +% important flag is reset, which normally happens in the |\everypar| +% of a |\section|-command: |\if@nobreak|. (otherwise the next section +% is typeset directly after the text of the previous section instead +% of leaving some space)\footnote{I discovered this the hard way, +% spending one or two hours wondering why the spacing between two +% sections was much too small.} +% +% \begin{macrocode} + \@nobreakfalse% +% \end{macrocode} +% +% We reset |\everypar|, as it is of no use for us and can only screw +% up things badly: +% +% \begin{macrocode} + \global\everypar{}% +}{% +% \end{macrocode} +% +% At the end of the |parcolumns|-environment \ldots\ just in case, we +% place the last chunks, if not already done so: +% +% \begin{macrocode} + \colplacechunks% + \endgraf% +% \end{macrocode} +% +% We reset |\clubpenalty| globally to its normal value (the |\global| +% makes sure that if |\everypar| should have reset |\clubpenalty|, it +% is reset now). +% +% \begin{macrocode} + \global\clubpenalty\@clubpenalty% +% \end{macrocode} +% +% We suppress the indentation of the next paragraph immediately +% following the environment: +% +% \begin{macrocode} + \@doendpe% +} +% \end{macrocode} +% \end{environment} +% +% +% \begin{macro}{\colchunk} +% +% Sets the text for the next chunk of the next column. +% +% Usage: |\colchunk| \oarg{column} \marg{chunk}. (note that the |{| +% and |}| are \emph{not} optional, even if the chunk consists of only +% one token!) +% +% We need two macros for handling the optional parameter +% \meta{column}, |\colchunk| and |\colchunk@|. First we define +% |\colchunk|: +% +% \changes{1.1}{2004/08/22}{Optional parameter added.} +% +% \begin{macrocode} +\newcommand{\colchunk}{\@testopt\colchunk@{}}% +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\colchunk@} +% +% What are we doing now? By suffixing the last (optional) parameter by +% |#|, we tell \TeX\ that the last parameter of |\colchunk| is to be +% delimited by a right brace |{|, or \TeX\ will complain with a more +% comprehensible message that without the |#|: `Use of |\colchunk| +% doesn't match its definition.' instead of `Missing |{| inserted.' +% +% \changes{1.0.1}{2004/08/10}{Parameter added.} +% \changes{1.1}{2004/08/22}{Optional parameter added.} +% +% \begin{macrocode} +\long\def\colchunk@[#1]#{% +% \end{macrocode} +% +% We check if the optional parameter is not empty. Then we use it as +% the column number, otherwise we simply pick the next column: +% +% \begin{macrocode} + \ifx\\#1\\% + \advance\pc@columnctr\@ne% + \else% + \pc@columnctr#1\relax% + \fi% +% \end{macrocode} +% +% If we try to add a column past the last one, we display an error +% message: +% +% \begin{macrocode} + \ifnum\pc@columnctr>\pc@columncount% + \PackageError{parcolumns}{The column \number\pc@columnctr\space% + is too large}{Only \number\pc@columncount\space columns are% + \space allowed.} +% \end{macrocode} +% +% As we cannot simply skip the chunk (we could gobble what follows +% after the macro, but this would require a lot of jumping, and just +% for handling a small mistake \ldots), we simply set the last column: +% +% \changes{1.0.1}{2004/08/10}{Error handling somewhat improved.} +% +% \begin{macrocode} + \pc@columnctr\pc@columncount% + \fi% +% \end{macrocode} +% +% We zero the |\clubpenalty| that could have been changed, i.e. by +% |\everypar| of a |\section|-command: |\section| changes the +% clubpenalty to prevent a break between the first two lines of the +% paragraph following immediately after the section; as we split off +% line after line when typesetting the two columns, this would make +% splitting of a single line impossible (|\vsplit| uses the same logic +% as page-breaking), thus resulting in a lot of overfull vboxes and +% weird spacing inbetween, as \emph{two} lines would be split off. +% +% We do this every time we add chunks just in case some macro in the +% chunks has changed |\clubpenalty|. Note that we cannot prevent a +% macro in the text of the chunk to change the +% |\clubpenalty|.\footnote{Well we could, by redefining the +% clubpenalty to be a macro that simply throws its parameter away, and +% using some tricks to make this macro behave like a register, +% therefore completely ignoring any change of the clubpenalty.} But if +% it is changed, at least it will not stay changed (though the typeset +% columns will still look bad). +% +% \changes{1.0.1}{2004/08/09}{clubpenalty is always reset before +% adding chunks} +% +% \begin{macrocode} + \clubpenalty\z@% +% \end{macrocode} +% +% The same goes for the other penalties \TeX\ will insert between two +% lines, as we absolutely, positively \emph{must} be able to break +% between any two lines:\footnote{C.f. chapter 14 of the \TeX book} +% +% \changes{1.2}{2004/11/25}{other penalties added} +% +% \begin{macrocode} + \interlinepenalty\z@% + \displaywidowpenalty\z@% + \widowpenalty\z@% + \brokenpenalty\z@% +% \end{macrocode} +% +% We set |\everypar| to our self-defined |\pc@everypar| to suppress +% the indentation of the first paragraph if so desired: +% +% \begin{macrocode} + \everypar\expandafter{\the\pc@everypar}% +% \end{macrocode} +% +% After the next assignment, insert the width of the column: +% +% \begin{macrocode} + \afterassignment\pc@setcolumnwidth% +% \end{macrocode} +% +% We typeset the chunk's text into the box |\pc@column@|\meta{column +% counter}. The text of the chunk follows the macro, meaning that the +% last line looks like this: |\vbox{|\meta{chunk text}|}|. +% +% But what about the width of the box? |\hsize| must be set in the +% vbox in order to make it the correct width! We achieve this using +% the |\afterassignment| above: After the assignment of the chunk's +% text to the box, we are inside the box, therefore the contents of +% |\pc@setcolumnwidth| is inserted at the very beginning of the vbox, +% setting the correct width. +% +% Why don't we simply make |\colchunk| take one parameter that +% contains the text of the chunk? Because in that case, macros that +% change catcodes like |\verb| would be prohibited, which would +% restrict this package somewhat. Also it would be slower and would +% use more memory. +% +% \begin{macrocode} + \expandafter\setbox\csname pc@column@\number\pc@columnctr\endcsname% + \vbox% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\colplacechunks} +% +% Places all chunks set with |\colchunk|. +% +% \begin{macrocode} +\newcommand{\colplacechunks}{% +% \end{macrocode} +% +% If there are any chunks to place: +% +% \begin{macrocode} + \ifnum\pc@columnctr>\z@% +% \end{macrocode} +% +% We place them: +% +% \begin{macrocode} + \pc@placeboxes% +% \end{macrocode} +% +% We reset the column counter: +% +% \begin{macrocode} + \pc@columnctr\z@% +% \end{macrocode} +% +% We clear |\pc@everypar|, because we only want to suppress the +% indentation of the first paragraph of each column at the very top of +% the |parcolumns| environment, not of the first paragraph of every +% call to |\colchunk|. +% +% \begin{macrocode} + \pc@everypar{}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsection{Internal environments and macros} +% +% \begin{macro}{\pc@placeboxes} +% +% Places the prepared boxes (containing the chunks) on the page. +% +% \begin{macrocode} +\def\pc@placeboxes{% +% \end{macrocode} +% +% We assume we don't have to perform another line (|\@tempa| contains +% what we have to to after we are finished with this macro). The +% assignment is global because later on when changing |\@tempa| we are +% in a group: +% +% \begin{macrocode} + \global\let\@tempa\relax% + \count@\z@% +% \end{macrocode} +% +% We create a hbox. Inside a hbox, vboxes are put horizontally +% next to each other and are aligned on their baseline: +% +% \begin{macrocode} + \hb@xt@\linewidth{% +% \end{macrocode} +% +% Before doing any work, we change a few parameters: +% +% \changes{1.2}{2004/11/22}{moved parameter changes from begin of +% environment} +% +% We prevent warnings of overfull and underfull vboxes as they can +% happen, but we do not really care (happens when we |\vsplit| the top +% off the chunks, this is okay): +% +% \changes{1.2}{2004/11/22}{vfuzz increased to prevent warnings with +% math} +% +% \changes{1.2}{2004/11/22}{vbadness set} +% +% \begin{macrocode} + \vfuzz30ex % + \vbadness\@M% +% \end{macrocode} +% +% We prevent vertical glue to be insert when |vsplit|ting a vbox +% (otherwise it screws up the spacing). +% +% \begin{macrocode} + \splittopskip\z@skip% +% \end{macrocode} +% +% Now we loop over all the prepared boxes. We can use |\loop| here as +% we are in a group (begun by |\hbox|). Otherwise we would have to +% open a group manually or loop manually, as to not screw up a |\loop| +% outside the macro: +% +% \begin{macrocode} + \loop\ifnum\count@<\pc@columncount% + \advance\count@\@ne% +% \end{macrocode} +% +% If the box |\pc@column@|\meta{counter} is empty, we simply insert a +% hskip the width of the box (saved in +% |\pc@column@width@|\meta{counter}): +% +% \begin{macrocode} + \expandafter\ifvoid\csname pc@column@\number\count@% + \endcsname% + \hskip\csname pc@column@width@\number\count@\endcsname% + \else% +% \end{macrocode} +% +% Otherwise we |\vsplit| the first line of the box (at the same time +% removing it from |\pc@column@|\meta{counter}) and save it in +% |\@tempboxa|. Then, we strip this resulting box of its enclosing +% vbox and put it into another vbox, which we put into the hbox begun +% a few lines ago. +% +% Why is this so complicated? To ensure that proper vertical glue is +% inserted (otherwise the spacing between the lines would be wrong). +% +% \begin{macrocode} + \expandafter\setbox\expandafter\@tempboxa\expandafter% + \vsplit\csname pc@column@\number\count@\endcsname% + to \dp\strutbox% + \vbox{\unvbox\@tempboxa}% + \fi% +% \end{macrocode} +% +% If the remaining box is not empty, we have to perform at least +% another line: +% +% \begin{macrocode} + \expandafter\ifvoid\csname pc@column@\number\count@% + \endcsname\else% + \global\let\@tempa\pc@placeboxes% + \fi% +% \end{macrocode} +% +% If this is not the last column, we put a strut into the hbox to +% ensure propery vertical spacing: +% +% \begin{macrocode} + \ifnum\count@<\pc@columncount% + \strut% +% \end{macrocode} +% +% If a vertical line should be placed between two columns, we insert +% it now, centering it between two |\hfill|s. Otherwise, we simply +% insert a |\hfill| that stretches as much as possible, pushing the +% right column to the right margin. (see also section \ref{sec:Notes} +% on page \pageref{sec:Notes}) +% +% \begin{macrocode} + \hfill% + \ifpc@rulebetween% + \vrule% + \hfill% + \fi% + \fi% + \repeat% + }% +% \end{macrocode} +% +% If necessary, we perform another line: +% +% \begin{macrocode} + \@tempa% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\pc@alloccolumns} +% +% Allocates a number of |\box|es, named |\pc@column@1|, |\pc@column@2| +% et cetera, if not already allocated. +% +% Also allocates a number of |\dimen|s, named |\pc@column@width@1| et +% cetera. +% +% If the |\box|es and |\dimen|s are already allocated, they are +% cleared (|\box|es) or set to zero (|\dimen|s). +% +% \begin{macrocode} +\def\pc@alloccolumns{% + \count@\z@% + \loop\ifnum\count@<\pc@columncount% + \advance\count@\@ne% + \@ifundefined{pc@column@\number\count@}{% + \expandafter\newbox\csname pc@column@\number\count@% + \endcsname% + \expandafter\newdimen\csname pc@column@width@\number% + \count@\endcsname% + }{% + \setbox0\box\csname pc@column@\number\count@\endcsname% + \csname pc@column@width@\number\count@\endcsname\z@% + }% + \repeat% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\pc@setcolumnwidths} +% +% Sets the widths of all columns. The defined widths have been +% temporarily stored in |\toks@|. |\@tempdimc| contains the space +% between two columns. +% +% \begin{macrocode} +\def\pc@setcolumnwidths{% + \expandafter\processkeyvalues\expandafter{\the\toks@}% + \pc@setsinglecolwidth% +% \end{macrocode} +% +% |\@tempdima| will contain the total width of all columns that have a +% known width (read: have had their width set via the parameter +% |colwidths|) +% +% \begin{macrocode} + \@tempdima\z@% +% \end{macrocode} +% +% |\@tempcnta| will contain the count of columns that an unknown width +% (read: have had their width \emph{not} set via the parameter +% |colwidths|, thus now having a width of zero points, as the widths +% of all columns have been reset in |\pc@alloccolumns|): +% +% \begin{macrocode} + \@tempcnta\z@% +% \end{macrocode} +% +% We calculate the total width of all columns known. We count how many +% columns have an unknown width: +% +% \begin{macrocode} + \count@\z@% + \loop\ifnum\count@<\pc@columncount% + \advance\count@\@ne% + \@tempdimb\csname pc@column@width@\number\count@\endcsname% + \advance\@tempdima\@tempdimb% + \ifnum\@tempdimb=\z@% + \advance\@tempcnta\@ne% + \else% + \PackageInfo{parcolumns}{Width of column \number\count@% + \space set to \the\@tempdimb} + \fi% + \repeat% +% \end{macrocode} +% +% If at least one column has an unknown width: +% +% \begin{macrocode} + \ifnum\@tempcnta>\z@% +% \end{macrocode} +% +% |\@tempdimc| contains the distance between columns. We calculate the +% space left for the columns with an unknown width. +% +% |\@tempdimb| will contain the sum of the space between all the +% columns \ldots +% +% \begin{macrocode} + \@tempdimb\@tempdimc% + \multiply\@tempdimb\pc@columncount% + \advance\@tempdimb-\@tempdimc% +% \end{macrocode} +% +% \ldots\ plus the sum of the width of all columns with a known width: +% +% \begin{macrocode} + \advance\@tempdimb\@tempdima% +% \end{macrocode} +% +% |\@tempdima| will contain the space for each column with an unknown +% width: +% +% \begin{macrocode} + \@tempdima\linewidth% + \advance\@tempdima-\@tempdimb% + \divide\@tempdima\@tempcnta% +% \end{macrocode} +% +% We set the widths of the colums with an unknown width: +% +% \begin{macrocode} + \count@\z@% + \loop\ifnum\count@<\pc@columncount% + \advance\count@\@ne% + \ifnum\csname pc@column@width@\number\count@\endcsname=\z@% + \csname pc@column@width@\number\count@\endcsname\@tempdima% + \PackageInfo{parcolumns}{Width of column \number\count@% + \space calculated as \the\@tempdima} + \fi% + \repeat% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\pc@setsinglecolwidth} +% +% Usage: |\pc@setsinglecolwidth| \marg{column} \marg{width}. +% +% Sets the width of the column \meta{column} to the width +% \meta{width}. Displays an error message if the column is not valid. +% +% \begin{macrocode} +\def\pc@setsinglecolwidth#1#2{% + \@ifundefined{pc@column@width@\number#1}{ + \PackageError{parcolumns}{`#1' is not a valid column number!}% + {\@ehc}% + }{% + \csname pc@column@width@\number#1\endcsname=#2\relax% + }% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\pc@setcolumnwidth} +% +% Sets |\hsize| to the width of a column (stored in +% |\pc@column@width@|\meta{pc@columnctr}) and enters horizonal mode. +% +% \changes{1.2}{2004/11/22}{linewidth set, too} +% +% \begin{macrocode} +\def\pc@setcolumnwidth{% + \hsize\csname pc@column@width@\number\pc@columnctr\endcsname% + \linewidth\hsize% + \leavevmode% +} +% \end{macrocode} +% \end{macro} +% +% +% \Finale +% \PrintChanges +% \PrintIndex +\endinput
\ No newline at end of file |