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