% Usage: % % \parboxwithmaxwidth{3in}{Blah, blah, blah. Blah, blah, blah.} % \parboxwithmaxwidth[t]{3in}{Blah, blah, blah. Blah, blah, blah.} % \parboxwithmaxwidth[b]{3in}{Blah, blah, blah. Blah, blah, blah.} % % This works like the ordinary \parbox command, except after forming % the box, it goes through and resets every piece of glue in each line % to its natural width, with no stretching or shrinking. The effect % of this is that the size given acts as an upper bound on the % horizontal size of the box, rather than forcing the box to have % exactly that horizontal size. (There is a theoretical possibility % that the box might be a little bit larger horizontally than the size % given.) \newsavebox{\jbwpb@vbox} \newsavebox{\jbwpb@hbox} \newsavebox{\jbwpb@temphbox} \newdimen\jbwpb@MaxWidth \newcommand{\parboxwithmaxwidth}[3][c] {\if#1t% \vtop \else \if#1b% \vbox \else \if#1c% % even in math mode, we want to wrap this in \hbox so that it % can be an argument to a box command. \hbox{$\vcenter \else \PackageError{jbw-parbox} {Bad optional argument "#1" to \parboxwithmaxwidth} {No additional help.} \fi \fi \fi {% \setbox\jbwpb@vbox=\vbox{% \setlength{\hsize}{#2}% % One of the important things the next line does is ensure a % sane meaning for \par ... \@parboxrestore% from ltboxes.dtx % \@parboxrestore fixes everything but \lineskiplimit, which % the following fixes. \normalbaselines% from ltplain.dtx \parindent=0pt% \parfillskip=0pt% \rightskip=0pt plus0.2\hsize \spaceskip=0.3333em% should be: \fontdimen2\currentfontcmd \xspaceskip=0.5em% should be: \spaceskip+\fontdimen7\currentfontcmd #3% %\showthe\baselineskip %\showthe\lineskip %\showthe\lineskiplimit \hfuzz=\maxdimen % disable warnings \par \jbwpb@MaxWidth=0pt% \jbwpb@resethboxes{#2}}% %\jbwpb@showbox{\jbwpb@vbox}% \unvbox\jbwpb@vbox }% \if#1c% $}% \fi } \newcommand{\jbwpb@resethboxes}[1] {% #1 is PARBOX_MAX_WIDTH \ifhmode\instantdeath\fi %\showthe\lastskip %\edef\myskip{\the\lastskip}% %\show\myskip \unskip %\edef\mypenalty{\the\lastpenalty}% %\show\mypenalty \unpenalty \unskip\unpenalty\unskip\unpenalty \setbox\jbwpb@hbox=\lastbox %\jbwpb@showbox{\jbwpb@hbox}% \ifhbox\jbwpb@hbox \setbox\jbwpb@temphbox=\hbox{\unhcopy\jbwpb@hbox}% %\jbwpb@showbox{\jbwpb@temphbox}% \ifdim\wd\jbwpb@temphbox>\jbwpb@MaxWidth \ifdim\wd\jbwpb@temphbox<#1\relax \global\jbwpb@MaxWidth=\wd\jbwpb@temphbox \else \ifdim\wd\jbwpb@temphbox=#1\relax \global\jbwpb@MaxWidth=\wd\jbwpb@temphbox \else % width(temphbox) > max(MaxWidth, PARBOX_MAX_WIDTH) % So hbox was squeezed. Did it fit in PARBOX_MAX_WIDTH? % We reset it again to get its \badness value. \setbox\jbwpb@hbox=\hbox to #1{\unhcopy\jbwpb@hbox}% \ifnum\badness>10000\relax % hbox didn't fit in PARBOX_MAX_WIDTH, even with % squeezing. So we require its natural width. % Set MaxWidth to max(width(temphbox),MaxWidth). \global\jbwpb@MaxWidth=\wd\jbwpb@temphbox \else % hbox did fit in PARBOX_MAX_WIDTH after squeezing. % So we set MaxWidth to max(PARBOX_MAX_WIDTH,MaxWidth). \ifdim\jbwpb@MaxWidth<#1\relax \global\jbwpb@MaxWidth=#1\relax \fi \fi \fi \fi \fi {% The effect of this group is to save the last hbox on the stack % while we recursively process the preceding lines. \jbwpb@resethboxes{#1}}% %\showthe\jbwpb@MaxWidth \setbox\jbwpb@temphbox=\hbox to \jbwpb@MaxWidth{\unhcopy\jbwpb@hbox}% \ifnum\badness>10000\relax \setbox\jbwpb@temphbox=\hbox{\unhcopy\jbwpb@hbox}% \fi %\jbwpb@showbox{\jbwpb@temphbox}% \box\jbwpb@temphbox \else \nointerlineskip % set \prevdepth to large negative value \fi %\penalty\mypenalty %\vskip\myskip } % Testing reveals that \badness is not saved/restored by groups!!! % for debugging \newcommand{\jbwpb@showbox}[1] {{\showboxdepth=9999% \showboxbreadth=9999% \tracingonline=1% \showbox#1}}