% \begin{meta-comment}
%
% $Id: slowbox.dtx,v 1.2 2003/09/06 13:08:16 mdw Exp $
%
% Cop-out for slow things
%
% (c) 2003 Mark Wooding
%
% \end{meta-comment}
%
% \begin{meta-comment} <general public licence>
%%
%% slowbox package -- skipping of slow boxes
%% Copyright (c) 2003 Mark Wooding
%%
%% 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 2 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, write to the Free Software Foundation,
%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
% \end{meta-comment}
%
% \begin{meta-comment} <Package preambles>
%<+package>\NeedsTeXFormat{LaTeX2e}
%<+package>\ProvidesPackage{slowbox}
%<+package>                [2003/08/27 1.0 skipping of slow boxes]
% \end{meta-comment}
%
% \CheckSum{222}
%% \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         \~}
%%
%
% \begin{meta-comment}
%
%<*driver>
\input{mdwtools}
\describespackage{slowbox}
\newcommand\opt[1]{\textsf{#1}}
\expandafter\def\csname sb@box:tag\endcsname{{2cm}{1cm}{0.5cm}}
\def\*{\hspace{0pt plus 0.1pt}\ignorespaces}
\mdwdoc
%</driver>
%
% \end{meta-comment}
%
%^^A-------------------------------------------------------------------------
% \section{User guide}
%
% The problem is that some things, e.g., diagrams, can take a while to
% typeset, and aren't particularly interesting as far as the global document
% layout is concerned.  Once you've got a diagram right, the only thing that
% matters as far as general previewing is concerned is its size.
%
% The solution is \package{slowbox}.  Put things you're usually not
% interested in seeing in a \env{slowbox} environment.  Then they get
% replaced by a frame saying that there's meant to be something there, and
% that's it.
%
% There are two modes, chosen by package options: \opt{show} and \opt{hide}.
% The default is \opt{show} mode, because I had to pick one.  In \opt{show}
% mode, everything happens normally; in \opt{hide} mode, slow  boxes are
% replaced by frames.  In order for the package to know the sizes of all of
% your boxes, you must first run through once in \opt{show} mode.
% Thereafter, all should be well. 
%
% \DescribeEnv{slowbox}
% In \opt{show} mode, the \env{slowbox} environment typesets its contents in
% LR-mode (for \TeX nicians, restricted horizontal mode).\footnote{^^A
%   Vertical mode causes all sorts of pain, and makes things way too wide.
%   Horizontal mode seems a good `standard currency' for \LaTeX\ things like
%   diagrams.} ^^A
% In \opt{hide} mode, the boxes are replaced by frames, and \TeX\ will skip
% over the contents of the environment at high speed, ignoring it
% completely.
%
% The \env{slowbox} environment needs an argument, a \emph{tag} which is used
% to identify this box.  This is needed because otherwise the package has no
% way of deciding that you've inserted some new box and need to shunt
% everything about.  So the full syntax is
% \syntax{"\\begin{slowbox}{"<tag>"}" \ldots "\\end{slowbox}"}.
% Tags can be any piece of text.  If you include control sequences in the
% tag, then they get expanded.  That might be what you want.
%
% \DescribeEnv{slowbox$*$}
% Adding new slow boxes is best done using the starred version of the
% environment.  Stuff in a \env{slowbox$*$} environment is always typset in
% \opt{show} mode, regardless of the global mode setting.  The right thing to
% do is wrap your new stuff in a \env{slowbox$*$} while you're writing it.
% Then remove the \env{$*$} and it will turn into a frame.  The
% \env{slowbox$*$} environment takes a tag name, just like \env{slowbox}
% does.
%
% \DescribeMacro\slowboxbegin
% \DescribeMacro\slowboxend
% It's useful to define your own commands environments which create slow
% boxes.  Often, though, what happens is that you want to put some stuff
% \emph{inside} the slow box, but that doesn't work properly.  What you must
% do instead is say something like
% \begin{verbatim}
%   \newenvironment{splunt}[1]
%     {...\slowboxbegin{#1}{...\startsplunt...}}
%     {\slowboxend{...\finishsplunt...}...}
% \end{verbatim}
% That is, \syntax{"\\slowboxbegin{"<tag>"}{{"<stuff>"}"} starts a slow box,
% beginning with \<stuff> if we're in \opt{show} mode.
%
% The |\slowboxbegin| command has a |*|-variant, which causes the box to be
% typeset regardless of the current mode setting.
%
% \DescribeMacro\newslowboxenv
% There's an environment for building slow box environments.  Say
% \syntax{"\\newslowboxenv{"<env-name>"}"\* "["<n-args>"]"\*
% "{"<before-text>"}"\* "{"<start-text>"}"\* "{"<end-text>"}"\*
% "{"<after-text>"}"}. This creates a new environment (just like with
% |\newenvironment|).  The contents are put in a slow box with \<start-text>
% on the front and \<end-text> on the end.  Before the box is begun,
% \<before-text> is performed, and \<after-text> is done afterwards.  The
% environments so created have \env{$*$}-variants which ignore the current
% mode, just like \env{slowbox$*$}.  They also gather an additional \<tag>
% argument, which you don't have to bother with. 
%
% \DescribeMacro\doslowbox
% Finally, for commands, there's \syntax{"\\doslowbox{"<tag>"}"\*
% "{"<stuff>"}"}.  This typesets \<stuff> in a slow box with the given tag.
% There's a |*|-variant, of course.
%
% \DescribeMacro\slowboxshow
% \DescribeMacro\slowboxhide
% \DescribeMacro\ifslowboxshow
% The declarations |\showboxshow| and |\slowboxhide| switch between the
% \opt{show} and \opt{hide} modes.  They obey standard scoping rules.
% They're probably not very useful.  They twiddle the |\ifslowboxshow| macro,
% which is an old-fashioned Plain \TeX\ switch.  If you're the sort of person
% who uses \package{ifthen}, then you can test |\boolean{slowboxshow}|.
%
%^^A-------------------------------------------------------------------------
% \implementation
%
% \section{Implementation of \package{slowbox}}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% \subsection{The mode switch}
%
% \begin{macro}{\ifslowboxshow}
% \begin{macro}{\slowboxshow}
% \begin{macro}{\slowboxhide}
% The |\if@slowboxshow| switch remembers which mode we're in.  The
% |\slowboxshow| and |\slowboxhide| macros flip the switch.  It's really
% easy.  The |\relax|es are to annoy people who say |\global\showboxshow|.
%    \begin{macrocode}
\def\slowboxshow{\relax\let\ifslowboxshow\iftrue}
\def\slowboxhide{\relax\let\ifslowboxshow\iffalse}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Dependencies}
%
% The skipping-over-stuff-at-high-speed is done by my \package{sverb}
% package.
%    \begin{macrocode}
\RequirePackage{sverb}
%    \end{macrocode}
%
% \subsection{Options}
%
% Oh, this is obvious.
%    \begin{macrocode}
\DeclareOption{show}{\slowboxshow}
\DeclareOption{hide}{\slowboxhide}
\ExecuteOptions{show}
\ProcessOptions
%    \end{macrocode}
%
% \subsection{Remembering stuff}
%
% \begin{macro}{\sb@def}
% Box dimensions are recorded in the |.aux| file using
% \syntax{"\\sb@def{"<tag>"}"\* "{"<width>"}"\* "{"<height>"}"\*
% "{"<depth>"}"}.  This turns into a definition of a strange control
% sequence.
%    \begin{macrocode}
\def\sb@def#1#2#3#4%
  {\expandafter\gdef\csname sb@box:#1\endcsname{{#2}{#3}{#4}}}
%    \end{macrocode}
% \end{macro}
%
% \subsection{The actual work}
%
% \begin{macro}{\sb@begin}
% This is where most of the intelligence is.
% \syntax{"\\sb@begin{"<tag>"}{"<stuff>"}"} starts a slow box, putting
% \<stuff> at the start if we're in \opt{show} mode.  It doesn't ignore stuff
% -- though it sets |\sb@ignore| to be |\relax| in \opt{show} mode and
% |\ignore| in \opt{hide} mode.  It also sets |\sb@end| correctly, so that
% \syntax{"\\sb@end{"<stuff>"}"} ends the current box, putting \<stuff> in
% it.
%
% Disappointingly, perhaps, this is in fact just a dispatcher to the right
% implementation.
%    \begin{macrocode}
\def\sb@begin{%
  \ifslowboxshow\expandafter\sb@begin@show%
  \else\expandafter\sb@begin@hide\fi%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\sb@begin@show}
% Now we have the implementation for \opt{show} mode.  This is sometimes
% called directly, by |*|-variants.  Needs to be |\long| because \<stuff>
% might contain embedded vmode-material which could legitimately have |\par|
% tokens in.
%    \begin{macrocode}
\long\def\sb@begin@show#1#2{%
  \begingroup%
  \def\sb@end##1{%
    ##1%
    \color@endgroup%
    \egroup%
    \immediate\write\@auxout%
      {\string\sb@def{#1}{\the\wd\z@}{\the\ht\z@}{\the\dp\z@}}%
    \leavevmode\box\z@%
    \endgroup%
  }%
  \let\sb@ignore\relax%
  \setbox\z@\hbox\bgroup\color@begingroup#2%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\sb@begin@hide}
% Now for something a bit stranger.  If we're in \opt{hide} mode, we need to
% find out whether we've saved information about this box before.  We pass
% the \emph{control sequence} containing the box dimensions to another
% macro.  Needs to be |\long| to collect the \<stuff> argument.
%    \begin{macrocode}
\long\def\sb@begin@hide#1#2{%
  \begingroup%
  \def\sb@end##1{\endgroup}%
  \let\sb@ignore\ignore%
  \expandafter\sb@hidden\csname sb@box:#1\endcsname{#1}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\sb@hidden}
% We're given the control token and the tag name.  If the control sequence is
% like |\relax| then |\csname| must have invented it and we just have to make
% something up.  Otherwise we put the right stuff in a frame.  Don't forget
% to write out the box dimensions to the new aux file!
%    \begin{macrocode}
\def\sb@hidden#1#2{%
  \ifx#1\relax\fbox{Unknown slow box \texttt{#2}!}%
  \else\edef\next@{\noexpand\sb@hidden@i#1{#2}}\expandafter\next@\fi%
}
\def\sb@hidden@i#1#2#3#4{%
  \frameonly{#1}{#2}{#3}{Omitted \texttt{#4}}%
  \immediate\write\@auxout{\string\sb@def{#4}{#1}{#2}{#3}}%  
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Stuff in frames}
%
% \begin{macro}{\frameonly}
% \syntax{"\\frameonly{"<width>"}{"<height>"}{"<depth>"}{"<stuff>"}"}
% typesets \<stuff> in a frame with the given dimensions.  This is a bit
% tricky -- we want the \<stuff> in the middle of the box, but the box's
% reference point is somewhere else.  We start with a |\vcenter| of the right
% height, and then nudge it into position later.
%
% In case the label is just too big, put shrinky glue all round.  It'll look
% horrible, but at least it won't mess everything up.
%    \begin{macrocode}
\def\frameonly#1#2#3#4{%
  \dimen\tw@#2\advance\dimen\tw@#3\advance\dimen\tw@-.8\p@%
  \setbox\z@\hbox{$\vcenter{\hrule\@height\dimen\tw@\@depth\z@}$}%
  \dimen@#1%
  \advance\dimen@-.8\p@%
  \setbox\z@\vbox{%
    \hrule\vss%
    \hb@xt@\dimen@{%
      \vrule\@height\ht\z@\@depth\dp\z@\hss%
      \advance\dimen@-2em%
      \parbox\dimen@{\centering#4}%
      \hss\vrule}%
    \vss\hrule%
  }%
  \dimen@#3\advance\dimen@-\dp\z@%
  \setbox\z@\hbox{\lower\dimen@\box\z@}%
  \leavevmode\box\z@%  
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{User commands}
%
% \begin{macro}{\slowboxbegin}
% \begin{macro}{\slowboxend}
% This is just a matter of using the machinery we've built already.
%    \begin{macrocode}
\def\slowboxbegin{\@ifstar{\sb@go\sb@begin}{\sb@go\sb@begin@show}}
\long\def\sb@go#1#2#3{#1{#2}{#3}\sb@ignore}
\def\slowboxend{\sb@end}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\doslowbox}
% And this too.
%    \begin{macrocode}
\def\doslowbox{\@ifstar{\sb@do\sb@begin}{\sb@do\sb@begin@show}}
\long\def\sb@do#1#2#3{#1{#2}{#3}\sb@end}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\newslowboxenv}
% Something a bit more interesting now.  Gathering the optional arguments for
% |\newenvironment| is a bit tedious, but we do it anyway.  Picking up the
% arguments for the environment is a bit tricky -- they come in the wrong
% order, unfortunately.
%    \begin{macrocode}
\def\newslowboxenv#1{\@ifnextchar[{\sb@nenv@i{#1}}{\sb@nenv@do{#1}{}}}
\def\sb@nenv@i#1[#2]{%
  \@ifnextchar[{\sb@nenv@ii{#1}{[{#2}]}}{\sb@nenv@do{#1}{[{#2}]}}%
}
\def\sb@nenv@ii#1#2[#3]{\sb@nenv@do{#1}{#2[{#2}]}}
\long\def\sb@nenv@do#1#2#3#4#5#6{%
  \newenvironment{#1}#2{#3\sb@env\sb@begin{#4}}{\sb@end{#5}#6}%
  \newenvironment{#1*}#2{#3\sb@env\sb@begin@show{#4}}{\sb@end{#5}#6}%
}
\def\sb@env#1#2#3{#1{#3}{#2}\sb@ignore}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{slowbox}
% And the \env{slowbox} is built using the above equipment.
%    \begin{macrocode}
\newslowboxenv{slowbox}{}{}{}{}
%    \end{macrocode}
% \end{environment}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \Finale
\endinput