| 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 |