From d9fe66749d8072f377522910c593df4705a9dc66 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 17 Jul 2006 22:56:22 +0000 Subject: bigfoot update (18jul06) git-svn-id: svn://tug.org/texlive/trunk@1872 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/source/latex/bigfoot/perpage.dtx | 483 +++++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 Master/texmf-dist/source/latex/bigfoot/perpage.dtx (limited to 'Master/texmf-dist/source/latex/bigfoot/perpage.dtx') diff --git a/Master/texmf-dist/source/latex/bigfoot/perpage.dtx b/Master/texmf-dist/source/latex/bigfoot/perpage.dtx new file mode 100644 index 00000000000..0209aa9e5d2 --- /dev/null +++ b/Master/texmf-dist/source/latex/bigfoot/perpage.dtx @@ -0,0 +1,483 @@ +% \iffalse +%% +%% perpage is part of the bigfoot bundle for critical typesetting +%% Copyright 2002, 03, 04, 05, 06 David Kastrup +%% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +% \fi +% \CheckSum{363} +% \GetFileInfo{perpage.sty} +% \date{\filedate} +% \author{David Kastrup\thanks{\texttt{dak@gnu.org}}} +% \title{The \texttt{perpage} package\\Version \fileversion} +% \maketitle +% \section{Description} +% +% The \texttt{perpage} package adds the ability to reset counters per +% page and/or keep their occurences sorted in order of appearance on +% the page. +% +% It works by attaching itself to the code for \cmd{\stepcounter} and +% will then modify the given counter according to information written +% to the |.aux| file, which means that multiple passes may be needed. +% Since it uses the internals of the \cmd{\label} mechanism, the need +% for additional passes will get announced by \LaTeX\ as ``labels may +% have changed''. +% +% \DescribeMacro{\MakePerPage} +% \begin{quote} +% |\MakePerPage[2]{footnote}| +% \end{quote} +% will start footnote numbers with~2 on each page (the optional +% argument defaults to~1). 2~might be a strange number, unless you +% have used something like +% \begin{quote} +% |\renewcommand\thefootnote{\fnsymbol{footnote}}| +% \end{quote} +% and want to start off with a dagger. The starting value must not be +% less than~1 so that the counter logic can detect the reset of a +% counter +% reliably.\footnote{This unfortunately means that you can't just use +% \cmd{\alph} in order to get figures on page~10 numbered as ``10'', +% ``10a'', ``10b''.} +% It could be a good idea to redefine |\@cnterr| if you use a format +% with limited range: at the first pass, footnotes are not reset +% across pages and things like |\fnsymbol| will quickly run out of +% characters to use. +% +% \DescribeMacro{\theperpage} +% If you want to label things also on a per page base, for example +% with +% \begin{quote} +% |\renewcommand{\thefigure}{\thepage-\arabic{figure}}| +% \end{quote} +% you'll have the problem that \thepage is updated asynchronously with +% the real page, since \TeX\ does not know which page the figure will +% end up. If you have used the |perpage| package for modifying the +% figure counter, however, at the point where the counter is +% incremented, the macro \cmd{\theperpage} will be set to the correct +% value corresponding to the actual page location. Note that this +% macro is shared between all counters, so advancing a different +% counter under control of |perpage| will render \cmd{\thefigure} +% incorrect. +% +% \DescribeMacro{\MakeSorted} +% \begin{quote} +% |\MakeSorted{figure}| +% \end{quote} +% will make the |figure| counter get `sorted': this means that counter +% values will be assigned in order of appearance in the output, not in +% order of appearance in the source code. For example, the order of +% interspersed one- and two-column figures might get mixed up by +% \LaTeX\ in the output. Making the counter sorted will fix the order +% to match the order of appearance. A similar problem is when +% ordinary footnotes are present in floating material (this does not +% work in standard \LaTeX, but might do so when using |manyfoot.sty| +% or |bigfoot.sty|): this might jumble their order in the output, and +% making their counter sorted will make things appear fine again. +% +% While this would not fix the order in the table of figures, +% fortunately the respective entries actually get written out in order +% of appearance in the output anyway, so this indeed fixes the +% problem. +% +% Manually setting the counter does not lead to reliable results in +% general; as a special case, however, resetting it to zero is +% recognized (this can also happen automatically when the counter is +% dependent on some other counter). The point where it is reset in +% the source code separates `count groups': everything in the source +% before that point is assigned sorted numbers separately from +% everything appearing behind it, and the sequence numbers start again +% with~1 with the first item appearing in the output (not the source) +% from the new count group. +% +% \DescribeMacro{\MakeSortedPerPage} +% \begin{quote} +% |\MakeSortedPerPage[2]{table}| +% \end{quote} +% will make the table numbers restart at 2 on each page \emph{and} +% will keep them sorted, to boot. Introducing new count groups by +% resetting the counter to~0 manually will not work, as it is not +% clear how to handle count groups scattered between pages. You will +% usually want to use something like +% \begin{quote} +% |\renewcommand{\thefigure}{\theperpage-\arabic{figure}}| +% \end{quote} +% to go along with a page-wise figure +% number.\footnote{Note the use of \cmd{\theperpage} here, see above.} +% Note that it would be quite silly to start the ranges with~2: this +% is just an example for the optional argument in case that you ever +% need it. +% +% \DescribeMacro{\AddAbsoluteCounter} +% \begin{quote} +% |\AddAbsoluteCounter{equation}| +% \end{quote} +% will create a counter |absequation| that will advance together with +% the counter |equation| but will not get reset along with it. This +% is not sorted into output order, but just runs along with the +% sequence in the source file. As a special case, the counter +% |abspage| is created in this manner and \cmd{\theabspage} is defined +% as an arabic number that works in the same contexts as \cmd{\page} +% (namely, gets properly deferred by \cmd{\protected@write}). +% +% \StopEventually{} +% \section{The documentation driver} +% This is the default driver for typesetting the docs. Running it +% through as a separate file will include the code section. Running +% the original |.dtx| file through will omit the code. +% \begin{macrocode} +%<*driver> +\documentclass{ltxdoc} +\usepackage{perpage} +\MakePerPage{footnote} +\begin{document} +\OnlyDescription +% \AlsoImplementation +\DocInput{perpage.dtx} +\end{document} +% +% \end{macrocode} +% +% \section{The package interfaces} +% First identification. We just use date and version from CVS. +% \begin{macrocode} +%<*style> +\NeedsTeXFormat{LaTeX2e} +\def\next$#1: #2 #3${#2} +\ProvidesPackage{perpage}[\next$Date: 2006/07/15 21:43:23 $ + \next$Revision: 1.12 $ Reset/sort counters per page] +% \end{macrocode} +% \begin{macro}{\AddAbsoluteCounter} +% adds a counter with prefix |abs| to a given counter. It typesets as +% an arabic number and never gets reset. And it is advanced with the +% unprefixed counter. +% \begin{macrocode} +\newcommand\AddAbsoluteCounter[1] +{\@ifundefined{c@abs#1}{% + \expandafter\newcount\csname c@abs#1\endcsname + \global\value{abs#1}\@ne + \global\expandafter\let\csname cl@abs#1\endcsname\@empty + \expandafter\xdef\csname theabs#1\endcsname{% + \noexpand\number \csname c@abs#1\endcsname}% + \global\@namedef{c@pabs@#1}{\z@=\z@{% + \stepcounter{abs#1}% + \afterassignment}\count@}% + \@addtoreset{pabs@#1}{#1}}{}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\c@perpage} +% We now create the absolute counter |perpage|: +% \begin{macrocode} +\AddAbsoluteCounter{page} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\theabspage} +% This has to be specially defined so that it will expand as late as +% \cmd{\thepage} does. Several commands set the latter temporarily +% to \cmd{\relax} in order to inhibit expansion, and we will more or +% less imitate its behavior when found set in that manner. +% \begin{macrocode} +\def\theabspage{\ifx\thepage\relax + \noexpand\theabspage + \else + \number\c@abspage + \fi} +% \end{macrocode} +% \end{macro} +% Here follow the three commands for defining counters per page: +% \begin{macro}{\MakePerPage} +% This creates a counter reset per page. An optional second +% argument specifies the starting point of the sequence. +% \begin{macrocode} +\newcommand*\MakePerPage[2][\@ne]{% + \pp@makeperpage{#2}\c@pchk@{#1}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\MakeSorted} +% This will create a counter sorted in appearance on the page. No +% optional argument is given: set the counter to a desired starting +% value manually if you need to. Resetting it to zero will start a +% new count group, setting it to other values is probably not reliable. +% \begin{macrocode} +\newcommand*\MakeSorted[1]{% + \setcounter{#1}{\z@}% + \pp@makeperpage{#1}\c@schk@{\@ne}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\MakeSortedPerPage} +% This will create output in sorted order, reset on each page. Use +% an optional argument to specify the starting value per page. This +% must not be~0, unfortunately. +% \begin{macrocode} +\newcommand*\MakeSortedPerPage[2][\@ne]{% + \pp@makeperpage{#2}\c@spchk@{#1}} +% \end{macrocode} +% \end{macro} +% All of those must only occur in the preamble since we can't do the +% initialization of the counter values otherwise. +% \begin{macrocode} +\@onlypreamble\MakePerPage +\@onlypreamble\MakeSorted +\@onlypreamble\MakeSortedPerPage +% \end{macrocode} +% \section{Internals} +% +% It works in the following manner: The basic work is done through +% attaching help code to the counter's reset list. Each counter has +% an associated absolute id that is counted through continuously and +% is never reset, thus providing a unique frame of reference. Sorted +% and perpage counters work by writing out information to the +% |.aux| file. +% +% The information we maintain for each counter while processing the +% source file are: +% \begin{itemize} +% \item The absolute counter id. +% \item The last counter value so that we can check whether the +% sequence has been interrupted. +% \item The current scope id. +% \item Its starting value. +% \end{itemize} +% +% The information written to the file consists of: +% \begin{itemize} +% \item The absolute counter id. +% \item The current scope id. +% \item The scope's starting value. +% \item The absolute counter id of a superior counter. +% \end{itemize} +% +% Sorted counters work by writing out the current absolute id and +% range id into the |.aux| file each time the counter gets incremented. +% Whenever the counter is changed in a manner different from being +% incremented, a new counter scope gets started. Each counter scope +% has its own independently assigned counter numbers and is associated +% with its absolute id starting value. So as each counter is +% incremented, we write out the triple of current absolute id, counter +% scope and initial value for the scope. Scope changes when a value +% assigned from the file differs from the `natural' value. When the +% file is read in, counter movements are tracked. Each counter that +% does not have its `natural' value, is having a counter setting +% recorded. +% +% The stuff works by adding a pseudo-reset counter to the counter's +% dependent counter list. +% +% \begin{macro}{\pp@makeperpage} +% This does the relevant things for modifying a counter. It defines +% its reset value, it defines the correspoding absolute counter. +% The absolute counter serves a double function: it is also used for +% assigning numbers while reading the |.aux| file. For this purpose +% it is assigned the initialized values here and in the enddocument +% hook (which is called before rereading the |.aux| file and +% checking for changed labels), while the counter is reset to zero +% at the start of the document. +% \begin{macrocode} +\def\pp@makeperpage#1#2#3{% + \global\expandafter\mathchardef\csname c@pp@r@#1\endcsname=#3\relax + \global\@namedef{c@pchk@#1}{#2{#1}}% + \newcounter{pp@a@#1}% + \setcounter{pp@a@#1}{#3}% + \addtocounter{pp@a@#1}\m@ne + \@addtoreset{pchk@#1}{#1}% + \AtBeginDocument{\setcounter{pp@a@#1}\z@}% + \edef\next{\noexpand\AtEndDocument{\noexpand\setcounter{pp@a@#1}{% + \number\value{pp@a@#1}}}}\next} +\@onlypreamble\pp@makeperpage +% \end{macrocode} +% \end{macro} +% \begin{macro}{\pp@chkvlist} +% Check for an empty vertical list. If we have one, that is worth +% warning about. +% \begin{macrocode} +\def\pp@chkvlist{% + \ifcase + \ifvmode + \ifx\lastnodetype\@undefined + \ifdim-\@m\p@=\prevdepth\ifdim\lastskip=\z@\ifnum\lastpenalty=\z@ + \@ne + \fi\fi\fi + \else + \ifnum\lastnodetype=\m@ne \@ne \fi + \fi + \fi \z@ + \or + \PackageWarning{perpage}{\string\stepcounter\space probably at start of + vertical list:^^JYou might need to use \string\leavevmode\space + before it to avoid vertical shifts}% + \fi} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\pp@fetchctr} +% \begin{macro}{\theperpage} +% This fetches the counter information and puts it into +% \cmd{\pp@label}, \cmd{\pp@page} and (globally) into +% \cmd{\theperpage}. +% \begin{macrocode} +\def\pp@fetchctr#1{\expandafter\expandafter\expandafter\pp@fetchctrii + \csname pp@r@#1@\number\value{pp@a@#1}\endcsname + \@empty\@empty} + +\global\let\theperpage\@empty + +\def\pp@fetchctrii#1#2#3{\edef\pp@label{#1}% + \edef\pp@page{#2}% + \gdef\theperpage{#3}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% Ok, let's put together all the stuff for the simplest case, counters +% numbered per page without sorting: +% \begin{macro}{\c@pchk@} +% This is the code buried into to the reset list. When the reset +% list is executed in the context of advancing a counter, we call +% something like +% \begin{verbatim} +%\global\c@pchk@{countername}\z@ +% \end{verbatim} +% since the reset list expected a counter here instead of some +% generic command. That is the reason we start off this command by +% giving \cmd{\global} something to chew on. +% \begin{macrocode} +\def\c@pchk@#1{\z@=\z@ + \begingroup +% \end{macrocode} +% Now we fetch the page value corresponding to the not yet adjusted +% value of the absolute counter to see whether the previous counter +% advance happened on the same page. +% \begin{macrocode} + \pp@fetchctr{#1}\let\next\pp@page + \addtocounter{pp@a@#1}\@ne + \pp@fetchctr{#1}% +% \end{macrocode} +% We compare the pages for current and last advance of the counter. +% If they differ, we reset the counter to its starting value. We do +% the same if the counter has been reset to zero manually, likely by +% being in the reset list of some other counter. +% \begin{macrocode} + \ifcase\ifx\next\pp@page\else\@ne\fi + \ifnum\value{#1}=\z@\@ne\fi\z@ + \else + \setcounter{#1}{\value{pp@r@#1}}% + \fi + \pp@writectr\pp@pagectr{#1}{\noexpand\theabspage}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\pp@writectr} +% This is the common ending of all pseudo reset counters. It writes +% out an appropriate command to the |.aux| file with all required +% information. +% \begin{macrocode} +\def\pp@writectr#1#2#3{\edef\next{% + \string#1{#2}{\number\value{pp@a@#2}}{#3}{\noexpand\thepage}}% + \pp@chkvlist + \dimen@=\lastkern + \ifdim\dimen@=\z@ \else \unkern\fi + \protected@write\@auxout{}{\next}% + \ifdim\dimen@=\z@ \nobreak \else \kern\dimen@\fi + \afterassignment\endgroup\count@} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\pp@pagectr} +% This is the workhorse for normal per page counters. It is called +% whenever the |.aux| file is read in and establishes the +% appropriate information for each counter advancement in a +% pseudolabel. +% \begin{macrocode} +\def\pp@pagectr#1#2#3#4{\@ifundefined{c@pp@a@#1}{}{% + \addtocounter{pp@a@#1}\@ne + \edef\next{\noexpand + \@newl@bel{pp@r@#1}{#2}{{\number\value{pp@a@#1}}{#3}% + {#4}}}\next}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\c@schk@} +% This is called for implementing sorted counters. Sorted counters +% maintain a ``count group'', and the values in each count group are +% numbered independently from that of other count groups. Whenever +% a counter is found to have been reset, it will start a new count +% group. At the end of document, the count group counters need to +% get reset, too, so that the check for changed |.aux| files will +% still work. +% \begin{macrocode} +\def\c@schk@#1{\z@=\z@ + \begingroup + \addtocounter{pp@a@#1}\@ne + \ifnum\value{#1}=\@ne + \expandafter\xdef\csname pp@g@#1\endcsname{\number\value{pp@a@#1}}% + \edef\next{\noexpand\AtEndDocument{\global\let + \expandafter\noexpand\csname pp@g@#1@\number\value{pp@a@#1}\endcsname + \relax}}\next + \fi + \pp@fetchctr{#1}% + \ifx\pp@page\@empty + \else \setcounter{#1}{\pp@label}\fi + \pp@writectr\pp@spagectr{#1}{\csname pp@g@#1\endcsname}}% +% \end{macrocode} +% \end{macro} +% \begin{macro}{\pp@spagectr} +% This is the code advancing the respective value of the appropriate +% count group and assigning the label. +% \begin{macrocode} +\def\pp@spagectr#1#2#3#4{\@ifundefined{c@pp@a@#1}{}{% + \count@0\csname pp@g@#1@#3\endcsname + \advance\count@\@ne + \expandafter\xdef\csname pp@g@#1@#3\endcsname{\number\count@}% + \edef\next{\noexpand + \@newl@bel{pp@r@#1}{#2}{{\number\count@}{#3}% + {#4}}}\next}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\c@spchk@} +% And this finally is the counter advance code for sorted counters +% per page. Basically, we just use one count group per page. +% Resetting a counter manually will not introduce a new count group, +% and it would be hard to decide what to do in case count groups and +% page positions overlap. +% \begin{macrocode} +\def\c@spchk@#1{\z@=\z@ + \begingroup + \addtocounter{pp@a@#1}\@ne + \pp@fetchctr{#1}% + \ifx\pp@page\@empty + \else \setcounter{#1}{\pp@label}\fi + \pp@writectr\pp@ppagectr{#1}{\noexpand\theabspage}} +% +% \end{macrocode} +% \end{macro} +% \begin{macro}{\pp@ppagectr} +% \begin{macrocode} +\def\pp@ppagectr#1#2#3#4{\@ifundefined{c@pp@a@#1}{}{% + \def\next{#3}% + \expandafter\ifx\csname pp@page@#1\endcsname\next + \addtocounter{pp@a@#1}\@ne + \else + \setcounter{pp@a@#1}{\value{pp@r@#1}}% + \fi + \global\expandafter\let\csname pp@page@#1\endcsname\next + \edef\next{\noexpand + \@newl@bel{pp@r@#1}{#2}{{\number\value{pp@a@#1}}{#3}% + {#4}}}\next}} +% \end{macrocode} +% \end{macro} +% +% \Finale{} +% \endinput +% Local Variables: +% mode: doctex +% TeX-master: "perpage.drv" +% End: + -- cgit v1.2.3