diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/mdwtools/footnote.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/footnote.dtx | 699 |
1 files changed, 699 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/mdwtools/footnote.dtx b/Master/texmf-dist/source/latex/mdwtools/footnote.dtx new file mode 100644 index 00000000000..16e94ae2a29 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/footnote.dtx @@ -0,0 +1,699 @@ +% \begin{meta-comment} +% +% $Id: footnote.dtx,v 1.13 1997/01/28 19:45:16 mdw Exp $ +% +% Save footnotes around boxing environments and things +% +% (c) 1996 Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: footnote.dtx,v $ +% Revision 1.13 1997/01/28 19:45:16 mdw +% Fixed stupid bug in AMS environment handling which stops the thing from +% working properly if you haven't included amsmath. Doh. +% +% Revision 1.12 1997/01/18 00:45:37 mdw +% Fix problems with duplicated footnotes in broken AMS environments which +% typeset things multiple times. This is a nasty kludge. +% +% Revision 1.11 1996/11/19 20:50:05 mdw +% Entered into RCS +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% footnote package -- Save footnotes around boxing environments +%% Copyright (c) 1996 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>\NeedsTeXFormat{LaTeX2e} +%<+package>\ProvidesPackage{footnote} +%<+package> [1997/01/28 1.13 Save footnotes around boxes] +% \end{meta-comment} +% +% \CheckSum{327} +%\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> +% +%<*driver> +\input{mdwtools} +\describespackage{footnote} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +% \section{User guide} +% +% This package provides some commands for handling footnotes slightly +% better than \LaTeX\ usually does; there are several commands and +% environments (notably |\parbox|, \env{minipage} and \env{tabular} +% \begin{footnote} +% The \package{mdwtab} package, provided in this distribution, handles +% footnotes correctly anyway; it uses an internal version of this package +% to do so. +% \end{footnote}) +% which `trap' footnotes so that they can't escape and appear at the bottom +% of the page. +% +% \DescribeEnv{savenotes} +% The \env{savenotes} environment saves up any footnotes encountered within +% it, and performs them all at the end. +% +% \DescribeMacro{\savenotes} +% \DescribeMacro{\spewnotes} +% If you're defining a command or environment, you can use the |\savenotes| +% command to start saving up footnotes, and the |\spewnotes| command to +% execute them all at the end. Note that |\savenotes| and |\spewnotes| +% enclose a group, so watch out. You can safely nest the commands and +% environments -- they work out if they're already working and behave +% appropriately. +% +% \DescribeEnv{minipage*} +% To help things along a bit, the package provides a $*$-version of the +% \env{minipage} environment, which doesn't trap footnotes for itself (and +% in fact sends any footnotes it contains to the bottom of the page, where +% they belong). +% +% \DescribeMacro{\makesavenoteenv} +% The new \env{minipage$*$} environment was created with a magic command +% called |\makesavenoteenv|. It has a fairly simple syntax: +% +% \begin{grammar} +% <make-save-note-env-cmd> ::= \[[ +% "\\makesavenoteenv" +% \begin{stack} \\ "[" <new-env-name> "]" \end{stack} +% "{" <env-name> "}" +% \]] +% \end{grammar} +% +% Without the optional argument, it redefines the named environment so that +% it handles footnotes correctly. With the optional argument, it makes +% the new environment named by \<new-env-name> into a footnote-friendly +% version of the \<env-name> environment. +% +% \DescribeMacro{\parbox} +% The package also redefines the |\parbox| command so that it works properly +% with footnotes. +% +% \DescribeEnv{footnote} +% The other problem which people tend to experience with footnotes is that +% you can't put verbatim text (with the |\verb| comamnd or the \env{verbatim} +% environment) into the |\footnote| command's argument. This package +% provides a \env{footnote} \emph{environment}, which \emph{does} allow +% verbatim things. You use the environment just like you do the command. +% It's really easy. It even has an optional argument, which works the same +% way. +% +% \DescribeEnv{footnotetext} +% To go with the \env{footnote} environment, there's a \env{footnotetext} +% environment, which just puts the text in the bottom of the page, like +% |\footnotetext| does. +% +% There's a snag with these environments, though. Some other nonstandard +% environments, like \env{tabularx}, try to handle footnotes their own +% way, because they won't work otherwise. The way they do this is not +% compatible with the way that the \env{footnote} and \env{footnotetext} +% environments work, and you will get strange results if you try (there'll +% be odd vertical spacing, and the footnote text may well be incorrect). +% \begin{footnote} +% The solution to this problem is to send mail to David Carlisle persuading +% him to use this package to handle footnotes, rather than doing it his +% way. +% \end{footnote} +% +% \implementation +% +% \section{Implementation} +% +% Most implementations of footnote-saving (in particular, that used in +% the \package{tabularx} and \package{longtable} packages) use a token +% list register to store the footnote text, and then expand it when whatever +% was preventing footnotes (usually a vbox) stops. This is no good at all +% if the footnotes contain things which might not be there by the time the +% expansion occurs. For example, references to things in temporary boxes +% won't work. +% +% This implementation therefore stores the footnotes up in a box register. +% This must be just as valid as using tokens, because all I'm going to do +% at the end is unbox the box). +% +% \begin{macrocode} +%<*macro|package> +\ifx\fn@notes\@@undefined% + \newbox\fn@notes% +\fi +% \end{macrocode} +% +% I'll need a length to tell me how wide the footnotes should be at the +% moment. +% +% \begin{macrocode} +\newdimen\fn@width +% \end{macrocode} +% +% Of course, I can't set this up until I actually start saving footnotes. +% Until then I'll use |\columnwidth| (which works in \package{multicol} +% even though it doesn't have any right to). +% +% \begin{macrocode} +\let\fn@colwidth\columnwidth +% \end{macrocode} +% +% And now a switch to remember if we're already handling footnotes, +% +% \begin{macrocode} +\newif\if@savingnotes +% \end{macrocode} +% +% +% \subsection{Building footnote text} +% +% I need to emulate \LaTeX's footnote handling when I'm putting the notes +% into my box; this is also useful in the verbatim-in-footnotes stuff. +% +% \begin{macro}{\fn@startnote} +% +% Here's how a footnote gets started. Most of the code here is stolen +% from |\@footnotetext|. +% +% \begin{macrocode} +\def\fn@startnote{% + \hsize\fn@colwidth% + \interlinepenalty\interfootnotelinepenalty% + \reset@font\footnotesize% + \floatingpenalty\@MM% Is this right??? + \@parboxrestore% + \protected@edef\@currentlabel{\csname p@\@mpfn\endcsname\@thefnmark}% + \color@begingroup% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\fn@endnote} +% +% Footnotes are finished off by this macro. This is the easy bit. +% +% \begin{macrocode} +\let\fn@endnote\color@endgroup +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Footnote saving} +% +% \begin{macro}{\fn@fntext} +% +% Now to define how to actually do footnotes. I'll just add the notes to +% the bottom of the footnote box I'm building. +% +% There's some hacking added here to handle the case that a footnote is +% in an |\intertext| command within a broken \package{amsmath} alignment +% environment -- otherwise the footnotes get duplicated due to the way that +% that package measures equations. +% \begin{footnote} +% The correct solution of course is to +% implement aligning environments in a sensible way, by building the table +% and leaving penalties describing the intended format, and then pick that +% apart in a postprocessing phase. If I get the time, I'll start working +% on this again. I have a design worked out and the beginnings of an +% implementation, but it's going to be a long time coming. +% \end{footnote} +% +% \begin{macrocode} +\def\fn@fntext#1{% + \ifx\ifmeasuring@\@@undefined% + \expandafter\@secondoftwo\else\expandafter\@iden% + \fi% + {\ifmeasuring@\expandafter\@gobble\else\expandafter\@iden\fi}% + {% + \global\setbox\fn@notes\vbox{% + \unvbox\fn@notes% + \fn@startnote% + \@makefntext{% + \rule\z@\footnotesep% + \ignorespaces% + #1% + \@finalstrut\strutbox% + }% + \fn@endnote% + }% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\savenotes} +% +% The |\savenotes| declaration starts saving footnotes, to be spewed at a +% later date. We'll also remember which counter we're meant to use, and +% redefine the footnotes used by minipages. +% +% The idea here is that we'll gather up footnotes within the environment, +% and output them in whatever format they were being typeset outside the +% environment. +% +% I'll take this a bit at a time. The start is easy: we need a group in +% which to keep our local definitions. +% +% \begin{macrocode} +\def\savenotes{% + \begingroup% +% \end{macrocode} +% +% Now, if I'm already saving footnotes away, I won't bother doing anything +% here. Otherwise I need to start hacking, and set the switch. +% +% \begin{macrocode} + \if@savingnotes\else% + \@savingnotestrue% +% \end{macrocode} +% +% I redefine the |\@footnotetext| command, which is responsible for adding +% a footnote to the appropriate insert. I'll redefine both the current +% version, and \env{minipage}'s specific version, in case there's a nested +% minipage. +% +% \begin{macrocode} + \let\@footnotetext\fn@fntext% + \let\@mpfootnotetext\fn@fntext% +% \end{macrocode} +% +% I'd better make sure my box is empty before I start, and I must set up +% the column width so that later changes (e.g., in \env{minipage}) don't +% upset things too much. +% +% \begin{macrocode} + \fn@width\columnwidth% + \let\fn@colwidth\fn@width% + \global\setbox\fn@notes\box\voidb@x% +% \end{macrocode} +% +% Now for some yuckiness. I want to ensure that \env{minipage} doesn't +% change how footnotes are handled once I've taken charge. I'll store the +% current values of |\thempfn| (which typesets a footnote marker) and +% |\@mpfn| (which contains the name of the current footnote counter). +% +% \begin{macrocode} + \let\fn@thempfn\thempfn% + \let\fn@mpfn\@mpfn% +% \end{macrocode} +% +% The \env{minipage} environment provides a hook, called |\@minipagerestore|. +% Initially it's set to |\relax|, which is unfortunately unexpandable, so if +% I want to add code to it, I must check this possibility. I'll make it +% |\@empty| (which expands to nothing) if it's still |\relax|. Then I'll +% add my code to the hook, to override |\thempfn| and |\@mpfn| set up by +% \env{minipage}. +% +% Note that I can't just force the |mpfootnote| counter to be equal to +% the |footnote| one, because \env{minipage} clears |\c@mpfootnote| to zero +% when it starts. This method will ensure that even so, the current counter +% works OK. +% +% \begin{macrocode} + \ifx\@minipagerestore\relax\let\@minipagerestore\@empty\fi% + \expandafter\def\expandafter\@minipagerestore\expandafter{% + \@minipagerestore% + \let\thempfn\fn@thempfn% + \let\@mpfn\fn@mpfn% + }% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\spewnotes} +% +% Now I can spew out the notes we saved. This is a bit messy, actually. +% Since the standard |\@footnotetext| implementation tries to insert funny +% struts and things, I must be a bit careful. I'll disable all this bits +% which start paragraphs prematurely. +% +% \begin{macrocode} +\def\spewnotes{% + \endgroup% + \if@savingnotes\else\ifvoid\fn@notes\else\begingroup% + \let\@makefntext\@empty% + \let\@finalstrut\@gobble% + \let\rule\@gobbletwo% + \@footnotetext{\unvbox\fn@notes}% + \endgroup\fi\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% Now make an environment, for users. +% +% \begin{macrocode} +\let\endsavenotes\spewnotes +% \end{macrocode} +% +% That's all that needs to be in the shared code section. +% +% \begin{macrocode} +%</macro|package> +%<*package> +% \end{macrocode} +% +% +% \subsection{The \env{footnote} environment} +% +% Since |\footnote| is a command with an argument, things like \env{verbatim} +% are unwelcome in it. Every so often someone on |comp.text.tex| moans +% about it and I post a nasty hack to make it work. However, as a more +% permanent and `official' solution, here's an environment which does the +% job rather better. Lots of this is based on code from my latest attempt +% on the newsgroup. +% +% I'll work on this in a funny order, although I think it's easier to +% understand. First, I'll do some macros for reading the optional argument +% of footnote-related commands. +% +% \begin{macro}{\fn@getmark} +% +% Saying \syntax{"\\fn@getmark{"<default-code>"}{"<cont-code>"}"} will read +% an optional argument giving a value for the footnote counter; if the +% argument isn't there, the \<default-code> is executed, and it's expected +% to set up the appropriate counter to the current value. The footnote +% marker text is stored in the macro |\@thefnmark|, as is conventional for +% \LaTeX's footnote handling macros. Once this is done properly, the +% \<cont-code> is called to continue handling things. +% +% Since the handling of the optional argument plays with the footnote +% counter locally, I'll start a group right now to save some code. Then I'll +% decide what to do based on the presence of the argument. +% +% \begin{macrocode} +\def\fn@getmark#1#2{% + \begingroup% + \@ifnextchar[% + {\fn@getmark@i{#1}}% + {#1\fn@getmark@ii{#2}}% +} +% \end{macrocode} +% +% There's an optional argument, so I need to read it and assign it to the +% footnote counter. +% +% \begin{macrocode} +\def\fn@getmark@i#1[#2]{% + \csname c@\@mpfn\endcsname#2% + \fn@getmark@ii% +} +% \end{macrocode} +% +% Finally, set up the macro properly, and end the group. +% +% \begin{macrocode} +\def\fn@getmark@ii#1{% + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup% + #1% +} +% \end{macrocode} +% +% \end{macro} +% +% From argument reading, I'll move on to footnote typesetting. +% +% \begin{macro}{\fn@startfntext} +% +% The |\fn@startfntext| macro sets everything up for building the footnote +% in a box register, ready for unboxing into the footnotes insert. The +% |\fn@prefntext| macro is a style hook I'll set up later. +% +% \begin{macrocode} +\def\fn@startfntext{% + \setbox\z@\vbox\bgroup% + \fn@startnote% + \fn@prefntext% + \rule\z@\footnotesep% + \ignorespaces% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\fn@endfntext} +% +% Now I'll end the vbox, and add it to the footnote insertion. Again, I +% must be careful to prevent |\@footnotetext| from adding horizontal mode +% things in bad places. +% +% \begin{macrocode} +\def\fn@endfntext{% + \@finalstrut\strutbox% + \fn@postfntext% + \egroup% + \begingroup% + \let\@makefntext\@empty% + \let\@finalstrut\@gobble% + \let\rule\@gobbletwo% + \@footnotetext{\unvbox\z@}% + \endgroup% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{footnote} +% +% I can now start on the environment proper. First I'll look for an +% optional argument. +% +% \begin{listing} +%\def\footnote{% +% \end{listing} +% +% Oh. I've already come up against the first problem: that name's already +% used. I'd better save the original version. +% +% \begin{macrocode} +\let\fn@latex@@footnote\footnote +% \end{macrocode} +% +% The best way I can think of for seeing if I'm in an environment is to +% look at |\@currenvir|. I'll need something to compare with, then. +% +% \begin{macrocode} +\def\fn@footnote{footnote} +% \end{macrocode} +% +% Now to start properly. |;-)| +% +% \begin{macrocode} +\def\footnote{% + \ifx\@currenvir\fn@footnote% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {\fn@getmark{\stepcounter\@mpfn}% + {\leavevmode\unskip\@footnotemark\fn@startfntext}}% + {\fn@latex@@footnote}% +} +% \end{macrocode} +% +% Ending the environment is simple. +% +% \begin{macrocode} +\let\endfootnote\fn@endfntext +% \end{macrocode} +% +% \end{environment} +% +% \begin{environment}{footnotetext} +% +% I'll do the same magic as before for |\footnotetext|. +% +% \begin{macrocode} +\def\fn@footnotetext{footnotetext} +\let\fn@latex@@footnotetext\footnotetext +\def\footnotetext{% + \ifx\@currenvir\fn@footnotetext% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {\fn@getmark{}\fn@startfntext}% + {\fn@latex@@footnotetext}% +} +\let\endfootnotetext\endfootnote +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\fn@prefntext} +% \begin{macro}{\fn@postfntext} +% +% Now for one final problem. The style hook for footnotes is the command +% |\@makefntext|, which takes the footnote text as its argument. Clearly +% this is utterly unsuitable, so I need to split it into two bits, where +% the argument is. This is very tricky, and doesn't deserve to work, +% although it appears to be a good deal more effective than it has any right +% to be. +% +% \begin{macrocode} +\long\def\@tempa#1\@@#2\@@@{\def\fn@prefntext{#1}\def\fn@postfntext{#2}} +\expandafter\@tempa\@makefntext\@@\@@@ +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% +% +% \subsection{Hacking existing environments} +% +% Some existing \LaTeX\ environments ought to have footnote handling but +% don't. Now's our chance. +% +% \begin{macro}{\makesavenoteenv} +% +% The |\makesavenoteenv| command makes an environment save footnotes around +% itself. +% +% It would also be nice to make |\parbox| work with footnotes. I'll do this +% later. +% +% \begin{macrocode} +\def\makesavenoteenv{\@ifnextchar[\fn@msne@ii\fn@msne@i} +% \end{macrocode} +% +% We're meant to redefine the environment. We'll copy it (using |\let|) to +% a magic name, and then pass it on to stage~2. +% +% \begin{macrocode} +\def\fn@msne@i#1{% + \expandafter\let\csname msne$#1\expandafter\endcsname% + \csname #1\endcsname% + \expandafter\let\csname endmsne$#1\expandafter\endcsname% + \csname end#1\endcsname% + \fn@msne@ii[#1]{msne$#1}% +} +% \end{macrocode} +% +% Now we'll define the new environment. The start is really easy, since we +% just need to insert a |\savenotes|. The end is more complex, since we +% need to preserve the |\if@endpe| flag so that |\end| can pick it up. I +% reckon that proper hooks should be added to |\begin| and |\end| so that +% environments can define things to be done outside the main group as +% well as within it; still, we can't all have what we want, can we? +% +% \begin{macrocode} +\def\fn@msne@ii[#1]#2{% + \expandafter\edef\csname#1\endcsname{% + \noexpand\savenotes% + \expandafter\noexpand\csname#2\endcsname% + }% + \expandafter\edef\csname end#1\endcsname{% + \expandafter\noexpand\csname end#2\endcsname% + \noexpand\expandafter% + \noexpand\spewnotes% + \noexpand\if@endpe\noexpand\@endpetrue\noexpand\fi% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{minipage*} +% +% Let's define a \env{minipage$*$} environment which handles footnotes +% nicely. Really easy: +% +% \begin{macrocode} +\makesavenoteenv[minipage*]{minipage} +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\parbox} +% +% Now to alter |\parbox| slightly, so that it handles footnotes properly. +% I'm going to do this fairly inefficiently, because I'm going to try and +% change it as little as possible. +% +% First, I'll save the old |\parbox| command. If I don't find a \lit{*}, +% I'll just call this command. +% +% \begin{macrocode} +\let\fn@parbox\parbox +% \end{macrocode} +% +% This is the clever bit: I don't know how many optional arguments +% Mr~Mittelbach and his chums will add to |\parbox|, so I'll handle any +% number. I'll store them all up in my first argument and call myself +% every time I find a new one. If I run out of optional arguments, +% I'll call the original |\parbox| command, surrounding it with |\savenotes| +% and |\spewnotes|. +% +% \begin{macrocode} +\def\parbox{\@ifnextchar[{\fn@parbox@i{}}{\fn@parbox@ii{}}} +\def\fn@parbox@i#1[#2]{% + \@ifnextchar[{\fn@parbox@i{#1[#2]}}{\fn@parbox@ii{#1[#2]}}% +} +\long\def\fn@parbox@ii#1#2#3{\savenotes\fn@parbox#1{#2}{#3}\spewnotes} +% \end{macrocode} +% +% \end{macro} +% +% Done! +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \hfill Mark Wooding, \today +% +% \Finale +% +\endinput |