%D \module %D [ file=page-pcl, %D version=2017.11.08, %D title=\CONTEXT\ Page Macros, %D subtitle=Page Columns, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Page Macros / Page Columns} %D This is very experimental code! We took a bit from the mixed columns and single %D column page code. This one works acceptable with floats and is for whole double %D column documents. We don't balance (yet). Footnotes are per column. One can have %D side floats too. No balancing and other fancy features. %D %D Don't use this in production! Although the main approach will stay there might be %D changes in the way floats are dealt with. Not much testing has been done but as %D we stay close to the single column mode we expect most to just work. Only floats %D are the (usual) pain. Backgrounds, line numbering, etc.\ not tested either. \unprotect \definemeasure[onecolumn] [\columnwidth] \definemeasure[twocolumns] [\dimexpr\plustwo \columnwidth+ \columndistance\relax] \definemeasure[threecolumns][\dimexpr\plusthree\columnwidth+\plustwo \columndistance\relax] \definemeasure[fourcolumns] [\dimexpr\plusfour \columnwidth+\plusthree\columndistance\relax] \newinteger \c_page_col_n_of_columns \c_page_col_n_of_columns\plusone \newinteger \c_page_col_current \c_page_col_current \plusone \newdimension \d_page_col_distance \newdimension \d_page_col_max_height \newdimension \d_page_col_max_width %newdimension \d_page_col_balance_step \newdimension \d_page_col_column_width \newdimension \d_page_col_top_height \newdimension \d_page_col_top_width \newdimension \d_page_col_available \newdimension \d_page_col_sofar \newconditional\c_page_col_page %D We need to step over empty columns. \protected\def\page_col_command_next_page {\page_col_eject_page} \permanent\protected\def\page_col_column {\page_otr_eject_page} \protected\def\page_col_eject_page {\begingroup \scratchcountertwo \realpageno \page_otr_eject_page \scratchcounterone \c_page_col_current \scratchcounterthree\zerocount \doloop{% \ifnum\scratchcounterthree>\plushundred % too many attempts \exitloop \orelse\ifnum\realpageno>\scratchcountertwo % we advanced at least one page so we're done \exitloop \else \ifnum\scratchcounterone=\c_page_col_current \dontleavehmode\null \fi \page_otr_eject_page \scratchcounterone\c_page_col_current \advanceby\scratchcounterthree\plusone \fi }% \endgroup} %D \unknown \protected\def\page_col_command_next_page_and_inserts {\page_otr_eject_page_and_flush_inserts} %D \unknown \protected\def\page_col_command_set_hsize {\global\hsize\d_page_col_column_width\relax \global\d_page_col_available{% \numexpr\c_page_col_n_of_columns-\c_page_col_current+\plusone\relax\d_page_col_column_width + \numexpr\c_page_col_n_of_columns-\c_page_col_current \relax\d_page_col_distance }% \global\d_page_col_sofar \ifnum\c_page_col_n_of_columns=\plusone \zeropoint \else \numexpr\c_page_col_n_of_columns-\plusone\relax \dimexpr\d_page_col_column_width+\d_page_col_distance\relax \fi % consistent with mixed: \textwidth\d_page_col_column_width} %D \unknown \def\page_col_registered_text_area_b#1% {\begingroup \makeupwidth\d_page_col_column_width \page_one_registered_text_area_b{#1}% \endgroup} \protected\def\page_col_command_package_contents#1#2% \box \unvbox % this one will be redone (checked) {\bgroup \setbox\b_page_one_contents\vbox to \textheight {\page_one_registered_text_area_a#1#2}% \page_one_command_package_show_state \ht\b_page_one_contents\textheight \page_col_registered_text_area_b {\box\b_page_one_contents}% \egroup} \protected\def\page_col_command_package_contents_one#1#2% \box \unvbox % this one will be redone (checked) {\bgroup \forgetall % see one for comments as it is similar \strc_notes_check_if_bottom_present \d_page_one_natural_depth\dp#2\relax % \page_layouts_check_stretch#2% \setbox\b_page_one_contents\vbox to \textheight {\page_col_command_flush_top_insertions \page_one_registered_text_area_a#1#2% \hsize\d_page_col_column_width \ifgridsnapping \vskip{\openstrutdepth-\d_page_one_natural_depth}% \prevdepth\openstrutdepth \page_col_command_flush_bottom_insertions \vfil \orelse\ifcase\bottomraggednessmode % ragged (default) \vskip{\openstrutdepth-\d_page_one_natural_depth}% \prevdepth\openstrutdepth \page_col_command_flush_bottom_insertions \vfil \or % align (normal) \page_col_command_flush_bottom_insertions \or % baseline \vkern{\maxdepth-\d_page_one_natural_depth}% \page_col_command_flush_bottom_insertions \or % depth \vskip-\d_page_one_natural_depth \page_col_command_flush_bottom_insertions \fi \fakepagenotes}% \page_layouts_check_stretch\b_page_one_contents \page_one_command_package_show_state \ifconditional\c_notes_bottom_present \ifgridsnapping \ifcase\layoutlines \getrawnoflines\textheight \else \noflines\layoutlines \fi \scratchoffset{\numexpr\noflines-\plusone\relax\lineheight+\topskip}% \else \scratchoffset\ht\b_page_one_contents \fi \setbox\b_page_one_bottom_notes\hpack {\hsize\d_page_col_column_width \setupnotes[\c!width=\textwidth]% \lower{\scratchoffset-\initialpageskip}\vbox{\placebottomnotes\par\kern\zeropoint}}% \ht\b_page_one_contents \zeropoint \wd\b_page_one_contents \zeropoint \ht\b_page_one_bottom_notes\zeropoint \wd\b_page_one_bottom_notes\d_page_col_column_width \page_col_registered_text_area_b {\vpack to \textheight {\hpack{\box\b_page_one_contents\box\b_page_one_bottom_notes}}}% \else \ifcase\c_page_scale_lines % nothing to do: vz not enabled \orelse\ifdim\d_page_box_stretch_delta>\zeropoint \page_scale_text_box_register_box\b_page_one_contents \page_scale_text_box\b_page_one_contents \else \page_scale_text_box_register_page \page_scale_text_box\b_page_one_contents \fi \ht\b_page_one_contents\textheight \wd\b_page_one_contents\d_page_col_column_width \page_col_registered_text_area_b {\box\b_page_one_contents}% \fi \egroup} %D \unknown \protected\def\page_col_command_side_float_output {% % % \ifzeropt\insertheight\namedinsertionnumber\s!topfloat\else \scratchwidth\insertwidth\namedinsertionnumber\s!topfloat\relax \ifdim\scratchwidth>\d_page_col_top_width \global\d_page_col_top_width \scratchwidth \fi \global\d_page_col_top_height\insertheight\namedinsertionnumber\s!topfloat\relax \fi % % % \setbox\scratchbox\vbox\bgroup \page_col_command_package_contents_one\unvbox\normalpagebox \egroup \putboxincache\s!pagecolumn{\the\c_page_col_current}\scratchbox \ifnum\c_page_col_current=\c_page_col_n_of_columns \page_col_routine_package \page_otr_construct_and_shipout\box\normalpagebox\plusone \global\c_page_col_current\plusone \global\d_page_col_top_height\zeropoint \global\d_page_col_top_width\zeropoint % \page_col_command_flush_top_insertions % \page_col_command_flush_floats \else \ifdim\d_page_col_top_width>\zeropoint \ifdim{\d_page_col_top_width>\d_page_col_sofar}% \begingroup \floatingpenalty\zerocount \insert\namedinsertionnumber\s!topfloat\bgroup \vbox to \d_page_col_top_height{\vss}% % can be an option \page_col_command_flush_top_insertions \page_col_command_flush_floats % so far till option \egroup \endgroup \fi \fi \global\advanceby\c_page_col_current\plusone \fi % \page_col_notes_synchronize % \page_col_command_set_vsize \page_col_command_set_hsize} % use \currentmixedcolumns instead of \recurselevel \lettonothing\page_col_routine_balance \def\page_col_routine_package {\page_col_routine_balance \global\setbox\normalpagebox\hbox to \makeupwidth\bgroup \edef\p_separator{\pagecolumnsparameter\c!separator}% \pagecolumnseparatorwidth\d_page_col_distance \ifcstok{\pagecolumnsparameter\c!direction}\v!reverse \localcontrolledloop\c_page_col_n_of_columns\plusone\minusone {\mofcolumns\currentloopiterator \page_col_routine_package_step \ifnum\mofcolumns>\plusone \page_col_routine_package_separate \fi}% \else \localcontrolledloop\plusone\c_page_col_n_of_columns\plusone {\mofcolumns\currentloopiterator \page_col_routine_package_step \ifnum\mofcolumns<\c_page_col_n_of_columns \page_col_routine_package_separate \fi}% \fi \egroup \resetboxesincache{\s!pagecolumn\s!pagecolumn}% \resetboxesincache{\s!pagecolumn}% \global\initialpageskip\zeroskip \global\initialtopskip \zeroskip} \def\page_col_routine_package_step {% needs packaging anyway \getboxfromcache{\s!pagecolumn\s!pagecolumn}{\number\mofcolumns}\scratchboxone \getboxfromcache{\s!pagecolumn}{\number\mofcolumns}\scratchboxtwo \ht\scratchboxtwo{\ht\scratchboxtwo-\ht\scratchboxone}% \page_lines_add_numbers_to_box\scratchbox\mofcolumns\c_page_col_n_of_columns\plusone % new \page_marks_synchronize_column\plusone\c_page_col_n_of_columns\mofcolumns\scratchboxtwo % backgrounds \anch_mark_column_box\scratchboxtwo\mofcolumns \pagecolumnseparatorheight\ht\scratchboxtwo \pagecolumnseparatordepth \dp\scratchboxtwo \vpack\bgroup \box\scratchboxone \nointerlineskip\par \inheritedpagecolumnsframedbox\mofcolumns\scratchboxtwo \egroup} %D \unknown \protected\def\page_col_command_check_if_float_fits {\ifconditional\c_page_floats_not_permitted % forget about it anyway \global\c_page_floats_room\conditionalfalse \else % first we check the current column \ifdim{\hsize-\naturalfloatwd}>-\onepoint \global\c_page_floats_room\conditionaltrue \else \global\c_page_floats_room\conditionalfalse \fi \ifconditional\c_page_floats_room % we fit in the column but do we have room \ifdim{\pagetotal+\lineheight}>\pagegoal % try again later \goodbreak \fi \ifdim\pagetotal>\zeropoint \scratchdimenone{\pagetotal+\floatheight+\d_strc_floats_top-\pageshrink}% \scratchdimentwo\pagegoal \relax % needed \ifcase\c_page_one_float_method % method 0 : raw \or % method 1 : safe \advanceby\scratchdimentwo -\strutdp \or % method 2 : tight \advanceby\scratchdimenone -\onepoint \fi \relax % really needed ! ! ! ! \ifdim\scratchdimenone>\scratchdimentwo % there is no room, give up \global\c_page_floats_room\conditionalfalse % now we can decide on a top float % \fi \else % \ifconditional\c_page_floats_room % \global\setbox\floatbox\hpack to \d_page_col_float_available{\hss\box\floatbox\hss}% % \fi \fi \fi \fi \fi} %D \unknown \def\page_col_set_float_pack_hsize {\ifnum\c_page_col_current=\c_page_col_n_of_columns \c_page_col_current\plusone \else \advanceby\c_page_col_current\plusone \fi \page_col_command_set_hsize \hsize\d_page_col_available} \protected\def\page_col_command_flush_floats {\global\c_page_floats_flushing\conditionaltrue \ifconditional\c_page_floats_some_waiting \par \page_col_set_float_pack_hsize \page_col_command_flush_floats_indeed \fi \global\savednoffloats\zerocount \global\c_page_floats_some_waiting\conditionalfalse \global\c_page_floats_flushing\conditionalfalse} \def\page_floats_show_pack_state_indeed#1% {\llap{\smash{\backgroundline[black]{\strut\smallinfofont\white#1\space\the\nofcollectedfloats\space of\space\the\savednoffloats:\the\hsize}}\hkern.25\emwidth}} \installtextracker {floats.collecting} {\let\page_floats_show_pack_state\page_floats_show_pack_state_indeed} {\let\page_floats_show_pack_state\gobbleoneargument} \let\page_floats_show_pack_state\gobbleoneargument \def\page_col_command_flush_floats_indeed % much in common with OTRSET {\ifconditional\c_page_floats_some_waiting \ifconditional\c_page_floats_compress_flushed \c_page_floats_center_box\conditionalfalse % not needed as we do call directly \page_floats_collect\s!text\hsize\d_page_floats_compress_distance % \ifnum\nofcollectedfloats=\plusone \ifdim\naturalfloatwd>\hsize \nofcollectedfloats\zerocount \fi \fi \ifnum\nofcollectedfloats>\zerocount \global\setbox\floatbox\hpack to \hsize {\page_floats_show_pack_state F% \hfil \dorecurse\nofcollectedfloats {\ifcase\columndirection % nog document wide \page_floats_flush\s!text\plusone \else \page_floats_flush\s!text{\tointeger{\nofcollectedfloats-\recurselevel+1}}% \fi % this could happen at the lua end instead \scratchdimen{\wd\floatbox-\naturalfloatwd}% \ifdim\scratchdimen<\zeropoint \global\setbox\floatbox\hpack spread -\scratchdimen{\hss\box\floatbox\hss}% \fi % \ifdim\wd\floatbox>\textwidth % \hsize \hpack to \textwidth{\hss\box\floatbox\hss}% \textwidth \else \box\floatbox \fi \ifnum\recurselevel<\nofcollectedfloats \hfil \fi}% \hfil}% \doplacefloatbox % \page_one_insert_top_float \doubleexpandafter\page_col_command_flush_floats_indeed \else % todo \fi \else \page_floats_get % \page_one_insert_top_float \doplacefloatbox \doubleexpandafter\page_col_command_flush_floats_indeed \fi \fi} \protected\def\page_col_command_flush_saved_floats % like one {\global\d_page_floats_inserted_top\zeropoint \global\d_page_floats_inserted_bottom\zeropoint \ifconditional\c_page_floats_flushing \else \page_col_command_set_top_insertions \page_col_command_set_bottom_insertions \ifconditional\c_page_floats_some_waiting \ifcstok{\rootfloatparameter\c!cache}\v!no \page_col_command_flush_floats % could be _otr_ \fi \orelse\ifconditional\c_page_margin_blocks_present \page_col_command_flush_floats \fi \fi} \protected\def\page_col_command_set_top_insertions {\bgroup \ifconditional\c_page_floats_some_waiting \noffloatinserts\zerocount \let\totaltopinserted\!!zeropoint \page_col_set_float_pack_hsize \page_col_command_set_top_insertions_indeed \ifnum\rootfloatparameter\c!nbottom=\zerocount \ifnum\rootfloatparameter\c!nlines>\zerocount \ifdim\totaltopinserted>\zeropoint\relax \ifdim{\rootfloatparameter\c!nlines\lineheight+\totaltopinserted}>\textheight \showmessage\m!floatblocks8{\rootfloatparameter\c!nlines}% \page_otr_fill_and_eject_page % was tripple: vfilll \fi \fi \fi \fi \fi \egroup} \permanent\def\d_page_col_collected_top_float_height % pseudo {\dimexpr \d_page_floats_inserted_top + \maxcollectedfloatstotal + \ifdim\d_strc_floats_top>\d_strc_floats_bottom \d_strc_floats_top \else \d_strc_floats_bottom \fi \relax} \def\page_col_command_set_top_insertions_indeed {\ifnum\noffloatinserts<\c_page_floats_n_of_top \ifcase\savednoffloats \let\page_col_command_set_top_insertions_indeed\relax \else \page_floats_collect\s!text\hsize\emwidth \ifdim\d_page_col_collected_top_float_height<\textheight \global\setbox\floatbox\hpack to \hsize {\page_floats_show_pack_state T% \hfil \dorecurse\nofcollectedfloats {\ifcase\columndirection % nog document wide \page_floats_flush\s!text\plusone \else \page_floats_flush\s!text{\tointeger{\nofcollectedfloats-\recurselevel+1}}% \fi % this could happen at the lua end instead \scratchdimen{\wd\floatbox-\naturalfloatwd}% \ifdim\scratchdimen<\zeropoint \global\setbox\floatbox\hpack spread -\scratchdimen{\hss\box\floatbox\hss}% \fi % \ifdim\wd\floatbox>\makeupwidth % \hsize \hpack to \makeupwidth{\hss\box\floatbox\hss}% \else \box\floatbox \fi \ifnum\recurselevel<\nofcollectedfloats \hfil \fi}% \hfil}% \page_one_prepare_top_float \xdef\totaltopinserted{\the\d_page_floats_inserted_top}% \page_one_insert_top_float \ifconditional\c_page_floats_some_waiting \advanceby\noffloatinserts \plusone \else \noffloatinserts\c_page_floats_n_of_top\relax \fi \page_floats_report_flushed \else \let\page_col_command_set_top_insertions_indeed\relax \fi \fi \else \ifconditional\c_page_floats_some_waiting \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}% \fi \let\page_col_command_set_top_insertions_indeed\relax \fi \page_col_command_set_top_insertions_indeed} \let\page_col_command_flush_top_insertions \page_one_command_flush_top_insertions \let\page_col_command_flush_bottom_insertions\page_one_command_flush_bottom_insertions \let\page_col_command_set_bottom_insertions \page_one_command_set_bottom_insertions \let\page_col_command_flush_float_box \page_one_command_flush_float_box \let\page_col_command_synchronize_side_floats\page_one_command_synchronize_side_floats \let\page_col_command_flush_side_floats \page_one_command_flush_side_floats \let\page_col_command_flush_margin_blocks \page_one_command_flush_margin_blocks \let\page_col_command_test_page \page_one_command_test_page %D The separator code is more or less the same as mixed columns but we need %D to compensate for the top floats so we comment a bit for now. \newdimension\pagecolumnseparatorheight \newdimension\pagecolumnseparatordepth \newdimension\pagecolumnseparatorwidth % \installcorenamespace{pagecolumnsseparator} % % \protected\def\installpagecolumnseparator#1#2% % {\setvalue{\??pagecolumnsseparator#1}{#2}} % % \installpagecolumnseparator\v!rule % {\vrule % \s!width \pagecolumnsparameter\c!rulethickness % \s!height\pagecolumnseparatorheight % \s!depth \pagecolumnseparatordepth % \relax} % % \def\page_col_routine_package_separate % {\ifcsname\??pagecolumnsseparator\p_separator\endcsname % \page_col_command_inject_separator % \else % \hss % \fi} % % \protected\def\page_col_command_inject_separator % {\begingroup % \setbox\scratchbox\hbox to \zeropoint \bgroup % \hss % \starttextproperties % \usepagecolumnscolorparameter\c!rulecolor % \begincsname\??pagecolumnsseparator\p_separator\endcsname % was \c!rule % \stoptextproperties % \hss % \egroup % \ht\scratchbox\zeropoint % \dp\scratchbox\zeropoint % \hss % \box\scratchbox % \hss % \endgroup} \def\page_col_routine_package_separate {\hss} %D \unknown \protected\def\page_col_command_routine {\page_sides_output_routine} % % not: % % \protected\def\page_col_command_routine % {\ifconditional\c_page_sides_short % \page_sides_output_routine_yes_column % \else % \page_sides_output_routine_nop_column % \fi} % % \let\page_sides_output_routine_nop_column\page_sides_output_routine % % \def\page_sides_output_routine_yes_column % this might become the main one too % {\unvbox\normalpagebox % bah, and the discards? % %\page_col_column % \column % \page % % why was this \global\holdinginserts\zerocount % \global\c_page_sides_short\conditionalfalse} \let\page_col_command_flush_all_floats\relax %D \unknown \defineoutputroutine [\s!pagecolumn] [\s!page_otr_command_routine =\page_col_command_routine, \s!page_otr_command_package_contents =\page_col_command_package_contents, \s!page_otr_command_set_vsize =\page_col_command_set_vsize, \s!page_otr_command_set_hsize =\page_col_command_set_hsize, % \s!page_otr_command_synchronize_hsize =\page_col_command_synchronize_hsize, % not done \s!page_otr_command_next_page =\page_col_command_next_page, \s!page_otr_command_next_page_and_inserts =\page_col_command_next_page_and_inserts, \s!page_otr_command_set_top_insertions =\page_col_command_set_top_insertions, \s!page_otr_command_set_bottom_insertions =\page_col_command_set_bottom_insertions, \s!page_otr_command_flush_top_insertions =\page_col_command_flush_top_insertions, \s!page_otr_command_flush_bottom_insertions=\page_col_command_flush_bottom_insertions, \s!page_otr_command_check_if_float_fits =\page_col_command_check_if_float_fits, % \s!page_otr_command_set_float_hsize =\page_col_command_set_float_hsize, % not done \s!page_otr_command_flush_float_box =\page_col_command_flush_float_box, \s!page_otr_command_side_float_output =\page_col_command_side_float_output, \s!page_otr_command_synchronize_side_floats=\page_col_command_synchronize_side_floats, \s!page_otr_command_flush_floats =\page_col_command_flush_floats, \s!page_otr_command_flush_side_floats =\page_col_command_flush_side_floats, \s!page_otr_command_flush_saved_floats =\page_col_command_flush_saved_floats, \s!page_otr_command_flush_all_floats =\page_col_command_flush_all_floats, \s!page_otr_command_flush_margin_blocks =\page_col_command_flush_margin_blocks, \s!page_otr_command_test_column =\page_col_command_test_page ] %D \unknown \installfloatmethod \s!pagecolumn \v!here \page_one_place_float_here \installfloatmethod \s!pagecolumn \v!force \page_one_place_float_force \installfloatmethod \s!pagecolumn \v!left \page_one_place_float_left \installfloatmethod \s!pagecolumn \v!right \page_one_place_float_right \installfloatmethod \s!pagecolumn \v!text \page_one_place_float_text \installfloatmethod \s!pagecolumn \v!top \page_one_place_float_top \installfloatmethod \s!pagecolumn \v!bottom \page_one_place_float_bottom \installfloatmethod \s!pagecolumn \v!auto \page_one_place_float_auto \installfloatmethod \s!pagecolumn \v!margin \page_one_place_float_margin \installfloatmethod \s!pagecolumn \v!opposite \page_one_place_float_face \installfloatmethod \s!pagecolumn \v!page \page_one_place_float_page \installfloatmethod \s!pagecolumn \v!leftpage \page_one_place_float_leftpage \installfloatmethod \s!pagecolumn \v!rightpage \page_one_place_float_rightpage \installfloatmethod \s!pagecolumn \v!inmargin \page_one_place_float_inmargin \installfloatmethod \s!pagecolumn \v!inleft \page_one_place_float_leftmargin \installfloatmethod \s!pagecolumn \v!inright \page_one_place_float_rightmargin \installfloatmethod \s!pagecolumn \v!leftmargin \page_one_place_float_leftmargin \installfloatmethod \s!pagecolumn \v!rightmargin \page_one_place_float_rightmargin \installfloatmethod \s!pagecolumn \v!leftedge \page_one_place_float_leftedge \installfloatmethod \s!pagecolumn \v!rightedge \page_one_place_float_rightedge \installfloatmethod \s!pagecolumn \v!somewhere \page_one_place_float_somewhere \installfloatmethod \s!pagecolumn \v!backspace \page_one_place_float_backspace \installfloatmethod \s!pagecolumn \v!cutspace \page_one_place_float_cutspace %installfloatmethod \s!pagecolumn \s!tblr \page_one_place_float_top %installfloatmethod \s!pagecolumn \s!lrtb \page_one_place_float_top %installfloatmethod \s!pagecolumn \s!tbrl \page_one_place_float_top %installfloatmethod \s!pagecolumn \s!fxtb \page_one_place_float_top %installfloatmethod \s!pagecolumn \s!rltb \page_one_place_float_top %installfloatmethod \s!pagecolumn \s!btlr \page_one_place_float_bottom %installfloatmethod \s!pagecolumn \s!lrbt \page_one_place_float_bottom %installfloatmethod \s!pagecolumn \s!btrl \page_one_place_float_bottom %installfloatmethod \s!pagecolumn \s!rlbt \page_one_place_float_bottom %installfloatmethod \s!pagecolumn \s!fxbt \page_one_place_float_bottom %installfloatmethod \s!pagecolumn \s!fixd \page_one_place_float_force \installfloatmethod \s!pagecolumn \v!local \somelocalfloat %D The main interface: \installcorenamespace{pagecolumns} \installframedcommandhandler \??pagecolumns {pagecolumns} \??pagecolumns \setuppagecolumns [\c!distance=1.5\bodyfontsize, \c!n=\plustwo, \c!page=\v!yes, %\c!align=, % inherit (also replaces tolerance) %\c!before=, %\c!after=, %\c!separator=\v!none, %\c!setups=, %\c!balance=\v!no, %\c!blank={\v!line,\v!fixed}, yes or no \c!frame=\v!off, \c!strut=\v!no, \c!offset=\v!overlay, %\c!maxheight=\textheight, \c!maxwidth=\makeupwidth, %\c!grid=\v!tolerant, %\c!internalgrid=\v!line, \c!direction=\v!normal] \appendtoks % could become an option \frozen\instance\protected\edefcsname\e!start\currentpagecolumns\endcsname{\startpagecolumns[\currentpagecolumns]}% \frozen\instance\protected\edefcsname\e!stop \currentpagecolumns\endcsname{\stoppagecolumns}% \to \everydefinepagecolumns \def\page_col_pickup_preceding {\begingroup \setupoutputroutine[\s!mixedcolumn]% \c_page_mix_routine\c_page_mix_routine_intercept \page_otr_trigger_output_routine \ifvoid\b_page_mix_preceding \else % moved here, before the packaging \page_postprocessors_linenumbers_deepbox\b_page_mix_preceding % we need to avoid unvboxing with successive balanced on one page \global\setbox\b_page_mix_preceding\vbox\bgroup % yes or no: \forcestrutdepth \unvbox\b_page_mix_preceding \forcestrutdepth \egroup \wd\b_page_mix_preceding\makeupwidth \global\d_page_mix_preceding_height\ht\b_page_mix_preceding \fi \endgroup} % Keep this one as original: % % \def\page_col_flush_preceding % {\ifvoid\b_page_mix_preceding \else % % this is just one method but ok for now % \begingroup % % we might need more but for now this is ok % \setupfloat[\c!spacebefore=,\c!spaceafter=]% % \startplacefigure[\c!location={\v!top,\v!none}]% % \box\b_page_mix_preceding % \stopplacefigure % \endgroup % \fi} \def\page_col_flush_preceding {\ifvoid\b_page_mix_preceding \else \scratchwidth \emwidth \scratchheight\ht\b_page_mix_preceding \scratchdepth \dp\b_page_mix_preceding \global\initialpageskip\htdp\b_page_mix_preceding \global\initialtopskip \strutht % for the moment \setbox\scratchbox\vbox\bgroup \pagediscards \egroup \global\advanceby\initialtopskip \ht\scratchbox % till here \setbox\scratchbox\hbox to \zeropoint \bgroup \box\b_page_mix_preceding \egroup \putboxincache{\s!pagecolumn\s!pagecolumn}{\number\plusone}\scratchbox \dostepwiserecurse\plustwo\c_page_col_n_of_columns\plusone {\setbox\scratchbox\hbox to \zeropoint \bgroup \novrule \s!width \scratchwidth \s!height\scratchheight \s!depth \scratchdepth \hss \egroup \putboxincache{\s!pagecolumn\s!pagecolumn}{\recurselevel}\scratchbox}% \fi} % \let\page_col_notes_initialize \relax % \let\page_col_notes_synchronize\relax % \let\page_col_notes_reset \relax % % \protected\def\page_col_command_set_vsize % \page_one_command_set_vsize minus the pagegoal setting % {\ifgridsnapping % \ifcase\layoutlines % \getrawnoflines\textheight % \else % \noflines\layoutlines % \fi % \global\vsize\noflines\openlineheight % \else % \global\vsize\textheight % \fi} \newconditional\c_page_col_notes_lastcolumn \def\page_col_notes_synchronize {\insertstoring\zerocount \ifnum\c_page_col_current=\c_page_col_n_of_columns\relax \strc_notes_process\page_col_notes_inject \ifconditional\c_page_col_notes_lastcolumn \insertstoring\plusone \fi \else \strc_notes_process\page_col_notes_delay \ifconditional\c_page_col_notes_lastcolumn \insertstoring\plustwo \fi \fi} \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} \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} \def\page_col_notes_initialize {\insertstoring\zerocount\strc_notes_process\page_col_notes_delay} \def\page_col_notes_reset {\insertstoring\zerocount\strc_notes_process\page_col_notes_inject} \protected\def\page_col_command_set_vsize % different ! {\page_one_command_set_vsize} \permanent\tolerant\protected\def\startpagecolumns[#S#1]% {\begingroup \begingroup \ifhastok={#1}% \lettonothing\currentpagecolumns \setuppagecolumns[#1]% \else \cdef\currentpagecolumns{#1}% \fi \edef\p_page{\pagecolumnsparameter\c!page}% \ifempty\p_page \c_page_col_page\conditionalfalse \orelse\ifx\p_page\v!no \c_page_col_page\conditionalfalse \else \c_page_col_page\conditionaltrue \page[\p_page]% \fi \c_page_col_n_of_columns\pagecolumnsparameter\c!n\relax \ifnum\c_page_col_n_of_columns>\plusone \expandafter\page_col_start_yes \else \expandafter\page_col_start_nop \fi} % public \aliased\let\stoppagecolumns\relax \protected\def\page_col_start_yes {\d_page_col_distance {\pagecolumnsparameter\c!distance}% % \d_page_col_max_height {\pagecolumnsparameter\c!maxheight}% \d_page_col_max_width {\pagecolumnsparameter\c!maxwidth}% % \d_page_col_balance_step {\pagecolumnsparameter\c!step}% \c_page_col_current \plusone % \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}% % \columnwidth \d_page_col_column_width \columndistance \d_page_col_distance \nofcolumns \c_page_col_n_of_columns \textwidth \columnwidth % kind of redundant % \nopenalties % \global\initialpageskip\zeroskip \global\initialtopskip \zeroskip % % \insidecolumnstrue % NO! % \enforced\let\column\page_col_column % \def\page_floats_get_used_hsize{\makeupwidth} % a bit of a hack % \usealignparameter \pagecolumnsparameter \useblankparameter \pagecolumnsparameter % \useprofileparameter\pagecolumnsparameter % \usepagecolumnscolorparameter\c!color % \setupnotes[\c!width=\textwidth]% % \usesetupsparameter\pagecolumnsparameter % % This will become a method but for now it's good enough % \ifconditional\c_page_col_page\else \page_col_pickup_preceding \fi \setupoutputroutine[\s!pagecolumn]% \ifconditional\c_page_col_page\else \page_col_flush_preceding \fi % \setupfloats[\c!ntop=\plusthousand]% % \setupfloats[\c!nbottom=\plusthousand]% % \page_col_notes_initialize % \page_col_command_set_vsize \page_col_command_set_hsize % \enforced\permanent\protected\def\startpagecolumns[##1]{\page_col_start_nop}% % \enforced\let\stoppagecolumns\page_col_stop_yes} \protected\def\page_col_start_nop {\nofcolumns\c_page_mix_n_of_columns \enforced\let\stoppagecolumns\page_col_stop_nop} \lettonothing\page_col_routine_balance_check \protected\def\page_col_stop_yes {%\column % \page_otr_eject_page \page_col_routine_balance_check \page % beware for empty pages \endgroup % \setupoutputroutine[\s!singlecolumn]% \global\initialpageskip\zeroskip \global\initialtopskip \zeroskip \page_otr_command_set_vsize \page_otr_command_set_hsize \page \page_col_notes_reset \endgroup} \protected\def\page_col_stop_nop {\page \endgroup \endgroup} % This is only for me, experimental and subject to changes! The problem is that we're already % wrapped so e.g. when we use vz we are toast. % \def\page_col_routine_balance_check % {\ifcstok{\pagecolumnsparameter\c!balance}\v!yes % \let\page_col_routine_balance\page_col_routine_balance_indeed % \fi} % % \def\page_col_routine_balance_indeed % {\ifnum\nofcolumns=\plustwo % \setbox\scratchbox\vbox\bgroup % \directboxfromcache{\s!pagecolumn}{1} % \setbox\scratchbox\lastbox\unvbox\scratchbox % \setbox\scratchbox\lastbox\unvbox\scratchbox % \directboxfromcache{\s!pagecolumn}{2} % \setbox\scratchbox\lastbox\unvbox\scratchbox % \setbox\scratchbox\lastbox\unvbox\scratchbox % \egroup % % holdinginserts % \scratchdimen.5\htdp\scratchbox % \splittopskip\topskip % \localcontrolledendless {% % \setbox\scratchboxtwo\copy\scratchbox % \setbox\scratchboxone\vsplit\scratchboxtwo to \scratchdimen % \ifdim\ht\scratchboxone<\ht\scratchboxtwo % \quitloop % \orelse\ifvoid\scratchboxtwo % \quitloop % \orelse\ifdim\scratchdimen>\textheight % \quitloop % \else % \advanceby\scratchdimen\onepoint % \fi % }% % \setbox\scratchboxone\vtop to \scratchdimen{\unvbox\scratchboxone}% % \setbox\scratchboxtwo\vtop to \scratchdimen{\unvbox\scratchboxtwo}% % \putboxincache{\s!pagecolumn}{1}\scratchboxone % \putboxincache{\s!pagecolumn}{2}\scratchboxtwo % \fi} % \def\page_col_routine_balance_indeed % {\ifnum\nofcolumns=\plustwo % \setbox\scratchbox\vbox\bgroup % \directboxfromcache{\s!pagecolumn}{1} % \setbox\scratchbox\lastbox\ifvbox\scratchbox\unvbox\scratchbox\fi % \setbox\scratchbox\lastbox\ifvbox\scratchbox\unvbox\scratchbox\fi % \doifelseboxincache{\s!pagecolumn}{2} % {\directboxfromcache{\s!pagecolumn}{2} % \setbox\scratchbox\lastbox\ifvbox\scratchbox\unvbox\scratchbox\fi % \setbox\scratchbox\lastbox\ifvbox\scratchbox\unvbox\scratchbox\fi % }% % {}% % \egroup % % holdinginserts % \scratchdimen.5\htdp\scratchbox % \splittopskip\topskip % \localcontrolledendless {% % \setbox\scratchboxtwo\copy\scratchbox % \setbox\scratchboxone\vsplit\scratchboxtwo upto \scratchdimen % % \writestatus{page columns}{ \the\ht\scratchboxone,\the\ht\scratchboxtwo}% % \ifdim\ht\scratchboxone<\ht\scratchboxtwo % \quitloop % \orelse\ifvoid\scratchboxtwo % \quitloop % \orelse\ifdim\scratchdimen>\textheight % \quitloop % \else % \advanceby\scratchdimen\onepoint % \fi % }% % % \ifdim\ht\scratchboxone<\ht\scratchboxtwo % % \scratchdimen\ht\scratchboxone % % \advanceby\scratchdimen\onepoint % % \localcontrolledendless {% % % \setbox\scratchboxtwo\copy\scratchbox % % \setbox\scratchboxone\vsplit\scratchboxtwo upto \scratchdimen % % \writestatus{page columns}{ \the\ht\scratchboxone,\the\ht\scratchboxtwo}% % % \ifdim\ht\scratchboxone>\ht\scratchboxtwo % % \quitloop % % \orelse\ifdim\ht\scratchboxone=\ht\scratchboxtwo % % \quitloop % % \orelse\ifvoid\scratchboxtwo % % \quitloop % % \orelse\ifdim\scratchdimen>\textheight % % \quitloop % % \else % % \advanceby\scratchdimen\onepoint % % \fi % % }% % % \fi % \setbox\scratchboxone\vtop to \scratchdimen{\unvbox\scratchboxone}% % \setbox\scratchboxtwo\vtop to \scratchdimen{\unvbox\scratchboxtwo}% % \putboxincache{\s!pagecolumn}{1}\scratchboxone % \putboxincache{\s!pagecolumn}{2}\scratchboxtwo % \fi} \protect \endinput