% framed.sty v 0.8a 21-Jul-2003 % Copyright (C) 1992-2003 by Donald Arseneau % These macros may be freely transmitted, reproduced, or modified % provided that this notice is left intact. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Create framed or shaded regions that can break across pages using % \begin{framed} ... \end{framed} -- ordinary frame box (box at margin) % \begin{shaded} ... \end{shaded} -- shaded background (into margin) % ... leftbar ... -- line on left side % \begin{MakeFramed}{settings} ... \end{MakeFramed} % -- generic frame (for new environments) % % The "framed" environment puts the text into "\fbox" with the % settings "\fboxrule=\FrameRule" and "\fboxsep=\FrameSep". % You can change these lengths (using "\setlength") and you % can even change the definition of "\FrameCommand" to use % much fancier boxes. % % In fact, the "shaded" environment just redefines "\FrameCommand" % to use "\colorbox{shadecolor}" (and you have to define the % color "shadecolor": \newcolor{shadecolor}...). % % A page break is allowed, and even encouraged, before the framed % environment. If you want to attach some text (a box title) to the % frame, then the text should be inserted by \FrameCommand % % The contents of the framed regions are restricted: % Floats, footnotes, marginpars and head-line entries will be lost. % (Some of these may be handled in a later version.) % This package will not work with the page breaking of multicol.sty, % or other systems that perform column-balancing. % % The MakeFramed environment does the work. Its "settings" argument % should contain any adjustments to the text width (applied to \hsize, % and using the "\width" of the frame itself) as well as a `restore' % command -- \@parboxrestore or \FrameRestore or something similar. % % Expert commands: % \MakeFramed, \endMakeFramed: the "MakeFramed" environment % \FrameCommand: command to draw the frame around its argument % \FrameRestore: restore some text settings, but fewer than \@parboxrestore % \FrameRule: length register; \fboxrule for default "framed". % \FrameSep: length register; \fboxsep for default "framed". % \FrameHeightAdjust: macro; height of frame above baseline at top of page % % This is still a `pre-production' version because I can think of many % features/improvements that should be made. Nevertheless, starting % with version 0.5 it should be bug-free. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ProvidesPackage{framed}[2003/07/21 v 0.8a: framed or shaded text with page breaks] \newenvironment{framed}% using default \FrameCommand {\MakeFramed {\advance\hsize-\width \FrameRestore}}% {\endMakeFramed} \newenvironment{shaded}{% \def\FrameCommand{\colorbox{shadecolor}}% \MakeFramed {\FrameRestore}}% {\endMakeFramed} \newenvironment{leftbar}{% \def\FrameCommand{\vrule width 3pt \hspace{10pt}}% \MakeFramed {\advance\hsize-\width \FrameRestore}}% {\endMakeFramed} \chardef\FrameRestore=\catcode`\| % for debug \catcode`\|=\catcode`\% % (debug: insert space after backslash) \def\MakeFramed#1{\par % measure added width and height; call result \width and \height \setbox\z@\vbox{\vskip-1in \hbox{\hskip-1in \FrameCommand{\hbox{\vrule \@height .7in \@depth.3in \@width 1in}}}% \vskip\z@skip}% \def\width{\wd\z@}\def\height{\ht\z@}% \edef\fb@frw{\the\width}\edef\fb@frh{\the\height}% % insert pre-penalties and skips \begingroup \skip@\lastskip \if@nobreak\else \penalty9999 % updates \page parameters \ifdim\pagefilstretch=\z@ \ifdim\pagefillstretch=\z@ \edef\@tempa{\the\skip@}% \ifx\@tempa\zero@glue \penalty-30 \else \vskip-\skip@ \penalty-30 \vskip\skip@ \fi\fi\fi \penalty\z@ % Give a stretchy breakpoint that will always be taken in preference % to the \penalty 9999 used to update page parameters. The cube root % of 10000/100 indicates a multiplier of 0.21545, but the maximum % calculated badness is really 8192, not 10000, so the multiplier % is 0.2301. \advance\skip@ \z@ plus-.5\baselineskip \advance\skip@ \z@ plus-.231\height \advance\skip@ \z@ plus-.231\skip@ \advance\skip@ \z@ plus-.231\topsep \vskip-\skip@ \penalty 1800 \vskip\skip@ \fi \addvspace{\topsep}% \endgroup % clear out pending page break \penalty\@M \vskip 2\baselineskip \vskip\height \penalty9999 \vskip -2\baselineskip \vskip-\height \penalty9999 % updates \pagetotal |\message{After clearout, \pagetotal=\the\pagetotal, \pagegoal=\the\pagegoal. }% \fb@adjheight \setbox\@tempboxa\vbox\bgroup #1% Modifications to \hsize (can use \width and \height) \textwidth\hsize \columnwidth\hsize } \def\endMakeFramed{\par \kern\z@ \penalty-100 % put depth into height \egroup \begingroup \put@frame \endgroup } % \put@frame takes the contents of \@tempboxa and puts all, or a piece, % of it on the page with a frame (\FrameCommand). It recurses until % all of \@tempboxa has been used up. (\@tempboxa must have zero depth.) \def\put@frame{\relax \ifdim\pagegoal=\maxdimen \pagegoal\vsize \fi | \message{=============== Entering putframe ====================^^J | \pagegoal=\the\pagegoal, \pagetotal=\the\pagetotal. }% \ifinner \else \dimen@\pagegoal \advance\dimen@-\pagetotal % natural space left on page \ifdim\dimen@<2\baselineskip | \message{Page has only \the\dimen@\space room left; eject. }% \eject \fb@adjheight \put@frame \else % there's appreciable room left on the page | \message{\string\pagetotal=\the\pagetotal, | \string\pagegoal=\the\pagegoal, | \string\pagestretch=\the\pagestretch, | \string\pageshrink=\the\pageshrink, | \string\fb@frh=\fb@frh. \space} | \message{Box of size \the\ht\@tempboxa\space + \fb@frh}% \begingroup % temporarily set \dimen@ to be... \advance\dimen@.8\pageshrink % maximum space available on page \advance\dimen@-\fb@frh\relax % space available for frame's contents \expandafter\endgroup % restore \dimen@ to real room left on page \ifdim\dimen@>\ht\@tempboxa % whole box does fit | \message{fits in \the\dimen@. }% \else % box must be split | \message{must be split to fit in \the\dimen@. }% \setbox\@tempboxa\vbox{% simulate frame and flexiblity of the page: \vskip \fb@frh \@plus\pagestretch \@minus.8\pageshrink \kern137sp\kern-137sp\penalty-30 \unvbox\@tempboxa}% \edef\fb@resto@set{\boxmaxdepth\the\boxmaxdepth \splittopskip\the\splittopskip}% \boxmaxdepth\z@ \splittopskip\z@ \setbox\tw@\vsplit\@tempboxa to\dimen@ \setbox\tw@\vbox{\unvbox\tw@}% natural-sized | \message{Box of size \the\ht\@tempboxa\space split to \the\dimen@. | Natural height of split box is \the\ht\tw@. }% % If the split-to size > (\vsize-\topskip), then set box to full size \begingroup \advance\dimen@\topskip \expandafter\endgroup \ifdim\dimen@>\pagegoal | \message{Frame is big -- Use up the full column. }% \dimen@ii\pagegoal \advance\dimen@ii -\topskip \advance\dimen@ii \FrameHeightAdjust\relax \else % suspect this is wrong: % If the split-to size > feasible room_on_page, rebox it smaller. \advance\dimen@.8\pageshrink \ifdim\ht\tw@>\dimen@ | \message{Box too tall; rebox it to \the\dimen@. }% \dimen@ii\dimen@ \else % use natural size \dimen@ii\ht\tw@ \fi \fi % Re-box contents to desired size \dimen@ii \advance\dimen@ii -\fb@frh \setbox\tw@\vbox to\dimen@ii \bgroup % remove simulated frame and page flexibility: \vskip -\fb@frh \@plus-\pagestretch \@minus-.8\pageshrink \unvbox\tw@ \unpenalty\unpenalty \ifdim\lastkern=-137sp % whole box went to next page | \message{box split at beginning! }% \egroup \fb@resto@set \eject % (\vskip for frame size was discarded) \fb@adjheight \else % \egroup \fb@resto@set \ifvoid\@tempboxa % it all fit after all | \message{box split at end! }% \setbox\@tempboxa\box\tw@ \else % it really did split | \message{box split as expected. Its reboxed height is \the\ht\tw@. }% \ifdim\wd\tw@>\z@ \centerline{\FrameCommand{\box\tw@}}% ??? \centerline bad idea \else | \message{Zero width means likely blank. Don't frame it (guess)}% \box\tw@ \fi \hrule \@height\z@ \eject \fb@adjheight \put@frame \fi\fi\fi\fi\fi \ifvoid\@tempboxa\else \centerline{\FrameCommand{\box\@tempboxa}}% \nointerlineskip \null %{\showoutput \showlists} \penalty-30 \vskip\topsep \fi} \def\fb@adjheight{% \vbox to\FrameHeightAdjust{}% get proper baseline skip from above. \penalty\@M \nointerlineskip \vskip-\FrameHeightAdjust \penalty\@M} % useful for tops of pages \edef\zero@glue{\the\z@skip} \catcode`\|=\FrameRestore % Provide configuration commands: \providecommand\FrameCommand{\fboxrule=\FrameRule \fboxsep=\FrameSep \fbox} \@ifundefined{FrameRule}{\newdimen\FrameRule \FrameRule=\fboxrule}{} \@ifundefined{FrameSep} {\newdimen\FrameSep \FrameSep =2pt} % Height of frame above first baseline when frame starts a page: \providecommand\FrameHeightAdjust{6pt} % \FrameRestore has parts of \@parboxrestore. See how it is used in the % "settings" argument of \MakeFrame. Previous behavior can be restored by % using \@parboxrestore there, or redefining: % \makeatletter \renewcommand\FrameRestore{\@parboxrestore} \makeatother \def\FrameRestore{% \let\if@nobreak\iffalse \let\if@noskipsec\iffalse % \let\par\@@par ?? \let\-\@dischyph \let\'\@acci\let\`\@accii\let\=\@acciii % \parindent\z@ \parskip\z@skip Definitely omit! % \everypar{}% ?? \linewidth\hsize % \@totalleftmargin\z@ % \leftskip\z@skip \rightskip\z@skip \@rightskip\z@skip % \parfillskip\@flushglue \lineskip\normallineskip % \baselineskip\normalbaselineskip \sloppy % \let\\\@normalcr } % Compatibility with previous versions (temporary!): \let\fram@d=\MakeFramed \let\endfram@d=\endMakeFramed %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%