page-mul.mkiv /size: 64 Kb    last modification: 2021-10-28 13:50
1
%D \module
2
%D [ file=page-mul, % was: core-mul
3
%D version=1998.03.15,
4
%D title=\CONTEXT\ Page Macros,
5
%D subtitle=Multi Column Output,
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
% todo: basecolumns as parent for columns and itemize
15 16
% !!! there are some issues with hsize an vsize as well as flushing
17
% !!! floats but this module will be redone anyway
18
%
19
% can have some vpack and hpack
20 21
\writestatus
{
loading
}
{
ConTeXt
Page
Macros
/
Simple
Multi
Column
}
22 23
%D This module is mostly a copy from the original multi column routine as
24
%D implemented in \type {core-mul}. When the main OTR macro's were
25
%D isolated in modules and column sets were introduced, this module became
26
%D part of the OTR modules. As a result this module is no longer generic.
27 28
\unprotect
29 30
\definesystemvariable
{
ks
}
% KolomSpan
31 32
% check \count<insert> multiplications
33 34
%D The following macro's implement a multi||column output routine. The original
35
%D implementation was based on Donald Knuth's implementation, which was adapted by
36
%D Craig Platt to support balancing of the last page. I gradually adapted Platt's
37
%D version to our needs but under certain circumstances things still went wrong. I
38
%D considered all calls to Platt's \type{\page_mul_routine_error} as undesirable.
39
%D
40
%D This completely new implementation can handle enough situations for everyday
41
%D documents, but is still far from perfect. While at the moment the routine doesn't
42
%D support all kind of floats, it does support:
43
%D
44
%D \startitemize[packed]
45
%D \item an unlimitted number of columns
46
%D \item ragged or not ragged bottoms
47
%D \item optional balancing without \type{\page_mul_routine_errors}
48
%D \item different \type{\baselineskips}, \type{\spacing}, \type {\topskip} and
49
%D \type {\maxdepth}
50
%D \item left- and right indentation, e.g. within lists
51
%D \item moving columns floats to the next column or page
52
%D \item handling of floats that are to wide for a columns
53
%D \stopitemize
54
%D
55
%D One could wonder why single and multi||columns modes are still separated. One
56
%D reason for this is that \TeX\ is not suited well for handling multi||columns. As
57
%D a result, the single columns routines are more robust. Handling one column as a
58
%D special case of multi||columns is posible but at the cost of worse float
59
%D handling, worse page breaking, worse etc. Complicated multi||column page handling
60
%D should be done in \cap{DTP}||systems anyway.
61 62
\installcorenamespace
{
columns
}
63 64
\installframedcommandhandler
\??columns
{
columns
}
\??columns
65 66
%D Going to a new columns is done by means of a \type {\ejectcolumn}. The
67
%D following definition does not always work.
68 69
\unexpanded
\def
\ejectcolumn
% not good enough
70
{
\goodbreak
71
\showmessage
\m!columns
2
\empty
}
72 73
%D The output routines plug into a more generic mechanism as can be seen at the
74
%D end of this file. So, occasionally we need to define some plugin code.
75 76
\unexpanded
\def
\page_mul_place_float_top
77
{
\showmessage
\m!columns
4
\empty
\page_one_place_float_here
}
78 79
\unexpanded
\def
\page_mul_place_float_bottom
80
{
\showmessage
\m!columns
5
\empty
\page_one_place_float_here
}
81 82
\unexpanded
\def
\page_mul_place_float_here
83
{
\page_one_place_float_here
}
84 85
\unexpanded
\def
\page_mul_place_float_force
86
{
\page_one_place_float_force
}
87 88
\unexpanded
\def
\page_mul_command_side_float_output
89
{
\page_otr_construct_and_shipout
\unvbox
\normalpagebox
\zerocount
}
% three arguments
90 91
\unexpanded
\def
\page_mul_command_flush_side_floats
92
{
\page_sides_forget_floats
}
93 94
\unexpanded
\def
\page_mul_command_synchronize_side_floats
95
{
\page_sides_forget_floats
}
96 97
\unexpanded
\def
\page_mul_command_next_page
98
{
\page_otr_eject_page
}
99 100
\unexpanded
\def
\page_mul_command_next_page_and_inserts
101
{
\page_otr_eject_page_and_flush_inserts
}
102 103
\let
\page_mul_initialize_floats
\relax
104
\let
\page_mul_flush_floats
\relax
105
\let
\page_mul_flush_float
\relax
106 107
%D A hook:
108 109
\let
\finishcolumnbox
\relax
% todo in mkiv
110 111
%D This will change to a local one:
112 113
\ifdefined
\nofcolumns
\else
\newcount
\nofcolumn
\fi
114
\ifdefined
\mofcolumns
\else
\newcount
\mofcolumn
\fi
115 116
\appendtoks
117
\nofcolumns
\columnsparameter
\c!n
\relax
118
\to
\everysetupcolumns
119 120
%D Columns are separated by spacing or rules or whatever suits.
121 122
\installcorenamespace
{
columnseparators
}
123 124
\setvalue
{
\??columnseparators
\v!on
}
{
\let
\page_mul_between_columns
\page_mul_between_columns_rule
}
125
\setvalue
{
\??columnseparators
\v!off
}
{
\let
\page_mul_between_columns
\page_mul_between_columns_space
}
126
\setvalue
{
\??columnseparators
}
{
\let
\page_mul_between_columns
\page_mul_between_columns_space
}
127
\setvalue
{
\??columnseparators
\s!unknown
}
{
\let
\page_mul_between_columns
\p_page_mul_rule
}
128 129
\def
\page_mul_between_columns_rule
130
{
\bgroup
131
\starttextproperties
132
\scratchdistance
\dimexpr
\columnsparameter
\c!distance
/
2
\relax
133
\hskip
\scratchdistance
\relax
134
\vrule
135
\s!width
\linewidth
136
\ifnum
\bottomraggednessmode
=
\plustwo
% baselinebottom
137
\s!depth
\strutdepth
138
\fi
139
\hskip
\scratchdistance
\relax
140
\stoptextproperties
141
\egroup
}
142 143
\def
\page_mul_between_columns_space
144
{
\hskip
\columnsparameter
\c!distance
\relax
}
145 146
\let
\page_mul_between_columns
\page_mul_between_columns_space
147 148
%D We declare some registers:
149 150
\newdimen
\d_page_mul_available_width
151
\newdimen
\d_page_mul_distance
152
\newdimen
\d_page_mul_leftskip
153
\newdimen
\d_page_mul_rightskip
154
\newdimen
\d_page_mul_offset
155
\newdimen
\d_page_mul_forced_height
156
\newdimen
\d_page_mul_used_width
157
\newdimen
\d_page_mul_temp
158 159
\newcount
\c_page_mul_balance_minimum
160
\newcount
\c_page_mul_n_of_lines
161 162
\newbox
\b_page_mul_preceding
163
\newdimen
\d_page_mul_preceding_height
164
\newdimen
\d_page_mul_preceding_depth
165
\newconditional
\c_page_mul_preceding_present
166 167
\newbox
\b_page_mul_preceding_rest_of_page
168 169
\newconditional
\c_page_mul_reverse
170
\newconditional
\c_page_mul_trace
171 172
%D The next dimensions reports the final column height .. todo
173 174
\newdimen
\finalcolumnheights
175
\newcount
\finalcolumnlines
176 177
\newdimen
\savedpagetotal
% brrr
178 179
\newif
\ifstretchcolumns
\stretchcolumnsfalse
180
\newif
\ifheightencolumns
\heightencolumnsfalse
181
\newif
\ifinheritcolumns
\inheritcolumnsfalse
182
\newif
\ifbalancecolumns
%\balancecolumnstrue
183 184
%D An important one:
185 186
\unexpanded
\def
\page_mul_command_set_hsize
% beware, this one is available for use in macros
187
{
\setbox
\scratchbox
\hbox
{
\page_mul_between_columns
}
%
188
\d_page_mul_distance
\wd
\scratchbox
189
\d_page_mul_available_width
\dimexpr
190
\makeupwidth
191
-
\d_page_mul_leftskip
192
-
\d_page_mul_rightskip
193
-
\nofcolumns
\d_page_mul_distance
194
+
\d_page_mul_distance
195
\relax
196
\d_page_mul_used_width
\dimexpr
197
\d_page_mul_available_width
/
\nofcolumns
198
-
\d_page_mul_offset
*
\plustwo
199
\relax
200
\textwidth
\d_page_mul_used_width
% needs thinking ... grouping etc
201
\hsize
\d_page_mul_used_width
}
202 203
%D Torture test:
204
%D
205
%D \startbuffer
206
%D \startbuffer[b]
207
%D \startcolumns
208
%D \input tufte
209
%D \stopcolumns
210
%D \stopbuffer
211
%D \typebuffer[b] \getbuffer[b]
212
%D
213
%D \startbuffer[b]
214
%D \startnarrower
215
%D \input tufte
216
%D \stopnarrower
217
%D \stopbuffer
218
%D \typebuffer[b] \getbuffer[b]
219
%D
220
%D \startbuffer[b]
221
%D \startcolumns \startnarrower
222
%D \input tufte
223
%D \stopnarrower \stopcolumns
224
%D \stopbuffer
225
%D \typebuffer[b] \getbuffer[b]
226
%D
227
%D \startbuffer[b]
228
%D \startnarrower \startcolumns
229
%D \input tufte
230
%D \stopcolumns \stopnarrower
231
%D \stopbuffer
232
%D \typebuffer[b] \getbuffer[b]
233
%D
234
%D \startbuffer[b]
235
%D \startcolumns \startnarrower[left]
236
%D \input tufte
237
%D \stopnarrower \stopcolumns
238
%D \stopbuffer
239
%D \typebuffer[b] \getbuffer[b]
240
%D
241
%D \startbuffer[b]
242
%D \startnarrower[left] \startcolumns
243
%D \input tufte
244
%D \stopcolumns \stopnarrower
245
%D \stopbuffer
246
%D \typebuffer[b] \getbuffer[b]
247
%D
248
%D \startbuffer[b]
249
%D \startnarrower \startcolumns \startnarrower
250
%D \input tufte
251
%D \stopnarrower\stopcolumns \stopnarrower
252
%D \stopbuffer
253
%D \typebuffer[b] \getbuffer[b]
254
%D
255
%D \startbuffer[b]
256
%D \startnarrower[left] \startcolumns \startnarrower
257
%D \input tufte
258
%D \stopnarrower\stopcolumns \stopnarrower
259
%D \stopbuffer
260
%D \typebuffer[b] \getbuffer[b]
261
%D \stopbuffer
262
%D
263
%D \start
264
%D \def\postprocesscolumnline#1{\ruledhbox{\strut\box#1}\hss}
265
%D \getbuffer
266
%D \stop
267 268
%D One should be aware that when font related dimensions are used in typesetting the
269
%D in||between material, these dimensions are influenced by bodyfont switches inside
270
%D multi||column mode.
271 272
\setnewconstant
\multicolumnlinemethod
\zerocount
% 0=normal 1=raw
273 274
\def
\multicolumnovershootratio
{
.
5
}
% {\ifgridsnapping0\else.5\fi}
275 276
\unexpanded
\def
\page_mul_set_n_of_lines
277
{
\settotalinsertionheight
278
\d_page_mul_temp
\dimexpr
279
-
\d_page_mul_offset
*
\plustwo
280
+
\textheight
281
\ifdim
\d_page_mul_preceding_height
>
\zeropoint
-
\d_page_mul_preceding_height
\fi
282
-
\totalinsertionheight
283
\relax
284
\ifcase
\multicolumnlinemethod
285
\getnoflines
\d_page_mul_temp
\or
286
\getrawnoflines
\d_page_mul_temp
\else
287
\getrawnoflines
\d_page_mul_temp
288
\fi
289
% added 30/7/2004
290
\ifnum
\layoutlines
>
\zerocount
\ifnum
\noflines
>
\layoutlines
291
\noflines
\layoutlines
292
\fi
\fi
293
\c_page_mul_n_of_lines
\noflines
}
294 295
\unexpanded
\def
\page_mul_command_set_vsize
296
{
\page_one_command_set_vsize
% indeed?
297
\page_mul_set_n_of_lines
298
\d_page_mul_temp
\nofcolumns
\dimexpr
299
\c_page_mul_n_of_lines
\openlineheight
300
+
\multicolumnovershootratio
\openlineheight
% collect enough data
301
\relax
302
\global
\vsize
\d_page_mul_temp
303
\pagegoal
\d_page_mul_temp
}
% let's do it only here
304 305
%D It really starts here. After some checks and initializations we change the output
306
%D routine to continous multi||column mode. This mode handles columns that fill the
307
%D current and next full pages. The method used is (more or less) multiplying \type
308
%D {\vsize} and dividing \type {\hsize} by \type {\nofcolumns}. More on this can be
309
%D found in the \TeX book. We save the top of the current page in box
310
%D \type {\b_page_mul_preceding}.
311
%D
312
%D We manipulate \type {\topskip} a bit, just to be shure that is has no
313
%D flexibility. This has te be done every time a font switch takles place, because
314
%D \type {\topskip} can depend on this.
315 316
\newconstant
\c_page_mul_routine
317 318
\setnewconstant
\c_page_mul_routine_regular
\zerocount
319
\setnewconstant
\c_page_mul_routine_intercept
\plusone
320
\setnewconstant
\c_page_mul_routine_continue
\plustwo
321
\setnewconstant
\c_page_mul_routine_balance
\plusthree
322
\setnewconstant
\c_page_mul_routine_error
\plusfour
323 324
\unexpanded
\def
\page_mul_command_routine
325
{
\ifcase
\c_page_mul_routine
326
\page_one_command_routine
327
\or
328
\page_mul_routine_intercept
329
\or
330
\page_mul_routine_continue
331
\or
332
\page_mul_routine_balance
333
\or
334
\page_mul_routine_error
335
\fi
}
336 337
\def
\page_mul_routine_intercept
338
{
\global
\setbox
\b_page_mul_preceding
\vbox
339
{
\page_otr_command_flush_top_insertions
340
\unvbox
\normalpagebox
}
}
341 342
\def
\page_mul_routine_error
343
{
\showmessage
\m!columns
3
\empty
344
\page_otr_construct_and_shipout
\unvbox
\normalpagebox
\zerocount
}
% three arguments
345 346
%D When we leave the multi||column mode, we have to process the not yet shipped out
347
%D part of the columns. When we don't balance, we simply force a continuous output,
348
%D but a balanced output is more tricky.
349
%D
350
%D First we try to fill up the page and when all or something is left we try to
351
%D balance things. This is another useful adaption of the ancesters of these
352
%D macro's. It takes some reasoning to find out what happens and maybe I'm making
353
%D some mistake, but it works.
354
%D
355
%D Voiding box \type {\b_page_mul_preceding} is sometimes necessary, e.g. when there is no
356
%D text given between \type {\begin..} and \type {\end..}. The \type {\par} is
357
%D needed!
358 359
%D Because some initializations happen three times, we defined a macro for
360
%D them. Erasing \type{\everypar} is needed because we don't want anything
361
%D to interfere.
362 363
\unexpanded
\def
\page_mul_initialize_variables
364
{
\reseteverypar
365
\dontcomplain
366
\settopskip
367
\setmaxdepth
368
\topskip
1
\topskip
369
\splittopskip
\topskip
370
\splitmaxdepth
\maxdepth
371
\boxmaxdepth
\maxdepth
% dangerous
372
\emergencystretch
\zeropoint
373
\relax
}
% sometimes needed !
374 375
%D Flushing the page comes to pasting the columns together and appending the result
376
%D to box \type {\b_page_mul_preceding}, if not void. I've seen a lot of implementations in
377
%D which some skip was put between normal text and multi||column text. When we don't
378
%D want this, the baselines can be messed up. I hope the seemingly complicated
379
%D calculation of a correction \type {\kern} is adequate to overcome this. Although
380
%D not watertight, spacing is taken into account and even multiple mode changes on
381
%D one page go well. But cross your fingers and don't blame me.
382
%D
383
%D One of the complications of flushing out the boxes is that \type {\b_page_mul_preceding}
384
%D needs to be \type {\unvbox}'ed, otherwise there is too less flexibility in the
385
%D page when using \type {\raggedbottom}. It took a lot of time before these kind of
386
%D problems were overcome. Using \type {\unvbox} at the wrong moment can generate
387
%D \type {\page_mul_routine_error}'s.
388
%D
389
%D One can use the macros \type {\maxcolumnheight} and \type {\maxcolumndepth} when
390
%D generating material between columns as well as postprocessing column lines.
391 392
\newdimen
\maxcolumnheight
393
\newdimen
\maxcolumndepth
394 395
\newbox
\columnpagebox
396 397
\def
\page_mul_calculate_column_result_dimensions
398
{
\maxcolumnheight
\zeropoint
399
\maxcolumndepth
\zeropoint
400
\dohandleallcolumnscs
\page_mul_calculate_column_result_dimensions_step
}
401 402
\def
\page_mul_calculate_column_result_dimensions_step
403
{
\ifdim
\ht
\currentcolumnbox
>
\maxcolumnheight
404
\maxcolumnheight
\ht
\currentcolumnbox
405
\fi
406
\ifdim
\dp
\currentcolumnbox
>
\maxcolumndepth
407
\maxcolumndepth
\dp
\currentcolumnbox
408
\fi
}
409 410
\setnewconstant
\multicolumntopflushmethod
\plusone
% 0: no correction, 1: correction when topstuff, 2: correction, 3: correction++
411
\setnewconstant
\multicolumntopalignmethod
\plustwo
% 0: nothing, 1: force grid, 2: follow grid
412 413
\def
\page_mul_flush_preceding_normal
414
{
\unvbox
\b_page_mul_preceding
}
415 416
\def
\page_mul_flush_preceding_ongrid
417
{
\scratchdimen
\dimexpr
418
\savedpagetotal
419
-
\d_page_mul_preceding_height
420
-
\d_page_mul_preceding_depth
421
-
\topskip
422
\relax
423
\box
\b_page_mul_preceding
424
\kern
\scratchdimen
}
425 426
\def
\page_mul_flush_packaged_columns_continued
427
{
\bgroup
428
\page_mul_flush_packaged_columns_indeed
429
\box
\columnpagebox
430
\egroup
}
431 432
\def
\page_mul_flush_packaged_columns_balanced
433
{
\bgroup
434
\page_mul_flush_packaged_columns_indeed
435
% messy correction, we need to rewrite this module (newcolumns)
436
\setbox
\columnpagebox
\vbox
437
{
\offinterlineskip
438
\scratchdimen
\htdp
\columnpagebox
439
\box
\columnpagebox
440
\vskip
-
\scratchdimen
}
%
441
\ht
\columnpagebox
\dimexpr
442
\noflines
\openlineheight
443
-
\openstrutdepth
444
\ifgridsnapping
445
% quick hack (at least it works with itemize)
446
\else
447
-
\openlineheight
448
+
\topskip
449
\fi
450
\relax
451
\dp
\columnpagebox
\openstrutdepth
452
% end of mess
453
\box
\columnpagebox
454
\egroup
}
455 456
\def
\page_mul_synchronize_marks
457
{
\dohandleallcolumns
{
\page_marks_synchronize_column
\plusone
\nofcolumns
\mofcolumns
\currentcolumnbox
}
}
458 459
\def
\page_mul_flush_packaged_columns_indeed
460
{
\ifvoid
\b_page_mul_preceding
461
\setfalse
\c_page_mul_preceding_present
% will be set elsewhere
462
\else
463
\settrue
\c_page_mul_preceding_present
464
\page_apply_postprocessors_box
\b_page_mul_preceding
465
\fi
466
\forgetall
467
\page_mul_initialize_variables
468
\page_mul_calculate_column_result_dimensions
469
\page_mul_postprocess_linenumbers
470
\page_mul_synchronize_marks
471
\page_mul_postprocess_lines
472
\page_mul_postprocess_columns
473
\dohandleallcolumns
474
{
\global
\setbox
\currentcolumnbox
\hpack
to
\d_page_mul_used_width
475
{
\box
\currentcolumnbox
}
%
476
\wd
\currentcolumnbox
\d_page_mul_used_width
477
\ifheightencolumns
478
\ht
\currentcolumnbox
\d_page_mul_forced_height
479
\fi
}
%
480
\page_mul_calculate_column_result_dimensions
481
\overlaycolumnfootnotes
482
\setbox
\columnpagebox
\vpack
% \vbox
483
{
\ifconditional
\c_page_mul_reverse
\reversehpack
\else
\naturalhpack
\fi
to
\makeupwidth
484
{
\hskip
\ifconditional
\c_page_mul_reverse
\d_page_mul_rightskip
\else
\d_page_mul_leftskip
\fi
\relax
485
\dohandleallcolumns
486
{
\finishcolumnbox
487
{
\setbox
\scratchbox
\hpack
488
{
\ifx
\finishcolumnbox
\relax
\else
\strut
\fi
489
\box
\currentcolumnbox
}
% hm, why strut
490
\anch_mark_column_box
\scratchbox
\currentcolumn
491
\box
\scratchbox
}
%
492
\hfil
}
%
493
\unskip
494
\hskip
\ifconditional
\c_page_mul_reverse
\d_page_mul_leftskip
\else
\d_page_mul_rightskip
\fi
}
}
%
495
\scratchdimen
\zeropoint
496
\dohandleallcolumns
497
{
\ifdim
-
\ht
\currenttopcolumnbox
<
\scratchdimen
498
\scratchdimen
-
\ht
\currenttopcolumnbox
499
\fi
500
\global
\setbox
\currenttopcolumnbox
\emptybox
}
%
501
\advance
\scratchdimen
\ht
\columnpagebox
502
\setbox
\scratchbox
\hbox
to
\makeupwidth
% between can be something so no \hpack
503
{
\vrule
504
\s!width
\zeropoint
505
\s!height
\scratchdimen
506
\s!depth
\dp
\columnpagebox
507
\dostepwiserecurse
\plustwo
\nofcolumns
\plusone
{
\hfil
\page_mul_between_columns
}
\hfil
}
%
508
\setbox
\columnpagebox
\hpack
509
{
\box
\columnpagebox
510
\hskip
-
\makeupwidth
511
\box
\scratchbox
}
%
512
\page_mul_postprocess_page
513
\ifconditional
\c_page_mul_preceding_present
514
\settrue
\c_page_mul_preceding_present
515
% next some incredible crappy code
516
\ifcase
\multicolumntopalignmethod
517
\page_mul_flush_preceding_normal
% not on grid
518
\or
519
\page_mul_flush_preceding_ongrid
% force on grid
520
\else
\ifgridsnapping
521
\page_mul_flush_preceding_ongrid
% obey grid settings, force on grid
522
\else
523
\page_mul_flush_preceding_normal
% ignore grid settings, not on grid
524
\fi
\fi
525
\fi
526
\global
\d_page_mul_preceding_height
\zeropoint
527
\page_otr_command_set_vsize
528
\dosomebreak
\nobreak
% hm, only needed when topstuff
529
\ifgridsnapping
\else
530
\ifcase
\multicolumntopflushmethod
531
% sometimes method 1 goes wrong, so we need a way out; best sort this out
532
% when we run into it again
533
\or
534
% \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte
535
\ifconditional
\c_page_mul_preceding_present
536
% \scratchdimen\topskip
537
% \advance\scratchdimen -\openstrutheight
538
% \nointerlineskip
539
% \vskip-\scratchdimen
540
\nointerlineskip
541
\vskip
\dimexpr
\openstrutheight
-
\topskip
\relax
542
\fi
543
\or
544
% \scratchdimen\topskip
545
% \advance\scratchdimen -\openstrutheight
546
% \nointerlineskip
547
% \vskip-\scratchdimen
548
\nointerlineskip
549
\vskip
\dimexpr
\openstrutheight
-
\topskip
\relax
550
\or
551
% untested but maybe handy
552
% \scratchdimen\topskip
553
% \advance\scratchdimen -\openstrutheight
554
% \nointerlineskip
555
% \vskip-\scratchdimen
556
% \vskip-\lineheight
557
% \vbox{\strut}%
558
\nointerlineskip
559
\vskip
\dimexpr
\openstrutheight
-
\topskip
-
\lineheight
\relax
560
\vbox
{
\strut
}
%
561
\fi
562
\fi
563
\prevdepth
\openstrutdepth
564
\nointerlineskip
565
\dp
\columnpagebox
\zeropoint
566
\global
\finalcolumnheights
\ht
\columnpagebox
567
\getnoflines
\finalcolumnheights
568
\global
\finalcolumnlines
\noflines
}
569 570
%D In case one didn't notice, finaly \type{\finishcolumnbox} is applied to
571
%D all boxes. One can use these hooks for special purposes.
572
%D
573
%D Once upon a time I wanted to manipulate the individual lines in a column.
574
%D This feature is demonstrated in the two examples below.
575
%D
576
%D \startbuffer
577
%D \def\postprocesscolumnline#1% or \postprocesscolumnbox
578
%D {\ruledhbox{\box#1}\hss}
579
%D
580
%D \startcolumns[n=4]
581
%D \dorecurse{25}{line: \recurselevel\par}
582
%D \stopcolumns
583
%D \stopbuffer
584
%D
585
%D \typebuffer
586
%D
587
%D Here we show the natural width of the lines:
588
%D
589
%D {\getbuffer}
590
%D
591
%D The next example does a bit more advanced manipulation:
592
%D
593
%D \startbuffer
594
%D \def\postprocesscolumnline#1%
595
%D {\ifodd\currentcolumn
596
%D \hfill\unhbox#1\relax
597
%D \else
598
%D \relax\unhbox#1\hfill
599
%D \fi}
600
%D
601
%D \startcolumns[n=4]
602
%D \dorecurse{25}{line \recurselevel\par}
603
%D \stopcolumns
604
%D \stopbuffer
605
%D
606
%D \typebuffer
607
%D
608
%D Here we also see an application of \type{\currentcolumn}:
609
%D
610
%D {\getbuffer}
611
%D
612
%D This feature is implemented using the reshape macros presented
613
%D in \type{supp-box}.
614 615
%ifdefined\page_postprocessors_column\else\let\page_postprocessors_column\relax\fi % operates on passed box
616
\ifdefined
\postprocesscolumnline
\else
\let
\postprocesscolumnline
\relax
\fi
% operates on passed box
617
\ifdefined
\postprocesscolumnbox
\else
\let
\postprocesscolumnbox
\relax
\fi
% operates on passed box
618
\ifdefined
\postprocesscolumnpagebox
\else
\let
\postprocesscolumnpagebox
\relax
\fi
% operates on passed box
619 620
%def\page_mul_postprocess_linenumbers{\ifx\page_postprocessors_column\relax\else\page_mul_postprocess_linenumbers_indeed\fi}
621
\def
\page_mul_postprocess_lines
{
\ifx
\postprocesscolumnline
\relax
\else
\page_mul_postprocess_lines_indeed
\fi
}
622
\def
\page_mul_postprocess_columns
{
\ifx
\postprocesscolumnbox
\relax
\else
\page_mul_postprocess_columns_indeed
\fi
}
623
\def
\page_mul_postprocess_page
{
\ifx
\postprocesscolumnpagebox
\relax
\else
\page_mul_postprocess_page_indeed
\fi
}
624 625
% \def\page_mul_postprocess_linenumbers_indeed
626
% {\dohandleallcolumns{\page_apply_postprocessors_column\currentcolumnbox}}
627 628
\def
\page_mul_postprocess_linenumbers
629
{
\dohandleallcolumns
{
\page_apply_postprocessors_column
\currentcolumnbox
}
}
630 631
\def
\page_mul_postprocess_lines_indeed
632
{
\dohandleallcolumnscs
\page_mul_postprocess_lines_step
}
633 634
\def
\page_mul_postprocess_lines_step
% TODO: use lua solution instead
635
{
\global
\setbox
\currentcolumnbox
\vtop
636
{
\beginofshapebox
637
\unvbox
\currentcolumnbox
638
\unskip
\unskip
639
\endofshapebox
640
\reshapebox
641
{
\scratchheight
\ht
\shapebox
642
\scratchdepth
\dp
\shapebox
643
\setbox
\shapebox
\hbox
to
\hsize
644
{
\postprocesscolumnline
\shapebox
}
%
645
\ht
\shapebox
\scratchheight
646
\dp
\shapebox
\scratchdepth
647
\box
\shapebox
}
%
648
\flushshapebox
649
\reseteverypar
650
\parskip
\zeropoint
% = \forgetall
651
\verticalstrut
652
\vskip
-
\struttotal
653
\vfil
}
}
654 655
\def
\page_mul_postprocess_columns_indeed
656
{
\dohandleallcolumnscs
\page_mul_postprocess_columns_step
}
657 658
\def
\page_mul_postprocess_columns_step
659
{
\global
\setbox
\currentcolumnbox
\hbox
660
{
\postprocesscolumnbox
\currentcolumnbox
}
}
661 662
\def
\page_mul_postprocess_page_indeed
663
{
\postprocesscolumnpagebox
\columnpagebox
}
664 665
%D Here comes the simple splitting routine. It's a bit longer than expected because
666
%D of ragging bottoms or not. This part can be a bit shorter but I suppose that I
667
%D will forget what happens. The splitting takes some already present material
668
%D (think of floats) into account!
669
%D
670
%D First we present some auxiliary routines. Any material, like for instance floats,
671
%D that is already present in the boxes is preserved.
672 673
\newdimen
\d_page_mul_split_height_used
674
\newdimen
\d_page_mul_split_height_max
675 676
\def
\page_mul_split_column
#
1
#
2
#
3
#
4
% copy or box
677
{
\bgroup
678
\ifdim
\ht
#
4
>
\zeropoint
679
\d_page_mul_split_height_used
#
3
\relax
680
\d_page_mul_split_height_max
\d_page_mul_split_height_used
681
\advance
\d_page_mul_split_height_used
-
\ht
#
4
%
682
\columnfootnotecorrection
{
#
1
}
\d_page_mul_split_height_used
683
\setbox
\scratchbox
\vsplit
#
2
to
\d_page_mul_split_height_used
684
\global
\setbox
#
1
\vbox
to
\d_page_mul_split_height_max
685
{
\ifgridsnapping
686
\scratchdimen
\dimexpr
\topskip
-
\openstrutheight
\relax
687
\vskip
\scratchdimen
688
\copy
#
4
%
689
\vskip
-
\scratchdimen
690
\else
691
\unvcopy
#
4
%
692
\fi
693
\unvbox
\scratchbox
694
\fakecolumnfootnotes
{
#
1
}
}
%
695
\else
\ifcase
\c_strc_notes_page_location
696
\global
\setbox
#
1
\vsplit
#
2
to
#
3
%
697
\global
\setbox
#
1
\vbox
698
{
\unvbox
{
#
1
}
}
% % or \box ?
699
\else
700
\columnfootnotecorrection
{
#
1
}
{
#
3
}
%
701
\setbox
\scratchbox
\vsplit
#
2
to
#
3
%
702
\global
\setbox
#
1
\vbox
to
#
3
%
703
{
\unvbox
\scratchbox
704
\fakecolumnfootnotes
{
#
1
}
}
%
705
\fi
\fi
706
\egroup
}
707 708
\def
\page_mul_split_current_column
#
1
#
2
%
709
{
\page_mul_split_column
\currentcolumnbox
{
#
1
}
{
#
2
}
\currenttopcolumnbox
}
710 711
\def
\page_mul_split_first_column
#
1
#
2
%
712
{
\page_mul_split_column
\firstcolumnbox
{
#
1
}
{
#
2
}
\firsttopcolumnbox
}
713 714
\def
\page_mul_split_last_column
#
1
#
2
%
715
{
\global
\setbox
\lastcolumnbox
\vbox
716
{
\unvcopy
\lasttopcolumnbox
717
\unvbox
{
#
1
}
%
718
\fakecolumnfootnotes
\lastcolumnbox
}
}
719 720
%D NEW: still to be documented.
721 722
\def
\fakecolumnfootnotes
#
1
%
723
{
\relax
724
\ifcase
\c_strc_notes_page_location
\else
725
\ifnum
#
1
=
\lastcolumnbox
726
\fakenotes
727
\fi
728
\fi
}
729 730
\def
\columnfootnotecorrection
#
1
#
2
%
731
{
\relax
732
\ifcase
\c_strc_notes_page_location
733
% page notes
734
\or
735
\ifnum
#
1
=
\firstcolumnbox
\relax
736
\calculatetotalclevernoteheight
737
\advance
#
2
-
\totalnoteheight
738
\fi
739
\else
740
\ifnum
#
1
=
\lastcolumnbox
\relax
741
\calculatetotalclevernoteheight
742
\advance
#
2
-
\totalnoteheight
743
\fi
744
\fi
}
745 746
\def
\overlaycolumnfootnotes
747
{
\relax
748
\ifcase
\c_strc_notes_page_location
749
% page
750
\or
751
\checknotepresence
\ifnotespresent
\page_mul_notes_flush_first_column
\fi
752
\or
753
\checknotepresence
\ifnotespresent
\page_mul_notes_flush_last_column
\fi
754
\fi
}
755 756
\newbox
\b_page_mul_notes
757 758
\def
\page_mul_notes_flush_first_column
759
{
\begingroup
760
\setbox
\b_page_mul_notes
\vbox
{
\placenoteinserts
}
%
761
\ifzeropt
\ht
\b_page_mul_notes
762
% can't happen as we already checked
763
\else
764
\page_mul_set_n_of_lines
765
\advance
\c_page_mul_n_of_lines
\minustwo
766
\scratchdimen
\dimexpr
\c_page_mul_n_of_lines
\lineheight
+
\topskip
\relax
767
\setbox
\b_page_mul_notes
\hpack
{
\lower
\scratchdimen
\box
\b_page_mul_notes
}
%
768
\ht
\b_page_mul_notes
\openstrutheight
769
\dp
\b_page_mul_notes
\openstrutdepth
770
\wd
\b_page_mul_notes
\zeropoint
771
\scratchdimen
\ht
\firstcolumnbox
772
\global
\setbox
\firstcolumnbox
\vbox
to
\scratchdimen
773
{
\box
\firstcolumnbox
774
\vskip
-
\scratchdimen
775
\box
\b_page_mul_notes
}
%
776
\fi
777
\endgroup
}
778 779
\def
\page_mul_notes_flush_last_column
780
{
\begingroup
781
\setbox
\b_page_mul_notes
\vbox
{
\placenoteinserts
}
%
782
\ifzeropt
\ht
\b_page_mul_notes
783
% can't happen as we already checked
784
\else
785
% maybe here also \page_mul_set_n_of_lines
786
\scratchdimen
\dimexpr
\ht
\firstcolumnbox
-
\openstrutdepth
\relax
% \strutdp
787
\getnoflines
\scratchdimen
788
\advance
\noflines
\minustwo
789
\scratchdimen
\dimexpr
\noflines
\lineheight
+
\topskip
\relax
790
\setbox
\b_page_mul_notes
\hpack
{
\lower
\scratchdimen
\box
\b_page_mul_notes
}
%
791
\ht
\b_page_mul_notes
\openstrutheight
792
\dp
\b_page_mul_notes
\openstrutdepth
793
\wd
\b_page_mul_notes
\zeropoint
794
\scratchdimen
\ht
\lastcolumnbox
795
\global
\setbox
\lastcolumnbox
\vbox
to
\scratchdimen
796
{
\box
\lastcolumnbox
797
\vskip
-
\scratchdimen
798
\box
\b_page_mul_notes
}
%
799
\fi
800
\endgroup
}
801 802
%D Here comes the routine that splits the long box in columns. The macro \type
803
%D {\page_mul_flush_floats} can be used to flush either floats that were present before
804
%D the multi||column mode was entered, or floats that migrate to next columns.
805
%D Flushing floats is a delicate process.
806 807
\def
\page_mul_routine_continue
808
{
\bgroup
809
\forgetall
810
\page_mul_initialize_variables
811
% \dimen0=\makeupheight
812
% \advance\dimen0 -\d_page_mul_preceding_height
813
% \settotalinsertionheight
814
% \advance\dimen0 -\totalinsertionheight
815
% \ifgridsnapping % evt altijd, nog testen
816
% \getnoflines{\dimen0}
817
% \dimen0=\noflines\openlineheight
818
% \fi
819
\page_mul_set_n_of_lines
820
\d_page_mul_balance_target
\c_page_mul_n_of_lines
\openlineheight
821
\ifconditional
\c_page_mul_trace
822
\writestatus
\m!columns
{
continue
:
lines
=
\the
\c_page_mul_n_of_lines
,
target
=
\the
\d_page_mul_balance_target
,
textheight
=
\the
\textheight
}
%
823
\fi
824
\dohandleallcolumns
825
{
\page_mul_split_current_column
\normalpagebox
\d_page_mul_balance_target
}
%
826
\setbox
\b_page_mul_preceding_rest_of_page
\vbox
{
\unvbox
\normalpagebox
}
%
827
\ifinheritcolumns
828
\ifcase
\bottomraggednessmode
829
% 0 = ragged
830
\dohandleallcolumns
831
{
\global
\setbox
\currentcolumnbox
\vbox
to
\ht
\firstcolumnbox
832
{
\scratchdepth
\dp
\currentcolumnbox
833
\unvbox
\currentcolumnbox
834
\vskip
\dimexpr
\openstrutdepth
-
\scratchdepth
\relax
835
\prevdepth
\openstrutdepth
% \strutdp
836
\vfill
}
}
%
837
\strc_notes_check_if_bottom_present
838
%\ifconditional\c_notes_bottom_present \else
839
% \dimen0\ht\firstcolumnbox % ??
840
%\fi
841
\or
842
% 1 = normal
843
\advance
\d_page_mul_balance_target
\maxdepth
844
\dohandleallcolumns
845
{
\global
\setbox
\currentcolumnbox
\vbox
to
\d_page_mul_balance_target
846
{
\unvbox
\currentcolumnbox
}
}
%
847
\or
848
% 2 = baseline
849
% the columns are on top of the baseline
850
\fi
851
\else
852
\dohandleallcolumns
853
{
\global
\setbox
\currentcolumnbox
\vbox
to
\d_page_mul_balance_target
854
{
\ifstretchcolumns
855
\unvbox
\currentcolumnbox
856
\else
857
\unvbox
\currentcolumnbox
% wel of niet \unvbox ?
858
\vfill
859
\fi
}
}
%
860
\dohandleallcolumns
861
{
\ht
\currentcolumnbox
\d_page_mul_balance_target
}
% redundant
862
\fi
863
\setbox
\b_page_mul_preceding
\vbox
{
\page_mul_flush_packaged_columns_continued
}
%
864
\page_otr_construct_and_shipout
\box
\b_page_mul_preceding
\zerocount
% three arguments
865
\page_otr_command_set_hsize
866
\page_otr_command_set_vsize
867
\page_mul_flush_floats
868
\unvbox
\b_page_mul_preceding_rest_of_page
869
% \penalty\outputpenalty % gaat gruwelijk mis in opsommingen
870
\egroup
}
871 872
%D And this is the balancing stuff. Again, part of the routine is dedicated to
873
%D handling ragged bottoms, but here we also see some handling concerning the
874
%D stretching of columns. We set \type {\widowpenalty} at~0, which enables us to
875
%D balance columns with few lines. The use of \type {\box2} and \type {\box4}
876
%D garantees a more robust check when skips are used.
877 878
\newbox
\b_page_mul_balance_content
879
\newbox
\b_page_mul_balance_first_column
880
\newbox
\b_page_mul_balance_column
881
\newconstant
\c_page_mul_balance_tries_max
882
\newcount
\c_page_mul_balance_tries
883
\newdimen
\d_page_mul_balance_target
884
\newdimen
\d_page_mul_balance_target_less
885
\newdimen
\d_page_mul_balance_natural_height
886
\newdimen
\d_page_mul_balance_regular_height
887
\newdimen
\d_page_mul_balance_step
888
\newdimen
\d_page_mul_balance_fuzzyness
889
\newdimen
\d_page_mul_balance_threshold
890
\newconditional
\c_page_mul_balance_possible
891 892
\c_page_mul_balance_tries_max
2
5
0
% 100 is too small when floats are involved
893 894
\def
\page_mul_routine_balance
895
{
\bgroup
896
% why no \forgetall here
897
\page_mul_initialize_variables
898
\widowpenalty
\zerocount
899
\setbox
\b_page_mul_balance_content
\vbox
{
\unvbox
\normalpagebox
}
%
900
\ifdim
\ht
\b_page_mul_balance_content
>
\openlineheight
% at least one line
901
\ifnum
\c_page_mul_balance_minimum
<
\plustwo
% balance anyway
902
\settrue
\c_page_mul_balance_possible
903
\else
% check criterium to available lines
904
\getnoflines
{
\ht
\b_page_mul_balance_content
}
%
905
\divide
\noflines
\nofcolumns
\relax
906
\ifnum
\noflines
<
\c_page_mul_balance_minimum
\relax
907
\ifdim
\dimexpr
\ht
\b_page_mul_balance_content
+
\ht
\firsttopcolumnbox
+
\openlineheight
\relax
>
\makeupheight
908
\settrue
\c_page_mul_balance_possible
% column exceeding text height
909
\else
910
\setfalse
\c_page_mul_balance_possible
% it seems to fit
911
\fi
912
\else
913
\settrue
\c_page_mul_balance_possible
% balance indeed
914
\fi
915
\fi
916
\else
917
\setfalse
\c_page_mul_balance_possible
% balancing does not make sense
918
\fi
919
\ifconditional
\c_page_mul_balance_possible
% start balancing, was: \ifdim\ht\b_page_mul_balance_content>\openlineheight
920
\page_mul_balance_try_one
921
\ifinheritcolumns
922
\page_mul_balance_try_two
923
\else
924
\page_mul_balance_try_three
925
\fi
926
\else
927
% a one liner is not properly handled here, so best rewrite the text then
928
\showmessage
\m!columns
{
1
0
}
\empty
929
\global
\setbox
\firstcolumnbox
\vbox
{
\unvbox
\b_page_mul_balance_content
}
%
930
\fi
931
\c_page_mul_routine
\c_page_mul_routine_error
932
\baselinebottom
% forces depth in separation rule
933
\page_mul_flush_packaged_columns_balanced
934
\page_mul_eject_page
935
\egroup
}
936 937
\def
\page_mul_eject_page
938
{
%\ifdim\pagetotal>\textheight
939
% \page_otr_trigger_output_routine % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point)
940
%\else
941
\allowbreak
942
}
%\fi}
943 944
\def
\page_mul_balance_try_one
945
{
\d_page_mul_balance_target
\dimexpr
\ht
\b_page_mul_balance_content
+
\topskip
-
\baselineskip
\relax
946
\dohandleallcolumns
947
{
\advance
\d_page_mul_balance_target
\ht
\currenttopcolumnbox
}
%
948
\divide
\d_page_mul_balance_target
\nofcolumns
949
\vbadness
\plustenthousand
950
\c_page_mul_balance_tries
\zerocount
951
\bgroup
952
\ifgridsnapping
953
\d_page_mul_balance_step
\lineheight
954
\else
955
\d_page_mul_balance_step
\spacingfactor
\onepoint
% rubish
956
\fi
957
\doloop
\page_mul_balance_try_one_attempt
958
\page_mul_balance_try_one_attempt_final
959
\ifnum
\c_page_mul_balance_tries
>
\c_page_mul_balance_tries_max
\relax
960
\showmessage
\m!columns
7
\empty
961
\else
962
\showmessage
\m!columns
8
{
\the
\c_page_mul_balance_tries
}
%
963
\fi
964
\egroup
}
965 966
\def
\page_mul_balance_try_one_attempt
967
{
\advance
\c_page_mul_balance_tries
\plusone
968
\global
\setbox
\b_page_mul_preceding_rest_of_page
\copy
\b_page_mul_balance_content
\relax
969
\page_mul_split_first_column
\b_page_mul_preceding_rest_of_page
\d_page_mul_balance_target
970
\dohandlemidcolumns
971
{
\page_mul_split_current_column
\b_page_mul_preceding_rest_of_page
\d_page_mul_balance_target
}
%
972
\page_mul_split_last_column
\b_page_mul_preceding_rest_of_page
\d_page_mul_balance_target
973
\setbox
\b_page_mul_balance_first_column
\vbox
{
\unvcopy
\firstcolumnbox
}
%
974
\d_page_mul_balance_natural_height
\zeropoint
975
\dohandleallcolumns
\page_mul_balance_try_one_attempt_step
976
\advance
\d_page_mul_balance_natural_height
-
.
0
0
0
5
pt
% (33sp) get rid of accurracy problem, pretty new
977
\ifnum
\c_page_mul_balance_tries
>
\c_page_mul_balance_tries_max
\relax
978
\exitloop
979
\else
\ifdim
\d_page_mul_balance_natural_height
>
\ht
\b_page_mul_balance_first_column
980
\advance
\d_page_mul_balance_target
\d_page_mul_balance_step
\relax
981
\else
982
\exitloop
983
\fi
\fi
}
984 985
% \def\page_mul_balance_try_one_attempt_final
986
% {\dohandleallcolumns
987
% {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}}
988
%
989
% \def\page_mul_balance_try_one_attempt_step
990
% {\setbox\b_page_mul_balance_column\vbox
991
% {\unvcopy\currentcolumnbox
992
% \unpenalty
993
% \unskip
994
% \unpenalty
995
% \unskip}% maybe better in main splitter
996
% \ifdim\ht\b_page_mul_balance_column>\d_page_mul_balance_natural_height
997
% \d_page_mul_balance_natural_height\ht\b_page_mul_balance_column
998
% \fi}
999
%
1000
% In mkiv we juggle node lists and we cannot work on copies that easily but in
1001
% practice context hardly uses copies except here. So, the next variant doesn't
1002
% use copies but the original in the final result, for which we need an extra
1003
% split pass. A simple test case is:
1004
%
1005
% \starttext
1006
% \startcolumns
1007
% \inleft{!} x \par x
1008
% \stopcolumns
1009
% \stoptext
1010 1011
\def
\page_mul_balance_try_one_attempt_final
% we need this because we want to have the non copied content
1012
{
\global
\setbox
\b_page_mul_preceding_rest_of_page
\box
\b_page_mul_balance_content
1013
\page_mul_split_first_column
\b_page_mul_preceding_rest_of_page
\d_page_mul_balance_target
1014
\dohandlemidcolumns
1015
{
\page_mul_split_current_column
\b_page_mul_preceding_rest_of_page
\d_page_mul_balance_target
}
%
1016
\page_mul_split_last_column
\b_page_mul_preceding_rest_of_page
\d_page_mul_balance_target
1017
\dohandleallcolumns
1018
{
\global
\setbox
\currentcolumnbox
\vbox
{
\unvbox
\currentcolumnbox
}
}
}
1019 1020
\def
\page_mul_balance_try_one_attempt_step
1021
{
\setbox
\b_page_mul_balance_column
\vbox
1022
{
\unvbox
\currentcolumnbox
% was copy but not needed with the above
1023
\unpenalty
1024
\unskip
1025
\unpenalty
1026
\unskip
}
% maybe better in main splitter
1027
\ifdim
\ht
\b_page_mul_balance_column
>
\d_page_mul_balance_natural_height
1028
\d_page_mul_balance_natural_height
\ht
\b_page_mul_balance_column
1029
\fi
}
1030 1031
% We cannot assume that the first column is the tallest, if only because we may
1032
% have an aborted balance (one line in the first column and a graphic in the
1033
% second one).
1034 1035
\def
\page_mul_balance_try_two
1036
{
\d_page_mul_balance_target
\zeropoint
1037
\dohandleallcolumns
1038
{
\ifdim
\ht
\currentcolumnbox
>
\d_page_mul_balance_target
1039
\d_page_mul_balance_target
\ht
\currentcolumnbox
1040
\fi
}
%
1041
\d_page_mul_balance_target_less
\dimexpr
\d_page_mul_balance_target
-
\openlineheight
\relax
1042
\dohandleallcolumnscs
\page_mul_balance_try_two_step
}
1043 1044
\def
\page_mul_balance_try_two_step
1045
{
\d_page_mul_balance_regular_height
\ht
\currentcolumnbox
1046
\d_page_mul_balance_threshold
\plusten
\openlineheight
% funny value
1047
\global
\setbox
\currentcolumnbox
\vbox
to
\d_page_mul_balance_target
1048
{
\unvbox
\currentcolumnbox
1049
\ifdim
\d_page_mul_balance_regular_height
>
\d_page_mul_balance_threshold
1050
\ifdim
\d_page_mul_balance_regular_height
<
\d_page_mul_balance_target
1051
\ifdim
\d_page_mul_balance_regular_height
>
\d_page_mul_balance_target_less
1052
\vskip
\zeropoint
% !!
1053
\else
1054
\vskip
\openlineheight
1055
\vfill
1056
\fi
1057
\else
1058
\vskip
\zeropoint
1059
\fi
1060
\else
1061
\vskip
\openlineheight
1062
\vfill
1063
\fi
}
}
1064 1065
\def
\page_mul_balance_try_three
1066
{
\bgroup
1067
\ifstretchcolumns
1068
\d_page_mul_balance_target
\ht
\firstcolumnbox
1069
\d_page_mul_balance_fuzzyness
\bottomtolerance
\ht
\firstcolumnbox
1070
\setbox
\b_page_mul_balance_content
\vbox
{
\unvcopy
\lastcolumnbox
}
%
1071
\advance
\d_page_mul_balance_target
-
\htdp
\b_page_mul_balance_content
\relax
1072
\ifdim
\d_page_mul_balance_target
>
\openlineheight
\relax
1073
\ifdim
\d_page_mul_balance_target
>
\d_page_mul_balance_fuzzyness
\relax
1074
% \stretchcolumnsfalse % beter good bad than bad good
1075
\showmessage
\m!columns
9
\empty
1076
\fi
1077
\fi
1078
\fi
1079
\dohandleallcolumnscs
\page_mul_balance_try_three_step
1080
\egroup
}
1081 1082
\def
\page_mul_balance_try_three_step
1083
{
\global
\setbox
\currentcolumnbox
\vbox
to
\ht
\firstcolumnbox
1084
{
\ifstretchcolumns
1085
\unvbox
\currentcolumnbox
1086
\else
1087
\box
\currentcolumnbox
1088
\vfill
1089
\fi
}
}
1090 1091
%D The multicolumn mechanism is incorporated in a \CONTEXT\ interface,
1092
%D which acts like:
1093
%D
1094
%D \starttyping
1095
%D \startcolumns[n=4,balance=no]
1096
%D some text
1097
%D \stopcolumns
1098
%D \stoptyping
1099
%D
1100
%D The setup is optional. The default behaviour of columns can be set
1101
%D up with:
1102
%D
1103
%D \starttyping
1104
%D \setupcolumns
1105
%D [n=2,
1106
%D balance=yes]
1107
%D \stoptyping
1108
%D
1109
%D In this case, stretching is according to the way it's done outside columns
1110
%D (\type{\inheritcolumnstrue}). Also we can setup the \type{tolerance} within a
1111
%D column, the \type{distance} between columns and the fixed \type{height} of a
1112
%D column.
1113
%D
1114
%D Here come the routines that handle the placement of column floats. Floats that
1115
%D are to big migrate to the next column. Floats that are too wide, migrate to the
1116
%D top of the next page, where they span as much columns as needed. Floats that are
1117
%D left over from outside the multi||column mode are flushed first. In macro
1118
%D \type{\page_otr_construct_and_shipout} the topfloats that are left from previous
1119
%D text should be set.
1120
%D
1121
%D When there are some floats in the queue, we inhibit the flushing of floats on top
1122
%D of columns. The number of waiting floats is preswent in \type{\savednoftopfloats}
1123
%D and is saved. As long as there are floats waiting, the topfloats are places as if
1124
%D we are outside multi||column mode. This is neccessary for e.g. multicolumn lists.
1125
%D
1126
%D When all those floats are flushed, we switch to the local flushing routine.
1127 1128
% \newbox \floatlist
1129
% \newbox \savedfloatlist
1130
%
1131
% \def\page_floats_column_push_saved
1132
% {\ifconditional\c_page_floats_some_waiting
1133
% \showmessage\m!columns6{\the\savednoffloats}%
1134
% \global\setbox\savedfloatlist\box\floatlist
1135
% \xdef\page_floats_column_pop_saved
1136
% {\global\savednoffloats\the\savednoffloats
1137
% \global\setbox\floatlist\box\savedfloatlist
1138
% \global\noexpand\settrue\c_page_floats_some_waiting}%
1139
% \global\savednoffloats\zerocount
1140
% \global\setfalse\c_page_floats_some_waiting
1141
% \else
1142
% \glet\page_floats_column_pop_saved\relax
1143
% \fi}
1144
%
1145
% \let\page_floats_column_pop_saved\relax
1146 1147
% \def\page_mul_initialize_floats % messy as it adapts everypar
1148
% {\xdef\globalsavednoffloats{\the\savednoffloats}%
1149
% \ifnum\globalsavednoffloats>\zerocount
1150
% \setglobalcolumnfloats % hm, we always push so this never happens
1151
% \else
1152
% \setlocalcolumnfloats
1153
% \fi}
1154 1155
\def
\page_mul_initialize_floats
% messy as it adapts everypar, we need to adapt this
1156
{
\setlocalcolumnfloats
}
1157 1158
\newconditional
\onlylocalcolumnfloats
% temp hack as we will redo floats (grid snapping is also messy now)
1159
\newtoks
\everylocalcolumnfloatspar
1160 1161
\unexpanded
\def
\page_mul_command_flush_floats
1162
{
\ifconditional
\onlylocalcolumnfloats
1163
\doflushcolumnfloats
1164
\else
1165
\page_one_command_flush_floats
1166
\fi
}
1167 1168
\unexpanded
\def
\page_mul_command_check_if_float_fits
1169
{
\ifconditional
\onlylocalcolumnfloats
1170
\docolumnroomfloat
1171
\fi
}
1172 1173
\unexpanded
\def
\page_mul_command_flush_saved_floats
1174
{
\ifconditional
\onlylocalcolumnfloats
\relax
1175
\else
1176
\page_one_command_flush_saved_floats
1177
\fi
}
1178 1179
\unexpanded
\def
\page_mul_command_flush_top_insertions
1180
{
\ifconditional
\onlylocalcolumnfloats
\relax
1181
\else
1182
\page_one_command_flush_top_insertions
1183
\fi
}
1184 1185
\appendtoks
1186
\flushnotes
1187
\page_mul_flush_float
1188
%\flushmargincontents
1189
\checkindentation
1190
\to
\everylocalcolumnfloatspar
1191 1192
\def
\setlocalcolumnfloats
1193
{
\settrue
\onlylocalcolumnfloats
1194
\everypar
\everylocalcolumnfloatspar
1195
\let
\page_mul_flush_float
\doflushcolumnfloat
1196
\let
\page_mul_flush_floats
\doflushcolumnfloats
}
1197 1198
\def
\setglobalcolumnfloats
1199
{
\setfalse
\onlylocalcolumnfloats
1200
\reseteverypar
1201
\let
\page_mul_flush_float
\relax
1202
\let
\page_mul_flush_floats
\noflushcolumnfloats
}
1203 1204
% \def\noflushcolumnfloats
1205
% {\bgroup
1206
% \xdef\localsavednoffloats{\the\savednoffloats}%
1207
% \global\savednoffloats\globalsavednoffloats
1208
% \page_otr_command_flush_top_insertions
1209
% \xdef\globalsavenoffloats{\the\savednoffloats}%
1210
% \ifnum\globalsavednoffloats=\zerocount
1211
% \setlocalcolumnfloats
1212
% \fi
1213
% \global\savednoffloats\localsavednoffloats
1214
% \egroup}
1215
%
1216
\def
\noflushcolumnfloats
{
\doflushcolumnfloats
}
% not yet redone
1217 1218
%D We need to calculate the amount of free space in a columns. When there is not
1219
%D enough room, we migrate the float to the next column. These macro's are
1220
%D alternatives (and look||alikes) of \type {\doroomfloat}. When a float is to wide,
1221
%D for one column, it is moved to the top of the next page. Of course such moved
1222
%D floats have to be taken into account when we calculate the available space. It's
1223
%D a pitty that such things are no integral part of \TEX.
1224 1225
\def
\getcolumnstatus
#
1
#
2
#
3
%
1226
{
\dimen
0
=
\ifdim
\pagegoal
<
\maxdimen
\pagetotal
\else
\zeropoint
\fi
1227
\dimen
2
=
\zeropoint
1228
\count
2
5
5
=
\zerocount
1229
\dimen
8
=
\makeupheight
1230
\advance
\dimen
8
-
\d_page_mul_preceding_height
1231
\def
\dogetcolumnstatus
1232
{
\advance
\count
2
5
5
\plusone
1233
\advance
\dimen
2
\ht
\currenttopcolumnbox
1234
\advance
\dimen
2
\dp
\currenttopcolumnbox
1235
\dimen
4
\dimen
2
1236
\advance
\dimen
4
\dimen
0
1237
\dimen
6
=
\count
2
5
5
\dimen
8
1238
\ifdim
\dimen
4
>
\dimen
6
1239
\else
1240
\let
\dogetcolumnstatus
\relax
1241
\fi
}
%
1242
\dohandleallcolumns
{
\dogetcolumnstatus
}
%
1243
\ifnum
\count
2
5
5
=
0
\count
2
5
5
=
1
\fi
1244
#
1
=
\count
2
5
5
1245
#
2
=
\dimen
4
1246
#
3
=
\dimen
6
}
1247 1248
\def
\getinsertionheight
1249
{
\ifdim
\pagegoal
<
\maxdimen
1250
\bgroup
1251
\dimen
0
=
\makeupheight
1252
\advance
\dimen
0
-
\pagegoal
1253
\xdef
\insertionheight
{
\the
\dimen
0
}
%
1254
\egroup
1255
\else
1256
\glet
\insertionheight
\zeropoint
1257
\fi
}
1258 1259
\def
\docolumnroomfloat
1260
{
\ifpostponecolumnfloats
1261
\global
\setfalse
\c_page_floats_room
1262
\else
\ifconditional
\c_page_floats_not_permitted
1263
\global
\setfalse
\c_page_floats_room
1264
\else
1265
\bgroup
1266
\getcolumnstatus
{
\count
2
5
5
}
{
\dimen
0
}
{
\dimen
2
}
%
1267
\page_floats_get_info
\s!text
1268
\setbox
\scratchbox
\vbox
% tricky met objecten ?
1269
{
\blank
[
\rootfloatparameter
\c!spacebefore
]
1270
\snaptogrid
\vbox
{
\vskip
\floatheight
}
}
% copy?
1271
\advance
\dimen
0
\dimexpr
\ht
\scratchbox
+
2
\openlineheight
+
.
5
\lineheight
\relax
\relax
% needed because goal a bit higher
1272
\ifdim
\dimen
0
>
\dimen
2
1273
\global
\setfalse
\c_page_floats_room
1274
\else
1275
\global
\settrue
\c_page_floats_room
1276
\fi
1277
\ifdim
\floatwidth
>
\hsize
1278
\showmessage
\m!columns
{
1
1
}
\empty
1279
\global
\setfalse
\c_page_floats_room
1280
\fi
1281
\egroup
1282
\fi
\fi
}
1283 1284
%D Flushing one float is done as soon as possible, i.e. \type {\everypar}.
1285
%D This means that (at the moment) sidefloats are not supported (overulled)!
1286 1287
\newif
\ifflushingcolumnfloats
\flushingcolumnfloatstrue
1288 1289
\def
\doflushcolumnfloat
1290
{
\ifpostponecolumnfloats
\else
\ifflushingcolumnfloats
\ifconditional
\c_page_floats_some_waiting
1291
\doflushcolumnfloatindeed
1292
\fi
\fi
\fi
}
1293 1294
\def
\doflushcolumnfloatindeed
1295
{
\bgroup
1296
\forgetall
1297
\let
\doflushcolumnfloat
\relax
1298
\getcolumnstatus
{
\mofcolumns
}
{
\dimen
0
}
{
\dimen
2
}
%
1299
\ifdim
\dimen
0
>
\zeropoint
1300
\page_floats_get_info
\s!text
1301
\ifdim
\floatwidth
>
\hsize
1302
% dropped ?
1303
\else
1304
\setbox
2
\vbox
1305
{
\blank
[
\rootfloatparameter
\c!spacebefore
]
1306
\snaptogrid
\vbox
{
\vskip
\floatheight
}
}
%
1307
\advance
\dimen
0
\ht
2
1308
\ifdim
\dimen
0
>
\dimen
2
1309
\ifnum
\mofcolumns
<
\nofcolumns
1310
\advance
\mofcolumns
\plusone
1311
\ifdim
\ht
\currenttopcolumnbox
=
\zeropoint
1312
\page_floats_flush
\s!text
\plusone
1313
\global
\setbox
\currenttopcolumnbox
\vbox
1314
{
\snaptogrid
\vbox
{
\box
\floatbox
}
1315
\whitespace
% nodig ?
1316
\blank
[
\rootfloatparameter
\c!spaceafter
]
}
%
1317
\dimen
4
=
\htdp
\currenttopcolumnbox
1318
\global
\advance
\vsize
-
\dimen
4
1319
\advance
\dimen
4
-
\pagegoal
1320
\pagegoal
-
\dimen
4
1321
\showmessage
\m!columns
{
1
2
}
a
%
1322
\else
1323
\showmessage
\m!columns
{
1
2
}
b
%
1324
\fi
1325
\else
1326
\showmessage
\m!columns
{
1
2
}
c
%
1327
\fi
1328
\else
1329
\ifhmode
{
\setbox
0
\lastbox
}
\fi
% waar is die er in geslopen
1330
\par
1331
\ifdim
\prevdepth
<
\zeropoint
\else
% anders bovenaan kolom witruimte
1332
\nobreak
1333
\blank
[
\rootfloatparameter
\c!spacebefore
]
1334
\nobreak
1335
\fi
1336
\page_floats_flush
\s!text
\plusone
1337
\page_otr_command_flush_float_box
1338
\blank
[
\rootfloatparameter
\c!spaceafter
]
1339
\fi
1340
\fi
1341
\fi
1342
\egroup
}
1343 1344
%D This one looks complicated. Upto \type{\nofcolumns} floats are placed,
1345
%D taking the width of a float into account. This routine can be improved
1346
%D on different ways:
1347
%D
1348
%D \startitemize[intro,packed]
1349
%D \item taking into account some imaginary baseline, just to get the
1350
%D captions in line
1351
%D \item multipass flushing until as many floats are displaced as possible
1352
%D \stopitemize
1353
%D
1354
%D When handling lots of (small) floats spacing can get worse because of
1355
%D lining out the columns.
1356 1357
\def
\doflushcolumnfloats
1358
{
\ifpostponecolumnfloats
\else
1359
\bgroup
1360
\forgetall
1361
\ifconditional
\c_page_floats_some_waiting
1362
\dimen
8
\zeropoint
1363
\dimen
4
\zeropoint
1364
\count
0
\zerocount
% count0 can be used local
1365
\count
2
\nofcolumns
% count2 can be used local
1366
\dohandleallcolumns
1367
{
\ifnum
\count
0
>
\zerocount
% the wide one's reserved space
1368
\global
\setbox
\currenttopcolumnbox
\vbox
1369
{
\snaptogrid
\vbox
1370
{
\copy
\currenttopcolumnbox
1371
\hpack
{
\vphantom
{
\vskip
\floatheight
}
}
}
% known from previous
1372
\whitespace
% nodig ?
1373
\blank
[
\rootfloatparameter
\c!spaceafter
]
}
%
1374
\else
1375
\page_floats_get_info
\s!text
1376
\ifdim
\floatwidth
>
\hsize
1377
\dimen
0
\dimexpr
\floatwidth
+
\d_page_mul_distance
+
.
5
pt
\relax
1378
\dimen
2
\dimexpr
\hsize
+
\d_page_mul_distance
+
.
5
pt
\relax
1379
\divide
\dimen
0
\dimen
2
1380
\count
0
\dimen
0
1381
\advance
\count
0
\plusone
1382
\ifnum
\count
0
>
\count
2
1383
\count
0
\zerocount
1384
\else
1385
\dimen
0
\dimexpr
\count
0
\hsize
+
\count
0
\d_page_mul_distance
-
\d_page_mul_distance
\relax
1386
\page_floats_flush
\s!text
\plusone
1387
\ifdim
\floatwidth
>
\makeupwidth
% better somewhere else too
1388
\global
\setbox
\floatbox
\hbox
to
\makeupwidth
{
\hss
\box
\floatbox
\hss
}
%
1389
\fi
% otherwise the graphic may disappear
1390
\global
\setbox
\floatbox
\hbox
to
\dimen
0
1391
{
\processaction
[
\rootfloatparameter
\c!location
]
% how easy to forget
1392
[
\v!left
=
>
\box
\floatbox
\hss
,
1393
\v!right
=
>
\hss
\box
\floatbox
,
1394
\s!default
=
>
\hss
\box
\floatbox
\hss
,
1395
\s!unknown
=
>
\hss
\box
\floatbox
\hss
]
}
%
1396
\fi
1397
\showmessage
\m!columns
{
1
3
}
\empty
1398
\else
1399
\page_floats_flush
\s!text
\plusone
1400
\ifdim
\floatwidth
>
\makeupwidth
% better somewhere else too
1401
\global
\setbox
\floatbox
\hbox
to
\makeupwidth
{
\hss
\box
\floatbox
\hss
}
%
1402
\fi
% otherwise the graphic may disappear
1403
% \showmessage\m!columns{13}\empty
1404
\fi
1405
\ifdim
\ht
\floatbox
>
\zeropoint
\relax
1406
\global
\setbox
\currenttopcolumnbox
\vbox
1407
{
\snaptogrid
\vbox
1408
{
\box
\currenttopcolumnbox
% was copy
1409
\box
\floatbox
}
1410
\whitespace
% nodig ?
1411
\blank
[
\rootfloatparameter
\c!spaceafter
]
}
%
1412
\fi
1413
\dimen
6
\htdp
\currenttopcolumnbox
1414
\fi
1415
\ifdim
\dimen
4
<
\ht
\currenttopcolumnbox
1416
\dimen
4
\ht
\currenttopcolumnbox
1417
\fi
1418
\advance
\dimen
8
\dimen
6
1419
\advance
\count
2
\minusone
1420
\advance
\count
0
\minusone
}
%
1421
\page_otr_command_set_vsize
1422
\global
\advance
\vsize
-
\dimen
8
1423
\pagegoal
\vsize
1424
\else
1425
% \page_mul_command_flush_floats % does not snap!
1426
\fi
1427
\egroup
1428
\fi
}
1429 1430
%D The next macro can be used to flush floats in the current stream. No
1431
%D width checking is (yet) done.
1432 1433
\def
\insertcolumnfloats
1434
{
\doloop
1435
{
\ifconditional
\c_page_floats_some_waiting
1436
\bgroup
1437
\forgetall
1438
% no check for width
1439
\page_floats_get
1440
\blank
[
\rootfloatparameter
\c!spacebefore
]
1441
\snaptogrid
\vbox
{
\copy
\floatbox
}
1442
\blank
[
\rootfloatparameter
\c!spaceafter
]
1443
\egroup
1444
\else
1445
\exitloop
1446
\fi
}
}
1447 1448
%D This were the multi||column routines. They can and need to be improved
1449
%D but at the moment their behaviour is acceptable.
1450
%D
1451
%D One inprovement can be to normalize the height of floats to $ n \times $
1452
%D \type {\lineheight} with a macro like:
1453
%D
1454
%D \starttyping
1455
%D \normalizevbox{...}
1456
%D \stoptyping
1457 1458
% border case, should fit on one page
1459
%
1460
% \startcolumns
1461
% 1 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{1}}
1462
% 2 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{2}}
1463
% 3 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{3}}
1464
% \stopcolumns
1465 1466
\def
\backgroundfinishcolumnbox
1467
{
\inheritedcolumnsframed
}
1468
% [\c!strut=\v!no,
1469
% \c!width=\v!fit,
1470
% \c!height=\v!fit,
1471
% \c!align=]}
1472 1473
% to be reconsidered ... (in any case they need to be unexpandable sinze 2011.12.30)
1474 1475
\unexpanded
\def
\page_columns_align_option_yes
{
\stretchcolumnstrue
\inheritcolumnsfalse
}
% todo: new key
1476
\unexpanded
\def
\page_columns_align_option_no
{
\stretchcolumnsfalse
\inheritcolumnsfalse
}
% todo: new key
1477
\unexpanded
\def
\page_columns_align_option_text
{
\stretchcolumnsfalse
\inheritcolumnstrue
}
%
1478 1479
\newtoks
\t_page_mul_initialize
1480 1481
\unexpanded
\def
\startcolumns
1482
{
\dosingleempty
\page_mul_start
}
1483 1484
\def
\page_mul_start
[
#
1
]
% %% \startcolumns
1485
{
\bgroup
1486
\ifinsidecolumns
1487
\page_mul_start_nop
1488
\else
1489
\iffirstargument
1490
\setupcolumns
[
#
1
]
%
1491
\fi
1492
\nofcolumns
\columnsparameter
\c!n
\relax
1493
\ifnum
\nofcolumns
>
\plusone
1494
\page_mul_start_yes
1495
\else
1496
\page_mul_start_nop
1497
\fi
1498
\fi
}
1499 1500
\unexpanded
\def
\page_mul_start_nop
1501
{
\let
\stopcolumns
\page_mul_stop_nop
}
1502 1503
\unexpanded
\def
\page_mul_stop_nop
1504
{
\egroup
}
1505 1506
\unexpanded
\def
\page_mul_start_yes
1507
{
\whitespace
1508
\begingroup
1509
\let
\stopcolumns
\page_mul_stop_indeed
1510
\global
\insidecolumnstrue
1511
\the
\t_page_mul_initialize
1512
%
1513
\flushnotes
1514
\begingroup
1515
%
1516
\d_page_mul_leftskip
\leftskip
1517
\d_page_mul_rightskip
\rightskip
1518
\leftskip
\zeropoint
1519
\rightskip
\zeropoint
1520
%
1521
\widowpenalty
\zerocount
% will become option
1522
\clubpenalty
\zerocount
% will become option
1523
%
1524
\page_floats_column_push_saved
1525
%
1526
\ifdim
\dimexpr
\pagetotal
+
\parskip
+
\openlineheight
\relax
<
\pagegoal
1527
\allowbreak
1528
\else
1529
\break
% sometimes fails
1530
\fi
1531
\appendtoks
1532
\topskip
1
\topskip
% best a switch
1533
\to
\everybodyfont
1534
\the
\everybodyfont
% ugly here
1535
\saveinterlinespace
% ugly here
1536
%
1537
\initializecolumns
\nofcolumns
1538
%
1539
\hangafter
\zerocount
1540
\hangindent
\zeropoint
1541
\reseteverypar
1542
\ifdim
\pagetotal
=
\zeropoint
\else
1543
\verticalstrut
1544
\vskip
-
\struttotal
1545
\fi
1546
\global
\savedpagetotal
\pagetotal
1547
\setupoutputroutine
[
\s!multicolumn
]
%
1548
\c_page_mul_routine
\c_page_mul_routine_intercept
1549
\page_otr_trigger_output_routine
% no \holdinginserts=1, can make footnote disappear !
1550
\global
\d_page_mul_preceding_height
\ht
\b_page_mul_preceding
1551
\c_page_mul_routine
\c_page_mul_routine_continue
1552
\page_mul_initialize_floats
1553
\dohandleallcolumns
{
\global
\setbox
\currenttopcolumnbox
\emptybox
}
%
1554
\checkbegincolumnfootnotes
1555
\page_otr_command_set_hsize
1556
\page_otr_command_set_vsize
}
1557 1558
\setnewconstant
\multicolumnendsyncmethod
\plusone
% 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
1559 1560
\unexpanded
\def
\page_mul_stop_indeed
1561
{
\relax
1562
\ifnum
\multicolumnendsyncmethod
=
\plustwo
1563
\synchronizeoutput
1564
\else
1565
% don't collapse these
1566
\vskip
\lineheight
1567
\vskip
-
\lineheight
% take footnotes into account
1568
\fi
1569
\doflushcolumnfloat
% added recently
1570
%\doflushcolumnfloats % no, since it results in wrong top floats
1571
\flushnotes
% before start of columns
1572
\par
1573
\ifbalancecolumns
1574
\ifnum
\multicolumnendsyncmethod
=
\plusone
1575
\c_page_mul_routine
\c_page_mul_routine_continue
1576
\goodbreak
1577
\fi
1578
\c_page_mul_routine
\c_page_mul_routine_balance
1579
\else
1580
\goodbreak
1581
\fi
1582
% still the multi column routine
1583
\page_otr_trigger_output_routine
% the prevdepth is important, try e.g. toclist in
1584
\prevdepth
\zeropoint
% columns before some noncolumned text text
1585
%
1586
\c_page_mul_routine
\c_page_mul_routine_regular
1587
%
1588
\ifvoid
\b_page_mul_preceding
\else
1589
\unvbox
\b_page_mul_preceding
1590
\fi
1591
\global
\d_page_mul_preceding_height
\zeropoint
1592
\endgroup
% here
1593
\nofcolumns
\plusone
1594
\page_otr_command_set_vsize
1595
\checkendcolumnfootnotes
1596
\dosomebreak
\allowbreak
1597
\page_floats_column_pop_saved
1598
%
1599
\global
\insidecolumnsfalse
1600
\endgroup
1601
\egroup
}
%
1602 1603
\appendtoks
1604
\edef
\p_option
{
\columnsparameter
\c!option
}
%
1605
\ifx
\p_option
\v!background
1606
\let
\finishcolumnbox
\backgroundfinishcolumnbox
1607
\doifelseinset
{
\columnsparameter
\c!offset
}
{
\v!none
,
\v!overlay
}
1608
{
\d_page_mul_offset
\zeropoint
}
%
1609
{
\d_page_mul_offset
\dimexpr
\columnsparameter
\c!offset
-
\columnsparameter
\c!rulethickness
\relax
}
%
1610
\else
1611
\d_page_mul_offset
\zeropoint
1612
\fi
1613
\edef
\p_command
{
\columnsparameter
\c!command
}
%
1614
\ifx
\p_command
\empty
\else
1615
\let
\postprocesscolumnline
\p_command
1616
\fi
1617
\edef
\p_height
{
\columnsparameter
\c!height
}
%
1618
\ifx
\p_height
\empty
1619
\d_page_mul_forced_height
\textheight
1620
\heightencolumnsfalse
1621
\else
1622
\d_page_mul_forced_height
\p_height
\relax
1623
\heightencolumnstrue
1624
\fi
1625
\edef
\p_direction
{
\columnsparameter
\c!direction
}
%
1626
\ifx
\p_direction
\v!right
1627
\setfalse
\c_page_mul_reverse
1628
\else
1629
\settrue
\c_page_mul_reverse
1630
\fi
1631
\edef
\p_balance
{
\columnsparameter
\c!balance
}
%
1632
\ifx
\p_balance
\v!yes
1633
\balancecolumnstrue
1634
\else
1635
\balancecolumnsfalse
1636
\fi
1637
% % this won't work (blocked by check for overloading; too fuzzy anyway)
1638
% \installalign\v!yes {\page_columns_align_option_yes }% \stretchcolumnstrue \inheritcolumnsfalse
1639
% \installalign\v!no {\page_columns_align_option_no }% \stretchcolumnsfalse\inheritcolumnsfalse
1640
% \installalign\v!text{\page_columns_align_option_text}% \stretchcolumnsfalse\inheritcolumnstrue
1641
% %
1642
\stretchcolumnsfalse
1643
\inheritcolumnstrue
1644
\edef
\p_align
{
\columnsparameter
\c!align
}
%
1645
\ifx
\p_align
\empty
\else
1646
\setupalign
[
\p_align
]
%
1647
\fi
1648
\edef
\p_tolerance
{
\columnsparameter
\c!tolerance
}
%
1649
\ifx
\p_tolerance
\empty
\else
1650
\setuptolerance
[
\p_tolerance
]
%
1651
\fi
1652
\edef
\p_blank
{
\columnsparameter
\c!blank
}
%
1653
\ifx
\p_blank
\empty
\else
1654
\setupblank
[
\p_blank
]
%
1655
\fi
1656
\ifdim
\s_spac_whitespace_parskip
>
\zeropoint
\relax
1657
\setupwhitespace
[
\p_blank
]
%
1658
\fi
1659
\c_page_mul_balance_minimum
\columnsparameter
\c!ntop
\relax
1660
\edef
\p_page_mul_rule
{
\columnsparameter
\c!rule
}
%
1661
\expandnamespacemacro
\??columnseparators
\p_page_mul_rule
\s!unknown
1662
\to
\t_page_mul_initialize
1663 1664
%D Columns breaks
1665 1666
\installcolumnbreakmethod
\s!multicolumn
\v!preference
1667
{
\goodbreak
}
1668 1669
% \installcolumnbreakmethod \s!multicolumn \v!yes
1670
% {\vskip\textheight
1671
% \penalty-200 % we can mark and intercept this
1672
% \vskip-\textheight}
1673 1674
\installcolumnbreakmethod
\s!multicolumn
\v!yes
1675
{
\vskip
.
5
\pagegoal
1676
\penalty
-
2
0
0
% we can mark and intercept this
1677
\vskip
-
.
5
\pagegoal
}
1678 1679
%D Next we initialize the lot:
1680 1681
\setupcolumns
1682
[
\c!n
=
2
,
1683
\c!ntop
=
1
,
1684
\c!command
=
,
1685
\c!direction
=
\v!right
,
1686
\c!rule
=
\v!off
,
1687
\c!tolerance
=
\v!tolerant
,
1688
\c!distance
=
1
.
5
\bodyfontsize
,
% influenced by switching
1689
\c!height
=
,
1690
\c!balance
=
\v!yes
,
1691
\c!align
=
\v!text
,
1692
\c!blank
=
{
\v!line
,
\v!fixed
}
,
1693
\c!option
=
,
1694
\c!rulethickness
=
\linewidth
,
1695
\c!offset
=
.
5
\bodyfontsize
]
1696 1697
%D New: only at start of columns; may change ! Rather interwoven and therefore
1698
%D to be integrated when the multi column modules are merged.
1699 1700
\unexpanded
\def
\setupcolumnspan
[
#
1
]
%
1701
{
\getparameters
[
\??ks
]
[
#
1
]
}
1702 1703
\presetlocalframed
1704
[
\??ks
]
1705 1706
\setupcolumnspan
1707
[
\c!n
=
2
,
1708
\c!offset
=
\v!overlay
,
1709
\c!frame
=
\v!off
]
1710 1711
\newbox
\b_page_columns_span
\let
\page_mul_postprocess_spanbox
\gobbleoneargument
1712 1713
\unexpanded
\def
\startcolumnspan
1714
{
\dosingleempty
\dostartcolumnspan
}
1715 1716
\unexpanded
\def
\stopcolumnspan
1717
{
\egroup
}
1718 1719
\def
\dostartcolumnspan
[
#
1
]
%
1720
{
\bgroup
1721
\setupcolumnspan
[
#
1
]
%
1722
\forgetall
1723
\ifinsidecolumns
1724
\advance
\hsize
\d_page_mul_distance
1725
\hsize
\@@ksn
\hsize
1726
\advance
\hsize
-
\d_page_mul_distance
1727
\fi
1728
\dowithnextboxcs
\dofinishcolumnsetspan
\vbox
\bgroup
1729
%\topskipcorrection % becomes an option !
1730
\EveryPar
{
\begstrut
\EveryPar
{
}
}
}
% also !
1731 1732
\def
\dofinishcolumnsetspan
1733
{
\setbox
\b_page_columns_span
\flushnextbox
1734
\ifinsidecolumns
\wd
\b_page_columns_span
\hsize
\fi
1735
\page_mul_postprocess_spanbox
\b_page_columns_span
1736
\scratchdimen
\ht
\b_page_columns_span
1737
\setbox
\b_page_columns_span
\hbox
% depth to be checked, probably option!
1738
{
\localframed
[
\??ks
]
[
\c!offset
=
\v!overlay
]
{
\box
\b_page_columns_span
}
}
%
1739
\ht
\b_page_columns_span
\scratchdimen
1740
\dp
\b_page_columns_span
\strutdp
1741
\wd
\b_page_columns_span
\hsize
1742
\ifinsidecolumns
1743
\ifnum
\@@ksn
>
1
1744
\page_otr_command_set_vsize
1745
\dohandleallcolumns
1746
{
\ifnum
\currentcolumn
>
\@@ksn
\else
1747
\global
\setbox
\currenttopcolumnbox
=
\vbox
1748
{
\ifnum
\currentcolumn
=
1
1749
\snaptogrid
\vbox
{
\copy
\b_page_columns_span
}
1750
\else
1751
\snaptogrid
\vbox
{
\vphantom
{
\copy
\b_page_columns_span
}
}
1752
\fi
}
%
1753
\wd
\currenttopcolumnbox
\hsize
1754
\global
\advance
\vsize
-
\ht
\currenttopcolumnbox
1755
\fi
}
1756
\pagegoal
\vsize
1757
\else
1758
\snaptogrid
\vbox
{
\box
\b_page_columns_span
}
1759
\fi
1760
\else
1761
\snaptogrid
\vbox
{
\box
\b_page_columns_span
}
1762
\fi
1763
\endgraf
1764
\ifvmode
\prevdepth
\strutdp
\fi
1765
\egroup
}
1766 1767
%D Undocumented and still under development.\ifdefined\startsimplecolumns \else
1768 1769
\unexpanded
\def
\startsimplecolumns
1770
{
\dosingleempty
\page_mul_simple_start
}
1771 1772
\def
\page_mul_simple_start
[
#
1
]
%
1773
{
\bgroup
1774
\setsimplecolumnshsize
[
#
1
]
%
1775
\nopenalties
1776
\setbox
\scratchbox
\vbox
\bgroup
1777
\forgetall
}
% \blank[\v!disable]
1778 1779
\unexpanded
\def
\stopsimplecolumns
1780
{
\removebottomthings
1781
\egroup
1782
\rigidcolumnbalance
\scratchbox
1783
\egroup
}
1784 1785
\unexpanded
\def
\setsimplecolumnshsize
[
#
1
]
%
1786
{
\getdummyparameters
1787
[
\c!width
=
\hsize
,
1788
\c!distance
=
1
.
5
\bodyfontsize
,
1789
\c!n
=
2
,
1790
\c!lines
=
0
,
1791
#
1
]
%
1792
\edef
\rigidcolumnlines
1793
{
\directdummyparameter
\c!lines
}
%
1794
\setrigidcolumnhsize
1795
{
\directdummyparameter
\c!width
}
%
1796
{
\directdummyparameter
\c!distance
}
%
1797
{
\directdummyparameter
\c!n
}
}
1798 1799
%D Moved here:
1800 1801
\unexpanded
\def
\page_mul_command_test_column
1802
{
\dodoubleempty
\page_mul_command_test_column_indeed
}
1803 1804
\unexpanded
\def
\page_mul_command_test_column_indeed
[
#
1
]
[
#
2
]
% works on last column
1805
{
\page_otr_command_flush_top_insertions
\endgraf
1806
\ifdim
\pagegoal
<
\maxdimen
1807
\ifdim
\pagetotal
<
\pagegoal
1808
\d_page_tests_test
\dimexpr
1809
\pagegoal
1810
-
\pagetotal
1811
\ifdim
\lastskip
<
\parskip
+
\parskip
\fi
1812
\ifsecondargument
+
#
2
\fi
1813
\relax
1814
\getrawnoflines
\d_page_tests_test
% (raw)
1815
\ifnum
#
1
>
\noflines
1816
\column
1817
\fi
1818
\else
1819
\penalty
-
\plustenthousand
% (untested)
1820
\fi
1821
\fi
}
1822 1823
%D but fragile anyway.
1824 1825
\let
\page_mul_command_package_contents
\page_one_command_package_contents
1826
\let
\page_mul_command_flush_float_box
\page_one_command_flush_float_box
1827
\let
\page_mul_command_flush_all_floats
\page_one_command_flush_all_floats
1828 1829
\defineoutputroutine
1830
[
\s!multicolumn
]
1831
[
\s!page_otr_command_routine
=
\page_mul_command_routine
,
1832
\s!page_otr_command_package_contents
=
\page_mul_command_package_contents
,
1833
\s!page_otr_command_set_vsize
=
\page_mul_command_set_vsize
,
1834
\s!page_otr_command_set_hsize
=
\page_mul_command_set_hsize
,
1835
% \s!page_otr_command_synchronize_hsize =\page_mul_command_synchronize_hsize,
1836
\s!page_otr_command_next_page
=
\page_mul_command_next_page
,
1837
\s!page_otr_command_next_page_and_inserts
=
\page_mul_command_next_page_and_inserts
,
1838
% \s!page_otr_command_set_top_insertions =\page_mul_command_set_top_insertions,
1839
% \s!page_otr_command_set_bottom_insertions =\page_mul_command_set_bottom_insertions,
1840
\s!page_otr_command_flush_top_insertions
=
\page_mul_command_flush_top_insertions
,
1841
% \s!page_otr_command_flush_bottom_insertions=\page_mul_command_flush_bottom_insertions,
1842
\s!page_otr_command_check_if_float_fits
=
\page_mul_command_check_if_float_fits
,
1843
% \s!page_otr_command_set_float_hsize =\page_mul_command_set_float_hsize,
1844
\s!page_otr_command_flush_float_box
=
\page_mul_command_flush_float_box
,
1845
\s!page_otr_command_side_float_output
=
\page_mul_command_side_float_output
,
1846
\s!page_otr_command_synchronize_side_floats
=
\page_mul_command_synchronize_side_floats
,
1847
\s!page_otr_command_flush_floats
=
\page_mul_command_flush_floats
,
1848
\s!page_otr_command_flush_side_floats
=
\page_mul_command_flush_side_floats
,
1849
\s!page_otr_command_flush_saved_floats
=
\page_mul_command_flush_saved_floats
,
1850
\s!page_otr_command_flush_all_floats
=
\page_mul_command_flush_all_floats
,
1851
% \s!page_otr_command_flush_margin_blocks =\page_mul_command_flush_margin_blocks, % not used
1852
\s!page_otr_command_test_column
=
\page_mul_command_test_column
1853
]
1854 1855
\installfloatmethod
\s!multicolumn
\v!here
\page_mul_place_float_here
1856
\installfloatmethod
\s!multicolumn
\v!force
\page_mul_place_float_force
1857
\installfloatmethod
\s!multicolumn
\v!top
\page_mul_place_float_top
1858
\installfloatmethod
\s!multicolumn
\v!bottom
\page_mul_place_float_bottom
1859 1860
\appendtoks
1861
\flushingcolumnfloatsfalse
1862
\to
\everybeforesectionheadhandle
1863 1864
\appendtoks
1865
\flushingcolumnfloatstrue
1866
\to
\everyaftersectionheadhandle
1867 1868
\protect
\endinput
1869