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