% \iffalse meta-comment % pbox.dtx - DocStrip source code for the pbox package % Copyright (C) 2003,2011 Simon Law % % This program is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program. If not, see <http://www.gnu.org/licenses/>. % % \fi % \iffalse %<style>\NeedsTeXFormat{LaTeX2e} %<style>\ProvidesPackage{pbox}[2011/12/07 v1.2 Dynamic parboxes] %<*driver> \NeedsTeXFormat{LaTeX2e}[1995/12/01] \documentclass{ltxdoc} \usepackage{pbox} \usepackage{url} \usepackage{textcomp} \usepackage{fancyvrb} \newlength{\ExampleWidth} \setlength{\ExampleWidth}{3.5cm} \fvset{gobble=6,numbersep=3pt,frame=single, numbers=left,xleftmargin=5mm,xrightmargin=0pt} \fvset{xrightmargin=\ExampleWidth} \EnableCrossrefs %\DisableCrossrefs % Say \DisableCrossrefs if index is ready \CodelineIndex \RecordChanges % Gather update information %\OnlyDescription % comment out for implementation details \OldMakeindex % use if your MakeIndex is pre-v2.9 %\setlength\hfuzz{15pt} % don't make so many %\hbadness=7000 % over and under full box warnings \begin{document} \DocInput{pbox.dtx} \end{document} %</driver> % \fi % % \StopEventually{\PrintIndex \PrintChanges} % \CheckSum{77} % % \DoNotIndex{\begin} % \DoNotIndex{\columnwidth} % \DoNotIndex{\DeclareRobustCommand,\def} % \DoNotIndex{\end,\equal} % \DoNotIndex{\ifthenelse} % \DoNotIndex{\lengthtest} % \DoNotIndex{\makebox} % \DoNotIndex{\newcommand,\newlength} % \DoNotIndex{\parbox} % \DoNotIndex{\relax,\RequirePackage} % \DoNotIndex{\setlength,\settowidth} % \setcounter{IndexColumns}{2} % % \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.1}{2011/11/24}{Switch to GPLv3.} % \changes{v1.0}{2003/03/19}{Initial release.} % % \GetFileInfo{pbox.sty} % % \title{The \textsf{pbox} package\thanks{Version \fileversion, % last revised \filedate}} % \author{Simon Law \\ \url{sfllaw@sfllaw.ca}} % \maketitle %^^A \tableofcontents % % \section{Introduction} % % Most skilled \LaTeX{} users are familiar with the various box % commands. These commands include |\makebox|, |\framebox|, |\savebox|, % and |\parbox|. These boxes takes a parameter that specifies the % width of box to create. To simplify matters, there are the |\mbox|, % |\fbox|, and |\sbox| commands that fit the box created to the size of % its contents. Conspicuously absent, however, is a |\pbox| command. % % \section{A variable-width \texttt{\textbackslash parbox}} % % At first glance, it seems quite inappropriate to create a |\pbox| % command. After all, the size of a multi-line box will most likely be % limited by the |\textwidth| or |\columnwidth| of the text it encloses. % When a line of text is too long, it will be wrapped by \TeX{}'s own % line-breaking algorithms. However, there are certain circumstances % where one would want a variable-width |\parbox|. % % For example, you may want to align the top and bottom lines of % multi-line boxes. The simplest way to do this is with |parbox| % commands with an arbitrary width. % \makeatletter % \begingroup\center % \begin{minipage}[c]{\ExampleWidth-5mm} % \parbox[b]{1.5cm}{Hello\\World!}^^A % \parbox[t]{1.5cm}{Bonjour\\monde!} % \end{minipage} % \begin{minipage}{\textwidth-\ExampleWidth} % \fvset{xrightmargin=0pt} % \begin{Verbatim} % \parbox[b]{1.5cm}{Hello\\World!}% % \parbox[t]{1.5cm}{Bonjour\\monde!} % \end{Verbatim} % \end{minipage} % \endcenter\endgroup % \makeatother % % \begin{DescribeMacro}{\pbox} % However, this is not convenient. It may take several attempts to % guess the correct width; and if there was ever a need to change the % contents of the boxes, then the hard-coded widths must be changed as % well. It would ideal to have a box that would collapse to the % minimal required width. % \makeatletter % \begingroup\center % \begin{minipage}[c]{\ExampleWidth-5mm} % \pbox[b]{0.5\textwidth}{Hello\\World!}^^A % \pbox[t]{0.5\textwidth}{Bonjour\\monde!} % \end{minipage} % \begin{minipage}{\textwidth-\ExampleWidth} % \fvset{xrightmargin=0pt} % \begin{Verbatim} % \pbox[b]{0.5\textwidth}{Hello\\World!}% % \pbox[t]{0.5\textwidth}{Bonjour\\monde!} % \end{Verbatim} % \end{minipage} % \endcenter\endgroup % \makeatother % Notice how the exclaimation mark and the capital B have no extra % space between each other, implying that |\pbox| creates minimal-width % boxes. % % If the provided width argument is smaller than the minimal-width, % then |\pbox| acts just like a regular |\parbox|. By minimal-width, % we mean the width of the unwrapped piece of text. You will have to % put in line breaks, to make |\pbox| create the tightest bounding box. % % For instance, the following example tries to get |\pbox| to wrap its % lines automatically. % \makeatletter % \begingroup\center % \begin{minipage}[c]{\ExampleWidth-5mm} % \pbox[b]{1.5cm}{Hello World!}^^A % \pbox[t]{1.5cm}{Bonjour monde!} % \end{minipage} % \begin{minipage}{\textwidth-\ExampleWidth} % \fvset{xrightmargin=0pt} % \begin{Verbatim} % \pbox[b]{1.5cm}{Hello World!}% % \pbox[t]{1.5cm}{Bonjour monde!} % \end{Verbatim} % \end{minipage} % \endcenter\endgroup % \makeatother % \end{DescribeMacro} % % \section{Determining minimum widths} % % This is all well and good, but how does one measure the width of one % of these boxes? Well, a rather painful way would be to use % |\settowidth| in conjunction with a |\parbox|. But it is far easier % to do it with the new width commands. % % \begin{DescribeMacro}{\settominwidth} % The |\settominwidth| command works very similarly to the standard % |\settowidth| command. % \begin{description} % \item % |\settowidth[|\textit{max\_width}|]{|\textit{cmd}|}{|\textit{text}|}| % sets the value of the a length command \textit{cmd} equal to the width % of the multi-line \textit{text}. The optional argument % \textit{max\_width} allows you to specify the maximum width that will % be returned; it defaults to |\columnwidth|. % \end{description} % \end{DescribeMacro} % % \begin{DescribeMacro}{\widthofpbox} % To provide completeness for the \textsf{calc} package, the % |\widthofpbox| command was implemented to complement the |\widthof| % command. % \begin{description} % \item % |\widthofpbox{|\textit{text}|}| returns the width of the multi-line % \textit{text}. % \end{description} % Here is an example: % \makeatletter % \begingroup\center % \begin{minipage}[c]{\ExampleWidth-5mm} % I\\ % need\\ % support\\ % \rule{\widthofpbox{I\\need\\support}}{0.4pt} % \end{minipage} % \begin{minipage}{\textwidth-\ExampleWidth} % \fvset{xrightmargin=0pt} % \begin{Verbatim} % I\\ % need\\ % support\\ % \rule{\widthofpbox{I\\need\\support}}{0.4pt} % \end{Verbatim} % \end{minipage} % \endcenter\endgroup % \makeatother % \end{DescribeMacro} % % \section{Limitations} % % Unfortunately, there are some limitations in this package. One of the % intrinsic limitations is that you cannot do anything in a |\pbox| that % you could not do in a |\parbox|. This seems quite reasonable, so % it should not be a hardship. % % Since |\pbox| is implemented using the \textbf{tabular} environment, % there are some things that cannot, and should not be used. You should % note that errant |&| characters within a |\pbox| do not generate % meaningful error messages. As well, it is unfortunate that % |\linebreak| and |\newline| do not work as expected. % % Since it is a box, you cannot use the \textbf{verbatim} environment % within. I recommend that you use the \textsf{fancyvrb} package which % contains the \textbf{BVerbatim} and \textbf{LVerbatim} environments % for typesetting boxed verbatim text. % % Alas, I have also discovered that certain uses of |\widthof| and % |\widthofpbox| do not work within the \textsf{docstrip} environment. % % \newpage % \section{Implementation} % \iffalse %<*style> % \fi % % I use the standard \textsf{calc} package for general math. As well, % I wish % to support a |\widthofpbox| command, so I will demand that the % |\widthof| command exists as well. % \begin{macrocode} \RequirePackage{calc} % \end{macrocode} % % In order to perform |\lengthtest|s and |\equal|ity tests, I need to % include the standard \textsf{ifthen} package. This also provides me % with simple conditionals. % \begin{macrocode} \RequirePackage{ifthen} % \end{macrocode} % % \begin{macro}{\settominwidth} % \changes{v1.1}{2011/11/24}{Always return a robust value.} % \changes{v1.2}{2011/12/07}{Really fix the result.} % The minimum length is determined by the clever use of the % \textbf{tabular} environment. It knows how to calculate the minimum % requisite width for a column, and the way determines the end of a % column is with its end of row command |\\| . % This command is conveniently similar to the command typically used to % break lines. % % As you can see, |#1| defaults to the width of a column. This will % either be |\textwidth| or the width defined by the \textbf{twocolumn} % option, or even the \textsf{multicol} package. % \begin{macrocode} \newcommand{\settominwidth}[3][\columnwidth]{% % \end{macrocode} % Here, I set the length command |#2|. Notice the argument to the % \textbf{tabular} environment. I use |@{}| to eliminate any horizontal % padding, and use the |l| alignment to grab the width of the text in % |#3|. % \begin{macrocode} \settowidth{#2}{\begin{tabular}{@{}l@{}}#3\end{tabular}}% % \end{macrocode} % Finally, I wish to make sure that the length I have set in |#2| is % not larger than the maximum stored in |#1|. % \begin{macrocode} \ifthenelse{\lengthtest{#1<#2}}{\setlength{#2}{#1}}{}} % \end{macrocode} % \end{macro} % % \begin{macro}{\widthofpbox} % In order to find the width of a |\pbox|, I use the same % \textbf{tabular} trick from |\settominwidth|. I use the |\widthof| % command in order to preserve its semantics instead of trying to % emulate them using my |\settominwidth| command. % % I do \emph{not} check against a maximum length here. Restricting this % command to a maximum length would mean that I throw away length % information if the text is too long. % \begin{macrocode} \newcommand{\widthofpbox}[1]{% \widthof{\begin{tabular}{@{}l@{}}#1\end{tabular}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\pbox} % \begin{macro}{\pb@xi} % \begin{macro}{\pb@xii} % It is not possible to implement |\pbox| in a simple way. The command % definition commands in \LaTeX{} don't afford you more than one % optional parameter; however, |\parbox| has three. % % In order to faithfully simulate the three optional arguments, I must % trick \LaTeX{} in to catching three optional % arguments~\cite{fto:optargs}. Therefore |\pbox|, % |\pb@xi|, and |\pb@xii| are used to capture the optional arguments in % the |\pb@xargi|, |\pb@xargii|, and |\pb@xargiii| commands. These are % then passsed to |\pb@xiii| for actual processing. % \begin{macrocode} \DeclareRobustCommand*{\pbox}[1][]{% \def\pb@xargi{#1}% \pb@xi} \DeclareRobustCommand*{\pb@xi}[1][]{% \def\pb@xargii{#1}% \pb@xii} \DeclareRobustCommand*{\pb@xii}[1][]{% \def\pb@xargiii{#1}% \pb@xiii} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\pb@xiii} % In order to create the final paragraph box, I parse out the two % manditory arguments. I then use the provided maximal length |#1| to % determine the actual width of the |\parbox|. % \begin{macrocode} \newlength{\pb@xlen} \DeclareRobustCommand{\pb@xiii}[2]{% \settominwidth[#1]{\pb@xlen}{#2}% % \end{macrocode} % % Since the default optional arguments are all empty, I should be able % to just pass them to |\parbox|. However, |\parbox| interprets empty % optional values differently than just non-existant optional values. % So, I must make complicated decisions; if an optional argument is % empty, then I will just skip it.. % \begin{macrocode} \ifthenelse{\equal{\pb@xargi}{}} {\parbox{\pb@xlen}{#2}} {\ifthenelse{\equal{\pb@xargii}{}} {\ifthenelse{\equal{\pb@xargiii}{}} {\parbox[\pb@xargi]{\pb@xlen}{#2}} {\parbox[\pb@xargi][][\pb@xargiii]{\pb@xlen}{#2}}} {\ifthenelse{\equal{\pb@xargiii}{}} {\parbox[\pb@xargi][\pb@xargii]{\pb@xlen}{#2}} {\parbox[\pb@xargi][\pb@xargii][\pb@xargiii]{\pb@xlen}{#2}}}}% % \end{macrocode} % % Finally, I must clean up the optional arguments and remove their % special meaning. As well, I will terminate the |\parbox| I have % created with an empty |\makebox| in order to prevent the % |\def\pb@x...\relax| commands from interfering with other commands % that expect |\pbox| to solely consist of a box. % \begin{macrocode} \def\pb@xargi\relax \def\pb@xargii\relax \def\pb@xargiii\relax \makebox[0pt]{}} % \end{macrocode} % \end{macro} % \iffalse %</style> % \fi % \begin{thebibliography}{99} % \bibitem{fto:optargs} Robin Fairbanks. % ``A command with two optional arguments.'' % \emph{\TeX{} Frequently Asked Questions.} % \url{http://www.tex.ac.uk/cgi-bin/texfaq2html?label=twooptarg} % (current 6 April 2003.) % \end{thebibliography} % \Finale \endinput