summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/eqparbox
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/eqparbox
Initial commit
Diffstat (limited to 'macros/latex/contrib/eqparbox')
-rw-r--r--macros/latex/contrib/eqparbox/README54
-rw-r--r--macros/latex/contrib/eqparbox/eqparbox.dtx1650
-rw-r--r--macros/latex/contrib/eqparbox/eqparbox.ins55
-rw-r--r--macros/latex/contrib/eqparbox/eqparbox.pdfbin0 -> 223922 bytes
4 files changed, 1759 insertions, 0 deletions
diff --git a/macros/latex/contrib/eqparbox/README b/macros/latex/contrib/eqparbox/README
new file mode 100644
index 0000000000..a9ca8083ad
--- /dev/null
+++ b/macros/latex/contrib/eqparbox/README
@@ -0,0 +1,54 @@
+ +-------------------------------------+
+ | EQPARBOX: |
+ | Create equal-widthed boxes |
+ | By Scott Pakin, scott+eqp@pakin.org |
+ +-------------------------------------+
+
+
+Description
+-----------
+
+LaTeX users sometimes need to ensure that two or more blocks of text
+occupy the same horizontal space on the page. To that end, the
+eqparbox package defines \eqparbox, \eqmakebox, \eqframebox, and
+\eqsavebox macros and an eqminipage environment. These work,
+respectively, just like the \parbox, \makebox, \framebox, and \savebox
+macros and the minipage environment, except that instead of specifying
+a width, one specifies a tag. All boxes with the same tag --
+regardless of where they are in the document -- will stretch to fit
+the widest box that uses that tag. This simple, equal-width mechanism
+can be used for a variety of alignment purposes, as is evidenced by
+the examples in eqparbox's documentation.
+
+
+Installation
+------------
+
+There's nothing special about building eqparbox:
+
+ latex eqparbox.ins <== Generate eqparbox.sty
+ latex eqparbox.dtx <== Produce the documentation (eqparbox.dvi)
+ latex eqparbox.dtx <== Again, to get labels and eqparboxes right
+ makeindex -s gind.ist eqparbox <== Generate an index
+ makeindex -s gglo.ist eqparbox.glo -o eqparbox.gls <== Generate a change list
+ latex eqparbox.dtx <== Incorporate the index into the document
+
+If you're new to this, see
+http://www.tex.ac.uk/cgi-bin/texfaq2html?label=instpackages for more
+information on installing packages.
+
+
+Copyright and license
+---------------------
+
+Copyright (C) 2017 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.3c 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.3c or later is part of all distributions of LaTeX version
+2008/05/04 or later.
diff --git a/macros/latex/contrib/eqparbox/eqparbox.dtx b/macros/latex/contrib/eqparbox/eqparbox.dtx
new file mode 100644
index 0000000000..b8987df56f
--- /dev/null
+++ b/macros/latex/contrib/eqparbox/eqparbox.dtx
@@ -0,0 +1,1650 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2017 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.3c
+% 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.3c or later is part of all distributions of LaTeX
+% version 2008/05/04 or later.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\ProvidesFile{eqparbox.dtx}
+%</driver>
+%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package>\ProvidesPackage{eqparbox}
+%<*package>
+ [2017/09/03 v4.1 Create equal-widthed boxes]
+%</package>
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{eqparbox}
+\usepackage{calligra}
+\usepackage{array}
+\usepackage{boxedminipage}
+\usepackage{needspace}
+\usepackage{ifmtarg}
+\usepackage[subrefformat=parens,labelformat=parens]{subfig}
+\usepackage[bookmarksopen]{hyperref}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+
+% Uncomment the following line if you don't want to include a
+% source-code listing.
+%\OnlyDescription
+
+\begin{document}
+ \sloppy
+ \DocInput{eqparbox.dtx}
+ \Needspace{10\baselineskip}
+ \phantomsection\addcontentsline{toc}{section}{Change History}
+ \PrintChanges
+ \makeatletter
+ \let\orig@index@prologue=\index@prologue
+ \def\index@prologue{%
+ \phantomsection\addcontentsline{toc}{section}{Index}
+ \orig@index@prologue
+ }%
+ \makeatother
+ \Needspace{12\baselineskip}
+ \PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% \CheckSum{536}
+%
+% \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 \~}
+%
+% \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)}
+%
+% \GetFileInfo{eqparbox.dtx}
+%
+% \DoNotIndex{\@auxout,\@cons,\@ifnextchar,\@ifundefined,\@ne,\@tempboxa}
+% \DoNotIndex{\@tempdima,\DeclareRobustCommand,\\,\advance,\begin}
+% \DoNotIndex{\begingroup,\bgroup,\box,\csname,\def,\egroup,\else,\end}
+% \DoNotIndex{\endcsname,\endgroup,\expandafter,\fi,\gdef,\global,\hbox}
+% \DoNotIndex{\ifdim,\ifnum,\ifx,\immediate,\let,\long,\m@ne,\mbox}
+% \DoNotIndex{\newcommand,\newdimen,\newif,\newlength,\noexpand,\relax}
+% \DoNotIndex{\renewcommand,\renewenvironment,\romannumeral,\sbox,\setbox}
+% \DoNotIndex{\space,\string,\the,\wd,\xdef,\z@}
+%
+% ^^A The following environment, which typesets a declaration of a command
+% ^^A in a box set out into the margin, was copied almost verbatim from
+% ^^A ltxguide.cls.
+% \newenvironment{decl}[1][]^^A
+% {\par\small\addvspace{4.5ex plus 1ex}^^A
+% \vskip -\parskip
+% \ifx\relax#1\relax
+% \def\@decl@date{}^^A
+% \else
+% \def\@decl@date{\NEWfeature{#1}}^^A
+% \fi
+% \noindent\hspace{-\leftmargini}^^A
+% \begin{tabular}{|l|}\hline\ignorespaces}^^A
+% {\\\hline\end{tabular}\nobreak\@decl@date\par\nobreak
+% \vspace{2.3ex}\vskip -\parskip}
+%
+% ^^A Define a style for typesetting package names.
+% \DeclareRobustCommand{\pkgname}[1]{^^A
+% \textsf{#1}\index{#1=\textsf{#1} (package)}}
+%
+% ^^A Give LaTeX some more leeway in placing floats
+% ^^A (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}
+%
+% ^^A Because we put table captions *above* tables, we should add a
+% ^^A little extra space between the caption and the table.
+% \setlength{\belowcaptionskip}{2ex}
+%
+% ^^A Properly hyphenate Rob Verhoeven's name.
+% \hyphenation{Ver-hoe-ven}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% \title{The \pkgname{eqparbox} package\thanks{This document
+% corresponds to \pkgname{eqparbox}~\fileversion, dated \filedate.}}
+% \author{Scott Pakin \\ \textit{scott+eqp@pakin.org}}
+% \hypersetup{^^A
+% pdftitle={The eqparbox package},
+% pdfauthor={Scott Pakin <scott+eqp@pakin.org>},
+% pdfsubject={LaTeX package for typesetting text in equal-widthed boxes},
+% pdfkeywords={LaTeX2e, parbox, makebox, framebox, savebox, boxes, automatic width, largest}
+% }
+%
+% \maketitle
+%
+% \begin{abstract}
+% The \pkgname{eqparbox} package makes it easy to define a group of
+% boxes (such as those produced by |\parbox| or |\makebox|) 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}
+% \label{sec:motivation}
+%
+% Let's start with a little test. How would you typeset
+% Figure~\ref{fig:quotations}, in which the names of the quotations'
+% authors are left-justified relative to each other but as a group abut
+% the right margin? 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 header columns should be evenly spaced across the page.
+% \item Page breaks should be allowed within the r\'esum\'e.
+% \end{enumerate}
+%
+% \begin{figure}[htbp]
+% \centering
+% \makeatletter
+% \newcommand{\showquote}[2]{^^A
+% \begin{flushright}
+% ---~\eqparbox{quotebox}{\sffamily#1}^^A
+% \@ifnotmtarg{#2}{\\
+% \mbox{}\phantom{---}~\eqparbox{quotebox}{\sffamily\itshape#2}^^A
+% }^^A
+% \end{flushright}^^A
+% \par
+% }
+% \makeatother
+% \begin{boxedminipage}{\linewidth}
+% The only medicine for suffering, crime, and all other woes of mankind,
+% is wisdom. Teach a man to read and write, and you have put into his
+% hands the great keys of the wisdom box. But it is quite another thing
+% to open the box.
+% \showquote{Thomas Huxley}{}
+%
+% I would like a simple life \\
+% yet all night I am laying \\
+% poems away in a long box. \par
+% \bigskip
+% It is my immortality box, \\
+% my lay-away plan, \\
+% my coffin.
+% \showquote{Anne Sexton}{The Ambition Bird}
+%
+% \bigskip
+%
+% We have four boxes with which to defend our freedom: the soap box, the
+% ballot box, the jury box, and the cartridge box.
+% \showquote{Larry McDonald}{}
+%
+% \bigskip
+%
+% I saw the Count lying within the box upon the earth, some of which the
+% rude falling from the cart had scattered over him. He was deathly
+% pale, just like a waxen image, and the red eyes glared with the
+% horrible vindictive look which I knew so well.
+% \showquote{Bram Stoker}{Dracula}
+%
+% \bigskip
+%
+% Life in a box is better than no life at all, I expect. You'd
+% have a chance, at least. You could lie there thinking, ``Well,
+% at least I'm not dead.''
+% \showquote{Tom Stoppard}{Rosencrantz~\& Guildenstern Are Dead}
+%
+% \bigskip
+%
+% Alla fin del gioco tanto va nel sacco il re quanto la pedina. \\
+% \textit{(After the game, the king and pawn go into the same box.)}
+% \showquote{Italian proverb}{}
+% \end{boxedminipage}
+% \caption{Quotations with left-aligned attributions}
+% \label{fig:quotations}
+% \end{figure}
+%
+% \begin{figure}[htbp]
+% \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 author names in
+% Figure~\ref{fig:quotations} are placed within a |flushright|
+% environment and in |\parbox|es as wide as the widest text
+% (``Rosencrantz~\& Guildenstern Are Dead''), they will appear as
+% desired. 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.
+% Considering for now just Figure~\ref{fig:resume-excerpt}, 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 \pkgname{eqparbox} package.
+% \pkgname{eqparbox} exports an |\eqparbox| macro that 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. Unlike the cells in a |tabular| column,
+% however, a group of |\eqparbox|es can be spread throughout the
+% document.
+%
+% \section{Usage}
+% \label{sec:usage}
+%
+% \begin{decl}
+% |\eqparbox| \oarg{pos} \oarg{height} \oarg{inner-pos} \marg{tag} \marg{text} \\
+% |\eqmakebox| \oarg{tag} \oarg{pos} \marg{text} \\
+% |\eqframebox| \oarg{tag} \oarg{pos} \marg{text} \\
+% |\eqsavebox| \marg{cmd} \oarg{tag} \oarg{pos} \marg{text} \\[1ex]
+% |\begin{eqminipage}| \oarg{pos} \oarg{height} \oarg{inner-pos} \marg{tag} \\
+% \quad \meta{text} \\
+% |\end{eqminipage}|
+% \end{decl}
+%
+% These are almost identical to, respectively, the |\parbox|,
+% |\makebox|, |\framebox|, and |\savebox| macros and the |minipage|
+% environment. The key difference is that the \meta{width} argument is
+% replaced by a \meta{tag} argument. (For a description of the
+% remaining arguments, look up |\parbox|, |\makebox|, |\framebox|,
+% |\savebox|, and |minipage| in any \LaTeXe\ book or in the
+% \texttt{usrguide.pdf} file that comes with all \TeX\ distributions.)
+% \meta{tag} can be any valid identifier. All boxes produced using the
+% same tag are 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 boxes 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.
+%
+% \begin{decl}
+% |\eqboxwidth| \marg{tag}
+% \end{decl}
+%
+% It is sometimes useful to take the width of a box produced by one of
+% the preceding commands. While the width can be determined by creating
+% an |\eqparbox| and using |\settowidth| to measure it, the
+% \pkgname{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.
+%
+% Section~\ref{sec:tabular-l-p} presents a more general version of this
+% approach that doesn't require cells to be divided explicitly into
+% |\eqparbox| cells and |\parbox| cells.
+%
+% \begin{table}[htbp]
+% \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}
+%
+% \begin{decl}
+% |\eqsetminwidth| \marg{tag} \marg{width} \\
+% |\eqsetmaxwidth| \marg{tag} \marg{width}
+% \end{decl}
+%
+% These macros override the width calculation for boxes associated with
+% tag \meta{tag}, ensuring that they are no narrower than a given
+% minimum (|\eqsetminwidth|) and no wider than a given maximum
+% (|\eqsetmaxwidth|).
+%
+% \begin{decl}
+% |\eqsetminwidthto| \marg{tag} \marg{text} \\
+% |\eqsetmaxwidthto| \marg{tag} \marg{text}
+% \end{decl}
+%
+% These macros are analogous to |\eqsetminwidth| and |\eqsetmaxwidth|
+% but automatically compute the natural width of the given text and use
+% that as the minimum (|\eqsetminwidthto|) or maximum
+% (|\eqsetmaxwidthto|) width for boxes using tag \meta{tag}.
+%
+%
+% \section{Examples}
+% \label{sec:examples}
+%
+% This section presents some sample uses of the macros described in
+% Section~\ref{sec:usage}.
+%
+% \subsection{Figures and tables from previous sections}
+% \label{sec:prev-figs-tabs}
+%
+% Figure~\ref{fig:quotations} was typeset using an |\eqparbox|-based
+% helper macro, |\showquote|:
+%
+% \begin{verbatim}
+% \usepackage{ifmtarg}
+% \makeatletter
+% \newcommand{\showquote}[2]{%
+% \begin{flushright}
+% ---~\eqparbox{quotebox}{\sffamily#1}%
+% \@ifnotmtarg{#2}{\\
+% \mbox{}\phantom{---}~\eqparbox{quotebox}{\sffamily\itshape#2}%
+% }%
+% \end{flushright}%
+% \par
+% }
+% \makeatother
+% \end{verbatim}
+% \centerline{$\vdots$}
+% \begin{verbatim}
+% Alla fin del gioco tanto va nel sacco il re quanto la pedina. \\
+% \textit{(After the game, the king and pawn go into the same box.)}
+% \showquote{Italian proverb}{}
+% \end{verbatim}
+%
+% 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
+%
+% 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}
+%
+% \subsection{Lists within \texttt{tabular}s}
+% \label{sec:lists-tabulars}
+%
+% List environments (|itemize|, |enumerate|, etc.) cannot appear
+% directly within a |tabular| cell. Instead, they must be wrapped
+% within a |\parbox|. The problem is that the |\parbox| width must be
+% specified; it can't be determined automatically. Fortunately, as of
+% version~4.0 of \pkgname{eqparbox}, the |\eqparbox| macro can contain
+% list environments, and these are automatically sized to their widest
+% item, just like any other |\eqparbox| contents.
+% Table~\ref{tbl:lists-tabular} presents an example of |enumerate| lists
+% appearing within |tabular| cells. The code for this is
+% straightforward, thanks to \pkgname{eqparbox}:
+%
+% \begin{table}[tbp]
+% \centering
+% \caption{Lists within a \texttt{tabular}}
+% \label{tbl:lists-tabular}
+% \begin{tabular}{c|c}
+% \textbf{Meeting date} & \textbf{Topics discussed} \\
+% \hline
+% 2017-02-22
+% & \eqparbox{topiclist}{^^A
+% \begin{enumerate}
+% \item Hardware upgrades
+% \item Barbara's retirement
+% \item Revised 27B/6 paperwork
+% \end{enumerate}
+% }^^A
+% \\ \hline
+% 2017-03-01
+% & \eqparbox{topiclist}{^^A
+% \begin{enumerate}
+% \item Printer low on toner
+% \item Message from the V.P.
+% \end{enumerate}
+% }^^A
+% \\ \hline
+% 2017-03-08
+% & \eqparbox{topiclist}{^^A
+% \begin{enumerate}
+% \item Product to ship next week
+% \item Floors to be recarpeted
+% \item Too many meetings
+% \end{enumerate}
+% }^^A
+% \end{tabular}
+% \end{table}
+%
+% \begin{verbatim}
+% 2017-02-22 & \eqparbox{topiclist}{%
+% \begin{enumerate}
+% \item Hardware upgrades
+% \item Barbara's retirement
+% \item Revised 27B/6 paperwork
+% \end{enumerate}
+% } \\ \hline
+% \end{verbatim}
+%
+% \subsection{Hanging indentation}
+% \label{sec:hang-indent}
+%
+% 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. By using a custom |list|
+% environment that typesets its labels with |\eqparbox| this is fairly
+% straightforward:
+%
+% \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}
+%
+% \begin{figure}[htbp]
+% \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}
+%
+% \subsection{Justified, parallel text}
+% \label{sec:parallel-text}
+%
+% Consider line-by-line transcription of a piece of text as illustrated
+% by the mockup in Figure~\ref{fig:line-by-line}. The idea is to
+% juxtapose a scanned piece of handwritten text with its typeset version
+% (or, similarly, to typeset a piece of text in one language alongside a
+% line-by-line translation into another language). The challenge is in
+% ensuring that (1)~the same words appear on corresponding lines of text
+% and that (2)~the typeset text is fully justified. While the
+% \pkgname{parallel} package can typeset fully justified paragraphs
+% aligned in parallel columns, it does not support the alignment of
+% individual lines. |tabular| and |minipage| environments provide
+% control of line breaks but do not support full justification of the
+% text when explicit line breaks are used.
+%
+% \begin{figure}[htbp]
+% \centering
+% \DeleteShortVerb{\|}
+% \newsavebox{\tstretchbox}
+% \newcolumntype{S}[1]{^^A
+% >{\begin{lrbox}{\tstretchbox}}^^A
+% l^^A
+% <{\end{lrbox}^^A
+% \eqmakebox[#1][s]{\unhcopy\tstretchbox}}}
+% \begin{tabular}{|l|l|}
+% \hline
+% \calligra
+% \begin{tabular}{S{handwritten}}
+% Lorem ipsum dolor sit amet, \\
+% consectetur adipiscing elit. \\
+% Phasellus volutpat, nibh sit \\
+% amet mattis convallis, metus \\
+% libero rhoncus justo, sed auctor \\
+% erat mauris sit amet tellus. \\
+% \end{tabular}
+% &
+% \begin{tabular}{S{typeset}}
+% Lorem ipsum dolor sit amet, \\
+% consectetur adipiscing elit. \\
+% Phasellus volutpat, nibh sit \\
+% amet mattis convallis, metus \\
+% libero rhoncus justo, sed auctor \\
+% erat mauris sit amet tellus. \\
+% \end{tabular} \\
+% \hline
+% \end{tabular}
+% \MakeShortVerb{\|}
+% \caption{Line-by-line transcription of text with full justification}
+% \label{fig:line-by-line}
+% \end{figure}
+%
+% One solution is to use \pkgname{eqparbox}'s |\eqmakebox| macro. Like
+% |\makebox|, |\eqmakebox| supports the ``|s|'' (stretch) value for the
+% \meta{pos} argument, which causes the \meta{text} argument to stretch
+% to the width of the box. However, while |\makebox| requires the width
+% to be specified explicitly, |\eqmakebox| automatically sizes all boxes
+% that use the same tag (in this case, each line of the input paragraph)
+% to the widest text's natural width. Here's how to use the
+% \pkgname{array} package's |\newcolumntype| macro to define a new
+% |tabular| column type, ``|S|'', that stretches whitespace as needed to
+% fit the widest line in the column:
+%
+% \begin{verbatim}
+% \newsavebox{\tstretchbox}
+% \newcolumntype{S}[1]{%
+% >{\begin{lrbox}{\tstretchbox}}%
+% l%
+% <{\end{lrbox}%
+% \eqmakebox[#1][s]{\unhcopy\tstretchbox}}}
+% \end{verbatim}
+%
+% \noindent
+% That code works by storing the current cell's contents within a box
+% called |\tstretchbox| then passing |\tstretchbox|'s contents to
+% |\eqmakebox|. (The |tabular| environment does not enable a cell's
+% contents to be passed directly to a macro, hence the |lrbox|
+% trickery.) Note that the ``|S|'' column type takes an argument, which
+% is the tag to pass to |\eqmakebox|. Using the preceding definition we
+% can typeset Figure~\ref{fig:line-by-line} as follows. To simulate
+% scanned handwriting in the left column we use the Calligra handwriting
+% font provided by the \pkgname{calligra} package.
+%
+% \begin{verbatim}
+% \begin{tabular}{|l|l|}
+% \hline
+% \calligra
+% \begin{tabular}{S{handwritten}}
+% Lorem ipsum dolor sit amet, \\
+% consectetur adipiscing elit. \\
+% Phasellus volutpat, nibh sit \\
+% amet mattis convallis, metus \\
+% libero rhoncus justo, sed auctor \\
+% erat mauris sit amet tellus. \\
+% \end{tabular}
+% &
+% \begin{tabular}{S{typeset}}
+% Lorem ipsum dolor sit amet, \\
+% consectetur adipiscing elit. \\
+% Phasellus volutpat, nibh sit \\
+% amet mattis convallis, metus \\
+% libero rhoncus justo, sed auctor \\
+% erat mauris sit amet tellus. \\
+% \end{tabular} \\
+% \hline
+% \end{tabular}
+% \end{verbatim}
+%
+% \subsection{Combining \texttt{l} and \texttt{p} column properties in a \texttt{tabular}}
+% \label{sec:tabular-l-p}
+%
+% In a |tabular| environment, |l|~columns, which automatically fit the
+% column to its contents, are good for short pieces of text. Long
+% pieces of text are best set within a |p|~column, which wraps text
+% within a specified width. But which column type should you use to
+% typeset text whose width is unknown (e.g.,~if the text is generated
+% programmatically)? With the help of \pkgname{eqparbox}'s
+% |\eqsetmaxwidth| macro (and the \pkgname{array} package's
+% |\newcolumntype| macro), it is possible to define a column type that
+% behaves like~|l| for short pieces of text and like~|p| for long pieces
+% of text:
+%
+% \begin{verbatim}
+% \newcolumntype{M}[1]{%
+% >{\begin{lrbox}{\csname#1box\endcsname}}%
+% l%
+% <{\end{lrbox}%
+% \eqparbox[t]{#1}{\unhcopy\csname#1box\endcsname\strut}}%
+% }
+% \end{verbatim}
+%
+% This can then be used as follows to produce the output shown in
+% Figure~\subref*{fig:maxwd-narrow}:
+%
+% \begin{verbatim}
+% \eqsetmaxwidth{maybebig}{0.5\linewidth}
+% \newsavebox{\maybebigbox}
+% \begin{tabular}{|M{maybebig}|l|}
+% \hline
+% Very short & Good \\
+% A little bit longer & Okay \\
+% \end{tabular}
+% \end{verbatim}
+%
+% \noindent
+% Because the text in the first column is narrower than half the line
+% width, the column behaves like an |l|~column. Now observe what
+% happens if we add a long piece of text to the column:
+%
+% \begin{verbatim}
+% \eqsetmaxwidth{maybebig}{0.5\linewidth}
+% \newsavebox{\maybebigbox}
+% \begin{tabular}{|M{maybebig}|l|}
+% \hline
+% Very short & Good \\
+% A little bit longer & Okay \\
+% Almost certainly excessively long, even given the point we're
+% trying to make about box widths & Bad \\
+% \end{tabular}
+% \end{verbatim}
+%
+% \noindent
+% As Figure~\subref*{fig:maxwd-wide} shows, the first column now behaves
+% like a |p|~column, specifically |p{0.5\linewidth}|.
+%
+% \begin{figure}[htbp]
+% \centering
+% \subfloat[Output when the text is narrow\label{fig:maxwd-narrow}]{%
+% \begin{tabular}{|l|l|}
+% \hline
+% Very short & Good \\
+% A little bit longer & Okay \\
+% \hline
+% \end{tabular}%
+% }
+% \par
+% \subfloat[Output when the text is wide\label{fig:maxwd-wide}]{%
+% \begin{tabular}{|p{0.5\linewidth}|l|}
+% \hline
+% Very short & Good \\
+% A little bit longer & Okay \\
+% Almost certainly excessively long, even given the point we're
+% trying to make about box widths & Bad \\
+% \hline
+% \end{tabular}%
+% }
+% \caption{Combining the features of \texttt{l} and \texttt{p} columns}
+% \label{fig:maxwd}
+% \end{figure}
+%
+% \subsection{Centering a column of right-justified data}
+% \label{tbl:center-justified}
+%
+% The data in each of the Sales columns in Table~\ref{tbl:sales-data}
+% are centered relative to their column header. However, they are also
+% right-justified relative to each other. To achieve this effect we
+% simply need to put the data in each column in a right-justified box
+% using |\eqmakebox|\oarg{tag}|[r]|\marg{text} and center that:
+%
+% \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 & \eqmakebox[oct][r]{ 55.2} &
+% \eqmakebox[nov][r]{\bfseries 89.2} &
+% \eqmakebox[dec][r]{ 57.9} \\
+% Doohickeys & \eqmakebox[oct][r]{\bfseries 65.0} &
+% \eqmakebox[nov][r]{\tiny N/A} &
+% \eqmakebox[dec][r]{ 9.3} \\
+% Thingamabobs & \eqmakebox[oct][r]{ 10.4} &
+% \eqmakebox[nov][r]{ 8.0} &
+% \eqmakebox[dec][r]{\bfseries 109.7} \\ \hline
+% \end{tabular}
+% \end{verbatim}
+%
+% \begin{table}[htbp]
+% \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 & \eqmakebox[oct][r]{ 55.2} &
+% \eqmakebox[nov][r]{\bfseries 89.2} &
+% \eqmakebox[dec][r]{ 57.9} \\
+% Doohickeys & \eqmakebox[oct][r]{\bfseries 65.0} &
+% \eqmakebox[nov][r]{\tiny N/A} &
+% \eqmakebox[dec][r]{ 9.3} \\
+% Thingamabobs & \eqmakebox[oct][r]{ 10.4} &
+% \eqmakebox[nov][r]{ 8.0} &
+% \eqmakebox[dec][r]{\bfseries 109.7} \\ \hline
+% \end{tabular}
+% \end{table}
+%
+%
+% \section{Limitations}
+% \label{sec:limitations}
+%
+% Unfortunately, \pkgname{eqparbox}'s macros have a number of
+% limitations not exhibited by the corresponding \LaTeXe\ commands.
+% First, \pkgname{eqparbox}'s macros internally typeset 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.,~|verbatim| environments) are also not valid within the
+% \meta{text} argument of an \pkgname{eqparbox} macro. As a corollary,
+% the macros defined by the \pkgname{eqparbox} package can appear only
+% where a |tabular| is also acceptable.
+%
+% A second limitation is that \pkgname{eqparbox}'s macros typeset their
+% \meta{text} argument \emph{twice}: once within a |tabular| to
+% determine the natural width and again within a box wide 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{}
+%
+% \section{Implementation}
+% \label{sec:implementation}
+%
+% The one-sentence summary of the implementation is, ``As
+% \pkgname{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.
+%
+% \subsection{Preliminaries}
+%
+% \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}
+%
+% The |\eqp@settowidth| macro requires the \pkgname{array} package's
+% ability to inject code into every cell.
+% \begin{macrocode}
+\RequirePackage{array}
+% \end{macrocode}
+%
+% \begin{macro}{\eqp@tabular@box}
+% \begin{macro}{\eqp@list@box}
+% The |\eqp@settowidth| macro requires a box, |\eqp@tabular@box|, in
+% which to store the entire input text. |\eqp@settowidth| also requires
+% a box, |\eqp@list@box|, in which to store nested |list| environments.
+% \begin{macrocode}
+\newsavebox{\eqp@tabular@box}
+\newsavebox{\eqp@list@box}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\eqp@list@indent}
+% The |\eqp@settowidth| macro stores the accumulated |list| indentation
+% in |\eqp@list@indent|.
+% \begin{macrocode}
+\newlength{\eqp@list@indent}
+% \end{macrocode}
+% \end{macro}
+%
+% The |eqminipage| environment requires the \pkgname{environ} package's
+% |\Collect@Body|, which passes the body of an environment to a macro as
+% a single argument.
+% \begin{macrocode}
+\RequirePackage{environ}
+% \end{macrocode}
+%
+%
+% \subsection{Width calculation}
+%
+% \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}
+%
+% \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
+% \pkgname{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|.
+%
+% One catch is that lists cannot be included directly within a
+% |tabular|. True, they can be placed within a |\parbox| that itself is
+% within a |tabular| cell, but the whole point is that we're trying to
+% calculate how wide that |\parbox| should be, The trick we use here,
+% therefore, is to redefine the |list| environment as a single-column
+% |tabular| plus space for |\labelwidth| and |\labelsep|---we ignore all
+% other list-formatting parameters---and |\item| as~|\\|. There will be
+% an extra row at the beginning, but all we care about here is computing
+% a width, not a height, so that's acceptable.
+% \changes{v2.0}{2004/08/01}{Modified to store and restore the font
+% across \texttt{\string\string\string\\}~boundaries (suggested by
+% Mike Shell)}
+% \changes{v4.0}{2013/03/09}{Added support for list environments}
+% \changes{v4.0}{2013/03/15}{Added support for multi-paragraph input}
+% \begin{macrocode}
+\newcommand{\eqp@settowidth}[2]{%
+ \begingroup
+ \global\setbox\eqp@tabular@box=\hbox{%
+% \end{macrocode}
+% \begin{macro}{\eqp@endings}
+% Unfortunately, we can't simply redefine the |list| environment, which
+% underlies |itemize|, |enumerate|, and |description| lists, because
+% their definitions in the standard classes do not include a proper
+% |\begin{list}|\dots\linebreak[0]|\end{list}|. Instead, those parent
+% environments call |\list| directly and
+% |\let\end|\{|itemize|,\linebreak[0]|enumerate|,\linebreak[0]|description|\}|=\endlist|.
+% Our workaround is to reissue those |\let| bindings after redefining
+% |\list| and |\endlist| ourselves.
+% \begin{macrocode}
+ \def\eqp@endings{}%
+ \ifx\enditemize\endlist
+ \g@addto@macro\eqp@endings{\let\enditemize=\endlist}%
+ \fi
+ \ifx\endenumerate\endlist
+ \g@addto@macro\eqp@endings{\let\endenumerate=\endlist}%
+ \fi
+ \ifx\enddescription\endlist
+ \g@addto@macro\eqp@endings{\let\enddescription=\endlist}%
+ \fi
+% \end{macrocode}
+% \begin{environment}{list}
+% As described above, we locally redefine the |list| environment as a
+% single-column |tabular| and the |\item| macro as~|\\|. We begin by
+% copying a block of code from |ltlists.dtx| that sets the default
+% formatting parameters for a list of the current depth. This is
+% important because |trivlist| environments (e.g.,~|center| and
+% |flushleft|) reset some of the parameters, which would otherwise screw
+% up our width calculation.
+% \begin{macrocode}
+ \renewenvironment{list}[2]{%
+ \ifnum \@listdepth >5\relax
+ \@toodeep
+ \else
+ \global\advance\@listdepth\@ne
+ \fi
+ \rightmargin\z@
+ \listparindent\z@
+ \itemindent\z@
+ \csname @list\romannumeral\the\@listdepth\endcsname
+ ##2\relax
+% \end{macrocode}
+% \begin{macro}{\item}
+% We locally redefine |\item| to start a new row of the |tabular|, then
+% flush any nested lists from the previous |\item| at the current
+% nesting level, and finally adjust the current indentation based on
+% the item's label.
+% \begin{macrocode}
+ \renewcommand*{\item}[1][]{%
+ \mbox{}\\
+ \box\eqp@list@box\mbox{} \\
+ \sbox\@tempboxa{\makelabel{####1}}%
+ \ifdim\wd\@tempboxa>\labelwidth
+ \advance\eqp@list@indent by -\labelwidth
+ \advance\eqp@list@indent by \wd\@tempboxa
+ \fi
+ \hspace*{\eqp@list@indent}%
+ }%
+% \end{macrocode}
+% To measure the width of a |list| we introduce a single-column
+% |tabular| that includes |\eqp@list@indent|'s worth of padding
+% ($=$~|\leftmargin|~$+$ |\rightmargin|~$+$ |\itemindent|)
+% to mimic the width of the original |list| environment.
+% \begin{macrocode}
+ \hspace*{-\eqp@list@indent}%
+ \advance\eqp@list@indent by \leftmargin
+ \advance\eqp@list@indent by \rightmargin
+ \advance\eqp@list@indent by \itemindent
+ \global\setbox\eqp@list@box=\hbox\bgroup
+ \begin{tabular}{@{}l@{}}%
+ }{%
+ \item[]%
+ \end{tabular}%
+ \egroup
+ \global\advance\@listdepth\m@ne
+ }%
+ \eqp@endings
+% \end{macrocode}
+% Finally, we place the given text---list or not---within a |tabular| so
+% the preceding |\settowidth| can measure its width. Because the text
+% may contain paragraph breaks we redefine |\par| as~|\\| to turn them
+% into line breaks and restore |\par|'s original definition when the
+% |tabular| ends.
+% \begin{macrocode}
+ \global\let\eqp@par=\par
+ \eqp@storefont
+ \begin{tabular}{@{}>{\eqp@restorefont}l<{\eqp@storefont}@{}}%
+ \global\@setpar{\\}%
+ #2%
+ \\ \box\eqp@list@box
+ \end{tabular}%
+ \global\@restorepar
+ }%
+ \endgroup
+% \end{macrocode}
+% Now that we've constructed a |tabular| with lines of the input text as
+% cells we can use \LaTeX's |\settowidth| macro to take its width.
+% \begin{macrocode}
+ \settowidth{#1}{\box\eqp@tabular@box}%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{environment}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\eqp@compute@width}
+% The following function does all the real work for the
+% \pkgname{eqparbox} package. It takes two parameters---\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. It ends by passing \meta{tag}
+% and \meta{text} to the |\eqp@produce@box| command, which was defined
+% by the calling macro to produce a box using one of the existing
+% \LaTeXe\ commands.
+%
+% To keep track of box widths, |\eqp@compute@width| 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
+% widest text with tag \meta{tag} has been removed/shrunk. At the end of
+% a run, \pkgname{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)}
+% \changes{v3.1}{2010/01/01}{Restructured the package to make all
+% user-callable functions eventually call
+% \texttt{\string\string\string\eqp@compute@width}, which does the
+% bulk of the work}
+% \begin{macrocode}
+\long\def\eqp@compute@width#1#2{%
+ \eqp@settowidth{\eqp@tempdimb}{#2}%
+% \end{macrocode}
+% We first clamp the box width, currently in |\eqp@tempdimb|, to the
+% range [|\eqp@minwd@|\meta{tag}, |\eqp@maxwd@|\meta{tag}]. As these
+% bounds are not necessarily defined we first have to check for their
+% existence.
+% \begin{macrocode}
+ \@ifundefined{eqp@minwd@#1}{}{%
+ \ifdim\eqp@tempdimb<\csname eqp@minwd@#1\endcsname
+ \eqp@tempdimb=\csname eqp@minwd@#1\endcsname
+ \fi
+ }%
+ \@ifundefined{eqp@maxwd@#1}{}{%
+ \ifdim\eqp@tempdimb>\csname eqp@maxwd@#1\endcsname
+ \eqp@tempdimb=\csname eqp@maxwd@#1\endcsname
+ \fi
+ }%
+ \expandafter
+ \ifx\csname eqp@this@#1\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@#1\endcsname{\the\eqp@tempdimb}%
+ \expandafter\xdef\csname eqp@next@#1\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@#1\endcsname\relax
+ \ifdim\eqp@tempdima<\eqp@tempdimb
+ \expandafter\xdef\csname eqp@this@#1\endcsname{\the\eqp@tempdimb}%
+ \global\eqp@must@reruntrue
+ \fi
+% \end{macrocode}
+% \begin{macrocode}
+ \eqp@tempdima=\csname eqp@next@#1\endcsname\relax
+ \ifdim\eqp@tempdima<\eqp@tempdimb
+ \expandafter\xdef\csname eqp@next@#1\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@#1}{%
+ \expandafter\gdef\csname eqp@seen@#1\endcsname{}%
+ \@cons\eqp@taglist{{#1}}%
+ }{}%
+% \end{macrocode}
+%
+% Finally, we can call |\eqp@produce@box|. We pass it
+% |\eqp@this@|\meta{tag} for its \meta{width} argument and |#2| for its
+% \meta{text} argument.
+% \begin{macrocode}
+ \eqp@tempdima=\csname eqp@this@#1\endcsname\relax
+ \eqp@produce@box{\eqp@tempdima}{#2}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqp@set@min@width}
+% Given a tag and a textual length, ensure that |\eqp@this@|\meta{tag}
+% represents a width of at least \meta{length}.
+% \changes{v4.1}{2017/09/03}{Introduced this helper macro for
+% \texttt{\string\string\string\eqsetminwidth} and
+% \texttt{\string\string\string\eqsetminwidthto}}
+% \begin{macrocode}
+\def\eqp@set@min@width#1#2{%
+ \expandafter\ifx\csname eqp@this@#1\endcsname\relax
+% \end{macrocode}
+% If we get here, then we've never encountered tag \meta{tag}, even in
+% a previous |latex| run. We assign a value to \meta{tag} and request
+% that the user re-run |latex|.
+% \begin{macrocode}
+ \global\eqp@must@reruntrue
+ \expandafter\xdef\csname eqp@this@#1\endcsname{#2}%
+ \expandafter\xdef\csname eqp@next@#1\endcsname{#2}%
+ \else
+% \end{macrocode}
+% If we get here, then we \emph{have} previously seen tag \meta{tag}.
+% We ensure its width is at least~|#2|.
+% \begin{macrocode}
+ \eqp@tempdima=\csname eqp@this@#1\endcsname\relax
+ \eqp@tempdimb=#2\relax
+ \ifdim\eqp@tempdima<\eqp@tempdimb
+ \expandafter\xdef\csname eqp@this@#1\endcsname{\the\eqp@tempdimb}%
+ \fi
+ \eqp@tempdima=\csname eqp@next@#1\endcsname\relax
+ \ifdim\eqp@tempdima<\eqp@tempdimb
+ \expandafter\xdef\csname eqp@next@#1\endcsname{\the\eqp@tempdimb}%
+ \fi
+ \fi
+ \@ifundefined{eqp@seen@#1}{%
+ \expandafter\gdef\csname eqp@seen@#1\endcsname{}%
+ \@cons\eqp@taglist{{#1}}%
+ }{}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Author macros}
+%
+% \begin{macro}{\eqparbox}
+% 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 |\eqparbox|, |\eqparbox@i|,
+% |\eqparbox@ii|, and |\eqparbox@iii| macros, which correspond to
+% |\parbox|, |\@iparbox|, |\@iiparbox|, and |\@iiiparbox| in
+% |ltboxes.dtx|.
+%
+% |\eqparbox| takes an optional \meta{pos} argument that defaults
+% to~|c|. It passes the value of this argument to |\eqparbox@i|.
+% \begin{macrocode}
+\DeclareRobustCommand{\eqparbox}{%
+ \@ifnextchar[%]
+ {\eqparbox@i}%
+ {\eqparbox@iii[c][\relax][s]}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqparbox@i}
+% |\eqparbox@i| takes a \meta{pos} argument followed by an optional
+% \meta{height} argument that defaults to~|\relax|. It passes both
+% \meta{pos} and \meta{height} to |\eqparbox@ii|.
+% \begin{macrocode}
+\def\eqparbox@i[#1]{%
+ \@ifnextchar[%]
+ {\eqparbox@ii[#1]}%
+ {\eqparbox@iii[#1][\relax][s]}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqparbox@ii}
+% |\eqparbox@ii| takes \meta{pos} and \meta{height} arguments followed
+% by an optional \meta{inner-pos} argument that defaults to \meta{pos}.
+% It passes \meta{pos}, \meta{height}, and \meta{inner-pos} to
+% |\eqparbox@iii|.
+% \begin{macrocode}
+\def\eqparbox@ii[#1][#2]{%
+ \@ifnextchar[%]
+ {\eqparbox@iii[#1][#2]}%
+ {\eqparbox@iii[#1][#2][#1]}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\eqparbox@iii}
+% \begin{macro}{\eqp@produce@box}
+% |\eqparbox@iii| takes \meta{pos}, \meta{height} and \meta{inner-pos}
+% arguments. It defines an |\eqp@produce@box| macro that takes a
+% \meta{width} argument and a \meta{text} argument and passes all of
+% \meta{pos}, \meta{height}, \meta{inner-pos}, \meta{width}, and
+% \meta{text} to \LaTeX's |\parbox| macro. |\eqparbox@iii| ends by
+% calling |\eqp@compute@width|, which will eventually invoke
+% |\eqp@produce@box|.
+% \begin{macrocode}
+\def\eqparbox@iii[#1][#2][#3]{%
+ \long\gdef\eqp@produce@box##1##2{%
+ \parbox[#1][#2][#3]{##1}{##2}%
+ }%
+ \eqp@compute@width
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{environment}{eqminipage}
+% The |eqminipage| environment is implemented almost exactly like the
+% |\eqparbox| macro above. Just like |\eqparbox|, |eqminipage| takes an
+% optional \meta{pos} argument that defaults to~|c|. It passes the
+% value of this argument to |\eqminipage@i|.
+% \changes{v4.0}{2013/03/14}{Introduced this environment}
+% \begin{macrocode}
+\DeclareRobustCommand{\eqminipage}{%
+ \@ifnextchar[%]
+ {\eqminipage@i}%
+ {\eqminipage@iii[c][\relax][s]}%
+}
+\let\endeqpminipage=\relax
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\eqminipage@i}
+% |\eqminipage@i| takes a \meta{pos} argument followed by an optional
+% \meta{height} argument that defaults to~|\relax|. It passes both
+% \meta{pos} and \meta{height} to |\eqminipage@ii|.
+% \begin{macrocode}
+\long\def\eqminipage@i[#1]{%
+ \@ifnextchar[%]
+ {\eqminipage@ii[#1]}%
+ {\eqminipage@iii[#1][\relax][s]}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqminipage@ii}
+% |\eqminipage@ii| takes \meta{pos} and \meta{height} arguments followed
+% by an optional \meta{inner-pos} argument that defaults to \meta{pos}.
+% It passes \meta{pos}, \meta{height}, and \meta{inner-pos} to
+% |\eqminipage@iii|.
+% \begin{macrocode}
+\def\eqminipage@ii[#1][#2]{%
+ \@ifnextchar[%]
+ {\eqminipage@iii[#1][#2]}%
+ {\eqminipage@iii[#1][#2][#1]}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\eqminipage@iii}
+% This is where |eqminipage| differs from |\eqparbox|. Like
+% |\eqparbox@iii|, |\eqminipage@iii| takes \meta{pos}, \meta{height} and
+% \meta{inner-pos} arguments. However, while |\eqparbox@iii| expects to
+% be followed by a tag and text, |\eqminipage@iii| consumes the tag
+% itself. |\eqminipage@iii| then uses \pkgname{environ}'s
+% |\Collect@Body| macro to collect everything up to the
+% |\end{eqminipage}| into a single argument, which it passes to
+% |\eqminipage@iv|.
+% \begin{macrocode}
+\def\eqminipage@iii[#1][#2][#3]#4{%
+% \end{macrocode}
+% \begin{macro}{\eqminipage@iv}
+% \begin{macro}{\eqp@produce@box}
+% This code is a bit confusing due to the definition of a macro within a
+% macro within a macro. |\eqminipage@iv|, which is invoked by
+% |\collect@body|, is passed the body of the |eqminipage| environment as
+% an argument. In then defines an |\eqp@produce@box| macro with the
+% parameter list that |\eqp@compute@width| expects: a width (|####1|)
+% and text (|####2|). |\eqp@produce@box| typesets a |minipage| with
+% that width and text and the formatting parameters provided to
+% |\eqminipage@iii| (|#1|, |#2|, and~|#3|). Finally, |\eqminipage@iv|
+% invokes |\eqp@compute@width| with the tag passed to |\eqminipage@iii|
+% as~|#4| and the text passed to |\eqminipage@iv| as~|##1|.
+% \begin{macrocode}
+ \long\def\eqminipage@iv##1{%
+ \long\gdef\eqp@produce@box####1####2{%
+ \begin{minipage}[#1][#2][#3]{####1}%
+ ####2%
+ \end{minipage}%
+ }%
+ \eqp@compute@width{#4}{##1}%
+ }%
+ \Collect@Body\eqminipage@iv
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\eqmakebox}
+% |\eqmakebox| provides an automatic-width analogue to \LaTeX's
+% |\makebox|. It takes the same arguments as |\makebox| with the same
+% default values for the optional arguments. The only difference in
+% argument processing is that |\eqmakebox| has a \meta{tag} argument
+% where |\makebox| has \meta{width}. Note that if \meta{width} is not
+% specified, |\eqmakebox| simply invokes |\makebox|.
+% \changes{v3.0}{2010/01/01}{Included Rob Verhoeven's
+% \texttt{\string\string\string\eqmakebox} macro}
+% \changes{v3.1}{2010/01/01}{Modified the argument processing to match
+% \texttt{\string\string\string\makebox}'s}
+% \begin{macrocode}
+\DeclareRobustCommand{\eqmakebox}{%
+ \@ifnextchar[%]
+ {\eqlrbox@i\makebox}%
+ {\makebox}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqframebox}
+% |\eqframebox| provides an automatic-width analogue to \LaTeX's
+% |\framebox|. It takes the same arguments as |\framebox| with the same
+% default values for the optional arguments. The only difference in
+% argument processing is that |\eqframebox| has a \meta{tag} argument
+% where |\framebox| has \meta{width}. Note that if \meta{width} is not
+% specified, |\eqframebox| simply invokes |\framebox|.
+% \changes{v3.1}{2010/01/01}{Introduced this macro}
+% \begin{macrocode}
+\DeclareRobustCommand{\eqframebox}{%
+ \@ifnextchar[%]
+ {\eqlrbox@i\framebox}%
+ {\framebox}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqsavebox}
+% |\eqsavebox| provides an automatic-width analogue to \LaTeX's
+% |\savebox|. It takes the same arguments as |\savebox| with the same
+% default values for the optional arguments. The only difference in
+% argument processing is that |\eqsavebox| has a \meta{tag} argument
+% where |\savebox| has \meta{width}. Note that if \meta{width} is not
+% specified, |\eqsavebox| simply invokes |\savebox|.
+% \changes{v3.1}{2010/01/01}{Introduced this macro}
+% \begin{macrocode}
+\DeclareRobustCommand{\eqsavebox}[1]{%
+ \@ifnextchar[%]
+ {\eqlrbox@i{\savebox{#1}}}%
+ {\savebox{#1}}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqlrbox@i}
+% |\eqlrbox@i| takes a \marg{command} argument (one of |\makebox|,
+% |\framebox|, or |\savebox|\marg{cmd}) and a \oarg{tag} argument and
+% checks if those arguments are followed by a \oarg{pos} argument. If
+% not, then \meta{pos} defaults to ``|c|''. All of \meta{command},
+% \meta{tag}, and \meta{pos} are passed to |\eqlrbox@ii|.
+% \begin{macrocode}
+\def\eqlrbox@i#1[#2]{%
+ \@ifnextchar[%]
+ {\eqlrbox@ii{#1}[#2]}%
+ {\eqlrbox@ii{#1}[#2][c]}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqlrbox@ii}
+% \begin{macro}{\eqp@produce@box}
+% |\eqlrbox@i| takes a \marg{command} argument (one of |\makebox|,
+% |\framebox|, or |\savebox|\marg{cmd}), a \oarg{tag} argument, and a
+% \oarg{pos} argument. It defines |\eqp@produce@box| to take a
+% \meta{width} argument and a \meta{text} argument and invoke
+% \meta{command}\oarg{width}\oarg{pos}\marg{text}. |\eqlrbox@ii| ends
+% by calling |\eqp@compute@width|, which will eventually invoke
+% |\eqp@produce@box|.
+% \begin{macrocode}
+\def\eqlrbox@ii#1[#2][#3]{%
+ \long\gdef\eqp@produce@box##1##2{%
+ #1[##1][#3]{##2}%
+ }%
+ \eqp@compute@width{#2}%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\eqboxwidth}
+% For the times that the user wants to make something other than a box to
+% 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
+% \pkgname{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}
+%
+% \begin{macro}{\eqsetminwidth}
+% The |\eqsetminwidth| macro accepts a tag and a length and records that
+% the user wants the associated box to be no narrower than the given
+% length.
+% \changes{v4.0}{2013/03/04}{Introduced this macro}
+% \changes{v4.1}{2017/09/03}{Define
+% \texttt{\string\string\string\eqp@this@}\meta{tag} and
+% \texttt{\string\string\string\eqp@next@}\meta{tag} appropriately}
+% \begin{macrocode}
+\newcommand{\eqsetminwidth}[2]{%
+ \@tempdima=#2\relax
+ \expandafter\xdef\csname eqp@minwd@#1\endcsname{\the\@tempdima}%
+ \eqp@set@min@width{#1}{\csname eqp@minwd@#1\endcsname}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqsetmaxwidth}
+% The |\eqsetmaxwidth| macro accepts a tag and a length and records that
+% the user wants the associated box to be no wider than the given
+% length.
+% \changes{v4.0}{2013/03/04}{Introduced this macro}
+% \begin{macrocode}
+\newcommand{\eqsetmaxwidth}[2]{%
+ \@tempdima=#2\relax
+ \expandafter\xdef\csname eqp@maxwd@#1\endcsname{\the\@tempdima}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqsetminwidthto}
+% The |\eqsetminwidthto| macro accepts a tag and a piece of text and
+% records that the user wants the associated box to be no narrower than
+% the text, typeset at its natural width.
+% \changes{v4.0}{2013/03/04}{Introduced this macro}
+% \changes{v4.1}{2017/09/03}{Define
+% \texttt{\string\string\string\eqp@this@}\meta{tag} and
+% \texttt{\string\string\string\eqp@next@}\meta{tag} appropriately}
+% \begin{macrocode}
+\newcommand{\eqsetminwidthto}[2]{%
+ \eqp@settowidth{\@tempdima}{#2}%
+ \expandafter\xdef\csname eqp@minwd@#1\endcsname{\the\@tempdima}%
+ \eqp@set@min@width{#1}{\csname eqp@minwd@#1\endcsname}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eqsetmaxwidthto}
+% The |\eqsetmaxwidthto| macro accepts a tag and a piece of text and
+% records that the user wants the associated box to be no wider than
+% the text, typeset at its natural width.
+% \changes{v4.0}{2013/03/04}{Introduced this macro}
+% \begin{macrocode}
+\newcommand{\eqsetmaxwidthto}[2]{%
+ \eqp@settowidth{\@tempdima}{#2}%
+ \expandafter\xdef\csname eqp@maxwd@#1\endcsname{\the\@tempdima}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{End-of-document processing}
+%
+% 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)}
+% \changes{v4.0}{2013/03/04}{Modified to honor minimum and maximum
+% text widths, as set by
+% \texttt{\string\string\string\eqset}\{\texttt{max},\texttt{min}\}\texttt{width} and
+% \texttt{\string\string\string\eqset}\{\texttt{max},\texttt{min}\}\texttt{widthto}}
+% \begin{macrocode}
+ \def\@elt#1{%
+% \end{macrocode}
+% Complain if the tag's minimum width is greater than its maximum width.
+% \begin{macrocode}
+ \@ifundefined{eqp@minwd@#1}{}{%
+ \@ifundefined{eqp@maxwd@#1}{}{%
+ \ifdim\csname eqp@minwd@#1\endcsname>\csname eqp@maxwd@#1\endcsname
+ \PackageWarning{eqparbox}{For tag `#1',
+ minimum width (\csname eqp@minwd@#1\endcsname) >
+ maximum width (\csname eqp@maxwd@#1\endcsname)}%
+ \fi
+ }%
+ }%
+% \end{macrocode}
+% Make the |.aux| file define |\eqp@this@|\meta{tag} to the current
+% value of |\eqp@next@|\meta{tag} and |\eqp@next@|\meta{tag} to |0pt|.
+% \begin{macrocode}
+ \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}%
+ }%
+% \end{macrocode}
+% Also make the |.aux| file define |\eqp@minwd@|\meta{tag} and
+% |\eqp@maxwd@|\meta{tag} to their current value, if any.
+% \begin{macrocode}
+ \@ifundefined{eqp@minwd@#1}{}{%
+ \immediate\write\@auxout{%
+ \string\expandafter\string\gdef\string\csname\space
+ eqp@minwd@#1\string\endcsname{%
+ \csname eqp@minwd@#1\endcsname
+ }%
+ }%
+ }%
+ \@ifundefined{eqp@maxwd@#1}{}{%
+ \immediate\write\@auxout{%
+ \string\expandafter\string\gdef\string\csname\space
+ eqp@maxwd@#1\string\endcsname{%
+ \csname eqp@maxwd@#1\endcsname
+ }%
+ }%
+ }%
+ }%
+ \eqp@taglist
+ \endgroup
+% \end{macrocode}
+% We output a 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}
+%
+% \Finale
+\endinput
diff --git a/macros/latex/contrib/eqparbox/eqparbox.ins b/macros/latex/contrib/eqparbox/eqparbox.ins
new file mode 100644
index 0000000000..2aa1fa6834
--- /dev/null
+++ b/macros/latex/contrib/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) 2017 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.3c
+%% 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.3c or later is part of all distributions of LaTeX
+%% version 2008/05/04 or later.
+%%
+%% --------------- start of docstrip commands ------------------
+%%
+\input docstrip
+
+\keepsilent
+
+\usedir{tex/latex/eqparbox}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2017 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.3c or later is part of all distributions of LaTeX
+version 2008/05/04 or later.
+
+\endpreamble
+
+\generate{\file{eqparbox.sty}{\from{eqparbox.dtx}{package}}}
+
+\obeyspaces
+\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
diff --git a/macros/latex/contrib/eqparbox/eqparbox.pdf b/macros/latex/contrib/eqparbox/eqparbox.pdf
new file mode 100644
index 0000000000..55e85d1e62
--- /dev/null
+++ b/macros/latex/contrib/eqparbox/eqparbox.pdf
Binary files differ