% \iffalse
%%
%% perpage is part of the bigfoot bundle for critical typesetting
%% Copyright 2002, 03, 04, 05, 06  David Kastrup <dak@gnu.org>
%%
% 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
%<driver> \AlsoImplementation
\DocInput{perpage.dtx}
\end{document}
%</driver>
%    \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}}
%</style>
%    \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: 

