Commit | Line | Data |
---|---|---|
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 |