page-set.mkiv /size: 88 Kb    last modification: 2020-07-01 14:35
1%D \module
2%D   [       file=page-set,
3%D        version=2000.10.20,
4%D          title=\CONTEXT\ Page Macros,
5%D       subtitle=Column Sets,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14% not yet mkiv! probably namespace issues with localframed (only one left)
15%
16% getnoflines vs getrawnoflines
17%
18% can have some vpack and hpack
19
20% This is a rather old mechanism and we can best keep it as it is. If it gets
21% replaced by a more modern solution, it will be an extra mechanism. So, we
22% only do some basic cleanup.
23
24\writestatus{loading}{ConTeXt Page Macros / Column Sets}
25
26% todo : last longer than previous
27% todo : block span over last column if footnotes
28% todo : diagnosis balancing run
29% todo : separate footnote placement
30% todo : go on on same page with colset
31% todo : test page areas per page
32% todo : leftmargin/rightmargin (better than afstand(1))
33
34% use the OTRSET layer for more purposes, like the footnotes !
35
36\unprotect
37
38\newcount\tofcolumns % total
39\newcount\lofcolumns % left
40\newcount\rofcolumns % right
41
42\newcount\columnfirstcell \columnfirstcell=1
43\newcount\columnlastcell
44\newcount\columnfreecells
45\newcount\currenthcell
46\newcount\currentvcell
47\newcount\columnhcells
48\newcount\columnvcells
49
50\newif\ifenoughcolumncells
51\newif\ifsomefreecolumncells
52\newif\ifcolumnspread
53\newif\iftracecolumnset
54
55\newif\ifforcecolumnsetgrid      \forcecolumnsetgridtrue
56\newif\ifcollectingsetcontent    % never set
57\newif\ifcarryoverfootnotes      %\carryoverfootnotestrue
58\newif\iflastcolumnfootnotes     % never set \lastcolumnfootnotestrue
59\newif\ifintermediatefootnotes
60
61\newbox        \b_page_set_preceding
62\newbox        \b_page_set_trailing
63
64\newdimen      \d_page_set_local_hsize
65\newconditional\c_page_set_width_set
66
67\installcorenamespace{columnsetgrid}
68
69\def\columnmaxcells    {75} % runtime
70\def\columnmaxfreecells {0} % runtime
71\def\columngaplimit     {0} % {5}
72
73\def\page_set_cell    #1#2{\csname              \??columnsetgrid:\number#1:\number#2\endcsname}
74\def\page_set_cell_get#1#2{\box\csname          \??columnsetgrid:\number#1:\number#2\endcsname}
75\def\page_set_cell_set#1#2{\global\setbox\csname\??columnsetgrid:\number#1:\number#2\endcsname}
76
77\def\page_set_cell_doifelse#1#2%
78  {\relax
79   \ifvoid\csname\??columnsetgrid:\number#1:\number#2\endcsname
80     \expandafter\secondoftwoarguments
81   \else
82     \expandafter\firstoftwoarguments
83   \fi}
84
85\def\page_set_cell_erase_grid  % maybe dedicated loops ... make another loop when max's have changed
86  {\bgroup
87   \increment\columnmaxcells\relax
88   \ifodd\realpageno \else
89     \columnspreadfalse
90   \fi
91   \ifcolumnspread
92     \page_set_cell_erase_grid_spread
93   \else
94     \page_set_cell_erase_grid_page
95   \fi
96   \page_set_cell_erase_grid_top
97   \global\columnfirstcell\zerocount
98   \global\columnlastcell \columnfirstcell
99   \global\columnfreecells\columnfirstcell
100   \egroup}
101
102\let\m_page_column_l\relax
103\let\m_page_column_r\relax
104
105\def\page_set_cell_erase_grid_spread
106  {\dorecurse\nofcolumns
107     {\let \m_page_column_l\recurselevel
108      \edef\m_page_column_r{\the\numexpr\recurselevel+\lofcolumns}%
109      \dostepwiserecurse \zerocount \columnmaxcells \plusone
110        {\ifcsname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
111           \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
112           \ifcsname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
113             \box\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
114           \else
115             \emptyhbox
116             \expandafter\newbox\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
117           \fi
118         \else
119           \expandafter\newbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
120           \ifcsname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
121             \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname\box\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
122           \else
123             \expandafter\newbox\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
124           \fi
125         \fi}}}
126
127\def\page_set_cell_erase_grid_page
128  {\dorecurse \tofcolumns
129     {\let\m_page_column_l\recurselevel
130      \dostepwiserecurse \zerocount \columnmaxcells \plusone
131        {\ifcsname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
132           \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname\emptybox
133         \else
134           \expandafter\newbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
135         \fi}}}
136
137\def\page_set_cell_erase_grid_top
138  {\dorecurse\tofcolumns
139     {\global\setbox\csname\??columnsetgrid:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}}
140
141% % % %
142
143\def\OTRSETmakeupwidth{\innermakeupwidth}
144
145\unexpanded\def\page_set_command_flush_side_floats
146  {\page_sides_forget_floats}
147
148\unexpanded\def\page_set_command_synchronize_side_floats
149  {\page_sides_forget_floats}
150
151% The following two macros are used to compensate for a switch in body fonts
152% as in:
153%
154% \definecolumnset [two]  [n=2,balancing=yes]
155% \definecolumnset [three] [n=3,balancing=yes]
156%
157% \setupcolumnsetlines[two][1][1][7]
158% \setupcolumnsetlines[two][1][2][10]
159%
160% \setupcolumnsetlines[three][1][1][40]
161% \setupcolumnsetlines[three][1][2][40]
162% \setupcolumnsetlines[three][1][3][40]
163%
164% \setupcolumnsetstart[three][1][1][15]
165% \setupcolumnsetstart[three][1][2][20]
166% \setupcolumnsetstart[three][1][3][20]
167%
168% \starttext
169%   \startcolumnset [two] \dorecurse {1}{\input tufte \par} \stopcolumnset
170%   \switchtobodyfont[small]
171%   \startcolumnset [three] \dorecurse {1}{\input tufte \par} \stopcolumnset
172% \stoptext
173
174%D Marks in columnsets:
175%D
176%D \starttyping
177%D \definemarking[M]
178%D \setupheadertexts[\setups{show-M-marks}]
179%D \definecolumnset[test][n=3]
180%D
181%D \startsetups show-M-marks
182%D \getmarking[M][1][previous]/\getmarking[M][1][first]/\getmarking[M][1][last]\quad
183%D \getmarking[M][2][previous]/\getmarking[M][2][first]/\getmarking[M][2][last]\quad
184%D \getmarking[M][3][previous]/\getmarking[M][3][first]/\getmarking[M][3][last]\quad
185%D \getmarking[M][1][previous]/\getmarking[M][1][first]/\getmarking[M][last]\quad
186%D \getsavedmarking[M][previous]/\getsavedmarking[M][first]/\getsavedmarking[M][last]
187%D \stopsetups
188%D
189%D \startbuffer
190%D \section{Knuth} [K1]\marking[M]{k1} [K2]\marking[M]{k2} \input knuth
191%D \section{Zapf}  [Z]\marking[M]{z} \input zapf
192%D \stopbuffer
193%D
194%D \startbuffer
195%D \section{Ward} [W]\marking[M]{w} \input ward
196%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
197%D \section{Davis} [D]\marking[M]{d} \input davis
198%D \section{Zapf} [Z]\marking[M]{z} \input zapf
199%D \stopbuffer
200%D
201%D \startbuffer
202%D \section{Ward} [W]\marking[M]{w} \input ward
203%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
204%D \section{Davis} [D]\marking[M]{d} \input davis
205%D \section{Zapf} [Z]\marking[M]{z} \input zapf
206%D \section{Douglas} [O]\marking[M]{o} \input douglas
207%D \stopbuffer
208%D
209%D \starttext
210%D   \startcolumnset[test]
211%D     \dorecurse{5}{\getbuffer}
212%D     \placefigure[here]{none}{\externalfigure[a][height=2cm]}
213%D     % \column % sometimes needed
214%D   \stopcolumnset
215%D \stoptext
216%D \stoptyping
217
218%D test case of Vit Zika (context list):
219%D
220%D \starttyping
221%D \setuplayout[height=middle,width=middle,grid=yes]
222%D
223%D \starttext
224%D   \startcolumnset
225%D     \dorecurse{10}
226%D       {\input thuan \endgraf
227%D        \bgroup
228%D        \ss\restoreinterlinespace
229%D        \dorecurse{3}{\input hawking \endgraf}
230%D        \egroup
231%D        \input bryson \endgraf}
232%D   \stopcolumnset
233%D \stoptext
234%D \stoptyping
235
236\def\OTRSETsetcorrectnofcells#1%
237  {\bgroup
238   \!!counta#1\relax
239   \ifdim\globalbodyfontsize=\localbodyfontsize
240     \restoreinterlinespace
241   \else
242     \!!dimena-\!!counta\lineheight
243     \restoreglobalbodyfont % slow, we need a fast one
244     \advance\!!dimena\!!counta\lineheight
245     \getnoflines\!!dimena
246     \advance\!!counta\noflines
247     \ifnum\!!counta<#1\else
248       \!!counta#1\relax
249     \fi
250   \fi
251   \relax % needed ! ! ! ! else lookahead over \fi and \expandafter
252   \expandafter\egroup\expandafter\scratchcounter\the\!!counta\relax}
253
254\def\OTRSETsetcorrectcellht
255  {\bgroup
256   \!!dimena-\strutht\relax
257   \ifdim\globalbodyfontsize=\localbodyfontsize
258     \restoreinterlinespace
259   \else
260     \restoreglobalbodyfont
261   \fi
262   \advance\!!dimena\strutht
263   \relax % needed ! ! ! ! else lookahead over \fi and \expandafter
264   \expandafter\egroup\expandafter\scratchdimen\the\!!dimena\relax}
265
266\def\doOTRSETsetgridcells#1#2#3#4#5#6% placeholder col row wid hei {data}
267  {\!!countd#2\advance\!!countd#4\advance\!!countd\minusone
268   \!!counte#3\advance\!!counte#5\advance\!!counte\minusone
269   \dostepwiserecurse{#2}\!!countd\plusone
270     {\!!countf\recurselevel
271      \dostepwiserecurse{#3}\!!counte\plusone
272        {\page_set_cell_set\!!countf\recurselevel#1}}%
273   \dostepwiserecurse{#3}\!!counte\plusone
274     {\wd\page_set_cell{#2}\recurselevel\hsize}%
275   \page_set_cell_set{#2}\!!counte#6}
276
277\def\OTRSETsetgridcells
278  {\doOTRSETsetgridcells{\copy\placeholderboxb}}
279
280\def\OTRSETerasegridcells#1#2#3#4%
281  {\doOTRSETsetgridcells{\emptybox}{#1}{#2}{#3}{#4}{\emptybox}}
282
283\unexpanded\def\setupcolumnsetlines{\doquintupleempty\dosetupcolumnsettrick[l]}
284\unexpanded\def\setupcolumnsetstart{\doquintupleempty\dosetupcolumnsettrick[s]}
285
286\installcorenamespace{columnsettag} % temp hack
287
288\def\dosetupcolumnsettrick[#1][#2][#3][#4][#5]% tag id page col value
289  {\iffifthargument
290     \setevalue{\??columnsettag:#1:#2:\number#3:\number#4}{\number#5}%
291   \else
292     \setevalue{\??columnsettag:#1:#2:\number#3:0}{\number#4}%
293   \fi}
294
295\def\currentcolumnmaxcellstag #1{\??columnsettag:l:\OTRSETidentifier:\columnsetpage:\number#1}
296\def\currentcolumnstartcelltag#1{\??columnsettag:s:\OTRSETidentifier:\columnsetpage:\number#1}
297
298\def\doresetcolumnsetlines#1%
299  {\ifcsname\currentcolumnmaxcellstag{#1}\endcsname
300     \letgvalue{\currentcolumnmaxcellstag{#1}}\zerocount
301   \fi
302   \ifcsname\currentcolumnmaxcellstag{#1}\endcsname
303     \letgvalue{\currentcolumnmaxcellstag{#1}}\zerocount
304   \fi}
305
306\def\currentcolumnsomecells#1#2%
307  {\ifcsname#1\mofcolumns\endcsname
308     \ifnum\csname#1\mofcolumns\endcsname=\zerocount
309       #2%
310     \else
311       \number\numexpr\ifnum\csname#1\mofcolumns\endcsname<\zerocount
312         \columnmaxcells+\fi\csname#1\mofcolumns\endcsname\relax
313     \fi
314   \else\ifcsname#10\endcsname
315     \ifnum\csname#10\endcsname=\zerocount
316       #2%
317     \else
318       \number\numexpr\ifnum\csname#10\endcsname<\zerocount
319         \columnmaxcells+\fi\csname#10\endcsname\relax
320     \fi
321   \else
322     #2%
323   \fi\fi}
324
325\def\currentcolumnmaxcells {\currentcolumnsomecells\currentcolumnmaxcellstag \columnmaxcells}
326\def\currentcolumnstartcell{\currentcolumnsomecells\currentcolumnstartcelltag\plusone}
327
328\def\OTRSETsetfreecells#1#2% col start
329  {\bgroup
330   \global\columnfirstcell\ifnum#2=0 1\else#2\fi\relax
331   \OTRSETsetcorrectnofcells\currentcolumnmaxcells % sets \scratchcounter
332   \ifnum\scratchcounter<\columnmaxcells\relax
333     \edef\columnmaxcells{\the\scratchcounter}% added 2013.04.19
334   \fi
335   \ifnum\columnfirstcell>\columnmaxcells
336     \global\columnfreecells\zerocount
337     \global\columnfirstcell\plusone
338     \global\columnlastcell \zerocount
339     \global\somefreecolumncellsfalse
340    %\message{no cells a}%
341   \else
342     \doloop
343       {\ifnum\columnfirstcell>\columnmaxcells\relax
344          \exitloop
345        \else
346          \page_set_cell_doifelse{#1}\columnfirstcell
347            {\global\advance\columnfirstcell\plusone}\exitloop
348        \fi}%
349     \global\columnlastcell\columnfirstcell
350     \doloop
351       {\ifnum\columnlastcell>\columnmaxcells\relax
352          \exitloop
353        \else
354          \page_set_cell_doifelse{#1}\columnlastcell
355            {\global\advance\columnlastcell \minusone \exitloop}
356            {\global\advance\columnlastcell \plusone }%
357        \fi}%
358     \ifnum\columnfirstcell>\columnmaxcells
359       \global\columnfreecells\zerocount
360       \global\columnfirstcell\plusone
361       \global\columnlastcell \zerocount
362       \global\somefreecolumncellsfalse
363      %\message{no cells b}%
364     \else
365       \ifnum\columnlastcell>\columnmaxcells
366         \global\columnlastcell\columnmaxcells
367       \fi
368       \global\columnfreecells\numexpr\columnlastcell-\columnfirstcell+\plusone\relax
369       \global\somefreecolumncellstrue
370      %\message{\number\columnfirstcell-\number\columnlastcell=\number\columnfreecells}%
371     \fi
372   \fi
373   \egroup}
374
375\def\OTRSETgetmaxfreecells#1#2% col start
376  {\let\columnmaxfreecells\!!zerocount
377   \let\columnfrmfreecells\!!zerocount
378   \pushmacro \columnmaxcells
379\OTRSETsetcorrectnofcells\currentcolumnmaxcells % sets \scratchcounter
380\edef\columnmaxcells{\the\scratchcounter}%
381   \scratchcounter\zerocount
382   \dostepwiserecurse{#2}\columnmaxcells\plusone
383     {\page_set_cell_doifelse{#1}\recurselevel
384        {\ifnum\columnmaxfreecells<\scratchcounter
385           \edef\columnmaxfreecells{\the\scratchcounter}%
386           \let\columnfrmfreecells\recurselevel
387         \fi
388         \scratchcounter\zerocount}
389        {\advance\scratchcounter\plusone}}%
390   \popmacro\columnmaxcells}
391
392\def\OTRSETrecurseRL#1%
393  {\dostepwiserecurse\nofcolumns\plusone\minusone
394     {#1\hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}}
395
396\def\OTRSETmakegridbox
397  {\ifcase\columndirection
398     \OTRSETdomakegridbox\plusone\nofcolumns\plusone
399   \else
400     \OTRSETdomakegridbox\nofcolumns\plusone\minusone
401   \fi}
402
403\def\OTRSETmakeupwidth{\makeupwidth} % temporary indirectness
404
405\def\page_set_make_background_box
406  {\begingroup
407   \mofcolumns\recurselevel % used to signal mp
408   \d_page_set_local_hsize\OTRSETlocalwidth\recurselevel
409   \scratchdistance\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance\relax
410   \edef\currentcolumnset{\currentcolumnset:\recurselevel}%
411   \letcolumnsetparameter\c!width \d_page_set_local_hsize
412   \letcolumnsetparameter\c!height\!!heighta
413   \letcolumnsetparameter\c!lines \empty
414   \letcolumnsetparameter\c!region\currentcolumnset
415   \setbox\scratchbox\hpack\inheritedcolumnsetframed{}% maybe \fastlocalframed
416   \wd\scratchbox\d_page_set_local_hsize
417   \ht\scratchbox\!!heighta
418   \ifcase\columndirection
419     \hskip\scratchdistance
420     \box\scratchbox
421   \else
422     \box\scratchbox
423     \hskip\scratchdistance
424   \fi
425   \endgroup}
426
427\def\OTRSETdomakegridbox#1#2#3%
428  {\hbox\bgroup
429   \dontcomplain
430   \forgetall % can go once in \flush
431   \!!heighta \textheight
432   % test first !
433   \hbox to \OTRSETmakeupwidth
434     {\dostepwiserecurse{#1}{#2}{#3}\page_set_make_background_box}%
435   \hskip-\OTRSETmakeupwidth
436   % main text
437   \hbox to \OTRSETmakeupwidth
438     {\dostepwiserecurse{#1}{#2}{#3}
439        {\mofcolumns\recurselevel
440         \d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
441         \offinterlineskip
442         \setbox\scratchbox\vbox to \!!heighta
443           {%\topskipcorrection % not needed
444            \ifcase\OTRSETbalancemethod
445              % no
446            \or
447              % yes
448              \doifelselayerdata{OTRTEXT}\vfill\relax % temp hack
449            \or
450              % top
451            \or
452              % bottom
453              \vfill
454            \fi
455            \dorecurse\columnmaxcells
456              {\setbox\scratchbox\hbox{\page_set_cell_get\mofcolumns\recurselevel}%
457               \ht\scratchbox\strutht
458               \dp\scratchbox\strutdp
459               \ifcase\columndirection
460                 \box\scratchbox
461               \else
462                 \hbox to \d_page_set_local_hsize
463                   {\hskip\d_page_set_local_hsize\llap{\box\scratchbox}}%
464               \fi
465               \par}%
466            \ifcase\OTRSETbalancemethod
467              % no
468            \else
469              % yes, top, bottom
470              \ifdim\globalbodyfontsize=\localbodyfontsize
471                \removedepth
472                \restoreglobalbodyfont
473                \vskip\strutdepth
474              \fi
475              \kern\zeropoint
476              \vss
477            \fi}%
478         \wd\scratchbox\d_page_set_local_hsize % \textwidth
479         \page_marks_synchronize_column{#1}{#2}\recurselevel\scratchbox
480         \ifcase\columndirection
481           \hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance\box\scratchbox
482         \else
483           \box\scratchbox\hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance
484         \fi}}%
485   \egroup}
486
487\let\OTRSETbalht\zeropoint
488
489\def\OTRSETreducegridbox % for the moment no difference between methods
490  {\glet\OTRSETbalht\zeropoint
491   \ifcase\OTRSETbalancemethod
492     % no balancing
493   \else
494     \bgroup
495     \!!counta\columnmaxcells
496     \donetrue
497     \doloop
498       {\dorecurse\nofcolumns{\page_set_cell_doifelse\recurselevel\!!counta\donefalse\donothing}%
499        \ifdone
500          \ifnum\!!counta>\plusone\advance\!!counta\minusone\else\exitloop\fi
501        \else
502          \exitloop
503        \fi}%
504     \ifnum\!!counta>\plusone
505       \!!heighta\lineheight
506       \multiply\!!heighta \!!counta
507       \advance\!!heighta \topskip
508       \advance\!!heighta -\lineheight
509     \else
510       \!!heighta\zeropoint
511     \fi
512     \xdef\OTRSETbalht{\the\!!heighta}%
513     \egroup
514   \fi}
515
516\def\OTRSETflushfinalfootnotes
517  {\ifcase\lastcolumnlastcell \else
518     \setbox\scratchbox\hbox
519       {\placebottomnotes}%
520     \ifdim\ht\scratchbox>\zeropoint
521       \setbox\scratchbox\hbox
522         {\hbox to \zeropoint{\page_set_cell_get\nofcolumns\lastcolumnlastcell}%
523          \box\scratchbox}%
524       \ht\scratchbox\strutht
525       \dp\scratchbox\strutdp
526       \page_set_cell_set\nofcolumns\lastcolumnlastcell\box\scratchbox
527     \fi
528     \global\lastcolumnlastcell\zerocount
529   \fi}
530
531\def\OTRSETdoflush
532  {\ifcollectingsetcontent
533     \global\mofcolumns\plusone
534   \else
535     \OTRSETdofinalflush
536     \OTRSETdofinaloutput
537     \ifnum\columnsetpage>\zerocount
538       \dorecurse\nofcolumns{\doresetcolumnsetlines\recurselevel}%
539     \fi
540     \doglobal\increment\columnsetpage
541     \OTRSETinitializecolumns
542     \OTRSETstartnextpage
543     \initializecolumntextareas
544   \fi}
545
546\newbox\OTRfinalpagebox
547
548\def\OTRSETdofinalflush % see \OTRSETdoflush
549  {\OTRSETflushfinalfootnotes
550   \placecolumntextareas
551   \OTRSETcentergridcells
552   \bgroup % we want to keep the reduction local
553     \OTRSETreducegridbox
554     \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
555   \egroup % otherwise we get the wrong number of free cells
556  %\gdef\localcolumnmaxcells{0}% here ?
557   \global\mofcolumns\nofcolumns} % otherwise problems in finaloutput
558
559\def\OTRSETdofinaloutput
560  {\ifdim\ht\OTRfinalpagebox=\textheight
561     \bgroup
562     \ifcase\OTRSETbalancemethod
563       \page_otr_construct_and_shipout\box\OTRfinalpagebox\zerocount % three arguments
564     \else\ifdim\OTRSETbalht>\zeropoint
565       % catch a bordercase
566       \scratchdimen\OTRSETbalht
567       \advance\scratchdimen\lineheight\relax
568       \ifdim\scratchdimen>\textheight
569         % full page
570         \page_otr_construct_and_shipout\box\OTRfinalpagebox\zerocount % three arguments
571       \else
572         % same page
573         \global\setbox\OTRfinalpagebox \iftracecolumnset\ruledvbox\else\vbox\fi to \OTRSETbalht
574           {\box\OTRfinalpagebox\vss}%
575         \setlayer[OTRTEXT]{\box\OTRfinalpagebox}%
576         \snaptogrid\vbox{\vskip\OTRSETbalht}% hack
577       \fi
578     \else
579       \page_otr_construct_and_shipout\box\OTRfinalpagebox\zerocount % three arguments
580     \fi \fi
581     \glet\OTRSETbalht\zeropoint
582     \egroup
583   \fi}
584
585\definesystemconstant {colset}
586
587\definetwopasslist\s!colset
588
589\newdimen  \OTRSETtextswidth
590\newdimen  \OTRSETtextsheight
591\let       \OTRSETidentifier=\empty
592
593\def\OTRSETskipstart
594  {\doifelsenothing{\columnsetparameter\c!start}
595     {\scratchcounter\zerocount}%
596     {\scratchcounter\columnsetparameter\c!start}%
597   \relax % needed !
598   \ifcase\scratchcounter\else
599     \advance\scratchcounter\plusone
600     \doOTRSETsetgridcells
601       {\copy\placeholderboxe}
602       \plusone\plusone\nofcolumns\scratchcounter
603       \emptybox
604   \fi}
605
606\unexpanded\def\page_set_command_set_vsize % snap per sectie (gap here?)
607  {\ifcollectingsetcontent \else % can be assigndimen
608     \OTRSETsetcolumnmaxcells % layout can be changed
609     \OTRSETskipstart % not that well tested
610     \OTRSETcheckinsert % added
611     \OTRSETsetfreecells\mofcolumns\columnfirstcell
612     \ifsomefreecolumncells
613       \global\vsize\columnfreecells\lineheight
614       \ifinotr % else problems with floats, see extreme
615         \pagegoal\vsize % niet nodig, tenzij binnen otr
616       \fi
617       \synchronizeoutput % fails on example, try \triggerpagebuilder instead
618      % \allowbreak % hm
619     \fi
620     \synchronizenotes
621   \fi}
622
623\def\page_set_command_set_hsize  % of course this does not migrate outside the otr
624  {\d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
625   \textwidth\d_page_set_local_hsize
626   \hsize\d_page_set_local_hsize}
627
628\unexpanded\def\page_set_command_synchronize_hsize
629  {\ifconditional\c_page_set_width_set
630     \bgroup
631     \scratchdimen\OTRSETlocalwidth\mofcolumns
632     \ifdim\scratchdimen=\textwidth
633       \egroup
634     \else
635       % only if change in width and \column/\break
636       \egroup
637       \page_set_command_set_hsize
638     \fi
639   \fi}
640
641\def\OTRSETcheckfreelines
642  {\page_set_command_set_vsize}
643
644\def\doOTRSETcolumnseparator
645  {\hpack to \zeropoint{\hss\red\vl\hss}}
646
647\let\OTRSETcolumnseparator\relax
648
649\def\showbreaks
650  {\let\OTRSETcolumnseparator\doOTRSETcolumnseparator}
651
652\def\OTRSETcolumnhbreak
653  {\ifhmode
654     \bgroup
655     \removeunwantedspaces
656     \parfillskip\zeropoint
657     \OTRSETcolumnseparator
658     \par
659     \egroup
660   \fi}
661
662\installcolumnbreakmethod \s!columnset \v!local
663  {\OTRSETcolumnhbreak
664   \page_set_command_flush_all_floats
665   \page_otr_eject_page
666   % no \page_set_command_set_hsize, can be mid smaller (like tabulate)
667   % also, this one should be executed at the outer level
668   % (setting hsize inside otr does not work)
669   \page_set_command_synchronize_hsize}
670
671% We need to make sure that we really leave the column; mid
672% column we may end up in an empty gap, and we don't want to
673% stay there (basically such a gap is a small empty page
674% then).
675
676\installcolumnbreakmethod \s!columnset \v!yes
677  {\OTRSETcolumnhbreak
678   \edef\savedmofcolumns{\the\mofcolumns}%
679   \edef\savedrealpageno{\the\realpageno}%
680   \page_otr_flush_all_floats
681   \page_otr_eject_page
682   \doloop
683     {\ifnum\savedmofcolumns=\mofcolumns
684        \ifnum\savedrealpageno=\realpageno
685          \OTRSETdummycolumn
686        \else
687          \exitloop
688        \fi
689      \else
690        \exitloop
691      \fi}%
692   \page_set_command_synchronize_hsize}
693
694\installcolumnbreakmethod \s!columnset \s!unknown
695  {\expanded{\OTRSETgotocolumn[\@@columnspecification]}}
696
697\installcolumnbreakmethod \s!columnset \v!page
698  {\page_otr_fill_and_eject_page}
699
700\newtoks\OTRSETeverystartofcolumn
701
702\newbox\OTRSETsavedfootnotes
703
704% \installoutputroutine\OTRSETflushtextsofar % spacing goes wrong
705
706%\def\OTRSETflushtextsofar
707%  {\ifvoid\normalpagebox \else
708%     \setbox\scratchbox\vbox{\unvbox\normalpagebox}%
709%     \OTRSETsavenotes
710%     \OTRSEThandleflushedtext0
711%   \fi}
712
713% The complication is in the fact that when the HERE float
714% is placed, the otr is not invoked when there is not yet
715% enough content; this can lead to a change in order (turning
716% on the tracer with option 0 is very instructive, watch the
717% small numbers in the margin)
718%
719% 0 = no flushing, so no interference but user should handle
720%     border cases of placement
721% 1 = the normal otr, rather untested
722% 2 = a solution that works ok, is experimental and above
723%     all messy
724
725\newconstant\OTRSETflushtextmode % will be replaced
726
727\def\OTRSETflushtextsofar % needs renaming
728  {\ifcase\OTRSETflushtextmode
729     % don't mess around
730   \or
731     % the normal one
732     \ifvoid\normalpagebox\else
733       \OTRSETnaturalflush
734       \OTRSETcheckfreelines
735     \fi
736   \or
737     % way to complicated, but kind of ok
738     \doOTRSETflushtextsofar
739   \fi}
740
741\newskip\lastskipinotr
742
743\installoutputroutine\doOTRSETflushtextsofar % experimental
744  {\ifvoid\normalpagebox\else
745     \scratchdimen\dp\normalpagebox
746     \setbox\scratchbox\vbox
747       {\forgetall
748        \unvbox\normalpagebox
749        \global\lastskipinotr\lastskip\relax
750        \ifdim\lastskipinotr>\zeropoint\relax
751          \removelastskip
752        \else
753          \kern-\scratchdimen % handle depth
754        \fi}%
755     \ifdim\lastskipinotr>\zeropoint
756       \scratchskip\ht\scratchbox
757       \setbox\scratchbox\hpack
758         {\lower\strutdepth\box\scratchbox}%
759       \dp\scratchbox\scratchdimen
760       \ht\scratchbox\scratchskip
761     \fi
762     \OTRSETsavenotes
763     \OTRSEThandleflushedtext\zerocount
764     \ifdim\lastskipinotr>\zeropoint
765       %\vskip \lastskipinotr % hm, gets lost anyway
766     \else
767       % we should not discard skips after here; tricky
768     \fi
769     \page_set_command_set_vsize
770   \fi}
771
772\def\OTRSETplacebottomnotes
773  {\iflastcolumnfootnotes
774     \ifnum\nofcolumns=\mofcolumns
775       \ifintermediatefootnotes \placebottomnotes \fi
776     \fi
777   \else
778     \placebottomnotes
779   \fi}
780
781\def\OTRSETflushsavednotes
782  {\iflastcolumnfootnotes
783     \ifnum\nofcolumns=\mofcolumns
784       \flushsavednotes
785     \fi
786   \else
787     \flushsavednotes
788   \fi}
789
790\def\OTRSETsavenotes
791  {\iflastcolumnfootnotes
792     \ifnum\nofcolumns=\mofcolumns \else
793       \savenotes
794     \fi
795   \fi}
796
797\appendtoks \OTRSETflushsavednotes \to \OTRSETeverystartofcolumn
798
799\def\OTRSETnaturalflush
800  {\bgroup
801   \forgetall % new, needed !
802   \setbox0\vbox to \columnfreecells\lineheight
803     {\vskip-\topskip
804      \vskip\lineheight
805      \prevdepth\strutdp
806      \unvbox\normalpagebox
807      \vfill}%
808   \setbox2\hbox
809     {\OTRSETplacebottomnotes}%
810   \setbox\scratchbox\hbox
811     {\wd0\zeropoint\box0\box2}%
812   \dp\scratchbox\strutdp
813   \OTRSEThandleflushedtext\plusone
814   \egroup}
815
816\newcount\lastcolumnlastcell
817
818\def\OTRSEThandleflushedtext#1%
819  {\getnoflines{\ht\scratchbox}%
820  %\wd\scratchbox\textwidth % geen \hsize kan < zijn in bv split tabulate
821   \wd\scratchbox\OTRSETlocalwidth\mofcolumns
822   \doOTRSETsetgridcells
823     {\copy\placeholderboxf}
824     \mofcolumns\columnfirstcell\plusone\noflines
825     {\page_areas_registered_box1\columnfirstcell\scratchbox}% == \hbox / tricky htcorr == \columnfirstcell
826   \global\columnlastcell\columnfirstcell
827   \global\advance\columnlastcell \noflines
828   \global\lastcolumnlastcell\columnlastcell
829   \global\advance\lastcolumnlastcell \minusone
830   % find next (acceptable) gap, todo: deadcycle
831   \ifcase#1\else
832     \OTRSETfillgapsbetweencells\mofcolumns\columnlastcell
833   \fi
834   \OTRSETfindnextgap
835   % \message{\the\mofcolumns,\the\columnfirstcell,\the\columnfreecells}%
836   % \wait
837   % we cannot adapt the hsize since it may have changed (like
838   % inside a tabulate) so we only change it when there is a
839   % reason to do so
840   \page_set_command_synchronize_hsize
841   \page_set_command_set_vsize}
842
843\def\OTRSETfindnextgap
844  {\OTRSETsetfreecells\mofcolumns\columnlastcell
845   \ifsomefreecolumncells
846     % okay
847   \else
848     \global\advance\mofcolumns \plusone
849     \ifnum\mofcolumns>\nofcolumns
850       \OTRSETdoflush
851       \global\columnlastcell\plusone
852       \global\columnfirstcell\zerocount
853       \page_set_command_flush_floats
854     \else
855       \the\OTRSETeverystartofcolumn
856       \global\columnlastcell\plusone
857       \global\columnfirstcell\zerocount
858     \fi
859   \fi}
860
861\let\OTRSETcheckfreelines\donothing
862
863\def\OTRSETfillgapsbetweencells#1#2% col
864  {\ifnum\columngaplimit>\zerocount
865     \donefalse
866     \dostepwiserecurse{#2}\columnmaxcells\plusone
867       {\page_set_cell_doifelse{#1}\recurselevel
868          {\ifdone
869             \!!countb\recurselevel \advance\!!countb -\!!counta\relax
870             \ifnum\!!countb>\plusone
871               \advance\!!countb \minusone
872               \ifnum\!!countb<\columngaplimit\relax
873                 \!!countb\recurselevel \advance\!!countb \minusone
874                 \dostepwiserecurse\!!counta\!!countb\plusone
875                   {\page_set_cell_set{#1}\recurselevel\copy\placeholderboxc}%
876                %\message{[gap]}%
877               \fi
878             \fi
879           \fi
880           \donefalse}
881          {\ifdone \else
882             \donetrue
883             \!!counta\recurselevel
884           \fi}}%
885   \fi}
886
887\appendtoks
888  \OTRSETfillgapsbetweencells\mofcolumns\plusone
889\to \OTRSETeverystartofcolumn
890
891\newif\ifspancolumnslots \spancolumnslotstrue
892\newif\ifcheckcolumnspan \checkcolumnspantrue
893
894\def\OTRSETcheckwidthgap#1#2% box size
895  {\ifcheckcolumnspan
896     \bgroup
897     \scratchdimen#2%
898     \advance\scratchdimen-\wd#1\relax
899     \ifdim-10\scaledpoint>\scratchdimen
900       \egroup
901     \else\ifdim10\scaledpoint<\scratchdimen
902       \egroup
903     \else
904       \egroup
905       \wd#1=#2%
906     \fi\fi
907   \fi}
908
909\def\OTRSETcheckcolumnslot#1%
910  {\enoughcolumncellstrue
911   \ifspancolumnslots\else
912     \OTRSETcheckwidthgap#1\hsize
913     \ifdim\wd#1>\hsize
914       \enoughcolumncellsfalse
915     \fi
916   \fi
917   \ifenoughcolumncells
918     \getnoflines\pagetotal
919     \scratchcounter\noflines
920     \getnoflines{\ht#1}%
921     \columnvcells\noflines
922     \columnhcells\plusone
923     \advance\scratchcounter \columnvcells \relax
924     \ifnum\scratchcounter>\columnfreecells
925       \enoughcolumncellsfalse
926     \fi
927   \fi}
928
929\def\OTRSETstoreincolumnslotPAGE#1%
930  {\ifenoughcolumncells
931     % to do
932     \OTRSETsavebox{#1}%
933   \else
934     \OTRSETsavebox{#1}%
935   \fi}
936
937\def\OTRSETstoreincolumnslotTOPS#1%
938  {\OTRSETprepareforcolumnslot1{#1}%
939   \OTRSETcheckcolumnslot{#1}%
940   \ifenoughcolumncells
941     \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
942   \fi
943   \ifenoughcolumncells
944     \OTRSETsetgridcells\mofcolumns\columnfirstcell\columnhcells\columnvcells
945       {\hpack{\copy#1}}%
946     \page_set_command_set_vsize
947   \else
948     \OTRSETsavebox{#1}%
949   \fi}
950
951\def\OTRSETstoreincolumnslotBOTS#1%
952  {\OTRSETprepareforcolumnslot3{#1}%
953   \edef\savedcolumnlastcell{\the\columnlastcell}%
954   \OTRSETcheckcolumnslot{#1}%
955   \ifenoughcolumncells
956     \advance\columnlastcell -\columnvcells \advance\columnlastcell \plusone
957%     \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
958     \OTRSETcheckcolumnspace\mofcolumns\columnlastcell{#1}%
959   \fi
960   \ifenoughcolumncells
961     \OTRSETsetgridcells\mofcolumns\columnlastcell\columnhcells\columnvcells{\copy#1}%
962     \OTRSETfillgapsbetweencells\mofcolumns\savedcolumnlastcell % -)
963     \page_set_command_set_vsize
964   \else
965     \columnlastcell\savedcolumnlastcell
966     \OTRSETsavebox{#1}%
967   \fi}
968
969\newdimen\totalcolumnspace
970
971\def\columnspacetopoffset{0}
972\def\columnspacebotoffset{0}
973
974\def\OTRSETcheckcolumnspace#1#2#3% col row box
975  {\columnhcells\plusone
976   \totalcolumnspace\zeropoint
977   \scratchcounter#1%
978   \enoughcolumncellstrue
979   \doloop
980     {\advance\totalcolumnspace \OTRSETlocalwidth\scratchcounter\relax % needed
981\OTRSETcheckwidthgap#3\totalcolumnspace
982      \ifnum\wd#3>\totalcolumnspace\relax
983        \ifnum\scratchcounter=\nofcolumns
984          \enoughcolumncellsfalse
985          \exitloop
986        \else
987          \advance\columnhcells \plusone
988          \advance\scratchcounter \plusone
989          \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\number\scratchcounter}\c!distance
990        \fi
991      \else
992        \exitloop
993      \fi}%
994   \ifenoughcolumncells
995     \getnoflines{\ht#3}%
996     \columnvcells\noflines
997     \OTRSETcheckcolumncells{#1}{#2}\columnhcells\columnvcells
998   \fi}
999
1000\def\OTRSETcheckcolumncells#1#2#3#4% col row wid hei
1001  {\!!countd#1\advance\!!countd#3\advance\!!countd\minusone
1002   \!!counte#2\advance\!!counte#4\advance\!!counte\minusone
1003   \ifnum\!!counte>\columnmaxcells\relax
1004     \enoughcolumncellsfalse
1005   \else
1006     \enoughcolumncellstrue
1007%\let\columnspacetopoffset\zerocount
1008%\scratchcounter#2\advance\scratchcounter\minusone
1009%\ifnum\scratchcounter>0
1010%  \dostepwiserecurse{#1}\!!countd\plusone
1011%    {\ifdim\wd\page_set_cell\recurselevel\scratchcounter>\zeropoint
1012%       \let\columnspacetopoffset\plusone
1013%     \else\ifdim\dp\page_set_cell\recurselevel\scratchcounter>\zeropoint
1014%       \let\columnspacetopoffset\plusone
1015%     \fi\fi}%
1016%  \advance\!!counte \columnspacetopoffset \relax
1017%  \advance\columnvcells \columnspacetopoffset \relax
1018%\fi
1019%\let\columnspacebotoffset\zerocount
1020%\scratchcounter\!!counte
1021%\advance\scratchcounter \columnvcells \relax
1022%\ifnum\scratchcounter>\columnmaxcells\else
1023%  \dostepwiserecurse{#1}\!!countd\plusone
1024%    {\ifdim\wd\page_set_cell\recurselevel\scratchcounter>\zeropoint
1025%       \let\columnspacebotoffset\plusone
1026%     \else\ifdim\dp\page_set_cell\recurselevel\scratchcounter>\zeropoint
1027%       \let\columnspacebotoffset\plusone
1028%     \fi\fi}%
1029%  \advance\!!counte \columnspacebotoffset \relax
1030%  \advance\columnvcells \columnspacebotoffset \relax
1031%\fi
1032     \dostepwiserecurse{#1}\!!countd\plusone % cols
1033       {\ifenoughcolumncells
1034          \!!countf\recurselevel\relax
1035          \dostepwiserecurse{#2}\!!counte\plusone % rows
1036            {\ifenoughcolumncells
1037               \page_set_cell_doifelse\!!countf\recurselevel
1038                 {\enoughcolumncellsfalse}{}%
1039             \fi}%
1040        \fi}%
1041   \fi}
1042
1043\let\pofcolumns\mofcolumns
1044\let\qofcolumns\mofcolumns
1045
1046\newif\ifquitincurrentcolumn
1047
1048\def\OTRSETstoreincolumnslotLRTB#1%
1049  {\OTRSETprepareforcolumnslot1{#1}%
1050   \OTRSETflushtextsofar
1051   \OTRSETstoreincolumnslotindeed
1052     \mofcolumns\nofcolumns+\currenthcell
1053     \plusone\columnmaxcells+\currentvcell{#1}}
1054
1055\def\OTRSETstoreincolumnslotLRBT#1%
1056  {\OTRSETprepareforcolumnslot3{#1}%
1057   \OTRSETflushtextsofar
1058   \OTRSETstoreincolumnslotindeed
1059     \mofcolumns\nofcolumns+\currenthcell
1060     \columnmaxcells\plusone-\currentvcell{#1}}
1061
1062\def\OTRSETstoreincolumnslotRLTB#1%
1063  {\OTRSETprepareforcolumnslot1{#1}%
1064   \OTRSETflushtextsofar
1065   \OTRSETcheckprefered
1066   \OTRSETstoreincolumnslotindeed
1067     \nofcolumns\qofcolumns-\currenthcell
1068     \plusone\columnmaxcells+\currentvcell{#1}}
1069
1070\def\OTRSETstoreincolumnslotRLBT#1%
1071  {\OTRSETprepareforcolumnslot3{#1}%
1072   \OTRSETflushtextsofar
1073   \OTRSETcheckprefered
1074   \OTRSETstoreincolumnslotindeed
1075     \nofcolumns\qofcolumns-\currenthcell
1076     \columnmaxcells\plusone-\currentvcell{#1}}
1077
1078\def\OTRSETstoreincolumnslotTBLR#1%
1079  {\OTRSETprepareforcolumnslot1{#1}%
1080   \OTRSETflushtextsofar
1081   \OTRSETstoreincolumnslotindeed
1082     \plusone\columnmaxcells+\currentvcell
1083     \mofcolumns\nofcolumns+\currenthcell{#1}}
1084
1085\def\OTRSETstoreincolumnslotTBRL#1%
1086  {\OTRSETprepareforcolumnslot1{#1}%
1087   \OTRSETflushtextsofar
1088   \OTRSETcheckprefered
1089   \OTRSETstoreincolumnslotindeed
1090     \plusone\columnmaxcells+\currentvcell
1091     \nofcolumns\qofcolumns-\currenthcell{#1}}
1092
1093\def\OTRSETstoreincolumnslotBTLR#1%
1094  {\OTRSETprepareforcolumnslot3{#1}%
1095   \OTRSETflushtextsofar
1096   \OTRSETstoreincolumnslotindeed
1097     \columnmaxcells\plusone-\currentvcell
1098     \mofcolumns\nofcolumns+\currenthcell{#1}}
1099
1100\def\OTRSETstoreincolumnslotBTRL#1%
1101  {\OTRSETprepareforcolumnslot3{#1}%
1102   \OTRSETflushtextsofar
1103   \OTRSETcheckprefered
1104   \OTRSETstoreincolumnslotindeed
1105     \columnmaxcells\plusone-\currentvcell
1106     \nofcolumns\qofcolumns-\currenthcell{#1}}
1107
1108\def\OTRSETstoreincolumnslotFXTB#1% fixed column
1109  {\OTRSETcheckprefered
1110   \page_set_cell_doifelse\pofcolumns\plusone
1111     {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot1}{#1}% % 1/2 dependent of place, todo
1112   \OTRSETflushtextsofar
1113   \OTRSETstoreincolumnslotindeed
1114     \pofcolumns \pofcolumns +\currenthcell
1115     \floatrow\columnmaxcells+\currentvcell{#1}}
1116
1117\def\OTRSETstoreincolumnslotFXBT#1% fixed column
1118  {\OTRSETcheckprefered
1119   \page_set_cell_doifelse\pofcolumns\columnmaxcells
1120     {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot3}{#1}% % 3/2 dependent of place, todo
1121   \OTRSETflushtextsofar
1122   \OTRSETstoreincolumnslotindeed
1123     \pofcolumns    \pofcolumns+\currenthcell
1124     \columnmaxcells\floatrow  -\currentvcell{#1}}
1125
1126\newconstant\OTRSETforcefixedfloats
1127
1128\def\OTRSETstoreincolumnslotHERE#1% fixed column
1129  {\ifcase\OTRSETforcefixedfloats
1130     \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
1131   \else
1132     \OTRSETstoreincolumnslotFIXD{#1}%
1133   \fi}
1134
1135% this one looses too wide graphics
1136%
1137% \def\OTRSETstoreincolumnslotFIXD#1% fixed column
1138%   {\OTRSETprepareforcolumnslot2{#1}%
1139%    % no flush text sofar here, beware: no width test
1140%    \snaptogrid\vbox{\box#1}}
1141%
1142% still imperfect
1143
1144\def\OTRSETstoreincolumnslotFIXD#1% fixed column
1145  {\OTRSETflushtextsofar
1146   \ifdim\wd#1>\textwidth
1147     \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
1148   \else
1149     % crappy test / needed for o-pbu-f / will be replaced
1150     \getnoflines{\ht#1}%
1151     \scratchdimen\noflines\lineheight
1152     \advance\scratchdimen\lineheight
1153     \advance\scratchdimen\pagetotal\relax
1154     \ifdim\scratchdimen<\pagegoal
1155       %OTRSETprepareforcolumnslot3{#1}%
1156       %ruledvskip\columnslotspacing\lineheight
1157       \blank[\number\columnslotspacing*\v!line]%
1158       \snaptogrid\hpack to \hsize{\hss\box#1\hss}% strange, why the centering
1159       \blank[\number\columnslotspacing*\v!line]%
1160     \else
1161       \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
1162     \fi
1163   \fi}
1164
1165\def\OTRSETstoreincolumnslotSOMEWHERE#1#2%
1166  {\OTRSETprepareforcolumnslot{#1}{#2}%
1167   \OTRSETflushtextsofar
1168   \getnoflines\pagetotal \advance\noflines\columnfirstcell
1169   \OTRSETstoreincolumnslotindeed
1170     \mofcolumns\mofcolumns+\currenthcell
1171     \noflines\columnmaxcells+\currentvcell{#2}%
1172   \page_set_command_set_vsize}
1173
1174\def\OTRSETcheckprefered
1175  {\ifx\floatcolumn\empty
1176     \let\pofcolumns\nofcolumns
1177   \else\ifnum\floatcolumn<\mofcolumns
1178     \let\pofcolumns\mofcolumns
1179   \else
1180     \let\pofcolumns\floatcolumn
1181   \fi\fi
1182   \ifx\floatrow\empty
1183     \let\pofcolumns\plusone
1184   \fi
1185   \ifquitincurrentcolumn
1186     \ifnum\mofcolumns=\nofcolumns
1187       \def\qofcolumns{\mofcolumns}%
1188     \else
1189       \scratchcounter\mofcolumns
1190       \advance\scratchcounter \plusone
1191       \edef\qofcolumns{\the\scratchcounter}%
1192     \fi
1193   \else
1194     \let\qofcolumns\mofcolumns
1195   \fi}
1196
1197\def\OTRSETstoreincolumnslotindeed#1#2#3#4#5#6#7#8#9%
1198  {\OTRSETcheckprefered
1199   \enoughcolumncellsfalse
1200   \donefalse
1201   \dostepwiserecurse{#1}{#2}{#31}
1202     {\ifdone
1203        \exitloop
1204      \else
1205        #4=\recurselevel
1206        \dostepwiserecurse{#5}{#6}{#71}
1207          {\ifdone
1208             \exitloop
1209           \else
1210             #8=\recurselevel
1211             \OTRSETcheckcolumnspace\currenthcell\currentvcell{#9}%
1212             \ifenoughcolumncells \donetrue \fi
1213           \fi}%
1214      \fi}%
1215   \ifdone
1216     \enoughcolumncellstrue
1217   \else
1218     \enoughcolumncellsfalse
1219   \fi
1220   \ifenoughcolumncells
1221%    \ifnum\columnspacetopoffset>0\message{[+++]}\fi
1222%    \ifnum\columnspacebotoffset>0\message{[---]}\fi
1223%    \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
1224%      {\vbox
1225%         {\ifcase\columnspacetopoffset\else\ruledvskip\columnspacetopoffset\lineheight\fi
1226%          \copy#9
1227%          \ifcase\columnspacebotoffset\else\ruledvskip\columnspacebotoffset\lineheight\fi}}%
1228     \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
1229       {\copy#9}%
1230     \ifnum\currenthcell=\mofcolumns\relax
1231       \ifdim\ht\OTRSETsavedfootnotes>\zeropoint
1232         \OTRSETsetfreecells\mofcolumns\columnfirstcell
1233         \ifsomefreecolumncells
1234           \getnoflines{\ht\OTRSETsavedfootnotes}\relax
1235           \ifnum\columnfreecells<\noflines
1236             \global\somefreecolumncellsfalse
1237           \else
1238            %\message{[flt]}% float
1239           \fi
1240         \fi
1241         \ifsomefreecolumncells
1242           % ok, enough room for notes
1243          %\message{[flt]}% float
1244         \else % ?
1245           \OTRSETsavebox{#9}%
1246           \OTRSETerasegridcells\currenthcell\currentvcell\columnhcells\columnvcells
1247          %\message{[clr]}% save box
1248         \fi
1249       \else
1250        %\message{[flt]}% float
1251       \fi
1252     \else
1253      %\message{[flt]}% float
1254     \fi
1255     \page_set_command_set_vsize
1256    %\message{[fnt]}% float
1257   \else
1258    %\message{[rej]}% save box
1259     \OTRSETsavebox{#9}%
1260   \fi}
1261
1262\setnewconstant\columnslotspacing\plusone
1263
1264\def\OTRSETstoreincolumnslot#1% #2 % {method} {box} % alleen last
1265  {% no messing around here
1266   % \dp#2=\zeropoint
1267   % \ifcase\columnslotspacing\else
1268   %   \setbox#2=\vbox spread \columnslotspacing\lineheight
1269   %     {\vss\box#2\vss}%
1270   % \fi
1271   % and don't change this any more
1272%   \doifdefinedelse{\csstring\OTRSETstoreincolumnslot#1}
1273%     {\getvalue{\csstring\OTRSETstoreincolumnslot#1}{#2}}
1274%     {\OTRSETstoreincolumnslotUNKNOWN{#2}}}
1275   \executeifdefined{\csstring\OTRSETstoreincolumnslot#1}
1276     \OTRSETstoreincolumnslotUNKNOWN} % {#2}}
1277
1278\def\OTRSETstoreincolumnslotUNKNOWN#1%
1279  {\OTRSETprepareforcolumnslot2{#1}\copy#1} % {} ?
1280
1281\def\OTRSETprepareforcolumnslot#1#2% 1=hoog 2=midden 3=laag
1282  {\dp#2\zeropoint
1283   \ifcase\columnslotspacing\else
1284     \scratchdimen\columnslotspacing\lineheight
1285     \ifnum#1=2 \scratchdimen2\scratchdimen \fi
1286     \begingroup
1287     \advance\scratchdimen\ht#2\relax
1288     \ifdim\scratchdimen<\columnmaxcells\lineheight
1289       \endgroup \setbox#2\vbox spread \scratchdimen \bgroup
1290     \else
1291       \endgroup \setbox#2\vbox to \columnmaxcells\lineheight \bgroup
1292       \vskip\strutdepth
1293     \fi
1294     \ifnum#1>1\vss\fi
1295     \box#2\relax
1296     \ifnum#1<3\vss\fi
1297     \egroup
1298   \fi}
1299
1300\unexpanded\def\page_set_command_check_if_float_fits
1301  {\global\ifconditional\c_page_floats_not_permitted\setfalse\c_page_floats_room\else\settrue\c_page_floats_room\fi}
1302
1303\def\OTRSETunpreparebox#1%
1304  {\ifhbox#1% spans and so
1305     \global\setbox\floatbox\vbox{\box#1}%
1306   \else
1307     \setbox\scratchbox\vbox
1308       {\unvbox#1\unskip\unskip\unskip
1309        \global\setbox\floatbox\lastbox}%
1310   \fi}
1311
1312% for the moment resave is still needed here
1313
1314\def\OTRSETsavebox#1% clean up the skips
1315  {\OTRSETunpreparebox{#1}%
1316   \page_floats_save\s!text}
1317
1318\def\OTRSETresavebox#1% clean up the skips
1319  {\OTRSETunpreparebox{#1}%
1320   \page_floats_resave\s!text}
1321
1322\unexpanded\def\page_set_command_flush_float_box
1323  {\box\floatbox}
1324
1325\unexpanded\def\page_set_command_flush_floats
1326  {\bgroup
1327   \def\OTRSETsavebox##1{\!!doneafalse}%
1328   \doloop
1329     {\ifconditional\c_page_floats_some_waiting
1330        \OTRSETskipstart
1331        \page_floats_get_info\s!text
1332        \ifdim\floatwidth>\zeropoint
1333          \!!doneatrue
1334          \page_floats_flush\s!text\plusone
1335%
1336% a quick hack ... will be redone
1337%
1338\ifdim\wd\floatbox<\floatwidth \ifhbox\floatbox
1339    \global\setbox\floatbox\hpack{\unhbox\floatbox}%
1340\fi \fi
1341%
1342          \dp\floatbox\zeropoint
1343          \OTRSETstoreincolumnslot{TBLR}\floatbox
1344          \if!!donea
1345           %\message{[flu]}%
1346          \else
1347            \OTRSETresavebox\floatbox
1348            \exitloop
1349          \fi
1350        \else
1351         %\message{[err]}% happens but why?
1352        \fi
1353      \else
1354        \exitloop
1355      \fi}
1356   \egroup}
1357
1358\newif\ifcentergridcells        \centergridcellstrue
1359\newif\ifcentergridcellonly     \centergridcellonlyfalse
1360\newif\ifautocentergridcellonly \autocentergridcellonlytrue
1361
1362\def\OTRSETcentergridcells
1363  {\ifcentergridcells
1364     \dorecurse\nofcolumns
1365       {\currenthcell\recurselevel
1366        \ifautocentergridcellonly
1367          % we prevent centering when the next column is empty
1368          % to be checked ! ! ! !
1369          \advance\currenthcell \plusone
1370          \centergridcellonlytrue
1371          \ifnum\currenthcell>\nofcolumns
1372            % ok already
1373          \else
1374            % only span if there is a next column with content
1375            \dorecurse\columnmaxcells
1376              {\ifdim\ht\page_set_cell\currenthcell\currentvcell>\zeropoint
1377                 \centergridcellonlyfalse
1378               \else\ifdim\dp\page_set_cell\currenthcell\currentvcell>\zeropoint
1379                 \centergridcellonlyfalse
1380               \fi\fi}%
1381          \fi
1382        \fi
1383        \currenthcell\recurselevel
1384        \dorecurse\columnmaxcells
1385          {\currentvcell\recurselevel\relax
1386           \ifdim\ht\page_set_cell\currenthcell\currentvcell>\zeropoint
1387           \ifdim\dp\page_set_cell\currenthcell\currentvcell=\zeropoint
1388             \bgroup
1389             \setbox\scratchbox\page_set_cell_get\currenthcell\currentvcell
1390             \getnoflines{\ht\scratchbox}%
1391             \!!counta\currentvcell
1392             \advance\!!counta -\noflines
1393             \advance\!!counta \plusone
1394             % first col always ok
1395             \!!countb\currenthcell
1396             \!!countc\currenthcell
1397             \advance\!!countc \plusone
1398             \!!donebtrue
1399             \ifcentergridcellonly
1400               \!!countc\maxdimen
1401             \fi
1402             \dostepwiserecurse\!!countc\nofcolumns\plusone
1403               {\if!!doneb
1404                  \let\xrecurselevel\recurselevel
1405                  \dostepwiserecurse\!!counta\currentvcell\plusone
1406                    {\ifdim\ht\page_set_cell\xrecurselevel\recurselevel>\zeropoint
1407                       \!!donebfalse
1408                     \else\ifdim\wd\page_set_cell\xrecurselevel\recurselevel>\zeropoint
1409                       \!!donebfalse
1410                     \fi\fi}%
1411                  \if!!doneb
1412                    \!!countb\xrecurselevel
1413                  \fi
1414                \fi}%
1415             \totalcolumnspace\OTRSETlocalwidth\currenthcell
1416             \dostepwiserecurse\!!countc\!!countb\plusone
1417               {\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel
1418                \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
1419             \ifdim\totalcolumnspace>\wd\scratchbox
1420               \setbox\scratchbox\hpack to \totalcolumnspace{\hss\box\scratchbox\hss}%
1421             \fi
1422             \page_set_cell_set\currenthcell\currentvcell\box\scratchbox
1423           \egroup
1424           \fi
1425           \fi}}%
1426   \fi}
1427
1428\def\OTRSETinitializecolumns% once per page
1429  {\columnspreadtrue % todo
1430   \ifcolumnspread
1431     \global\rofcolumns\columnsetparameter\c!nright
1432     \global\lofcolumns\columnsetparameter\c!nleft
1433     \global\tofcolumns\rofcolumns \relax
1434     \ifodd\realpageno\relax
1435       \global\nofcolumns\rofcolumns
1436     \else
1437       \global\advance\tofcolumns\lofcolumns
1438       \global\nofcolumns\lofcolumns
1439     \fi
1440   \else
1441     \global\nofcolumns\columnsetparameter\c!n
1442     \global\rofcolumns\nofcolumns
1443     \global\lofcolumns\nofcolumns
1444     \global\tofcolumns\nofcolumns
1445   \fi
1446   \OTRSETassignwidths
1447   \global\mofcolumns\plusone
1448   \page_set_cell_erase_grid}
1449
1450% this is a first step in upgrading
1451
1452\installcorenamespace{columnset}
1453
1454\installframedcommandhandler \??columnset {columnset} \??columnset
1455
1456\setupcolumnset % todo, use the rather basic backgroundframed
1457  [\c!direction=\v!right,
1458   \c!balance=\v!no,
1459   \c!distance=1.5\bodyfontsize,
1460   \c!n=2,
1461   \c!nleft=\columnsetparameter\c!n,
1462   \c!nright=\columnsetparameter\c!n,
1463   \c!width=\v!fit,
1464   \c!lines=0,
1465   \c!start=0,
1466   \c!frame=\v!off,
1467   \c!offset=\v!overlay,
1468   \c!frame=\v!off,
1469   \c!align=]
1470
1471\let\page_set_setup_saved\setupcolumnset
1472
1473\newconditional\c_page_set_defining
1474
1475\appendtoks
1476    \ifconditional\c_page_set_defining \else
1477      \settrue\c_page_set_defining
1478      \dorecurse{\columnsetparameter\c!nleft}
1479        {\normalexpanded{\definecolumnset[\currentcolumnset:\recurselevel][\currentcolumnset]}}%
1480      \dorecurse{\columnsetparameter\c!nright}
1481        {\normalexpanded{\definecolumnset[\currentcolumnset:\recurselevel][\currentcolumnset]}}%
1482      \normalexpanded{\page_set_setup_saved[\currentcolumnset:1][\c!distance=\zeropoint]}%
1483      \setfalse\c_page_set_defining
1484    \fi
1485\to \everydefinecolumnset
1486
1487\unexpanded\def\setupcolumnset
1488  {\dotripleargument\page_set_setup}
1489
1490\def\page_set_setup[#1][#2][#3]%
1491  {\ifthirdargument
1492     \unexpanded\def\page_set_setup_step##1%
1493       {\doifelse{##1}\v!each
1494          {\dorecurse{\namedcolumnsetparameter{#1}\c!n}{\page_set_setup_step\recurselevel}}
1495          {\normalexpanded{\page_set_setup_saved[#1:##1]}[#3]}}%
1496     \processcommalist[#2]\page_set_setup_step
1497   \else
1498     \page_set_setup_saved[#1][#2]%
1499   \fi}
1500
1501\definecolumnset
1502  [\s!default]
1503
1504\unexpanded\def\page_set_command_next_page
1505  {\page_otr_fill_and_eject_page
1506   \relax\ifnum\mofcolumns>\plusone
1507     \OTRSETgotocolumn[\v!last]%
1508     \ifnum\mofcolumns>\plusone
1509       \OTRSETgotocolumn[\v!force]%
1510     \fi
1511   \fi}
1512
1513\let\page_set_command_next_page_and_inserts\page_set_command_next_page
1514
1515\def\OTRSETgotocolumn
1516  {\dosingleempty\doOTRSETgotocolumn}
1517
1518\def\doOTRSETgotoCOLROW#1% <number>|<number>*<number>
1519  {\bgroup % really needed
1520   \splitatasterisk{#1}\column\row
1521   \bgroup
1522     \ifx\column\empty\else\expanded{\doOTRSETgotoCOLUMN{\column}}\fi
1523   \egroup
1524   \bgroup
1525     \ifx\row   \empty\else\expanded{\doOTRSETgotoROW   {\row   }}\fi
1526   \egroup
1527   \egroup}
1528
1529\def\doOTRSETgotoCOLUMN#1%
1530  {\ifnum\mofcolumns=#1\else
1531     \page_otr_fill_and_eject_page
1532     \doloop
1533       {\ifnum\mofcolumns=#1\relax
1534          \exitloop \else \OTRSETdummycolumn
1535        \fi}%
1536   \fi}
1537
1538\def\doOTRSETgotoROW#1%
1539  {\ifnum#1>1
1540     \scratchcounter\zerocount
1541     \currenthcell\mofcolumns
1542     \currentvcell#1\advance\currentvcell \minusone
1543     \dorecurse\currentvcell
1544       {\page_set_cell_doifelse\mofcolumns\recurselevel\donothing
1545          {\advance\scratchcounter\plusone}}
1546     \getnoflines\pagetotal
1547     \advance\scratchcounter-\noflines
1548     \ifnum\scratchcounter>\zerocount
1549       \dorecurse\scratchcounter{\line{\strut}}%
1550     \fi
1551   \fi
1552   \page_set_command_set_vsize}
1553
1554\def\doOTRSETgotocolumn[#1]% yes|force|first|last|<number>|<number>*<number>
1555  {\processallactionsinset
1556     [#1]
1557     [    \v!yes=>\OTRSETdummycolumn,
1558           \v!no=>,% not supported
1559        \v!force=>\OTRSETdummycolumn,
1560        \v!first=>\expanded{\doOTRSETgotoCOLUMN{1}},
1561         \v!last=>\expanded{\doOTRSETgotoCOLUMN{\the\nofcolumns}},
1562      \s!default=>\OTRSETdummycolumn,
1563      \s!unknown=>\expanded{\doOTRSETgotoCOLROW{\commalistelement}}]}
1564
1565% to be documented and tested, not yet that robust
1566
1567% \def\OTRSETgotocell#1#2%
1568%   {\endgraf
1569%    \gdef\gotocellcounter{0}%
1570%    \doloop
1571%      {\ifnum\mofcolumns<#1\relax
1572%         \doglobal\increment\gotocellcounter\relax
1573%         \ifnum\gotocellcounter>#1\relax
1574%           \line{\strut}\crlf
1575%           \line{\strut}\crlf
1576%           \column
1577%           \writestatus{columnset}{quitting goto cell}%
1578%           \exitloop
1579%         \else
1580%           \column
1581%         \fi
1582%       \else
1583%         \exitloop
1584%       \fi}%
1585%    \ifnum\mofcolumns=#1\relax
1586%      \ifnum#2>1
1587%        \scratchcounter\zerocount
1588%        \currenthcell\mofcolumns
1589%        \currentvcell#2\advance\currentvcell \minusone
1590%        \dorecurse\currentvcell
1591%          {\page_set_cell_doifelse\mofcolumns\recurselevel\donothing
1592%             {\advance\scratchcounter\plusone}}
1593%        \getnoflines\pagetotal
1594%        \advance\scratchcounter-\noflines
1595%        \ifnum\scratchcounter>\zerocount
1596%          \dorecurse\scratchcounter{\line{\strut}}%
1597%        \fi
1598%      \fi
1599%    \fi
1600%    \page_set_command_set_vsize}
1601
1602\def\OTRSETgotocell#1#2% obsolete: now \column[#1*#2]
1603  {\endgraf
1604   \doOTRSETgotoCOLUMN{#1}%
1605   \doOTRSETgotoROW   {#2}}
1606
1607\def\OTRSETdummycolumn
1608  {\verticalstrut
1609   \vskip-\struttotal
1610   \page_otr_fill_and_eject_page}
1611
1612\newcounter\columnsetlevel
1613\let\currentcolumnset\empty
1614
1615\newconditional\OTRSETfinish % never checked
1616
1617\unexpanded\def\startcolumnset
1618  {\dodoubleempty\dostartcolumnset}
1619
1620\def\dostartcolumnset[#1][#2]%
1621  {\increment\columnsetlevel\relax
1622   \glet\localcolumnmaxcells\!!zerocount
1623   \global\setfalse\OTRSETfinish
1624   \ifnum\columnsetlevel=\plusone
1625     \bgroup
1626     \saveinterlinespace
1627     \glet\columnsetpage\!!plusone
1628     \def\currentcolumnset{#2}%
1629     \insidecolumnstrue % will be different flag in addition
1630     \setupoutputroutine[\s!columnset]%
1631     \doifelsenothing{#1}
1632       {\glet\OTRSETlist\s!default}
1633       {\xdef\OTRSETlist{#1}}%
1634     \OTRSETstartnextpage
1635     \OTRSETassignwidths
1636     \page_set_command_set_hsize
1637   \else
1638     \bgroup
1639   \fi
1640   \begingroup} % extra grouping needed ... else weird issue with ungrouped font switch (e.g. \ss)
1641
1642% \setuplayout[grid=yes] \definecolumnset[example] \showgrid
1643
1644% \starttext
1645%     \startcolumnset[example]
1646%         \input knuth \endgraf \input knuth
1647%         \placetable{table}{\framed[width=\makeupwidth,height=4cm]{Hello}}
1648%         \input knuth \endgraf \input knuth
1649%     \stopcolumnset
1650%     \input knuth \endgraf \input knuth
1651% \stoptext
1652
1653\def\OTRSETflushleftovers % new per 13/4/2006
1654  {\page_set_cell_doifelse\plusone\plusone
1655     {\bgroup
1656      \OTRSETcentergridcells
1657      \OTRSETbalancemethod\plusone
1658      \OTRSETreducegridbox
1659      \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
1660      \ht\OTRfinalpagebox\textheight % signals output that there is content
1661      \OTRSETdofinaloutput
1662      \glet\OTRSETbalht\zeropoint
1663      \egroup}
1664     {}}
1665
1666\unexpanded\def\stopcolumnset
1667  {\endgraf
1668   \endgroup % ends extra grouping
1669   \ifnum\columnsetlevel=\plusone
1670     \endgraf % needed, else wrong vsize in one par case
1671     \global\settrue\OTRSETfinish
1672     % no, extra page \pagebreak % (test on pascal toc)
1673     \dostopcolumnset
1674     \egroup
1675     \global\notelimittrue % brrr, untested and fuzzy
1676     \page_otr_command_set_vsize
1677     \page_otr_command_set_hsize
1678     \ifvoid\OTRfinalpagebox\else
1679       % probably balanced
1680       \ifdim\ht\OTRfinalpagebox<\textheight
1681         \snaptogrid[\v!page]\hpack{\box\OTRfinalpagebox}%
1682       \else
1683         \box\OTRfinalpagebox
1684       \fi
1685     \fi
1686     \global\setfalse\OTRSETfinish
1687     \ifconditional\c_page_floats_some_waiting
1688       \page_otr_command_set_vsize
1689       \pagebreak
1690       \page_otr_command_set_vsize
1691     \fi
1692     \OTRSETflushleftovers
1693   \else
1694     \egroup
1695   \fi
1696   \decrement\columnsetlevel\relax}
1697
1698\newconstant\OTRSETbalancemethod
1699
1700\def\dostopcolumnset
1701  {%\OTRSETdofinalflushfloats % yes/no
1702   \ifcase\OTRSETbalancemethod
1703     \OTRSETnobalance
1704   \else
1705     \OTRSETdobalance
1706   \fi}
1707
1708\def\OTRSETdobalance
1709  {\OTRSETnobalance}
1710
1711\def\localcolumnmaxcells{0}
1712
1713% currently line represents real line, i.e. on the grid, and
1714% not something noflines (also, watch out for switching from
1715% 2-3 columns on one page with both sets balanced: the
1716% second set does not see the first set
1717
1718% don't loose empty 1page/1column with area (example **)
1719%
1720% \definecolumntextarea[title][x=1,y=4,nx=2,ny=7,state=start]
1721% \setupcolumntextareatext[title][\vtop to 5cm{a\\b\\b\\d}]
1722%
1723% \starttext
1724% \startcolumnset \dorecurse{1}{\input tufte \par} \stopcolumnset
1725% \stoptext
1726
1727% better:
1728
1729\unexpanded\def\definecolumnsetarea   {\definecolumntextarea}
1730\unexpanded\def\setupcolumnsetarea    {\setupcolumntextarea}
1731\unexpanded\def\setupcolumnsetareatext{\setupcolumntextareatext}
1732
1733% so this will be changed
1734
1735\def\OTRSETnobalance
1736  {\iflastcolumnfootnotes % testen ! optie
1737     % inhibit flush of floats !
1738     % todo: nothing if no footnotes, else empty page
1739     \dostepwiserecurse\mofcolumns\nofcolumns\plusone
1740       {\vskip-\struttotal\verticalstrut\page_otr_fill_and_eject_page}%
1741   \else
1742     \ifnum\mofcolumns>\plusone
1743       \donetrue
1744     \else\ifdim\pagetotal>\zeropoint % too dangerous, we loose data
1745       \donetrue
1746     \else
1747       \donefalse
1748     \fi\fi
1749     \ifdone
1750       \ifnum\mofcolumns=\nofcolumns
1751         \OTRSETflushfinalfootnotes
1752       \else
1753         % probably todo
1754       \fi
1755       \page_otr_fill_and_eject_page
1756       % brr, may result in empty page after nicely fit text
1757       % or if left, then lost of first column only text
1758       \ifnum\mofcolumns>\plusone
1759         \OTRSETdofinalflush
1760         \OTRSETdofinaloutput
1761       \fi
1762     \fi
1763   \fi}
1764
1765\def\OTRSETstartnextpage
1766  {\doifsomething\OTRSETlist
1767     {\getfromcommacommand[\OTRSETlist][1]%
1768      \glet\OTRSETidentifier\commalistelement
1769      \xdef\currentcolumnset{\commalistelement}%
1770      \checkcolumnsetparent
1771      \let\newcommalistelement\empty
1772      \doglobal\replaceincommalist\OTRSETlist1%
1773      \OTRSETrestart}}
1774
1775\def\OTRSETrestart % weed
1776  {\OTRSETinitializefeatures
1777   \OTRSETflushpreposttext
1778   \OTRSETinitializecolumns
1779   \OTRSETcheckinsert
1780   \OTRSETcheckgrid
1781   \page_set_command_set_vsize
1782   \page_set_command_set_hsize % or local ?
1783   \OTRSETsetplaceholders
1784   \OTRSEThandlepreposttext
1785   \initializecolumntextareas % name !
1786   \OTRSETcheckstartcells
1787   \page_set_command_set_vsize}
1788
1789\def\OTRSETcheckstartcells
1790  {\dorecurse\nofcolumns
1791     {\bgroup
1792      \mofcolumns\recurselevel
1793\OTRSETsetcorrectnofcells\currentcolumnstartcell
1794\advance\scratchcounter \minusone
1795      \dorecurse\scratchcounter
1796        {\page_set_cell_doifelse\mofcolumns\recurselevel
1797           \donothing{\page_set_cell_set\mofcolumns\recurselevel\copy\placeholderboxe}}%
1798      \egroup}}
1799
1800\unexpanded\def\page_set_command_routine
1801  {\dontcomplain % new, get rid of overfull message (to be sorted out)
1802   \doloop
1803     {\OTRSETnaturalflush
1804     %\OTRSETstartnextpage %  no
1805      \page_set_command_flush_floats
1806      \OTRSETcheckfreelines
1807      \ifsomefreecolumncells
1808        \exitloop
1809      \else
1810        % flush page and get rid of more floats if present
1811      \fi}%
1812   \OTRSETchecksidefloat}
1813
1814\def\OTRSETsetcolumnmaxcells
1815  {\getrawnoflines\textheight\xdef\columnmaxcells{\the\noflines}}
1816
1817\def\OTRSETinitializefeatures
1818  {% number of lines
1819   % new: raw
1820   \OTRSETsetcolumnmaxcells
1821   % direction
1822   \doifelse{\columnsetparameter\c!direction}\v!right
1823     {\columndirection\zerocount}
1824     {\columndirection\plusone}%
1825   % balancing
1826   \OTRSETbalancemethod\zerocount
1827   \processaction
1828     [\columnsetparameter\c!balance]
1829     [    \v!yes=>\OTRSETbalancemethod\plusone,
1830          \v!top=>\OTRSETbalancemethod\plustwo,
1831       \v!bottom=>\OTRSETbalancemethod\plusthree]}
1832
1833% test:
1834%
1835% \definecolumnset[test-1]  %[balance=yes]
1836% \definecolumnset[test-2]  %[balance=yes]
1837%
1838% \setupcolumnsetlines[test-1][1][1] [4]
1839% \setupcolumnsetlines[test-1][1][2][10]
1840%
1841% \startcolumnset [test-1] \dorecurse {1}{\input tufte \par} \stopcolumnset
1842% \startcolumnset [test-2] \dorecurse {2}{\input ward  \par} \stopcolumnset
1843
1844\ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi
1845
1846\installoutputroutine\OTRSETflushpreposttext
1847  {\global\setbox\b_page_set_preceding\vbox
1848     {\unvbox\normalpagebox
1849      \global\lastskipinotr\lastskip}%
1850   \ifdim\lastskipinotr>\zeropoint
1851     \global\setbox\b_page_set_preceding\hpack
1852       {\lower\strutdepth\box\b_page_set_preceding}%
1853   \fi
1854   \dp\b_page_set_preceding\strutdepth
1855   \ifcarryoverfootnotes \else
1856     \global\setbox\b_page_set_trailing\vbox{\placebottomnotes}%
1857   \fi}
1858
1859\let\precolumnlines \!!zerocount
1860\let\postcolumnlines\!!zerocount
1861
1862\def\OTRSEThandlepreposttext
1863  {\ifdim\ht\b_page_set_preceding>\zeropoint % new
1864     \getnoflines{\ht\b_page_set_preceding}%
1865     \edef\precolumnlines{\the\noflines}%
1866     \doOTRSETsetgridcells
1867       {\copy\placeholderboxe}
1868       \plusone\plusone\nofcolumns\noflines
1869     % normal version (single column set)
1870     % {\box\b_page_set_preceding}%
1871     % compensated for bodyfont change
1872       {\hbox
1873          {\OTRSETsetcorrectcellht
1874           \raise\scratchdimen\box\b_page_set_preceding}}%
1875   \else
1876     \let\precolumnlines\!!zerocount
1877   \fi
1878   \ifdim\ht\b_page_set_trailing>\zeropoint % new, otherwise empty bottom line
1879     \getnoflines{\ht\b_page_set_trailing}%
1880     \edef\postcolumnlines{\the\noflines}%
1881     \advance\columnfreecells -\noflines
1882     \advance\columnfreecells \plusone
1883     \doOTRSETsetgridcells
1884       {\copy\placeholderboxe}
1885       \plusone\columnfreecells\nofcolumns\noflines
1886       {\box\b_page_set_trailing}%
1887   \else
1888     \let\postcolumnlines\!!zerocount
1889   \fi}
1890
1891\def\OTRSETchecksidefloat
1892  {} % {\sidefloatoutput}
1893
1894\unexpanded\def\page_set_command_side_float_output
1895  {} % nothing, reset anyway
1896
1897\def\OTRSETcheckgrid
1898  {\topskip1\topskip
1899   \ifforcecolumnsetgrid
1900     \widowpenalty\zerocount
1901     \clubpenalty\zerocount
1902     \brokenpenalty\zerocount
1903   \fi}
1904
1905\def\OTRSETcheckinsert
1906  {\iflastcolumnfootnotes
1907     \ifnum\nofcolumns=\mofcolumns
1908       \OTRSETforceinserts
1909     \else
1910       \OTRSETinhibitinserts
1911     \fi
1912   \else
1913     \OTRSETforceinserts
1914   \fi}
1915
1916\def\OTRSETforceinserts
1917  {\enablenotes}
1918
1919\def\OTRSETinhibitinserts
1920  {\disablenotes}
1921
1922% undocumented goodie
1923
1924\def\definecolumnsethsize#1#2#3#4% will be improved/speed up
1925  {\bgroup
1926   \def\OTRSETidentifier{#1}%
1927   \ifcase\columnsetlevel\relax
1928     \mofcolumns\plusone
1929     \OTRSETinitializecolumns
1930     \OTRSETassignwidths % already done
1931     \page_set_command_set_hsize
1932   \fi
1933   \!!counta#2\!!countb#3\docalculatecolumnsetspan
1934   \expandafter\egroup\expandafter\edef\expandafter#4\expandafter{\the\!!widtha}}
1935
1936% interface to footnotes
1937
1938\installcorenamespace{columnsetwidth}
1939
1940\def\OTRSETassignwidths
1941  {%\scratchdimen\makeupwidth
1942   \freezetextwidth \scratchdimen\textwidth
1943   %
1944   \scratchcounter\zerocount
1945   \dorecurse\nofcolumns
1946     {\doifelse{\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}\v!fit
1947        {\advance\scratchcounter \plusone}
1948        {\advance\scratchdimen -\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}%
1949      \advance\scratchdimen -\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
1950   \ifcase\scratchcounter\else
1951     \divide\scratchdimen \scratchcounter
1952   \fi
1953   \global\setfalse\c_page_set_width_set
1954   \dorecurse\nofcolumns
1955     {\doifelse{\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}\v!fit
1956        {\dimen0=\scratchdimen}
1957        {\global\settrue\c_page_set_width_set
1958         \dimen0=\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}%
1959      \setxvalue{\??columnsetwidth\recurselevel}{\the\dimen0}}}
1960
1961\def\OTRSETlocalwidth#1%
1962  {\getvalue{\??columnsetwidth\number#1}}
1963
1964\newbox\placeholderboxa
1965\newbox\placeholderboxb
1966\newbox\placeholderboxc
1967\newbox\placeholderboxd
1968\newbox\placeholderboxe
1969\newbox\placeholderboxf
1970
1971\def\columnplaceholder#1#2%
1972  {\hbox
1973     {\setbox\scratchbox\hpack to \hsize
1974        {\iftracecolumnset
1975           \hskip-.5ex%
1976           \startcolor[columnset:#2]\vrule\s!width\exheight\s!height.5\exheight\s!depth.5\exheight\stopcolor
1977         \fi
1978         \hss}%
1979      \ifcase#1\relax
1980        \ht\scratchbox\zeropoint
1981        \dp\scratchbox\zeropoint
1982        \wd\scratchbox\zeropoint
1983      \else
1984        \wd\scratchbox\hsize
1985        \ht\scratchbox\strutht
1986        \dp\scratchbox\strutdp
1987      \fi
1988      \box\scratchbox}}
1989
1990\definepalet
1991  [columnset]
1992  [a=cyan,b=green,c=blue,d=red,e=magenta,f=darkgray]
1993
1994\def\OTRSETsetplaceholders
1995  {\global\setbox\placeholderboxa\columnplaceholder0a%
1996   \global\setbox\placeholderboxb\columnplaceholder0b%
1997   \global\setbox\placeholderboxc\columnplaceholder0c%
1998   \global\setbox\placeholderboxd\columnplaceholder0d%
1999   \global\setbox\placeholderboxe\columnplaceholder0e%
2000   \global\setbox\placeholderboxf\columnplaceholder1f}
2001
2002\def\doOTRSETshowstatus
2003  {\llap{\tt\tfxx
2004     \startcolor[blue](\the\vsize->\number\columnfirstcell\#\number\columnfreecells)\stopcolor
2005     \hskip\leftskip}}
2006
2007\installtextracer{OTRSET} % low level
2008
2009\def\enabletextracerOTRSET {\tracecolumnsettrue \let\OTRSETshowstatus\doOTRSETshowstatus}
2010\def\disabletextracerOTRSET{\tracecolumnsetfalse\let\OTRSETshowstatus\relax}
2011
2012\disabletextracerOTRSET
2013
2014% \appendtoks \OTRSETshowstatus \to \everypar
2015
2016% page contents
2017
2018% \def\OTRSETdopagecontents#1#2% takes two args: \box<n> \unvbox<n>
2019\unexpanded\def\page_set_command_package_contents#1#2% \box<n> \unvbox<n> % this one will be redone (checked)
2020  {\vbox to \textheight{\forgetall#1#2}}
2021
2022\def\page_set_place_float_page  {\def\floatmethod{PAGE}\page_set_place_float_slot} % check
2023\def\page_set_place_float_here  {\def\floatmethod{HERE}\page_set_place_float_slot} % check
2024\def\page_set_place_float_else  {\def\floatmethod{HERE}\page_set_place_float_slot} % check / not used
2025\def\page_set_place_float_force {\def\floatmethod{FIXD}\page_set_place_float_slot} % check
2026\def\page_set_place_float_top   {\def\floatmethod{TOPS}\page_set_place_float_slot} % check
2027\def\page_set_place_float_bottom{\def\floatmethod{BOTS}\page_set_place_float_slot} % check
2028
2029\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
2030  {\box\floatbox}
2031
2032\def\page_set_place_float_slot
2033  {\setbox\floatbox\vbox{\page_otr_command_flush_float_box}%
2034   \dp\floatbox\strutdp
2035   \expandafter\uppercasestring\floatmethod\to\floatmethod
2036   \OTRSETstoreincolumnslot\floatmethod\floatbox
2037   \page_floats_report_total}
2038
2039% kind of new, looks much like OTRONE, but not entirely
2040
2041\newconditional\c_page_set_top_of_insert
2042
2043\unexpanded\def\page_set_command_set_top_insertions
2044  {\bgroup
2045   \ifconditional\c_page_floats_some_waiting
2046     \noffloatinserts\zerocount
2047     \let\totaltopinserted\!!zeropoint
2048     \OTRSETdodosettopinserts
2049     \ifnum\rootfloatparameter\c!nbottom=\zerocount
2050       \ifnum\rootfloatparameter\c!nlines>\zerocount
2051         \ifdim\totaltopinserted>\zeropoint\relax
2052           \scratchdimen\dimexpr\rootfloatparameter\c!nlines\lineheight+\totaltopinserted\relax
2053           \ifdim\scratchdimen>\textheight % \vsize  %%%%%%%%% \textheight
2054             \showmessage\m!floatblocks8{\rootfloatparameter\c!nlines}%
2055             \page_otr_fill_and_eject_page % was triple: vfilll
2056           \fi
2057         \fi
2058       \fi
2059     \fi
2060   \fi
2061   \egroup}
2062
2063\def\OTRSETdodosettopinserts
2064  {\ifnum\noffloatinserts<\c_page_floats_n_of_top
2065     \page_floats_get
2066     \ifdim\d_page_floats_inserted_top=\zeropoint\relax
2067       \settrue\c_page_set_top_of_insert
2068     \else
2069       \setfalse\c_page_set_top_of_insert
2070     \fi
2071     \setbox\scratchbox\vbox % kan beter !
2072       {\forgetall
2073        \ifconditional\c_page_set_top_of_insert
2074         %\ifdim\OTRSETtopoffset=\zeropoint
2075         %  \moveongrid[\v!top]
2076         %\fi
2077        \else
2078          \betweenfloatblanko % inserts can't look back
2079        \fi
2080        \page_otr_command_flush_float_box
2081        \blank[\rootfloatparameter\c!spaceafter]}%
2082     \global\advance\d_page_floats_inserted_top \ht\scratchbox\relax
2083     \ifdim\d_page_floats_inserted_top>\vsize % was \textheight\relax
2084       \OTRSETresavebox\scratchbox
2085       \noffloatinserts\c_page_floats_n_of_top\relax
2086       \global\advance\d_page_floats_inserted_top -\ht\scratchbox
2087       \let\OTRSETdodosettopinserts\relax % to be tested
2088     \else
2089       \xdef\totaltopinserted{\the\d_page_floats_inserted_top}%
2090       \insert\namedinsertionnumber\s!topfloat\bgroup
2091         \forgetall
2092         \box\scratchbox
2093       \egroup
2094       \ifconditional\c_page_floats_some_waiting
2095         \advance\noffloatinserts \plusone
2096       \else
2097         \noffloatinserts\c_page_floats_n_of_top\relax
2098       \fi
2099       \page_floats_report_flushed
2100     \fi
2101   \else
2102     \ifconditional\c_page_floats_some_waiting
2103       \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}%
2104     \fi
2105     \let\OTRSETdodosettopinserts\relax
2106   \fi
2107   \OTRSETdodosettopinserts}
2108
2109\unexpanded\def\page_set_command_set_bottom_insertions
2110  {\bgroup
2111   \ifconditional\c_page_floats_some_waiting
2112     \noffloatinserts\zerocount
2113     \OTRSETdodosetbotinserts
2114   \fi
2115   \egroup}
2116
2117\def\OTRSETdodosetbotinserts
2118  {\ifnum\noffloatinserts<\c_page_floats_n_of_bottom\relax
2119     \page_floats_get
2120     \global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
2121     \ifdim\d_page_floats_inserted_bottom<\pagegoal\relax
2122       \insert\namedinsertionnumber\s!bottomfloat\bgroup
2123         \forgetall
2124         \blank[\rootfloatparameter\c!spacebefore]%
2125         \page_otr_command_flush_float_box
2126       \egroup
2127       \ifconditional\c_page_floats_some_waiting
2128         \advance\noffloatinserts \plusone
2129       \else
2130         \noffloatinserts\c_page_floats_n_of_bottom
2131       \fi
2132       \page_floats_report_flushed
2133     \else
2134       \OTRSETresavebox\floatbox
2135       \noffloatinserts\c_page_floats_n_of_bottom\relax
2136     \fi
2137     \global\settrue\c_page_floats_not_permitted % vgl topfloats s!
2138   \else
2139     \ifconditional\c_page_floats_some_waiting
2140       \showmessage\m!floatblocks7{\the\c_page_floats_n_of_bottom}%
2141     \fi
2142     \let\OTRSETdodosetbotinserts\relax
2143   \fi
2144   \OTRSETdodosetbotinserts}
2145
2146\unexpanded\def\page_set_command_flush_top_insertions
2147  {\ifvoid\namedinsertionnumber\s!topfloat\else
2148     \ifvoid\columntopbox\mofcolumns
2149       \columnsettopbox\mofcolumns\box\namedinsertionnumber\s!topfloat
2150     \else
2151       \columnsettopbox\mofcolumns\vbox % temp, must be better
2152         {\forgetall
2153          \offinterlineskip
2154          \box\columntopbox\mofcolumns
2155          \box\namedinsertionnumber\s!topfloat}
2156     \fi
2157   \fi
2158   \global\d_page_floats_inserted_top\zeropoint\relax} % goes away
2159
2160\unexpanded\def\page_set_command_flush_bottom_insertions
2161  {\ifvoid\namedinsertionnumber\s!bottomfloat \else
2162     \columnsetbotbox\mofcolumns\box\namedinsertionnumber\s!bottomfloat
2163%   \else
2164%     \columnsetbotbox\mofcolumns\vbox % temp, must be better
2165%       {\forgetall
2166%        \offinterlineskip
2167%        \box\namedinsertionnumber\s!bottomfloat
2168%        \box\columnbotbox\mofcolumns}
2169   \fi
2170   \global\d_page_floats_inserted_bottom\zeropoint\relax} % goes away
2171
2172% set ipv text
2173
2174% left right 1 2 3 +1 +2 +3
2175
2176\let\columnleftareas \empty
2177\let\columnrightareas\empty
2178
2179% links rechts => odd, even, n, named
2180
2181\installcorenamespace{columnsetarea}
2182
2183\unexpanded\def\definecolumntextarea
2184  {\dotripleempty\dodefinecolumntextarea}
2185
2186\def\dodefinecolumntextarea[#1][#2][#3]% y=0 is mogelijke en handig !
2187  {\ifthirdargument
2188     \doifelseinset{#2}{\v!both,\v!fixed}
2189       {\definecolumntextarea[#1][\v!left ][\c!type=#2,#3]%
2190        \definecolumntextarea[#1][\v!right][\c!type=#2,#3]}
2191       {\doifelse{#2}\v!next
2192          {\doifelseoddpage
2193             {\definecolumntextarea[#1][\v!right][\c!type=#2,#3]}
2194             {\definecolumntextarea[#1][\v!left ][\c!type=#2,#3]}}
2195          {\presetlocalframed
2196             [\??columnsetarea#1#2]%
2197           \processaction[#2] % \doglobal voorkomt stack build up
2198             [ \v!left=>\doglobal\addtocommalist{#1}\columnleftareas,
2199              \v!right=>\doglobal\addtocommalist{#1}\columnrightareas]%
2200           \getparameters[\??columnsetarea#1#2]
2201             [\c!x=1,\c!y=1,\c!nx=1,\c!ny=1,\c!clipoffset=2\lineheight,
2202              \c!leftoffset=\zeropoint,\c!rightoffset=\zeropoint,
2203              \c!offset=\v!overlay,\c!strut=\v!no,\c!frame=\v!off,
2204              \c!type=#2,\c!page=1,\c!state=\v!stop,#3]}}%
2205   \else
2206     \definecolumntextarea[#1][\v!next][#2]%
2207   \fi}
2208
2209\unexpanded\def\setupcolumntextarea
2210  {\dotripleempty\dosetupcolumntextarea}
2211
2212\def\dosetupcolumntextarea[#1][#2][#3]%
2213  {\ifthirdargument
2214     \doifelse{#2}\v!both
2215       {\setupcolumntextarea[#1][\v!left ][#3]%
2216        \setupcolumntextarea[#1][\v!right][#3]}
2217       {\doifelse{#2}\v!next
2218          {\doifelseoddpage
2219             {\setupcolumntextarea[#1][\v!right][#3]}
2220             {\setupcolumntextarea[#1][\v!left][#3]}}
2221          {\getparameters[\??columnsetarea#1#2][#3]}}%
2222   \else
2223     \setupcolumntextarea[#1][\v!next][#2]%
2224   \fi}
2225
2226\def\docheckcolumnsetareapage#1#2%
2227  {\ifnum\getvalue{\??columnsetarea#1\c!page}>\plusone
2228     \doifelsevalue{\??columnsetarea#1\c!type}\v!fixed
2229       {\ifnum\columnsetpage=\getvalue{\??columnsetarea#1\c!page}\relax
2230          \donetrue\else\donefalse
2231        \fi}
2232       {\ifnum\columnsetpage<\getvalue{\??columnsetarea#1\c!page}\relax
2233          \donefalse\else\donetrue
2234        \fi}%
2235   \else
2236     \donetrue
2237   \fi}
2238
2239\def\initializecolumntextareas
2240  {\ifodd\realpageno
2241     \doinitializecolumntextareas\columnrightareas\v!right
2242   \else
2243     \doinitializecolumntextareas\columnleftareas\v!left
2244   \fi}
2245
2246\def\doinitializecolumntextareas#1#2%
2247  {\def\docommand##1%
2248     {\docheckcolumnsetareapage{##1#2}\plusone
2249      \ifdone
2250        \donefalse
2251        \processaction
2252          [\getvalue{\??columnsetarea##1#2\c!state}]
2253          [  \v!start=>\donetrue,
2254            \v!repeat=>\donetrue,
2255           \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
2256        \ifdone\dodoinitializecolumntextareas{##1}{#2}\fi
2257      \fi}%
2258   \processcommacommand[#1]\docommand}
2259
2260\def\dodoinitializecolumntextareas#1#2%
2261  {\doOTRSETsetgridcells
2262     {\copy\placeholderboxd}
2263     {\getvalue{\??columnsetarea#1#2\c!x }}{\getvalue{\??columnsetarea#1#2\c!y }}
2264     {\getvalue{\??columnsetarea#1#2\c!nx}}{\getvalue{\??columnsetarea#1#2\c!ny}}
2265     {\copy\placeholderboxd}}
2266
2267\unexpanded\def\placecolumntextareas
2268  {\ifodd\realpageno
2269     \doplacecolumntextareas\columnrightareas\v!right
2270   \else
2271     \doplacecolumntextareas\columnleftareas\v!left
2272   \fi}
2273
2274\def\doplacecolumntextareas#1#2% global ?
2275  {\bgroup
2276   \forgetall
2277   \def\docommand##1%
2278     {\docheckcolumnsetareapage{##1#2}\zerocount
2279      \ifdone
2280        \donefalse
2281        \processaction
2282          [\getvalue{\??columnsetarea##1#2\c!state}]
2283          [  \v!start=>\donetrue\doglobal\removefromcommalist{##1}#1,
2284            \v!repeat=>\donetrue,
2285           \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
2286        \ifdone
2287          \dodoplacecolumntextareas{##1}{#2}%
2288        \else
2289          \doglobal\removefromcommalist{##1}#1%
2290        \fi
2291      \fi}%
2292   \processcommacommand[#1]\docommand
2293   \egroup}
2294
2295% \page[left]
2296% \definecolumntextarea[intro][left][x=1,y=1,nx=4,ny=20,state=start,background=introlayer]
2297% \setupcolumntextareatext[intro][left][\setups{intro}]
2298% \flushcolumntextareas
2299
2300\def\flushcolumntextareas
2301  {\initializecolumntextareas
2302   \page_otr_command_set_vsize} % set ?
2303
2304\def\columntextlastbackspace{\backspace}
2305
2306% beware, we have clipping offsets of 2\lineheight by default
2307
2308\def\columntextareaparameter#1%
2309  {\csname\??columnsetarea\currentcolumntestarea#1\endcsname}
2310
2311\def\dodoplacecolumntextareas#1#2%
2312  {\def\currentcolumntestarea{#1#2}%
2313   \!!counta\columntextareaparameter\c!x
2314   \!!countb\columntextareaparameter\c!nx
2315   \docalculatecolumnsetspan
2316   \!!heighta\columntextareaparameter\c!ny\lineheight
2317   % wrong
2318   % \ifnum\columntextareaparameter\c!y=\zerocount
2319   %   \advance\!!heighta -\lineheight
2320   %   \advance\!!heighta \topskip
2321   % \fi
2322   % \advance\!!heighta -\lineheight % option
2323   \ifnum\columntextareaparameter\c!y=\plusone
2324     \advance\!!heighta -\lineheight
2325     \advance\!!heighta \topskip
2326   \fi
2327   %
2328   \setbox\scratchbox\vbox
2329     {\donetrue\localframed
2330        [\??columnsetarea\currentcolumntestarea]
2331        [\c!location=,% new (*)
2332            \c!width=\!!widtha,\c!height=\!!heighta,\c!lines=]
2333        {\columntextareaparameter\empty{}}}% messy
2334   \!!counta\columntextareaparameter\c!x
2335   \!!countb\columntextareaparameter\c!y
2336   \advance\!!countb \columntextareaparameter\c!ny
2337   \advance\!!countb \minusone
2338   % new (*)
2339   \doif{\columntextareaparameter\c!location}\v!depth
2340     {\setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}%
2341      \dp\scratchbox\zeropoint
2342      \ht\scratchbox\!!heighta}%
2343   %
2344   \setbox0\hpack
2345     {\ifcase\!!countc
2346        \copy\scratchbox % \box
2347      \else
2348        \clip
2349          [   %\c!topoffset=\columntextareaparameter\c!clipoffset,%
2350           %\c!bottomoffset=\columntextareaparameter\c!clipoffset,%
2351             %\c!leftoffset=\columntextareaparameter\c!clipoffset,%
2352                  \c!offset=\columntextareaparameter\c!clipoffset,%
2353             \c!rightoffset=\columntextareaparameter\c!rightoffset,%
2354                   \c!width=\!!widthb,%
2355                  \c!height=\!!heighta]%
2356          {\copy\scratchbox}%
2357      \fi}%
2358   \page_set_cell_set\!!counta\!!countb\box0
2359   \ifcase\!!countc\else
2360     \advance\!!counta \columntextareaparameter\c!nx
2361     \advance\!!counta -\!!countc
2362     \advance\!!widtha -\!!widthb
2363     \setbox0\hpack
2364%        {\hskip-\namedlayoutparameter\v!odd\c!backspace
2365       {\hskip-\layoutparameter\c!backspace
2366        \clip
2367          [   %\c!topoffset=\columntextareaparameter\c!clipoffset,%
2368           %\c!bottomoffset=\columntextareaparameter\c!clipoffset,%
2369            %\c!rightoffset=\columntextareaparameter\c!clipoffset,%
2370                  \c!offset=\columntextareaparameter\c!clipoffset,%
2371              \c!leftoffset=\columntextareaparameter\c!leftoffset,%
2372                   \c!width=\!!widtha,%
2373                  \c!height=\!!heighta,%
2374                 \c!hoffset=\!!widthb]%
2375          {\copy\scratchbox}}%
2376     \page_set_cell_set\!!counta\!!countb\box0%
2377   \fi}
2378
2379\unexpanded\def\setupcolumntextareatext
2380  {\dotripleempty\dosetupcolumntextareatext}
2381
2382\def\dosetupcolumntextareatext[#1][#2][#3]%
2383  {\ifthirdargument
2384     \doifelse{#2}\v!both
2385       {\setvalue{\??columnsetarea#1\v!left }{#3}%
2386        \setvalue{\??columnsetarea#1\v!right}{#3}}
2387       {\doifelse{#2}\v!next
2388          {\doifelseoddpage
2389             {\setvalue{\??columnsetarea#1\v!right}{#3}}%
2390             {\setvalue{\??columnsetarea#1\v!left }{#3}}}%
2391          {\setvalue{\??columnsetarea#1#2}{#3}}}%
2392   \else
2393     \setupcolumntextareatext[#1][\v!next][{#2}]%
2394   \fi}
2395
2396\def\docalculatecolumnsetspan
2397  {% \!!counta <= x
2398   % \!!countb <= nx
2399   % \!!widtha => total width
2400   % \!!widthb => left width
2401   % \!!countc => left cols
2402   \!!widtha\!!countb\textwidth % we assume equal widths
2403   \advance\!!countb \!!counta
2404   \advance\!!countb \minusone
2405   \ifnum\!!countb>\nofcolumns
2406     \!!countc\!!countb
2407     \advance\!!countc -\nofcolumns
2408     \!!countb\nofcolumns
2409   \else
2410     \!!countc\zerocount
2411   \fi
2412   \advance\!!counta \plusone
2413   \dostepwiserecurse\!!counta\!!countb\plusone
2414     {\advance\!!widtha\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
2415   \!!widthb\!!widtha
2416   \advance\!!widthb -\!!countc\textwidth
2417   \ifodd\realpageno \else % tricky, assumes that we keep there
2418     \ifcase\!!countc\else
2419       % nog niet ok voor enkel/doublesided
2420%        \advance\!!widtha \namedlayoutparameter\v!even\c!backspace
2421%        \advance\!!widtha \namedlayoutparameter\v!odd \c!backspace
2422%        \advance\!!widthb \namedlayoutparameter\v!even\c!backspace
2423       \advance\!!widtha \layoutparameter\c!backspace
2424       \advance\!!widtha \layoutparameter\c!backspace
2425       \advance\!!widthb \layoutparameter\c!backspace
2426       \dorecurse\!!countc
2427         {\advance\!!widtha\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
2428     \fi
2429   \fi}
2430
2431\def\columnsetspanhsize{\textwidth}
2432
2433\def\setcolumnsetspanhsize#1#2% x nx / uses counta/b
2434  {\!!counta#1\!!countb#2\docalculatecolumnsetspan
2435   \edef\columnsetspanhsize{\the\!!widtha}}
2436
2437\unexpanded\def\page_set_command_set_float_hsize % this helper has to be moved to strc-flt
2438  {\hsize                % maybe checking optional
2439     \ifdim\d_strc_float_temp_width>\makeupwidth
2440       \makeupwidth
2441     \else
2442       \d_strc_float_temp_width
2443     \fi}
2444
2445\installcorenamespace{columnsetspan}
2446
2447\unexpanded\def\definecolumnsetspan
2448  {\dodoubleempty\dodefinecolumnsetspan}
2449
2450\def\dodefinecolumnsetspan[#1][#2]%
2451  {%\ifsecondargument
2452     \defineframedtext % we can have a parent
2453       [\??columnsetspan#1]
2454       [\c!frame=\v!off,
2455        \c!before=,
2456        \c!after=,
2457        \c!offset=\v!overlay,
2458        \c!location=\v!left,
2459        \c!linecorrection=\v!off,
2460        \c!depthcorrection=\v!off,
2461        \c!n=2,
2462        \c!nlines=0,
2463        \c!indenting=,
2464        \c!indentnext=\v!yes,
2465        \c!default=HERE,
2466        \c!alternative=\v!a,
2467        #2]%
2468   %\else
2469   %  \definecolumnspan[][#1]%
2470  }%\fi}
2471
2472\definecolumnsetspan[\s!default]
2473
2474\unexpanded\def\setupcolumnsetspan
2475  {\dodoubleempty\dosetupcolumnsetspan}
2476
2477\def\dosetupcolumnsetspan[#1][#2]%
2478  {\ifsecondargument
2479     \setupframedtexts[\??columnsetspan#1][#2]%
2480   \else
2481     \setupcolumnsetspan[\s!default][#1]%
2482   \fi}
2483
2484\unexpanded\def\startcolumnsetspan
2485  {\dotripleempty\dostartcolumnsetspan}
2486
2487%%%%%%%%%%%%%%%% TODO
2488
2489\def\dostartcolumnsetspan[#1][#2][#3]% [#3] gobbles space
2490  {\endgraf % else rubish output if forgotten
2491   \vskip \zeropoint % make sure otr is done, otherwise last line problems
2492   \bgroup
2493   \forgetall
2494   \ifnum\columnsetlevel>\zerocount\else
2495     % of course we needed a one-column fall back for tm
2496     \columnsetspanhsize\hsize
2497     \nofcolumns\plusone
2498     \mofcolumns\plusone
2499   \fi
2500   \setupframedtexts[\??columnsetspan#1]
2501     [\c!width=\columnsetspanhsize,
2502      \c!linecorrection=\v!off,
2503      \c!depthcorrection=\v!off,
2504      #2]%
2505   % determine widths
2506   \!!countc\namedframedtextparameter{\??columnsetspan#1}\c!n
2507    % \!!countd\numexpr(\nofcolumns-\mofcolumns+\plusone)%
2508   \!!countd\nofcolumns
2509   % n <= n of columns
2510   \ifnum\!!countc>\!!countd \!!countc\!!countd \fi
2511   \advance\!!countd -\mofcolumns
2512   \advance\!!countd \plusone
2513   % n <= n of available columns (alternative a)
2514   \doif{\namedframedtextparameter{\??columnsetspan#1}\c!alternative}\v!a
2515     {\ifnum\!!countc>\!!countd \!!countc\!!countd \fi}%
2516   % here it all starts
2517   \setcolumnsetspanhsize\mofcolumns\!!countc % a/b used
2518   \hsize\columnsetspanhsize
2519   \setbox\scratchbox\vbox\bgroup
2520     \pack_framed_text_start{\??columnsetspan#1}[\v!none]% geen nils placement
2521     % spoils spacing : \vskip-\struttotal\par\verticalstrut\par
2522     \ifnum\columnsetlevel>\zerocount
2523       \namedframedtextparameter{\??columnsetspan#1}\c!before
2524     \fi
2525     \unexpanded\def\stopcolumnsetspan{\dostopcolumnsetspan{#1}}}
2526
2527\def\dostopcolumnsetspan#1%
2528  {\par
2529   \verticalstrut
2530   \kern-2\struttotal
2531   \verticalstrut
2532   \ifnum\columnsetlevel>\zerocount
2533     \doifsomething{\namedframedtextparameter{\??columnsetspan#1}\c!after}
2534       {\namedframedtextparameter{\??columnsetspan#1}\c!after
2535        \kern\zeropoint}% otherwise blanks disappear, better be a switch
2536   \else
2537     \endgraf
2538   \fi
2539   \pack_framed_text_stop
2540   \egroup
2541   \setbox\scratchbox\frozenhbox to \hsize
2542     {\dontcomplain
2543      \alignedline{\namedframedtextparameter{\??columnsetspan#1}\c!location}\v!middle{\lower\strutdepth\box\scratchbox}}%
2544   \dp\scratchbox\zeropoint % else wrong snap insidefloat
2545%
2546% to be tested first (strange in grid mode)
2547%
2548% \setbox\scratchbox\frozenhbox to \hsize
2549%   {\dontcomplain
2550%    \alignstrutmode\zerocount
2551%    \alignedline{\namedframedtextparameter{\??columnsetspan#1}\c!plaats}\v!midden
2552%      {\box\scratchbox}}%
2553%
2554   \ifinsidefloat
2555     \box\scratchbox
2556   \else\ifnum\columnsetlevel>\zerocount
2557     % we only set \columnsetspacing when asked for, else bottom problems
2558     % don't change this any more (test naw)
2559     \columnslotspacing\namedframedtextparameter{\??columnsetspan#1}\c!nlines\relax
2560     % todo: nboven/onder
2561     %\OTRSETstoreincolumnslotHERE\scratchbox
2562     \edef\floatmethod{\namedframedtextparameter{\??columnsetspan#1}\c!default}%
2563     \expandafter\uppercasestring\floatmethod\to\floatmethod
2564     % todo : \v!here -> here enzovoorts
2565     \OTRSETstoreincolumnslot\floatmethod\scratchbox
2566     \checknextindentation[\namedframedtextparameter{\??columnsetspan#1}\c!indentnext]%
2567   \else
2568     % of course we needed a one-column fall back for tm; brrr, the box has now too
2569     % much height (try \ruledvbox); don't change this without testing techniek
2570     \scratchdimen\ht\scratchbox
2571     \advance\scratchdimen-\strutdp
2572     \ht\scratchbox\scratchdimen
2573     \namedframedtextparameter{\??columnsetspan#1}\c!before
2574     \snaptogrid\vbox{\box\scratchbox}%
2575     \namedframedtextparameter{\??columnsetspan#1}\c!after
2576   \fi\fi
2577   \egroup
2578   \endgraf}
2579
2580% \startcolumnset[two]
2581%   \input tufte
2582%   \startcolumnsetspan[two][width=20cm,location=middle] \input tufte \stopcolumnsetspan
2583%   \startcolumnsetspan[two][default=btlr] \input tufte \stopcolumnsetspan
2584%   \input tufte \par
2585%   \input tufte \par
2586%   \startcolumnsetspan[two] \emptylines[5] \stopcolumnsetspan
2587%   \startcolumnsetspan[two] \input tufte   \stopcolumnsetspan
2588% \stopcolumnset
2589
2590\unexpanded\def\page_set_command_flush_saved_floats % rather similar to _one_ ut this might change
2591  {\global\d_page_floats_inserted_top\zeropoint
2592   \global\d_page_floats_inserted_bottom\zeropoint
2593   \ifconditional\c_page_floats_flushing \else
2594     \page_set_command_set_top_insertions
2595     \page_set_command_set_bottom_insertions
2596     \ifconditional\c_page_floats_some_waiting
2597        \doif{\rootfloatparameter\c!cache}\v!no\page_set_command_flush_floats % could be _otr_
2598     \fi
2599   \fi}
2600
2601\unexpanded\def\page_set_command_flush_all_floats
2602  {\page_one_command_flush_all_floats}
2603
2604\defineoutputroutine
2605  [\s!columnset]
2606  [\s!page_otr_command_routine                  =\page_set_command_routine,
2607   \s!page_otr_command_package_contents         =\page_set_command_package_contents,
2608   \s!page_otr_command_set_vsize                =\page_set_command_set_vsize,
2609 % \s!page_otr_command_set_hsize                =\page_one_command_set_hsize, % tricky, goes wrong
2610   \s!page_otr_command_synchronize_hsize        =\page_set_command_synchronize_hsize,
2611   \s!page_otr_command_next_page                =\page_set_command_next_page,
2612   \s!page_otr_command_next_page_and_inserts    =\page_set_command_next_page_and_inserts,
2613   \s!page_otr_command_set_top_insertions       =\page_set_command_set_top_insertions,
2614   \s!page_otr_command_set_bottom_insertions    =\page_set_command_set_bottom_insertions,
2615   \s!page_otr_command_flush_top_insertions     =\page_set_command_flush_top_insertions,
2616   \s!page_otr_command_flush_bottom_insertions  =\page_set_command_flush_bottom_insertions,
2617   \s!page_otr_command_check_if_float_fits      =\page_set_command_check_if_float_fits,
2618   \s!page_otr_command_set_float_hsize          =\page_set_command_set_float_hsize,
2619   \s!page_otr_command_flush_float_box          =\page_set_command_flush_float_box,
2620   \s!page_otr_command_side_float_output        =\page_set_command_side_float_output,
2621   \s!page_otr_command_synchronize_side_floats  =\page_set_command_synchronize_side_floats,
2622   \s!page_otr_command_flush_floats             =\page_set_command_flush_floats,
2623   \s!page_otr_command_flush_side_floats        =\page_set_command_flush_side_floats,
2624   \s!page_otr_command_flush_saved_floats       =\page_set_command_flush_saved_floats,
2625   \s!page_otr_command_flush_all_floats         =\page_set_command_flush_all_floats,
2626 % \s!page_otr_command_flush_margin_blocks      =\page_set_command_flush_margin_blocks, % not used
2627  ]
2628
2629\installfloatmethod \s!columnset \v!here   \page_set_place_float_here
2630\installfloatmethod \s!columnset \v!force  \page_set_place_float_force
2631\installfloatmethod \s!columnset \v!top    \page_set_place_float_top
2632\installfloatmethod \s!columnset \v!bottom \page_set_place_float_bottom
2633\installfloatmethod \s!columnset \v!page   \page_set_place_float_page
2634\installfloatmethod \s!columnset \s!tblr   \page_set_place_float_slot
2635\installfloatmethod \s!columnset \s!lrtb   \page_set_place_float_slot
2636\installfloatmethod \s!columnset \s!tbrl   \page_set_place_float_slot
2637\installfloatmethod \s!columnset \s!rltb   \page_set_place_float_slot
2638\installfloatmethod \s!columnset \s!fxtb   \page_set_place_float_slot
2639\installfloatmethod \s!columnset \s!btlr   \page_set_place_float_slot
2640\installfloatmethod \s!columnset \s!lrbt   \page_set_place_float_slot
2641\installfloatmethod \s!columnset \s!btrl   \page_set_place_float_slot
2642\installfloatmethod \s!columnset \s!rlbt   \page_set_place_float_slot
2643\installfloatmethod \s!columnset \s!fxbt   \page_set_place_float_slot
2644\installfloatmethod \s!columnset \s!fixd   \page_set_place_float_force
2645
2646\protect \endinput
2647
2648% extreme examples (1)
2649%
2650% \setupfloats[numbering=nocheck]
2651%
2652% \definecolumnset [first] [n=2,start=0]
2653% \definecolumnset [next]  [n=2,start=3]
2654%
2655% \setuptexttexts[\vbox to \textheight{\topskipcorrection \hsize\makeupwidth left \hfill right\vfill}]
2656%
2657% \setuphead[chapter][text=empty]
2658%
2659% \starttext
2660%
2661% \startcolumnset[first,next]
2662%   \placefigure[btrl]{}{}
2663%   \placefigure[tblr]{}{}
2664%   \chapter{thuan} \dorecurse{25}{\recurselevel: \input thuan \endgraf}
2665% \stopcolumnset
2666%
2667% \startcolumnset[first,next]
2668%   \chapter{thuan} \dorecurse{25}{\input thuan \endgraf\placefigure{}{}}
2669% \stopcolumnset
2670
2671% only in columnsets
2672
2673% \def\cornerfigure
2674%   {\dotripleempty\docornerfigure}
2675%
2676% \def\docornerfigure[#1][#2][#3]% [layer] [location] [settings]
2677%   {\bgroup
2678%    \dowithnextbox
2679%      {\!!doneafalse
2680%       \!!donebfalse
2681%       \processallactionsinset
2682%         [\v!left,\v!bottom,#2]
2683%         [ \v!left=>\!!doneatrue ,
2684%          \v!right=>\!!doneafalse,
2685%           \v!top=>\!!donebtrue ,
2686%           \v!bottom=>\!!donebfalse]%
2687%       \!!widtha\nextboxwd
2688%       \if!!donea
2689%         % unchecked
2690%         \advance\!!widtha-\backspace
2691%       \else
2692%         % unchecked
2693%         \advance\!!widtha-\backspace
2694%       \fi
2695%       \!!widtha\textwidth % could be an option
2696%       \!!heighta\nextboxht
2697%       % zou een macro moeten zijn \getnoflayoutlines
2698%       \ifnum\layoutparameter\c!lines=\zerocount
2699%         \getnoflines\textheight
2700%       \else
2701%         \noflines\layoutparameter\c!lines
2702%       \fi
2703%       %
2704%       \advance\noflines \plusone % wordt default, instelbaar
2705%       \!!heightb\noflines\lineheight\relax
2706%       \if!!doneb % boven
2707%         % unchecked
2708%         \advance\!!heighta-\topspace
2709%         \advance\!!heighta-\headerheight
2710%         \advance\!!heighta-\headerdistance
2711%       \else % onder
2712%         % checked
2713%         \advance\!!heighta-\paperheight
2714%         \advance\!!heighta+\!!heightb
2715%         \advance\!!heighta+\topspace
2716%         \advance\!!heighta+\headerheight
2717%         \advance\!!heighta+\headerdistance
2718%         \advance\!!heighta-\footerdistance
2719%         \advance\!!heighta-\footerheight
2720%       \fi
2721%       \getnoflines\!!heighta
2722%       \!!heighta\noflines\lineheight\relax
2723%       \def\docornerfigure[####1]%
2724%         {\expanded{\plaatsfiguur[####1,\v!none]{}
2725%            {\noexpand\phantombox[\c!width=\the\!!widtha,\c!height=\the\!!heighta]}}}%
2726%       \if!!donea
2727%         \if!!doneb % links  boven / rb
2728%           \setlayer[#1]
2729%             [\c!corner={\v!left,\v!top},\c!location=rb,#3]
2730%             {\flushnextbox}%
2731%           \docornerfigure[tblr]%
2732%         \else      % links  onder / rt
2733%           \setlayer[#1]
2734%             [\c!corner={\v!left,\v!bottom},\c!location=rt,#3]
2735%             {\flushnextbox}%
2736%           \docornerfigure[btlr]%
2737%         \fi
2738%       \else
2739%         \if!!doneb % rechts boven / lt
2740%           \setlayer[#1]
2741%             [\c!corner={\v!right,\v!top},\c!location=lb,#3]
2742%             {\flushnextbox}%
2743%           \docornerfigure[tbrl]%
2744%         \else      % rechts onder / lb
2745%           \setlayer[#1]
2746%             [\c!corner={\v!right,\v!bottom},\c!location=lt,#3]
2747%             {\flushnextbox}%
2748%           \docornerfigure[btrl]%
2749%         \fi
2750%       \fi
2751%       \egroup}
2752%    \vbox}
2753