%% This is part of OpTeX project, see http://petr.olsak.net/optex \_codedecl \begmulti {Balanced columns <2020-03-26>} % preloaded in format \_doc ----------------------------- This code is documented in detail in the \"\TeX/book naruby", pages 244--246, free available, \url{http://petr.olsak.net/tbn.html}, but in Czech. Roughly speaking, macros complete all material between `\begmulti` and `\endmulti` into one `\vbox 6`. Then the macro measures the amount of free space at the current page using `\pagegoal` and `\pagtotal` and does `\vsplit` of `\vbox 6` to columns with height of such free space. This is done only if we have enought amount of material in `\vbox 6` to fill full page by columns. This is repeated in loop until we have less amount of material in `\vbox 6`. Then we run `\_balancecolumns` which balances the last part of columns. Each part of printed material is distributed to main vertical list as `\hbox{}` and we need not do any change in the output routine. If you have paragraphs in `\begmulti`... `\endmulti` environment then you may say `\raggedright` inside this environment and you can re-assign `\widowpenalty` and `\clubppenalty` (they are set to 10000 in \OpTeX/). \_cod ----------------------------- \_def\_multiskip{\_medskip} % space above and below \begmulti...\endmulti \_newcount\_mullines \_def\_begmulti #1 {\_par\_bgroup\_wipeepar\_multiskip\_penalty0 \_def\_Ncols{#1} \_setbox6=\_vbox\_bgroup\_penalty0 %% \hsize := column width = (\hsize+\colsep) / n - \colsep \_advance\_hsize by\_colsep \_divide\_hsize by\_Ncols \_advance\_hsize by-\_colsep \_mullines=0 \_def\par{\_ifhmode\_endgraf\_global\_advance\_mullines by\_prevgraf\_fi}% } \_def\_endmulti{\_vskip-\_prevdepth\_vfil \_ea\_egroup\_ea\_baselineskip\_the\_baselineskip\_relax \_dimen0=.8\_maxdimen \_tmpnum=\_dimen0 \_divide\_tmpnum by\_baselineskip \_splittopskip=\_baselineskip \_setbox1=\_vsplit6 to0pt %% \dimen1 := the free space on the page \_ifdim\_pagegoal=\_maxdimen \_dimen1=\_vsize \_corrsize{\_dimen1} \_else \_dimen1=\_pagegoal \_advance\_dimen1 by-\_pagetotal \_fi \_ifdim \_dimen1<2\_baselineskip \_vfil\_break \_dimen1=\_vsize \_corrsize{\_dimen1} \_fi \_ifnum\_mullines<\_tmpnum \_dimen0=\_ht6 \_else \_dimen0=.8\_maxdimen \_fi \_divide\_dimen0 by\_Ncols \_relax %% split the material to more pages? \_ifdim \_dimen0>\_dimen1 \_splitpart \_else \_balancecolumns \_fi % only balancing \_multiskip\_egroup } \_def\_makecolumns{\_bgroup % full page, destination height: \dimen1 \_vbadness=20000 \_setbox1=\_hbox{}\_tmpnum=0 \_loop \_ifnum\_Ncols>\_tmpnum \_advance\_tmpnum by1 \_setbox1=\_hbox{\_unhbox1 \_vsplit6 to\_dimen1 \_hss} \_repeat \_hbox{}\_nobreak\_vskip-\_splittopskip \_nointerlineskip \_line{\_unhbox1\_unskip} \_dimen0=\_dimen1 \_divide\_dimen0 by\_baselineskip \_multiply\_dimen0 by\_Ncols \_global\_advance\_mullines by-\_dimen0 \_egroup } \_def\_splitpart{% \_makecolumns % full page \_vskip 0pt plus 1fil minus\_baselineskip \_break \_ifnum\_mullines<\_tmpnum \_dimen0=\_ht6 \_else \_dimen0=.8\_maxdimen \_fi \_divide\_dimen0 by\_Ncols \_relax \_ifx\_balancecolumns\_flushcolumns \_advance\_dimen0 by-.5\_vsize \_fi \_dimen1=\_vsize \_corrsize{\_dimen1}\_dimen2=\_dimen1 \_advance\_dimen2 by-\_baselineskip %% split the material to more pages? \_ifvoid6 \_else \_ifdim \_dimen0>\_dimen2 \_ea\_ea\_ea \_splitpart \_else \_balancecolumns % last balancing \_fi \_fi } \_def\_balancecolumns{\_bgroup \_setbox7=\_copy6 % destination height: \dimen0 \_ifdim\_dimen0>\_baselineskip \_else \_dimen0=\_baselineskip \_fi \_vbadness=20000 \_def\_tmp{% \_setbox1=\_hbox{}\_tmpnum=0 \_loop \_ifnum\_Ncols>\_tmpnum \_advance\_tmpnum by1 \_setbox1=\_hbox{\_unhbox1 \_ifvoid6 \_hbox to\_wd6{\_hss}\_else \_vsplit6 to\_dimen0 \_fi\_hss} \_repeat \_ifvoid6 \_else \_advance \_dimen0 by.2\_baselineskip \_setbox6=\_copy7 \_ea \_tmp \_fi}\_tmp \_hbox{}\_nobreak\_vskip-\_splittopskip \_nointerlineskip \_hbox to\_hsize{\_unhbox1\_unskip}% \_egroup } \_def\_corrsize #1{%% #1 := #1 + \splittopskip - \topskip \_advance #1 by \_splittopskip \_advance #1 by-\_topskip } \_public \begmulti \endmulti ; \_endcode % -------------------------------------