strc-pag.mkxl /size: 18 Kb    last modification: 2021-10-28 13:51
1%D \module
2%D   [       file=strc-pag,
3%D        version=2008.10.20,
4%D          title=\CONTEXT\ Structure Macros,
5%D       subtitle=Pagenumbering,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Structure Macros / Pagenumbering}
15
16\registerctxluafile{strc-pag}{}
17
18\unprotect
19
20\startcontextdefinitioncode
21
22% Allocation:
23
24\ifdefined\realpageno  \else \permanent\countdef\realpageno \zerocount  \fi \realpageno \plusone
25\ifdefined\userpageno  \else \permanent\countdef\userpageno \plusone    \fi \userpageno \plusone
26\ifdefined\subpageno   \else \permanent\countdef\subpageno  \plustwo    \fi \subpageno  \plusone % was \zerocount but that doesn't work well with bytext
27\ifdefined\arrangeno   \else \permanent\countdef\arrangeno  \plusthree  \fi \arrangeno  \zerocount % !
28\ifdefined\pagenoshift \else \permanent\countdef\pagenoshift\plusfour   \fi \pagenoshift\zerocount % !
29\ifdefined\lastpageno  \else \permanent\countdef\lastpageno \plusfive   \fi \lastpageno \zerocount % !
30
31\ifdefined\pageno \else \aliased\let\pageno\userpageno \fi
32
33\permanent\def\realfolio{\the\realpageno}
34\permanent\def\userfolio{\the\userpageno}
35\permanent\def\subfolio {\the\subpageno }
36\permanent\def\lastfolio{\the\lastpageno}
37
38\newtoks\everyinitializepagecounters
39
40\permanent\protected\def\initializepagecounters
41  {\the\everyinitializepagecounters}
42
43\appendtoks
44    \initializepagecounters
45\to \everyjob
46
47% Page numbers are kind of independent of each other and therefore they
48% all get their own counter. After all, it's easier to combine them in
49% a pseudo counterset than to deal with a complex set itself.
50
51% \defineprefixset   [mine][section-1,section-2]
52% \defineseparatorset[mine][:]
53%
54% \setupuserpagenumber
55%   [way=bypart,
56%    prefix=yes,
57%    prefixset=mine,
58%    prefixseparatorset=mine]
59
60% \defineconversionset[frontpart:pagenumber][][romannumerals]
61% \defineconversionset[bodypart:pagenumber] [][numbers]
62%
63% \setupuserpagenumber[way=byblock]
64% \setupuserpagenumber[way=bychapter]
65% \setupuserpagenumber[numberconversionset=pagenumber]
66%
67% \starttext
68%     \startfrontmatter
69%         \completecontent[criterium=all]
70%         \chapter{tufte} \section{one} \input tufte \page \section{two} \input tufte \page
71%         \chapter{tufte} \section{one} \input tufte \page \section{two} \input tufte \page
72%     \stopfrontmatter
73%     \startbodymatter
74%         \chapter{knuth} \section{one} \input knuth \page \section{two} \input knuth \page \section{three} \input knuth \page
75%         \chapter{knuth} \section{one} \input knuth \page \section{two} \input knuth \page \section{three} \input knuth \page
76%     \stopbodymatter
77% \stoptext
78
79\definecounter[\s!realpage][\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=realpageno,\c!method=\v!page]
80\definecounter[\s!userpage][\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=userpageno,\c!method=\v!page]
81\definecounter[\s!subpage] [\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=subpageno, \c!method=\v!page]
82
83\newtoks\everysetuprealpagenumber % todo: set state: none, start, stop, reset
84\newtoks\everysetupuserpagenumber % todo: set state: none, start, stop, reset
85\newtoks\everysetupsubpagenumber  % todo: set state: none, start, stop, reset
86
87\let\m_strc_pagenumbers_state_old\zerocount
88\let\m_strc_pagenumbers_state_new\zerocount
89
90\def\strc_pagenumbers_save_state#1{\edef\m_strc_pagenumbers_state_old{\namedcounterparameter#1\c!state}}
91
92\permanent\tolerant\protected\def\setuprealpagenumber[#1]{\strc_pagenumbers_save_state\s!realpage\setupcounter[\s!realpage][#1]\the\everysetuprealpagenumber}
93\permanent\tolerant\protected\def\setupuserpagenumber[#1]{\strc_pagenumbers_save_state\s!userpage\setupcounter[\s!userpage][#1]\the\everysetupuserpagenumber}
94\permanent\tolerant\protected\def\setupsubpagenumber [#1]{\strc_pagenumbers_save_state\s!subpage \setupcounter[\s!subpage ][#1]\the\everysetupsubpagenumber }
95
96\permanent\protected\def\resetrealpagenumber {} % not permitted
97\permanent\protected\def\resetuserpagenumber {\strc_counters_reset\s!userpage}
98\permanent\protected\def\resetsubpagenumber  {\strc_counters_reset\s!subpage}
99
100\appendtoks
101    \strc_counters_set\s!realpage\realpageno
102    \strc_counters_set\s!userpage\userpageno
103    \strc_counters_set\s!subpage \subpageno
104    \lastpageno\lastcountervalue[\s!realpage]\relax
105\to \everyinitializepagecounters
106
107\aliased\let\setuppagenumber\setupuserpagenumber
108\aliased\let\resetpagenumber\resetuserpagenumber
109
110% invisible =
111
112\def\strc_pagenumbers_page_state_save % \normalexpanded?
113  {\clf_savepagedata
114     {
115        prefix        {\namedcounterparameter\s!userpage\c!prefix}
116        separatorset  {\namedcounterparameter\s!userpage\c!prefixseparatorset}
117        conversion    {\namedcounterparameter\s!userpage\c!prefixconversion}
118        conversionset {\namedcounterparameter\s!userpage\c!prefixconversionset}
119        set           {\namedcounterparameter\s!userpage\c!prefixset}
120        segments      {\namedcounterparameter\s!userpage\c!prefixsegments}
121        connector     {\namedcounterparameter\s!userpage\c!prefixconnector}
122     }{
123        conversion    {\namedcounterparameter\s!userpage\c!numberconversion}
124        conversionset {\namedcounterparameter\s!userpage\c!numberconversionset}
125        starter       {\namedcounterparameter\s!userpage\c!numberstarter}
126        stopper       {\namedcounterparameter\s!userpage\c!numberstopper}
127     }{
128        viewerprefix  {\namedcounterparameter\s!userpage\c!viewerprefix}
129        state         {\namedcounterparameter\s!userpage\c!state}
130     }%
131   \relax}
132
133\prependtoks
134    \strc_pagenumbers_page_state_save
135\to \everyshipout
136
137\installcorenamespace{pagestatestack} % no level yet
138
139\protected\def\strc_pagenumbers_page_state_push{\xdefcsname\??pagestatestack\c!state\endcsname{\namedcounterparameter\s!userpage\c!state}}
140\protected\def\strc_pagenumbers_page_state_pop {\normalexpanded{\setuppagenumber[\c!state=\csname\??pagestatestack\c!state\endcsname]}}
141
142\setuppagenumber
143  [\c!way=\v!by\v!text,
144   \c!prefix=\v!no,
145   \c!prefixset=\v!part,
146   \c!prefixconnector=\endash,
147   \c!state=\v!start]
148
149\setupsubpagenumber
150  [\c!way=\v!by\v!part,
151   \c!state=\v!start] % was stop but start looks better in logging
152
153% Counters
154
155%permanent\def\firstrealpagenumber{\convertedcounter[\s!realpage][\c!type=\v!first]}
156%permanent\def\firstuserpagenumber{\convertedcounter[\s!userpage][\c!type=\v!first]}
157%permanent\def\firstsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!first]}
158
159%permanent\def\lastrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!last]}
160%permanent\def\lastuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!last]}
161%permanent\def\lastsubpagenumber  {\convertedcounter[\s!subpage ][\c!type=\v!last]}
162
163%permanent\def\prevrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!previous]}
164%permanent\def\prevuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!previous]}
165%permanent\def\prevsubpagenumber  {\convertedcounter[\s!subpage ][\c!type=\v!previous]}
166
167%permanent\def\nextrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!next]}
168%permanent\def\nextuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!next]}
169%permanent\def\nextsubpagenumber  {\convertedcounter[\s!subpage ][\c!type=\v!next]}
170
171\permanent\def\firstrealpage{\strc_counters_first\s!realpage}
172\permanent\def\firstuserpage{\strc_counters_first\s!userpage}
173\permanent\def\firstsubpage {\strc_counters_first\s!subpage }
174
175\permanent\def\prevrealpage {\strc_counters_prev \s!realpage}
176\permanent\def\prevuserpage {\strc_counters_prev \s!userpage}
177\permanent\def\prevsubpage  {\strc_counters_prev \s!subpage }
178
179\permanent\def\nextrealpage {\strc_counters_next \s!realpage}
180\permanent\def\nextuserpage {\strc_counters_next \s!userpage}
181\permanent\def\nextsubpage  {\strc_counters_next \s!subpage }
182
183\permanent\def\lastrealpage {\strc_counters_last \s!realpage}
184\permanent\def\lastuserpage {\strc_counters_last \s!userpage}
185\permanent\def\lastsubpage  {\strc_counters_last \s!subpage }
186
187\aliased\let\firstpage\firstrealpage
188\aliased\let\prevpage \prevrealpage
189\aliased\let\nextpage \nextrealpage
190\aliased\let\lastpage \lastrealpage
191
192% Compatibility counters:
193
194\permanent\def\nofrealpages {\lastrealpage} \permanent\def\totalnumberofpages{\lastrealpage}
195\permanent\def\nofuserpages {\lastuserpage} \permanent\def\lastpagenumber    {\lastuserpage}
196\permanent\def\nofsubpages  {\lastsubpage }
197
198% Renderers:
199
200\permanent\def\pagenumber         {\strc_counters_raw\s!userpage}
201\permanent\def\prefixedpagenumber {\directconvertedcounter\s!userpage\empty} % \userpagenumber
202
203\permanent\def\realpagenumber     {\directconvertedcounter\s!realpage\empty}
204\permanent\def\userpagenumber     {\directconvertedcounter\s!userpage\empty}
205\permanent\def\subpagenumber      {\directconvertedcounter\s!subpage \empty}
206
207\permanent\def\firstrealpagenumber{\directconvertedcounter\s!realpage\v!first}
208\permanent\def\firstuserpagenumber{\directconvertedcounter\s!userpage\v!first}
209\permanent\def\firstsubpagenumber {\directconvertedcounter\s!subpage \v!first}
210
211\permanent\def\lastrealpagenumber {\directconvertedcounter\s!realpage\v!last}
212\permanent\def\lastuserpagenumber {\directconvertedcounter\s!userpage\v!last}
213\permanent\def\lastsubpagenumber  {\directconvertedcounter\s!subpage \v!last}
214
215\permanent\def\prevrealpagenumber {\directconvertedcounter\s!realpage\v!previous}
216\permanent\def\prevuserpagenumber {\directconvertedcounter\s!userpage\v!previous}
217\permanent\def\prevsubpagenumber  {\directconvertedcounter\s!subpage \v!previous}
218
219\permanent\def\nextrealpagenumber {\directconvertedcounter\s!realpage\v!next}
220\permanent\def\nextuserpagenumber {\directconvertedcounter\s!userpage\v!next}
221\permanent\def\nextsubpagenumber  {\directconvertedcounter\s!subpage \v!next}
222
223\protected\def\strc_pagenumbers_decrement_counters % only at the end
224   {\strc_counters_decrement\s!realpage
225    \strc_counters_decrement\s!userpage
226    \strc_counters_decrement\s!subpage}
227
228\protected\def\strc_pagenumbers_increment_counters
229  {\incrementpagenumber
230   \incrementsubpagenumber}
231
232\appendtoks
233    \strc_pagenumbers_decrement_counters
234\to \everygoodbye
235
236\newcount\c_strc_subpage_first_real \c_strc_subpage_first_real\plusone
237
238\appendtoks
239   \ifcase\subpageno\relax
240     \global\c_strc_subpage_first_real\realpageno
241   \or
242     \global\c_strc_subpage_first_real\realpageno
243   \fi
244\to \everybeforepagebody
245
246\permanent\def\therealsubpageno#1% new helper
247  {\the\numexpr\c_strc_subpage_first_real+#1+\minusone\relax}
248
249% Equivalents (compatibility):
250%
251% todo: maybe leave lastpage etc lua calls
252
253\permanent\def\realpage{\the\realpageno}
254\permanent\def\userpage{\the\userpageno}
255\permanent\def\subpage {\the\subpageno}
256
257% Hooks:
258
259\permanent\def\currentpage{\the\realpageno}% rather useless
260
261\appendtoks
262    \ifnum\realpageno>\lastpage \enforced\glet\lastpage\lastrealpage \fi
263\to \everyinitializepagecounters
264
265% States:
266
267\newconditional\layoutisdoublesided % already defined: \newif\ifdoublesided
268\newconditional\layoutissinglesided % already defined: \newif\ifsinglesided
269
270% Realpage and subpage numbers:
271
272\permanent\protected\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax}
273\permanent\protected\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax}
274
275% Page numbers: (can move to lua) ... inconsistent names
276
277\installcorenamespace{pagenumberinc}
278\installcorenamespace{pagenumberdec}
279
280\protected\def\strc_pagenumbers_decrement_userpage{\global\userpageno\strc_counters_decremented\s!userpage\relax}
281\protected\def\strc_pagenumbers_increment_userpage{\global\userpageno\strc_counters_incremented\s!userpage\relax}
282
283\permanent\protected\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax}
284\permanent\protected\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax}
285
286\protected\def\strc_pagenumbers_synchronize_userpage{\global\c_strc_pagenumbers_state_userpage\plustwo} % start and visible
287
288\permanent\protected\def\decrementpagenumber{\csname\??pagenumberdec\namedcounterparameter\s!userpage\c!state\endcsname}
289\permanent\protected\def\incrementpagenumber{\csname\??pagenumberinc\namedcounterparameter\s!userpage\c!state\endcsname}
290
291\letvalue{\??pagenumberdec\v!start}\strc_pagenumbers_decrement_userpage
292\letvalue{\??pagenumberdec\v!none }\strc_pagenumbers_decrement_userpage
293\letvalue{\??pagenumberdec\v!empty}\strc_pagenumbers_decrement_userpage
294
295\letvalue{\??pagenumberinc\v!start}\strc_pagenumbers_increment_userpage
296\letvalue{\??pagenumberinc\v!none }\strc_pagenumbers_increment_userpage
297\setvalue{\??pagenumberinc\v!empty}{\strc_pagenumbers_increment_userpage\strc_pagenumbers_synchronize_userpage}
298\letvalue{\??pagenumberinc\v!keep }\strc_pagenumbers_synchronize_userpage
299
300% Setup general page numbering
301
302\installcorenamespace{pagenumbering}
303
304\installdirectcommandhandler \??pagenumbering {pagenumbering}
305
306% some day ifsinglesided and ifdoublesided will become obsolete
307
308\newtoks\everysidedswitch
309
310\appendtoks
311   \singlesidedfalse \setfalse\layoutisdoublesided
312   \doublesidedfalse \setfalse\layoutissinglesided
313   \resetsystemmode\v!singlesided
314   \resetsystemmode\v!doublesided
315   \processallactionsinset
316     [\directpagenumberingparameter\c!alternative]%
317     [ \v!singlesided=>\setsystemmode\v!singlesided\singlesidedtrue\settrue\layoutissinglesided,
318       \v!doublesided=>\setsystemmode\v!doublesided\doublesidedtrue\settrue\layoutisdoublesided]%
319   \the\everysidedswitch
320   \pageduplexmode
321     \ifsinglesided
322       \ifdoublesided\plustwo\else\zerocount\fi
323     \else
324       \ifdoublesided\plusone\else\zerocount\fi
325     \fi
326   \page_backgrounds_recalculate
327   \strc_pagenumbers_set_location
328\to \everysetuppagenumbering
329
330\ifdefined \page_backgrounds_recalculate \else
331    \let\page_backgrounds_recalculate\relax
332\fi
333
334\ifdefined \strc_pagenumbers_set_location \else
335    \let\strc_pagenumbers_set_location\relax
336\fi
337
338\protected\def\strc_pagenumbers_flush_final_page
339  {\edef\p_strc_pagenumbers_page{\directpagenumberingparameter\c!page}%
340   \ifempty\p_strc_pagenumbers_page \else
341     \ifx\p_strc_pagenumbers_page\v!no \else
342       \page[\p_strc_pagenumbers_page]%
343     \fi
344   \fi}
345
346% The numbered location handler is there because we need to be downward
347% compatible. So, in fact there can be multiple handlers active at the
348% same time, but only the current one does something.
349
350% Rendering:
351
352\protected\def\strc_pagenumbers_place_location
353  {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
354     \ifnum\c_strc_pagenumbers_state=\plusone
355        \doif{\directpagenumberingparameter\c!strut}\v!yes\strut
356        \begingroup
357        \usepagenumberingstyleandcolor\c!style\c!color
358        \directpagenumberingparameter\c!command
359          {\directpagenumberingparameter\c!left
360           \labeltexts\v!pagenumber\prefixedpagenumber
361           \directpagenumberingparameter\c!right}%
362        \endgroup
363     \fi
364   \fi}
365
366\permanent\protected\def\completepagenumber
367  {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
368     \ifnum\c_strc_pagenumbers_state=\plusone
369        \directpagenumberingparameter\c!left
370        \labeltexts\v!pagenumber\prefixedpagenumber
371        \directpagenumberingparameter\c!right
372     \fi
373   \fi}
374
375\permanent\protected\def\placepagenumber
376  {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
377     \ifnum\c_strc_pagenumbers_state=\plusone
378        \labeltexts\v!pagenumber\pagenumber
379     \fi
380   \fi}
381
382\permanent\protected\def\referencepagenumber[#1]%
383  {\doifelsenothing{#1}{?}{}}
384
385% The numbered location handler is there because we need to be downward
386% compatible. So, in fact there can be multiple handlers active at the
387% same time, but only the current one does something.
388
389\setnewconstant\c_strc_pagenumbers_state_realpage\plustwo % counter state : 0=stop, 1=start, 2=start and visible
390\setnewconstant\c_strc_pagenumbers_state_userpage\plustwo % counter state : 0=stop, 1=start, 2=start and visible
391\setnewconstant\c_strc_pagenumbers_state_subpage \plustwo % counter state : 0=stop, 1=start, 2=start and visible
392\setnewconstant\c_strc_pagenumbers_state         \plusone % general number: 0=invisible, 1=visible
393
394\protected\def\strc_pagenumbers_check_state_change#1#2%
395  {\edef\m_strc_pagenumbers_state_new{\namedcounterparameter#1\c!state}%
396   \ifx\m_strc_pagenumbers_state_new\m_strc_pagenumbers_state_old \else
397     #2\ifx\m_strc_pagenumbers_state_new\v!start\plustwo\else\zerocount\fi
398   \fi}
399
400\appendtoks % todo: set state: none, start, stop, reset
401    \strc_pagenumbers_check_state_change\s!realpage\c_strc_pagenumbers_state_realpage
402\to \everysetuprealpagenumber
403
404\appendtoks % todo: set state: none, start, stop, reset
405    \strc_pagenumbers_check_state_change\s!userpage\c_strc_pagenumbers_state_userpage
406\to \everysetupuserpagenumber
407
408\appendtoks % todo: set state: none, start, stop, reset
409    \strc_pagenumbers_check_state_change\s!subpage\c_strc_pagenumbers_state_subpage
410\to \everysetupsubpagenumber
411
412\appendtoks % todo: set state: none, start, stop, reset
413    \doifelse{\directpagenumberingparameter\c!state}\v!start
414      {\c_strc_pagenumbers_state\plusone  }%
415      {\c_strc_pagenumbers_state\zerocount}%
416\to \everysetuppagenumbering
417
418% Done
419
420% \c!way=\v!by\v!part
421% \c!text=
422% \v!chapter\v!number=\v!no
423% \v!part\v!number=\v!yes
424% \c!numberseparator=--
425% \c!conversion=\v!numbers
426
427\setuppagenumbering
428  [\c!alternative=\v!singlesided,
429   \c!location={\v!header,\v!middle},
430   \c!width=, % in geval van \v!marginedge
431   \c!left=,
432   \c!right=,
433   \c!page=\v!last,
434   \c!textseparator=\tfskip,
435   \c!state=\v!start,
436   \c!command=,
437   \c!strut=\v!yes,
438   \c!style=, % empty, otherwise conflict
439   \c!color=]
440
441% just for downward compatbility
442
443\appendtoks
444    \edef\scratchstringone{\namedcounterparameter\s!userpage\c!number}%
445    \ifempty\scratchstringone \else
446      \normalexpanded{\setuppagenumber[\c!start=\scratchstringone,\c!number=]}%
447      \userpageno\strc_counters_raw\s!userpage
448    \fi
449\to \everysetupuserpagenumber % todo: set state: none, start, stop, reset
450
451\appendtoks
452    \edef\scratchstringone{\namedcounterparameter\s!subpage\c!number}%
453    \ifempty\scratchstringone \else
454      \normalexpanded{\setupsubpagenumber[\c!start=\scratchstringone,\c!number=]}%
455      \subpageno\strc_counters_raw\s!subpage\relax
456    \fi
457\to \everysetupsubpagenumber % todo: set state: none, start, stop, reset
458
459% \setuplayout[width=300pt,backspace=4cm]
460% \setuppagenumbering [alternative=doublesided]
461% \setupuserpagenumber[start=2]
462% \starttext \dorecurse{20}{\input knuth \par} \stoptext
463
464\protected\def\strc_pagenumbers_check_change_shift
465  {\userpageno\strc_counters_raw\s!userpage\relax
466   \ifnum\realpageno=\plusone
467     \ifodd\userpageno
468     \else
469       \global\pagenoshift\plusone
470     \fi
471   \fi}
472
473\appendtoks % todo: set state: none, start, stop, reset
474    % this makes starting at an even page possible
475    \strc_pagenumbers_check_change_shift
476\to \everysetupuserpagenumber
477
478\appendtoks % todo: set state: none, start, stop, reset
479    % this makes starting at an even page possible
480    \strc_pagenumbers_check_change_shift
481\to \everysetuppagenumbering
482
483\initializepagecounters
484
485\stopcontextdefinitioncode
486
487\protect \endinput
488