diff options
Diffstat (limited to 'tex/context/base/page-mul.tex')
-rw-r--r-- | tex/context/base/page-mul.tex | 1566 |
1 files changed, 1566 insertions, 0 deletions
diff --git a/tex/context/base/page-mul.tex b/tex/context/base/page-mul.tex new file mode 100644 index 000000000..40f211090 --- /dev/null +++ b/tex/context/base/page-mul.tex @@ -0,0 +1,1566 @@ +%D \module +%D [ file=page-mul, % was: core-mul +%D version=1998.03.15, +%D title=\CONTEXT\ OTR Macros, +%D subtitle=Multi Column Output, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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 OTR Macros / Simple Multi Column} + +%D This module is mostly a copy from the original multi column +%D routine as implemented in \type {core-mul}. When the main +%D OTR macro's were isolated in modules and when Kluwer +%D Academic Publishers needed more advanced footnote support, +%D this module became part of the OTR modules. As a result this +%D module is no longer generic. + +\unprotect + +% TO DO ! + +\let\OTRMULsetvsize \OTRONEsetvsize +\let\OTRMULsethsize \OTRONEsethsize +\let\OTRMULsetfootnotehsize \OTRONEsetfootnotehsize +\let\OTRMULdopagecontents \OTRONEdopagecontents +\let\OTRMULfinalsidefloatoutput\OTRONEfinalsidefloatoutput +\let\OTRMULflushfloatbox \OTRONEflushfloatbox + +\let\OTRMULdosettopinserts \relax +\let\OTRMULdosetbotinserts \relax +\let\OTRMULdotopinsertions \relax +\let\OTRMULdobotinsertions \relax +\let\OTRMULdosetbothinserts \relax + +\newtoks \OTRMULoutput + +% check \count<insert> multiplications + +% some day try this in balancing routine +% +% \ifdim\pagetotal>\pagegoal +% \eject +% \else +% \goodbreak +% \fi + +%D The following macro's implement a multi||column output +%D routine. The original implementation was based on Donald +%D Knuth's implementation, which was adapted by Craig Platt to +%D support balancing of the last page. I gradually adapted +%D Platt's version to our needs but under certain +%D circumstances things still went wrong. I considered all +%D calls to Platt's \type{\balancingerror} as undesirable. + +%D This completely new implementation can handle enough +%D situations for everyday documents, but is still far from +%D perfect. While at the moment the routine doesn't support +%D all kind of floats, it does support: +%D +%D \startopsomming[opelkaar] +%D \som an unlimitted number of columns +%D \som ragged or not ragged bottoms +%D \som optional balancing without \type{\balancingerrors} +%D \som different \type{\baselineskips}, \type{\spacing}, +%D \type{\topskip} and \type{\maxdepth} +%D \som left- and right indentation, e.g. within lists +%D \som moving columns floats to the next column or page +%D \som handling of floats that are to wide for a columns +%D \stopopsomming +%D +%D One could wonder why single and multi||columns modes are +%D still separated. One reason for this is that \TeX\ is not +%D suited well for handling multi||columns. As a result, the +%D single columns routines are more robust. Handling one +%D column as a special case of multi||columns is posible but at +%D the cost of worse float handling, worse page breaking, +%D worse etc. Complicated multi||column page handling should +%D be done in \kap{DTP}||systems anyway. +%D +%D There are three commands provided for entering and leaving +%D multi||column mode and for going to the next column: +%D +%D \interface \type{\beginmulticolumns} \\ \\ +%D \interface \type{\endmulticolumns} \\ \\ +%D \interface \type{\ejectcolumn} \\ \\ +%D +%D This routines are sort of stand||alone. They communicate +%D with the rest of \CONTEXT\ by means of some interface +%D macro's, which we only mention. +%D +%D \interface \type{\nofcolumns} \\ +%D the number of columns \\ +%D \interface \type{\minbalancetoplines} \\ +%D the minimum number op balanced top lines \\ +%D \interface \type{\betweencolumns} \\ +%D the stuff between columns \\ +%D \interface \type{\finaloutput{action}{box}} \\ +%D some kind of \type{\pagebody} and \type{\shipout} \\ +%D +%D \interface \type{\ifbalancecolumns} \\ +%D balancing the colums or not \\ +%D \interface \type{\ifstretchcolumns} \\ +%D ragging the bottom or not \\ +%D +%D \interface \type{\ifheightencolumns} \\ +%D fix the heigh tor not \\ +%D \interface \type{\fixedcolumnheight} \\ +%D the optional fixed height \\ +%D +%D \interface \type{\ifinheritcolumns} \\ +%D handle ragging or not \\ +%D \interface \type{\ifr@ggedbottom} \\ +%D use ragged bottoms \\ +%D \interface \type{\ifb@selinebottom} \\ +%D put the bottom line on the baseline \\ +%D \interface \type{\ifnormalbottom} \\ +%D put the bottom line at the baseline \\ +%D +%D \interface \type{\ifreversecolumns} \\ +%D reverse the order in wich columns are flushed \\ +%D +%D \interface \type{\usercolumnwidth} \\ +%D the calculated width of a column \\ +%D \interface \type{\columntextwidth} \\ +%D the maximum width of a column \\ +%D \interface \type{\columntextheight} \\ +%D the minimum width of a column \\ +%D +%D \interface \type{\spacingfactor} \\ +%D the spacing factor \\ +%D \interface \type{\bodyfontsize} \\ +%D the (local) bodyfontsize \\ +%D \interface \type{\openlineheight} \\ +%D the lineheight (including \type{\spacing}) \\ +%D +%D \interface \type{\Everybodyfont} \\ +%D communication channel to font switching routines \\ +%D +%D \interface \type{\global\settopskip} \\ +%D set \type{\topskip} \\ +%D \interface \type{\setvsize} \\ +%D set \type{\vsize} and \type{\pagegoal} \\ +%D \interface \type{\sethsize} \\ +%D set \type{\hsize} \\ +%D +%D \interface \type{\flushcolumnfloats} \\ +%D push saved column floats (next page) \\ +%D \interface \type{\flushcolumnfloat} \\ +%D push saved column floats (next column) \\ +%D \interface \type{\setcolumnfloats} \\ +%D initialize column floats \\ +%D +%D \interface \type{\finishcolumnbox} \\ +%D do something special (a hook) \\ +%D \interface \type{\postprocesscolumnpagebox} \\ +%D do something with each columnbox (also a hook) \\ +%D \interface \type{\postprocesscolumnbox} \\ +%D do something with each columnbox (also a hook) \\ +%D \interface \type{\postprocesscolumnline} \\ +%D do something with each columnline (also a hook) \\ +%D \interface \type{\currentcolumn} \\ +%D the current column \\ +%D +%D These interface macro's are called upon or initialized +%D by the multi||column macro's. + +%D A lot of footnote stuff added! + +\def\finalcolumntextwidth {\zetbreedte} +\def\finalcolumntextheight {\teksthoogte} +\def\columntextwidth {\zetbreedte} +\def\columntextheight {\teksthoogte} +\def\usercolumnwidth {\tekstbreedte} +\def\columntextoffset {\!!zeropoint} + +\def\fixedcolumnheight {\teksthoogte} +\def\betweencolumns {\hskip\bodyfontsize} + +\let\setcolumnfloats \relax % in CONTEXT used for floats +\let\flushcolumnfloats \relax % in CONTEXT used for floats +\let\flushcolumnfloat \relax % in CONTEXT used for floats +\let\finishcolumnbox \relax % in CONTEXT used for backgrounds + +% %D In fact, the column height and width are set by means of +% %D two macro's. One can change their meaning if needed: +% +% \def\setcolumntextheight% +% {\def\columntextheight{\teksthoogte}} +% +% \def\setcolumntextwidth% +% {\def\columntextwidth{\zetbreedte}} + +%D Both macros are redefined in \CONTEXT\ when backgrounds +%D are applied to columns. The final values are used when +%D flushing the columns. + +\newtoks\singlecolumnout % remove that one + +%D It's more convenient to use \type {\columnwidth} instead +%D of messing around with boxes each time. + +\newdimen\columnwidth +\newdimen\gutterwidth + +\def\determinecolumnwidth% + {\bgroup + \setbox\scratchbox=\hbox + {\setcolumnhsize + \global\columnwidth=\usercolumnwidth + \global\gutterwidth=\intercolumnwidth}% + \egroup} + +%D Going to a new columns is done by means of a +%D \type{\ejectcolumn}. The following definition does not +%D always work. + +\def\ejectcolumn% + {\goodbreak + \showmessage{\m!columns}{2}{}} + +%D The next macro should never be called so let's deal with it. +%D There were several solutions to these kind of errors. First +%D we check for a good breakpoint before firing up the +%D multi||column routine (\type{\break} or \type{\allowbreak}). +%D We do the same at the end of the routine +%D (\type{\allowbreak}). These allowances are definitely +%D needed! +%D +%D Some on first sight redundant calls to for instance +%D \type{\setvsize} in the flushing, splitting and balancing +%D macro's can definitely not be omitted! Some are just there +%D to handle situations that only few times arise. One of +%D those can be that the output routine is invoked before +%D everything is taken care of. This happens when we +%D flush (part of) the current page with an \type{\unvbox} +%D with a \type{\pagetotal}~$\approx$ \type{\pagegoal}. One +%D simply cannot balance columns that are just balanced. +%D +%D I hope one never sees the following message. Because it +%D took me a lot of time to develop the multi||columns +%D routines, every (although seldom) warning gives me the +%D creeps! + +\def\balancingerror% + {\showmessage{\m!columns}{3}{}% + \finaloutput\unvbox\normalpagebox} + +\def\OTRMULsometopsfloat{\showmessage{\m!columns}{4}{}\someherefloat} +\def\OTRMULsomebotsfloat{\showmessage{\m!columns}{5}{}\someherefloat} + +\def\OTRMULsomeherefloat{\OTRONEsomeherefloat} + +\def\getinsertionheights\to#1\\% \relax'm + {#1=\!!zeropoint + \def\doaddinsertionheight##1% + {\ifvoid##1\else + \advance#1 by 1\skip##1 + \advance#1 by \ht##1 + \fi}% + \doaddinsertionheight\topins + \doaddinsertionheight\botins + \ifcleverfootnotes + \doaddinsertionheight\savedfootins + \else + \doaddinsertionheight\footins + \fi} + +%D The local column width is available in the dimension +%D register \type{\localcolumnwidth}, which is calculated as: + +\def\setcolumnhsize% beware, this one is available for use in macros + {\setbox0=\hbox + {\parindent\!!zeropoint\betweencolumns}% + \intercolumnwidth=\wd0 + \localcolumnwidth=\columntextwidth + \advance\localcolumnwidth by -\leftskip + \advance\localcolumnwidth by -\rightskip + \advance\localcolumnwidth by -\nofcolumns\intercolumnwidth + \advance\localcolumnwidth by \intercolumnwidth + \divide\localcolumnwidth by \nofcolumns + \dimen0=\columntextoffset + \multiply\dimen0 by 2 + \advance\localcolumnwidth by -\dimen0 + \usercolumnwidth=\localcolumnwidth + \hsize=\localcolumnwidth} % we don't do it \global + +%D One should be aware that when font related dimensions are +%D used in typesetting the in||between material, these +%D dimensions are influenced by bodyfont switches inside +%D multi||column mode. + +\def\setcolumnvsize% + {%\global\vsize=\columntextheight + \global\vsize=-\columntextoffset + \global\multiply\vsize by 2 + \global\advance\vsize by \columntextheight + \ifdim\precolumnboxheight>\!!zeropoint + \global\advance\vsize by -\precolumnboxheight + \fi + \getinsertionheights\to\dimen0\\% + \global\advance\vsize by -\dimen0 + \ifgridsnapping % evt altijd, nog testen + \getnoflines\vsize + \vsize=\noflines\openlineheight + \advance\vsize by .5\openlineheight % collect enough data + \fi + \global\vsize=\nofcolumns\vsize + \global\pagegoal=\vsize} % let's do it only here + +%D It really starts here. After some checks and initializations +%D we change the output routine to continous multi||column +%D mode. This mode handles columns that fill the current and +%D next full pages. The method used is (more or less) +%D multiplying \type{\vsize} and dividing \type{\hsize} by +%D \type{\nofcolumns}. More on this can be found in the +%D \TeX book. We save the top of the current page in box +%D \type{\precolumnbox}. +%D +%D We manipulate \type{\topskip} a bit, just to be shure that +%D is has no flexibility. This has te be done every time a +%D font switch takles place, because \type{\topskip} can depend +%D on this. +%D +%D Watch the trick with the \type{\vbox}. This way we get the +%D right interlining and white space. + +\def\beginmulticolumns% + {\par + \flushfootnotes + \xdef\precolumndepth{\the\prevdepth}% + \begingroup + \dontshowcomposition + %\setcolumntextwidth\relax + %\setcolumntextheight\relax + \widowpenalty=0 % is gewoon beter + \clubpenalty=0 % zeker bij grids + \ifsomefloatwaiting + \showmessage{\m!columns}{6}{\the\savednoffloats}% + \global\setbox\savedfloatlist=\box\floatlist + \xdef\restoresavedfloats% + {\global\savednoffloats=\the\savednoffloats + \global\setbox\floatlist=\box\savedfloatlist + \global\noexpand\somefloatwaitingtrue}% + \global\savednoffloats=0 + \global\somefloatwaitingfalse + \else + \global\let\restoresavedfloats=\relax + \fi + \dimen0=\pagetotal + \advance\dimen0 by \parskip + \advance\dimen0 by \openlineheight + \ifdim\dimen0<\pagegoal + \allowbreak + \else + \break % Sometimes fails + \fi + \appendtoks\topskip=1\topskip\to\everybodyfont + \the\everybodyfont + \initializecolumns\nofcolumns + \hangafter=0 + \hangindent=\!!zeropoint + \everypar{}% + \ifdim\pagetotal=\!!zeropoint \else + \vbox{\forgetall\strut}% + \vskip-\openlineheight + \fi + \global\savedpagetotal=\pagetotal + \global\singlecolumnout=\output +% \global\output={\global\setbox\precolumnbox=\vbox{\unvbox\normalpagebox}}% +\global\output={\global\setbox\precolumnbox=\vbox{\dotopinsertions\unvbox\normalpagebox}}% + \eject % no \holdinginserts=1, can make footnote disappear ! + \global\precolumnboxheight=\ht\precolumnbox + \global\output={\continuousmulticolumnsout}% + \setcolumnfloats + \dohandleallcolumns + {\global\setbox\currenttopcolumnbox=\box\voidb@x}% + \checkbegincolumnfootnotes +\activateotr{MUL}{ONE}% todo ! ! ! ! + \let\sethsize=\setcolumnhsize + \let\setvsize=\setcolumnvsize + \sethsize + \setvsize + \showcomposition} + +%D When we leave the multi||column mode, we have to process the +%D not yet shipped out part of the columns. When we don't +%D balance, we simply force a continuous output, but a balanced +%D output is more tricky. + +%D First we try to fill up the page and when all or something +%D is left we try to balance things. This is another useful +%D adaption of the ancesters of these macro's. It takes some +%D reasoning to find out what happens and maybe I'm making +%D some mistake, but it works. +%D +%D Voiding box \type{\precolumnbox} is sometimes necessary, +%D e.g. when there is no text given between \type{\begin..} +%D and \type{\end..}. The \type{\par} is needed! + +\def\endmulticolumns% + {%\par + \vskip\lineheight\vskip-\lineheight % take footnotes into account + \dontshowcomposition + \doflushcolumnfloat % added recently + %\doflushcolumnfloats % no, since it results in wrong top floats + \flushfootnotes % before start of columns + \par + \ifbalancecolumns + \global\output={\continuousmulticolumnsout}% + \goodbreak + \global\output={\balancedmulticolumnsout}% + \else + \goodbreak + \fi + \eject % the prevdepth is important, try e.g. toclist in + \prevdepth\!!zeropoint % columns before some noncolumned text text + \global\output=\singlecolumnout +\global\output={\the\mainoutput}% % % % % todo + \ifvoid\precolumnbox\else + \unvbox\precolumnbox + \fi + \global\precolumnboxheight=\!!zeropoint + \endgroup % here + \nofcolumns=1 + \setvsize % the outer one! + \checkendcolumnfootnotes + \dosomebreak\allowbreak + \restoresavedfloats} + +%D NEW: still to be documented! + +\newinsert\savedfootins + +\def\checkbegincolumnfootnotes% + {\ifcleverfootnotes + \doflushfootnotes + \ifdim\ht\footins>\!!zeropoint % hm, actually unknown + \global\setbox\savedfootins=\box\footins + \else + \global\setbox\savedfootins=\box\voidb@x + \fi + \else + \global\setbox\savedfootins=\box\voidb@x + \fi + \global\skip\savedfootins=\skip\footins + \global\count\savedfootins=\count\footins + \setupfootnotes} + +\def\checkendcolumnfootnotes% + {\ifcleverfootnotes\ifvoid\savedfootins\else + \global\setbox\footins=\box\savedfootins + \fi\fi + \global\skip\footins=\skip\savedfootins + \global\count\footins=\count\savedfootins} + +%D Because some initializations happen three times, we +%D defined a macro for them. The \type{\everypar{}} is +%D needed because we don't want anything to interfere. + +\def\setmulticolumnsout% + {\everypar{}% + \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 +%D appending the result to box \type{\precolumnbox}, if not +%D void. I've seen a lot of implementations in which some skip +%D was put between normal text and multi||column text. When we +%D don't want this, the baselines can be messed up. I hope the +%D seemingly complicated calculation of a correction +%D \type{\kern} is adequate to overcome this. Although not +%D watertight, spacing is taken into account and even multiple +%D mode changes on one page go well. But cross your fingers and +%D don't blame me. +%D +%D One of the complications of flushing out the boxes is that +%D \type{\precolumnbox} needs to be \type{\unvbox}'ed, otherwise +%D there is too less flexibility in the page when using +%D \type{\r@ggedbottom}. It took a lot of time before these +%D kind of problems were overcome. Using \type{\unvbox} at the +%D wrong moment can generate \type{\balancingerror}'s. +%D +%D One can use the macros \type {\maxcolumnheight} and \type +%D {\maxcolumndepth} when generating material between columns +%D as well as postprocessing column lines. + +\let\maxcolumnheight=\!!zeropoint +\let\maxcolumndepth =\!!zeropoint + +\newbox\columnpagebox + +\def\setmaxcolumndimensions% + {\let\maxcolumnheight=\!!zeropoint + \let\maxcolumndepth =\!!zeropoint + \dohandleallcolumns + {\ifdim\ht\currentcolumnbox>\maxcolumnheight + \edef\maxcolumnheight{\the\ht\currentcolumnbox}% + \fi + \ifdim\dp\currentcolumnbox>\maxcolumndepth + \edef\maxcolumndepth{\the\dp\currentcolumnbox}% + \fi}} + +\def\flushcolumnedpage% + {\bgroup + \forgetall + \setmulticolumnsout + \showcomposition + \setmaxcolumndimensions + \postprocesscolumns + \dohandleallcolumns % \hbox i.v.m. \showcomposition + {\global\setbox\currentcolumnbox=\hbox to \localcolumnwidth + {\box\currentcolumnbox + \global\wd\currentcolumnbox=\localcolumnwidth + \ifheightencolumns + \global\ht\currentcolumnbox=\fixedcolumnheight + \fi}}% + \setmaxcolumndimensions + \overlaycolumnfootnotes + \setbox\columnpagebox=\vbox + {\hbox to \finalcolumntextwidth + {\ifreversecolumns + \@EA\dohandlerevcolumns + \else + \@EA\dohandleallcolumns + \fi + {\finishcolumnbox{\hbox + {\ifx\finishcolumnbox\relax\else\strut\fi + \box\currentcolumnbox}}% + \hfil}% + \unskip}}% + \scratchdimen=\!!zeropoint + \dohandleallcolumns + {\ifdim-\ht\currenttopcolumnbox<\scratchdimen + \scratchdimen=-\ht\currenttopcolumnbox + \fi + \global\setbox\currenttopcolumnbox=\box\voidb@x}% + \advance\scratchdimen by \ht\columnpagebox + \setbox\scratchbox=\hbox to \columntextwidth + {\vrule + \!!width\!!zeropoint + \!!height\scratchdimen + \!!depth\dp\columnpagebox + \dostepwiserecurse{2}{\nofcolumns}{1}{\hfil\betweencolumns}\hfil}% + \setbox\columnpagebox=\hbox + {\box\columnpagebox + \hskip-\columntextwidth + \color[black]{\box\scratchbox}}% + \postprocesscolumnpagebox % new, acts upon \box\columnpagebox + \ifvoid\precolumnbox \else + \ifgridsnapping % do you believe this junk? + \scratchdimen=\savedpagetotal + \advance\scratchdimen by -\ht\precolumnbox + \advance\scratchdimen by -\dp\precolumnbox + \advance\scratchdimen by -\topskip + \box\precolumnbox + \kern\scratchdimen + \else + \unvbox\precolumnbox + \fi + \fi + \global\precolumnboxheight=\!!zeropoint + \setvsize + \dosomebreak\nobreak + \ifgridsnapping \else + \scratchdimen=\topskip + \advance\scratchdimen by -\openstrutheight + \nointerlineskip + \vskip-\scratchdimen + \fi + \prevdepth\openstrutdepth + \nointerlineskip + \dp\columnpagebox=\!!zeropoint + \global\finalcolumnheights=\ht\columnpagebox + \getnoflines\finalcolumnheights + \global\finalcolumnlines=\noflines + \box\columnpagebox + \egroup} + +%D In case one didn't notice, finaly \type{\finishcolumnbox} is +%D applied to all boxes. One can use these hooks for special +%D purposes. +%D +%D Once upon a time I wanted to manipulate the individual lines +%D in a column. This feature is demonstrated in the two examples +%D below. +%D +%D \startbuffer +%D \def\postprocesscolumnline#1% or \postprocesscolumnbox +%D {\ruledhbox{\box#1}\hss} +%D +%D \startkolommen[n=4] +%D \dorecurse{25}{line: \recurselevel\par} +%D \stopkolommen +%D \stopbuffer +%D +%D \typebuffer +%D +%D Here we show the natural width of the lines: +%D +%D {\haalbuffer} +%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 \startkolommen[n=4] +%D \dorecurse{25}{line \recurselevel\par} +%D \stopkolommen +%D \stopbuffer +%D +%D \typebuffer +%D +%D Here we also see an application of \type{\currentcolumn}: +%D +%D {\haalbuffer} +%D +%D This feature is implemented using the reshape macros +%D presented in \type{supp-box}. + +\def\postprocesscolumns% + {\ifx\postprocesscolumnline\undefined \else + \dohandleallcolumns + {\global\setbox\currentcolumnbox=\vtop + {\beginofshapebox + \unvbox\currentcolumnbox + \unskip\unskip + \endofshapebox + \reshapebox + {\dimen0=\ht\shapebox + \dimen2=\dp\shapebox + \setbox\shapebox=\hbox to \hsize + {\postprocesscolumnline\shapebox}% + \ht\shapebox=\dimen0 + \dp\shapebox=\dimen2 + \box\shapebox}% + \flushshapebox + \everypar{}\parskip\!!zeropoint % = \forgetall + \strut\endgraf + \vskip-\lineheight + \vfil}}% + \fi + \ifx\postprocesscolumnbox\undefined \else + \dohandleallcolumns + {\global\setbox\currentcolumnbox=\hbox + {\postprocesscolumnbox\currentcolumnbox}} + \fi} + +%D We default to doing nothing! + +\let\postprocesscolumnline =\undefined +\let\postprocesscolumnbox =\undefined +\let\postprocesscolumnpagebox=\relax + +%D \macros +%D {reversecolumnstrue} +%D +%D We can force the macro that takes care of combining +%D the columns, to flush them in the revere order. Of +%D course, by default we don't reverse. + +\newif\ifreversecolumns + +%D Here comes the simple splitting routine. It's a bit +%D longer than expected because of ragging bottoms or not. +%D This part can be a bit shorter but I suppose that I will +%D forget what happens. The splitting takes some already +%D present material (think of floats) into account! +%D +%D First we present some auxiliary routines. Any material, +%D like for instance floats, that is already present in the +%D boxes is preserved. + +% \def\splitcolumn#1from \box#2to \dimen#3 top \box#4% +% {\bgroup +% \ifdim\ht#4>\!!zeropoint +% \dimen0=\dimen#3\relax +% \dimen2=\dimen#3\relax +% \advance\dimen0 by -\ht#4 +% \setbox0=\vsplit#2 to \dimen0 +% \global\setbox#1=\vbox to \dimen2{\unvcopy#4\unvbox0}% +% \else +% \global\setbox#1=\vsplit#2 to \dimen#3 +% \fi +% \egroup} + +% \def\splitcolumn#1from \box#2to \dimen#3 top \box#4% +% {\bgroup +% \ifdim\ht#4>\!!zeropoint +% \dimen0=\dimen#3\relax +% \dimen2=\dimen2 +% \advance\dimen0 by -\ht#4% +% \columnfootnotecorrection{#1}{\dimen0}% +% \setbox0=\vsplit#2 to \dimen0 +% \global\setbox#1=\vbox to \dimen2 +% {\ifgridsnapping +% \dimen0=-\openstrutheight\advance\dimen0 by \topskip +% \vskip\dimen0\copy#4\vskip-\dimen0 +% \else +% \unvcopy#4% +% \fi +% \unvbox0 +% \fakecolumnfootnotes{#1}}% +% \else +% \ifcleverfootnotes +% \columnfootnotecorrection{#1}{\dimen#3}% +% \setbox0=\vsplit#2 to \dimen#3% +% \global\setbox#1=\vbox to \dimen#3% +% {\unvbox0 +% \fakecolumnfootnotes{#1}}% +% \else +% \global\setbox#1=\vsplit#2 to \dimen#3% +% \fi +% \fi +% \egroup} + +\def\splitcolumn#1from \box#2to \dimen#3 top \box#4% + {\bgroup + \ifdim\ht#4>\!!zeropoint + \dimen0=\dimen#3\relax + \dimen2=\dimen0 + \advance\dimen0 by -\ht#4% + \columnfootnotecorrection{#1}{\dimen0}% + \setbox0=\vsplit#2 to \dimen0 + \global\setbox#1=\vbox to \dimen2 + {\ifgridsnapping + \dimen0=-\openstrutheight\advance\dimen0 by \topskip + \vskip\dimen0\copy#4\vskip-\dimen0 + \else + \unvcopy#4% + \fi + \fuzzysnappedbox\unvbox0 + \fakecolumnfootnotes{#1}}% + \else + \ifcleverfootnotes + \columnfootnotecorrection{#1}{\dimen#3}% + \setbox0=\vsplit#2 to \dimen#3% + \global\setbox#1=\vbox to \dimen#3% + {\fuzzysnappedbox\unvbox0 + \fakecolumnfootnotes{#1}}% + \else + \global\setbox#1=\vsplit#2 to \dimen#3% + \global\setbox#1=\vbox + {\fuzzysnappedbox\unvbox{#1}}% % or \box ? + \fi + \fi + \egroup} + +\def\splitcurrentcolumn from \box#1to \dimen#2% + {\splitcolumn\currentcolumnbox from \box#1 to \dimen#2 top \box\currenttopcolumnbox} + +\def\splitfirstcolumn from \box#1to \dimen#2% + {\splitcolumn\firstcolumnbox from \box#1 to \dimen#2 top \box\firsttopcolumnbox} + +\def\splitlastcolumn from \box#1to \dimen#2% + {\global\setbox\lastcolumnbox=\vbox + {\unvcopy\lasttopcolumnbox + \fuzzysnappedbox\unvbox{#1}% + \fakecolumnfootnotes\lastcolumnbox}} + +%D NEW: still to be documented. + +\def\fakecolumnfootnotes#1% + {\relax + \ifcleverfootnotes + \ifnum#1=\lastcolumnbox + \ifdim\ht\footins>\!!zeropoint + \vskip1\skip\footins % remove stretch and shrink + \kern\ht\footins % a \vskip would be is discarded! + \fi + \fi + \fi} + +\def\columnfootnotecorrection#1#2% + {\relax + \ifcleverfootnotes + \ifnum#1=\lastcolumnbox\relax + \ifdim\ht\footins>\!!zeropoint + \advance#2 by -\ht\footins + \advance#2 by -\skip\footins + \fi + \fi + \fi} + +\def\overlaycolumnfootnotes% VERVANGEN !!! + {\relax + \ifcleverfootnotes\ifdim\ht\footins>\!!zeropoint + \bgroup + \scratchdimen=\ht\firstcolumnbox + \advance\scratchdimen by -\openstrutdepth % \dp\strutbox + \getnoflines\scratchdimen + \advance\noflines by -2 + \scratchdimen=\noflines\lineheight + \advance\scratchdimen by \topskip + \setbox0=\hbox + {\lower\scratchdimen\vbox{\placefootnoteinserts}}% + \ht0=\openstrutheight % \ht\strutbox + \dp0=\openstrutdepth % \dp\strutbox + \scratchdimen=\ht\lastcolumnbox + \global\setbox\lastcolumnbox=\vbox to \scratchdimen + {\box\lastcolumnbox + \vskip-\scratchdimen + \color[black]{\box0}}% + \egroup + \fi\fi} + +%D Here comes the routine that splits the long box in columns. +%D The macro \type{\flushcolumnfloats} can be used to flush +%D either floats that were present before the multi||column +%D mode was entered, or floats that migrate to next columns. +%D Flushing floats is a delicate process. + +\def\continuousmulticolumnsout% + {\bgroup + \forgetall + \setmulticolumnsout + \dontshowcomposition + \dimen0=\columntextheight + \getinsertionheights\to\dimen2\\% toegevoegd ivm voetnoten + \advance\dimen2 by \precolumnboxheight + \dimen0=\columntextheight + \advance\dimen0 by -\precolumnboxheight + \getinsertionheights\to\dimen2\\% + \advance\dimen0 by -\dimen2 + \ifgridsnapping % evt altijd, nog testen + \getnoflines{\dimen0} + \dimen0=\noflines\openlineheight + \fi + \dohandleallcolumns + {\splitcurrentcolumn from \box\normalpagebox to \dimen0} + \setbox\restofpage=\vbox{\unvbox\normalpagebox}% + \ifinheritcolumns + \ifr@ggedbottom % vreemd +%\ifbottomnotes % can better be a state + \dohandleallcolumns + {\global\setbox\currentcolumnbox=\vbox to \ht\firstcolumnbox + {\dimen0=\dp\currentcolumnbox + \unvbox\currentcolumnbox + \vskip-\dimen0 + \vskip\openstrutdepth % \dp\strutbox + \prevdepth\openstrutdepth % \dp\strutbox + \vfill}}% +%\else +% \dimen0=\ht\firstcolumnbox +%\fi +\ifbottomnotes \else + \dimen0=\ht\firstcolumnbox +\fi + \fi + \ifn@rmalbottom + \advance\dimen0 by \maxdepth + \dohandleallcolumns + {\global\setbox\currentcolumnbox=\vbox to \dimen0 + {\unvbox\currentcolumnbox}}% + \fi + \ifb@selinebottom + % the columns are on top of the baseline + \fi + \else + \dohandleallcolumns + {\global\setbox\currentcolumnbox=\vbox to \dimen0 + {\ifstretchcolumns + \unvbox\currentcolumnbox + \else + \unvbox\currentcolumnbox % wel of niet \unvbox ? + \vfill + \fi}}% + \dohandleallcolumns + {\global\ht\currentcolumnbox=\dimen0}% + \fi + \setbox\precolumnbox=\vbox{\flushcolumnedpage}% + \finaloutput\box\precolumnbox + \sethsize + \setvsize + \flushcolumnfloats + \unvbox\restofpage + % \penalty\outputpenalty % gaat gruwelijk mis in opsommingen + \egroup} + +%D And this is the balancing stuff. Again, part of the routine +%D is dedicated to handling ragged bottoms, but here we also +%D see some handling concerning the stretching of columns. +%D We set \type{\widowpenalty} at~0, which enables us to +%D balance columns with few lines. The use of \type{\box2} and +%D \type{\box4} garantees a more robust check when skips are +%D used. + +\def\balancedmulticolumnsout% + {\bgroup + \setmulticolumnsout + \dontshowcomposition + \widowpenalty=0 + \setbox0=\vbox{\unvbox\normalpagebox}% +\ifdim\ht0>\openlineheight % at least one line + \ifnum\minbalancetoplines<2 % balance anyway + \donetrue + \else % check criterium to available lines + \getnoflines{\ht0}% + \divide\noflines by \nofcolumns \relax + \ifnum\noflines<\minbalancetoplines \relax + \dimen0=\ht0 + \advance\dimen0 by \ht\firsttopcolumnbox + \advance\dimen0 by \openlineheight \relax % let's play safe + \ifdim\dimen0>\columntextheight % column exceeding text height + \donetrue + \else % it seems to fit + \donefalse + \fi + \else % balance indeed + \donetrue + \fi + \fi +\else % balancing does not make sense + \donefalse +\fi +\ifdone % start balancing + %\ifdim\ht0>\openlineheight + \dimen0=\ht0 + \advance\dimen0 by \topskip + \advance\dimen0 by -\baselineskip + \dohandleallcolumns + {\advance\dimen0 by \ht\currenttopcolumnbox}% + \divide\dimen0 by \nofcolumns + \vbadness=\!!tenthousand\relax + \count255=0 + \bgroup + \ifgridsnapping + \dimen2=\lineheight + \else + \dimen2=\!!onepoint % RUBISH + \dimen2=\spacingfactor\dimen2 + \fi + \loop + \advance\count255 by 1 + \global\setbox\restofpage=\copy0\relax + \splitfirstcolumn from \box\restofpage to \dimen0 + \dohandlemidcolumns + {\splitcurrentcolumn from \box\restofpage to \dimen0}% + \splitlastcolumn from \box\restofpage to \dimen0 + \setbox2=\vbox{\unvcopy\firstcolumnbox}% + \dimen4=\!!zeropoint + \dohandleallcolumns + {\setbox4=\vbox + {\unvcopy\currentcolumnbox + %rather new, test this on pdftex-z.tex + \unpenalty\unskip\unpenalty\unskip}% maybe better in main splitter + %\writestatus{balance}{\the\currentcolumnbox: \the\ht4}% + \dimen6=\ht4 + \ifdim\dimen6>\dimen4 \dimen4=\dimen6 \fi}% +\advance\dimen4 by -.0005pt % get rid of accurracy problem, pretty new + \ifnum\count255>100\relax + \donefalse + \else\ifdim\dimen4>\ht2 + \donetrue + \else + \donefalse + \fi\fi + \ifdone + \advance\dimen0 by \dimen2\relax + \repeat + \dohandleallcolumns + {\global\setbox\currentcolumnbox=\vbox{\unvcopy\currentcolumnbox}}% NIEUW + \ifnum\count255>100\relax + \showmessage{\m!columns}{7}{}% + \else + \showmessage{\m!columns}{8}{\the\count255\space}% + \fi + \egroup + \ifinheritcolumns + \dimen0=\ht\firstcolumnbox + \dimen2=\ht\firstcolumnbox + \advance\dimen2 by -\openlineheight + \dohandleallcolumns + {\dimen4=\ht\currentcolumnbox + \dimen6=10\openlineheight + \global\setbox\currentcolumnbox=\vbox to \dimen0 + {\unvbox\currentcolumnbox + \ifdim\dimen4>\dimen6 + \ifdim\dimen4<\dimen0 + \ifdim\dimen4>\dimen2 + \vskip\!!zeropoint % !! + \else + \vskip\openlineheight + \vfill + \fi + \else + \vskip\!!zeropoint + \fi + \else + \vskip\openlineheight + \vfill + \fi}}% + \else + \bgroup + \ifstretchcolumns + \dimen0=\ht\firstcolumnbox + \dimen2=\bottomtolerance\ht\firstcolumnbox + \setbox0=\vbox{\unvcopy\lastcolumnbox}% + \advance\dimen0 by -\ht0\relax + \advance\dimen0 by -\dp0\relax + \ifdim\dimen0>\openlineheight\relax + \ifdim\dimen0>\dimen2\relax + % \stretchcolumnsfalse % beter goed slecht dan slecht goed + \showmessage{\m!columns}{9}{}% + \fi + \fi + \fi + \dohandleallcolumns + {\global\setbox\currentcolumnbox=\vbox to \ht\firstcolumnbox + {\ifstretchcolumns + \unvbox\currentcolumnbox + \else + \box\currentcolumnbox + \vfill + \fi}}% + \egroup + \fi + \else + \showmessage{\m!columns}{10}{}% + \global\setbox\firstcolumnbox=\vbox{\unvbox0}% + \fi + \global\output={\balancingerror}% + \b@selinebottomtrue % forces depth in separation rule + \flushcolumnedpage + \allowbreak + \egroup} + +%D The multicolumn mechanism is incorporated in a \CONTEXT\ +%D interface, which acts like: +%D +%D \starttypen +%D \startcolumns[n=4,balance=no,stretch=no,line=on] +%D some text +%D \stopcolumns +%D \stoptypen +%D +%D The setup is optional. The default behaviour of columns +%D can be set up with: +%D +%D \starttypen +%D \setupcolumns +%D [n=2, +%D balance=yes, +%D stretch=text, +%D line=off] +%D \stoptypen +%D +%D In this case, stretching is according to the way it's +%D done outside columns (\type{\inheritcolumnstrue}). Also +%D we can setup the \type{tolerance} within a column, the +%D \type{distance} between columns and the fixed +%D \type{height} of a column. + +%D Multi||column output: the float routines +%D +%D Here come the routines that handle the placement of column +%D floats. Floats that are to big migrate to the next +%D column. Floats that are too wide, migrate to the top of the +%D next page, where they span as much columns as needed. +%D Floats that are left over from outside the multi||column +%D mode are flushed first. In macro \type{\finaloutput} the +%D topfloats that are left from previous text should be set. +%D +%D When there are some floats in the queue, we inhibit the +%D flushing of floats on top of columns. The number of +%D waiting floats is preswent in \type{\savednoftopfloats} and +%D is saved. As long as there are floats waiting, the topfloats +%D are places as if we are outside multi||column mode. This is +%D neccessary for e.g. multicolumn lists. +%D +%D When all those floats are flushed, we switch to the local +%D flushing routine. + +\def\setcolumnfloats% + {\xdef\globalsavednoffloats{\the\savednoffloats}% + \ifnum\globalsavednoffloats>0 + \setglobalcolumnfloats + \else + \setlocalcolumnfloats + \fi} + +\def\setglobalcolumnfloats% + {\everypar\emptytoks + \let\flushcolumnfloat=\relax + %\let\doroomfloat=\relax + \let\docheckiffloatfits=\relax + \let\flushcolumnfloats=\noflushcolumnfloats} + +\def\setlocalcolumnfloats% + {\everypar= + {\flushfootnotes\flushcolumnfloat\flushmargincontents\checkindentation}% + \let\flushcolumnfloat=\doflushcolumnfloat + %\let\doroomfloat=\docolumnroomfloat + \let\docheckiffloatfits=\docolumnroomfloat + \let\flushcolumnfloats=\doflushcolumnfloats + \let\doflushfloats\doflushcolumnfloats % new + \let\dosetbothinserts=\relax + \let\dotopinsertions=\relax} + +\def\noflushcolumnfloats% + {\bgroup + \xdef\localsavednoffloats{\the\savednoffloats}% + \global\savednoffloats=\globalsavednoffloats + \dotopinsertions + \xdef\globalsavenoffloats{\the\savednoffloats}% + \ifnum\globalsavednoffloats=0 + \setlocalcolumnfloats + \fi + \global\savednoffloats=\localsavednoffloats + \egroup} + +%D We need to calculate the amount of free space in a columns. +%D When there is not enough room, we migrate the float to the +%D next column. These macro's are alternatives (and +%D look||alikes) of \type{\doroomfloat}. When a float is to +%D wide, for one column, it is moved to the top of the next +%D page. Of course such moved floats have to be taken into +%D account when we calculate the available space. It's a pitty +%D that such things are no integral part of \TEX. + +\def\getcolumnstatus\column#1\total#2\goal#3\\% + {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi + \dimen2=\!!zeropoint + \count255=0 + \dimen8=\columntextheight + \advance\dimen8 by -\precolumnboxheight + \def\dogetcolumnstatus% + {\advance\count255 by 1 + \advance\dimen2 by \ht\currenttopcolumnbox + \advance\dimen2 by \dp\currenttopcolumnbox + \dimen4=\dimen2 + \advance\dimen4 by \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=\columntextheight + \advance\dimen0 by -\pagegoal + \xdef\insertionheight{\the\dimen0}% + \egroup + \else + \global\let\insertionheight=\zeropoint + \fi} + +\def\docolumnroomfloat% + {\ifpostponecolumnfloats + \global\roomforfloatfalse + \else\ifnofloatpermitted + \global\roomforfloatfalse + \else + \bgroup + \getcolumnstatus\column\count255\total\dimen0\goal\dimen2\\% + \advance\dimen0 by 2\openlineheight % nog nodig ? + %\ifnum\count255=\nofcolumns + % \getinsertionheight + % %\message{\insertionheight}\wait + % \advance\dimen0 by \insertionheight + %\fi + \setbox\scratchbox=\vbox % tricky met objecten ? + {\blanko[\@@bkvoorwit] + \snaptogrid\vbox{\copy\floatbox}}% + \advance\dimen0 by \ht\scratchbox + \advance\dimen0 by .5\lineheight % needed because goal a bit higher + %\message{column: \the\count255; total: \the\dimen0; goal: \the\dimen2}\wait + \ifdim\dimen0>\dimen2 + \global\roomforfloatfalse + \else + \global\roomforfloattrue + \fi + \ifdim\wd\floatbox>\hsize + \showmessage{\m!columns}{11}{}% + \global\roomforfloatfalse + \fi + \egroup + \fi\fi} + +%D Flushing one float is done as soon as possible, i.e. +%D \type{\everypar}. This means that (at the moment) +%D sidefloats are not supported (overulled)! + +\newif\ifflushingcolumnfloats \flushingcolumnfloatstrue + +\def\doflushcolumnfloat% + {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifprocessingverbatim\else\ifsomefloatwaiting + \bgroup + \forgetall + \let\doflushcolumnfloat=\relax + \getcolumnstatus\column\count255\total\dimen0\goal\dimen2\\% + \ifdim\dimen0>\zeropoint + \dogetfloat + \ifdim\wd\floatbox>\hsize + \doresavefloat + \else + %\setbox2=\vbox + % {\blanko[\@@bkvoorwit] + % \snaptogrid\vbox{\copy\floatbox}% + % \blanko[\@@bknawit] + \setbox2=\vbox + {\blanko[\@@bkvoorwit] + \snaptogrid\vbox{\copy\floatbox}}% + \advance\dimen0 by \ht2 + \ifdim\dimen0>\dimen2 + \ifnum\count255<\nofcolumns + \advance\count255 by 1 + \edef\currenttopcolumnbox{\getvalue{\@@topcol\the\count255}}% + \ifdim\ht\currenttopcolumnbox=\zeropoint + \global\setbox\currenttopcolumnbox=\vbox + {\snaptogrid\vbox{\copy\floatbox} + \witruimte % nodig ? + \blanko[\@@bknawit]}% + \dimen4=\ht\currenttopcolumnbox + \advance\dimen4 by \dp\currenttopcolumnbox + \global\advance\vsize by -\dimen4 + \advance\dimen4 by -\pagegoal + \global\pagegoal=-\dimen4 + \showmessage{\m!columns}{12}{a}% + \else + \showmessage{\m!columns}{12}{b}% + \doresavefloat + \fi + \else + \showmessage{\m!columns}{12}{c}% + \doresavefloat + \fi + \else + \ifhmode{\setbox0=\lastbox}\fi% waar is die er in geslopen + \par + \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte + \nobreak + \blanko[\@@bkvoorwit] + \nobreak + \fi + \flushfloatbox + \blanko[\@@bknawit] + \fi + \fi + \fi + \egroup + \fi\fi\fi\fi} + +%D This one looks complicated. Upto \type{\nofcolumns} floats +%D are placed, taking the width of a float into account. This +%D routine can be improved on different ways: +%D +%D \startopsomming[intro,opelkaar] +%D \som taking into account some imaginary baseline, just to +%D get the captions in line +%D \som multipass flushing until as many floats are displaced +%D as possible +%D \stopopsomming +%D +%D When handling lots of (small) floats spacing can get worse +%D because of lining out the columns. + +\def\doflushcolumnfloats% + {\ifpostponecolumnfloats\else + \bgroup + \forgetall + \ifsomefloatwaiting + \dimen8=\!!zeropoint + \dimen4=\!!zeropoint + \count0=0 % count0 can be used local + \count2=\nofcolumns % count2 can be used local + \dohandleallcolumns + {\ifnum\count0>0\relax % the wide one's reserved space + \global\setbox\currenttopcolumnbox=\vbox + {\snaptogrid\vbox + {\copy\currenttopcolumnbox + \hbox{\vphantom{\copy\floatbox}}} + \witruimte % nodig ? + \blanko[\@@bknawit]}% + \else + \dogetfloat + \ifdim\wd\floatbox>\finalcolumntextwidth % better somewhere else too + \global\setbox\floatbox=\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}% + \fi % otherwise the graphic may disappear + \ifdim\wd\floatbox>\hsize + \dimen0=\wd\floatbox + \advance\dimen0 by \intercolumnwidth + \dimen2=\hsize + \advance\dimen2 by \intercolumnwidth + \advance\dimen0 by .5pt % hm, why 1 + \advance\dimen2 by .5pt % hm, why 2 + \divide\dimen0 by \dimen2 + \count0=\dimen0 + \advance\count0 by 1 + \ifnum\count0>\count2 + \doresavefloat + \count0=0 + \else + \dimen0=\count0\hsize + \advance\dimen0 by \count0\intercolumnwidth + \advance\dimen0 by -\intercolumnwidth + \global\setbox\floatbox=\hbox to \dimen0 + %{\hss\hbox{\copy\floatbox}\hss}% + {\processaction[\@@bkplaats] % how easy to forget + [ \v!links=>\copy\floatbox\hss, + \v!rechts=>\hss\copy\floatbox, + \s!default=>\hss\copy\floatbox\hss, + \s!unknown=>\hss\copy\floatbox\hss]}% + \fi + \showmessage{\m!columns}{13}{}% + \else + % \showmessage{\m!columns}{13}{}% + \fi + \ifdim\ht\floatbox>\!!zeropoint\relax + \global\setbox\currenttopcolumnbox=\vbox + {\snaptogrid\vbox + {\copy\currenttopcolumnbox + \copy\floatbox} + \witruimte % nodig ? + \blanko[\@@bknawit]}% + \fi + \dimen6=\ht\currenttopcolumnbox + \advance\dimen6 by \dp\currenttopcolumnbox + \fi + \ifdim\dimen4<\ht\currenttopcolumnbox + \dimen4=\ht\currenttopcolumnbox + \fi + \advance\dimen8 by \dimen6 + \advance\count2 by -1 + \advance\count0 by -1 }% + \setvsize + \global\advance\vsize by -\dimen8 + \global\pagegoal=\vsize + \else + %\doflushfloats % does not snap! + \fi + \egroup + \fi} + +%D This were the multi||column routines. They can and need to +%D be improved but at the moment their behaviour is acceptable. +%D +%D One inprovement can be to normalize the height of floats +%D to $n\times$\type{\lineheight} with a macro like: +%D +%D \starttypen +%D \normalizevbox{...} +%D \stoptypen + +% border case, should fit on one page +% +% \startkolommen +% +% 1 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{1}} +% 2 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{2}} +% 3 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{3}} +% +% \stopkolommen + +\newif\ifbinnenkolommen +\newif\if@@klbalanceren +\newif\if@@kluitlijnen + +\binnenkolommenfalse + +\def\stelkolommenin% + {\dodoubleargument\dostelkolommenin} + +\def\stelkolommenin[#1]% + {\getparameters[\??kl][#1]% + \nofcolumns=\@@kln\relax + \processaction + [\@@kllijn] + [ \v!aan=>\let\betweencolumns=\linebetweencolumns, + \v!uit=>\let\betweencolumns=\spacebetweencolumns, + \s!default=>\let\betweencolumns=\spacebetweencolumns, + \s!unknown=>\let\betweencolumns=\@@kllijn]} + +\def\linebetweencolumns% + {\bgroup + \startcolorpage + \ifdim\@@klafstand>\!!zeropoint + \dimen0=\@@klafstand + \else + \dimen0=\linewidth + \fi + \advance\dimen0 by -\linewidth + \hskip.5\dimen0 + \vrule + \!!width\linewidth + \ifb@selinebottom\!!depth\strutdepth\fi + \hskip.5\dimen0\relax + \stopcolorpage + \egroup} + +\def\spacebetweencolumns% + {\hskip\@@klafstand} + +\presetlocalframed[\??kl] + +\def\backgroundfinishcolumnbox% + {\doifinsetelse{\@@kloffset}{\v!geen,\v!overlay} + {\let\@@kloffset\!!zeropoint} + {\scratchdimen=\@@kloffset + \advance\scratchdimen by -\@@kllijndikte + \edef\@@kloffset{\the\scratchdimen}}% + \localframed + [\??kl] + [\c!strut=\v!nee, + \c!breedte=\v!passend, + \c!hoogte=\v!passend, + \c!uitlijnen=]} + +\let\restorecolumnsettings\relax + +\def\complexstartkolommen[#1]% %% \startkolommen + {\bgroup + \let\stopkolommen=\egroup + \ifbinnenkolommen + \else + \stelkolommenin[#1]% + \ifnum\@@kln>1\relax + \witruimte + \begingroup + \doif{\@@kloptie}{\v!achtergrond} + {\let\finishcolumnbox=\backgroundfinishcolumnbox + \let\columntextoffset=\@@kloffset}% + \ifx\@@klcommando\empty\else + \let\postprocesscolumnline\@@klcommando + \fi + \doifelsenothing{\@@klhoogte} + {\heightencolumnsfalse} + {\heightencolumnstrue}% + \doifelse{\@@klrichting}{\v!rechts} + {\reversecolumnsfalse} + {\reversecolumnstrue}% + \doifelse{\@@klbalanceren}{\v!ja} + {\balancecolumnstrue} + {\balancecolumnsfalse}% + \processaction % ook nog: laatsteuitlijnen + [\@@kluitlijnen] + [ \v!ja=>\stretchcolumnstrue + \inheritcolumnsfalse, + \v!nee=>\stretchcolumnsfalse + \inheritcolumnsfalse, + \v!tekst=>\stretchcolumnsfalse + \inheritcolumnstrue]% + \nofcolumns=\@@kln + % + % probably more is needed, and how about nesting save's + % + \savecurrentblanko + \savecurrentwitruimte + \def\restorecolumnsettings% + {\boxmaxdepth\maxdimen % done elsewhere + \restorecurrentblanko + \restorecurrentwitruimte}% + % + \edef\fixedcolumnheight{\@@klhoogte}% + \edef\minbalancetoplines{\@@klnboven}% + \steltolerantiein[\@@kltolerantie]% %% \startkolommen + \stelblankoin[\@@klblanko]% + \ifdim\tussenwit>\!!zeropoint + \stelwitruimtein[\@@klblanko]% + \fi + \def\stopkolommen% + {\endmulticolumns + \global\binnenkolommenfalse + \endgroup + \egroup}% + \global\binnenkolommentrue + \beginmulticolumns + \fi + \fi} + +\definecomplexorsimpleempty\startkolommen + +%\def\kolom% +% {\ifbinnenkolommen +% \ejectcolumn +% \fi} + +\def\preferredejectcolumn% + {\goodbreak} + +% \def\forcedejectcolumn% +% {\vfil +% \penalty-200 +% \prevdepth=-1000pt % signals top of column to \blanko +% \vfilneg} + +\def\forcedejectcolumn% + {\par % todo: since + {\testrulewidth\!!zeropoint\ruledvskip\teksthoogte} % we misuse a + \penalty-200 % side effect + \vskip-\teksthoogte + \prevdepth=-1000pt} % signals top of column to \blanko + +\def\kolom% + {\dosingleempty\dokolom} + +\def\dokolom[#1]% + {\ifbinnenkolommen + \iffirstargument + \processaction + [#1] + [ \v!ja=>\forcedejectcolumn, + \v!voorkeur=>\preferredejectcolumn]% + \else + \preferredejectcolumn + \fi + \fi} + +\stelkolommenin + [\c!n=2, + \c!nboven=1, + \c!commando=, + \c!richting=\v!rechts, + \c!lijn=\v!uit, + \c!tolerantie=\v!soepel, + \c!afstand=1.5\korpsgrootte, % influenced by switching + \c!hoogte=, + \c!balanceren=\v!ja, + \c!uitlijnen=\v!tekst, + \c!blanko={\v!regel,\v!vast}, + \c!optie=, + \c!lijndikte=\linewidth, + \c!offset=.5\korpsgrootte] + +%D Undocumented and still under development. + +\def\startsimplecolumns% + {\dosingleempty\dostartsimplecolumns} + +\def\dostartsimplecolumns[#1]% + {\bgroup + \getparameters[\??kl][\c!breedte=\hsize,\c!afstand=1em,\c!n=2,#1]% + \setrigidcolumnhsize\@@klbreedte\@@klafstand\@@kln + \setbox\scratchbox=\vbox\bgroup + \forgetall} % \blanko[\v!blokkeer] + +\def\stopsimplecolumns% + {\removebottomthings + \egroup + \rigidcolumnbalance\scratchbox + \egroup} + +\protect \endinput |