Fix dates and version numbers in the package files.
[mdwtools] / footnote.dtx
CommitLineData
86f6a31e 1% \begin{meta-comment} <general public licence>
2%%
3%% footnote package -- Save footnotes around boxing environments
8bc5bdd2 4%% Copyright (c) 1996, 1997, 2002, 2020 Mark Wooding
86f6a31e 5%<*package>
6%%
7%% This program is free software; you can redistribute it and/or modify
8%% it under the terms of the GNU General Public License as published by
9%% the Free Software Foundation; either version 2 of the License, or
10%% (at your option) any later version.
11%%
12%% This program is distributed in the hope that it will be useful,
13%% but WITHOUT ANY WARRANTY; without even the implied warranty of
14%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15%% GNU General Public License for more details.
16%%
17%% You should have received a copy of the GNU General Public License
18%% along with this program; if not, write to the Free Software
19%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20%</package>
21%%
22% \end{meta-comment}
23%
24% \begin{meta-comment} <Package preamble>
25%<+package>\NeedsTeXFormat{LaTeX2e}
26%<+package>\ProvidesPackage{footnote}
af8af7eb 27%<+package> [2020/09/06 1.14.0 Save footnotes around boxes]
86f6a31e 28% \end{meta-comment}
29%
3e2c5da8 30% \CheckSum{329}
86f6a31e 31%\iffalse
32%<*package>
33%\fi
34%% \CharacterTable
35%% {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
36%% 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
37%% Digits \0\1\2\3\4\5\6\7\8\9
38%% Exclamation \! Double quote \" Hash (number) \#
39%% Dollar \$ Percent \% Ampersand \&
40%% Acute accent \' Left paren \( Right paren \)
41%% Asterisk \* Plus \+ Comma \,
42%% Minus \- Point \. Solidus \/
43%% Colon \: Semicolon \; Less than \<
44%% Equals \= Greater than \> Question mark \?
45%% Commercial at \@ Left bracket \[ Backslash \\
46%% Right bracket \] Circumflex \^ Underscore \_
47%% Grave accent \` Left brace \{ Vertical bar \|
48%% Right brace \} Tilde \~}
49%%
50%\iffalse
51%</package>
52%\fi
53%
54% \begin{meta-comment} <driver>
55%
56%<*driver>
57\input{mdwtools}
58\describespackage{footnote}
59\mdwdoc
60%</driver>
61%
62% \end{meta-comment}
63%
64% \section{User guide}
65%
66% This package provides some commands for handling footnotes slightly
67% better than \LaTeX\ usually does; there are several commands and
68% environments (notably |\parbox|, \env{minipage} and \env{tabular}
69% \begin{footnote}
70% The \package{mdwtab} package, provided in this distribution, handles
71% footnotes correctly anyway; it uses an internal version of this package
72% to do so.
73% \end{footnote})
74% which `trap' footnotes so that they can't escape and appear at the bottom
75% of the page.
76%
77% \DescribeEnv{savenotes}
78% The \env{savenotes} environment saves up any footnotes encountered within
79% it, and performs them all at the end.
80%
81% \DescribeMacro{\savenotes}
82% \DescribeMacro{\spewnotes}
83% If you're defining a command or environment, you can use the |\savenotes|
84% command to start saving up footnotes, and the |\spewnotes| command to
85% execute them all at the end. Note that |\savenotes| and |\spewnotes|
86% enclose a group, so watch out. You can safely nest the commands and
87% environments -- they work out if they're already working and behave
88% appropriately.
89%
90% \DescribeEnv{minipage*}
91% To help things along a bit, the package provides a $*$-version of the
92% \env{minipage} environment, which doesn't trap footnotes for itself (and
93% in fact sends any footnotes it contains to the bottom of the page, where
94% they belong).
95%
96% \DescribeMacro{\makesavenoteenv}
97% The new \env{minipage$*$} environment was created with a magic command
98% called |\makesavenoteenv|. It has a fairly simple syntax:
99%
100% \begin{grammar}
101% <make-save-note-env-cmd> ::= \[[
102% "\\makesavenoteenv"
103% \begin{stack} \\ "[" <new-env-name> "]" \end{stack}
104% "{" <env-name> "}"
105% \]]
106% \end{grammar}
107%
108% Without the optional argument, it redefines the named environment so that
109% it handles footnotes correctly. With the optional argument, it makes
110% the new environment named by \<new-env-name> into a footnote-friendly
111% version of the \<env-name> environment.
112%
113% \DescribeMacro{\parbox}
114% The package also redefines the |\parbox| command so that it works properly
115% with footnotes.
116%
117% \DescribeEnv{footnote}
118% The other problem which people tend to experience with footnotes is that
119% you can't put verbatim text (with the |\verb| comamnd or the \env{verbatim}
120% environment) into the |\footnote| command's argument. This package
121% provides a \env{footnote} \emph{environment}, which \emph{does} allow
122% verbatim things. You use the environment just like you do the command.
123% It's really easy. It even has an optional argument, which works the same
124% way.
125%
126% \DescribeEnv{footnotetext}
127% To go with the \env{footnote} environment, there's a \env{footnotetext}
128% environment, which just puts the text in the bottom of the page, like
129% |\footnotetext| does.
130%
131% There's a snag with these environments, though. Some other nonstandard
132% environments, like \env{tabularx}, try to handle footnotes their own
133% way, because they won't work otherwise. The way they do this is not
134% compatible with the way that the \env{footnote} and \env{footnotetext}
135% environments work, and you will get strange results if you try (there'll
136% be odd vertical spacing, and the footnote text may well be incorrect).
137% \begin{footnote}
138% The solution to this problem is to send mail to David Carlisle persuading
139% him to use this package to handle footnotes, rather than doing it his
140% way.
141% \end{footnote}
142%
143% \implementation
144%
145% \section{Implementation}
146%
147% Most implementations of footnote-saving (in particular, that used in
148% the \package{tabularx} and \package{longtable} packages) use a token
149% list register to store the footnote text, and then expand it when whatever
150% was preventing footnotes (usually a vbox) stops. This is no good at all
151% if the footnotes contain things which might not be there by the time the
152% expansion occurs. For example, references to things in temporary boxes
153% won't work.
154%
155% This implementation therefore stores the footnotes up in a box register.
156% This must be just as valid as using tokens, because all I'm going to do
157% at the end is unbox the box).
158%
159% \begin{macrocode}
160%<*macro|package>
161\ifx\fn@notes\@@undefined%
162 \newbox\fn@notes%
163\fi
164% \end{macrocode}
165%
166% I'll need a length to tell me how wide the footnotes should be at the
167% moment.
168%
169% \begin{macrocode}
170\newdimen\fn@width
171% \end{macrocode}
172%
173% Of course, I can't set this up until I actually start saving footnotes.
174% Until then I'll use |\columnwidth| (which works in \package{multicol}
175% even though it doesn't have any right to).
176%
177% \begin{macrocode}
178\let\fn@colwidth\columnwidth
179% \end{macrocode}
180%
181% And now a switch to remember if we're already handling footnotes,
182%
183% \begin{macrocode}
184\newif\if@savingnotes
185% \end{macrocode}
186%
187%
188% \subsection{Building footnote text}
189%
190% I need to emulate \LaTeX's footnote handling when I'm putting the notes
191% into my box; this is also useful in the verbatim-in-footnotes stuff.
192%
193% \begin{macro}{\fn@startnote}
194%
195% Here's how a footnote gets started. Most of the code here is stolen
196% from |\@footnotetext|.
197%
198% \begin{macrocode}
199\def\fn@startnote{%
200 \hsize\fn@colwidth%
201 \interlinepenalty\interfootnotelinepenalty%
202 \reset@font\footnotesize%
203 \floatingpenalty\@MM% Is this right???
204 \@parboxrestore%
205 \protected@edef\@currentlabel{\csname p@\@mpfn\endcsname\@thefnmark}%
206 \color@begingroup%
207}
208% \end{macrocode}
209%
210% \end{macro}
211%
212% \begin{macro}{\fn@endnote}
213%
214% Footnotes are finished off by this macro. This is the easy bit.
215%
216% \begin{macrocode}
5ca7df6a 217\def\fn@endnote{\color@endgroup}
86f6a31e 218% \end{macrocode}
219%
220% \end{macro}
221%
222%
223% \subsection{Footnote saving}
224%
225% \begin{macro}{\fn@fntext}
226%
227% Now to define how to actually do footnotes. I'll just add the notes to
228% the bottom of the footnote box I'm building.
229%
230% There's some hacking added here to handle the case that a footnote is
231% in an |\intertext| command within a broken \package{amsmath} alignment
232% environment -- otherwise the footnotes get duplicated due to the way that
233% that package measures equations.
234% \begin{footnote}
235% The correct solution of course is to
236% implement aligning environments in a sensible way, by building the table
237% and leaving penalties describing the intended format, and then pick that
238% apart in a postprocessing phase. If I get the time, I'll start working
239% on this again. I have a design worked out and the beginnings of an
240% implementation, but it's going to be a long time coming.
241% \end{footnote}
242%
243% \begin{macrocode}
9369e223 244\long\def\fn@fntext#1{%
86f6a31e 245 \ifx\ifmeasuring@\@@undefined%
246 \expandafter\@secondoftwo\else\expandafter\@iden%
247 \fi%
248 {\ifmeasuring@\expandafter\@gobble\else\expandafter\@iden\fi}%
249 {%
250 \global\setbox\fn@notes\vbox{%
251 \unvbox\fn@notes%
252 \fn@startnote%
253 \@makefntext{%
254 \rule\z@\footnotesep%
255 \ignorespaces%
256 #1%
257 \@finalstrut\strutbox%
258 }%
259 \fn@endnote%
260 }%
261 }%
262}
263% \end{macrocode}
264%
265% \end{macro}
266%
267% \begin{macro}{\savenotes}
268%
269% The |\savenotes| declaration starts saving footnotes, to be spewed at a
270% later date. We'll also remember which counter we're meant to use, and
271% redefine the footnotes used by minipages.
272%
273% The idea here is that we'll gather up footnotes within the environment,
274% and output them in whatever format they were being typeset outside the
275% environment.
276%
277% I'll take this a bit at a time. The start is easy: we need a group in
278% which to keep our local definitions.
279%
280% \begin{macrocode}
281\def\savenotes{%
282 \begingroup%
283% \end{macrocode}
284%
285% Now, if I'm already saving footnotes away, I won't bother doing anything
286% here. Otherwise I need to start hacking, and set the switch.
287%
288% \begin{macrocode}
289 \if@savingnotes\else%
290 \@savingnotestrue%
291% \end{macrocode}
292%
293% I redefine the |\@footnotetext| command, which is responsible for adding
294% a footnote to the appropriate insert. I'll redefine both the current
295% version, and \env{minipage}'s specific version, in case there's a nested
296% minipage.
297%
298% \begin{macrocode}
299 \let\@footnotetext\fn@fntext%
300 \let\@mpfootnotetext\fn@fntext%
301% \end{macrocode}
302%
303% I'd better make sure my box is empty before I start, and I must set up
304% the column width so that later changes (e.g., in \env{minipage}) don't
305% upset things too much.
306%
307% \begin{macrocode}
308 \fn@width\columnwidth%
309 \let\fn@colwidth\fn@width%
310 \global\setbox\fn@notes\box\voidb@x%
311% \end{macrocode}
312%
313% Now for some yuckiness. I want to ensure that \env{minipage} doesn't
314% change how footnotes are handled once I've taken charge. I'll store the
315% current values of |\thempfn| (which typesets a footnote marker) and
316% |\@mpfn| (which contains the name of the current footnote counter).
317%
318% \begin{macrocode}
319 \let\fn@thempfn\thempfn%
320 \let\fn@mpfn\@mpfn%
321% \end{macrocode}
322%
323% The \env{minipage} environment provides a hook, called |\@minipagerestore|.
324% Initially it's set to |\relax|, which is unfortunately unexpandable, so if
325% I want to add code to it, I must check this possibility. I'll make it
326% |\@empty| (which expands to nothing) if it's still |\relax|. Then I'll
327% add my code to the hook, to override |\thempfn| and |\@mpfn| set up by
328% \env{minipage}.
329%
330% Note that I can't just force the |mpfootnote| counter to be equal to
331% the |footnote| one, because \env{minipage} clears |\c@mpfootnote| to zero
332% when it starts. This method will ensure that even so, the current counter
333% works OK.
334%
335% \begin{macrocode}
336 \ifx\@minipagerestore\relax\let\@minipagerestore\@empty\fi%
337 \expandafter\def\expandafter\@minipagerestore\expandafter{%
338 \@minipagerestore%
339 \let\thempfn\fn@thempfn%
340 \let\@mpfn\fn@mpfn%
341 }%
342 \fi%
343}
344% \end{macrocode}
345%
346% \end{macro}
347%
348% \begin{macro}{\spewnotes}
349%
350% Now I can spew out the notes we saved. This is a bit messy, actually.
351% Since the standard |\@footnotetext| implementation tries to insert funny
352% struts and things, I must be a bit careful. I'll disable all this bits
353% which start paragraphs prematurely.
354%
355% \begin{macrocode}
356\def\spewnotes{%
357 \endgroup%
358 \if@savingnotes\else\ifvoid\fn@notes\else\begingroup%
359 \let\@makefntext\@empty%
360 \let\@finalstrut\@gobble%
361 \let\rule\@gobbletwo%
362 \@footnotetext{\unvbox\fn@notes}%
363 \endgroup\fi\fi%
364}
365% \end{macrocode}
366%
367% \end{macro}
368%
369% Now make an environment, for users.
370%
371% \begin{macrocode}
372\let\endsavenotes\spewnotes
373% \end{macrocode}
374%
375% That's all that needs to be in the shared code section.
376%
377% \begin{macrocode}
378%</macro|package>
379%<*package>
380% \end{macrocode}
381%
382%
383% \subsection{The \env{footnote} environment}
384%
385% Since |\footnote| is a command with an argument, things like \env{verbatim}
386% are unwelcome in it. Every so often someone on |comp.text.tex| moans
387% about it and I post a nasty hack to make it work. However, as a more
388% permanent and `official' solution, here's an environment which does the
389% job rather better. Lots of this is based on code from my latest attempt
390% on the newsgroup.
391%
392% I'll work on this in a funny order, although I think it's easier to
393% understand. First, I'll do some macros for reading the optional argument
394% of footnote-related commands.
395%
396% \begin{macro}{\fn@getmark}
397%
398% Saying \syntax{"\\fn@getmark{"<default-code>"}{"<cont-code>"}"} will read
399% an optional argument giving a value for the footnote counter; if the
400% argument isn't there, the \<default-code> is executed, and it's expected
401% to set up the appropriate counter to the current value. The footnote
402% marker text is stored in the macro |\@thefnmark|, as is conventional for
403% \LaTeX's footnote handling macros. Once this is done properly, the
404% \<cont-code> is called to continue handling things.
405%
406% Since the handling of the optional argument plays with the footnote
407% counter locally, I'll start a group right now to save some code. Then I'll
408% decide what to do based on the presence of the argument.
409%
410% \begin{macrocode}
411\def\fn@getmark#1#2{%
412 \begingroup%
413 \@ifnextchar[%
414 {\fn@getmark@i{#1}}%
415 {#1\fn@getmark@ii{#2}}%
416}
417% \end{macrocode}
418%
419% There's an optional argument, so I need to read it and assign it to the
420% footnote counter.
421%
422% \begin{macrocode}
423\def\fn@getmark@i#1[#2]{%
424 \csname c@\@mpfn\endcsname#2%
425 \fn@getmark@ii%
426}
427% \end{macrocode}
428%
429% Finally, set up the macro properly, and end the group.
430%
431% \begin{macrocode}
432\def\fn@getmark@ii#1{%
433 \unrestored@protected@xdef\@thefnmark{\thempfn}%
434 \endgroup%
435 #1%
436}
437% \end{macrocode}
438%
439% \end{macro}
440%
441% From argument reading, I'll move on to footnote typesetting.
442%
443% \begin{macro}{\fn@startfntext}
444%
445% The |\fn@startfntext| macro sets everything up for building the footnote
446% in a box register, ready for unboxing into the footnotes insert. The
447% |\fn@prefntext| macro is a style hook I'll set up later.
448%
449% \begin{macrocode}
450\def\fn@startfntext{%
451 \setbox\z@\vbox\bgroup%
452 \fn@startnote%
453 \fn@prefntext%
454 \rule\z@\footnotesep%
455 \ignorespaces%
456}
457% \end{macrocode}
458%
459% \end{macro}
460%
461% \begin{macro}{\fn@endfntext}
462%
463% Now I'll end the vbox, and add it to the footnote insertion. Again, I
464% must be careful to prevent |\@footnotetext| from adding horizontal mode
465% things in bad places.
466%
467% \begin{macrocode}
468\def\fn@endfntext{%
469 \@finalstrut\strutbox%
470 \fn@postfntext%
3e2c5da8 471 \fn@endnote%
86f6a31e 472 \egroup%
473 \begingroup%
474 \let\@makefntext\@empty%
475 \let\@finalstrut\@gobble%
476 \let\rule\@gobbletwo%
477 \@footnotetext{\unvbox\z@}%
478 \endgroup%
479}
480% \end{macrocode}
481%
482% \end{macro}
483%
484% \begin{environment}{footnote}
485%
486% I can now start on the environment proper. First I'll look for an
487% optional argument.
488%
489% \begin{listing}
490%\def\footnote{%
491% \end{listing}
492%
493% Oh. I've already come up against the first problem: that name's already
494% used. I'd better save the original version.
495%
496% \begin{macrocode}
497\let\fn@latex@@footnote\footnote
498% \end{macrocode}
499%
500% The best way I can think of for seeing if I'm in an environment is to
501% look at |\@currenvir|. I'll need something to compare with, then.
502%
503% \begin{macrocode}
504\def\fn@footnote{footnote}
505% \end{macrocode}
506%
507% Now to start properly. |;-)|
508%
509% \begin{macrocode}
510\def\footnote{%
511 \ifx\@currenvir\fn@footnote%
512 \expandafter\@firstoftwo%
513 \else%
514 \expandafter\@secondoftwo%
515 \fi%
516 {\fn@getmark{\stepcounter\@mpfn}%
517 {\leavevmode\unskip\@footnotemark\fn@startfntext}}%
518 {\fn@latex@@footnote}%
519}
520% \end{macrocode}
521%
522% Ending the environment is simple.
523%
524% \begin{macrocode}
525\let\endfootnote\fn@endfntext
526% \end{macrocode}
527%
528% \end{environment}
529%
530% \begin{environment}{footnotetext}
531%
532% I'll do the same magic as before for |\footnotetext|.
533%
534% \begin{macrocode}
535\def\fn@footnotetext{footnotetext}
536\let\fn@latex@@footnotetext\footnotetext
537\def\footnotetext{%
538 \ifx\@currenvir\fn@footnotetext%
539 \expandafter\@firstoftwo%
540 \else%
541 \expandafter\@secondoftwo%
542 \fi%
543 {\fn@getmark{}\fn@startfntext}%
544 {\fn@latex@@footnotetext}%
545}
546\let\endfootnotetext\endfootnote
547% \end{macrocode}
548%
549% \end{environment}
550%
551% \begin{macro}{\fn@prefntext}
552% \begin{macro}{\fn@postfntext}
553%
554% Now for one final problem. The style hook for footnotes is the command
555% |\@makefntext|, which takes the footnote text as its argument. Clearly
556% this is utterly unsuitable, so I need to split it into two bits, where
557% the argument is. This is very tricky, and doesn't deserve to work,
558% although it appears to be a good deal more effective than it has any right
559% to be.
560%
561% \begin{macrocode}
562\long\def\@tempa#1\@@#2\@@@{\def\fn@prefntext{#1}\def\fn@postfntext{#2}}
563\expandafter\@tempa\@makefntext\@@\@@@
564% \end{macrocode}
565%
566% \end{macro}
567% \end{macro}
568%
569%
570% \subsection{Hacking existing environments}
571%
572% Some existing \LaTeX\ environments ought to have footnote handling but
573% don't. Now's our chance.
574%
575% \begin{macro}{\makesavenoteenv}
576%
577% The |\makesavenoteenv| command makes an environment save footnotes around
578% itself.
579%
580% It would also be nice to make |\parbox| work with footnotes. I'll do this
581% later.
582%
583% \begin{macrocode}
584\def\makesavenoteenv{\@ifnextchar[\fn@msne@ii\fn@msne@i}
585% \end{macrocode}
586%
587% We're meant to redefine the environment. We'll copy it (using |\let|) to
588% a magic name, and then pass it on to stage~2.
589%
590% \begin{macrocode}
591\def\fn@msne@i#1{%
592 \expandafter\let\csname msne$#1\expandafter\endcsname%
593 \csname #1\endcsname%
594 \expandafter\let\csname endmsne$#1\expandafter\endcsname%
595 \csname end#1\endcsname%
596 \fn@msne@ii[#1]{msne$#1}%
597}
598% \end{macrocode}
599%
600% Now we'll define the new environment. The start is really easy, since we
601% just need to insert a |\savenotes|. The end is more complex, since we
602% need to preserve the |\if@endpe| flag so that |\end| can pick it up. I
603% reckon that proper hooks should be added to |\begin| and |\end| so that
604% environments can define things to be done outside the main group as
605% well as within it; still, we can't all have what we want, can we?
606%
607% \begin{macrocode}
608\def\fn@msne@ii[#1]#2{%
609 \expandafter\edef\csname#1\endcsname{%
610 \noexpand\savenotes%
611 \expandafter\noexpand\csname#2\endcsname%
612 }%
613 \expandafter\edef\csname end#1\endcsname{%
614 \expandafter\noexpand\csname end#2\endcsname%
615 \noexpand\expandafter%
616 \noexpand\spewnotes%
617 \noexpand\if@endpe\noexpand\@endpetrue\noexpand\fi%
618 }%
619}
620% \end{macrocode}
621%
622% \end{macro}
623%
624% \begin{environment}{minipage*}
625%
626% Let's define a \env{minipage$*$} environment which handles footnotes
627% nicely. Really easy:
628%
629% \begin{macrocode}
630\makesavenoteenv[minipage*]{minipage}
631% \end{macrocode}
632%
633% \end{environment}
634%
635% \begin{macro}{\parbox}
636%
637% Now to alter |\parbox| slightly, so that it handles footnotes properly.
638% I'm going to do this fairly inefficiently, because I'm going to try and
639% change it as little as possible.
640%
641% First, I'll save the old |\parbox| command. If I don't find a \lit{*},
642% I'll just call this command.
643%
644% \begin{macrocode}
645\let\fn@parbox\parbox
646% \end{macrocode}
647%
648% This is the clever bit: I don't know how many optional arguments
649% Mr~Mittelbach and his chums will add to |\parbox|, so I'll handle any
650% number. I'll store them all up in my first argument and call myself
651% every time I find a new one. If I run out of optional arguments,
652% I'll call the original |\parbox| command, surrounding it with |\savenotes|
653% and |\spewnotes|.
654%
655% \begin{macrocode}
656\def\parbox{\@ifnextchar[{\fn@parbox@i{}}{\fn@parbox@ii{}}}
657\def\fn@parbox@i#1[#2]{%
658 \@ifnextchar[{\fn@parbox@i{#1[#2]}}{\fn@parbox@ii{#1[#2]}}%
659}
660\long\def\fn@parbox@ii#1#2#3{\savenotes\fn@parbox#1{#2}{#3}\spewnotes}
661% \end{macrocode}
662%
663% \end{macro}
664%
665% Done!
666%
667% \begin{macrocode}
668%</package>
669% \end{macrocode}
670%
671% \hfill Mark Wooding, \today
672%
673% \Finale
674%
675\endinput