page-brk.mkxl /size: 15 Kb    last modification: 2025-02-21 11:03
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{\realpageno;\plusfour}\else
243       \page_breaks_handle_direct\v!yes
244       \localcontrolledrepeating
245         {\ifcase{\realpageno;\plusfour}%
246            \quitloop
247          \else
248            \page_breaks_handle_direct\v!empty
249          \fi}%
250     \fi
251   \fi}
252
253\installpagebreakmethod \v!last
254  {\page_otr_command_flush_all_floats
255   \page_otr_command_next_page_and_inserts
256   \relax
257   \doifbothsidesoverruled
258     \page_facings_flush % hm
259     \donothing
260     {\noheaderandfooterlines
261      \page_otr_insert_dummy_page}%
262   \filluparrangedpages}
263
264\installpagebreakmethod \v!lastpage % handy for backpage preceded by empty pages
265  {\page_breaks_handle_direct\v!yes
266   \ifdoublesided
267     \page_breaks_handle_direct\v!left
268     \page_breaks_handle_direct\v!empty
269     \page_breaks_handle_direct\v!empty
270   \fi}
271
272\installpagebreakmethod \v!start {\global\c_otr_shipout_enabled\conditionaltrue}
273\installpagebreakmethod \v!stop  {\global\c_otr_shipout_enabled\conditionalfalse}
274
275\installpagebreakmethod{xy}% for Mojca
276  {\page_breaks_handle_direct\v!yes
277   \scratchcounterone  {(\rootlayouttargetparameter\c!nx)*(\rootlayouttargetparameter\c!ny)}%
278  %\scratchcountertwo  \luaexpr{math.mod(\the\realpageno-1,\the\scratchcounterone)}\relax
279   \scratchcountertwo  {(\realpageno-1):\scratchcounterone}%
280   \scratchcounterthree{\scratchcounterone-\scratchcountertwo}%
281   \dorecurse\scratchcounterthree{\page_breaks_handle_direct\v!empty}}
282
283% Column breaks.
284
285\installcorenamespace{columnbreakmethod}
286\installcorenamespace{columnbreaks}
287
288\newtoks\everybeforecolumnbreak
289\newtoks\everyaftercolumnbreak
290\newtoks\everysynchronizecolumn
291
292\lettonothing\page_breaks_columns_current_option
293\lettonothing\page_breaks_columns_current_options
294
295\def\page_breaks_columns_handle#1%
296  {\edef\page_breaks_columns_current_options{#1}%
297   \processcommacommand[#1]\page_breaks_columns_handle_step}
298
299\def\page_breaks_columns_handle_step#1%
300  {\edef\page_breaks_columns_current_option{#1}%
301   \ifcsname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
302     \lastnamedcs
303   \orelse\ifcsname\??columnbreaks\page_breaks_columns_current_option\endcsname
304    %\expandafter\csname\page_breaks_columns_handle\??columnbreaks\page_breaks_columns_current_option\endcsname
305     \lastnamedcs
306   \orelse\ifcsname\??columnbreakmethod\currentoutputroutine:\s!unknown\endcsname
307     \lastnamedcs
308   \fi}
309
310\def\page_breaks_columns_handle_direct#1%
311  {\begincsname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
312
313\permanent\protected\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action
314  {\defcsname\??columnbreakmethod#1:#2\endcsname{#3}}
315
316\aliased\let\installcolumnbreakhandler\installcolumnbreakmethod % will go
317
318\permanent\tolerant\protected\def\definecolumnbreak[#1]#*[#2]%
319  {\defcsname\??columnbreaks#1\endcsname{#2}}
320
321%D So, page ornaments are reset after a pagebreak command, unless set!
322
323\permanent\tolerant\protected\def\columnbreak[#1]%
324  {\par % else no vertical penalties
325   \begingroup
326   \expand\everybeforecolumnbreak
327   \ifparameter#1\or
328     \page_breaks_columns_handle{#1}%
329   \else
330     \page_breaks_columns_handle_direct\v!yes
331   \fi
332   \relax
333   \expand\everyaftercolumnbreak
334   \endgroup
335   % outside group e.g. setting hsize
336   \expand\everysynchronizecolumn}
337
338\aliased\let\column\columnbreak
339
340\appendtoks
341    \page_otr_command_set_hsize
342\to \everysynchronizecolumn
343
344%D Test page breaks.
345
346% \newdimension\d_page_tests_test
347% \newconstant \c_page_tests_mode
348
349\newconstant\testpagemethod  % old
350\newconstant\testpagetrigger % old
351
352\installcorenamespace {pagechecker}
353\installcorenamespace {pagecheckermethod}
354
355\installcommandhandler \??pagechecker {pagechecker} \??pagechecker
356
357\setuppagechecker
358  [\c!method=1,
359   \c!before=,
360   \c!after=,
361   \c!inbetween=,
362   \c!lines=\plusthree,
363   \c!offset=\zeropoint]
364
365\def\page_check_amount
366  {(\pagecheckerparameter\c!lines\lineheight)%
367   +\pagetotal
368    \ifdim\lastskip<\parskip+\parskip\fi
369   +(\pagecheckerparameter\c!offset)}
370
371\permanent\tolerant\protected\def\checkpage[#1]#*[#2]%
372  {\relax % look ahead prevention
373   \endgraf
374   \triggerpagebuilder
375   \relax
376   \ifconditional\c_page_breaks_enabled
377     \begingroup
378     \cdef\currentpagechecker{#1}%
379     \setupcurrentpagechecker[#2]%
380     \csname\??pagecheckermethod\pagecheckerparameter\c!method\endcsname
381     \endgroup
382   \fi}
383
384\defcsname\??pagecheckermethod 0\endcsname
385  {\ifdim\pagegoal<\maxdimen \relax
386     \ifdim\pagetotal<\pagegoal \relax
387       \ifdim{\page_check_amount}>.99\pagegoal
388         \pagecheckerparameter\c!before
389         \penalty-\plustenthousand
390         \pagecheckerparameter\c!after
391       \else
392         \pagecheckerparameter\c!inbetween
393       \fi
394     \else
395       \pagecheckerparameter\c!inbetween
396     \fi
397   \else
398     \pagecheckerparameter\c!inbetween
399   \fi}
400
401\defcsname\??pagecheckermethod 1\endcsname
402  {\ifdim\pagegoal<\maxdimen \relax
403     \ifdim\pagetotal<\pagegoal \relax
404       \ifdim{\page_check_amount-\pagegoal}>-\lineheight
405         \pagecheckerparameter\c!before
406         \penalty-\plustenthousand
407         \pagecheckerparameter\c!after
408       \else
409         \pagecheckerparameter\c!inbetween
410       \fi
411     \else
412       \pagecheckerparameter\c!inbetween
413     \fi
414   \else
415     \goodbreak
416     \pagecheckerparameter\c!inbetween
417   \fi}
418
419\defcsname\??pagecheckermethod 2\endcsname
420  {\ifdim\pagegoal<\maxdimen \relax
421     \ifdim\pagetotal<\pagegoal \relax
422       \getnoflines\pagegoal
423       \ifdim{\page_check_amount-\noflines\lineheight}>-\lineheight
424         \pagecheckerparameter\c!before
425         \penalty-\plustenthousand
426         \pagecheckerparameter\c!after
427       \else
428         \pagecheckerparameter\c!inbetween
429       \fi
430     \else
431       \pagecheckerparameter\c!inbetween
432     \fi
433   \else
434     \pagecheckerparameter\c!inbetween
435   \fi}
436
437\defcsname\??pagecheckermethod 3\endcsname
438  {\ifdim\pagegoal<\maxdimen \relax
439     \ifdim\pagetotal<\pagegoal \relax
440       \ifdim{\page_check_amount-10\scaledpoint}>\pagegoal
441         \pagecheckerparameter\c!before
442         \penalty-\plustenthousand
443         \pagecheckerparameter\c!after
444       \else
445         \pagecheckerparameter\c!inbetween
446       \fi
447     \orelse\ifdim\pagetotal>\pagegoal
448       \ifdim{\pagetotal-\pageshrink}>\pagegoal
449         \goodbreak
450         \pagecheckerparameter\c!inbetween
451       \else
452         \pagecheckerparameter\c!before
453         \page
454         \pagecheckerparameter\c!after
455       \fi
456     \else
457       \pagecheckerparameter\c!inbetween
458     \fi
459   \else
460     \pagecheckerparameter\c!inbetween
461   \fi}
462
463\definepagechecker[\s!unknown:0]              [\c!method=0,\c!before=,\c!after=,\c!inbetween=]
464\definepagechecker[\s!unknown:1][\s!unknown:0][\c!method=1]
465\definepagechecker[\s!unknown:2][\s!unknown:0][\c!method=2]
466\definepagechecker[\s!unknown:3][\s!unknown:0][\c!method=3]
467
468% the \relax prevents premature expansion in case of lookahead
469
470\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]}} %
471\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
472\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
473
474%D Test column breaks.
475
476\permanent\tolerant\protected\def\testcolumn[#1]#*[#2]%
477  {\relax % look ahead prevention
478   \ifdefined\page_otr_command_test_column
479     \ifparameter#2\or
480        \page_otr_command_test_column[#1][#2]%
481     \else
482        \page_otr_command_test_column[#1][\zeropoint]%
483     \fi
484   \fi}
485
486%D Experiment:
487
488\permanent\protected\def\setpagelooseness[#1]%
489  {\begingroup
490   \ifchkdimension#1\lineheight\or
491     \additionalpageskip
492       \lastchkdimension
493     \relax
494   \else
495     \letdummyparameter\c!lines  \zerocount
496     \letdummyparameter\c!height \zeropoint
497     \letdummyparameter\c!stretch\zeropoint
498     \letdummyparameter\c!shrink \zeropoint
499     \getdummyparameters[#1]%
500     \additionalpageskip
501       {(\dummyparameter\c!height)+\lineheight*(\dummyparameter\c!lines)}
502       \s!plus \dummyparameter\c!stretch
503       \s!minus\dummyparameter\c!shrink
504     \relax
505   \fi
506   \endgroup}
507
508\protect \endinput
509