summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/page-mul.mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/page-mul.mkiv')
-rw-r--r--tex/context/base/mkiv/page-mul.mkiv1824
1 files changed, 1824 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/page-mul.mkiv b/tex/context/base/mkiv/page-mul.mkiv
new file mode 100644
index 000000000..631232368
--- /dev/null
+++ b/tex/context/base/mkiv/page-mul.mkiv
@@ -0,0 +1,1824 @@
+%D \module
+%D [ file=page-mul, % was: core-mul
+%D version=1998.03.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Multi Column Output,
+%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.
+
+% todo: basecolumns as parent for columns and itemize
+
+% !!! there are some issues with hsize an vsize as well as flushing
+% !!! floats but this module will be redone anyway
+
+\writestatus{loading}{ConTeXt Page Macros / Simple Multi Column}
+
+%D This module is mostly a copy from the original multi column routine as
+%D implemented in \type {core-mul}. When the main OTR macro's were
+%D isolated in modules and column sets were introduced, this module became
+%D part of the OTR modules. As a result this module is no longer generic.
+
+\unprotect
+
+\definesystemvariable {ks} % KolomSpan
+
+% check \count<insert> multiplications
+
+%D The following macro's implement a multi||column output routine. The original
+%D implementation was based on Donald Knuth's implementation, which was adapted by
+%D Craig Platt to support balancing of the last page. I gradually adapted Platt's
+%D version to our needs but under certain circumstances things still went wrong. I
+%D considered all calls to Platt's \type{\page_mul_routine_error} as undesirable.
+%D
+%D This completely new implementation can handle enough situations for everyday
+%D documents, but is still far from perfect. While at the moment the routine doesn't
+%D support all kind of floats, it does support:
+%D
+%D \startitemize[packed]
+%D \item an unlimitted number of columns
+%D \item ragged or not ragged bottoms
+%D \item optional balancing without \type{\page_mul_routine_errors}
+%D \item different \type{\baselineskips}, \type{\spacing}, \type {\topskip} and
+%D \type {\maxdepth}
+%D \item left- and right indentation, e.g. within lists
+%D \item moving columns floats to the next column or page
+%D \item handling of floats that are to wide for a columns
+%D \stopitemize
+%D
+%D One could wonder why single and multi||columns modes are still separated. One
+%D reason for this is that \TeX\ is not suited well for handling multi||columns. As
+%D a result, the single columns routines are more robust. Handling one column as a
+%D special case of multi||columns is posible but at the cost of worse float
+%D handling, worse page breaking, worse etc. Complicated multi||column page handling
+%D should be done in \cap{DTP}||systems anyway.
+
+\installcorenamespace {columns}
+
+\installcommandhandler \??columns {columns} \??columns
+
+%D Going to a new columns is done by means of a \type {\ejectcolumn}. The
+%D following definition does not always work.
+
+ \unexpanded\def\ejectcolumn % not good enough
+ {\goodbreak
+ \showmessage\m!columns2\empty}
+
+%D The output routines plug into a more generic mechanism as can be seen at the
+%D end of this file. So, occasionally we need to define some plugin code.
+
+\unexpanded\def\page_mul_place_float_top
+ {\showmessage\m!columns4\empty\page_one_place_float_here}
+
+\unexpanded\def\page_mul_place_float_bottom
+ {\showmessage\m!columns5\empty\page_one_place_float_here}
+
+\unexpanded\def\page_mul_place_float_here
+ {\page_one_place_float_here}
+
+\unexpanded\def\page_mul_place_float_force
+ {\page_one_place_float_force}
+
+\unexpanded\def\page_mul_command_side_float_output
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+\unexpanded\def\page_mul_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mul_command_synchronize_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mul_command_next_page
+ {\page_otr_eject_page}
+
+\unexpanded\def\page_mul_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
+
+\let\page_mul_initialize_floats\relax
+\let\page_mul_flush_floats \relax
+\let\page_mul_flush_float \relax
+
+%D A hook:
+
+ \let\finishcolumnbox\relax
+
+%D This will change to a local one:
+
+\ifdefined\nofcolumns \else \newcount\nofcolumn \fi
+\ifdefined\mofcolumns \else \newcount\mofcolumn \fi
+
+\appendtoks
+ \nofcolumns\columnsparameter\c!n\relax
+\to \everysetupcolumns
+
+%D Columns are separated by spacing or rules or whatever suits.
+
+\installcorenamespace{columnseparators}
+
+\setvalue{\??columnseparators\v!on }{\let\page_mul_between_columns\page_mul_between_columns_rule}
+\setvalue{\??columnseparators\v!off }{\let\page_mul_between_columns\page_mul_between_columns_space}
+\setvalue{\??columnseparators }{\let\page_mul_between_columns\page_mul_between_columns_space}
+\setvalue{\??columnseparators\s!unknown}{\let\page_mul_between_columns\p_page_mul_rule}
+
+\def\page_mul_between_columns_rule
+ {\bgroup
+ \starttextproperties
+ \scratchdistance\dimexpr\columnsparameter\c!distance/2\relax
+ \hskip\scratchdistance\relax
+ \vrule
+ \s!width\linewidth
+ \ifnum\bottomraggednessmode=\plustwo % baselinebottom
+ \s!depth\strutdepth
+ \fi
+ \hskip\scratchdistance\relax
+ \stoptextproperties
+ \egroup}
+
+\def\page_mul_between_columns_space
+ {\hskip\columnsparameter\c!distance\relax}
+
+\let\page_mul_between_columns\page_mul_between_columns_space
+
+%D We declare some registers:
+
+\newdimen \d_page_mul_available_width
+\newdimen \d_page_mul_distance
+\newdimen \d_page_mul_leftskip
+\newdimen \d_page_mul_rightskip
+\newdimen \d_page_mul_offset
+\newdimen \d_page_mul_forced_height
+\newdimen \d_page_mul_used_width
+\newdimen \d_page_mul_temp
+
+\newcount \c_page_mul_balance_minimum
+\newcount \c_page_mul_n_of_lines
+
+\newbox \b_page_mul_preceding
+\newdimen \d_page_mul_preceding_height
+\newdimen \d_page_mul_preceding_depth
+\newconditional\c_page_mul_preceding_present
+
+\newbox \b_page_mul_preceding_rest_of_page
+
+\newconditional\c_page_mul_reverse
+
+\newconditional\c_page_mul_trace
+
+%D The next dimensions reports the final column height .. todo
+
+ \newdimen\finalcolumnheights
+ \newcount\finalcolumnlines
+
+ \newdimen\savedpagetotal % brrr
+
+ \newif\ifstretchcolumns \stretchcolumnsfalse
+ \newif\ifheightencolumns \heightencolumnsfalse
+ \newif\ifinheritcolumns \inheritcolumnsfalse
+ \newif\ifbalancecolumns %\balancecolumnstrue
+
+%D An important one:
+
+\unexpanded\def\page_mul_command_set_hsize % beware, this one is available for use in macros
+ {\setbox\scratchbox\hbox{\page_mul_between_columns}%
+ \d_page_mul_distance\wd\scratchbox
+ \d_page_mul_available_width\dimexpr
+ \makeupwidth
+ -\d_page_mul_leftskip
+ -\d_page_mul_rightskip
+ -\nofcolumns\d_page_mul_distance
+ +\d_page_mul_distance
+ \relax
+ \d_page_mul_used_width\dimexpr
+ \d_page_mul_available_width/\nofcolumns
+ -\d_page_mul_offset*\plustwo
+ \relax
+ \textwidth\d_page_mul_used_width % needs thinking ... grouping etc
+ \hsize\d_page_mul_used_width}
+
+%D Torture test:
+%D
+%D \startbuffer
+%D \startbuffer[b]
+%D \startcolumns
+%D \input tufte
+%D \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower
+%D \input tufte
+%D \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower \startcolumns
+%D \input tufte
+%D \stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startcolumns \startnarrower[left]
+%D \input tufte
+%D \stopnarrower \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower[left] \startcolumns
+%D \input tufte
+%D \stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower\stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower[left] \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower\stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D \stopbuffer
+%D
+%D \start
+%D \def\postprocesscolumnline#1{\ruledhbox{\strut\box#1}\hss}
+%D \getbuffer
+%D \stop
+
+%D One should be aware that when font related dimensions are used in typesetting the
+%D in||between material, these dimensions are influenced by bodyfont switches inside
+%D multi||column mode.
+
+\setnewconstant\multicolumnlinemethod\zerocount % 0=normal 1=raw
+
+\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
+
+\unexpanded\def\page_mul_set_n_of_lines
+ {\settotalinsertionheight
+ \d_page_mul_temp\dimexpr
+ -\d_page_mul_offset*\plustwo
+ +\textheight
+ \ifdim\d_page_mul_preceding_height>\zeropoint -\d_page_mul_preceding_height \fi
+ -\totalinsertionheight
+ \relax
+ \ifcase\multicolumnlinemethod
+ \getnoflines \d_page_mul_temp \or
+ \getrawnoflines\d_page_mul_temp \else
+ \getrawnoflines\d_page_mul_temp
+ \fi
+ % added 30/7/2004
+ \ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines
+ \noflines\layoutlines
+ \fi \fi
+ \c_page_mul_n_of_lines\noflines}
+
+\unexpanded\def\page_mul_command_set_vsize
+ {\page_one_command_set_vsize % indeed?
+ \page_mul_set_n_of_lines
+ \d_page_mul_temp\nofcolumns\dimexpr
+ \c_page_mul_n_of_lines\openlineheight
+ +\multicolumnovershootratio\openlineheight % collect enough data
+ \relax
+ \global\vsize\d_page_mul_temp
+ \pagegoal \d_page_mul_temp} % let's do it only here
+
+%D It really starts here. After some checks and initializations we change the output
+%D routine to continous multi||column mode. This mode handles columns that fill the
+%D current and next full pages. The method used is (more or less) multiplying \type
+%D {\vsize} and dividing \type {\hsize} by \type {\nofcolumns}. More on this can be
+%D found in the \TeX book. We save the top of the current page in box
+%D \type {\b_page_mul_preceding}.
+%D
+%D We manipulate \type {\topskip} a bit, just to be shure that is has no
+%D flexibility. This has te be done every time a font switch takles place, because
+%D \type {\topskip} can depend on this.
+
+\newconstant\c_page_mul_routine
+
+\setnewconstant\c_page_mul_routine_regular \zerocount
+\setnewconstant\c_page_mul_routine_intercept \plusone
+\setnewconstant\c_page_mul_routine_continue \plustwo
+\setnewconstant\c_page_mul_routine_balance \plusthree
+\setnewconstant\c_page_mul_routine_error \plusfour
+
+\unexpanded\def\page_mul_command_routine
+ {\ifcase\c_page_mul_routine
+ \page_one_command_routine
+ \or
+ \page_mul_routine_intercept
+ \or
+ \page_mul_routine_continue
+ \or
+ \page_mul_routine_balance
+ \or
+ \page_mul_routine_error
+ \fi}
+
+\def\page_mul_routine_intercept
+ {\global\setbox\b_page_mul_preceding\vbox
+ {\page_otr_command_flush_top_insertions
+ \unvbox\normalpagebox}}
+
+\def\page_mul_routine_error
+ {\showmessage\m!columns3\empty
+ \page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+%D When we leave the multi||column mode, we have to process the not yet shipped out
+%D part of the columns. When we don't balance, we simply force a continuous output,
+%D but a balanced output is more tricky.
+%D
+%D First we try to fill up the page and when all or something is left we try to
+%D balance things. This is another useful adaption of the ancesters of these
+%D macro's. It takes some reasoning to find out what happens and maybe I'm making
+%D some mistake, but it works.
+%D
+%D Voiding box \type {\b_page_mul_preceding} is sometimes necessary, e.g. when there is no
+%D text given between \type {\begin..} and \type {\end..}. The \type {\par} is
+%D needed!
+
+%D Because some initializations happen three times, we defined a macro for
+%D them. Erasing \type{\everypar} is needed because we don't want anything
+%D to interfere.
+
+\unexpanded\def\page_mul_initialize_variables
+ {\reseteverypar
+ \dontcomplain
+ \settopskip
+ \setmaxdepth
+ \topskip 1\topskip
+ \splittopskip \topskip
+ \splitmaxdepth \maxdepth
+ \boxmaxdepth \maxdepth % dangerous
+ \emergencystretch\zeropoint
+ \relax} % sometimes needed !
+
+%D Flushing the page comes to pasting the columns together and appending the result
+%D to box \type {\b_page_mul_preceding}, if not void. I've seen a lot of implementations in
+%D which some skip was put between normal text and multi||column text. When we don't
+%D want this, the baselines can be messed up. I hope the seemingly complicated
+%D calculation of a correction \type {\kern} is adequate to overcome this. Although
+%D not watertight, spacing is taken into account and even multiple mode changes on
+%D one page go well. But cross your fingers and don't blame me.
+%D
+%D One of the complications of flushing out the boxes is that \type {\b_page_mul_preceding}
+%D needs to be \type {\unvbox}'ed, otherwise there is too less flexibility in the
+%D page when using \type {\raggedbottom}. It took a lot of time before these kind of
+%D problems were overcome. Using \type {\unvbox} at the wrong moment can generate
+%D \type {\page_mul_routine_error}'s.
+%D
+%D One can use the macros \type {\maxcolumnheight} and \type {\maxcolumndepth} when
+%D generating material between columns as well as postprocessing column lines.
+
+\newdimen\maxcolumnheight
+\newdimen\maxcolumndepth
+
+\newbox\columnpagebox
+
+\def\page_mul_calculate_column_result_dimensions
+ {\maxcolumnheight\zeropoint
+ \maxcolumndepth \zeropoint
+ \dohandleallcolumnscs\page_mul_calculate_column_result_dimensions_step}
+
+\def\page_mul_calculate_column_result_dimensions_step
+ {\ifdim\ht\currentcolumnbox>\maxcolumnheight
+ \maxcolumnheight\ht\currentcolumnbox
+ \fi
+ \ifdim\dp\currentcolumnbox>\maxcolumndepth
+ \maxcolumndepth\dp\currentcolumnbox
+ \fi}
+
+\setnewconstant\multicolumntopflushmethod\plusone % 0: no correction, 1: correction when topstuff, 2: correction, 3: correction++
+\setnewconstant\multicolumntopalignmethod\plustwo % 0: nothing, 1: force grid, 2: follow grid
+
+\def\page_mul_flush_preceding_normal
+ {\unvbox\b_page_mul_preceding}
+
+\def\page_mul_flush_preceding_ongrid
+ {\scratchdimen\dimexpr
+ \savedpagetotal
+ -\d_page_mul_preceding_height
+ -\d_page_mul_preceding_depth
+ -\topskip
+ \relax
+ \box\b_page_mul_preceding
+ \kern\scratchdimen}
+
+\def\page_mul_flush_packaged_columns_continued
+ {\bgroup
+ \page_mul_flush_packaged_columns_indeed
+ \box\columnpagebox
+ \egroup}
+
+\def\page_mul_flush_packaged_columns_balanced
+ {\bgroup
+ \page_mul_flush_packaged_columns_indeed
+ % messy correction, we need to rewrite this module (newcolumns)
+ \setbox\columnpagebox\vbox
+ {\offinterlineskip
+ \scratchdimen\ht\columnpagebox
+ \advance\scratchdimen\dp\columnpagebox % we probably lost that one already
+ \box\columnpagebox
+ \vskip-\scratchdimen}%
+ \scratchdimen\noflines\openlineheight
+ \advance\scratchdimen-\openstrutdepth
+ \ifgridsnapping
+ % quick hack (at least it works with itemize)
+ \else
+ \advance\scratchdimen-\openlineheight
+ \advance\scratchdimen\topskip
+ \fi
+ \ht\columnpagebox\scratchdimen
+ \dp\columnpagebox\openstrutdepth
+ % end of mess
+ \box\columnpagebox
+ \egroup}
+
+\def\page_mul_synchronize_marks
+ {\dohandleallcolumns{\page_marks_synchronize_column\plusone\nofcolumns\mofcolumns\currentcolumnbox}}
+
+\def\page_mul_flush_packaged_columns_indeed
+ {\ifvoid\b_page_mul_preceding
+ \setfalse\c_page_mul_preceding_present % will be set elsewhere
+ \else
+ \settrue\c_page_mul_preceding_present
+ \page_postprocessors_box\b_page_mul_preceding
+ \fi
+ \forgetall
+ \page_mul_initialize_variables
+ \page_mul_calculate_column_result_dimensions
+ \page_mul_postprocess_linenumbers
+ \page_mul_synchronize_marks
+ \page_mul_postprocess_lines
+ \page_mul_postprocess_columns
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\hbox to \d_page_mul_used_width
+ {\box\currentcolumnbox}%
+ \wd\currentcolumnbox\d_page_mul_used_width
+ \ifheightencolumns
+ \ht\currentcolumnbox\d_page_mul_forced_height
+ \fi}%
+ \page_mul_calculate_column_result_dimensions
+ \overlaycolumnfootnotes
+ \setbox\columnpagebox\vbox
+ {\hbox to \makeupwidth
+ {\hskip\d_page_mul_leftskip\relax % new, \relax needed
+ \ifconditional\c_page_mul_reverse
+ \expandafter\dohandlerevcolumns
+ \else
+ \expandafter\dohandleallcolumns
+ \fi
+ {\finishcolumnbox
+ {\setbox\scratchbox\hbox
+ {\ifx\finishcolumnbox\relax\else\strut\fi
+ \box\currentcolumnbox}% hm, why strut
+ \anch_mark_column_box\scratchbox
+ \box\scratchbox}%
+ \hfil}%
+ \unskip
+ \hskip\d_page_mul_rightskip}}% new
+ \scratchdimen\zeropoint
+ \dohandleallcolumns
+ {\ifdim-\ht\currenttopcolumnbox<\scratchdimen
+ \scratchdimen-\ht\currenttopcolumnbox
+ \fi
+ \global\setbox\currenttopcolumnbox\emptybox}%
+ \advance\scratchdimen \ht\columnpagebox
+ \setbox\scratchbox\hbox to \makeupwidth
+ {\vrule
+ \s!width\zeropoint
+ \s!height\scratchdimen
+ \s!depth\dp\columnpagebox
+ \dostepwiserecurse\plustwo\nofcolumns\plusone{\hfil\page_mul_between_columns}\hfil}%
+ \setbox\columnpagebox\hbox
+ {\box\columnpagebox
+ \hskip-\makeupwidth
+ \box\scratchbox}%
+ \page_mul_postprocess_page
+ \ifconditional\c_page_mul_preceding_present
+ \settrue\c_page_mul_preceding_present
+ % next some incredible crappy code
+ \ifcase\multicolumntopalignmethod
+ \page_mul_flush_preceding_normal % not on grid
+ \or
+ \page_mul_flush_preceding_ongrid % force on grid
+ \else\ifgridsnapping
+ \page_mul_flush_preceding_ongrid % obey grid settings, force on grid
+ \else
+ \page_mul_flush_preceding_normal % ignore grid settings, not on grid
+ \fi \fi
+ \fi
+ \global\d_page_mul_preceding_height\zeropoint
+ \page_otr_command_set_vsize
+ \dosomebreak\nobreak % hm, only needed when topstuff
+ \ifgridsnapping
+ \else
+ \ifcase\multicolumntopflushmethod
+ % sometimes method 1 goes wrong, so we need a way out; best sort this out
+ % when we run into it again
+ \or
+ % \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte
+ \ifconditional\c_page_mul_preceding_present
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip\relax
+ \fi
+ \or
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip\relax
+ \or
+ % untested but maybe handy
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
+ % \vskip-\lineheight
+ % \vbox{\strut}%
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip-\lineheight\relax
+ \vbox{\strut}%
+ \fi
+ \fi
+ \prevdepth\openstrutdepth
+ \nointerlineskip
+ \dp\columnpagebox\zeropoint
+ \global\finalcolumnheights\ht\columnpagebox
+ \getnoflines\finalcolumnheights
+ \global\finalcolumnlines\noflines}
+
+%D In case one didn't notice, finaly \type{\finishcolumnbox} is applied to
+%D all boxes. One can use these hooks for special purposes.
+%D
+%D Once upon a time I wanted to manipulate the individual lines in a column.
+%D This feature is demonstrated in the two examples below.
+%D
+%D \startbuffer
+%D \def\postprocesscolumnline#1% or \postprocesscolumnbox
+%D {\ruledhbox{\box#1}\hss}
+%D
+%D \startcolumns[n=4]
+%D \dorecurse{25}{line: \recurselevel\par}
+%D \stopcolumns
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here we show the natural width of the lines:
+%D
+%D {\getbuffer}
+%D
+%D The next example does a bit more advanced manipulation:
+%D
+%D \startbuffer
+%D \def\postprocesscolumnline#1%
+%D {\ifodd\currentcolumn
+%D \hfill\unhbox#1\relax
+%D \else
+%D \relax\unhbox#1\hfill
+%D \fi}
+%D
+%D \startcolumns[n=4]
+%D \dorecurse{25}{line \recurselevel\par}
+%D \stopcolumns
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here we also see an application of \type{\currentcolumn}:
+%D
+%D {\getbuffer}
+%D
+%D This feature is implemented using the reshape macros presented
+%D in \type{supp-box}.
+
+\ifdefined\page_postprocessors_column\else\let\page_postprocessors_column\relax\fi % operates on passed box
+\ifdefined\postprocesscolumnline \else\let\postprocesscolumnline \relax\fi % operates on passed box
+\ifdefined\postprocesscolumnbox \else\let\postprocesscolumnbox \relax\fi % operates on passed box
+\ifdefined\postprocesscolumnpagebox \else\let\postprocesscolumnpagebox \relax\fi % operates on passed box
+
+\def\page_mul_postprocess_linenumbers{\ifx\page_postprocessors_column\relax\else\page_mul_postprocess_linenumbers_indeed\fi}
+\def\page_mul_postprocess_lines {\ifx\postprocesscolumnline \relax\else\page_mul_postprocess_lines_indeed \fi}
+\def\page_mul_postprocess_columns {\ifx\postprocesscolumnbox \relax\else\page_mul_postprocess_columns_indeed \fi}
+\def\page_mul_postprocess_page {\ifx\postprocesscolumnpagebox \relax\else\page_mul_postprocess_page_indeed \fi}
+
+\def\page_mul_postprocess_linenumbers_indeed
+ {\dohandleallcolumns{\page_postprocessors_column\currentcolumnbox}}
+
+\def\page_mul_postprocess_lines_indeed
+ {\dohandleallcolumnscs\page_mul_postprocess_lines_step}
+
+\def\page_mul_postprocess_lines_step % TODO: use lua solution instead
+ {\global\setbox\currentcolumnbox\vtop
+ {\beginofshapebox
+ \unvbox\currentcolumnbox
+ \unskip\unskip
+ \endofshapebox
+ \reshapebox
+ {\scratchheight\ht\shapebox
+ \scratchdepth \dp\shapebox
+ \setbox\shapebox\hbox to \hsize
+ {\postprocesscolumnline\shapebox}%
+ \ht\shapebox\scratchheight
+ \dp\shapebox\scratchdepth
+ \box\shapebox}%
+ \flushshapebox
+ \reseteverypar
+ \parskip\zeropoint % = \forgetall
+ \verticalstrut
+ \vskip-\struttotal
+ \vfil}}
+
+\def\page_mul_postprocess_columns_indeed
+ {\dohandleallcolumnscs\page_mul_postprocess_columns_step}
+
+\def\page_mul_postprocess_columns_step
+ {\global\setbox\currentcolumnbox\hbox
+ {\postprocesscolumnbox\currentcolumnbox}}
+
+\def\page_mul_postprocess_page_indeed
+ {\postprocesscolumnpagebox\columnpagebox}
+
+%D Here comes the simple splitting routine. It's a bit longer than expected because
+%D of ragging bottoms or not. This part can be a bit shorter but I suppose that I
+%D will forget what happens. The splitting takes some already present material
+%D (think of floats) into account!
+%D
+%D First we present some auxiliary routines. Any material, like for instance floats,
+%D that is already present in the boxes is preserved.
+
+\newdimen\d_page_mul_split_height_used
+\newdimen\d_page_mul_split_height_max
+
+\def\page_mul_split_column#1#2#3#4% copy or box
+ {\bgroup
+ \ifdim\ht#4>\zeropoint
+ \d_page_mul_split_height_used#3\relax
+ \d_page_mul_split_height_max\d_page_mul_split_height_used
+ \advance\d_page_mul_split_height_used -\ht#4%
+ \columnfootnotecorrection{#1}\d_page_mul_split_height_used
+ \setbox\scratchbox\vsplit#2 to \d_page_mul_split_height_used
+ \global\setbox#1\vbox to \d_page_mul_split_height_max
+ {\ifgridsnapping
+ \scratchdimen\dimexpr\topskip-\openstrutheight\relax
+ \vskip\scratchdimen
+ \copy#4%
+ \vskip-\scratchdimen
+ \else
+ \unvcopy#4%
+ \fi
+ \fuzzysnappedbox\unvbox\scratchbox
+ \fakecolumnfootnotes{#1}}%
+ \else\ifcase\c_strc_notes_page_location
+ \global\setbox#1\vsplit#2 to #3%
+ \global\setbox#1\vbox
+ {\fuzzysnappedbox\unvbox{#1}}% % or \box ?
+ \else
+ \columnfootnotecorrection{#1}{#3}%
+ \setbox\scratchbox\vsplit#2 to #3%
+ \global\setbox#1\vbox to #3%
+ {\fuzzysnappedbox\unvbox\scratchbox
+ \fakecolumnfootnotes{#1}}%
+ \fi \fi
+ \egroup}
+
+\def\page_mul_split_current_column#1#2%
+ {\page_mul_split_column\currentcolumnbox{#1}{#2}\currenttopcolumnbox}
+
+\def\page_mul_split_first_column#1#2%
+ {\page_mul_split_column\firstcolumnbox{#1}{#2}\firsttopcolumnbox}
+
+\def\page_mul_split_last_column#1#2%
+ {\global\setbox\lastcolumnbox\vbox
+ {\unvcopy\lasttopcolumnbox
+ \fuzzysnappedbox\unvbox{#1}%
+ \fakecolumnfootnotes\lastcolumnbox}}
+
+%D NEW: still to be documented.
+
+ \def\fakecolumnfootnotes#1%
+ {\relax
+ \ifcase\c_strc_notes_page_location\else
+ \ifnum#1=\lastcolumnbox
+ \fakenotes
+ \fi
+ \fi}
+
+ \def\columnfootnotecorrection#1#2%
+ {\relax
+ \ifcase\c_strc_notes_page_location
+ % page notes
+ \or
+ \ifnum#1=\firstcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \else
+ \ifnum#1=\lastcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \fi}
+
+ \def\overlaycolumnfootnotes
+ {\relax
+ \ifcase\c_strc_notes_page_location
+ % page
+ \or
+ \checknotepresence \ifnotespresent \page_mul_notes_flush_first_column \fi
+ \or
+ \checknotepresence \ifnotespresent \page_mul_notes_flush_last_column \fi
+ \fi}
+
+ \newbox\b_page_mul_notes
+
+ \def\page_mul_notes_flush_first_column
+ {\begingroup
+ \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
+ \ifzeropt\ht\b_page_mul_notes
+ % can't happen as we already checked
+ \else
+ \page_mul_set_n_of_lines
+ \advance\c_page_mul_n_of_lines \minustwo
+ \scratchdimen\dimexpr\c_page_mul_n_of_lines\lineheight+\topskip\relax
+ \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \ht\b_page_mul_notes\openstrutheight
+ \dp\b_page_mul_notes\openstrutdepth
+ \wd\b_page_mul_notes\zeropoint
+ \scratchdimen\ht\firstcolumnbox
+ \global\setbox\firstcolumnbox\vbox to \scratchdimen
+ {\box\firstcolumnbox
+ \vskip-\scratchdimen
+ \box\b_page_mul_notes}%
+ \fi
+ \endgroup}
+
+ \def\page_mul_notes_flush_last_column
+ {\begingroup
+ \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
+ \ifzeropt\ht\b_page_mul_notes
+ % can't happen as we already checked
+ \else
+ % maybe here also \page_mul_set_n_of_lines
+ \scratchdimen\dimexpr\ht\firstcolumnbox-\openstrutdepth\relax % \strutdp
+ \getnoflines\scratchdimen
+ \advance\noflines \minustwo
+ \scratchdimen\dimexpr\noflines\lineheight+\topskip\relax
+ \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \ht\b_page_mul_notes\openstrutheight
+ \dp\b_page_mul_notes\openstrutdepth
+ \wd\b_page_mul_notes\zeropoint
+ \scratchdimen\ht\lastcolumnbox
+ \global\setbox\lastcolumnbox\vbox to \scratchdimen
+ {\box\lastcolumnbox
+ \vskip-\scratchdimen
+ \box\b_page_mul_notes}%
+ \fi
+ \endgroup}
+
+%D Here comes the routine that splits the long box in columns. The macro \type
+%D {\page_mul_flush_floats} can be used to flush either floats that were present before
+%D the multi||column mode was entered, or floats that migrate to next columns.
+%D Flushing floats is a delicate process.
+
+\def\page_mul_routine_continue
+ {\bgroup
+ \forgetall
+ \page_mul_initialize_variables
+ % \dimen0=\makeupheight
+ % \advance\dimen0 -\d_page_mul_preceding_height
+ % \settotalinsertionheight
+ % \advance\dimen0 -\totalinsertionheight
+ % \ifgridsnapping % evt altijd, nog testen
+ % \getnoflines{\dimen0}
+ % \dimen0=\noflines\openlineheight
+ % \fi
+ \page_mul_set_n_of_lines
+ \d_page_mul_balance_target\c_page_mul_n_of_lines\openlineheight
+ \ifconditional\c_page_mul_trace
+ \writestatus\m!columns{continue: lines=\the\c_page_mul_n_of_lines, target=\the\d_page_mul_balance_target, textheight=\the\textheight}%
+ \fi
+ \dohandleallcolumns
+ {\page_mul_split_current_column\normalpagebox\d_page_mul_balance_target}%
+ \setbox\b_page_mul_preceding_rest_of_page\vbox{\unvbox\normalpagebox}%
+ \ifinheritcolumns
+ \ifcase\bottomraggednessmode
+ % 0 = ragged
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\scratchdepth\dp\currentcolumnbox
+ \unvbox\currentcolumnbox
+ \vskip\dimexpr\openstrutdepth-\scratchdepth\relax
+ \prevdepth\openstrutdepth % \strutdp
+ \vfill}}%
+ \strc_notes_check_if_bottom_present
+ %\ifconditional\c_notes_bottom_present \else
+ % \dimen0\ht\firstcolumnbox % ??
+ %\fi
+ \or
+ % 1 = normal
+ \advance\d_page_mul_balance_target\maxdepth
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
+ {\unvbox\currentcolumnbox}}%
+ \or
+ % 2 = baseline
+ % the columns are on top of the baseline
+ \fi
+ \else
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \unvbox\currentcolumnbox % wel of niet \unvbox ?
+ \vfill
+ \fi}}%
+ \dohandleallcolumns
+ {\ht\currentcolumnbox\d_page_mul_balance_target}% redundant
+ \fi
+ \setbox\b_page_mul_preceding\vbox{\page_mul_flush_packaged_columns_continued}%
+ \page_otr_construct_and_shipout\box\b_page_mul_preceding
+ \page_otr_command_set_hsize
+ \page_otr_command_set_vsize
+ \page_mul_flush_floats
+ \unvbox\b_page_mul_preceding_rest_of_page
+ % \penalty\outputpenalty % gaat gruwelijk mis in opsommingen
+ \egroup}
+
+%D And this is the balancing stuff. Again, part of the routine is dedicated to
+%D handling ragged bottoms, but here we also see some handling concerning the
+%D stretching of columns. We set \type {\widowpenalty} at~0, which enables us to
+%D balance columns with few lines. The use of \type {\box2} and \type {\box4}
+%D garantees a more robust check when skips are used.
+
+\newbox \b_page_mul_balance_content
+\newbox \b_page_mul_balance_first_column
+\newbox \b_page_mul_balance_column
+\newconstant \c_page_mul_balance_tries_max
+\newcount \c_page_mul_balance_tries
+\newdimen \d_page_mul_balance_target
+\newdimen \d_page_mul_balance_target_less
+\newdimen \d_page_mul_balance_natural_height
+\newdimen \d_page_mul_balance_regular_height
+\newdimen \d_page_mul_balance_step
+\newdimen \d_page_mul_balance_fuzzyness
+\newdimen \d_page_mul_balance_threshold
+\newconditional\c_page_mul_balance_possible
+
+\c_page_mul_balance_tries_max 250 % 100 is too small when floats are involved
+
+\def\page_mul_routine_balance
+ {\bgroup
+ \page_mul_initialize_variables
+ \widowpenalty\zerocount
+ \setbox\b_page_mul_balance_content\vbox{\unvbox\normalpagebox}%
+ \ifdim\ht\b_page_mul_balance_content>\openlineheight % at least one line
+ \ifnum\c_page_mul_balance_minimum<\plustwo % balance anyway
+ \settrue\c_page_mul_balance_possible
+ \else % check criterium to available lines
+ \getnoflines{\ht\b_page_mul_balance_content}%
+ \divide\noflines \nofcolumns \relax
+ \ifnum\noflines<\c_page_mul_balance_minimum \relax
+ \ifdim\dimexpr\ht\b_page_mul_balance_content+\ht\firsttopcolumnbox+\openlineheight\relax>\makeupheight
+ \settrue\c_page_mul_balance_possible % column exceeding text height
+ \else
+ \setfalse\c_page_mul_balance_possible % it seems to fit
+ \fi
+ \else
+ \settrue\c_page_mul_balance_possible % balance indeed
+ \fi
+ \fi
+ \else
+ \setfalse\c_page_mul_balance_possible % balancing does not make sense
+ \fi
+ \ifconditional\c_page_mul_balance_possible % start balancing, was: \ifdim\ht\b_page_mul_balance_content>\openlineheight
+ \page_mul_balance_try_one
+ \ifinheritcolumns
+ \page_mul_balance_try_two
+ \else
+ \page_mul_balance_try_three
+ \fi
+ \else
+ % a one liner is not properly handled here, so best rewrite the text then
+ \showmessage\m!columns{10}\empty
+ \global\setbox\firstcolumnbox\vbox{\unvbox\b_page_mul_balance_content}%
+ \fi
+ \c_page_mul_routine\c_page_mul_routine_error
+ \baselinebottom % forces depth in separation rule
+ \page_mul_flush_packaged_columns_balanced
+ \page_mul_eject_page
+ \egroup}
+
+\def\page_mul_eject_page
+ {%\ifdim\pagetotal>\textheight
+ % \page_otr_trigger_output_routine % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point)
+ %\else
+ \allowbreak
+ }%\fi}
+
+\def\page_mul_balance_try_one
+ {\d_page_mul_balance_target\dimexpr\ht\b_page_mul_balance_content+\topskip-\baselineskip\relax
+ \dohandleallcolumns
+ {\advance\d_page_mul_balance_target \ht\currenttopcolumnbox}%
+ \divide\d_page_mul_balance_target \nofcolumns
+ \vbadness\plustenthousand
+ \c_page_mul_balance_tries\zerocount
+ \bgroup
+ \ifgridsnapping
+ \d_page_mul_balance_step\lineheight
+ \else
+ \d_page_mul_balance_step\spacingfactor\onepoint % rubish
+ \fi
+ \doloop\page_mul_balance_try_one_attempt
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}%
+ \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax
+ \showmessage\m!columns7\empty
+ \else
+ \showmessage\m!columns8{\the\c_page_mul_balance_tries}%
+ \fi
+ \egroup}
+
+\def\page_mul_balance_try_one_attempt
+ {\advance\c_page_mul_balance_tries \plusone
+ \global\setbox\b_page_mul_preceding_rest_of_page\copy\b_page_mul_balance_content\relax
+ \page_mul_split_first_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target
+ \dohandlemidcolumns
+ {\page_mul_split_current_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target}%
+ \page_mul_split_last_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target
+ \setbox\b_page_mul_balance_first_column\vbox{\unvcopy\firstcolumnbox}%
+ \d_page_mul_balance_natural_height\zeropoint
+ \dohandleallcolumns\page_mul_balance_try_one_attempt_step
+ \advance\d_page_mul_balance_natural_height -.0005pt % (33sp) get rid of accurracy problem, pretty new
+ \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax
+ \exitloop
+ \else\ifdim\d_page_mul_balance_natural_height>\ht\b_page_mul_balance_first_column
+ \advance\d_page_mul_balance_target \d_page_mul_balance_step\relax
+ \else
+ \exitloop
+ \fi\fi}
+
+\def\page_mul_balance_try_one_attempt_step
+ {\setbox\b_page_mul_balance_column\vbox
+ {\unvcopy\currentcolumnbox
+ \unpenalty
+ \unskip
+ \unpenalty
+ \unskip}% maybe better in main splitter
+ \ifdim\ht\b_page_mul_balance_column>\d_page_mul_balance_natural_height
+ \d_page_mul_balance_natural_height\ht\b_page_mul_balance_column
+ \fi}
+
+% We cannot assume that the first column is the tallest, if only because we may
+% have an aborted balance (one line in the first column and a graphic in the
+% second one).
+
+\def\page_mul_balance_try_two
+ {\d_page_mul_balance_target\zeropoint
+ \dohandleallcolumns
+ {\ifdim\ht\currentcolumnbox>\d_page_mul_balance_target
+ \d_page_mul_balance_target\ht\currentcolumnbox
+ \fi}%
+ \d_page_mul_balance_target_less\dimexpr\d_page_mul_balance_target-\openlineheight\relax
+ \dohandleallcolumnscs\page_mul_balance_try_two_step}
+
+\def\page_mul_balance_try_two_step
+ {\d_page_mul_balance_regular_height\ht\currentcolumnbox
+ \d_page_mul_balance_threshold\plusten\openlineheight % funny value
+ \global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
+ {\unvbox\currentcolumnbox
+ \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_threshold
+ \ifdim\d_page_mul_balance_regular_height<\d_page_mul_balance_target
+ \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_target_less
+ \vskip\zeropoint % !!
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi
+ \else
+ \vskip\zeropoint
+ \fi
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi}}
+
+\def\page_mul_balance_try_three
+ {\bgroup
+ \ifstretchcolumns
+ \d_page_mul_balance_target\ht\firstcolumnbox
+ \d_page_mul_balance_fuzzyness\bottomtolerance\ht\firstcolumnbox
+ \setbox\b_page_mul_balance_content\vbox{\unvcopy\lastcolumnbox}%
+ \advance\d_page_mul_balance_target-\htdp\b_page_mul_balance_content\relax
+ \ifdim\d_page_mul_balance_target>\openlineheight\relax
+ \ifdim\d_page_mul_balance_target>\d_page_mul_balance_fuzzyness\relax
+ % \stretchcolumnsfalse % beter good bad than bad good
+ \showmessage\m!columns9\empty
+ \fi
+ \fi
+ \fi
+ \dohandleallcolumnscs\page_mul_balance_try_three_step
+ \egroup}
+
+\def\page_mul_balance_try_three_step
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \box\currentcolumnbox
+ \vfill
+ \fi}}
+
+%D The multicolumn mechanism is incorporated in a \CONTEXT\ interface,
+%D which acts like:
+%D
+%D \starttyping
+%D \startcolumns[n=4,balance=no]
+%D some text
+%D \stopcolumns
+%D \stoptyping
+%D
+%D The setup is optional. The default behaviour of columns can be set
+%D up with:
+%D
+%D \starttyping
+%D \setupcolumns
+%D [n=2,
+%D balance=yes]
+%D \stoptyping
+%D
+%D In this case, stretching is according to the way it's done outside columns
+%D (\type{\inheritcolumnstrue}). Also we can setup the \type{tolerance} within a
+%D column, the \type{distance} between columns and the fixed \type{height} of a
+%D column.
+%D
+%D Here come the routines that handle the placement of column floats. Floats that
+%D are to big migrate to the next column. Floats that are too wide, migrate to the
+%D top of the next page, where they span as much columns as needed. Floats that are
+%D left over from outside the multi||column mode are flushed first. In macro
+%D \type{\page_otr_construct_and_shipout} the topfloats that are left from previous
+%D text should be set.
+%D
+%D When there are some floats in the queue, we inhibit the flushing of floats on top
+%D of columns. The number of waiting floats is preswent in \type{\savednoftopfloats}
+%D and is saved. As long as there are floats waiting, the topfloats are places as if
+%D we are outside multi||column mode. This is neccessary for e.g. multicolumn lists.
+%D
+%D When all those floats are flushed, we switch to the local flushing routine.
+
+% \newbox \floatlist
+% \newbox \savedfloatlist
+%
+% \def\page_floats_column_push_saved
+% {\ifconditional\c_page_floats_some_waiting
+% \showmessage\m!columns6{\the\savednoffloats}%
+% \global\setbox\savedfloatlist\box\floatlist
+% \xdef\page_floats_column_pop_saved
+% {\global\savednoffloats\the\savednoffloats
+% \global\setbox\floatlist\box\savedfloatlist
+% \global\noexpand\settrue\c_page_floats_some_waiting}%
+% \global\savednoffloats\zerocount
+% \global\setfalse\c_page_floats_some_waiting
+% \else
+% \global\let\page_floats_column_pop_saved\relax
+% \fi}
+%
+% \let\page_floats_column_pop_saved\relax
+
+% \def\page_mul_initialize_floats % messy as it adapts everypar
+% {\xdef\globalsavednoffloats{\the\savednoffloats}%
+% \ifnum\globalsavednoffloats>\zerocount
+% \setglobalcolumnfloats % hm, we always push so this never happens
+% \else
+% \setlocalcolumnfloats
+% \fi}
+
+ \def\page_mul_initialize_floats % messy as it adapts everypar, we need to adapt this
+ {\setlocalcolumnfloats}
+
+ \newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now)
+ \newtoks \everylocalcolumnfloatspar
+
+ \unexpanded\def\page_mul_command_flush_floats
+ {\ifconditional\onlylocalcolumnfloats
+ \doflushcolumnfloats
+ \else
+ \page_one_command_flush_floats
+ \fi}
+
+ \unexpanded\def\page_mul_command_check_if_float_fits
+ {\ifconditional\onlylocalcolumnfloats
+ \docolumnroomfloat
+ \fi}
+
+ \unexpanded\def\page_mul_command_flush_saved_floats
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_saved_floats
+ \fi}
+
+ \unexpanded\def\page_mul_command_flush_top_insertions
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_top_insertions
+ \fi}
+
+ \appendtoks
+ \flushnotes
+ \page_mul_flush_float
+ %\flushmargincontents
+ \checkindentation
+ \to \everylocalcolumnfloatspar
+
+ \def\setlocalcolumnfloats
+ {\settrue\onlylocalcolumnfloats
+ \everypar\everylocalcolumnfloatspar
+ \let\page_mul_flush_float \doflushcolumnfloat
+ \let\page_mul_flush_floats\doflushcolumnfloats}
+
+ \def\setglobalcolumnfloats
+ {\setfalse\onlylocalcolumnfloats
+ \reseteverypar
+ \let\page_mul_flush_float \relax
+ \let\page_mul_flush_floats\noflushcolumnfloats}
+
+ % \def\noflushcolumnfloats
+ % {\bgroup
+ % \xdef\localsavednoffloats{\the\savednoffloats}%
+ % \global\savednoffloats\globalsavednoffloats
+ % \page_otr_command_flush_top_insertions
+ % \xdef\globalsavenoffloats{\the\savednoffloats}%
+ % \ifnum\globalsavednoffloats=\zerocount
+ % \setlocalcolumnfloats
+ % \fi
+ % \global\savednoffloats\localsavednoffloats
+ % \egroup}
+ %
+ \def\noflushcolumnfloats{\doflushcolumnfloats} % not yet redone
+
+%D We need to calculate the amount of free space in a columns. When there is not
+%D enough room, we migrate the float to the next column. These macro's are
+%D alternatives (and look||alikes) of \type {\doroomfloat}. When a float is to wide,
+%D for one column, it is moved to the top of the next page. Of course such moved
+%D floats have to be taken into account when we calculate the available space. It's
+%D a pitty that such things are no integral part of \TEX.
+
+ \def\getcolumnstatus#1#2#3%
+ {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi
+ \dimen2=\zeropoint
+ \count255=\zerocount
+ \dimen8=\makeupheight
+ \advance\dimen8 -\d_page_mul_preceding_height
+ \def\dogetcolumnstatus
+ {\advance\count255 \plusone
+ \advance\dimen2 \ht\currenttopcolumnbox
+ \advance\dimen2 \dp\currenttopcolumnbox
+ \dimen4\dimen2
+ \advance\dimen4 \dimen0
+ \dimen6=\count255\dimen8
+ \ifdim\dimen4>\dimen6
+ \else
+ \let\dogetcolumnstatus\relax
+ \fi}%
+ \dohandleallcolumns{\dogetcolumnstatus}%
+ \ifnum\count255=0 \count255=1 \fi
+ #1=\count255
+ #2=\dimen4
+ #3=\dimen6 }
+
+ \def\getinsertionheight
+ {\ifdim\pagegoal<\maxdimen
+ \bgroup
+ \dimen0=\makeupheight
+ \advance\dimen0 -\pagegoal
+ \xdef\insertionheight{\the\dimen0}%
+ \egroup
+ \else
+ \global\let\insertionheight\zeropoint
+ \fi}
+
+ \def\docolumnroomfloat
+ {\ifpostponecolumnfloats
+ \global\setfalse\c_page_floats_room
+ \else\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
+ \else
+ \bgroup
+ \getcolumnstatus{\count255}{\dimen0}{\dimen2}%
+ \page_floats_get_info\s!text
+ \setbox\scratchbox\vbox % tricky met objecten ?
+ {\blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}% copy?
+ \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher
+ \ifdim\dimen0>\dimen2
+ \global\setfalse\c_page_floats_room
+ \else
+ \global\settrue\c_page_floats_room
+ \fi
+ \ifdim\floatwidth>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\setfalse\c_page_floats_room
+ \fi
+ \egroup
+ \fi\fi}
+
+%D Flushing one float is done as soon as possible, i.e. \type {\everypar}.
+%D This means that (at the moment) sidefloats are not supported (overulled)!
+
+ \newif\ifflushingcolumnfloats \flushingcolumnfloatstrue
+
+ \def\doflushcolumnfloat
+ {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifconditional\c_page_floats_some_waiting
+ \doflushcolumnfloatindeed
+ \fi\fi\fi}
+
+ \def\doflushcolumnfloatindeed
+ {\bgroup
+ \forgetall
+ \let\doflushcolumnfloat\relax
+ \getcolumnstatus{\mofcolumns}{\dimen0}{\dimen2}%
+ \ifdim\dimen0>\zeropoint
+ \page_floats_get_info\s!text
+ \ifdim\floatwidth>\hsize
+ % dropped ?
+ \else
+ \setbox2\vbox
+ {\blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}%
+ \advance\dimen0 \ht2
+ \ifdim\dimen0>\dimen2
+ \ifnum\mofcolumns<\nofcolumns
+ \advance\mofcolumns \plusone
+ \ifdim\ht\currenttopcolumnbox=\zeropoint
+ \page_floats_flush\s!text\plusone
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox{\box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \dimen4=\htdp\currenttopcolumnbox
+ \global\advance\vsize -\dimen4
+ \advance\dimen4 -\pagegoal
+ \pagegoal-\dimen4
+ \showmessage\m!columns{12}a%
+ \else
+ \showmessage\m!columns{12}b%
+ \fi
+ \else
+ \showmessage\m!columns{12}c%
+ \fi
+ \else
+ \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen
+ \par
+ \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte
+ \nobreak
+ \blank[\rootfloatparameter\c!spacebefore]
+ \nobreak
+ \fi
+ \page_floats_flush\s!text\plusone
+ \page_otr_command_flush_float_box
+ \blank[\rootfloatparameter\c!spaceafter]
+ \fi
+ \fi
+ \fi
+ \egroup}
+
+%D This one looks complicated. Upto \type{\nofcolumns} floats are placed,
+%D taking the width of a float into account. This routine can be improved
+%D on different ways:
+%D
+%D \startitemize[intro,packed]
+%D \item taking into account some imaginary baseline, just to get the
+%D captions in line
+%D \item multipass flushing until as many floats are displaced as possible
+%D \stopitemize
+%D
+%D When handling lots of (small) floats spacing can get worse because of
+%D lining out the columns.
+
+ \def\doflushcolumnfloats
+ {\ifpostponecolumnfloats\else
+ \bgroup
+ \forgetall
+ \ifconditional\c_page_floats_some_waiting
+ \dimen8\zeropoint
+ \dimen4\zeropoint
+ \count0\zerocount % count0 can be used local
+ \count2\nofcolumns % count2 can be used local
+ \dohandleallcolumns
+ {\ifnum\count0>\zerocount % the wide one's reserved space
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\copy\currenttopcolumnbox
+ \hbox{\vphantom{\vskip\floatheight}}}% known from previous
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \else
+ \page_floats_get_info\s!text
+ \ifdim\floatwidth>\hsize
+ \dimen0\dimexpr\floatwidth+\d_page_mul_distance+.5pt\relax
+ \dimen2\dimexpr\hsize +\d_page_mul_distance+.5pt\relax
+ \divide\dimen0 \dimen2
+ \count0\dimen0
+ \advance\count0 \plusone
+ \ifnum\count0>\count2
+ \count0\zerocount
+ \else
+ \dimen0\dimexpr\count0\hsize+\count0\d_page_mul_distance-\d_page_mul_distance\relax
+ \page_floats_flush\s!text\plusone
+ \ifdim\floatwidth>\makeupwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ \global\setbox\floatbox\hbox to \dimen0
+ {\processaction[\rootfloatparameter\c!location] % how easy to forget
+ [ \v!left=>\box\floatbox\hss,
+ \v!right=>\hss\box\floatbox,
+ \s!default=>\hss\box\floatbox\hss,
+ \s!unknown=>\hss\box\floatbox\hss]}%
+ \fi
+ \showmessage\m!columns{13}\empty
+ \else
+ \page_floats_flush\s!text\plusone
+ \ifdim\floatwidth>\makeupwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ % \showmessage\m!columns{13}\empty
+ \fi
+ \ifdim\ht\floatbox>\zeropoint\relax
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\box\currenttopcolumnbox % was copy
+ \box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \fi
+ \dimen6\htdp\currenttopcolumnbox
+ \fi
+ \ifdim\dimen4<\ht\currenttopcolumnbox
+ \dimen4\ht\currenttopcolumnbox
+ \fi
+ \advance\dimen8 \dimen6
+ \advance\count2 \minusone
+ \advance\count0 \minusone }%
+ \page_otr_command_set_vsize
+ \global\advance\vsize -\dimen8
+ \pagegoal\vsize
+ \else
+ % \page_mul_command_flush_floats % does not snap!
+ \fi
+ \egroup
+ \fi}
+
+%D The next macro can be used to flush floats in the current stream. No
+%D width checking is (yet) done.
+
+ \def\insertcolumnfloats
+ {\doloop
+ {\ifconditional\c_page_floats_some_waiting
+ \bgroup
+ \forgetall
+ % no check for width
+ \page_floats_get
+ \blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\copy\floatbox}
+ \blank[\rootfloatparameter\c!spaceafter]
+ \egroup
+ \else
+ \exitloop
+ \fi}}
+
+%D This were the multi||column routines. They can and need to be improved
+%D but at the moment their behaviour is acceptable.
+%D
+%D One inprovement can be to normalize the height of floats to $ n \times $
+%D \type {\lineheight} with a macro like:
+%D
+%D \starttyping
+%D \normalizevbox{...}
+%D \stoptyping
+
+% border case, should fit on one page
+%
+% \startcolumns
+% 1 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{1}}
+% 2 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{2}}
+% 3 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{3}}
+% \stopcolumns
+
+ % \def\backgroundfinishcolumnbox
+ % {\doifelseinset\@@kloffset{\v!none,\v!overlay}
+ % {\let\@@kloffset\!!zeropoint}
+ % {\scratchdimen\@@kloffset
+ % \advance\scratchdimen -\@@klrulethickness
+ % \edef\@@kloffset{\the\scratchdimen}}%
+ % \localframed
+ % [\??kl]
+ % [\c!strut=\v!no,
+ % \c!width=\v!fit,
+ % \c!height=\v!fit,
+ % \c!align=]}
+
+ \def\backgroundfinishcolumnbox
+ {}
+
+% to be reconsidered ... (in any case they need to be unexpandable sinze 2011.12.30)
+
+\unexpanded\def\page_columns_align_option_yes {\stretchcolumnstrue \inheritcolumnsfalse}% todo: new key
+\unexpanded\def\page_columns_align_option_no {\stretchcolumnsfalse\inheritcolumnsfalse}% todo: new key
+\unexpanded\def\page_columns_align_option_text{\stretchcolumnsfalse\inheritcolumnstrue }%
+
+\newtoks\t_page_mul_initialize
+
+\unexpanded\def\startcolumns
+ {\dosingleempty\page_mul_start}
+
+\def\page_mul_start[#1]% %% \startcolumns
+ {\bgroup
+ \ifinsidecolumns
+ \page_mul_start_nop
+ \else
+ \iffirstargument
+ \setupcolumns[#1]%
+ \fi
+ \nofcolumns\columnsparameter\c!n\relax
+ \ifnum\nofcolumns>\plusone
+ \page_mul_start_yes
+ \else
+ \page_mul_start_nop
+ \fi
+ \fi}
+
+\unexpanded\def\page_mul_start_nop
+ {\let\stopcolumns\page_mul_stop_nop}
+
+\unexpanded\def\page_mul_stop_nop
+ {\egroup}
+
+\unexpanded\def\page_mul_start_yes
+ {\whitespace
+ \begingroup
+ \let\stopcolumns\page_mul_stop_indeed
+ \global\insidecolumnstrue
+ \the\t_page_mul_initialize
+ %
+ \flushnotes
+ \begingroup
+ %
+ \d_page_mul_leftskip\leftskip
+ \d_page_mul_rightskip\rightskip
+ \leftskip\zeropoint
+ \rightskip\zeropoint
+ %
+ \widowpenalty\zerocount % will become option
+ \clubpenalty \zerocount % will become option
+ %
+ \page_floats_column_push_saved
+ %
+ \ifdim\dimexpr\pagetotal+\parskip+\openlineheight\relax<\pagegoal
+ \allowbreak
+ \else
+ \break % sometimes fails
+ \fi
+ \appendtoks
+ \topskip1\topskip % best a switch
+ \to \everybodyfont
+ \the\everybodyfont % ugly here
+ \saveinterlinespace % ugly here
+ %
+ \initializecolumns\nofcolumns
+ %
+ \hangafter\zerocount
+ \hangindent\zeropoint
+ \reseteverypar
+ \ifdim\pagetotal=\zeropoint \else
+ \verticalstrut
+ \vskip-\struttotal
+ \fi
+ \global\savedpagetotal\pagetotal
+ \setupoutputroutine[\s!multicolumn]%
+ \c_page_mul_routine\c_page_mul_routine_intercept
+ \page_otr_trigger_output_routine % no \holdinginserts=1, can make footnote disappear !
+ \global\d_page_mul_preceding_height\ht\b_page_mul_preceding
+ \c_page_mul_routine\c_page_mul_routine_continue
+ \page_mul_initialize_floats
+ \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}%
+ \checkbegincolumnfootnotes
+ \page_otr_command_set_hsize
+ \page_otr_command_set_vsize}
+
+\setnewconstant\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
+
+\unexpanded\def\page_mul_stop_indeed
+ {\relax
+ \ifnum\multicolumnendsyncmethod=\plustwo
+ \synchronizeoutput
+ \else
+ % don't collapse these
+ \vskip \lineheight
+ \vskip-\lineheight % take footnotes into account
+ \fi
+ \doflushcolumnfloat % added recently
+ %\doflushcolumnfloats % no, since it results in wrong top floats
+ \flushnotes % before start of columns
+ \par
+ \ifbalancecolumns
+ \ifnum\multicolumnendsyncmethod=\plusone
+ \c_page_mul_routine\c_page_mul_routine_continue
+ \goodbreak
+ \fi
+ \c_page_mul_routine\c_page_mul_routine_balance
+ \else
+ \goodbreak
+ \fi
+ % still the multi column routine
+ \page_otr_trigger_output_routine % the prevdepth is important, try e.g. toclist in
+ \prevdepth\zeropoint % columns before some noncolumned text text
+ %
+ \c_page_mul_routine\c_page_mul_routine_regular
+ %
+ \ifvoid\b_page_mul_preceding\else
+ \unvbox\b_page_mul_preceding
+ \fi
+ \global\d_page_mul_preceding_height\zeropoint
+ \endgroup % here
+ \nofcolumns\plusone
+ \page_otr_command_set_vsize
+ \checkendcolumnfootnotes
+ \dosomebreak\allowbreak
+ \page_floats_column_pop_saved
+ %
+ \global\insidecolumnsfalse
+ \endgroup
+ \egroup}%
+
+\appendtoks
+ \edef\p_option{\columnsparameter\c!option}%
+ \ifx\p_option\v!background
+ \let\finishcolumnbox\backgroundfinishcolumnbox
+ \fi
+ \d_page_mul_offset\columnsparameter\c!offset\relax
+ \edef\p_command{\columnsparameter\c!command}%
+ \ifx\p_command\empty \else
+ \let\postprocesscolumnline\p_command
+ \fi
+ \edef\p_height{\columnsparameter\c!height}%
+ \ifx\p_height\empty
+ \d_page_mul_forced_height\textheight
+ \heightencolumnsfalse
+ \else
+ \d_page_mul_forced_height\p_height\relax
+ \heightencolumnstrue
+ \fi
+ \edef\p_direction{\columnsparameter\c!direction}%
+ \ifx\p_direction\v!right
+ \setfalse\c_page_mul_reverse
+ \else
+ \settrue\c_page_mul_reverse
+ \fi
+ \edef\p_balance{\columnsparameter\c!balance}%
+ \ifx\p_balance\v!yes
+ \balancecolumnstrue
+ \else
+ \balancecolumnsfalse
+ \fi
+ % % this won't work (blocked by check for overloading; too fuzzy anyway)
+ % \installalign\v!yes {\page_columns_align_option_yes }% \stretchcolumnstrue \inheritcolumnsfalse
+ % \installalign\v!no {\page_columns_align_option_no }% \stretchcolumnsfalse\inheritcolumnsfalse
+ % \installalign\v!text{\page_columns_align_option_text}% \stretchcolumnsfalse\inheritcolumnstrue
+ % %
+ \stretchcolumnsfalse
+ \inheritcolumnstrue
+ \edef\p_align{\columnsparameter\c!align}%
+ \ifx\p_align\empty \else
+ \setupalign[\p_align]%
+ \fi
+ \edef\p_tolerance{\columnsparameter\c!tolerance}%
+ \ifx\p_tolerance\empty \else
+ \setuptolerance[\p_tolerance]%
+ \fi
+ \edef\p_blank{\columnsparameter\c!blank}%
+ \ifx\p_blank\empty \else
+ \setupblank[\p_blank]%
+ \fi
+ \ifdim\s_spac_whitespace_parskip>\zeropoint\relax
+ \setupwhitespace[\p_blank]%
+ \fi
+ \c_page_mul_balance_minimum\columnsparameter\c!ntop\relax
+ \edef\p_page_mul_rule{\columnsparameter\c!rule}%
+ \expandnamespacemacro\??columnseparators\p_page_mul_rule\s!unknown
+\to \t_page_mul_initialize
+
+%D Columns breaks
+
+\installcolumnbreakmethod \s!multicolumn \v!preference
+ {\goodbreak}
+
+% \installcolumnbreakmethod \s!multicolumn \v!yes
+% {\vskip\textheight
+% \penalty-200 % we can mark and intercept this
+% \vskip-\textheight}
+
+\installcolumnbreakmethod \s!multicolumn \v!yes
+ {\vskip .5\pagegoal
+ \penalty-200 % we can mark and intercept this
+ \vskip-.5\pagegoal}
+
+%D Next we initialize the lot:
+
+\setupcolumns
+ [\c!n=2,
+ \c!ntop=1,
+ \c!command=,
+ \c!direction=\v!right,
+ \c!rule=\v!off,
+ \c!tolerance=\v!tolerant,
+ \c!distance=1.5\bodyfontsize, % influenced by switching
+ \c!height=,
+ \c!balance=\v!yes,
+ \c!align=\v!text,
+ \c!blank={\v!line,\v!fixed},
+ \c!option=,
+ \c!rulethickness=\linewidth,
+ \c!offset=.5\bodyfontsize]
+
+%D New: only at start of columns; may change ! Rather interwoven and therefore
+%D to be integrated when the multi column modules are merged.
+
+ \unexpanded\def\setupcolumnspan[#1]%
+ {\getparameters[\??ks][#1]}
+
+ \presetlocalframed
+ [\??ks]
+
+ \setupcolumnspan
+ [\c!n=2,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+ \newbox\b_page_columns_span \let\page_mul_postprocess_spanbox\gobbleoneargument
+
+ \unexpanded\def\startcolumnspan
+ {\dosingleempty\dostartcolumnspan}
+
+ \unexpanded\def\stopcolumnspan
+ {\egroup}
+
+ \def\dostartcolumnspan[#1]%
+ {\bgroup
+ \setupcolumnspan[#1]%
+ \forgetall
+ \ifinsidecolumns
+ \advance\hsize \d_page_mul_distance
+ \hsize\@@ksn\hsize
+ \advance\hsize -\d_page_mul_distance
+ \fi
+ \dowithnextboxcs\dofinishcolumnsetspan\vbox\bgroup
+ %\topskipcorrection % becomes an option !
+ \EveryPar{\begstrut\EveryPar{}}} % also !
+
+ \def\dofinishcolumnsetspan
+ {\setbox\b_page_columns_span\flushnextbox
+ \ifinsidecolumns\wd\b_page_columns_span\hsize\fi
+ \page_mul_postprocess_spanbox\b_page_columns_span
+ \scratchdimen\ht\b_page_columns_span
+ \setbox\b_page_columns_span\hbox % depth to be checked, probably option!
+ {\localframed[\??ks][\c!offset=\v!overlay]{\box\b_page_columns_span}}%
+ \ht\b_page_columns_span\scratchdimen
+ \dp\b_page_columns_span\strutdp
+ \wd\b_page_columns_span\hsize
+ \ifinsidecolumns
+ \ifnum\@@ksn>1
+ \page_otr_command_set_vsize
+ \dohandleallcolumns
+ {\ifnum\currentcolumn>\@@ksn\else
+ \global\setbox\currenttopcolumnbox=\vbox
+ {\ifnum\currentcolumn=1
+ \snaptogrid\vbox{\copy\b_page_columns_span}
+ \else
+ \snaptogrid\vbox{\vphantom{\copy\b_page_columns_span}}
+ \fi}%
+ \wd\currenttopcolumnbox\hsize
+ \global\advance\vsize -\ht\currenttopcolumnbox
+ \fi}
+ \pagegoal\vsize
+ \else
+ \snaptogrid\vbox{\box\b_page_columns_span}
+ \fi
+ \else
+ \snaptogrid\vbox{\box\b_page_columns_span}
+ \fi
+ \endgraf
+ \ifvmode\prevdepth\strutdp\fi
+ \egroup}
+
+%D Undocumented and still under development.\ifdefined\startsimplecolumns \else
+
+\unexpanded\def\startsimplecolumns
+ {\dosingleempty\page_mul_simple_start}
+
+\def\page_mul_simple_start[#1]%
+ {\bgroup
+ \setsimplecolumnshsize[#1]%
+ \nopenalties
+ \setbox\scratchbox\vbox\bgroup
+ \forgetall} % \blank[\v!disable]
+
+\unexpanded\def\stopsimplecolumns
+ {\removebottomthings
+ \egroup
+ \rigidcolumnbalance\scratchbox
+ \egroup}
+
+\unexpanded\def\setsimplecolumnshsize[#1]%
+ {\getdummyparameters
+ [\c!width=\hsize,
+ \c!distance=1.5\bodyfontsize,
+ \c!n=2,
+ \c!lines=0,
+ #1]%
+ \edef\rigidcolumnlines
+ {\directdummyparameter\c!lines}%
+ \setrigidcolumnhsize
+ {\directdummyparameter\c!width}%
+ {\directdummyparameter\c!distance}%
+ {\directdummyparameter\c!n}}
+
+%D Moved here:
+
+\unexpanded\def\page_mul_command_test_column
+ {\dodoubleempty\page_mul_command_test_column_indeed}
+
+\unexpanded\def\page_mul_command_test_column_indeed[#1][#2]% works on last column
+ {\page_otr_command_flush_top_insertions\endgraf
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal<\pagegoal
+ \d_page_tests_test\dimexpr
+ \pagegoal
+ -\pagetotal
+ \ifdim\lastskip<\parskip+\parskip\fi
+ \ifsecondargument+#2\fi
+ \relax
+ \getrawnoflines\d_page_tests_test % (raw)
+ \ifnum#1>\noflines
+ \column
+ \fi
+ \else
+ \penalty-\plustenthousand % (untested)
+ \fi
+ \fi}
+
+%D but fragile anyway.
+
+\let\page_mul_command_package_contents\page_one_command_package_contents
+\let\page_mul_command_flush_float_box \page_one_command_flush_float_box
+
+\defineoutputroutine
+ [\s!multicolumn]
+ [\s!page_otr_command_routine =\page_mul_command_routine,
+ \s!page_otr_command_package_contents =\page_mul_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_mul_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_mul_command_set_hsize,
+ \s!page_otr_command_next_page =\page_mul_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_mul_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_mul_command_synchronize_hsize,
+ % \s!page_otr_command_set_top_insertions =\page_mul_command_set_top_insertions,
+ % \s!page_otr_command_set_bottom_insertions =\page_mul_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions =\page_mul_command_flush_top_insertions,
+ % \s!page_otr_command_flush_bottom_insertions=\page_mul_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_mul_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_mul_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_mul_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats=\page_mul_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_mul_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_mul_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_mul_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_mul_command_flush_saved_floats,
+ % \s!page_otr_command_flush_margin_blocks =\page_mul_command_flush_margin_blocks, % not used
+ \s!page_otr_command_test_column =\page_mul_command_test_column
+ ]
+
+\protect \endinput