page-pcl.mkxl /size: 36 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=page-pcl,
3%D        version=2017.11.08,
4%D          title=\CONTEXT\ Page Macros,
5%D       subtitle=Page Columns,
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 / Page Columns}
15
16%D This is very experimental code! We took a bit from the mixed columns and single
17%D column page code. This one works acceptable with floats and is for whole double
18%D column documents. We don't balance (yet). Footnotes are per column. One can have
19%D side floats too. No balancing and other fancy features.
20%D
21%D Don't use this in production! Although the main approach will stay there might be
22%D changes in the way floats are dealt with. Not much testing has been done but as
23%D we stay close to the single column mode we expect most to just work. Only floats
24%D are the (usual) pain. Backgrounds, line numbering, etc.\ not tested either.
25
26\unprotect
27
28\definemeasure[onecolumn]   [\columnwidth]
29\definemeasure[twocolumns]  [\dimexpr\plustwo  \columnwidth+          \columndistance\relax]
30\definemeasure[threecolumns][\dimexpr\plusthree\columnwidth+\plustwo  \columndistance\relax]
31\definemeasure[fourcolumns] [\dimexpr\plusfour \columnwidth+\plusthree\columndistance\relax]
32
33\newinteger    \c_page_col_n_of_columns \c_page_col_n_of_columns\plusone
34\newinteger    \c_page_col_current      \c_page_col_current     \plusone
35\newdimension  \d_page_col_distance
36\newdimension  \d_page_col_max_height
37\newdimension  \d_page_col_max_width
38%newdimension  \d_page_col_balance_step
39\newdimension  \d_page_col_column_width
40\newdimension  \d_page_col_top_height
41\newdimension  \d_page_col_top_width
42\newdimension  \d_page_col_available
43\newdimension  \d_page_col_sofar
44\newconditional\c_page_col_page
45
46%D We need to step over empty columns.
47
48\protected\def\page_col_command_next_page
49  {\page_col_eject_page}
50
51\permanent\protected\def\page_col_column
52  {\page_otr_eject_page}
53
54\protected\def\page_col_eject_page
55  {\begingroup
56   \scratchcountertwo  \realpageno
57   \page_otr_eject_page
58   \scratchcounterone  \c_page_col_current
59   \scratchcounterthree\zerocount
60   \doloop{%
61     \ifnum\scratchcounterthree>\plushundred
62       % too many attempts
63       \exitloop
64     \orelse\ifnum\realpageno>\scratchcountertwo
65       % we advanced at least one page so we're done
66       \exitloop
67     \else
68       \ifnum\scratchcounterone=\c_page_col_current
69          \dontleavehmode\null
70       \fi
71       \page_otr_eject_page
72       \scratchcounterone\c_page_col_current
73       \advanceby\scratchcounterthree\plusone
74     \fi
75   }%
76   \endgroup}
77
78%D \unknown
79
80\protected\def\page_col_command_next_page_and_inserts
81  {\page_otr_eject_page_and_flush_inserts}
82
83%D \unknown
84
85\protected\def\page_col_command_set_hsize
86  {\global\hsize\d_page_col_column_width\relax
87   \global\d_page_col_available{%
88      \numexpr\c_page_col_n_of_columns-\c_page_col_current+\plusone\relax\d_page_col_column_width
89    + \numexpr\c_page_col_n_of_columns-\c_page_col_current         \relax\d_page_col_distance
90   }%
91   \global\d_page_col_sofar
92   \ifnum\c_page_col_n_of_columns=\plusone
93     \zeropoint
94   \else
95     \numexpr\c_page_col_n_of_columns-\plusone\relax
96     \dimexpr\d_page_col_column_width+\d_page_col_distance\relax
97   \fi
98   % consistent with mixed:
99   \textwidth\d_page_col_column_width}
100
101%D \unknown
102
103\def\page_col_registered_text_area_b#1%
104  {\begingroup
105   \makeupwidth\d_page_col_column_width
106   \page_one_registered_text_area_b{#1}%
107   \endgroup}
108
109\protected\def\page_col_command_package_contents#1#2% \box<n> \unvbox<n> % this one will be redone (checked)
110  {\bgroup
111   \setbox\b_page_one_contents\vbox to \textheight
112     {\page_one_registered_text_area_a#1#2}%
113   \page_one_command_package_show_state
114   \ht\b_page_one_contents\textheight
115   \page_col_registered_text_area_b
116     {\box\b_page_one_contents}%
117   \egroup}
118
119\protected\def\page_col_command_package_contents_one#1#2% \box<n> \unvbox<n> % this one will be redone (checked)
120  {\bgroup
121     \forgetall
122     % see one for comments as it is similar
123     \strc_notes_check_if_bottom_present
124     \d_page_one_natural_depth\dp#2\relax
125%      \page_layouts_check_stretch#2%
126     \setbox\b_page_one_contents\vbox to \textheight
127       {\page_col_command_flush_top_insertions
128        \page_one_registered_text_area_a#1#2%
129        \hsize\d_page_col_column_width
130        \ifgridsnapping
131          \vskip{\openstrutdepth-\d_page_one_natural_depth}%
132          \prevdepth\openstrutdepth
133          \page_col_command_flush_bottom_insertions
134          \vfil
135        \orelse\ifcase\bottomraggednessmode
136          % ragged (default)
137          \vskip{\openstrutdepth-\d_page_one_natural_depth}%
138          \prevdepth\openstrutdepth
139          \page_col_command_flush_bottom_insertions
140          \vfil
141        \or
142          % align (normal)
143          \page_col_command_flush_bottom_insertions
144        \or
145          % baseline
146          \vkern{\maxdepth-\d_page_one_natural_depth}%
147          \page_col_command_flush_bottom_insertions
148        \or
149          % depth
150          \vskip-\d_page_one_natural_depth
151          \page_col_command_flush_bottom_insertions
152        \fi
153        \fakepagenotes}%
154     \page_layouts_check_stretch\b_page_one_contents
155     \page_one_command_package_show_state
156     \ifconditional\c_notes_bottom_present
157       \ifgridsnapping
158         \ifcase\layoutlines
159           \getrawnoflines\textheight
160         \else
161           \noflines\layoutlines
162         \fi
163         \scratchoffset{\numexpr\noflines-\plusone\relax\lineheight+\topskip}%
164       \else
165         \scratchoffset\ht\b_page_one_contents
166       \fi
167       \setbox\b_page_one_bottom_notes\hpack
168         {\hsize\d_page_col_column_width
169          \setupnotes[\c!width=\textwidth]%
170          \lower{\scratchoffset-\initialpageskip}\vbox{\placebottomnotes\par\kern\zeropoint}}%
171       \ht\b_page_one_contents    \zeropoint
172       \wd\b_page_one_contents    \zeropoint
173       \ht\b_page_one_bottom_notes\zeropoint
174       \wd\b_page_one_bottom_notes\d_page_col_column_width
175       \page_col_registered_text_area_b
176         {\vpack to \textheight
177            {\hpack{\box\b_page_one_contents\box\b_page_one_bottom_notes}}}%
178     \else
179       \ifcase\c_page_scale_lines
180         % nothing to do: vz not enabled
181       \orelse\ifdim\d_page_box_stretch_delta>\zeropoint
182         \page_scale_text_box_register_box\b_page_one_contents
183         \page_scale_text_box\b_page_one_contents
184       \else
185         \page_scale_text_box_register_page
186         \page_scale_text_box\b_page_one_contents
187       \fi
188       \ht\b_page_one_contents\textheight
189       \wd\b_page_one_contents\d_page_col_column_width
190       \page_col_registered_text_area_b
191         {\box\b_page_one_contents}%
192     \fi
193   \egroup}
194
195%D \unknown
196
197\protected\def\page_col_command_side_float_output
198  {% % %
199   \ifzeropt\insertheight\namedinsertionnumber\s!topfloat\else
200     \scratchwidth\insertwidth\namedinsertionnumber\s!topfloat\relax
201     \ifdim\scratchwidth>\d_page_col_top_width
202       \global\d_page_col_top_width \scratchwidth
203     \fi
204     \global\d_page_col_top_height\insertheight\namedinsertionnumber\s!topfloat\relax
205   \fi
206   % % %
207   \setbox\scratchbox\vbox\bgroup
208      \page_col_command_package_contents_one\unvbox\normalpagebox
209   \egroup
210   \putboxincache\s!pagecolumn{\the\c_page_col_current}\scratchbox
211   \ifnum\c_page_col_current=\c_page_col_n_of_columns
212     \page_col_routine_package
213     \page_otr_construct_and_shipout\box\normalpagebox\plusone
214     \global\c_page_col_current\plusone
215     \global\d_page_col_top_height\zeropoint
216     \global\d_page_col_top_width\zeropoint
217   % \page_col_command_flush_top_insertions
218   % \page_col_command_flush_floats
219   \else
220     \ifdim\d_page_col_top_width>\zeropoint
221       \ifdim{\d_page_col_top_width>\d_page_col_sofar}%
222         \begingroup
223         \floatingpenalty\zerocount
224         \insert\namedinsertionnumber\s!topfloat\bgroup
225           \vbox to \d_page_col_top_height{\vss}%
226             % can be an option
227             \page_col_command_flush_top_insertions
228             \page_col_command_flush_floats
229             % so far till option
230           \egroup
231         \endgroup
232       \fi
233     \fi
234     \global\advanceby\c_page_col_current\plusone
235   \fi
236   %
237   \page_col_notes_synchronize
238   %
239   \page_col_command_set_vsize
240   \page_col_command_set_hsize}
241
242% use \currentmixedcolumns instead of \recurselevel
243
244\lettonothing\page_col_routine_balance
245
246\def\page_col_routine_package
247  {\page_col_routine_balance
248   \global\setbox\normalpagebox\hbox to \makeupwidth\bgroup
249     \edef\p_separator{\pagecolumnsparameter\c!separator}%
250     \pagecolumnseparatorwidth\d_page_col_distance
251     \ifcstok{\pagecolumnsparameter\c!direction}\v!reverse
252       \localcontrolledloop\c_page_col_n_of_columns\plusone\minusone
253         {\mofcolumns\currentloopiterator
254          \page_col_routine_package_step
255          \ifnum\mofcolumns>\plusone
256            \page_col_routine_package_separate
257          \fi}%
258     \else
259       \localcontrolledloop\plusone\c_page_col_n_of_columns\plusone
260         {\mofcolumns\currentloopiterator
261          \page_col_routine_package_step
262          \ifnum\mofcolumns<\c_page_col_n_of_columns
263            \page_col_routine_package_separate
264          \fi}%
265     \fi
266   \egroup
267   \resetboxesincache{\s!pagecolumn\s!pagecolumn}%
268   \resetboxesincache{\s!pagecolumn}%
269   \global\initialpageskip\zeroskip
270   \global\initialtopskip \zeroskip}
271
272
273\def\page_col_routine_package_step
274  {% needs packaging anyway
275    \getboxfromcache{\s!pagecolumn\s!pagecolumn}{\number\mofcolumns}\scratchboxone
276    \getboxfromcache{\s!pagecolumn}{\number\mofcolumns}\scratchboxtwo
277    \ht\scratchboxtwo{\ht\scratchboxtwo-\ht\scratchboxone}%
278    \page_lines_add_numbers_to_box\scratchbox\mofcolumns\c_page_col_n_of_columns\plusone % new
279    \page_marks_synchronize_column\plusone\c_page_col_n_of_columns\mofcolumns\scratchboxtwo
280    % backgrounds
281    \anch_mark_column_box\scratchboxtwo\mofcolumns
282    \pagecolumnseparatorheight\ht\scratchboxtwo
283    \pagecolumnseparatordepth \dp\scratchboxtwo
284    \vpack\bgroup
285      \box\scratchboxone
286      \nointerlineskip\par
287      \inheritedpagecolumnsframedbox\mofcolumns\scratchboxtwo
288   \egroup}
289
290%D \unknown
291
292\protected\def\page_col_command_check_if_float_fits
293  {\ifconditional\c_page_floats_not_permitted
294     % forget about it anyway
295     \global\c_page_floats_room\conditionalfalse
296   \else
297     % first we check the current column
298     \ifdim{\hsize-\naturalfloatwd}>-\onepoint
299       \global\c_page_floats_room\conditionaltrue
300     \else
301       \global\c_page_floats_room\conditionalfalse
302     \fi
303     \ifconditional\c_page_floats_room
304       % we fit in the column but do we have room
305       \ifdim{\pagetotal+\lineheight}>\pagegoal
306         % try again later
307         \goodbreak
308       \fi
309       \ifdim\pagetotal>\zeropoint
310         \scratchdimenone{\pagetotal+\floatheight+\d_strc_floats_top-\pageshrink}%
311         \scratchdimentwo\pagegoal
312         \relax % needed
313         \ifcase\c_page_one_float_method
314           % method 0 : raw
315         \or
316           % method 1 : safe
317           \advanceby\scratchdimentwo -\strutdp
318         \or
319           % method 2 : tight
320           \advanceby\scratchdimenone -\onepoint
321         \fi
322         \relax % really needed ! ! ! !
323         \ifdim\scratchdimenone>\scratchdimentwo
324           % there is no room, give up
325           \global\c_page_floats_room\conditionalfalse
326           % now we can decide on a top float
327%          \fi
328         \else
329%            \ifconditional\c_page_floats_room
330%              \global\setbox\floatbox\hpack to \d_page_col_float_available{\hss\box\floatbox\hss}%
331%            \fi
332         \fi
333       \fi
334     \fi
335   \fi}
336
337%D \unknown
338
339\def\page_col_set_float_pack_hsize
340  {\ifnum\c_page_col_current=\c_page_col_n_of_columns
341     \c_page_col_current\plusone
342   \else
343     \advanceby\c_page_col_current\plusone
344   \fi
345   \page_col_command_set_hsize
346   \hsize\d_page_col_available}
347
348\protected\def\page_col_command_flush_floats
349  {\global\c_page_floats_flushing\conditionaltrue
350   \ifconditional\c_page_floats_some_waiting
351     \par
352     \page_col_set_float_pack_hsize
353     \page_col_command_flush_floats_indeed
354   \fi
355   \global\savednoffloats\zerocount
356   \global\c_page_floats_some_waiting\conditionalfalse
357   \global\c_page_floats_flushing\conditionalfalse}
358
359\def\page_floats_show_pack_state_indeed#1%
360  {\llap{\smash{\backgroundline[black]{\strut\smallinfofont\white#1\space\the\nofcollectedfloats\space of\space\the\savednoffloats:\the\hsize}}\hkern.25\emwidth}}
361
362\installtextracker
363  {floats.collecting}
364  {\let\page_floats_show_pack_state\page_floats_show_pack_state_indeed}
365  {\let\page_floats_show_pack_state\gobbleoneargument}
366
367\let\page_floats_show_pack_state\gobbleoneargument
368
369\def\page_col_command_flush_floats_indeed % much in common with OTRSET
370  {\ifconditional\c_page_floats_some_waiting
371     \ifconditional\c_page_floats_compress_flushed
372       \c_page_floats_center_box\conditionalfalse % not needed as we do call directly
373       \page_floats_collect\s!text\hsize\d_page_floats_compress_distance
374       %
375       \ifnum\nofcollectedfloats=\plusone
376         \ifdim\naturalfloatwd>\hsize
377           \nofcollectedfloats\zerocount
378         \fi
379       \fi
380       \ifnum\nofcollectedfloats>\zerocount
381         \global\setbox\floatbox\hpack to \hsize
382           {\page_floats_show_pack_state F%
383            \hfil
384            \dorecurse\nofcollectedfloats
385              {\ifcase\columndirection % nog document wide
386                 \page_floats_flush\s!text\plusone
387               \else
388                 \page_floats_flush\s!text{\tointeger{\nofcollectedfloats-\recurselevel+1}}%
389               \fi
390               % this could happen at the lua end instead
391               \scratchdimen{\wd\floatbox-\naturalfloatwd}%
392               \ifdim\scratchdimen<\zeropoint
393                 \global\setbox\floatbox\hpack spread -\scratchdimen{\hss\box\floatbox\hss}%
394               \fi
395               %
396               \ifdim\wd\floatbox>\textwidth % \hsize
397                 \hpack to \textwidth{\hss\box\floatbox\hss}% \textwidth
398               \else
399                 \box\floatbox
400               \fi
401               \ifnum\recurselevel<\nofcollectedfloats
402                 \hfil
403               \fi}%
404            \hfil}%
405           \doplacefloatbox
406         % \page_one_insert_top_float
407           \doubleexpandafter\page_col_command_flush_floats_indeed
408       \else
409         % todo
410       \fi
411     \else
412       \page_floats_get
413     % \page_one_insert_top_float
414       \doplacefloatbox
415       \doubleexpandafter\page_col_command_flush_floats_indeed
416     \fi
417   \fi}
418
419\protected\def\page_col_command_flush_saved_floats % like one
420  {\global\d_page_floats_inserted_top\zeropoint
421   \global\d_page_floats_inserted_bottom\zeropoint
422   \ifconditional\c_page_floats_flushing \else
423     \page_col_command_set_top_insertions
424     \page_col_command_set_bottom_insertions
425     \ifconditional\c_page_floats_some_waiting
426        \ifcstok{\rootfloatparameter\c!cache}\v!no
427          \page_col_command_flush_floats % could be _otr_
428        \fi
429     \orelse\ifconditional\c_page_margin_blocks_present
430       \page_col_command_flush_floats
431     \fi
432   \fi}
433
434\protected\def\page_col_command_set_top_insertions
435  {\bgroup
436   \ifconditional\c_page_floats_some_waiting
437     \noffloatinserts\zerocount
438     \let\totaltopinserted\!!zeropoint
439     \page_col_set_float_pack_hsize
440     \page_col_command_set_top_insertions_indeed
441     \ifnum\rootfloatparameter\c!nbottom=\zerocount
442       \ifnum\rootfloatparameter\c!nlines>\zerocount
443         \ifdim\totaltopinserted>\zeropoint\relax
444           \ifdim{\rootfloatparameter\c!nlines\lineheight+\totaltopinserted}>\textheight
445             \showmessage\m!floatblocks8{\rootfloatparameter\c!nlines}%
446             \page_otr_fill_and_eject_page % was tripple: vfilll
447           \fi
448         \fi
449       \fi
450     \fi
451   \fi
452   \egroup}
453
454\permanent\def\d_page_col_collected_top_float_height % pseudo
455  {\dimexpr
456     \d_page_floats_inserted_top +
457     \maxcollectedfloatstotal +
458     \ifdim\d_strc_floats_top>\d_strc_floats_bottom
459       \d_strc_floats_top
460     \else
461       \d_strc_floats_bottom
462     \fi
463   \relax}
464
465\def\page_col_command_set_top_insertions_indeed
466  {\ifnum\noffloatinserts<\c_page_floats_n_of_top
467     \ifcase\savednoffloats
468       \let\page_col_command_set_top_insertions_indeed\relax
469     \else
470       \page_floats_collect\s!text\hsize\emwidth
471       \ifdim\d_page_col_collected_top_float_height<\textheight
472         \global\setbox\floatbox\hpack to \hsize
473           {\page_floats_show_pack_state T%
474            \hfil
475            \dorecurse\nofcollectedfloats
476              {\ifcase\columndirection % nog document wide
477                 \page_floats_flush\s!text\plusone
478               \else
479                 \page_floats_flush\s!text{\tointeger{\nofcollectedfloats-\recurselevel+1}}%
480               \fi
481               % this could happen at the lua end instead
482               \scratchdimen{\wd\floatbox-\naturalfloatwd}%
483               \ifdim\scratchdimen<\zeropoint
484                   \global\setbox\floatbox\hpack spread -\scratchdimen{\hss\box\floatbox\hss}%
485               \fi
486               %
487               \ifdim\wd\floatbox>\makeupwidth % \hsize
488                 \hpack to \makeupwidth{\hss\box\floatbox\hss}%
489               \else
490                 \box\floatbox
491               \fi
492               \ifnum\recurselevel<\nofcollectedfloats
493                 \hfil
494               \fi}%
495            \hfil}%
496         \page_one_prepare_top_float
497         \xdef\totaltopinserted{\the\d_page_floats_inserted_top}%
498         \page_one_insert_top_float
499         \ifconditional\c_page_floats_some_waiting
500           \advanceby\noffloatinserts \plusone
501         \else
502           \noffloatinserts\c_page_floats_n_of_top\relax
503         \fi
504         \page_floats_report_flushed
505      \else
506         \let\page_col_command_set_top_insertions_indeed\relax
507       \fi
508     \fi
509   \else
510     \ifconditional\c_page_floats_some_waiting
511       \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}%
512     \fi
513     \let\page_col_command_set_top_insertions_indeed\relax
514   \fi
515   \page_col_command_set_top_insertions_indeed}
516
517\let\page_col_command_flush_top_insertions   \page_one_command_flush_top_insertions
518\let\page_col_command_flush_bottom_insertions\page_one_command_flush_bottom_insertions
519
520\let\page_col_command_set_bottom_insertions  \page_one_command_set_bottom_insertions
521
522\let\page_col_command_flush_float_box        \page_one_command_flush_float_box
523\let\page_col_command_synchronize_side_floats\page_one_command_synchronize_side_floats
524\let\page_col_command_flush_side_floats      \page_one_command_flush_side_floats
525\let\page_col_command_flush_margin_blocks    \page_one_command_flush_margin_blocks
526\let\page_col_command_test_page              \page_one_command_test_page
527
528%D The separator code is more or less the same as mixed columns but we need
529%D to compensate for the top floats so we comment a bit for now.
530
531\newdimension\pagecolumnseparatorheight
532\newdimension\pagecolumnseparatordepth
533\newdimension\pagecolumnseparatorwidth
534
535% \installcorenamespace{pagecolumnsseparator}
536%
537% \protected\def\installpagecolumnseparator#1#2%
538%   {\setvalue{\??pagecolumnsseparator#1}{#2}}
539%
540% \installpagecolumnseparator\v!rule
541%   {\vrule
542%      \s!width \pagecolumnsparameter\c!rulethickness
543%      \s!height\pagecolumnseparatorheight
544%      \s!depth \pagecolumnseparatordepth
545%    \relax}
546%
547% \def\page_col_routine_package_separate
548%   {\ifcsname\??pagecolumnsseparator\p_separator\endcsname
549%      \page_col_command_inject_separator
550%    \else
551%      \hss
552%    \fi}
553%
554% \protected\def\page_col_command_inject_separator
555%   {\begingroup
556%    \setbox\scratchbox\hbox to \zeropoint \bgroup
557%      \hss
558%      \starttextproperties
559%      \usepagecolumnscolorparameter\c!rulecolor
560%      \begincsname\??pagecolumnsseparator\p_separator\endcsname % was \c!rule
561%      \stoptextproperties
562%      \hss
563%    \egroup
564%    \ht\scratchbox\zeropoint
565%    \dp\scratchbox\zeropoint
566%    \hss
567%    \box\scratchbox
568%    \hss
569%    \endgroup}
570
571\def\page_col_routine_package_separate
572  {\hss}
573
574%D \unknown
575
576\protected\def\page_col_command_routine
577  {\page_sides_output_routine}
578
579% % not:
580%
581% \protected\def\page_col_command_routine
582%   {\ifconditional\c_page_sides_short
583%      \page_sides_output_routine_yes_column
584%    \else
585%      \page_sides_output_routine_nop_column
586%    \fi}
587%
588% \let\page_sides_output_routine_nop_column\page_sides_output_routine
589%
590% \def\page_sides_output_routine_yes_column % this might become the main one too
591%   {\unvbox\normalpagebox % bah, and the discards?
592%   %\page_col_column
593%    \column % \page
594%    % why was this \global\holdinginserts\zerocount
595%    \global\c_page_sides_short\conditionalfalse}
596
597\let\page_col_command_flush_all_floats\relax
598
599%D \unknown
600
601\defineoutputroutine
602  [\s!pagecolumn]
603  [\s!page_otr_command_routine                =\page_col_command_routine,
604   \s!page_otr_command_package_contents       =\page_col_command_package_contents,
605   \s!page_otr_command_set_vsize              =\page_col_command_set_vsize,
606   \s!page_otr_command_set_hsize              =\page_col_command_set_hsize,
607 % \s!page_otr_command_synchronize_hsize      =\page_col_command_synchronize_hsize, % not done
608   \s!page_otr_command_next_page              =\page_col_command_next_page,
609   \s!page_otr_command_next_page_and_inserts  =\page_col_command_next_page_and_inserts,
610   \s!page_otr_command_set_top_insertions     =\page_col_command_set_top_insertions,
611   \s!page_otr_command_set_bottom_insertions  =\page_col_command_set_bottom_insertions,
612   \s!page_otr_command_flush_top_insertions   =\page_col_command_flush_top_insertions,
613   \s!page_otr_command_flush_bottom_insertions=\page_col_command_flush_bottom_insertions,
614   \s!page_otr_command_check_if_float_fits    =\page_col_command_check_if_float_fits,
615 % \s!page_otr_command_set_float_hsize        =\page_col_command_set_float_hsize,   % not done
616   \s!page_otr_command_flush_float_box        =\page_col_command_flush_float_box,
617   \s!page_otr_command_side_float_output      =\page_col_command_side_float_output,
618   \s!page_otr_command_synchronize_side_floats=\page_col_command_synchronize_side_floats,
619   \s!page_otr_command_flush_floats           =\page_col_command_flush_floats,
620   \s!page_otr_command_flush_side_floats      =\page_col_command_flush_side_floats,
621   \s!page_otr_command_flush_saved_floats     =\page_col_command_flush_saved_floats,
622   \s!page_otr_command_flush_all_floats       =\page_col_command_flush_all_floats,
623   \s!page_otr_command_flush_margin_blocks    =\page_col_command_flush_margin_blocks,
624   \s!page_otr_command_test_column            =\page_col_command_test_page
625  ]
626
627%D \unknown
628
629\installfloatmethod \s!pagecolumn \v!here        \page_one_place_float_here
630\installfloatmethod \s!pagecolumn \v!force       \page_one_place_float_force
631\installfloatmethod \s!pagecolumn \v!left        \page_one_place_float_left
632\installfloatmethod \s!pagecolumn \v!right       \page_one_place_float_right
633\installfloatmethod \s!pagecolumn \v!text        \page_one_place_float_text
634\installfloatmethod \s!pagecolumn \v!top         \page_one_place_float_top
635\installfloatmethod \s!pagecolumn \v!bottom      \page_one_place_float_bottom
636\installfloatmethod \s!pagecolumn \v!auto        \page_one_place_float_auto
637\installfloatmethod \s!pagecolumn \v!margin      \page_one_place_float_margin
638\installfloatmethod \s!pagecolumn \v!opposite    \page_one_place_float_face
639\installfloatmethod \s!pagecolumn \v!page        \page_one_place_float_page
640\installfloatmethod \s!pagecolumn \v!leftpage    \page_one_place_float_leftpage
641\installfloatmethod \s!pagecolumn \v!rightpage   \page_one_place_float_rightpage
642\installfloatmethod \s!pagecolumn \v!inmargin    \page_one_place_float_inmargin
643\installfloatmethod \s!pagecolumn \v!inleft      \page_one_place_float_leftmargin
644\installfloatmethod \s!pagecolumn \v!inright     \page_one_place_float_rightmargin
645\installfloatmethod \s!pagecolumn \v!leftmargin  \page_one_place_float_leftmargin
646\installfloatmethod \s!pagecolumn \v!rightmargin \page_one_place_float_rightmargin
647\installfloatmethod \s!pagecolumn \v!leftedge    \page_one_place_float_leftedge
648\installfloatmethod \s!pagecolumn \v!rightedge   \page_one_place_float_rightedge
649\installfloatmethod \s!pagecolumn \v!somewhere   \page_one_place_float_somewhere
650\installfloatmethod \s!pagecolumn \v!backspace   \page_one_place_float_backspace
651\installfloatmethod \s!pagecolumn \v!cutspace    \page_one_place_float_cutspace
652%installfloatmethod \s!pagecolumn \s!tblr        \page_one_place_float_top
653%installfloatmethod \s!pagecolumn \s!lrtb        \page_one_place_float_top
654%installfloatmethod \s!pagecolumn \s!tbrl        \page_one_place_float_top
655%installfloatmethod \s!pagecolumn \s!fxtb        \page_one_place_float_top
656%installfloatmethod \s!pagecolumn \s!rltb        \page_one_place_float_top
657%installfloatmethod \s!pagecolumn \s!btlr        \page_one_place_float_bottom
658%installfloatmethod \s!pagecolumn \s!lrbt        \page_one_place_float_bottom
659%installfloatmethod \s!pagecolumn \s!btrl        \page_one_place_float_bottom
660%installfloatmethod \s!pagecolumn \s!rlbt        \page_one_place_float_bottom
661%installfloatmethod \s!pagecolumn \s!fxbt        \page_one_place_float_bottom
662%installfloatmethod \s!pagecolumn \s!fixd        \page_one_place_float_force
663
664\installfloatmethod \s!pagecolumn \v!local       \somelocalfloat
665
666%D The main interface:
667
668\installcorenamespace{pagecolumns}
669
670\installframedcommandhandler \??pagecolumns {pagecolumns} \??pagecolumns
671
672\setuppagecolumns
673  [\c!distance=1.5\bodyfontsize,
674   \c!n=\plustwo,
675   \c!page=\v!yes,
676  %\c!align=, % inherit (also replaces tolerance)
677  %\c!before=,
678  %\c!after=,
679  %\c!separator=\v!none,
680  %\c!setups=,
681  %\c!balance=\v!no,
682  %\c!blank={\v!line,\v!fixed}, yes or no
683   \c!frame=\v!off,
684   \c!strut=\v!no,
685   \c!offset=\v!overlay,
686  %\c!maxheight=\textheight,
687   \c!maxwidth=\makeupwidth,
688  %\c!grid=\v!tolerant,
689  %\c!internalgrid=\v!line,
690   \c!direction=\v!normal]
691
692\appendtoks % could become an option
693    \frozen\instance\protected\edefcsname\e!start\currentpagecolumns\endcsname{\startpagecolumns[\currentpagecolumns]}%
694    \frozen\instance\protected\edefcsname\e!stop \currentpagecolumns\endcsname{\stoppagecolumns}%
695\to \everydefinepagecolumns
696
697\def\page_col_pickup_preceding
698  {\begingroup
699   \setupoutputroutine[\s!mixedcolumn]%
700   \c_page_mix_routine\c_page_mix_routine_intercept
701   \page_otr_trigger_output_routine
702   \ifvoid\b_page_mix_preceding \else
703     % moved here, before the packaging
704     \page_postprocessors_linenumbers_deepbox\b_page_mix_preceding
705     % we need to avoid unvboxing with successive balanced on one page
706     \global\setbox\b_page_mix_preceding\vbox\bgroup
707       % yes or no: \forcestrutdepth
708       \unvbox\b_page_mix_preceding
709       \forcestrutdepth
710     \egroup
711     \wd\b_page_mix_preceding\makeupwidth
712     \global\d_page_mix_preceding_height\ht\b_page_mix_preceding
713   \fi
714   \endgroup}
715
716% Keep this one as original:
717%
718% \def\page_col_flush_preceding
719%   {\ifvoid\b_page_mix_preceding \else
720%      % this is just one method but ok for now
721%      \begingroup
722%      % we might need more but for now this is ok
723%      \setupfloat[\c!spacebefore=,\c!spaceafter=]%
724%      \startplacefigure[\c!location={\v!top,\v!none}]%
725%        \box\b_page_mix_preceding
726%      \stopplacefigure
727%      \endgroup
728%    \fi}
729
730\def\page_col_flush_preceding
731  {\ifvoid\b_page_mix_preceding \else
732     \scratchwidth \emwidth
733     \scratchheight\ht\b_page_mix_preceding
734     \scratchdepth \dp\b_page_mix_preceding
735     \global\initialpageskip\htdp\b_page_mix_preceding
736     \global\initialtopskip \strutht
737     % for the moment
738     \setbox\scratchbox\vbox\bgroup
739        \pagediscards
740     \egroup
741     \global\advanceby\initialtopskip \ht\scratchbox
742     % till here
743     \setbox\scratchbox\hbox to \zeropoint
744       \bgroup
745         \box\b_page_mix_preceding
746       \egroup
747     \putboxincache{\s!pagecolumn\s!pagecolumn}{\number\plusone}\scratchbox
748     \dostepwiserecurse\plustwo\c_page_col_n_of_columns\plusone
749       {\setbox\scratchbox\hbox to \zeropoint
750          \bgroup
751            \novrule
752              \s!width \scratchwidth
753              \s!height\scratchheight
754              \s!depth \scratchdepth
755            \hss
756          \egroup
757        \putboxincache{\s!pagecolumn\s!pagecolumn}{\recurselevel}\scratchbox}%
758   \fi}
759
760% \let\page_col_notes_initialize \relax
761% \let\page_col_notes_synchronize\relax
762% \let\page_col_notes_reset      \relax
763%
764% \protected\def\page_col_command_set_vsize % \page_one_command_set_vsize minus the pagegoal setting
765%   {\ifgridsnapping
766%      \ifcase\layoutlines
767%        \getrawnoflines\textheight
768%      \else
769%        \noflines\layoutlines
770%      \fi
771%      \global\vsize\noflines\openlineheight
772%    \else
773%      \global\vsize\textheight
774%    \fi}
775
776\newconditional\c_page_col_notes_lastcolumn
777
778\def\page_col_notes_synchronize
779  {\insertstoring\zerocount
780   \ifnum\c_page_col_current=\c_page_col_n_of_columns\relax
781     \strc_notes_process\page_col_notes_inject
782     \ifconditional\c_page_col_notes_lastcolumn
783       \insertstoring\plusone
784     \fi
785   \else
786     \strc_notes_process\page_col_notes_delay
787     \ifconditional\c_page_col_notes_lastcolumn
788       \insertstoring\plustwo
789     \fi
790   \fi}
791
792\def\page_col_notes_delay {\c_page_col_notes_lastcolumn\conditionalfalse\ifcstok{\noteparameter\c!location}\v!lastcolumn\c_page_col_notes_lastcolumn\conditionaltrue\insertstorage\currentnoteinsertionnumber\plusone  \fi}
793\def\page_col_notes_inject{\c_page_col_notes_lastcolumn\conditionalfalse\ifcstok{\noteparameter\c!location}\v!lastcolumn\c_page_col_notes_lastcolumn\conditionaltrue\insertstorage\currentnoteinsertionnumber\zerocount\fi}
794
795\def\page_col_notes_initialize {\insertstoring\zerocount\strc_notes_process\page_col_notes_delay}
796\def\page_col_notes_reset      {\insertstoring\zerocount\strc_notes_process\page_col_notes_inject}
797
798\protected\def\page_col_command_set_vsize % different !
799  {\page_one_command_set_vsize}
800
801\permanent\tolerant\protected\def\startpagecolumns[#S#1]%
802  {\begingroup
803   \begingroup
804   \ifhastok={#1}%
805     \lettonothing\currentpagecolumns
806     \setuppagecolumns[#1]%
807   \else
808     \cdef\currentpagecolumns{#1}%
809   \fi
810   \edef\p_page{\pagecolumnsparameter\c!page}%
811   \ifempty\p_page
812     \c_page_col_page\conditionalfalse
813   \orelse\ifx\p_page\v!no
814     \c_page_col_page\conditionalfalse
815   \else
816     \c_page_col_page\conditionaltrue
817     \page[\p_page]%
818   \fi
819   \c_page_col_n_of_columns\pagecolumnsparameter\c!n\relax
820   \ifnum\c_page_col_n_of_columns>\plusone
821     \expandafter\page_col_start_yes
822   \else
823     \expandafter\page_col_start_nop
824   \fi} % public
825
826\aliased\let\stoppagecolumns\relax
827
828\protected\def\page_col_start_yes
829  {\d_page_col_distance     {\pagecolumnsparameter\c!distance}%
830 % \d_page_col_max_height   {\pagecolumnsparameter\c!maxheight}%
831   \d_page_col_max_width    {\pagecolumnsparameter\c!maxwidth}%
832 % \d_page_col_balance_step {\pagecolumnsparameter\c!step}%
833   \c_page_col_current  \plusone
834   %
835   \d_page_col_column_width{(\d_page_col_max_width-\d_page_col_distance*\numexpr\c_page_col_n_of_columns-\plusone\relax)/\c_page_col_n_of_columns}%
836   %
837   \columnwidth    \d_page_col_column_width
838   \columndistance \d_page_col_distance
839   \nofcolumns     \c_page_col_n_of_columns
840   \textwidth      \columnwidth % kind of redundant
841   %
842   \nopenalties
843   %
844   \global\initialpageskip\zeroskip
845   \global\initialtopskip \zeroskip
846   %
847   % \insidecolumnstrue % NO!
848   %
849   \enforced\let\column\page_col_column
850   %
851   \def\page_floats_get_used_hsize{\makeupwidth} % a bit of a hack
852   %
853   \usealignparameter  \pagecolumnsparameter
854   \useblankparameter  \pagecolumnsparameter
855 % \useprofileparameter\pagecolumnsparameter
856   %
857   \usepagecolumnscolorparameter\c!color
858   %
859   \setupnotes[\c!width=\textwidth]%
860   %
861   \usesetupsparameter\pagecolumnsparameter
862   %
863   % This will become a method but for now it's good enough
864   %
865   \ifconditional\c_page_col_page\else
866     \page_col_pickup_preceding
867   \fi
868   \setupoutputroutine[\s!pagecolumn]%
869   \ifconditional\c_page_col_page\else
870     \page_col_flush_preceding
871   \fi
872   %
873   \setupfloats[\c!ntop=\plusthousand]%
874 % \setupfloats[\c!nbottom=\plusthousand]%
875   %
876   \page_col_notes_initialize
877   %
878   \page_col_command_set_vsize
879   \page_col_command_set_hsize
880   %
881   \enforced\permanent\protected\def\startpagecolumns[##1]{\page_col_start_nop}%
882   %
883   \enforced\let\stoppagecolumns\page_col_stop_yes}
884
885\protected\def\page_col_start_nop
886  {\nofcolumns\c_page_mix_n_of_columns
887   \enforced\let\stoppagecolumns\page_col_stop_nop}
888
889\lettonothing\page_col_routine_balance_check
890
891\protected\def\page_col_stop_yes
892  {%\column % \page_otr_eject_page
893   \page_col_routine_balance_check
894   \page    % beware for empty pages
895   \endgroup
896 % \setupoutputroutine[\s!singlecolumn]%
897   \global\initialpageskip\zeroskip
898   \global\initialtopskip \zeroskip
899   \page_otr_command_set_vsize
900   \page_otr_command_set_hsize
901   \page
902   \page_col_notes_reset
903   \endgroup}
904
905\protected\def\page_col_stop_nop
906  {\page
907   \endgroup
908   \endgroup}
909
910% This is only for me, experimental and subject to changes! The problem is that we're already
911% wrapped so e.g. when we use vz we are toast.
912
913% \def\page_col_routine_balance_check
914%   {\ifcstok{\pagecolumnsparameter\c!balance}\v!yes
915%      \let\page_col_routine_balance\page_col_routine_balance_indeed
916%    \fi}
917%
918% \def\page_col_routine_balance_indeed
919%   {\ifnum\nofcolumns=\plustwo
920%      \setbox\scratchbox\vbox\bgroup
921%         \directboxfromcache{\s!pagecolumn}{1}
922%         \setbox\scratchbox\lastbox\unvbox\scratchbox
923%         \setbox\scratchbox\lastbox\unvbox\scratchbox
924%         \directboxfromcache{\s!pagecolumn}{2}
925%         \setbox\scratchbox\lastbox\unvbox\scratchbox
926%         \setbox\scratchbox\lastbox\unvbox\scratchbox
927%      \egroup
928%      % holdinginserts
929%      \scratchdimen.5\htdp\scratchbox
930%      \splittopskip\topskip
931%      \localcontrolledendless {%
932%        \setbox\scratchboxtwo\copy\scratchbox
933%        \setbox\scratchboxone\vsplit\scratchboxtwo to \scratchdimen
934%        \ifdim\ht\scratchboxone<\ht\scratchboxtwo
935%          \quitloop
936%        \orelse\ifvoid\scratchboxtwo
937%          \quitloop
938%        \orelse\ifdim\scratchdimen>\textheight
939%          \quitloop
940%        \else
941%          \advanceby\scratchdimen\onepoint
942%        \fi
943%      }%
944%      \setbox\scratchboxone\vtop to \scratchdimen{\unvbox\scratchboxone}%
945%      \setbox\scratchboxtwo\vtop to \scratchdimen{\unvbox\scratchboxtwo}%
946%      \putboxincache{\s!pagecolumn}{1}\scratchboxone
947%      \putboxincache{\s!pagecolumn}{2}\scratchboxtwo
948%    \fi}
949
950% \def\page_col_routine_balance_indeed
951%   {\ifnum\nofcolumns=\plustwo
952%      \setbox\scratchbox\vbox\bgroup
953%         \directboxfromcache{\s!pagecolumn}{1}
954%         \setbox\scratchbox\lastbox\ifvbox\scratchbox\unvbox\scratchbox\fi
955%         \setbox\scratchbox\lastbox\ifvbox\scratchbox\unvbox\scratchbox\fi
956%         \doifelseboxincache{\s!pagecolumn}{2}
957%           {\directboxfromcache{\s!pagecolumn}{2}
958%            \setbox\scratchbox\lastbox\ifvbox\scratchbox\unvbox\scratchbox\fi
959%            \setbox\scratchbox\lastbox\ifvbox\scratchbox\unvbox\scratchbox\fi
960%           }%
961%           {}%
962%      \egroup
963%      % holdinginserts
964%      \scratchdimen.5\htdp\scratchbox
965%      \splittopskip\topskip
966%      \localcontrolledendless {%
967%        \setbox\scratchboxtwo\copy\scratchbox
968%        \setbox\scratchboxone\vsplit\scratchboxtwo upto \scratchdimen
969% % \writestatus{page columns}{  \the\ht\scratchboxone,\the\ht\scratchboxtwo}%
970%        \ifdim\ht\scratchboxone<\ht\scratchboxtwo
971%          \quitloop
972%        \orelse\ifvoid\scratchboxtwo
973%          \quitloop
974%        \orelse\ifdim\scratchdimen>\textheight
975%          \quitloop
976%        \else
977%          \advanceby\scratchdimen\onepoint
978%        \fi
979%      }%
980% %      \ifdim\ht\scratchboxone<\ht\scratchboxtwo
981% %        \scratchdimen\ht\scratchboxone
982% %        \advanceby\scratchdimen\onepoint
983% %        \localcontrolledendless {%
984% %          \setbox\scratchboxtwo\copy\scratchbox
985% %          \setbox\scratchboxone\vsplit\scratchboxtwo upto \scratchdimen
986% % \writestatus{page columns}{  \the\ht\scratchboxone,\the\ht\scratchboxtwo}%
987% %          \ifdim\ht\scratchboxone>\ht\scratchboxtwo
988% %            \quitloop
989% %          \orelse\ifdim\ht\scratchboxone=\ht\scratchboxtwo
990% %            \quitloop
991% %          \orelse\ifvoid\scratchboxtwo
992% %            \quitloop
993% %          \orelse\ifdim\scratchdimen>\textheight
994% %            \quitloop
995% %          \else
996% %            \advanceby\scratchdimen\onepoint
997% %          \fi
998% %        }%
999% %      \fi
1000%      \setbox\scratchboxone\vtop to \scratchdimen{\unvbox\scratchboxone}%
1001%      \setbox\scratchboxtwo\vtop to \scratchdimen{\unvbox\scratchboxtwo}%
1002%      \putboxincache{\s!pagecolumn}{1}\scratchboxone
1003%      \putboxincache{\s!pagecolumn}{2}\scratchboxtwo
1004%    \fi}
1005
1006\protect \endinput
1007