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