diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-11 23:52:50 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-11 23:52:50 +0000 |
commit | ca0a12e3eb2e190b040b2333036e48cb0d34dca8 (patch) | |
tree | e2373ad3c8ac8bd688b72a39e85b0d0c45e43a23 | |
parent | 04ffa713ed0f042fc5cf25048dc7a0ec1e883819 (diff) |
trunk/Master/texmf-dist/source/latex/eqparbox
git-svn-id: svn://tug.org/texlive/trunk@254 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/source/latex/eqparbox/eqparbox.dtx | 761 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/eqparbox/eqparbox.ins | 55 |
2 files changed, 816 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/eqparbox/eqparbox.dtx b/Master/texmf-dist/source/latex/eqparbox/eqparbox.dtx new file mode 100644 index 00000000000..bd7f402172c --- /dev/null +++ b/Master/texmf-dist/source/latex/eqparbox/eqparbox.dtx @@ -0,0 +1,761 @@ +% \iffalse meta-comment +% +% Copyright (C) 2004 Scott Pakin <scott+eqp@pakin.org> +% ---------------------------------------------------- +% +% This package may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.2 +% 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.2 or later is part of all distributions of LaTeX +% version 1999/12/01 or later. +% +% \fi +% \iffalse +%% File: eqparbox.dtx Copyright (C) 2004 Scott Pakin <scott+eqp@pakin.org> +% +%<package>\NeedsTeXFormat{LaTeX2e} +%<package>\ProvidesPackage{eqparbox} +%<package> [2004/08/02 v2.1 Create equal-widthed parboxes] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{eqparbox} +\EnableCrossrefs +\CodelineIndex +\RecordChanges + +% Uncomment the following line if you don't want to include a +% source-code listing. +%\OnlyDescription + +% Give LaTeX some more leeway in placing floats +% (suggested by Donald Arseneau <asnd@triumf.ca>). +\renewcommand{\topfraction}{0.85} +\renewcommand{\bottomfraction}{0.7} +\renewcommand{\textfraction}{0.15} +\renewcommand{\floatpagefraction}{0.66} +\renewcommand{\dbltopfraction}{0.66} +\renewcommand{\dblfloatpagefraction}{0.66} +\setcounter{topnumber}{9} +\setcounter{bottomnumber}{9} +\setcounter{totalnumber}{20} +\setcounter{dbltopnumber}{9} + +% Because we put table captions *above* tables, we should add a +% little extra space between the caption and the table. +\setlength{\belowcaptionskip}{2ex} + +\begin{document} +\DocInput{eqparbox.dtx} +\end{document} +%</driver> +% \fi +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \CheckSum{169} +% \GetFileInfo{eqparbox.sty} +% +% \title{The \textsf{eqparbox} package\thanks{This file +% has version number \fileversion, last +% revised \filedate.}} +% \author{Scott Pakin \\ \textit{scott+eqp@pakin.org}} +% \date{\filedate} +% \maketitle +% +% \changes{v1.0}{2001/04/19}{Initial version} +% \changes{v2.0}{2004/07/31}{Rewrote to use only two \meta{dimen}s total +% and the rest macros (problem reported by Gilles P\'erez-Lambert and +% Plamen Tanovski; solution suggested by David Kastrup and Donald +% Arseneau)} +% +% \DoNotIndex{\@auxout,\@ifnextchar,\@ifundefined} +% \DoNotIndex{\begin,\begingroup,\csname,\DeclareRobustCommand,\def} +% \DoNotIndex{\else,\end,\endcsname,\endgroup,\expandafter,\fi,\gdef,\global} +% \DoNotIndex{\hbox,\ifdim,\ifx,\immediate,\let} +% \DoNotIndex{\newcommand,\newdimen,\newif,\newlength,\noexpand} +% \DoNotIndex{\relax,\setbox,\space,\string,\the,\wd,\xdef,\z@} +% +% \begin{abstract} +% The \textsf{eqparbox} package makes it easy to define a group of +% \verb|\parbox|es whose members all have the same width, the natural +% width of the widest member. A document can contain any number of +% groups, and each group can contain any number of members. This +% simple, equal-width mechanism can be used for a variety of alignment +% purposes, as is evidenced by the examples in this document. +% \end{abstract} +% +% \section{Motivation} +% +% Let's start with a little test. How would you typeset +% Table~\ref{tbl:sales-data}, in which the numbers are right-justified +% relative to each other but centered as a group within each column. +% And second, how would you typeset the r\'esum\'e excerpt shown in +% Figure~\ref{fig:resume-excerpt} while meeting the following +% requirements: +% +% \begin{enumerate} +% \item The header columns must be left-justified relative to each +% other. +% \item The headers columns should be evenly spaced across the page. +% \item Page breaks should be allowed within the r\'esum\'e. +% \end{enumerate} +% +% \begin{table}[tp] +% \centering +% \caption{Sample sales data} +% \label{tbl:sales-data} +% \begin{tabular}{@{}lccc@{}} \hline +% & \multicolumn{3}{c}{Sales (in millions)} \\ \cline{2-4} +% \multicolumn{1}{c}{\raisebox{1ex}[2ex]{Product}} & +% October & November & December \\ \hline +% +% Widgets & \eqparbox{oct}{\raggedleft 55.2 } & +% \eqparbox{nov}{\raggedleft\textbf{ 89.2}} & +% \eqparbox{dec}{\raggedleft 57.9 } \\ +% Doohickeys & \eqparbox{oct}{\raggedleft\textbf{ 65.0}} & +% \eqparbox{nov}{\raggedleft 64.1 } & +% \eqparbox{dec}{\raggedleft 9.3 } \\ +% Thingamabobs & \eqparbox{oct}{\raggedleft 10.4 } & +% \eqparbox{nov}{\raggedleft 8.0 } & +% \eqparbox{dec}{\raggedleft\textbf{109.7}} \\ \hline +% \end{tabular} +% \end{table} +% +% \begin{figure} +% \bigskip\noindent\rule{\linewidth}{1pt}\bigskip\par +% \noindent% +% \eqparbox{place}{\textbf{Widgets, Inc.}} \hfill +% \eqparbox{title}{\textbf{Senior Widget Designer}} \hfill +% \eqparbox{dates}{\textbf{1/95--present}} +% +% \begin{itemize} +% \item Supervised the development of the new orange and blue widget lines. +% \item Improved the design of various widgets, making them less sticky +% and far less likely to explode. +% \item Made widget management ten times more cost-effective. +% \end{itemize} +% +% \noindent% +% \eqparbox{place}{\textbf{Thingamabobs, Ltd.}} \hfill +% \eqparbox{title}{\textbf{Lead Engineer}} \hfill +% \eqparbox{dates}{\textbf{9/92--12/94}} +% +% \begin{itemize} +% \item Found a way to make thingamabobs run on solar power. +% \item Drafted a blueprint for a new doohickey-compatibility module for +% all cool-mint thingamabobs. +% \item Upgraded superthingamabob specification document from Microsoft +% Word to \LaTeXe. +% \end{itemize} +% \noindent\rule{\linewidth}{1pt} +% \caption{Excerpt from a sample r\'esum\'e} +% \label{fig:resume-excerpt} +% \end{figure} +% +% The two questions can be answered the same way: by putting various +% blocks of text into equal-widthed boxes. if the data in +% Table~\ref{tbl:sales-data} are put into equal-sized |\parbox|es, each +% containing a |\raggedleft| for right-justification, the |\parbox|es +% can then be centered to achieve the desired result. Similarly, if the +% company names in Figure~\ref{fig:resume-excerpt} are both put in a +% |\parbox| as wide as ``Thingamabobs, Ltd.,'' the job titles in a +% |\parbox| as wide as ``Senior Widget Designer,'' and the dates in a +% |\parbox| as wide as ``1/95--present,'' then they can be spaced evenly +% by separating them with |\hfill|s. +% +% The problem is in choosing the width for each set of |\parbox|es. For +% Table~\ref{tbl:sales-data}, this isn't too difficult, because digits +% are the same width as each other in most fonts. Each |\parbox|, +% therefore, need be only as wide as the largest sequence of digits +% expected. Figure~\ref{fig:resume-excerpt} is more of a bother. The +% user must typeset the r\'esum\'e once to see which entry in each +% column is the widest and then assign lengths appropriately: +% +% \begin{verbatim} +% \newlength{\placewidth} +% \settowidth{\placewidth}{Thingamabobs, Ltd.} % Employment 2 +% \newlength{\jobtitlewidth} +% \settowidth{\jobtitlewidth}{Senior Widget Designer} % Employment 1 +% \newlength{\dateswidth} +% \settowidth{\dateswidth}{1/95--present} % Employment 1 +% \end{verbatim} +% +% \noindent +% Every time a piece of information changes, it must be changed in two +% places: in the r\'esum\'e itself and in the |\settowidth| +% command. When employment information is added or deleted, the +% |\settowidth| commands must be modified to reflect the new +% maximum-widthed entry in each column. If only there were a simpler +% way to keep a set of |\parbox|es as wide as the widest entry in the +% set\,\dots +% +% That simpler way is the \textsf{eqparbox} package. \textsf{eqparbox} +% exports a macro, |\eqparbox|, which works just like |\parbox|, except +% that instead of specifying the width of the box, one specifies the +% group that the box belongs to. All boxes in the same group will be +% typeset as wide as the widest member of the group. In that sense, an +% |\eqparbox| behaves like a cell in an~|l|, |c|, or~|r| column in a +% |tabular|; |\eqparbox|es in the same group are analogous to +% cells in the same column. +% +% \section{Usage} +% +% \DescribeMacro{\eqparbox} +% The primary macro in the \textsf{eqparbox} package is |\eqparbox|. +% Usage is almost identical to that of |\parbox|: +% +% \begin{center} +% |\eqparbox| \oarg{pos} \oarg{height} \oarg{inner-pos} +% \marg{tag} \marg{text} +% \end{center} +% +% \noindent +% The only difference is that, where |\parbox| has its \meta{width} +% argument, |\eqparbox| has \meta{tag}. (For a description of the +% remaining arguments, look up |\parbox| in any \LaTeXe\ book or in +% the \texttt{usrguide.tex} file that comes with \LaTeXe.) \meta{tag} +% can be any valid identifier. All |\eqparbox|es with the same tag +% will be typeset in a box wide enough to hold the widest of them. +% Discounting \TeX's limitations, any number of tags can be used in the +% same document, and any number of |\eqparbox|es can share a tag. +% +% The only catch is that \texttt{latex} will need to be run a second +% time for the various box widths to stabilize. +% +% \bigskip +% +% \DescribeMacro{\eqboxwidth} +% It is sometimes useful to take the width of an |\eqparbox| to use in +% other \LaTeX{} commands. While the width can be determined by +% creating an |\eqparbox| and using |\settowidth| to measure it, the +% \textsf{eqparbox} package defines a convenience routine called +% |\eqboxwidth| that achieves the same result. +% +% |\eqboxwidth| makes it easy to typeset something like +% Table~\ref{tbl:mixed-tabular}. Table~\ref{tbl:mixed-tabular}'s only +% column expands to fit the widest cell in the column, excluding the +% final cell. The final cell's text word-wraps within whatever space is +% allocated to it. In a sense, the first four cells behave as if they were +% typeset in an~|l| column, while the final cell behaves as if it were +% typeset in a~|p| column. In actuality, the column is an~|l| column; +% an |\eqparbox| for the first four cells ensures the column stretches +% appropriately, while a |\parbox| of width |\eqboxwidth{|\meta{tag}|}| +% in the final cell ensures that the final cell word-wraps. +% +% \begin{table} +% \centering +% \caption{A \texttt{tabular} that stretches to fit some cells while +% forcing others to wrap} +% \label{tbl:mixed-tabular} +% \DeleteShortVerb{\|} +% \begin{tabular}{|@{}l@{}|} +% \hline +% \eqparbox[b]{wtab}{Wide} \\ \hline +% \eqparbox[b]{wtab}{Wider} \\ \hline +% \eqparbox[b]{wtab}{Wider than that} \\ \hline +% \eqparbox[b]{wtab}{This is a fairly wide cell} \\ \hline +% \parbox[b]{\eqboxwidth{wtab}}{\strut +% While this cell's text wraps, the previous cells (whose text +% doesn't wrap) determine the width of the column.} \\ \hline +% \end{tabular} +% \MakeShortVerb{\|} +% \end{table} +% +% \section{Examples} +% +% Figure~\ref{fig:resume-excerpt}'s headings were typeset with the +% following code: +% +% \begin{verbatim} +% \noindent% +% \eqparbox{place}{\textbf{Widgets, Inc.}} \hfill +% \eqparbox{title}{\textbf{Senior Widget Designer}} \hfill +% \eqparbox{dates}{\textbf{1/95--present}} +% \end{verbatim} +% \centerline{$\vdots$} +% \begin{verbatim} +% \noindent% +% \eqparbox{place}{\textbf{Thingamabobs, Ltd.}} \hfill +% \eqparbox{title}{\textbf{Lead Engineer}} \hfill +% \eqparbox{dates}{\textbf{9/92--12/94}} +% \end{verbatim} +% \centerline{$\vdots$} +% \bigskip +% +% \noindent +% Table~\ref{tbl:sales-data} was entered as follows: +% +% \begin{verbatim} +% \begin{tabular}{@{}lccc@{}} \hline +% & \multicolumn{3}{c}{Sales (in millions)} \\ \cline{2-4} +% \multicolumn{1}{c}{\raisebox{1ex}[2ex]{Product}} & +% October & November & December \\ \hline +% +% Widgets & \eqparbox{oct}{\raggedleft 55.2 } & +% \eqparbox{nov}{\raggedleft\textbf{ 89.2}} & +% \eqparbox{dec}{\raggedleft 57.9 } \\ +% Doohickeys & \eqparbox{oct}{\raggedleft\textbf{ 65.0}} & +% \eqparbox{nov}{\raggedleft 64.1 } & +% \eqparbox{dec}{\raggedleft 9.3 } \\ +% Thingamabobs & \eqparbox{oct}{\raggedleft 10.4 } & +% \eqparbox{nov}{\raggedleft 8.0 } & +% \eqparbox{dec}{\raggedleft\textbf{109.7}} \\ \hline +% \end{tabular} +% \end{verbatim} +% +% \noindent +% Note that the above can be simplified by defining a macro that +% combines |\eqparbox| and |\raggedleft|. Furthermore, because the +% numeric data being typeset are all approximately the same width, a +% single tag could reasonably replace |oct|, |nov|, and |dec|. As it +% stands, the code serves more as an illustration than as an optimal way +% to typeset Table~\ref{tbl:sales-data}. +% +% Finally, Table~\ref{tbl:mixed-tabular} was typeset using the +% following code: +% +% \begin{verbatim} +% \begin{tabular}{|@{}l@{}|} +% \hline +% \eqparbox[b]{wtab}{Wide} \\ \hline +% \eqparbox[b]{wtab}{Wider} \\ \hline +% \eqparbox[b]{wtab}{Wider than that} \\ \hline +% \eqparbox[b]{wtab}{This is a fairly wide cell} \\ \hline +% \parbox[b]{\eqboxwidth{wtab}}{\strut +% While this cell's text wraps, the previous cells (whose text +% doesn't wrap) determine the width of the column.} \\ \hline +% \end{tabular} +% \end{verbatim} +% +% As an additional example, consider the paragraphs depicted in +% Figure~\ref{fig:hang-indent}. We'd like the paragraph labels set on +% the left, as shown, but we'd also like to allow both intra-~and +% inter-paragraph page breaks. Of course, if the labels are made wider +% or narrower, we'd like the paragraph widths to adjust automatically. +% (Can any word processor do that, incidentally?) By using a custom +% |list| environment which typesets its labels with |\eqparbox|, this is +% fairly straightforward: +% +% \begin{figure}[tbp] ^^A NOT "here" (in case the default is changed) +% \rule{\linewidth}{1pt} +% \begin{list}{}{^^A +% \renewcommand{\makelabel}[1]{\eqparbox[b]{listlab}{#1}}^^A +% \setlength{\labelwidth}{\eqboxwidth{listlab}}^^A +% \setlength{\labelsep}{2em}^^A +% \setlength{\parsep}{2ex plus 2pt minus 1pt}^^A +% \setlength{\itemsep}{0pt}^^A +% \setlength{\leftmargin}{\labelwidth}^^A +% \addtolength{\leftmargin}{\labelsep}^^A +% \setlength{\rightmargin}{0pt}} +% +% \item[Stuff about me] I am great. Blah, blah, blah, blah, blah, +% blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, +% blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, +% blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, +% blah. +% +% \item[More stuff] I am wonderful. Blah, blah, blah, blah, blah, +% blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, +% blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, +% blah. +% +% Did I mention that blah, blah, blah, blah, blah, blah, blah, blah, +% blah, blah, blah, blah, blah, blah, blah? +% +% \item[The final exciting thing] I am fantastic. Blah, blah, blah, +% blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, +% blah, blah, blah, blah, blah, blah, blah, blah, blah. +% \end{list} +% \rule{\linewidth}{1pt} +% \caption{Paragraphs with hanging indentation} +% \label{fig:hang-indent} +% \end{figure} +% +% \begin{verbatim} +% \begin{list}{}{% +% \renewcommand{\makelabel}[1]{\eqparbox[b]{listlab}{#1}}% +% \setlength{\labelwidth}{\eqboxwidth{listlab}}% +% \setlength{\labelsep}{2em}% +% \setlength{\parsep}{2ex plus 2pt minus 1pt}% +% \setlength{\itemsep}{0pt}% +% \setlength{\leftmargin}{\labelwidth+\labelsep}% +% \setlength{\rightmargin}{0pt}} +% +% \item[Stuff about me] I am great. Blah, blah, blah, ... +% +% \item[More stuff] I am wonderful. Blah, blah, blah, ... +% +% \item[The final exciting thing] I am fantastic. Blah, +% blah, blah, ... +% \end{list} +% \end{verbatim} +% +% +% \section{Limitations} +% +% Unfortunately, |\eqparbox| has a number of limitations not exhibited +% by the original |\parbox| command. First, |\eqparbox| internally +% typesets the given text within a |tabular| environment---specifically, +% using ``|@{}l@{}|'' as the template---in order to determine the text's +% natural width. Consequently, commands not valid within such a +% |tabular| (e.g.,~list environments) are also not valid within the +% \meta{text} argument of |\eqparbox|. As a corollary, an |\eqparbox| +% can appear only where a |tabular| is also acceptable. +% +% A second limitation is that |\eqparbox| typesets its \meta{text} +% argument \emph{twice}: once within a |tabular| to determine the +% natural width and again within a parbox large enough to hold all text +% associated with tag \meta{tag}. This approach may cause unexpected +% results if \meta{text} is non-idempotent (i.e.,~has side +% effects). For example, if \meta{text} increments a counter, the +% counter will be incremented twice per invocation of |\eqparbox|. +% +% +% \StopEventually{^^A +% \section{Future Work} +% +% The following are some of the features people have requested I implement +% in \textsf{eqparbox}: +% +% \begin{itemize} +% \item Evalaute \texttt{\string\eqparbox}'s \meta{text} argument +% exactly once in case it contains side effects. Currently, +% \meta{text} is evaluated twice: once to determine its natural +% size and once to put it in a parbox of the width associated with +% the given tag. (Feature requested by Bernd Schandl.) +% +% \item Get \textsf{eqparbox} to work properly within an +% \textsf{algorithmic} environment. (Feature requested by Mike +% Shell.) +% +% \item Support pre-1999 \LaTeXe. (Feature requested by Mike Shell.) +% \end{itemize} +% +% One idea I've been toying with that may resolve the first two items in +% that list is to typeset \meta{text} within a parbox, then check +% \texttt{\string\badness} to see if the box was too small for +% \meta{text}. If not (i.e.,~the box was not overfull), then the +% initial parbox can be reused directly without needing to re-typeset +% \meta{text}. With this approach, \texttt{\string\eqparbox} will work +% anywhere \texttt{\string\parbox} works. Unfortunately, I don't know +% how to get at the \texttt{\string\badness} of the +% \texttt{\string\hbox}es that comprise the \texttt{\string\vbox} +% utilized by \texttt{\string\parbox}. If anyone has a suggestion, I'm +% all ears. +% +% \PrintChanges +% \PrintIndex +% } +% +% \section{Implementation} +% +% The one-sentence summary of the implementation is, ``As +% \textsf{eqparbox} goes along, it keeps track of the maximum width of +% each box type, and when it's finished, it writes those widths to +% the~|.aux| file for use on subsequent runs.'' If you're satisfied +% with that summary, then read no further. Otherwise, get ready to +% tackle the following annotated code listing. +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \begin{macro}{\eqp@tempdima} +% \begin{macro}{\eqp@tempdimb} +% Define a couple temporary \meta{dimen}s for use in a variety of locations. +% \begin{macrocode} +\newlength{\eqp@tempdima} \newlength{\eqp@tempdimb} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\eqp@taglist} +% Define a list of all of the tags we encountered in the author's document. +% \begin{macrocode} +\def\eqp@taglist{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifeqp@must@rerun} +% \begin{macro}{\eqp@must@reruntrue} +% \begin{macro}{\eqp@must@rerunfalse} +% If an |eqparbox| is wider than the maximum-width |eqparbox| with the +% same tag, we need to store the new maximum width and request that the +% user re-run |latex|. We use |\ifeqp@must@rerun| and |\eqp@must@reruntrue| +% to assist with this. +% \begin{macrocode} +\newif\ifeqp@must@rerun +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% At the |\end{document}|, for each tag \meta{tag} we see if +% |\eqp@next@|\meta{tag}, which was initialized to~|0.0pt|, is different +% from |\eqp@this@|\meta{tag}, which was initialized to the maximum box +% width from the previous run. If so, we issue an informational +% message. In any case, we initialize the next run's +% |\eqp@this@|\meta{tag} to |\eqp@next@|\meta{tag} and the next run's +% |\eqp@next@|\meta{tag} to |0pt|. +% \begin{macrocode} +\AtEndDocument{% + \begingroup +% \end{macrocode} +% \begin{macro}{\@elt} +% The |\eqp@taglist| list is of the form ``|\@elt| |{|\meta{tag$_1$}|}| +% |\@elt| |{|\meta{tag$_2$}|}|~\ldots''. We therefore locally define +% |\@elt| to take the name of a tag and perform all of the checking +% described above and then merely execute |\eqp@taglist|. +% \changes{v2.0}{2004/08/01}{Modified to allow numbers in tag names +% (suggested by Martin Vaeth)} +% \begin{macrocode} + \def\@elt#1{% + \eqp@tempdima\csname eqp@this@#1\endcsname\relax + \eqp@tempdimb\csname eqp@next@#1\endcsname\relax + \ifdim\eqp@tempdima=\eqp@tempdimb + \else + \@latex@warning@no@line{Rerun to correct the width of eqparbox `#1'}% + \fi + \immediate\write\@auxout{% + \string\expandafter\string\gdef\string\csname\space + eqp@this@#1\string\endcsname{% + \csname eqp@next@#1\endcsname + }% + ^^J% + \string\expandafter\string\gdef\string\csname\space + eqp@next@#1\string\endcsname{0pt}% + }% + }% + \eqp@taglist + \endgroup +% \end{macrocode} +% We output the generic ``rerun |latex|'' message if we encountered a +% tag that was not present on the previous run. (This is always the +% case on the first run or the first run after deleting the +% corresponding |.aux| file. +% \begin{macrocode} + \ifeqp@must@rerun + \@latex@warning@no@line{Rerun to correct eqparbox widths} + \fi +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\eqp@storefont} +% \begin{macro}{\eqp@restorefont} +% To find the natural width of a piece of text, we put it in a table and +% take the width of that. The problem is that font changes are not +% preserved across line breaks (table cells). We therefore define an +% |\eqp@storefont| macro which itself defines an |\eqp@restorefont| +% macro that restores the current font and font size to its current +% state. +% \begin{macrocode} +\newcommand*{\eqp@storefont}{% + \xdef\eqp@restorefont{% + \noexpand\usefont{\f@encoding}{\f@family}{\f@series}{\f@shape}% + \noexpand\fontsize{\f@size}{\f@baselineskip}% + \noexpand\selectfont + }% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% The following macro (|\eqp@settowidth|) requires the \textsf{array} +% package's ability to inject code into every cell. +% \begin{macrocode} +\RequirePackage{array} +% \end{macrocode} +% +% \begin{macro}{\eqp@settowidth} +% This macro is just like |\settowidth|, but it puts its argument in a +% |tabular|, which means that it can contain |\\|. We use the +% \textsf{array} package's ``|>|'' and ``|<|'' template parameters to +% inject an |\eqp@restorefont| at the start of every cell and an +% |\eqp@storefont| at the end of every cell. Doing so preserves fonts +% and font sizes across |\\| boundaries, just like |\parbox|. +% \changes{v2.0}{2004/08/01}{Modified to store and restore the font +% across \texttt{\string\string\string\\}~boundaries (suggested by +% Mike Shell)} +% \begin{macrocode} +\newcommand{\eqp@settowidth}[2]{% + \settowidth{#1}{{% + \eqp@storefont + \begin{tabular}{@{}>{\eqp@restorefont}l<{\eqp@storefont}@{}}% + #2% + \end{tabular}% + }}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\eqparbox} +% \begin{macro}{\eqparbox@i} +% \begin{macro}{\eqparbox@ii} +% We want |\eqparbox| to take the same arguments as |\parbox|, with the +% same default values for the optional arguments. The only difference +% in argument processing is that |\eqparbox| has a \meta{tag} argument +% where |\parbox| has \meta{width}. +% +% Because |\eqparbox| has more than one optional argument, we can't use +% a single function defined by |\DeclareRobustCommand|. Instead, we +% have to split |\eqparbox| into the following four macros: +% +% \begin{description} +% \item[\texttt{\string\eqparbox}] Takes zero or more optional arguments. +% First optional argument defaults to~|c|. Calls |\eqparbox@i|. +% +% \item[\texttt{\string\eqparbox@i}] Takes one or more optional arguments. +% Second optional argument defaults to~|\relax|. Calls |\eqparbox@ii|. +% +% \item[\texttt{\string\eqparbox@ii}] Takes two or more optional arguments. +% Third optional argument defaults to~|s| if either of the first two +% arguments is absent or to the first argument if both are present. +% Calls |\eqparbox@iii|. +% +% \item[\texttt{\string\eqparbox@iii}] Takes three optional arguments +% and two mandatory arguments. Does all the work for |\eqparbox|. +% \end{description} +% +% \noindent +% Note the direct correspondence between these macros and +% |ltboxes.dtx|'s |\parbox|, |\@iparbox|, |\@iiparbox|, and +% |\@iiiparbox| macros. +% \begin{macrocode} +\DeclareRobustCommand\eqparbox{% + \@ifnextchar[%] + {\eqparbox@i}% + {\eqparbox@iii[c][\relax][s]}% +} +\def\eqparbox@i[#1]{% + \@ifnextchar[%] + {\eqparbox@ii[#1]}% + {\eqparbox@iii[#1][\relax][s]}% +} +\def\eqparbox@ii[#1][#2]{% + \@ifnextchar[%] + {\eqparbox@iii[#1][#2]}% + {\eqparbox@iii[#1][#2][#1]}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\eqparbox@iii} +% The following function does all the real work for |\eqparbox|. It takes +% five parameters---\meta{pos}, \meta{height}, \meta{inner-pos}, +% \meta{tag}, and \meta{text}---and ensures that all boxes with the same +% tag will be as wide as the widest box with that tag. +% +% To keep track of box widths, |\eqparbox| makes use of two global +% variables for each tag: |\eqp@this@|\meta{tag} and +% |\eqp@next|\meta{tag}. |\eqp@this@|\meta{tag} is the maximum width +% ever seen for tag \meta{tag}, including in previous |latex| runs. +% |\eqp@next@|\meta{tag} works the same way but is always initialized +% to~|0.0pt|. It represents the maximum width to assume in +% \emph{subsequent} |latex| runs. It is needed to detect whether the +% dest text with tag \meta{tag} has been removed/shrunk. At the end of +% a run, \textsf{eqparbox} prepares the next run (via the~|.aux| file) +% to initialize |\eqp@this@|\meta{tag} to the final value of +% |\eqp@next@|\meta{tag}. +% \changes{v2.0}{2004/07/30}{Removed extraneous \texttt{\string\string\string\global}s +% (suggested by David Kastrup)} +% \begin{macrocode} +\def\eqparbox@iii[#1][#2][#3]#4#5{% + \eqp@settowidth{\eqp@tempdimb}{#5}% + \expandafter + \ifx\csname eqp@this@#4\endcsname\relax +% \end{macrocode} +% If we get here, then we've never encountered tag \meta{tag}, even in a +% previous |latex| run. We request that the user re-run |latex| This is +% not always necessary (e.g., when all uses of the |\eqparbox| with tag +% \meta{tag} are left-justified), but it's better to be safe than sorry. +% \begin{macrocode} + \global\eqp@must@reruntrue + \expandafter\xdef\csname eqp@this@#4\endcsname{\the\eqp@tempdimb}% + \expandafter\xdef\csname eqp@next@#4\endcsname{\the\eqp@tempdimb}% + \else +% \end{macrocode} +% If we get here, then we \emph{have} previously seen tag \meta{tag}. +% We just have to keep track of the maximum text width associated with +% it. +% \begin{macrocode} + \eqp@tempdima=\csname eqp@this@#4\endcsname\relax + \ifdim\eqp@tempdima<\eqp@tempdimb + \expandafter\xdef\csname eqp@this@#4\endcsname{\the\eqp@tempdimb}% + \global\eqp@must@reruntrue + \fi +% \end{macrocode} +% \begin{macrocode} + \eqp@tempdima=\csname eqp@next@#4\endcsname\relax + \ifdim\eqp@tempdima<\eqp@tempdimb + \expandafter\xdef\csname eqp@next@#4\endcsname{\the\eqp@tempdimb}% + \fi + \fi +% \end{macrocode} +% +% The first time we encounter tag \meta{tag} in the current document we +% ensure \LaTeX{} will notify the user if he needs to re-run |latex| on +% account of that tag. +% \begin{macrocode} + \@ifundefined{eqp@seen@#4}{% + \expandafter\gdef\csname eqp@seen@#4\endcsname{}% + \@cons\eqp@taglist{{#4}}% + }{}% +% \end{macrocode} +% +% Finally, we can call |\parbox|. We pass it \meta{pos}, \meta{height}, +% \meta{inner-pos}, and \meta{text} directly, and we pass it +% |\eqp@this@|\meta{tag} for its \meta{width} argument. +% \begin{macrocode} + \eqp@tempdima=\csname eqp@this@#4\endcsname\relax + \parbox[#1][#2][#3]{\eqp@tempdima}{#5}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\eqboxwidth} +% For the times that the user wants to make something other than a box +% match an |\eqparbox|'s width, we provide |\eqboxwidth|. |\eqboxwidth| +% returns the width of a box corresponding to a given tag. More +% precisely, if |\eqp@this@|\meta{tag} is defined, it's returned. +% Otherwise,~|0pt| is returned. +% \changes{v2.1}{2004/08/02}{Rewrote so as to be compatible with the +% \textsf{calc} package's \texttt{\string\string\string\setlength} +% command (problem initially reported by Gary L. Gray and narrowed +% down by Martin Vaeth)} +% \begin{macrocode} +\newcommand*{\eqboxwidth}[1]{% + \@ifundefined{eqp@this@#1}{0pt}{\csname eqp@this@#1\endcsname}% +} +% \end{macrocode} +% \end{macro} +% +% \DeleteShortVerb{\|} +% \MakeShortVerb{\!} +% \paragraph{Per-tag memory usage} +% The \textsf{eqparbox} package defines three macros for each unique +% tag: !\eqp@this@!\meta{tag}, !\eqp@next@!\meta{tag}, and +% !\eqp@seen@!\meta{tag}. Consequently, each unique tag subtracts three +% strings from \TeX's string pool and three multiletter control +% sequences from that pool. In addition, each unique tag \meta{tag} +% subtracts $|!\eqp@this@!| + |\meta{tag}| + |!\eqp@next@!| + +% |\meta{tag}| + |!\eqp@seen@!| + |\meta{tag}| = 27 + 3 \times +% |\meta{tag}|$ string characters from \TeX's pool of string characters. +% For example, a document that invokes !\eqparbox! with tags +% ``!hello!'' and ``!goodbye!'' will utilize $3 \times 2 = 6$ strings, +% $3 \times 2 = 6$ multiletter control sequences, and $(27 + 3 \times 5) +% + (27 + 3 \times 7) = 90$ \TeX{} string characters. +% \DeleteShortVerb{\!} +% \MakeShortVerb{\|} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \Finale +% diff --git a/Master/texmf-dist/source/latex/eqparbox/eqparbox.ins b/Master/texmf-dist/source/latex/eqparbox/eqparbox.ins new file mode 100644 index 00000000000..7fa1304eef1 --- /dev/null +++ b/Master/texmf-dist/source/latex/eqparbox/eqparbox.ins @@ -0,0 +1,55 @@ +%% +%% This file will generate fast loadable files and documentation +%% driver files from the doc files in this package when run through +%% LaTeX or TeX. +%% +%% Copyright (C) 2004 Scott Pakin <scott+eqp@pakin.org> +%% ------------------------------------------------------- +%% +%% This package may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.2 +%% 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.2 or later is part of all distributions of LaTeX +%% version 1999/12/01 or later. +%% +%% --------------- start of docstrip commands ------------------ +%% +\input docstrip + +\keepsilent + +\usedir{tex/latex/eqparbox} + +\preamble + +This is a generated file. + +Copyright (C) 2004 Scott Pakin <scott+eqp@pakin.org> +------------------------------------------------------- + +This package may be distributed and/or modified under the +conditions of the LaTeX Project Public License, either version 1.2 +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.2 or later is part of all distributions of LaTeX +version 1999/12/01 or later. + +\endpreamble + +\generate{\file{eqparbox.sty}{\from{eqparbox.dtx}{package}}} + +\Msg{***********************************************************} +\Msg{*} +\Msg{* To finish the installation, you have to move} +\Msg{* eqparbox.sty into a directory searched by TeX.} +\Msg{*} +\Msg{* To produce the documentation, run eqparbox.dtx} +\Msg{* through LaTeX.} +\Msg{*} +\Msg{* Happy TeXing!} +\Msg{***********************************************************} + +\endbatchfile |