footnote.dtx 21 KB

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