New feature\!
authormdw <mdw>
Fri, 5 Sep 2003 16:09:57 +0000 (16:09 +0000)
committermdw <mdw>
Fri, 5 Sep 2003 16:09:57 +0000 (16:09 +0000)
centre.dtx [new file with mode: 0644]
colour.dtx [new file with mode: 0644]
mdwkey.dtx [new file with mode: 0644]
slowbox.dtx [new file with mode: 0644]

diff --git a/centre.dtx b/centre.dtx
new file mode 100644 (file)
index 0000000..3424cbf
--- /dev/null
@@ -0,0 +1,117 @@
+% \begin{meta-comment}
+%
+% $Id: centre.dtx,v 1.1 2003/09/05 16:09:56 mdw Exp $
+%
+% UK spellings of `centre'
+%
+% (c) 2003 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: centre.dtx,v $
+% Revision 1.1  2003/09/05 16:09:56  mdw
+% New feature\!
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% centre package -- center, only spelt correctly
+%% Copyright (c) 2003 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{centre}
+%<+package>                [2003/08/24 1.0 center, only spelt correctly]
+% \end{meta-comment}
+%
+% \CheckSum{21}
+%% \CharacterTable
+%%  {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
+%%   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
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{centre}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \section{User guide}
+%
+% \DescribeMacro\vcentre
+% \DescribeEnv{centre}
+% \DescribeMacro\centring
+% \DescribeMacro\centreline
+% \DescribeMacro\textasteriskcentred
+% \DescribeMacro\textdotcentred
+% More of my ranting about American spellings.  A bunch of synonyms for those
+% whose spelling of `centre' is French-influenced.
+%
+%
+%^^A-------------------------------------------------------------------------
+% \implementation
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% And add new definitions.
+%
+%    \begin{macrocode}
+\let\vcentre\vcenter
+\let\centre\center
+\let\endcentre\endcenter
+\let\centring\centering
+\let\centreline\centerline
+\let\textasteriskcentred\textasteriskcentered
+\let\textdotcentred\textperiodcentered
+%    \end{macrocode}
+%
+% That's all there is.  Byebye.
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+% \nopagebreak
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/colour.dtx b/colour.dtx
new file mode 100644 (file)
index 0000000..685274b
--- /dev/null
@@ -0,0 +1,121 @@
+% \begin{meta-comment}
+%
+% $Id: colour.dtx,v 1.1 2003/09/05 16:09:57 mdw Exp $
+%
+% UK spellings of `colour'
+%
+% (c) 2003 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: colour.dtx,v $
+% Revision 1.1  2003/09/05 16:09:57  mdw
+% New feature\!
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% colour package -- color, only spelt correctly
+%% Copyright (c) 2003 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{colour}
+%<+package>                [2003/08/24 1.0 color, only spelt correctly]
+% \end{meta-comment}
+%
+% \CheckSum{26}
+%% \CharacterTable
+%%  {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
+%%   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
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{colour}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \section{User guide}
+%
+% This is the |\package{color}| package, with the addition of English
+% spellings to the American misspellings.  In particular, it provides
+% commands |\colour|, |\definecolour|, |\textcolour|, |\pagecolour|,
+% |\colourbox| and |\fcolourbox| commands.  It also provides a \textsf{grey}
+% colour model, which works the same as \textsf{gray}.
+%
+%^^A-------------------------------------------------------------------------
+% \implementation
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% Import the \package{color} package.
+%
+%    \begin{macrocode}
+\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{color}}
+\ProcessOptions
+\RequirePackage{color}
+%    \end{macrocode}
+%
+% And add new definitions.
+%
+%    \begin{macrocode}
+\let\colour\color
+\let\definecolour\definecolor
+\let\textcolour\textcolor
+\let\pagecolour\pagecolor
+\let\colourbox\colorbox
+\let\fcolourbox\fcolorbox
+\let\color@grey\color@gray
+%    \end{macrocode}
+%
+% That's all there is.  Byebye.
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+% \nopagebreak
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/mdwkey.dtx b/mdwkey.dtx
new file mode 100644 (file)
index 0000000..b00e6ec
--- /dev/null
@@ -0,0 +1,391 @@
+% \begin{meta-comment}
+%
+% $Id: mdwkey.dtx,v 1.1 2003/09/05 16:09:56 mdw Exp $
+%
+% Parsing key/value pairs
+%
+% (c) 2003 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: mdwkey.dtx,v $
+% Revision 1.1  2003/09/05 16:09:56  mdw
+% New feature\!
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwkey package -- yet another key/value parser
+%% Copyright (c) 2003 Mark Wooding
+%<*package>
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%</package>
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preamble>
+%<+package&!plain>\NeedsTeXFormat{LaTeX2e}
+%<+package&!plain>\ProvidesPackage{mdwkey}
+%<+package&!plain>                [2003/08/21 1.0 key/value parser]
+% \end{meta-comment}
+%
+% \CheckSum{316}
+%\iffalse
+%<*package>
+%\fi
+%% \CharacterTable
+%%  {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
+%%   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
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%\iffalse
+%</package>
+%\fi
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{mdwkey}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \section{User's guide}
+%
+% This is a key/value-pair parser, rather like the one in David Carlisle's
+% \package{keyval} package but a little more powerful.  There's no problem
+% with having both in the same program.
+%
+% \subsection{Terminology}
+%
+% A \emph{key-value pair} is a pair \syntax{<key> `=' <value>}, where the
+% \lit{=} appears at the topmost bracing level.  A \emph{tag} is just a
+% single \syntax{<key>}.  A \emph{list} is a sequence of key-value pairs and
+% tags separated by commas \lit{,} at the topmost bracing level.  A \<key> or
+% \<value> has a leading and/or trailing space removed, if there are any, and
+% if the whole thing is enclosed in braces, then the braces are removed.
+% Examples:
+% \begin{itemize} \synshorts
+% \item "foo = bar" is a key-value pair.  The key is `foo' and the value is
+%   `bar'. 
+% \item `{foo = bar}' is a tag.  The key is `foo = bar'.
+% \item `foo = { bar }' is a key-value pair.  The key is `foo' and
+%   the value is ` bar ' (with the leading and trailing spaces).
+% \item `foo = { bar }x' is a key-value pair.  The key is `foo' and
+%   the value is `{ bar }x'.
+% \item `one, two' is a list of two tags, `one' and `two'.
+% \item `one, {two, three}' is a list of two tags, `one' and `two, three'.
+% \end{itemize}
+% There is no way to get an unmatched brace into a \<key> or \<value> without
+% stupid catcode tricks.
+%
+% \subsection{Using the system}
+%
+% \DescribeMacro\mkdef
+% New key names, and what to do when they're encountered, is all defined
+% using |\mkdef|.  Keys are gathered into \emph{groups}, so that lots of
+% people can use the system without treading on their toes.  I recommend that
+% people use \syntax{<package-name>":"<label>} for their group names.
+%
+% There's a lot which can be done using |\mkdef|.
+% \begin{itemize} \synshorts
+% \item "\\mkdef{"<group>"}{"<key>"}{"<stuff>"}" will perform <stuff> when
+%   <key> is given a value: the value is available as "#1" in <stuff>.
+% \item "\\mkdef{"<group>"}{"<key>"}["<default>"]{"<stuff>"}" is the same,
+%   but additionally if <key> is found as a tag, then treat it as if we found
+%   <key>"={"<default>"}" instead. 
+% \item "\\mkdef{"<group>"}{"<key>"}*{"<stuff>"}" will perform <stuff> when
+%   <key> is found as a tag. 
+% \item "\\mkdef*{"<group>"}{"<stuff>"}" will perform <stuff> when an unknown
+%   key (one for which there is no specific definition in this group) is
+%   given a value: the key is available as "#1" and the value as "#2" in
+%   <stuff>. 
+% \item "\\mkdef*{"<group>"}["<default>"]{"<stuff>"}" is the same, but
+%   additionally if an unknown key is found as a tag then treat it as if 
+%   it had been assigned the value <default> instead.
+% \item "\\mkdef*{"<group>"}*{"<stuff>"}" will perform <stuff> when  an
+%   unknown key is found as a tag: the key is available as "#1" in <stuff>.
+% \end{itemize}
+%
+% \DescribeMacro\mkparse
+% All that remains now is to learn how to use the thing.  Once you have a
+% list, you can say \syntax{"\\mkparse{"<group>"}{"<list>"}"} to perform all
+% the appropriate actions.  (This will mess up |\toks0| and |\next@| and some
+% other standard scratch macros.)
+%
+%^^A-------------------------------------------------------------------------
+% \implementation
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*package|macro>
+%    \end{macrocode}
+%
+% \subsection{Provide bits of \LaTeX\ for plain \TeX}
+%
+% This lot is the infrastructure needed to make the macros work under Plain
+% \TeX.
+%
+%    \begin{macrocode}
+%<*plain>
+\edef\done{\catcode`\noexpand\@=\the\catcode`\@}
+\catcode`\@=11
+\def\@gobble#1{}
+\def\@firstoftwo#1#2{#1}
+\def\@firstofthree#1#2#3{#1}
+\def\@secondoftwo#1#2{#2}
+\def\@ifnextchar#1#2#3{%
+  \def\next@{%
+    \ifx\char@#1\expandafter\@firstoftwo%
+    \else\expandafter\@secondoftwo\fi{#2}{#3}%
+  }%
+  \@ifn@i%
+}
+\def\@ifn@i{\futurelet\char@\@ifn@ii}
+\def\@ifn@ii{%
+  \ifx\char@\@sptoken\expandafter\@ifn@i\else%
+  \expandafter\next@\fi%
+}
+\def\@ifstar#1#2{%
+  \def\next@{%
+    \ifx\char@*\expandafter\@firstofthree%
+    \else\expandafter\@secondoftwo\fi{#1}{#2}%
+  }%
+  \futurelet\char@\next@%
+}
+\def\@namedef#1{\expandafter\def\csname#1\endcsname}
+\def\PackageError#1#2#3{\errhelp{#3}\errmessage{#1 error: #2}\errhelp{}}
+%</plain>
+%    \end{macrocode}
+%
+% \subsection{Removing spaces}
+%
+% \begin{macro}{\withoutspaces}
+%
+% Saying \syntax{"\\withoutspaces{"<macro>"}{"<stuff>"}"} calls \<macro>,
+% passing it the argument which is \<stuff>, shorn of (a) a single leading
+% and/or space token, and (b) a single layer of |{|\ldots|}| grouping, if
+% present.  This improves over \package{keyval}'s attempt by being a little
+% simpler and only stripping off one layer of braces.
+%
+%    \begin{macrocode}
+\def\q@delim{\q@delim}
+\def\next@#1{%
+\let\@sptoken=#1
+\def\withoutspaces##1##2{%
+  \def\next@{##1}\futurelet\char@\wsp@i##2%
+  \q@delim#1\q@delim\q@delim\relax%
+}
+\def\wsp@i{%
+  \ifx\char@\@sptoken\expandafter\wsp@ii%
+  \else\expandafter\wsp@iii\fi%
+}
+\def\wsp@ii#1{\wsp@iii}
+\def\wsp@iii##1#1\q@delim##2\relax{\wsp@iv##1\q@delim\relax}
+\def\wsp@iv##1\q@delim##2\relax{\next@{##1}}
+}\next@{ }
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\withoutspacesdef}
+%
+% As a trivial but useful application of the above,
+% \syntax{"\\withoutspacesdef{"<name>"}{"<stuff>"}"} defines \<name> as a
+% macro containing \<stuff> with a leading and trailing space deleted and a
+% level of bracing removed.
+%
+%    \begin{macrocode}
+\def\withoutspacesdef#1#2{\withspaces\toks@{#2}\edef#1{\the\toks@}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Parsing key/value lists}
+%
+% \begin{macro}{\mkparse}
+%
+% The main parser macro.  Stash some information away and then start on the
+% main loop.
+%
+%    \begin{macrocode}
+\def\mkparse#1#2{%
+  \def\mk@group{#1}%
+  \def\mk@{mk$#1$}%
+  \mk@loop!#2,\q@delim,\relax%
+}
+%    \end{macrocode}
+%
+% And already the subtlety begins.  Note that there's a leading \lit{!} at
+% the front of the token list.  This prevents our delimited argument from
+% being entirely brace-enclosed, which in turn stops \TeX\ from removing it
+% until we're good and ready.
+%
+% This doesn't trap empty items -- that happens later.
+%
+%    \begin{macrocode}
+\def\mk@loop#1,{%
+  \expandafter\def\expandafter\next@\expandafter{\@gobble#1}%
+  \ifx\next@\q@delim\expandafter\mk@x%
+  \else\mk@i#1=\q@delim\expandafter\mk@loop\expandafter!\fi%
+}
+\def\mk@x#1\relax{\relax}
+%    \end{macrocode}
+%
+% Now we have to split an entry into a key and a value.  If we have
+% \<key>|=|\<value> then |#1| = |!|\<key> and |#2| = \<value>|=|; if we have
+% only \<key>, then |#1| = |!|\<key> as before, and |#2| is empty.  The first
+% thing to do is strip the |!| and spaces from |#1|.  If |#2| is empty then
+% we're done with this stage and can just call |\mk@k| with what we've got;
+% otherwise we swap the trailing |=| on |#2| for a leading |!| and strip that
+% off, and then call |\mk@kv| with the answer.
+%
+%    \begin{macrocode}
+\def\mk@i#1=#2\q@delim{%
+  \expandafter\withoutspaces\expandafter%
+    \mk@ii\expandafter{\@gobble#1}{#2}%
+}
+\def\mk@ii#1#2{%
+  \ifx\q@delim#2\q@delim\mk@k{#1}%
+  \else\mk@iii{#1}!#2\q@delim\fi%
+}
+\def\mk@iii#1#2=\q@delim{%
+  \expandafter\withoutspaces\expandafter%
+    \mk@iv\expandafter{\@gobble#2}{#1}%
+}
+\def\mk@iv#1#2{\mk@kv{#2}{#1}}
+%    \end{macrocode}
+%
+% We just have \<key>, shorn of spaces and outer braces.  If it's empty then
+% the whole entry was empty and we should ignore it.  Otherwise, if there's a
+% defined command for handling the token then we use that; if not, then we
+% look for a general unknown-key command.  If nothing works, we raise an
+% error.
+%
+%    \begin{macrocode}
+\def\mk@k#1{%
+  \ifx\q@delim#1\q@delim\else%
+    \expandafter\let\expandafter\next@\csname\mk@!#1\endcsname%
+    \ifx\next@\relax%
+      \expandafter\let\expandafter\next@\csname\mk@*!\endcsname%
+      \ifx\next@\relax\mk@err{#1}%
+      \else\next@{#1}\fi%
+    \else\next@\fi%
+  \fi%
+  }
+%    \end{macrocode}
+%
+% We have a \<key> and a \<value>, both stripped of spaces and braces.  If
+% there's a command for this key, then give it the value; otherwise look for
+% a general unknown-key-with-value command.  If nothing works, raise an
+% error.
+%
+%    \begin{macrocode}
+\def\mk@kv#1#2{%
+  \expandafter\let\expandafter\next@\csname\mk@=#1\endcsname%
+  \ifx\next@\relax%
+    \expandafter\let\expandafter\next@\csname\mk@*=\endcsname%
+    \ifx\next@\relax\mk@err{#1}%
+    \else\next@{#1}{#2}\fi%
+  \else\next@{#2}\fi%
+}
+%    \end{macrocode}
+%
+% How to raise an error.  Not so difficult.
+%
+%    \begin{macrocode}
+\def\mk@err#1{%
+  \PackageError{mdwkey}{Key `#1' not found in group `\mk@group'}{%
+    I've never heard of the key you tried to set.  I'm going to ignore it.
+  }
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Defining keys}
+%
+% \begin{macro}{\mkdefkey}
+%
+% This is all quite dull, really.  I tried to merge the two cases, but it
+% failed because I can't pass around macro parameter names through
+% |\@ifnextchar| and their friends.  If anyone has any bright ideas, I'd be
+% delighted.
+%
+%    \begin{macrocode}
+\def\mkdef{\@ifstar\mkdef@star@\mkdef@}
+\def\mkdef@#1#2{%
+  \@ifstar%
+    {\mkdef@ii{#1}{#2}}%
+    {\@ifnextchar[%
+      {\mkdef@iii{#1}{#2}}%
+      {\mkdef@i{#1}{#2}}}%
+}
+\def\mkdef@i#1#2{\@namedef{mk$#1$=#2}##1}
+\def\mkdef@ii#1#2{\@namedef{mk$#1$!#2}}
+\def\mkdef@iii#1#2[#3]{%
+  \toks@{#3}%
+  \expandafter\edef\csname mk$#1$!#2\endcsname%
+    {\expandafter\noexpand\csname mk$#1$=#2\endcsname{\the\toks@}}%
+  \@namedef{mk$#1$=#2}##1%
+}
+\def\mkdef@star@#1{%
+  \@ifstar%
+    {\mkdef@star@ii{#1}}%
+    {\@ifnextchar[%
+      {\mkdef@star@iii{#1}}%
+      {\mkdef@star@i{#1}}}%
+}
+\def\mkdef@star@i#1{\@namedef{mk$#1$*=}##1##2}
+\def\mkdef@star@ii#1{\@namedef{mk$#1$*!}##1}
+\def\mkdef@star@iii#1[#2]{%
+  \toks@{#2}%
+  \expandafter\edef\csname mk$#1$*!\endcsname##1%
+    {\expandafter\noexpand\csname mk$#1$*=\endcsname{##1}{\the\toks@}}%
+  \@namedef{mk$#1$*=}##1##2%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% And with that, we're done.
+%
+%    \begin{macrocode}
+%<+plain>\done
+%</package|macro>
+%    \end{macrocode}
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/slowbox.dtx b/slowbox.dtx
new file mode 100644 (file)
index 0000000..f713feb
--- /dev/null
@@ -0,0 +1,382 @@
+% \begin{meta-comment}
+%
+% $Id: slowbox.dtx,v 1.1 2003/09/05 16:09:56 mdw Exp $
+%
+% Cop-out for slow things
+%
+% (c) 2003 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: slowbox.dtx,v $
+% Revision 1.1  2003/09/05 16:09:56  mdw
+% New feature\!
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% slowbox package -- skipping of slow boxes
+%% Copyright (c) 2003 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%% 
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%% 
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software Foundation,
+%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{slowbox}
+%<+package>                [2003/08/27 1.0 skipping of slow boxes]
+% \end{meta-comment}
+%
+% \CheckSum{221}
+%% \CharacterTable
+%%  {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
+%%   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
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{slowbox}
+\newcommand\opt[1]{\textsf{#1}}
+\expandafter\def\csname sb@box:tag\endcsname{{2cm}{1cm}{0.5cm}}
+\def\*{\hspace{0pt plus 0.1pt}\ignorespaces}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \section{User guide}
+%
+% The problem is that some things, e.g., diagrams, can take a while to
+% typeset, and aren't particularly interesting as far as the global document
+% layout is concerned.  Once you've got a diagram right, the only thing that
+% matters as far as general previewing is concerned is its size.
+%
+% The solution is \package{slowbox}.  Put things you're usually not
+% interested in seeing in a \env{slowbox} environment.  Then they get
+% replaced by a frame saying that there's meant to be something there, and
+% that's it.
+%
+% There are two modes, chosen by package options: \opt{show} and \opt{hide}.
+% The default is \opt{show} mode, because I had to pick one.  In \opt{show}
+% mode, everything happens normally; in \opt{hide} mode, slow  boxes are
+% replaced by frames.  In order for the package to know the sizes of all of
+% your boxes, you must first run through once in \opt{show} mode.
+% Thereafter, all should be well. 
+%
+% \DescribeEnv{slowbox}
+% In \opt{show} mode, the \env{slowbox} environment typesets its contents in
+% LR-mode (for \TeX nicians, restricted horizontal mode).\footnote{^^A
+%   Vertical mode causes all sorts of pain, and makes things way too wide.
+%   Horizontal mode seems a good `standard currency' for \LaTeX\ things like
+%   diagrams.} ^^A
+% In \opt{hide} mode, the boxes are replaced by frames, and \TeX\ will skip
+% over the contents of the environment at high speed, ignoring it
+% completely.
+%
+% The \env{slowbox} environment needs an argument, a \emph{tag} which is used
+% to identify this box.  This is needed because otherwise the package has no
+% way of deciding that you've inserted some new box and need to shunt
+% everything about.  So the full syntax is
+% \syntax{"\\begin{slowbox}{"<tag>"}" \ldots "\\end{slowbox}"}.
+% Tags can be any piece of text.  If you include control sequences in the
+% tag, then they get expanded.  That might be what you want.
+%
+% \DescribeEnv{slowbox$*$}
+% Adding new slow boxes is best done using the starred version of the
+% environment.  Stuff in a \env{slowbox$*$} environment is always typset in
+% \opt{show} mode, regardless of the global mode setting.  The right thing to
+% do is wrap your new stuff in a \env{slowbox$*$} while you're writing it.
+% Then remove the \env{$*$} and it will turn into a frame.  The
+% \env{slowbox$*$} environment takes a tag name, just like \env{slowbox}
+% does.
+%
+% \DescribeMacro\slowboxbegin
+% \DescribeMacro\slowboxend
+% It's useful to define your own commands environments which create slow
+% boxes.  Often, though, what happens is that you want to put some stuff
+% \emph{inside} the slow box, but that doesn't work properly.  What you must
+% do instead is say something like
+% \begin{verbatim}
+%   \newenvironment{splunt}[1]
+%     {...\slowboxbegin{#1}{...\startsplunt...}}
+%     {\slowboxend{...\finishsplunt...}...}
+% \end{verbatim}
+% That is, \syntax{"\\slowboxbegin{"<tag>"}{{"<stuff>"}"} starts a slow box,
+% beginning with \<stuff> if we're in \opt{show} mode.
+%
+% The |\slowboxbegin| command has a |*|-variant, which causes the box to be
+% typeset regardless of the current mode setting.
+%
+% \DescribeMacro\newslowboxenv
+% There's an environment for building slow box environments.  Say
+% \syntax{"\\newslowboxenv{"<env-name>"}"\* "["<n-args>"]"\*
+% "{"<before-text>"}"\* "{"<start-text>"}"\* "{"<end-text>"}"\*
+% "{"<after-text>"}"}. This creates a new environment (just like with
+% |\newenvironment|).  The contents are put in a slow box with \<start-text>
+% on the front and \<end-text> on the end.  Before the box is begun,
+% \<before-text> is performed, and \<after-text> is done afterwards.  The
+% environments so created have \env{$*$}-variants which ignore the current
+% mode, just like \env{slowbox$*$}.  They also gather an additional \<tag>
+% argument, which you don't have to bother with. 
+%
+% \DescribeMacro\doslowbox
+% Finally, for commands, there's \syntax{"\\doslowbox{"<tag>"}"\*
+% "{"<stuff>"}"}.  This typesets \<stuff> in a slow box with the given tag.
+% There's a |*|-variant, of course.
+%
+% \DescribeMacro\slowboxshow
+% \DescribeMacro\slowboxhide
+% \DescribeMacro\ifslowboxshow
+% The declarations |\showboxshow| and |\slowboxhide| switch between the
+% \opt{show} and \opt{hide} modes.  They obey standard scoping rules.
+% They're probably not very useful.  They twiddle the |\ifslowboxshow| macro,
+% which is an old-fashioned Plain \TeX\ switch.  If you're the sort of person
+% who uses \package{ifthen}, then you can test |\boolean{slowboxshow}|.
+%
+%^^A-------------------------------------------------------------------------
+% \implementation
+%
+% \section{Implementation of \package{slowbox}}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{The mode switch}
+%
+% \begin{macro}{\ifslowboxshow}
+% \begin{macro}{\slowboxshow}
+% \begin{macro}{\slowboxhide}
+% The |\if@slowboxshow| switch remembers which mode we're in.  The
+% |\slowboxshow| and |\slowboxhide| macros flip the switch.  It's really
+% easy.  The |\relax|es are to annoy people who say |\global\showboxshow|.
+%    \begin{macrocode}
+\def\slowboxshow{\relax\let\ifslowboxshow\iftrue}
+\def\slowboxhide{\relax\let\ifslowboxshow\iffalse}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Dependencies}
+%
+% The skipping-over-stuff-at-high-speed is done by my \package{sverb}
+% package.
+%    \begin{macrocode}
+\RequirePackage{sverb}
+%    \end{macrocode}
+%
+% \subsection{Options}
+%
+% Oh, this is obvious.
+%    \begin{macrocode}
+\DeclareOption{show}{\slowboxshow}
+\DeclareOption{hide}{\slowboxhide}
+\ExecuteOptions{show}
+\ProcessOptions
+%    \end{macrocode}
+%
+% \subsection{Remembering stuff}
+%
+% \begin{macro}{\sb@def}
+% Box dimensions are recorded in the |.aux| file using
+% \syntax{"\\sb@def{"<tag>"}"\* "{"<width>"}"\* "{"<height>"}"\*
+% "{"<depth>"}"}.  This turns into a definition of a strange control
+% sequence.
+%    \begin{macrocode}
+\def\sb@def#1#2#3#4%
+  {\expandafter\gdef\csname sb@box:#1\endcsname{{#2}{#3}{#4}}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{The actual work}
+%
+% \begin{macro}{\sb@begin}
+% This is where most of the intelligence is.
+% \syntax{"\\sb@begin{"<tag>"}{"<stuff>"}"} starts a slow box, putting
+% \<stuff> at the start if we're in \opt{show} mode.  It doesn't ignore stuff
+% -- though it sets |\sb@ignore| to be |\relax| in \opt{show} mode and
+% |\ignore| in \opt{hide} mode.  It also sets |\sb@end| correctly, so that
+% \syntax{"\\sb@end{"<stuff>"}"} ends the current box, putting \<stuff> in
+% it.
+%
+% Disappointingly, perhaps, this is in fact just a dispatcher to the right
+% implementation.
+%    \begin{macrocode}
+\def\sb@begin{%
+  \ifslowboxshow\expandafter\sb@begin@show%
+  \else\expandafter\sb@begin@hide\fi%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sb@begin@show}
+% Now we have the implementation for \opt{show} mode.  This is sometimes
+% called directly, by |*|-variants.  Needs to be |\long| because \<stuff>
+% might contain embedded vmode-material which could legitimately have |\par|
+% tokens in.
+%    \begin{macrocode}
+\long\def\sb@begin@show#1#2{%
+  \begingroup%
+  \def\sb@end##1{%
+    ##1%
+    \color@endgroup%
+    \egroup%
+    \immediate\write\@auxout%
+      {\string\sb@def{#1}{\the\wd\z@}{\the\ht\z@}{\the\dp\z@}}%
+    \leavevmode\box\z@%
+    \endgroup%
+  }%
+  \let\sb@ignore\relax%
+  \setbox\z@\hbox\bgroup\color@begingroup#2%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sb@begin@hide}
+% Now for something a bit stranger.  If we're in \opt{hide} mode, we need to
+% find out whether we've saved information about this box before.  We pass
+% the \emph{control sequence} containing the box dimensions to another
+% macro.  Needs to be |\long| to collect the \<stuff> argument.
+%    \begin{macrocode}
+\long\def\sb@begin@hide#1#2{%
+  \begingroup%
+  \def\sb@end##1{\endgroup}%
+  \let\sb@ignore\ignore%
+  \expandafter\sb@hidden\csname sb@box:#1\endcsname{#1}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sb@hidden}
+% We're given the control token and the tag name.  If the control sequence is
+% like |\relax| then |\csname| must have invented it and we just have to make
+% something up.  Otherwise we put the right stuff in a frame.  Don't forget
+% to write out the box dimensions to the new aux file!
+%    \begin{macrocode}
+\def\sb@hidden#1#2{%
+  \ifx#1\relax\fbox{Unknown slow box \texttt{#2}!}%
+  \else\edef\next@{\noexpand\sb@hidden@i#1{#2}}\expandafter\next@\fi%
+}
+\def\sb@hidden@i#1#2#3#4{%
+  \frameonly{#1}{#2}{#3}{Omitted \texttt{#4}}%
+  \immediate\write\@auxout{\string\sb@def{#4}{#1}{#2}{#3}}%  
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Stuff in frames}
+%
+% \begin{macro}{\frameonly}
+% \syntax{"\\frameonly{"<width>"}{"<height>"}{"<depth>"}{"<stuff>"}"}
+% typesets \<stuff> in a frame with the given dimensions.  This is a bit
+% tricky -- we want the \<stuff> in the middle of the box, but the box's
+% reference point is somewhere else.  We start with a |\vcenter| of the right
+% height, and then nudge it into position later.
+%
+% In case the label is just too big, put shrinky glue all round.  It'll look
+% horrible, but at least it won't mess everything up.
+%    \begin{macrocode}
+\def\frameonly#1#2#3#4{%
+  \dimen\tw@#2\advance\dimen\tw@#3\advance\dimen\tw@-.8\p@%
+  \setbox\z@\hbox{$\vcenter{\hrule\@height\dimen\tw@\@depth\z@}$}%
+  \dimen@#1%
+  \advance\dimen@-.8\p@%
+  \setbox\z@\vbox{%
+    \hrule\vss%
+    \hb@xt@\dimen@{%
+      \vrule\@height\ht\z@\@depth\dp\z@\hss%
+      \advance\dimen@-2em%
+      \parbox\dimen@{\centering#4}%
+      \hss\vrule}%
+    \vss\hrule%
+  }%
+  \dimen@#3\advance\dimen@-\dp\z@%
+  \setbox\z@\hbox{\lower\dimen@\box\z@}%
+  \box\z@%  
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{User commands}
+%
+% \begin{macro}{\slowboxbegin}
+% \begin{macro}{\slowboxend}
+% This is just a matter of using the machinery we've built already.
+%    \begin{macrocode}
+\def\slowboxbegin{\@ifstar{\sb@go\sb@begin}{\sb@go\sb@begin@show}}
+\long\def\sb@go#1#2#3{#1{#2}{#3}\sb@ignore}
+\def\slowboxend{\sb@end}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\doslowbox}
+% And this too.
+%    \begin{macrocode}
+\def\doslowbox{\@ifstar{\sb@do\sb@begin}{\sb@do\sb@begin@show}}
+\long\def\sb@do#1#2#3{#1{#2}{#3}\sb@end}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\newslowboxenv}
+% Something a bit more interesting now.  Gathering the optional arguments for
+% |\newenvironment| is a bit tedious, but we do it anyway.  Picking up the
+% arguments for the environment is a bit tricky -- they come in the wrong
+% order, unfortunately.
+%    \begin{macrocode}
+\def\newslowboxenv#1{\@ifnextchar[{\sb@nenv@i{#1}}{\sb@nenv@do{#1}{}}}
+\def\sb@nenv@i#1[#2]{%
+  \@ifnextchar[{\sb@nenv@ii{#1}{[{#2}]}}{\sb@nenv@do{#1}{[{#2}]}}%
+}
+\def\sb@nenv@ii#1#2[#3]{\sb@nenv@do{#1}{#2[{#2}]}}
+\long\def\sb@nenv@do#1#2#3#4#5#6{%
+  \newenvironment{#1}#2{#3\sb@env\sb@begin{#4}}{\sb@end{#5}#6}%
+  \newenvironment{#1*}#2{#3\sb@env\sb@begin@show{#4}}{\sb@end{#5}#6}%
+}
+\def\sb@env#1#2#3{#1{#3}{#2}\sb@ignore}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{slowbox}
+% And the \env{slowbox} is built using the above equipment.
+%    \begin{macrocode}
+\newslowboxenv{slowbox}{}{}{}{}
+%    \end{macrocode}
+% \end{environment}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \Finale
+\endinput
\ No newline at end of file