page-brk.mkxl /size: 15 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=page-brk,   % moved from page-ini
3%D        version=2011.12.07, % 2000.10.20,
4%D          title=\CONTEXT\ Page Macros,
5%D       subtitle=Breaks,
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 Page Macros / Breaks}
15
16\unprotect
17
18\ifdefined\resetcurrentstructuremarkswithpage \else \let\resetcurrentstructuremarkswithpage\relax \fi
19\ifdefined\noheaderandfooterlines             \else \let\noheaderandfooterlines            \relax \fi
20
21%D Page breaks.
22
23% \definepagebreak
24%   [chapter]
25%   [yes,header,right]
26%
27% \setuphead
28%   [chapter]
29%   [page=chapter,
30%    header=empty,
31%    footer=chapter]
32%
33% \definepagebreak % untested
34%   [lastpage]
35%   [left,{empty,right},{empty,left}]
36
37% public page handler, beware: definepage already in use (core-ref)
38%
39% \definepagebreak[instance][forsure]
40% \definepagebreak[forsure][yes,+4]
41
42\newconditional\c_page_breaks_enabled   \c_page_breaks_enabled\conditionaltrue
43\newinteger    \c_page_breaks_prevpage
44
45\newtoks\everybeforepagebreak
46\newtoks\everyafterpagebreak
47
48\lettonothing\page_breaks_current_option
49\lettonothing\page_breaks_current_options
50
51\installcorenamespace{pagebreakmethod}
52\installcorenamespace{pagebreaks}
53
54\def\page_breaks_handle#1%
55  {\edef\page_breaks_current_options{#1}% handy for tracing
56   \processcommacommand[\page_breaks_current_options]\page_breaks_handle_step}
57
58\def\page_breaks_handle_step#1%
59  {\edef\page_breaks_current_option{#1}% can be used in handler
60   \ifcsname\??pagebreakmethod\page_breaks_current_option\endcsname
61     \lastnamedcs
62   \orelse\ifcsname\??pagebreaks\page_breaks_current_option\endcsname
63     \expandafter\page_breaks_handle\lastnamedcs
64   \else
65     \page_breaks_unknown
66   \fi}
67
68\def\page_breaks_handle_direct#1%
69  {\begincsname\??pagebreakmethod#1\endcsname}
70
71\permanent\protected\def\installpagebreakmethod#1#2% low level definer
72  {\defcsname\??pagebreakmethod#1\endcsname{#2}}
73
74\aliased\let\installpagebreakhandler\installpagebreakmethod % will go
75
76\permanent\tolerant\protected\def\definepagebreak[#1]#*[#2]%
77  {\defcsname\??pagebreaks#1\endcsname{#2}}
78
79\appendtoks
80    \flushnotes
81\to \everybeforepagebreak
82
83\permanent\tolerant\protected\def\pagebreak[#1]
84  {\par % else no vertical penalties, always before group so that we clear hangs etc (as in side floats)
85   \ifvmode % extra check
86     \begingroup
87     \expand\everybeforepagebreak
88     \c_page_breaks_prevpage\realpageno
89     \ifcase\pageornamentstate \or
90       % disable reset after shipout
91       \global\pageornamentstate\plustwo
92     \fi
93     % maybe \ifempty{#1}%
94     \ifparameter#1\or
95       \page_breaks_handle{#1}%
96     \else % so, no pagebreak when \pagebreak[] ! ! !
97       \page_breaks_handle_direct\v!yes
98     \fi
99     \relax
100     \ifnum\c_page_breaks_prevpage<\realpageno
101       \global\pageornamentstate\zerocount
102     \fi
103     \expand\everyafterpagebreak
104     \endgroup
105   \fi}
106
107\aliased\let\page\pagebreak
108
109\permanent\protected\def\usepageparameter#1%
110  {\edef\m_page_breaks_asked{#1\c!page}%
111   \ifempty\m_page_breaks_asked\else
112     \pagebreak[\m_page_breaks_asked]%
113   \fi}
114
115\permanent\protected\def\dousepageparameter#1%
116  {\edef\m_page_breaks_asked{#1}%
117   \ifempty\m_spac_align_asked\else
118     \pagebreak[\m_page_breaks_asked]%
119   \fi}
120
121\permanent\protected\def\resetpagebreak % used elsewhere too
122  {\global\c_page_breaks_enabled\conditionaltrue}
123
124\permanent\protected\def\simplifypagebreak % to be used grouped !
125  {\enforced\permanent\protected\def\pagebreak[##1]{\goodbreak}}
126
127\permanent\protected\def\disablepagebreaks % to be used grouped !
128  {\enforced\let\pagebreak\gobbleoneoptional}
129
130\installpagebreakmethod \s!dummy
131  {\page_otr_command_flush_all_floats
132   \page_otr_command_next_page
133   \page_otr_insert_dummy_page}
134
135\installpagebreakmethod \v!frame
136  {\page
137   \begingroup
138   \showframe
139   \page[\v!empty]
140   \endgroup}
141
142\protected\def\page_breaks_unknown % how often called ?
143  {\ifhastok+\page_breaks_current_option
144     \page_otr_command_flush_all_floats
145     \page_otr_command_next_page
146     \dorecurse\page_breaks_current_option\page_otr_insert_dummy_page
147   \orelse\ifchknum\page_breaks_current_option\or
148      \page_otr_command_flush_all_floats
149      \page_otr_command_next_page
150      \localcontrolledrepeating
151        {\ifnum\userpageno<\page_breaks_current_option\relax
152           \page_otr_insert_dummy_page
153         \else
154           \quitloop
155         \fi}%
156   \fi}
157
158\installpagebreakmethod \s!unknown
159  {\page_breaks_unknown}
160
161\installpagebreakmethod \s!default
162  {} % do nothing if empty
163
164\installpagebreakmethod \v!reset
165  {% better not: \global\pageornamentstate\zerocount
166   \resetpagebreak}
167
168\installpagebreakmethod \v!disable
169  {\global\c_page_breaks_enabled\conditionalfalse}
170
171\installpagebreakmethod \v!yes
172  {\ifconditional\c_page_breaks_enabled
173     \page_otr_command_flush_all_floats
174     \page_otr_command_next_page
175     \ifinsidecolumns       % this will move to MUL
176       \page_otr_eject_page % otherwise sometimes no change
177     \fi
178   \fi}
179
180\installpagebreakmethod \v!makeup
181  {\ifconditional\c_page_breaks_enabled
182     \page_otr_fill_and_eject_page
183   \fi}
184
185\installpagebreakmethod \v!blank
186  {\ifcase\pageornamentstate
187     \global\pageornamentstate\plusone
188   \fi}
189
190% also needed: \page \doifoddpageelse\relax{\page[\v!blank,\v!right]
191
192\installpagebreakmethod \v!no
193  {\ifconditional\c_page_breaks_enabled
194     \dosomebreak\nobreak
195   \fi}
196
197\installpagebreakmethod \v!preference
198  {\ifconditional\c_page_breaks_enabled
199     \ifinsidecolumns % this will move to MUL
200       \dosomebreak\goodbreak
201     \else
202       \testpage[3][\zeropoint]%
203     \fi
204   \fi}
205
206\installpagebreakmethod \v!bigpreference
207  {\ifconditional\c_page_breaks_enabled
208     \ifinsidecolumns % this will move to MUL
209       \dosomebreak\goodbreak
210     \else
211       \testpage[5][\zeropoint]%
212     \fi
213   \fi}
214
215% \installpagebreakmethod \v!empty {} % defined in page-txt.mkiv
216% \installpagebreakmethod \v!header{} % defined in page-txt.mkiv
217% \installpagebreakmethod \v!footer{} % defined in page-txt.mkiv
218
219\def\page_reset_marks_and_insert_dummy
220  {\resetcurrentstructuremarkswithpage\page_otr_insert_dummy_page}
221
222\installpagebreakmethod \v!left
223  {\page_otr_command_flush_all_floats
224   \page_otr_command_next_page_and_inserts
225   \doifbothsidesoverruled\donothing\page_reset_marks_and_insert_dummy\donothing}
226
227\installpagebreakmethod \v!right
228  {\page_otr_command_flush_all_floats
229   \page_otr_command_next_page_and_inserts
230   \doifbothsidesoverruled\donothing\donothing\page_reset_marks_and_insert_dummy}
231
232\installpagebreakmethod \v!even
233  {\page
234   \doifelseoddpage\page_reset_marks_and_insert_dummy\donothing}
235
236\installpagebreakmethod \v!odd
237  {\page
238   \doifelseoddpage\donothing\page_reset_marks_and_insert_dummy}
239
240\installpagebreakmethod \v!quadruple % not yet ok inside columnsets
241  {\ifdoublesided
242   % \ifcase\modulonumber\plusfour\realpageno\else
243     \ifcase\numexpr\realpageno;\plusfour\relax\else
244       \page_breaks_handle_direct\v!yes
245       \localcontrolledrepeating
246        %{\ifcase\modulonumber\plusfour\realpageno\relax
247         {\ifcase\numexpr\realpageno;\plusfour\relax
248            \quitloop
249          \else
250            \page_breaks_handle_direct\v!empty
251          \fi}%
252     \fi
253   \fi}
254
255\installpagebreakmethod \v!last
256  {\page_otr_command_flush_all_floats
257   \page_otr_command_next_page_and_inserts
258   \relax
259   \doifbothsidesoverruled
260     \page_facings_flush % hm
261     \donothing
262     {\noheaderandfooterlines
263      \page_otr_insert_dummy_page}%
264   \filluparrangedpages}
265
266\installpagebreakmethod \v!lastpage % handy for backpage preceded by empty pages
267  {\page_breaks_handle_direct\v!yes
268   \ifdoublesided
269     \page_breaks_handle_direct\v!left
270     \page_breaks_handle_direct\v!empty
271     \page_breaks_handle_direct\v!empty
272   \fi}
273
274\installpagebreakmethod \v!start {\global\c_otr_shipout_enabled\conditionaltrue}
275\installpagebreakmethod \v!stop  {\global\c_otr_shipout_enabled\conditionalfalse}
276
277\installpagebreakmethod{xy}% for Mojca
278  {\page_breaks_handle_direct\v!yes
279   \scratchcounterone  \numexpr\rootlayouttargetparameter\c!nx*\rootlayouttargetparameter\c!ny\relax
280   \scratchcountertwo  \luaexpr{math.mod(\the\realpageno-1,\the\scratchcounterone)}\relax
281   \scratchcounterthree\numexpr\scratchcounterone-\scratchcountertwo\relax
282   \dorecurse\scratchcounterthree{\page_breaks_handle_direct\v!empty}}
283
284% Column breaks.
285
286\installcorenamespace{columnbreakmethod}
287\installcorenamespace{columnbreaks}
288
289\newtoks\everybeforecolumnbreak
290\newtoks\everyaftercolumnbreak
291\newtoks\everysynchronizecolumn
292
293\lettonothing\page_breaks_columns_current_option
294\lettonothing\page_breaks_columns_current_options
295
296\def\page_breaks_columns_handle#1%
297  {\edef\page_breaks_columns_current_options{#1}%
298   \processcommacommand[#1]\page_breaks_columns_handle_step}
299
300\def\page_breaks_columns_handle_step#1%
301  {\edef\page_breaks_columns_current_option{#1}%
302   \ifcsname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
303     \lastnamedcs
304   \orelse\ifcsname\??columnbreaks\page_breaks_columns_current_option\endcsname
305    %\expandafter\csname\page_breaks_columns_handle\??columnbreaks\page_breaks_columns_current_option\endcsname
306     \lastnamedcs
307   \orelse\ifcsname\??columnbreakmethod\currentoutputroutine:\s!unknown\endcsname
308     \lastnamedcs
309   \fi}
310
311\def\page_breaks_columns_handle_direct#1%
312  {\begincsname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
313
314\permanent\protected\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action
315  {\defcsname\??columnbreakmethod#1:#2\endcsname{#3}}
316
317\aliased\let\installcolumnbreakhandler\installcolumnbreakmethod % will go
318
319\permanent\tolerant\protected\def\definecolumnbreak[#1]#*[#2]%
320  {\defcsname\??columnbreaks#1\endcsname{#2}}
321
322%D So, page ornaments are reset after a pagebreak command, unless set!
323
324\permanent\tolerant\protected\def\columnbreak[#1]%
325  {\par % else no vertical penalties
326   \begingroup
327   \expand\everybeforecolumnbreak
328   \ifparameter#1\or
329     \page_breaks_columns_handle{#1}%
330   \else
331     \page_breaks_columns_handle_direct\v!yes
332   \fi
333   \relax
334   \expand\everyaftercolumnbreak
335   \endgroup
336   % outside group e.g. setting hsize
337   \expand\everysynchronizecolumn}
338
339\aliased\let\column\columnbreak
340
341\appendtoks
342    \page_otr_command_set_hsize
343\to \everysynchronizecolumn
344
345%D Test page breaks.
346
347% \newdimension\d_page_tests_test
348% \newconstant \c_page_tests_mode
349
350\newconstant\testpagemethod  % old
351\newconstant\testpagetrigger % old
352
353\installcorenamespace {pagechecker}
354\installcorenamespace {pagecheckermethod}
355
356\installcommandhandler \??pagechecker {pagechecker} \??pagechecker
357
358\setuppagechecker
359  [\c!method=1,
360   \c!before=,
361   \c!after=,
362   \c!inbetween=,
363   \c!lines=\plusthree,
364   \c!offset=\zeropoint]
365
366\def\page_check_amount
367  {\dimexpr
368      \pagecheckerparameter\c!lines\lineheight
369     +\pagetotal
370     \ifdim\lastskip<\parskip+\parskip\fi
371     +\pagecheckerparameter\c!offset
372   \relax}
373
374\permanent\tolerant\protected\def\checkpage[#1]#*[#2]%
375  {\relax % look ahead prevention
376   \endgraf
377   \triggerpagebuilder
378   \relax
379   \ifconditional\c_page_breaks_enabled
380     \begingroup
381     \cdef\currentpagechecker{#1}%
382     \setupcurrentpagechecker[#2]%
383     \csname\??pagecheckermethod\pagecheckerparameter\c!method\endcsname
384     \endgroup
385   \fi}
386
387\defcsname\??pagecheckermethod 0\endcsname
388  {\ifdim\pagegoal<\maxdimen \relax
389     \ifdim\pagetotal<\pagegoal \relax
390       \ifdim\page_check_amount>.99\pagegoal
391         \pagecheckerparameter\c!before
392         \penalty-\plustenthousand
393         \pagecheckerparameter\c!after
394       \else
395         \pagecheckerparameter\c!inbetween
396       \fi
397     \else
398       \pagecheckerparameter\c!inbetween
399     \fi
400   \else
401     \pagecheckerparameter\c!inbetween
402   \fi}
403
404\defcsname\??pagecheckermethod 1\endcsname
405  {\ifdim\pagegoal<\maxdimen \relax
406     \ifdim\pagetotal<\pagegoal \relax
407       \ifdim\dimexpr\page_check_amount-\pagegoal\relax>-\lineheight
408         \pagecheckerparameter\c!before
409         \penalty-\plustenthousand
410         \pagecheckerparameter\c!after
411       \else
412         \pagecheckerparameter\c!inbetween
413       \fi
414     \else
415       \pagecheckerparameter\c!inbetween
416     \fi
417   \else
418     \goodbreak
419     \pagecheckerparameter\c!inbetween
420   \fi}
421
422\defcsname\??pagecheckermethod 2\endcsname
423  {\ifdim\pagegoal<\maxdimen \relax
424     \ifdim\pagetotal<\pagegoal \relax
425       \getnoflines\pagegoal
426       \ifdim\dimexpr\page_check_amount-\noflines\lineheight\relax>-\lineheight
427         \pagecheckerparameter\c!before
428         \penalty-\plustenthousand
429         \pagecheckerparameter\c!after
430       \else
431         \pagecheckerparameter\c!inbetween
432       \fi
433     \else
434       \pagecheckerparameter\c!inbetween
435     \fi
436   \else
437     \pagecheckerparameter\c!inbetween
438   \fi}
439
440\defcsname\??pagecheckermethod 3\endcsname
441  {\ifdim\pagegoal<\maxdimen \relax
442     \ifdim\pagetotal<\pagegoal \relax
443       \ifdim\dimexpr\page_check_amount-10\scaledpoint\relax>\pagegoal
444         \pagecheckerparameter\c!before
445         \penalty-\plustenthousand
446         \pagecheckerparameter\c!after
447       \else
448         \pagecheckerparameter\c!inbetween
449       \fi
450     \orelse\ifdim\pagetotal>\pagegoal
451       \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal
452         \goodbreak
453         \pagecheckerparameter\c!inbetween
454       \else
455         \pagecheckerparameter\c!before
456         \page
457         \pagecheckerparameter\c!after
458       \fi
459     \else
460       \pagecheckerparameter\c!inbetween
461     \fi
462   \else
463     \pagecheckerparameter\c!inbetween
464   \fi}
465
466\definepagechecker[\s!unknown:0]              [\c!method=0,\c!before=,\c!after=,\c!inbetween=]
467\definepagechecker[\s!unknown:1][\s!unknown:0][\c!method=1]
468\definepagechecker[\s!unknown:2][\s!unknown:0][\c!method=2]
469\definepagechecker[\s!unknown:3][\s!unknown:0][\c!method=3]
470
471% the \relax prevents premature expansion in case of lookahead
472
473\permanent\tolerant\protected\def\testpage    [#1]#*[#2]{\relax\normalexpanded{\checkpage[\s!unknown:1][\c!lines=#1,\c!offset=\ifparameter#2\or#2\else\zeropoint\fi]}} %
474\permanent\tolerant\protected\def\testpageonly[#1]#*[#2]{\relax\normalexpanded{\checkpage[\s!unknown:2][\c!lines=#1,\c!offset=\ifparameter#2\or#2\else\zeropoint\fi]}} % no penalties added to the mvl
475\permanent\tolerant\protected\def\testpagesync[#1]#*[#2]{\relax\normalexpanded{\checkpage[\s!unknown:3][\c!lines=#1,\c!offset=\ifparameter#2\or#2\else\zeropoint\fi]}} % force sync
476
477%D Test column breaks.
478
479\permanent\tolerant\protected\def\testcolumn[#1]#*[#2]%
480  {\relax % look ahead prevention
481   \ifdefined\page_otr_command_test_column
482     \ifparameter#2\or
483        \page_otr_command_test_column[#1][#2]%
484     \else
485        \page_otr_command_test_column[#1][\zeropoint]%
486     \fi
487   \fi}
488
489%D Experiment:
490
491\permanent\protected\def\setpagelooseness[#1]%
492  {\begingroup
493   \ifchkdimension#1\lineheight\or
494     \additionalpageskip
495       \lastchkdimension
496     \relax
497   \else
498     \letdummyparameter\c!lines  \zerocount
499     \letdummyparameter\c!height \zeropoint
500     \letdummyparameter\c!stretch\zeropoint
501     \letdummyparameter\c!shrink \zeropoint
502     \getdummyparameters[#1]%
503     \additionalpageskip
504       \dimexpr\dummyparameter\c!height+\lineheight*\dummyparameter\c!lines\relax
505       \s!plus \dummyparameter\c!stretch
506       \s!minus\dummyparameter\c!shrink
507     \relax
508   \fi
509   \endgroup}
510
511\protect \endinput
512