summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/bigfoot/perpage.dtx
blob: 0209aa9e5d21da80b66975f5c0b5f346d95adfb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
% \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: