summaryrefslogtreecommitdiff
path: root/support/splint/tex/dcols.sty
diff options
context:
space:
mode:
Diffstat (limited to 'support/splint/tex/dcols.sty')
-rw-r--r--support/splint/tex/dcols.sty454
1 files changed, 341 insertions, 113 deletions
diff --git a/support/splint/tex/dcols.sty b/support/splint/tex/dcols.sty
index 71176efd14..44fa97355f 100644
--- a/support/splint/tex/dcols.sty
+++ b/support/splint/tex/dcols.sty
@@ -1,4 +1,4 @@
-% Copyright 2004-2020, Alexander Shibakov
+% Copyright 2004-2024, Alexander Shibakov
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
@@ -48,9 +48,6 @@
\newbox\migrantbox
{\setbox\migrantbox=\box\migrantbox}
-\newtoks\fromword
-\newtoks\toword
-
\newcount\remaindergaps % the number of gaps between columns after the
% first `footnote column'
\newcount\remaindernonfoots % the number of columns without footnotes
@@ -60,7 +57,7 @@
\newif\iflastpageup
\maxdeadcycles=600 % this should be approximately half the \pageheight in points
- % to handle the case when \enddoublecolumns is called before the
+ % to handle the case when \enddoublecols is called before the
% last doublecolumn page is full
% setup the page length and the column count
@@ -108,7 +105,35 @@
\pagewidth=\hsize
\pageheight=\vsize
-%
+% some debugging tools (rather primitive)
+
+\def\onpage#1#2{%
+ {%
+ \yystringempty{#1}{#2}%
+ {%
+ \ifnum#1=\pageno\relax
+ \showboxbreadth=1000
+ \showboxdepth=1000
+ #2%
+ \fi
+ }%
+ }%
+}
+
+\def\onpageg#1#2{% make global assignments possible
+ \yystringempty{#1}{#2}%
+ {%
+ \ifnum#1=\pageno\relax
+ \showboxbreadth=1000
+ \showboxdepth=1000
+ #2%
+ \fi
+ }%
+}
+
+\ifx\testpageno\UNDEFINED
+ \def\testpageno{-\@M}
+\fi
\def\footnote#1{%
\edef\@sf{\spacefactor\the\spacefactor}\setfnmark
@@ -232,7 +257,11 @@
\dsskip\smallskipamount
-\def\begindoublecols{\begingroup\normalbottom\parindent=0pt
+\def\begindoublecols{%
+ \begingroup
+ %\normalbottom
+ \r@ggedbottomfalse % \normalbottom changes \topskip which we do not want
+ \parindent=0pt
\count\footins=\@m \multiply\count\footins by\fnotesspan
\skip\footins=\fnotesspan\realfootins
\remaindergaps=\noofcolumns
@@ -265,6 +294,7 @@
\fi
%
\output={
+ \settopmark % save the \topmark if this is the top of the page
\ifvoid\partialpage
\else % this is a border case: too much material has been contributed, this routine will be called twice
% so output the full page now
@@ -287,23 +317,25 @@
\lastpageupfalse % not the final page yet
\holdinginserts=\@ne
\let\thepage\pagesofar
- \output={\multcolumnout}
\hsize=\columnwidth
+ \output={\multcolumnout}
+ \mco@computevsize
+ \ifvoid\migrantbox
+ \else
+ \insert\footins{\box\migrantbox}%
+ \fi
+}
+
+\def\mco@computevsize{%
\global\vsize=\pageheight%
\global\advance\vsize by-\ht\partialpage%
\global\divide\vsize\baselineskip
\global\multiply\vsize\baselineskip
\global\multiply\vsize\noofcolumns%
-%\message{starting with vsize at \the\vsize, with pp at \the\ht\partialpage}
\global\advance\vsize by-\noofcolumns\topskip
\global\advance\vsize by\topskip
\global\advance\vsize by\noofcolumns\baselineskip
\global\advance\vsize by-\baselineskip
-%\message{vsize set at \the\vsize}
- \ifvoid\migrantbox
- \else
- \insert\footins{\box\migrantbox}%
- \fi
}
\newif\ifpenultimatepage
@@ -376,6 +408,7 @@
}
\def\multcolumnout{%
+ \settopmark % save the \topmark if this is the top of the page
\splittopskip=\topskip
\splitmaxdepth=\maxdepth
\dimen\z@=\pageheight
@@ -386,16 +419,23 @@
% quickly enough resulting in an infinite \deadcycles loop
\normaloutput{\unvbox\partialpage}\lheader\rheader
\unvbox\@cclv \penalty\lastpenalty
+ \mco@computevsize
+ \else
+ \multcolumnout@split
\fi
+}
+
+\newtoks\fromword % save the marks
+\newtoks\toword
+
+\def\multcolumnout@split{% proceed with splitting and balancing the columns
+ % normalize the max column height of the collected material first
\divide\dimen\z@\baselineskip \multiply\dimen\z@\baselineskip
-%\message{aiming for d0: \the\dimen0}
\dimen\@ne=\pagegoal % we claculate the maximum allowable height of the
% middle column next
\advance\dimen\@ne by-\vsize
\advance\dimen\@ne by \fnotesspan\dimen\z@
\divide\dimen\@ne by\fnotesspan
-%\message{d1: \the\dimen1, d0: \the\dimen0, pageheight: \the\pageheight }%
-%\message{(vsize: \the\vsize, pagegoal: \the\pagegoal\space ppage: \the\ht\partialpage)^^J^^J}%
%
\balanceallcolumns
%
@@ -403,22 +443,23 @@
\global\fromword=\expandafter{\firstmark}
\global\toword=\expandafter{\botmark}
\iflastpageup
+ \onpage{\testpageno}{\message{outputting last page...}}%
\ifnum\outputpenalty<-9999 % this break was forced (most likely by the \break in \enddouble...)
\ifvoid\footins
\else
\ifdim\dp\footins=\z@ \else
{\setbox\footins=\box\footins}% this was a correcion box after which no new real footnotes
- \fi % were cotributed
+ \fi % were contributed
\fi
% a correction (\hbox{}) was added by the \enddouble... command;
% this correction will affect \box\footins (since it will appear
% as a box in \foothhbox, a box that is not a footnote);
% this correction will be translated into an appropriate
% adjustment to \box\footins (since the output routine thinks
- % it is a footnote); however, it does throw off the footnote count in \foothhbox
+ % it is a footnote); however, it does throw the footnote count in \foothhbox
% off by one; kill it here; the footnotes will be inserted from the footins box
\setbox\z@=\vbox{\pagesofar}%
- \unvbox\z@ \penalty\lastpenalty
+ \unvbox\z@ \penalty\lastpenalty %?
% since we could not touch \foothhbox above (to keep the footnote height calculations correct),
% the \footins box is messed up; fix it
{\setbox\footins=\box\footins}%
@@ -432,13 +473,13 @@
\global\outputnowfalse
\global\holdinginserts=\@ne
\fi
- \else % this is not the last page, preform normal multicolumn output
+ \else % this is not the last page, perform normal multicolumn output
\normaloutput\page\lheader\rheader
%
\global\vsize=\longvsize
\global\outputnowfalse
\global\holdinginserts=\@ne
- \ifpenultimatepage % page broken at a penalty inserted by \enddoublecolumns
+ \ifpenultimatepage % page broken at a penalty inserted by \enddoublecols
\global\p@nultimatepagetrue % the next penalty should be removed
\fi
\fi
@@ -450,11 +491,11 @@
\global\outputnowtrue
\global\holdinginserts=\z@
\fi
- \unvbox\@cclv
+ \unvbox\@cclv\relax
\ifnum\outputpenalty=\@M % 10000 the break was not at a penalty item
\else
\ifp@nultimatepage % we already split the page at this penalty
- \global\p@nultimatepagefalse % let \enddoublecolumns insert the penalty
+ \global\p@nultimatepagefalse % let \enddoublecols insert the penalty
\else
\penalty\outputpenalty
\fi
@@ -474,13 +515,55 @@
}
}
+% since the output routine is executed several times for every physical page of output
+% we have to make sure that the \topmark value is saved only once;
+% the mechanism below relies on \normaloutput being the only physical means of outputting the page
+% (more precisely, the only macro that contains the \shipout command and expands \savetopmark)
+
+\newtoks\savedtopmark % keep track of the last mark
+
+\def\settopmark{% this has to be done at the beginning of every \output routine
+ % it would have been a lot easier if there was an \everyoutput type command available
+ \yytoksempty\savedtopmark{\global\savedtopmark\expandafter{\topmark}}{}%
+ \yytoksempty\savedtopmark{\global\savedtopmark{{0}{0}{0}}}{}% make sure the saved topmark is not empty from now on
+}
+
\def\normaloutput#1#2#3{\ifodd\pageno\hoffset=\pageshift\fi
- \shipout\vbox{
- \vbox to\fullpageheight{
- \iftitle\global\titlefalse
- \else\hbox to\pagewidth{\vbox to10pt{}\ifodd\pageno #3\else#2\fi}\fi
- \vfill#1}} % parameter #1 is the page itself
- \global\advance\pageno by1}
+ % this is a convenient (although not very refined) way to ivestigate spacing problems
+ \onpageg{\testpageno}{\tracingoutput=1\relax}%
+ \shipout\vbox{
+ \vbox to\fullpageheight{
+ \iftitle\global\titlefalse
+ \else\hbox to\pagewidth{\vbox to10pt{}\ifodd\pageno #3\else#2\fi}\fi
+ \vfill
+ #1
+ }
+ }% parameter #1 is the page itself
+ \ifnum\outputpenalty=-'10000000000 % this is the \end ...
+ \everyendofjob
+ \fi
+ \global\advance\pageno by1
+ \global\savedtopmark{}% reset the last mark (the only place where this is done)
+}
+
+\def\topsecno{\expandafter\takeone\the\savedtopmark} % the last section on the
+ % previous page
+
+% we change the original output routine from cwebmac.tex to handle the topmark saving
+% mechanism introduced here
+
+% a word of caution about the change below: if dcols.sty is not loaded immediately after
+% cwebmac.tex (or at least before the first page is discarded) the output routine below
+% must be further adjusted to
+% \global\output{\settopmark\normaloutput\page\lheader\rheader}
+% so that any `watsit' nodes on the first page (like \write, \open, etc) have a chance to
+% execute; one possible (although not perfect) way of automating this choice is to detect
+% the horizontal mode here and change the output routine accordingly.
+
+\output{\setbox0=\page % the first page is garbage
+ \openout\cont=\contentsfile
+ \write\cont{\catcode `\noexpand\@=11\relax} % \makeatletter
+ \global\output{\settopmark\normaloutput\page\lheader\rheader}} % make sure the \topmark is nonempty; AS
\let\page\pagebody % this is a cwebmac command but it has to be executed here, after the \pagebody macro is changed
@@ -515,18 +598,20 @@
}
\def\b@lanceallcolumns{
+ \onpage{\testpageno}{\message{normalized (after partial page) max column ht(dimen0): \the\dimen0}}%
\advance\count\@cclv\@ne
\whichcolumn{\count\@cclv}%
\ifinfoots % if the footnotes go under these columns ...
\dimen\tw@=\ht\z@
-%\message{set d2(=ht0): \the\dimen2, d0: \the\dimen0; vs. ph: \the\pageheight}%
+ \onpage{\testpageno}{\message{total height of remaining collected material, in footnotes(dimen2): \the\dimen2}}%
\advance\dimen\tw@ by -\remaindernonfoots\dimen\z@
\advance\dimen\tw@ by -\remaindergaps\baselineskip
\advance\dimen\tw@ by \remaindergaps\topskip
\divide\dimen\tw@ by \fnotesspan
-%\message{set d2: \the\dimen2}%
+ \onpage{\testpageno}{\message{set footnote column ht(dimen2): \the\dimen2}}%
\let\next=\b@l@nceallcolumns
\else % otherwise, split off the columns ...
+ \onpage{\testpageno}{\message{total height of remaining collected material, pre footnotes(ht0): \the\ht0}}%
\ifnum\dimen\z@<\topskip
\setbox\@ne=\vsplit\z@ to \topskip
\else
@@ -543,32 +628,38 @@
\newcount\tcthr
\def\b@l@nceallcolumns{% splitting off the columns after the footnotes start
- \count\@cclv=\fnotesstart
- \setbox3=\copy\z@
- \setbox5=\vbox{}%
- \b@l@nc@allcolumns
+ \count\@cclv=\fnotesstart
+ \setbox3=\copy\z@
+ \setbox5=\vbox{}%
+ \b@l@nc@allcolumns
}
\def\b@l@nc@allcolumns{
+ % box3 contains a copy of the collected material after the pre footnote columns have been split off
\whichcolumn{\count\@cclv}%
\iflastcolumn
-%\message{box3 height: \the\ht3, box3 depth: \the\dp3, d0: \the\dimen0, d2: \the\dimen2}%
\ifnum\ht3>\dimen\ifinfoots \tw@ \else \z@ \fi
+ \onpage{\testpageno}{\message{last \ifinfoots (footnote) \fi column too high: \the\ht3 %
+ \space vs. allowable height(dimen\ifinfoots 2\else 0\fi): \the\dimen\ifinfoots \tw@ \else \z@ \fi}}%
\advance\dimen\tw@ by \@ne pt
\let\next=\b@l@nceallcolumns
\else
\ifinfoots
\else
\ifnum\dimen\z@<\topskip
+ \onpage{\testpageno}{\message{d0<ts--->}}%
\setbox3=\vsplit3 to \topskip
\else
+ \onpage{\testpageno}{\message{d0>=ts--->}}%
\setbox3=\vsplit3 to \dimen\z@
\fi
\fi
-%\message{**box3 height: \the\ht3, d0: \the\dimen0, bs: \the\baselineskip, ts: \the\topskip}%
+ \onpage{\testpageno}{\message{last \ifinfoots footnote \fi column height(ht3): \the\ht3 %
+ \space topskip: \the\topskip, }}%
+ \onpage{\testpageno}{\message{max column height(dimen0): \the\dimen0}}%
\wd3=\hsize
\setbox\tw@=\vbox{\box3 \unvbox5 \unvbox\tw@}%
- %%% \box2 is laterchanged globally
+ %%% \box2 is later changed globally
\vbadness=\tcthr
\let\next=\relax
\fi
@@ -617,16 +708,20 @@
}
\def\footblock{%
+ \onpage{\testpageno}{\message{building footnote columns...}}%
\hbox to \fnoteboxwidth{\f@otblock}%
\count\@cclv=\fnotesstart
\advance\count\@cclv by\fnotesspan
\advance\count\@cclv\m@ne
\whichcolumn{\count\@cclv}%
+ \onpage{\testpageno}{\message{column \the\count\@cclv\space to process...}}%
\iflastcolumn
\let\next=\relax
+ \onpage{\testpageno}{\message{done...}}%
\else
\hfil
\let\next=\p@gesofar
+ \onpage{\testpageno}{\message{process columns after the footnotes...}}%
\fi
\next
}
@@ -634,7 +729,7 @@
\def\f@otblock{%
\whichcolumn{\count\@cclv}%
\ifinfoots
- \iffirstfootcol
+ \iffirstfootcol % put all the footnotes after the first column
\setbox\z@=\rlap{\vbox{
\ifvoid\footins
\else
@@ -659,14 +754,20 @@
\wd\z@=\hsize
\box\z@
\else
+% \onpage{\testpageno}{\showboxbreadth=100 \showboxdepth=100 \showbox\currentcolumn}%
\hfil\setbox\z@=\vbox{
\getnextcolumn\unvbox\currentcolumn\kern-\dimen3
\vskip\adjskip
\hrule width\z@ height \dimen5 depth\z@
}%
- \ifnum\ht\z@>\baselineskip
+ \onpage{\testpageno}{\message{topskip: \the\topskip, adjskip: \the\adjskip, bottom rule: wd=0pt, ht=\the\dimen5, dp=0pt}}%
+ \onpage{\testpageno}{\message{splittopskip: \the\splittopskip}}%
+ \onpage{\testpageno}{\message{last box height (preadjustment): \the\ht0 }}%
+ \ifnum\ht\z@<\topskip%>\baselineskip is another option
+ \else
\setbox\z@=\vbox to \dimen\iflastpageup 6 \else \z@ \fi{\unvbox\z@}%
\fi
+ \onpage{\testpageno}{\message{last box height: \the\ht0 }}%
\wd\z@=\hsize
\box\z@
\fi
@@ -716,7 +817,198 @@
\fi
}
-% footnote counting macros
+% footnote accounting macros using aux stream
+
+\yyuniondeclare\fnoteunion{aux:global:fnotes}
+
+\defp\addfnlabel{}
+\defp\addpgendlabel#1{}
+\defp\setfniteration#1{}
+
+\toyyunion{aux:global:fnotes:neutral}
+
+\defc\addfnlabel{\expandafter\fnstream\expandafter{\the\fnstream*}}
+\defc\addpgendlabel#1{\expandafter\fnstream\expandafter{\the\fnstream|}}
+\defc\setfniteration#1{\fniteration=#1 }
+
+\toyyunion{aux:global:fnotes}
+
+\def\yyuniontag{\auxunionctl}
+\defp\fnoteunionctl{}% sequence to activate/deactivate/take other action for
+ % fnote set of macros
+
+\defc\fnoteunionctl{%
+ \restorecslist{aux:global:fnotes}\fnoteunion
+}
+\savecs{aux:global:activate}\fnoteunionctl
+
+\defc\fnoteunionctl{%
+ \restorecslist{aux:global:fnotes:neutral}\fnoteunion
+}
+\savecs{aux:global:deactivate}\fnoteunionctl
+
+\defc\fnoteunionctl{% this command should not make any page material contributions
+ \message{footnotes...}%
+ \fnstream{}%
+ \restorecslist{aux:global:deactivate}\auxunionctl
+ \auxunionctl % ignore all other sets
+ \restorecslist{aux:global:fnotes}\fnoteunion
+ \restorecs{aux:global:fnotes:neutral}\setfniteration
+ \input\jobname.aux
+ \edef\next{\the\fnstream}%
+ \checkfnprefixx{\savedfnstream}{\the\fnstream}%
+ {\message{Footnotes are stable ...}}%
+ {\message{Footnotes may be set incorrectly ...}}%
+}
+\savecs{aux:global:preend}\fnoteunionctl
+
+\defc\fnoteunionctl{% this command should not make any page material contributions
+ \message{footnotes...}%
+ \let\footthenotes\markbottomofpage
+ \edef\savedfnstream{\the\fnstream}%
+ \advance\fniteration by\@ne
+ \toksa\expandafter{\fnoteunion}%
+ \immediate\write\auxstream{\harmlesscomment\the\toksa}%
+ \immediate\write\auxstream{\noexpand\setfniteration{\the\fniteration}}%
+}
+\savecs{aux:global:prestart}\fnoteunionctl
+
+% end footnote accounting macros
+
+% text crossreferencing setup using the aux stream
+
+\yyuniondeclare\textrefunion{aux:global:textrefs}
+
+\defp\refanchor#1#2\end{}
+
+\toyyunion{aux:global:textrefs:neutral}
+
+\defc\refanchor#1#2\end{%
+ \expandafter\def\csname ref: #1\endcsname{#2}%
+}%
+
+\toyyunion{aux:global:textrefs}
+
+\def\yyuniontag{\auxunionctl}
+\defp\textrefunionctl{}% sequence to activate/deactivate/take other action for
+ % fnote set of macros
+
+\defc\textrefunionctl{%
+ \restorecslist{aux:global:textrefs}\textrefunion
+}
+\savecs{aux:global:activate}\textrefunionctl
+
+\defc\textrefunionctl{%
+ \restorecslist{aux:global:textrefs:neutral}\textrefunion
+}
+\savecs{aux:global:deactivate}\textrefunionctl
+
+\defc\textrefunionctl{% this command should not make any page material contributions
+ \message{text references...}%
+}
+\savecs{aux:global:preend}\textrefunionctl
+
+\defc\textrefunionctl{% this command should not make any page material contributions
+ \message{text references...}%
+ \toksa\expandafter{\textrefunion}%
+ \immediate\write\auxstream{\harmlesscomment\the\toksa}%
+}
+\savecs{aux:global:prestart}\textrefunionctl
+
+% end text cross referencing macros
+
+% macros for adding and using counters for referencing
+
+\def\volatile@counters{1(0){\errmessage{invalid counter!}}}
+\def\delayed@counters{1(0){\errmessage{invalid counter!}}}
+
+\def\addvcounter#1#2{% #1 is the name of the counter
+ % #2 is the access sequence
+ \counterattach\volatile@counters{#2}{#1}%
+}
+
+\def\adddcounter#1#2{% #1 is the name of the counter
+ % #2 is the access sequence
+ \counterattach\delayed@counters{#2}{#1}%
+}
+
+\def\counterattach#1#2{%
+ \expandafter\c@unterattach#1\end{#1}{#2}%
+}
+
+\def\c@unterattach#1(#2\end#3#4#5{% #1 is the counter top index
+ % #2 is the counter array
+ % #3 is the name of the counter array
+ % #4 is the access sequence of the new counter
+ % #5 is the name of the counter
+ \expandafter\def\expandafter#3\expandafter{\number\xincrement{#1}(#2(#1){#4}}% add the counter to the array
+ \expandafter\def\csname ct:\expandafter\eatone\string#3[#5]\endcsname{#1}% save counter index
+ \expandafter\def\csname get ct:\expandafter\eatone\string#3[#5]\endcsname##1(#1)##2##3\end{##2}%
+}
+
+\def\getcountervalue#1#2#3{% #1 is the name
+ % #2 is the name of the array
+ % #3 is the array instance
+ \csname get ct:\expandafter\eatone\string#2[#1]\endcsname#3\end
+}
+
+\addvcounter{section}{\secno}
+\adddcounter{page}{\the\pageno}
+
+\def\fulllabel#1{%
+ {%
+ \edef\next{\toksa{\volatile@counters}}\next % immediate references
+ \toksb\expandafter{\delayed@counters}% references to be processed at the page output stage
+ \edef\next{\write\auxstream{%
+ \string\refanchor{#1}\the\toksa\string\delayed\the\toksb\end}}\next
+ }%
+}
+
+\def\extractref#1{%
+ \ifx#1\relax
+ \yybreak{\ignoreref}%
+ \else
+ \yybreak{\expandafter\extractr@f#1}%
+ \yycontinue
+}%
+
+\def\ignoreref#1\end#2\end{{ref \bf ??}}
+
+\def\extractr@f#1\delayed#2\end#3#4\end{%
+ % #1 is the volatile counters
+ % #2 is the delayed counters
+ % #3 is text for the link
+ % #4 is the reference constructor (like \solrefcompose)
+ #4{#1}{#2}{#3}%
+}
+
+% end crossreferencing setup macros
+
+% helper macros to check if footnotes have been correctly placed
+\def\checkfnprefix#1#2{%
+ \expandafter\ch@ckfnprefix\romannumeral-0\yyprefixmatch{#1}{#2}%
+}
+
+\def\ch@ckfnprefix#1#2#3{% #1 is the common prefix, #2 and #3 are remainders
+ \yystringempty{#2}{%
+ \yyifrepeatedchar|{#3}{\yyfirstoftwo}{\yysecondoftwo}%
+ }{%
+ \yysecondoftwo
+ }
+}
+
+\def\checkfnprefixx#1#2{%
+ \expandafter\ch@ckfnprefixx\expandafter{#1}{#2}%
+}
+
+\def\ch@ckfnprefixx#1#2{%
+ \expandafter\ch@ckfnpr@fixx\expandafter{#2}{#1}%
+}
+
+\def\ch@ckfnpr@fixx#1#2{%
+ \checkfnprefix{#2}{#1}%
+}
+% end footnote prefix checking helper macros
\let\footthenotes\empty
@@ -742,78 +1034,14 @@
\vbox to \ht\z@{\box\@ne\vss}\box\z@
\fi}}
-\def\addfnlabel{\expandafter\fnstream\expandafter{\the\fnstream*}}
-\def\addpgendlabel{\expandafter\fnstream\expandafter{\the\fnstream|}}
-
-% the commands above will be exectuted when the .ftn file is loaded below
-
\newtoks\fnstream % locations of footnotes
\fnstream={}
-
-% before processing the footnotes one by one we have to open an
-% auxiliary file (we have to read it in whole because it will be
-% rewritten as the document is being typeset); this opening has to be
-% done carefully for the file might not be there yet; check for it first.
-% as a side note, one should not use the same stream number (at least the
-% one allocated by a \new... command) for both the input and the output
-% streams, since one might accidentally close a different stream that
-% happened to have the same index but allocated by a \new... command as a
-% stream of a different type.
-
-\newread\tryfnlabels % to check if the file exists
-\newwrite\fnlabels
\newcount\localfn % footnote count
-\newcount\fniteration
-
-\def\setupfootnotes{% this macro should be used at the beginning of the file, after a box (preferably)
- \let\footthenotes\markbottomofpage
- \openin\tryfnlabels=\jobname.ftn\relax
- \ifeof\tryfnlabels
- \closein\tryfnlabels\relax
- \fniteration\z@
- \else
- \closein\tryfnlabels\relax
- \input \jobname.ftn\relax
- \fi
- \edef\savedfnstream{\the\fnstream}%
- % now we open the same file for writing ...
- \openout\fnlabels=\jobname.ftn\relax
- \advance\fniteration\@ne
- \write\fnlabels{\noexpand\fniteration\the\fniteration\space}%
-}
+\newcount\fniteration % current footnote calculation iteration count
+\fniteration\z@
\def\markbottomofpage{%
- \write\fnlabels{\noexpand\addpgendlabel}%
-}
-
-\def\unsetfootnotes{%
- \def\footthenotes{%
- \write\fnlabels{\noexpand\endinput}%
- \closeout\fnlabels
- \global\let\footthenotes\checkfootnotestream%
- % it is tempting to say \input \jobname.ftn
- % at this point to use in the test below but this is not
- % going to work: the \closeout will get invoked during the
- % \shipout, which happens after the page is set and these
- % macros are expanded.
- % note that using another `stream' sequence for this purpose
- % would not work either, since a footnote at the bottom of the
- % page might `fire' but would be put on the next page by
- % the epage builder.
- }%
-}
-
-\def\checkfootnotestream{% this needs at least one extra page to work correctly ...
- \fnstream{}%
- \input\jobname.ftn
- \edef\next{\the\fnstream}%
- \ifx\next\savedfnstream
- \message{Footnotes are stable ...}%
- \else % this test is too strict, a better way would be to check that
- % \next is a prefix in \savedfnstream and the remaining characters are all `|'
- \message{Footnotes may be set incorrectly ...}%
- \fi
- \global\let\footthenotes\empty
+ \write\auxstream{\noexpand\addpgendlabel{\the\pageno}\harmlesscomment\space bottom of page \the\pageno}%
}
\def\setfnmark{{%
@@ -826,13 +1054,14 @@
\fi
\fi
\removewhitespace\kern2pt\fnmark\localfn
- \write\fnlabels{\noexpand\addfnlabel}%
+ \write\auxstream{\noexpand\addfnlabel}%
}}
\def\getfntok{\loop\splitfnstream\if|\nexttok\global\localfn=\z@ \repeat}
-\def\splitfnstream{\edef\tempdefone{\the\fnstream}%
- \ifx\tempdefone\empty
+\def\splitfnstream{%
+ \edef\tempdefone{\the\fnstream}%
+ \ifx\tempdefone\empty % no footnote tokens left, although we are expecting one
\def\nexttok{?}\message{You may have to reposition the footnotes ...}%
\else
\expandafter\splitfnstre@m\tempdefone\end
@@ -840,4 +1069,3 @@
}
\def\splitfnstre@m#1#2\end{\def\nexttok{#1}\global\fnstream={#2}}
-