% 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}}
