% \iffalse %% %% File: manyfoot.dtx Copyright (C) 1998 Alexander Rozhenko %% %\NeedsTeXFormat{LaTeX2e}[1993/12/01] %\ProvidesPackage{manyfoot} % [1998/12/19 v1.4 Many Footnote Levels Package (NCC)] % % \changes{v1.0}{1998/11/09}{Initial version} % \changes{v1.1}{1998/11/13}{Compartibility problems solved} % \changes{v1.2}{1998/11/15}{Such footnotes may now appear in minipages!} % \changes{v1.3}{1998/11/23}{Floating support bug fixed} % \changes{v1.4}{1998/12/19}{Hand footnotes are moved to nccfoots package} % \changes{v1.4}{1998/12/19}{Options |ruled| and |para*| added} % %<*driver> \documentclass{ltxdoc} \usepackage[para]{manyfoot} \newfootnote{A} \newfootnote[para]{B} \newcounter{footnoteA} \newcommand{\footnoteA}{% \stepcounter{footnoteA}% \Footnotemark\thefootnoteA\FootnotetextA{}} \newcounter{footnoteB} \newcommand{\footnoteB}{% \stepcounter{footnoteB}% \Footnotemark\thefootnoteB\FootnotetextB\thefootnoteB} \renewcommand{\thefootnoteB}{\roman{footnoteB}} \GetFileInfo{manyfoot.sty} \begin{document} \title{The \textsf{manyfoot} package\thanks{This file has version number \fileversion, last revised \filedate.}} \author{Alexander Rozhenko\\rozhenko@oapmg.sscc.ru} \date{\filedate} \maketitle \DocInput{manyfoot.dtx} \end{document} % % \fi % % This package implements a command, |\newfootnote|, that adds % footnote levels to the standard \LaTeX's footnote mechanism. Footnotes % of every additional level are automatically grouped together % on a \LaTeXe{} output page and are separated from another levels % by the special vertical space and rule. % The command |\newfootnote| allows customisation of the % way foonotes of additional level are represented in \LaTeXe{} % documents. Two % customisation styles are available now: the |plain| style is the % ordinary \LaTeX's style of footnote representation; the |para| style % causes footnotes to be typeset as a run-in paragraph (derived from % Donald Knuth's \TeX book and from anouther sources such as the package % |fnpara| by Dominik Wujastyk and Chris Rowley and the package % |footmisc| by Robin Fairbairns). % % \section{User Interface} % % \DescribeMacro\extrafootnoterule % Footnotes of different levels are separated at the output page % by the special footnote % rule, |\extrafootnoterule|. By the default this command is empty. If % you want to separate footnotes by a rule you may redefine it % or call the package with |ruled| option: % \begin{quote} % |\usepackage[ruled]{manyfoot}| % \end{quote} % In the last case |\extrafootnoterule| receives the value of the % |\footnoterule| command. % % The style |para| of footnotes typesetting is rarely useful. To save % space we implement options |para| and |para*|. % If you are going to use run-in paragraph footnotes typesetted with % the same indentation as ordinary footnotes call the package with % |para| option: % \begin{quote} % |\usepackage[para]{manyfoot}| % \end{quote} % To suppress indentation call it with |para*| option: % \begin{quote} % |\usepackage[para*]{manyfoot}| % \end{quote} % Note, that these options only \emph{allows} you to generate % additional footnote levels in |para| style. % But what style you prefer for every footnote level is your choise. For % example, let as generate two footnote levels: the first---in ordinary % style and the second---in |para| style. To do this we have to write % the following code in the preamble of the document: % \begin{quote} % |\usepackage[para]{manyfoot}|\\ % |\newfootnote{A}|\\ % |\newfootnote[para]{B}| % \end{quote} % \DescribeMacro\newfootnote % The |\newfootnote| mandatory parameter \emph{suffix} will be added % to the end of command names generated by |\newfootnote| command. % The optional parameter is a customisation % style for generated footnote level (two styles now implemented, named % |plain| and |para|; the default is |plain|). % % This code generates % two commands, |\FootnotetextA| and |\FootnotetextB|, for insertion of % a text into corresponding footnote levels. Their syntax % is the following: % \begin{quote} % |\Footnotetext|\meta{suffix}\marg{marker}\marg{inserted % text} % \end{quote} % They put the \meta{inserted text} marked with \meta{marker} into % \TeX's insert register |\footins|\meta{suffix} (this insert is also % generated by |\newfootnote| command). We use \emph{the hand} style of % footnote marking, because the choise of how such footnotes have to be % marked is user's one. Such a way simplifies the syntax of new commands % and minimize a number of additional commands needed. % % \DescribeMacro\Footnotemark % \DescribeMacro\Footnotetext % \DescribeMacro\Footnote % It is clear that acompany to |\Footnotetext|\meta{suffix} must % present something like \emph{the hand footnote mark} command. Such % commands are provided by |nccfoots| package which is automatically % called in this package. Their syntax is the following: % \begin{quote} % |\Footnotemark|\marg{marker}\\ % |\Footnotetext|\marg{marker}\marg{inserted text}\\ % |\Footnote|\marg{marker}\marg{inserted text} % \end{quote} % The first command is useful for all footnote levels. Two last commands % are the hand companions for \LaTeX's |\footnote...| commands. % % The question is what these commands have to do when \meta{marker} is % empty? In such a case we leave the current marker unchanged. % Therefore, |\Footnote| command is equal to % \begin{quote} % |\Footnotemark|\marg{marker}|\Footnotetext{}|\marg{inserted text} % \end{quote} % The same rule is useful for |\Footnotetext|\meta{suffix} commands in % |plain| style. For |para| style the empty \meta{marker} means % the footnote without marker (this is the special case useful for % splitting of long footnotes in |para| style; see below). % % Finally, we explain\footnoteA{This is the first A-level footnote.} % on the previous example\footnoteB{This is the first B-level % footnote.} how to automate\footnoteA{The second % A-footnote.} enumeration of the % additional\footnoteB{The second B-footnote.} % footnote\footnoteA{The third A-footnote.} % levels\footnoteB{The third very very very very very very very very very % long B-footnote.} (we have used in this % sentence a number of level's |A| and |B| footnotes to show how this % package works). Let us enumerate the footnotes of |A|~level by arabic % numbers and the footnotes of |B|~level by roman numbers. We allocate % two new counters named |footnoteA| and |footnoteB| and define the % corresponding |\footnote...| commands with automatic enumeration. The % corresponding code is the following % \begin{quote} % |\newcounter{footnoteA}|\\ % |\newcommand{\footnoteA}{%|\\ % | \stepcounter{footnoteA}%|\\ % | \Footnotemark\thefootnoteA \FootnotetextA{}}|\\ % |\newcounter{footnoteB}|\\ % |\newcommand{\footnoteB}{%|\\ % | \stepcounter{footnoteB}%|\\ % | \Footnotemark\thefootnoteB \FootnotetextB\thefootnoteB}|\\ % |\renewcommand{\thefootnoteB}{\roman{footnoteB}}| % \end{quote} % To produce footnotes presented here we have done the following % \begin{verbatim} % Finally, we explain\footnoteA{This is the first A-level % footnote.} on the previous example\footnoteB{This is the first % B-level footnote.} how to automate\footnoteA{The second % A-footnote.} enumeration of the additional\footnoteB{The second % B-footnote.} footnote\footnoteA{The third A-footnote.} % levels\footnoteB{The third very very very very very very very % very very long B-footnote.}\end{verbatim} % % \section{Splitting of \texttt{para} Footnotes} % % The algorithm proposed by Donald Knuth for processing of run-in % paragraph footnotes has some shortages. Namely, small overfulls of % output page frequently arise and the automatical splitting of long % footnotes is impossible. First bug is corrected here (look at the % implementation section below), but the second one couldn't be easily % eliminated. % % \DescribeMacro\SplitNote % To split a long footnote near the end of the output page we propose % the following method. You should decide where the splitting have to be % done. Then you split footnote ``by hands" into two parts. You leave % \emph{the first part} at the same position in the text and comlete its % text by the command |\SplitNote|. You move \emph{the second part} down % in the source file and attach it to any text corresponding to the next % page via the |\Footnotetext...| command with \emph{the empty marker}. % E.g. you source text will look as follows: % \begin{verbatim} % This text goes on the current % page\footnotemarkB{This is the beginning of the long % footnote ... the splitting must be here\SplitNote} % ... % This text goes on the next % page\FootnotetextB{}{and the end of the splitted % footnote is here ...}\end{verbatim} % If both parts of splitted footnote get into the same output page the % splitting is ignored. % % \section{Footnotes within Minipages and Multicolumns} % % If you attach an additional level footnote to some text inside a % minipage, it will appear at the bottom of the page nor the minipage. % % The package correctly works together with |multicol| package and % gives good results when switching between one and two columns by % \LaTeX's commands |\twocolumn| and |\onecolumn|. % % You can use |footmisc| package without |para| option together with % this package. % % \StopEventually{} % % \section{The Implementation} % % First we load |nccfoots| package, containing hand footnote mark % commands and the command |\NCC@makemark|\marg{marker} which % generates marker in |\@thefnmark| command. % \begin{macrocode} %<*package> \RequirePackage{nccfoots} % \end{macrocode} % % \begin{macro}{\extrafootnoterule} % Then we define the empty |\extrafootnoterule| command and implement % |ruled| option. % \begin{macrocode} \newcommand{\extrafootnoterule}{} \DeclareOption{ruled}{\def\extrafootnoterule{\footnoterule}} % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@columnwidth} % \begin{macro}{\MFL@floathook} % We use the dimen |\MFL@columnwidth| instead of |\columnwidth| while % producing the footnote for insertion. We set this dimen to be equal % to |\columnwidth| at the beginning of document and within the % |\@floatplacement| command. The command |\MFL@floathook| does this % job. Later, in |para| option, we'll add to this hook the resetting of % the fudge factor. % \begin{macrocode} \newdimen\MFL@columnwidth \def\MFL@floathook{\MFL@columnwidth\columnwidth} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\MFL@insert} % The command |\MFL@insert|\marg{insert register}\marg{text} % inserts the text to the insert register and sets the standard % splitting parameters. We let this command to be equal |\MFL@mpinsert| % when go into a minipage. To use this command after a minipage we save % its value in |\MFL@realinsert| command. % \begin{macrocode} \long\def\MFL@insert#1#2{% \insert#1{\splittopskip\footnotesep \splitmaxdepth \dp\strutbox \floatingpenalty\@MM #2% }% } \let\MFL@realinsert\MFL@insert % \end{macrocode} % \end{macro} % % \subsection{Footnote Styles Support} % % \DescribeMacro{\MFL@start...} % Every additional footnote level has deal with its own % \emph{insert register} % which is allocated by |\newfootnote| command. This insert register is % automatically initialized by the same values as the |\footins| % register. You can modify its parameters and do something more by % the command % \begin{quote} % |\MFL@start|\meta{style}\marg{insert register} % \end{quote} % You must do all modifications globally, because this command is called % within the group. It is called at the beginning of the document for % every % footnote of such style and is needed in the preamble only. % % \DescribeMacro{\MFL@fnote...} % To put footnote into the insert register the command % \begin{quote} % |\MFL@fnote|\meta{style}\marg{insert % register}\marg{marker}\marg{inserted text} % \end{quote} % is used. Note that you have to define it with |\long| modifier if you % allow footnotes consisting of a number of paragraphs. You have to use % the macros |\MFL@insert| and |\MFL@columnwidth| instead of |\insert| % and |\columnwidth|. % % \DescribeMacro{\MFL@process...} % And the last style customisation command % \begin{quote} % |\MFL@process|\meta{style}\marg{insert register} % \end{quote} % is called within the output routine to prepare the box of the % \meta{insert register} for joining it with anouther footnote inserts. % % Do some comments on joining algorithm. It joins together all nonempty % footnote insert boxes and puts the result into |\footins| box. Special % vertical space and |\extrafootnoterule| are added between every % two neighboring nonempty inserts. This space % is defined by the skip of the second neighbor. In other words the skip % of the \meta{insert register} is the vertical space to be added % between % this insert and any nonempty footnote insert coming before it in the % \emph{list of footnote inserts}. Note that this skip may be % modified while processing of the document (the |multicol| package % multiplies |\skip| and |\count| of |\footins| to the number of columns % when goes into multicolumns mode; we do the same with these parameters % of all another footnote inserts to provide the compartibility with % |multicol| package). % % \DescribeMacro{\MFL@skip} % The command to add the vertical space before the processed insert % is saved in the command |\MFL@skip| exactly before the call of % |\MFL@process...| command. The value of this space is also calculated % in |\@tempskipa|. Using this skip register you can redefine the % command |\MFL@skip| if nesessary. Note that this command is inserted % \emph{between} vertical boxes in joining procedure. If processed box % is the first nonempty footnote box (|\footins| register and all % registers going in footins list before the processed insert are % empty) the command |\MFL@skip| is ignored. % % \subsection{Plain Footnote Style} % % \begin{macro}{\MFL@startplain} % \begin{macro}{\MFL@fnoteplain} % \begin{macro}{\MFL@processplain} % It is very simple. The commands % |\MFL@startplain| and |\MFL@processplain| do nothing % \begin{macrocode} \let\MFL@startplain\@gobble \@onlypreamble\MFL@startplain \let\MFL@processplain\@gobble % \end{macrocode} % and the command |\MFL@fnoteplain| does near the same as the usual % \@footnotetext command. % \begin{macrocode} \long\def\MFL@fnoteplain#1#2#3{\NCC@makemark{#2}% \MFL@insert#1{\reset@font\footnotesize \interlinepenalty\interfootnotelinepenalty \hsize\MFL@columnwidth \@parboxrestore \protected@edef\@currentlabel{\@thefnmark}% \color@begingroup \@makefntext{% \rule\z@\footnotesep\ignorespaces#3\@finalstrut\strutbox}% \color@endgroup }% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Para Footnote Style} % % \begin{macro}{\ifMFL@paraindent} % This style is too complicated and rarely used. We load its % commands optionally. First we define |\ifMFL@paraindent| command to % switch between indented and not indented versions of |para| footnotes. % \begin{macrocode} \newif\ifMFL@paraindent \MFL@paraindenttrue % \end{macrocode} % \end{macro} % % Now we implement |para| option. % \begin{macrocode} \DeclareOption{para}{% % \end{macrocode} % % \begin{macro}{\footglue} % The skip |\footglue| is the horisontal space between footnotes in % run-in paragraph. It's name goes from \TeX book % (Appendix D. Dirty Tricks) and we don't rename this % register. This gives us an additional protection from the usage % at the document a number of packages providing footnotes in % |para| style. % \begin{macrocode} \newskip\footglue % \end{macrocode} % Contrarily to |footmisc| package we initialize this skip in terms of % the footnote size (nor the normal size). % \begin{macrocode} {\footnotesize \global\footglue=1em plus.3em minus.3em } % \end{macrocode} % \end{macro} % % \begin{macro}{\SplitNote} % \begin{macro}{\ifMFL@split} % The switch |MFL@split| provides footnote splitting and % the command |\SplitNote| simply sets this switch to \emph{true}. % \begin{macrocode} \newif\ifMFL@split \MFL@splitfalse \newcommand\SplitNote{\MFL@splittrue} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\MFL@startpara} % Now we prepare |para| support routines. The first is the starting % routine. % \begin{macrocode} \def\MFL@startpara#1{% % \end{macrocode} % It adds to insert's skip additional space |\MFL@paraskip| (it is % unstrechable and is calculated at the beginning of the document). % \begin{macrocode} \global\advance\skip#1\MFL@paraskip % \end{macrocode} % Then we define the command named |\MFL@splitfootins|\meta{suffix} % which saves the splitting information for the corresponding footnote % level. While processing the document this command will have the % empty value or |\noindent| value. % \begin{macrocode} \MFL@setsplit{#1}{}% } \@onlypreamble\MFL@startpara % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@fnotepara} % The next command inserts footnote into \meta{insert register}. % We use Knuth's trick to inform the output procedure how many % horisontal space occupy the footnote by modifying its vertical size % as \emph{fudgefactor}${}\times{}$\emph{footnotebaselineskip} where % \emph{fudgefactor} is the ratio of \emph{footnotebaselineskip} to % |\columnwidth|. The real vertical size of such footnote is not needed % because the footnote is save in |\hbox| nor |\vbox| and % while processing to the run-in paragraph will be unboxed. % % This footnote command is not |\long| because the |\par| command can't % be used in |\hbox|. At the beginning we make footnote mark and % set current label only if footnote mark was nonempty. We use below the % temporary switch |@tempswa| to select the case of nonempty footnote % mark. % \begin{macrocode} \def\MFL@fnotepara#1#2#3{\let\@thefnmark\@empty \NCC@makemark{#2}% \MFL@insert#1{\reset@font\footnotesize \ifx\@thefnmark\@empty \@tempswafalse \else \@tempswatrue \protected@edef\@currentlabel{\@thefnmark}% \fi \color@begingroup % \end{macrocode} % Now we test the width of the footnote mark and if\/ it less than % |0.8em| we calculate in |\@tempdima| the difference between |0.8em| % and the natural width of the marker. This horisontal space is % inserted before the footnote mark. Why it is needed? While the % processing of |para| insert we set |\parindent| to |1em|. And taking % into account that the marker width is at least |0.8em| we obtain the % distance at least |1.8em| between the footnote text and the left % margin. It is exactly the same distance as for footnotes in |plain| % style. Why we add this space using |\hskip|? It should be removed % when line will be broken at this point. % We add this space when the switch |MFL@paraindent| is true. % \begin{macrocode} \if@tempswa \setbox\@tempboxa\hbox{\@makefnmark}% \ifMFL@paraindent \@tempdima.8em \advance\@tempdima-\wd\@tempboxa \ifdim \@tempdima<\z@ \@tempdima\z@ \fi \else \@tempdima\z@ \fi \fi \setbox\@tempboxa\hbox{% \if@tempswa \hskip\@tempdima\unhbox\@tempboxa\nobreak \fi % \end{macrocode} % Well. Now we insert the footnote text into hbox and test the % |MFL@split| switch. % If it is true (splitting needed) we add at the end of text the special % small penalty |-1|. It will indicate us where the splitting needed. % In false case we set penalty |-10| and insert |\footglue| space. % \begin{macrocode} \ignorespaces#3\unskip\strut \ifMFL@split \penalty\m@ne\space \else \penalty-10 \hskip\footglue \fi }% % \end{macrocode} % And finally we use Knuth's trick. % \begin{macrocode} \dp\@tempboxa\z@ \ht\@tempboxa\MFL@fudgefactor\wd\@tempboxa \box\@tempboxa \color@endgroup }% } % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@processpara} % This is the last procedure of |para| style which is called in the % output routine. We must reorganize the box of the \meta{insert % register} which is the ``vbox of hboxes". % \begin{macrocode} \def\MFL@processpara#1{% % \end{macrocode} % Firstly we redefine |\MFL@skip| command by decreasing its skip by % |\MFL@paraskip|. % \begin{macrocode} \advance\@tempskipa -\MFL@paraskip \edef\MFL@skip{\vskip\the\@tempskipa\relax}% \setbox#1\vbox{% % \end{macrocode} % Now we execute the first step of Knuth's algorithm: convert the ``vbox % of hboxes" to ``hbox of hboxes". % \begin{macrocode} \unvbox#1\setbox\@tempboxa\hbox{}\MFL@makehhbox % \end{macrocode} % The second step is unhboxing of all first level hboxes. After that we % have the normal hbox which may be easily converted to paragraph vbox. % \begin{macrocode} \setbox\@tempboxa\hbox{\unhbox\@tempboxa\MFL@removehboxes}% % \end{macrocode} % Now we set all needed parameters to prepare run-in paragraph. % \begin{macrocode} \footnotesize \hsize\MFL@columnwidth \@parboxrestore \ifMFL@paraindent \parindent\footglue \fi % \end{macrocode} % Then we call |\MFL@splitfootins|\meta{suffix} macro to set |\noindent| % if\/ it is needed (this case occurs when the footnote was splitted at % the previous page). % \begin{macrocode} \csname MFL@split\string#1\endcsname % \end{macrocode} % Here is the right place where |\footnotesep| rule have to be inserted. % \begin{macrocode} \rule\z@\footnotesep % \end{macrocode} % Finally, we convert prepared hbox to vbox and test the last penalty % (it is % the penalty of the last |para| footnote inserted into this vbox). This % penalty may be |-10| or |-1|. The case |-1| mean that the last % footnote continues onto the next page (splitting case; see the % command |\MFL@fnotepara|). In this case we adjust the last line of % paragraph to the right margin and set |\MFL@splitfootins|\meta{suffix} % macro to |\noindent|. % \begin{macrocode} \unhbox\@tempboxa\unskip \ifnum\lastpenalty=\m@ne \parfillskip\z@ \MFL@setsplit{#1}{\noindent}% \else \MFL@setsplit{#1}{}% \fi }% } % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@makehhbox} % This procedure converts ``vbox of hboxes" to ``hbox of hboxes". % Its implementation has minimal distinctions from the original code % described in \TeX book. We removed from it the initialization of % the accumulating box (|\@tempboxa|) and added a possibility some boxes % in the list to be vboxes nor hboxes. Such vboxes arises because % while processing a minipage we put all internal footnotes % into vbox to prevent their splitting. % We use the box 0 as the temporary box here. % \begin{macrocode} \def\MFL@makehhbox{% \loop\setbox\z@\lastbox \ifhbox\z@ \setbox\@tempboxa\hbox{\box\z@\unhbox\@tempboxa}% \repeat \ifvbox\z@ \unvbox\z@ \MFL@makehhbox \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@removehboxes} % This is internal procedure described in \TeX book to unboxing ``hbox % of hboxes". % \begin{macrocode} \def\MFL@removehboxes{\setbox\@tempboxa\lastbox \ifhbox\@tempboxa{\MFL@removehboxes}\unhbox\@tempboxa\fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@setsplit} % This macro sets the value of |\MFL@splitfootins|\meta{suffix} macro. % \begin{macrocode} \def\MFL@setsplit#1#2{% \expandafter\gdef\csname MFL@split\string#1\endcsname{#2}% } % \end{macrocode} % \end{macro} % % Finally, we have to prepare something for the work. % We add to |\MFL@floathook| the calculation of the fudge factor. % Such a calculation is needed when we switch between one and two % columns by the standard \LaTeX{} commands. % \begin{macrocode} \g@addto@macro\MFL@floathook{% \begingroup \footnotesize \@tempdima\normalbaselineskip \multiply\@tempdima 1024 \divide \@tempdima \columnwidth \multiply\@tempdima 64 \xdef\MFL@fudgefactor{\strip@pt\@tempdima}% \endgroup } % \end{macrocode} % % \begin{macro}{\MFL@paraskip} % The last trick is the calculation of |\MFL@paraskip|~--- the skip % which have to be added to the skip of all |para| style footnote % inserts and then ``turned back" while preparing of run-in paragraph. % Why it is needed? Two reasons. The first, the % value of |\footnotesep| may be larger than the height of |\strut|. % And we nowhere take into account this exceeding. The second, the % total height of |para| footnotes is less then the real height of % the prepared run-in paragraph by |0.5\baselineskip| on the average. % So we have to add it to the |\skip| register for the compensation. % We do this calculation at the beginning of the document. % \begin{macrocode} \AtBeginDocument{% \begingroup \footnotesize \@tempdima\footnotesep \advance\@tempdima -\ht\strutbox \ifdim\@tempdima<\z@ \@tempdima\z@ \fi \advance\@tempdima.5\normalbaselineskip \xdef\MFL@paraskip{\the\@tempdima\space}% \endgroup } } % \end{macrocode} % \end{macro} % % Finally, we implement |para*| option which suppresses indentation of % |para| footnotes. % \begin{macrocode} \DeclareOption{para*}{% \@ifundefined{MFL@startpara}{\ExecuteOptions{para}}{}% \MFL@paraindentfalse } % \end{macrocode} % % \subsection{Additional Footnotes Support} % % The footnote styles are already designed and we could process the % package options. % \begin{macrocode} \ProcessOptions\relax % \end{macrocode} % % \begin{macro}{\MFL@list} % We initialize the list of all additional footnote levels to be empty. % \begin{macrocode} \def\MFL@list{} % \end{macrocode} % Its items will have the form |\@elt|\marg{style}\meta{insert register} % \end{macro} % % \begin{macro}{\newfootnote} % Then we implement the basic command which generates additional % footnote levels. % \begin{macrocode} \newcommand*{\newfootnote}[2][plain]{% % \end{macrocode} % Firstly, we test the \meta{style} to be valid. % \begin{macrocode} \@ifundefined{MFL@fnote#1}{% \PackageError{manyfoot}{Incorrect footnote style #1}{}}{}% % \end{macrocode} % Then we allocate and initialize new insert % \begin{macrocode} \expandafter\MFL@newinsert\csname footins#2\endcsname % \end{macrocode} % and generate |\Footnotetext|\meta{suffix} command % \begin{macrocode} \edef\@tempa{\noexpand\newcommand \expandafter\noexpand\csname Footnotetext#2\endcsname {\expandafter\noexpand\csname MFL@fnote#1\endcsname{% \expandafter\noexpand\csname footins#2\endcsname}}}% \@tempa % \end{macrocode} % and finally we add the description of this insert to the list of % additional footnote inserts. % \begin{macrocode} \@cons\MFL@list{{#1}\csname footins#2\endcsname}% } \@onlypreamble\newfootnote % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@newinsert} % The initialization of new insert. % \begin{macrocode} \def\MFL@newinsert#1{\newinsert#1% \skip#1\skip\footins \dimen#1\dimen\footins \count#1\count\footins } \@onlypreamble\MFL@newinsert % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@start} % This command executes the |\MFL@start...| command. % It works at the preamble of the document only once for every % additional footnote level. % \begin{macrocode} \def\MFL@start#1{\csname MFL@start#1\endcsname} \@onlypreamble\MFL@start % \end{macrocode} % \end{macro} % % \subsection{The Basic Implementation Part} % % Now we have to build into \LaTeXe{} the support of additional % footnote levels. There are a number of points where the modifications % should be done. We do all real modifications at the beginning of the % document. Here we prepare macros needed. % % \subsubsection{Modifications of Output Routine} % % \begin{macro}{\MFL@joinnotes} % First point of modifications is the output routine. We choose the % strategy of joining of the additional footnotes with |\footins| % at the points where it is really needed. The procedure % |\MFL@joinnotes| processes this job. It will be added later to the % beginning of |\@makecol| and |\@doclearpage| macros.\footnote{The % version 1.2 of this package added this procedure to the beginning of % \texttt{\bslash @specialoutput} instead of \texttt{\bslash % @doclearpage}. It was incorrect because % the special output routine is often called to add the next float to % the output page without ejecting it. As a result the additional % footnotes disappeared before floats. Thanks to Fran\c cois Patte who % found this bug.} % \begin{macrocode} \def\MFL@joinnotes{% \let\MFL@elt\@elt \let\@elt\MFL@join \MFL@list \let\@elt\MFL@elt } \def\MFL@join#1#2{% \ifvoid#2% \else % \end{macrocode} % Well. The current insert is not empty. Firstly, we calculate the skip % of insert. Within |multicols| environement it has the size multiplied % in |\col@number| times matching to its natural size. Therefore, we % have to divide it by |\col@number| in such a case. % \begin{macrocode} \@tempskipa\skip#2% \MFL@ifmcol{\divide\@tempskipa\col@number}{}% \edef\MFL@skip{\vskip\the\@tempskipa\relax}% % \end{macrocode} % Now we process the current insert by the style processing driver % \begin{macrocode} \csname MFL@process#1\endcsname #2% % \end{macrocode} % and finally join it with |\footins| insert. % \begin{macrocode} \ifvoid\footins \setbox\footins\box#2% \else \setbox\footins\vbox{% \unvbox\footins\MFL@skip\extrafootnoterule\unvbox#2% }% \fi \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@reinsout} % When the special output is called to process float insertion, all % accumulated footnotes should be reinserted after the output box. % This job carries out |\@reinserts| command. We will add to it % the reinsertion of all additional footnotes with the help of % |\MFL@reinsout| macro. Note that |\@reinserts| command is called at % two points: when the float is the marginal note % (|\count\@currbox|~=~0) or when it is the real float. At the second % case we must take into account the height of all additional footnotes % by adding it to |\@pageht| value. % \begin{macrocode} \def\MFL@reinsout#1#2{\ifvoid#2\else \ifnum\count\@currbox>\z@ \advance\@pageht \ht#2% \advance\@pageht \skip#2% \advance\@pageht \dp#2% \fi \insert#2{\unvbox#2}% \fi } % \end{macrocode} % \end{macro} % % \subsubsection{Minipages Support} % % \begin{macro}{\MFL@reinsert} % The command reinserts all additional footins by adding if\/ % nessesary the empty insertion (such a way is used in |multicol|). % It is used in |minipage| and |multicols| environments. % The point of using it at a minipage is the beginning of the minipage. % Using this command we release the additional footnote boxes to % accumulate footnotes inside the minipage. % \begin{macrocode} \def\MFL@reinsert{{\let\@elt\MFL@reins \MFL@list}} \def\MFL@reins#1#2{\ifvoid#2\else\insert#2{}\fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@mpinsert} % Here we define the minipage insertion command which manually adds % vbox to the insertion box. The last footnote within minipage could be % splitted. So, we specially enclose it into vbox and unvbox the % previous last footnote. % \begin{macrocode} \long\def\MFL@mpinsert#1#2{% \global\setbox#1\vbox{% \unvbox#1\setbox\@tempboxa\lastbox \ifvbox\@tempboxa \unvbox\@tempboxa \fi \vbox{#2}% }% } % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@mpreinsert} % This macro is useful when we really insert footnotes at the end of the % minipage. We suppress splitting of all minipage insertions expecting % the last one. To do this we extract the last box from the insertion % box, then put anouther footnotes into the insert enclosing them into % vbox, and then put the last unvboxed footnote. % \begin{macrocode} \def\MFL@mpreinsert#1#2{% \ifvoid#2\else \setbox\@tempboxa\vbox{\unvbox#2\global\setbox#2\lastbox}% \setbox\z@\box#2% \ifdim\ht\@tempboxa>\z@ \MFL@realinsert#2{\box\@tempboxa}\fi \MFL@realinsert#2{\unvbox\z@}% \fi } % \end{macrocode} % Then we define two hooks which will be added to the beginning and to % the end of a minipage. We do them in not inner mode only (for % the first level minipages). % \end{macro} % % \begin{macro}{\MFL@minipage} % We release all box registers of the additional inserts at the % beginning of\/ minipage to use % them inside the minipage to accumulate inner inserts. % \begin{macrocode} \def\MFL@minipage{% \ifinner\else \MFL@reinsert \let\MFL@insert\MFL@mpinsert \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@endminipage} % We simply reinsert all footnotes at the end of the first level % minipage. % \begin{macrocode} \def\MFL@endminipage{% \ifinner\else {\let\@elt\MFL@mpreinsert \MFL@list}% \fi } % \end{macrocode} % \end{macro} % % \subsubsection{Multicol Package Support} % % \begin{macro}{\MFL@mult} % The command modifies parameters of the insert register. % It is usefull in the scope of |multicol| package only. % \begin{macrocode} \def\MFL@mult#1#2{% \multiply\count#2\col@number \multiply\skip#2\col@number } % \end{macrocode} % \end{macro} % % \begin{macro}{\MFL@ifmcol} % The next macro tests the multicolumn mode. There are two % conditions which have to be satisfied if we are in the multicolumn % mode: the value of |\col@number| should be greater then 1 and the % value of |\footins| count should be at least 2000. % \begin{macrocode} \def\MFL@ifmcol#1#2{\@tempswafalse \ifnum\col@number>\@ne \ifnum\count\footins>1999 \@tempswatrue \fi \fi \if@tempswa #1\else #2\fi } % \end{macrocode} % \end{macro} % % \subsection{What Do We Do at the Beginning of Document?} % % \begin{macrocode} \AtBeginDocument{% % \end{macrocode} % Firstly, we process starting commands for every level % \begin{macrocode} {\let\@elt\MFL@start \MFL@list} % \end{macrocode} % Then we modify |\@doclearpage| and |\@makecol| commands by added % the joining algorithm at their beginning. % \begin{macrocode} \let\MFL@doclearpage\@doclearpage \def\@doclearpage{\MFL@joinnotes\MFL@doclearpage} \let\MFL@makecol\@makecol \def\@makecol{\MFL@joinnotes\MFL@makecol} % \end{macrocode} % Then we modify |\@reinserts| command of the output routine to % process reinsertion of all additional footnotes. % \begin{macrocode} \g@addto@macro\@reinserts{% \let\MFL@elt\@elt \let\@elt\MFL@reinsout \MFL@list \let\@elt\MFL@elt } % \end{macrocode} % Then we execute |\MFL@floathook| and add it into |\@floatplacement| % command which is called when the column mode is % changed. One important note: in the multicolumn mode of |multicol| % package the width of footnotes is unchanged. So, we test % this case by the command |\MFL@ifmcol|. % \begin{macrocode} \MFL@floathook \g@addto@macro\@floatplacement{\MFL@ifmcol{}{\MFL@floathook}} % \end{macrocode} % % The next is the |minipage| environement. We modify |\@iiiminipage| and % |\endminipage| adding to them hooks describe earlier. % \begin{macrocode} \let\MFL@iminipage\@iiiminipage \def\@iiiminipage{\MFL@minipage\MFL@iminipage} \g@addto@macro\endminipage\MFL@endminipage % \end{macrocode} % % Finally, we do some tricks to provide the compartibility with % |multicol| package. If this package is loaded then the command % |\multi@column@out| should be defined % \begin{macrocode} \@ifundefined{multi@column@out} % \end{macrocode} % If it is undefined the |multicol| specific commands are not useful. % So, we delete |\MFL@mult| command and modify |\MFL@ifmcol| command to % choose the second case everytime. % \begin{macrocode} {\@onlypreamble\MFL@mult \let\MFL@ifmcol\@secondoftwo} % \end{macrocode} % If |multicol| package presents we add the joining algorithm to the % beginning of |\multi@column@out| command % \begin{macrocode} {\let\MFL@mcolout\multi@column@out \def\multi@column@out{\MFL@joinnotes\MFL@mcolout} % \end{macrocode} % and add the multiplication of additional footins parameters % by the number of columns to the end of |\init@mult@footins| command. % We can't do this globally. So we save the previous value of |\@elt| % command and then restore it after the calculation. % We also modify |\reinsert@footnotes| command. % \begin{macrocode} \g@addto@macro\init@mult@footins{% \let\MFL@elt\@elt \let\@elt\MFL@mult \MFL@list \let\@elt\MFL@elt } \g@addto@macro\reinsert@footnotes{\MFL@reinsert} } } % % \end{macrocode} \endinput