infra: Expunge revision history clutter.
[mdwtools] / slowbox.dtx
1 % \begin{meta-comment}
2 %
3 % $Id: slowbox.dtx,v 1.2 2003/09/06 13:08:16 mdw Exp $
4 %
5 % Cop-out for slow things
6 %
7 % (c) 2003 Mark Wooding
8 %
9 % \end{meta-comment}
10 %
11 % \begin{meta-comment} <general public licence>
12 %%
13 %% slowbox package -- skipping of slow boxes
14 %% Copyright (c) 2003 Mark Wooding
15 %%
16 %% This program is free software; you can redistribute it and/or modify
17 %% it under the terms of the GNU General Public License as published by
18 %% the Free Software Foundation; either version 2 of the License, or
19 %% (at your option) any later version.
20 %%
21 %% This program is distributed in the hope that it will be useful,
22 %% but WITHOUT ANY WARRANTY; without even the implied warranty of
23 %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 %% GNU General Public License for more details.
25 %%
26 %% You should have received a copy of the GNU General Public License
27 %% along with this program; if not, write to the Free Software Foundation,
28 %% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 % \end{meta-comment}
30 %
31 % \begin{meta-comment} <Package preambles>
32 %<+package>\NeedsTeXFormat{LaTeX2e}
33 %<+package>\ProvidesPackage{slowbox}
34 %<+package> [2003/08/27 1.0 skipping of slow boxes]
35 % \end{meta-comment}
36 %
37 % \CheckSum{222}
38 %% \CharacterTable
39 %% {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
40 %% 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
41 %% Digits \0\1\2\3\4\5\6\7\8\9
42 %% Exclamation \! Double quote \" Hash (number) \#
43 %% Dollar \$ Percent \% Ampersand \&
44 %% Acute accent \' Left paren \( Right paren \)
45 %% Asterisk \* Plus \+ Comma \,
46 %% Minus \- Point \. Solidus \/
47 %% Colon \: Semicolon \; Less than \<
48 %% Equals \= Greater than \> Question mark \?
49 %% Commercial at \@ Left bracket \[ Backslash \\
50 %% Right bracket \] Circumflex \^ Underscore \_
51 %% Grave accent \` Left brace \{ Vertical bar \|
52 %% Right brace \} Tilde \~}
53 %%
54 %
55 % \begin{meta-comment}
56 %
57 %<*driver>
58 \input{mdwtools}
59 \describespackage{slowbox}
60 \newcommand\opt[1]{\textsf{#1}}
61 \expandafter\def\csname sb@box:tag\endcsname{{2cm}{1cm}{0.5cm}}
62 \def\*{\hspace{0pt plus 0.1pt}\ignorespaces}
63 \mdwdoc
64 %</driver>
65 %
66 % \end{meta-comment}
67 %
68 %^^A-------------------------------------------------------------------------
69 % \section{User guide}
70 %
71 % The problem is that some things, e.g., diagrams, can take a while to
72 % typeset, and aren't particularly interesting as far as the global document
73 % layout is concerned. Once you've got a diagram right, the only thing that
74 % matters as far as general previewing is concerned is its size.
75 %
76 % The solution is \package{slowbox}. Put things you're usually not
77 % interested in seeing in a \env{slowbox} environment. Then they get
78 % replaced by a frame saying that there's meant to be something there, and
79 % that's it.
80 %
81 % There are two modes, chosen by package options: \opt{show} and \opt{hide}.
82 % The default is \opt{show} mode, because I had to pick one. In \opt{show}
83 % mode, everything happens normally; in \opt{hide} mode, slow boxes are
84 % replaced by frames. In order for the package to know the sizes of all of
85 % your boxes, you must first run through once in \opt{show} mode.
86 % Thereafter, all should be well.
87 %
88 % \DescribeEnv{slowbox}
89 % In \opt{show} mode, the \env{slowbox} environment typesets its contents in
90 % LR-mode (for \TeX nicians, restricted horizontal mode).\footnote{^^A
91 % Vertical mode causes all sorts of pain, and makes things way too wide.
92 % Horizontal mode seems a good `standard currency' for \LaTeX\ things like
93 % diagrams.} ^^A
94 % In \opt{hide} mode, the boxes are replaced by frames, and \TeX\ will skip
95 % over the contents of the environment at high speed, ignoring it
96 % completely.
97 %
98 % The \env{slowbox} environment needs an argument, a \emph{tag} which is used
99 % to identify this box. This is needed because otherwise the package has no
100 % way of deciding that you've inserted some new box and need to shunt
101 % everything about. So the full syntax is
102 % \syntax{"\\begin{slowbox}{"<tag>"}" \ldots "\\end{slowbox}"}.
103 % Tags can be any piece of text. If you include control sequences in the
104 % tag, then they get expanded. That might be what you want.
105 %
106 % \DescribeEnv{slowbox$*$}
107 % Adding new slow boxes is best done using the starred version of the
108 % environment. Stuff in a \env{slowbox$*$} environment is always typset in
109 % \opt{show} mode, regardless of the global mode setting. The right thing to
110 % do is wrap your new stuff in a \env{slowbox$*$} while you're writing it.
111 % Then remove the \env{$*$} and it will turn into a frame. The
112 % \env{slowbox$*$} environment takes a tag name, just like \env{slowbox}
113 % does.
114 %
115 % \DescribeMacro\slowboxbegin
116 % \DescribeMacro\slowboxend
117 % It's useful to define your own commands environments which create slow
118 % boxes. Often, though, what happens is that you want to put some stuff
119 % \emph{inside} the slow box, but that doesn't work properly. What you must
120 % do instead is say something like
121 % \begin{verbatim}
122 % \newenvironment{splunt}[1]
123 % {...\slowboxbegin{#1}{...\startsplunt...}}
124 % {\slowboxend{...\finishsplunt...}...}
125 % \end{verbatim}
126 % That is, \syntax{"\\slowboxbegin{"<tag>"}{{"<stuff>"}"} starts a slow box,
127 % beginning with \<stuff> if we're in \opt{show} mode.
128 %
129 % The |\slowboxbegin| command has a |*|-variant, which causes the box to be
130 % typeset regardless of the current mode setting.
131 %
132 % \DescribeMacro\newslowboxenv
133 % There's an environment for building slow box environments. Say
134 % \syntax{"\\newslowboxenv{"<env-name>"}"\* "["<n-args>"]"\*
135 % "{"<before-text>"}"\* "{"<start-text>"}"\* "{"<end-text>"}"\*
136 % "{"<after-text>"}"}. This creates a new environment (just like with
137 % |\newenvironment|). The contents are put in a slow box with \<start-text>
138 % on the front and \<end-text> on the end. Before the box is begun,
139 % \<before-text> is performed, and \<after-text> is done afterwards. The
140 % environments so created have \env{$*$}-variants which ignore the current
141 % mode, just like \env{slowbox$*$}. They also gather an additional \<tag>
142 % argument, which you don't have to bother with.
143 %
144 % \DescribeMacro\doslowbox
145 % Finally, for commands, there's \syntax{"\\doslowbox{"<tag>"}"\*
146 % "{"<stuff>"}"}. This typesets \<stuff> in a slow box with the given tag.
147 % There's a |*|-variant, of course.
148 %
149 % \DescribeMacro\slowboxshow
150 % \DescribeMacro\slowboxhide
151 % \DescribeMacro\ifslowboxshow
152 % The declarations |\showboxshow| and |\slowboxhide| switch between the
153 % \opt{show} and \opt{hide} modes. They obey standard scoping rules.
154 % They're probably not very useful. They twiddle the |\ifslowboxshow| macro,
155 % which is an old-fashioned Plain \TeX\ switch. If you're the sort of person
156 % who uses \package{ifthen}, then you can test |\boolean{slowboxshow}|.
157 %
158 %^^A-------------------------------------------------------------------------
159 % \implementation
160 %
161 % \section{Implementation of \package{slowbox}}
162 %
163 % \begin{macrocode}
164 %<*package>
165 % \end{macrocode}
166 %
167 % \subsection{The mode switch}
168 %
169 % \begin{macro}{\ifslowboxshow}
170 % \begin{macro}{\slowboxshow}
171 % \begin{macro}{\slowboxhide}
172 % The |\if@slowboxshow| switch remembers which mode we're in. The
173 % |\slowboxshow| and |\slowboxhide| macros flip the switch. It's really
174 % easy. The |\relax|es are to annoy people who say |\global\showboxshow|.
175 % \begin{macrocode}
176 \def\slowboxshow{\relax\let\ifslowboxshow\iftrue}
177 \def\slowboxhide{\relax\let\ifslowboxshow\iffalse}
178 % \end{macrocode}
179 % \end{macro}
180 % \end{macro}
181 % \end{macro}
182 %
183 % \subsection{Dependencies}
184 %
185 % The skipping-over-stuff-at-high-speed is done by my \package{sverb}
186 % package.
187 % \begin{macrocode}
188 \RequirePackage{sverb}
189 % \end{macrocode}
190 %
191 % \subsection{Options}
192 %
193 % Oh, this is obvious.
194 % \begin{macrocode}
195 \DeclareOption{show}{\slowboxshow}
196 \DeclareOption{hide}{\slowboxhide}
197 \ExecuteOptions{show}
198 \ProcessOptions
199 % \end{macrocode}
200 %
201 % \subsection{Remembering stuff}
202 %
203 % \begin{macro}{\sb@def}
204 % Box dimensions are recorded in the |.aux| file using
205 % \syntax{"\\sb@def{"<tag>"}"\* "{"<width>"}"\* "{"<height>"}"\*
206 % "{"<depth>"}"}. This turns into a definition of a strange control
207 % sequence.
208 % \begin{macrocode}
209 \def\sb@def#1#2#3#4%
210 {\expandafter\gdef\csname sb@box:#1\endcsname{{#2}{#3}{#4}}}
211 % \end{macrocode}
212 % \end{macro}
213 %
214 % \subsection{The actual work}
215 %
216 % \begin{macro}{\sb@begin}
217 % This is where most of the intelligence is.
218 % \syntax{"\\sb@begin{"<tag>"}{"<stuff>"}"} starts a slow box, putting
219 % \<stuff> at the start if we're in \opt{show} mode. It doesn't ignore stuff
220 % -- though it sets |\sb@ignore| to be |\relax| in \opt{show} mode and
221 % |\ignore| in \opt{hide} mode. It also sets |\sb@end| correctly, so that
222 % \syntax{"\\sb@end{"<stuff>"}"} ends the current box, putting \<stuff> in
223 % it.
224 %
225 % Disappointingly, perhaps, this is in fact just a dispatcher to the right
226 % implementation.
227 % \begin{macrocode}
228 \def\sb@begin{%
229 \ifslowboxshow\expandafter\sb@begin@show%
230 \else\expandafter\sb@begin@hide\fi%
231 }
232 % \end{macrocode}
233 % \end{macro}
234 %
235 % \begin{macro}{\sb@begin@show}
236 % Now we have the implementation for \opt{show} mode. This is sometimes
237 % called directly, by |*|-variants. Needs to be |\long| because \<stuff>
238 % might contain embedded vmode-material which could legitimately have |\par|
239 % tokens in.
240 % \begin{macrocode}
241 \long\def\sb@begin@show#1#2{%
242 \begingroup%
243 \def\sb@end##1{%
244 ##1%
245 \color@endgroup%
246 \egroup%
247 \immediate\write\@auxout%
248 {\string\sb@def{#1}{\the\wd\z@}{\the\ht\z@}{\the\dp\z@}}%
249 \leavevmode\box\z@%
250 \endgroup%
251 }%
252 \let\sb@ignore\relax%
253 \setbox\z@\hbox\bgroup\color@begingroup#2%
254 }
255 % \end{macrocode}
256 % \end{macro}
257 %
258 % \begin{macro}{\sb@begin@hide}
259 % Now for something a bit stranger. If we're in \opt{hide} mode, we need to
260 % find out whether we've saved information about this box before. We pass
261 % the \emph{control sequence} containing the box dimensions to another
262 % macro. Needs to be |\long| to collect the \<stuff> argument.
263 % \begin{macrocode}
264 \long\def\sb@begin@hide#1#2{%
265 \begingroup%
266 \def\sb@end##1{\endgroup}%
267 \let\sb@ignore\ignore%
268 \expandafter\sb@hidden\csname sb@box:#1\endcsname{#1}%
269 }
270 % \end{macrocode}
271 % \end{macro}
272 %
273 % \begin{macro}{\sb@hidden}
274 % We're given the control token and the tag name. If the control sequence is
275 % like |\relax| then |\csname| must have invented it and we just have to make
276 % something up. Otherwise we put the right stuff in a frame. Don't forget
277 % to write out the box dimensions to the new aux file!
278 % \begin{macrocode}
279 \def\sb@hidden#1#2{%
280 \ifx#1\relax\fbox{Unknown slow box \texttt{#2}!}%
281 \else\edef\next@{\noexpand\sb@hidden@i#1{#2}}\expandafter\next@\fi%
282 }
283 \def\sb@hidden@i#1#2#3#4{%
284 \frameonly{#1}{#2}{#3}{Omitted \texttt{#4}}%
285 \immediate\write\@auxout{\string\sb@def{#4}{#1}{#2}{#3}}%
286 }
287 % \end{macrocode}
288 % \end{macro}
289 %
290 % \subsection{Stuff in frames}
291 %
292 % \begin{macro}{\frameonly}
293 % \syntax{"\\frameonly{"<width>"}{"<height>"}{"<depth>"}{"<stuff>"}"}
294 % typesets \<stuff> in a frame with the given dimensions. This is a bit
295 % tricky -- we want the \<stuff> in the middle of the box, but the box's
296 % reference point is somewhere else. We start with a |\vcenter| of the right
297 % height, and then nudge it into position later.
298 %
299 % In case the label is just too big, put shrinky glue all round. It'll look
300 % horrible, but at least it won't mess everything up.
301 % \begin{macrocode}
302 \def\frameonly#1#2#3#4{%
303 \dimen\tw@#2\advance\dimen\tw@#3\advance\dimen\tw@-.8\p@%
304 \setbox\z@\hbox{$\vcenter{\hrule\@height\dimen\tw@\@depth\z@}$}%
305 \dimen@#1%
306 \advance\dimen@-.8\p@%
307 \setbox\z@\vbox{%
308 \hrule\vss%
309 \hb@xt@\dimen@{%
310 \vrule\@height\ht\z@\@depth\dp\z@\hss%
311 \advance\dimen@-2em%
312 \parbox\dimen@{\centering#4}%
313 \hss\vrule}%
314 \vss\hrule%
315 }%
316 \dimen@#3\advance\dimen@-\dp\z@%
317 \setbox\z@\hbox{\lower\dimen@\box\z@}%
318 \leavevmode\box\z@%
319 }
320 % \end{macrocode}
321 % \end{macro}
322 %
323 % \subsection{User commands}
324 %
325 % \begin{macro}{\slowboxbegin}
326 % \begin{macro}{\slowboxend}
327 % This is just a matter of using the machinery we've built already.
328 % \begin{macrocode}
329 \def\slowboxbegin{\@ifstar{\sb@go\sb@begin}{\sb@go\sb@begin@show}}
330 \long\def\sb@go#1#2#3{#1{#2}{#3}\sb@ignore}
331 \def\slowboxend{\sb@end}
332 % \end{macrocode}
333 % \end{macro}
334 % \end{macro}
335 %
336 % \begin{macro}{\doslowbox}
337 % And this too.
338 % \begin{macrocode}
339 \def\doslowbox{\@ifstar{\sb@do\sb@begin}{\sb@do\sb@begin@show}}
340 \long\def\sb@do#1#2#3{#1{#2}{#3}\sb@end}
341 % \end{macrocode}
342 % \end{macro}
343 %
344 % \begin{macro}{\newslowboxenv}
345 % Something a bit more interesting now. Gathering the optional arguments for
346 % |\newenvironment| is a bit tedious, but we do it anyway. Picking up the
347 % arguments for the environment is a bit tricky -- they come in the wrong
348 % order, unfortunately.
349 % \begin{macrocode}
350 \def\newslowboxenv#1{\@ifnextchar[{\sb@nenv@i{#1}}{\sb@nenv@do{#1}{}}}
351 \def\sb@nenv@i#1[#2]{%
352 \@ifnextchar[{\sb@nenv@ii{#1}{[{#2}]}}{\sb@nenv@do{#1}{[{#2}]}}%
353 }
354 \def\sb@nenv@ii#1#2[#3]{\sb@nenv@do{#1}{#2[{#2}]}}
355 \long\def\sb@nenv@do#1#2#3#4#5#6{%
356 \newenvironment{#1}#2{#3\sb@env\sb@begin{#4}}{\sb@end{#5}#6}%
357 \newenvironment{#1*}#2{#3\sb@env\sb@begin@show{#4}}{\sb@end{#5}#6}%
358 }
359 \def\sb@env#1#2#3{#1{#3}{#2}\sb@ignore}
360 % \end{macrocode}
361 % \end{macro}
362 %
363 % \begin{environment}{slowbox}
364 % And the \env{slowbox} is built using the above equipment.
365 % \begin{macrocode}
366 \newslowboxenv{slowbox}{}{}{}{}
367 % \end{macrocode}
368 % \end{environment}
369 %
370 % \begin{macrocode}
371 %</package>
372 % \end{macrocode}
373 %
374 % \Finale
375 \endinput