303 lines
10 KiB
Text
303 lines
10 KiB
Text
|
% varwidth.sty v 0.9a Mar 2003 Donald Arseneau asnd@triumf.ca
|
||
|
%
|
||
|
% Copyright 2003 by Donald Arseneau (asnd@triumf.ca).
|
||
|
% This software is released under the terms of the LaTeX Project Public
|
||
|
% License (ftp://ctan.tug.org/tex-archive/macros/latex/base/lppl.txt).
|
||
|
% (Essentially: Free to use, copy, distribute (sell) and change, but, if
|
||
|
% changed, the name must be changed.)
|
||
|
%
|
||
|
% The varwidth environment is based on minipage, and takes the same
|
||
|
% parameters, but the specified width is just a maximum value -- the
|
||
|
% environment will be typeset with a narrower "natural" width if
|
||
|
% possible.
|
||
|
%
|
||
|
% In a varwidth environment, paragraph line-breaks are chosen
|
||
|
% according to the specified width, but each line is reset to
|
||
|
% match a narrower natural width, if there is one.
|
||
|
%
|
||
|
% The \narrowragged command works like \raggedright, but produces
|
||
|
% generally narrower lines in paragraphs, but more text in the last
|
||
|
% line (the lines have more-equal lengths).
|
||
|
%
|
||
|
% This version works fine, but there are still many questions about
|
||
|
% how it would work best. Should there be a version that avoids the
|
||
|
% usual minipage formatting style?
|
||
|
%
|
||
|
% Numbered equations are not handled well, especially with leqno.
|
||
|
% AMSmath environments have not been tried, and undoubtedly fail.
|
||
|
%
|
||
|
% To do: Extend v-list wrappers to handle all e-TeX primitives.
|
||
|
% (pdfTeX too?)
|
||
|
% Capture marks and floats, propagating them out of the box
|
||
|
% Support numbered equations, including ams math.
|
||
|
%
|
||
|
|
||
|
\ProvidesPackage{varwidth}[2003/03/10 ver 0.9a; \space
|
||
|
Variable-width minipages]
|
||
|
|
||
|
\newcommand\narrowragged{\rightskip \z@ plus .25\hsize
|
||
|
\@rightskip\rightskip \parfillskip\z@ plus .15\hsize
|
||
|
\sloppy }
|
||
|
|
||
|
\newbox\@vwid@box
|
||
|
|
||
|
% The varwidth environment is based on minipage, and takes the same
|
||
|
% parameters, but the specified width is only a limit -- a narrower
|
||
|
% natural width may be used. \varwidth uses \minipage.
|
||
|
|
||
|
\def\varwidth{\let\@minipagerestore\@vwid@setup \minipage}
|
||
|
|
||
|
% Many things may appear on vertical lists that can't be re-processed,
|
||
|
% so they have to be modified.
|
||
|
|
||
|
\def\@vwid@setup{%
|
||
|
% several things can't appear in vertical mode, so they may get
|
||
|
% a \vbox wrapped around them.
|
||
|
\let\@bsphack\@vwid@bsphack % \label and others
|
||
|
\let\mark\@gobble % Marks disappear in minipages anyway
|
||
|
\let\@special\@vwid@special % \color and others
|
||
|
\let\addtocontents\@vwid@addtocontents % \addcontentsline
|
||
|
% Shifted boxes (\parshape,\hangindent) will have their shifts
|
||
|
% indicated in a separate box.
|
||
|
\let\@hangfrom\@vwid@hangfrom % hanging indents
|
||
|
\let\list\@vwid@list
|
||
|
\let\endtrivlist\@vwid@endtrivlist
|
||
|
\postdisplaypenalty\@vwid@posteqp
|
||
|
\predisplaypenalty\@vwid@preeqp
|
||
|
\def\@eqnnum{\aftergroup\@vwid@afterva\@@vwid@eqnnum}%
|
||
|
\global\@vwid@roff\z@ \global\@vwid@loff\z@
|
||
|
% Begin an inner minipage-like vertical box (in \@tempboxa)
|
||
|
\let\@minipagerestore\@@vwid@minipagerestore \@minipagerestore
|
||
|
\setbox\@tempboxa\vbox\bgroup\begingroup
|
||
|
% Flag the top of the list
|
||
|
\penalty\@vwid@toppen
|
||
|
}
|
||
|
|
||
|
\let\@@vwid@minipagerestore\@minipagerestore
|
||
|
|
||
|
% At end of varwidth environment.
|
||
|
\def\endvarwidth{\par\@@par
|
||
|
% Handle minipage-style notes.
|
||
|
\ifvoid\@mpfootins\else
|
||
|
\vskip\skip\@mpfootins
|
||
|
\normalcolor
|
||
|
\@vwid@wrap\footnoterule
|
||
|
\unvbox\@mpfootins
|
||
|
\fi
|
||
|
\unskip
|
||
|
\endgroup\egroup % got my \@tempboxa
|
||
|
% {\showoutput\showbox\@tempboxa}%
|
||
|
% in a discarded box, sift through list measuring max width.
|
||
|
\begingroup\setbox\z@\vbox\bgroup
|
||
|
%\message{-------------------------------------------------------------}%
|
||
|
%\message{First pass; hsize=\the\hsize... }%{\tracingall\showlists}%%
|
||
|
\unvcopy\@tempboxa
|
||
|
\@tempdima-\maxdimen
|
||
|
\let\@vwid@resetb\@vwid@measure
|
||
|
\let\@vwid@append\relax
|
||
|
\sift@deathcycles\z@
|
||
|
\@vwid@sift
|
||
|
\xdef\@vwid@{\the\@tempdima}%
|
||
|
\egroup\endgroup
|
||
|
% Done measuring. Now empty \@tempboxa onto current vertical list
|
||
|
% which is the contents of a minipage environment
|
||
|
%\message{Got natural width \@vwid@. }%
|
||
|
\unvbox\@tempboxa
|
||
|
% If the natural width is narrower, then go back through the list
|
||
|
% reboxing and moving everything into \@vwid@box; then spill \@vwid@box
|
||
|
\ifdim\@vwid@<\hsize
|
||
|
\hsize\@vwid@
|
||
|
\setbox\@vwid@box\vbox{}%
|
||
|
\sift@deathcycles\z@
|
||
|
%\message{----------------------------------------------------------------}%
|
||
|
%\message{Second pass; hsize=\the\hsize... }%{\tracingall\showlists}%
|
||
|
\@vwid@sift
|
||
|
\unvbox\@vwid@box
|
||
|
\fi
|
||
|
% end the minipage environment
|
||
|
\endminipage}
|
||
|
|
||
|
%
|
||
|
% Here are definitions for sifting through the vertical list, either
|
||
|
% measuring things or reboxing them.
|
||
|
%
|
||
|
% Penalties used as signals to the vertical-list processor:
|
||
|
|
||
|
\mathchardef\@vwid@posteqp 17321 % Penalty below equations
|
||
|
\mathchardef\@vwid@preeqp 17322 % Penalty above equations
|
||
|
\mathchardef\@vwid@postnump 17323 % Penalty below numbered equations
|
||
|
\mathchardef\@vwid@toppen 17324 % Penalty marking top of vertical list
|
||
|
\mathchardef\@vwid@offsets 17325 % Penalty below special h-offsets box
|
||
|
\mathchardef\@vwid@postw 17326 % Penalty below a \vbox-wrapped object
|
||
|
|
||
|
\newcount\sift@deathcycles
|
||
|
|
||
|
\def\@vwid@sift{%
|
||
|
\skip@\lastskip\unskip
|
||
|
\dimen@\lastkern\unkern
|
||
|
\count@\lastpenalty\unpenalty
|
||
|
\setbox\z@\lastbox
|
||
|
%{\showoutput\showbox\z@}%
|
||
|
\ifvoid\z@ \advance\sift@deathcycles\@ne \else \sift@deathcycles\z@ \fi
|
||
|
\ifnum\sift@deathcycles>33
|
||
|
\let\@vwid@sift\relax
|
||
|
\PackageWarning{varwidth}{Failed to reprocess entire contents}%
|
||
|
\fi
|
||
|
%\message{\the\sift@deathcycles: skip \the\skip@; kern \the\dimen@; penalty \the\count@. }%
|
||
|
%\ifhbox\z@\setbox99\hbox to0pt{\unhcopy\z@}\fi % = message
|
||
|
\ifnum\count@=\@vwid@preeqp \@vwid@eqmodefalse\fi
|
||
|
%\ifnum\count@=\@vwid@preeqp \message{End equation mode. }\fi
|
||
|
\ifnum\count@=\@vwid@posteqp \@vwid@eqmodetrue\fi
|
||
|
%\ifnum\count@=\@vwid@posteqp\message{Begin equation mode. }\fi
|
||
|
%\if@vwid@eqmode {\showoutput\showbox\z@}\fi
|
||
|
\ifnum\count@=\@vwid@toppen % finished
|
||
|
\let\@vwid@sift\relax
|
||
|
\else\ifnum\count@=\@vwid@offsets
|
||
|
\@vwid@setoffsets
|
||
|
\else
|
||
|
\ifnum\count@=\@vwid@postw
|
||
|
\else
|
||
|
\@vwid@resetb % reset box \z@ or measure it
|
||
|
\fi
|
||
|
\@vwid@append
|
||
|
\fi\fi
|
||
|
\@vwid@sift}
|
||
|
|
||
|
\def\@vwid@setoffsets{%
|
||
|
\setbox\z@=\hbox{\unhbox\z@
|
||
|
\global\@vwid@roff\lastkern\unkern
|
||
|
\global\@vwid@loff\lastkern\unkern}%
|
||
|
%\message{Set offsets to \the\@vwid@loff, \the\@vwid@roff. }%
|
||
|
}
|
||
|
|
||
|
\def\@vwid@append{% Append contents of box \z@ and glue to \@vwid@box
|
||
|
\setbox\@vwid@box\vbox{%
|
||
|
\unvbox\z@
|
||
|
\ifdim\dimen@=\z@\else \kern\dimen@ \fi
|
||
|
\vskip\skip@
|
||
|
\unvbox\@vwid@box
|
||
|
}%{\tracingall\showbox\@vwid@box}%
|
||
|
}
|
||
|
|
||
|
% reset box \z@ to \hsize, applying shifts, and wrap in vbox
|
||
|
% Don't worry about numbered equations because we won't get
|
||
|
% here if there are any.
|
||
|
\def\@vwid@resetb{%
|
||
|
\setbox\z@\vbox\bgroup
|
||
|
\ifvoid\z@
|
||
|
\else
|
||
|
\ifvbox\z@
|
||
|
\box\z@
|
||
|
\else % \hbox
|
||
|
\@tempdima\hsize
|
||
|
\advance\@tempdima-\@vwid@roff
|
||
|
\advance\@tempdima-\@vwid@loff
|
||
|
\advance\@tempdima-\p@
|
||
|
\ifdim\wd\z@>\@tempdima % full-width line; rebox it
|
||
|
%\message{An ordinary line or alignment. }%
|
||
|
\hbox to\hsize
|
||
|
{\kern\@vwid@loff \unhbox\z@ \kern\@vwid@roff}%
|
||
|
\else % an equation or direct \hbox
|
||
|
\if@vwid@eqmode % re-center unnumbered equations
|
||
|
%\message{A centered equation hsize=\the\hsize. }%
|
||
|
\hbox to\hsize
|
||
|
{\hskip\@vwid@loff\@plus1fil
|
||
|
\unhbox\z@ \hskip\@vwid@roff\@plus1fil}%
|
||
|
\else % plain narrow \hbox; leave it as-is
|
||
|
\box\z@
|
||
|
\fi\fi\fi\fi
|
||
|
\egroup}
|
||
|
|
||
|
\def\@vwid@measure{%
|
||
|
\ifvoid\z@
|
||
|
\else
|
||
|
% numbered equations not part of alignments can't be reset,
|
||
|
% so force retention of full width.
|
||
|
\ifnum\count@=\@vwid@postnump \ifdim\wd\z@<\linewidth
|
||
|
\ifdim\@tempdima<\linewidth \@tempdima\linewidth \fi
|
||
|
\fi\fi
|
||
|
\ifhbox\z@
|
||
|
\setbox\z@=\hbox
|
||
|
{\kern\@vwid@loff \unhbox\z@ \kern\@vwid@roff}%
|
||
|
\fi
|
||
|
\ifdim\wd\z@>\@tempdima \@tempdima\wd\z@ \fi
|
||
|
\fi}
|
||
|
|
||
|
\newdimen\@vwid@loff
|
||
|
\newdimen\@vwid@roff
|
||
|
|
||
|
\let\@@bsphack\@bsphack
|
||
|
\let\@@esphack\@esphack
|
||
|
\let\@@esphack\@Esphack
|
||
|
|
||
|
\def\@vwid@bsphack{\@@bsphack
|
||
|
\ifx\@vwid@wrap\@firstofone
|
||
|
\bgroup
|
||
|
\else
|
||
|
\ifvmode
|
||
|
\setbox\@vwid@box \vbox\bgroup \vbox\bgroup
|
||
|
\let\@vwid@wrap\@firstofone
|
||
|
\def\@esphack{\@vwid@esphack\@@esphack}%
|
||
|
\def\@Esphack{\@vwid@esphack\@@Esphack}%
|
||
|
\fi
|
||
|
\fi}
|
||
|
|
||
|
\def\@vwid@esphack{\egroup
|
||
|
\ifx\@vwid@wrap\@firstofone\else
|
||
|
\egroup % end outer box
|
||
|
\unvbox\@vwid@box % put inner box on list without lineskip
|
||
|
\penalty\@vwid@postw
|
||
|
\fi}
|
||
|
|
||
|
% \vbox Wrapper for misc vlist items
|
||
|
\long\def\@vwid@wrap{\relax
|
||
|
\ifvmode\expandafter\@vwid@dowrap \else \expandafter\@firstofone \fi}
|
||
|
\long\def\@vwid@dowrap#1{%
|
||
|
\setbox\@vwid@box \vbox{\vbox{\let\@vwid@wrap\@firstofone
|
||
|
#1}\penalty\@vwid@postw
|
||
|
}\unvbox\@vwid@box }
|
||
|
|
||
|
\let\@@vwid@special\special
|
||
|
\let\@@vwid@addtocontents\addtocontents
|
||
|
\let\@@vwid@list\list
|
||
|
\let\@@vwid@endtrivlist\endtrivlist
|
||
|
\let\@@vwid@eqnnum\@eqnnum
|
||
|
|
||
|
\long\def\@vwid@special#1{\@vwid@wrap{\@@vwid@special{#1}}}
|
||
|
\long\def\@vwid@addtocontents#1#2{\@vwid@wrap{\@@vwid@addtocontents{#1}{#2}}}
|
||
|
|
||
|
\long\def\@vwid@hangfrom#1{\par
|
||
|
\setbox\@tempboxa\hbox{{#1}}%
|
||
|
\setbox\@vwid@box \vbox{\hbox{\kern\z@ \kern\z@
|
||
|
}\penalty\@vwid@offsets}\unvbox\@vwid@box
|
||
|
\def\par{\relax\ifhmode\unskip\fi
|
||
|
\vadjust{\hbox{\kern\hangindent\kern\z@}\penalty\@vwid@offsets}%
|
||
|
\@restorepar\par}%
|
||
|
\hangindent \wd\@tempboxa\noindent\box\@tempboxa}
|
||
|
|
||
|
\def\@vwid@list{\@vwid@setlist\@@vwid@list}
|
||
|
\def\@vwid@endtrivlist{\@vwid@setlist\@@vwid@endtrivlist}
|
||
|
|
||
|
\def\@vwid@setlist{\relax\ifhmode \unskip\expandafter\vadjust\fi
|
||
|
{\setbox\@vwid@box \vbox{\hbox{%
|
||
|
\advance\hsize-\linewidth \advance\hsize-\@totalleftmargin
|
||
|
\kern\@totalleftmargin \kern\hsize}%
|
||
|
\penalty\@vwid@offsets}%
|
||
|
\unvbox\@vwid@box}}
|
||
|
|
||
|
\newif\if@vwid@eqmode
|
||
|
|
||
|
\def\@vwid@afterva{\vadjust{\penalty\@vwid@postnump}}
|
||
|
|
||
|
% Should I do this? ...
|
||
|
|
||
|
\@ifundefined{newcolumntype}{}{%
|
||
|
\@ifundefined{NC@rewrite@V}{
|
||
|
\newcolumntype{V}[1]{%
|
||
|
>{\begin{varwidth}[t]{#1}\narrowragged\let\\\tabularnewline}%
|
||
|
l%
|
||
|
<{\@finalstrut\@arstrutbox\end{varwidth}}}
|
||
|
}{}
|
||
|
}
|
||
|
|