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