page-sid.mkiv /size: 33 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=page-sid,
3%D        version=2000.10.20,
4%D          title=\CONTEXT\ Page Macros,
5%D       subtitle=Side Floats,
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\writestatus{loading}{ConTeXt Page Macros / Side Floats}
15
16\unprotect
17
18%D These macro deal with side floats. We started with Daniel Comenetz macros as
19%D published in TUGBoat Volume 14 (1993), No.\ 1: Anchored Figures at Either Margin.
20%D I extended and patched the macros to suite our needs which results in a messy
21%D module.
22%D
23%D A complication is that we need to deal with spacing differently before and after
24%D the float. Also, whitespace can interfere as does the prevdepth. There is no real
25%D universal solution. So, by now not much is left of that code, if only because we
26%D need to match \CONTEXT\ spacing module, because we have more placement options
27%D and control and because the math hackery is not suitable for \CONTEXT\ anyway.
28%D
29%D This code had been redone many times because we kept running into spacing issues
30%D and it's not that much fun (or rewarding). It's probably the module that made
31%D me go into distraciton mode most often (like watching amusing Walk of The
32%D Earth, sophisticated Massive Attack video clips, impressive Davie504 movies
33%D and so on).
34
35\newdimen       \d_page_sides_margin
36\newdimen       \d_page_sides_height       % includes the topskip
37\newdimen       \d_page_sides_width
38\newdimen       \d_page_sides_hsize
39\newdimen       \d_page_sides_vsize
40\newdimen       \d_page_sides_vsize_reset
41\newdimen       \d_page_sides_progress
42\newdimen       \d_page_sides_page_total
43
44\newdimen       \d_page_sides_leftoffset
45\newdimen       \d_page_sides_rightoffset
46
47%newbox         \b_page_sides_bottom
48
49\newcount       \c_page_sides_lines_done
50\newcount       \c_page_sides_checks_done
51\newcount       \c_page_sides_n_of_lines
52\newcount       \c_page_sides_n_of_hang
53\newconstant    \c_page_sides_float_type
54\newcount       \c_page_sides_hangafter
55
56\newconditional \c_page_sides_short
57\newconditional \c_page_sides_flag
58
59\newdimen       \d_page_sides_shift
60\newdimen       \d_page_sides_extrashift
61\newdimen       \d_page_sides_leftshift
62\newdimen       \d_page_sides_rightshift
63\newdimen       \d_page_sides_leftskip
64\newdimen       \d_page_sides_rightskip
65\newdimen       \d_page_sides_maximum
66\newdimen       \d_page_sides_topskip
67\newdimen       \d_page_sides_bottomskip
68\newdimen       \d_page_sides_midskip
69\newdimen       \d_page_sides_downshift
70\newdimen       \d_page_sides_pagetotal
71\newdimen       \d_page_sides_topoffset
72\newdimen       \d_page_sides_bottomoffset
73\newdimen       \d_page_sides_toptotal
74\newdimen       \d_page_sides_bottomtotal
75
76\newconstant    \c_page_sides_align
77\newconstant    \c_page_sides_skipmode
78\newconstant    \c_page_sides_tolerance
79
80\newconstant    \c_page_sides_method % sort of obsolete
81
82\newdimen       \d_page_sides_progression
83
84\newcount       \c_page_sides_m_of_lines
85\newconditional \c_page_sides_delayed
86
87\newconditional \c_page_sides_check_same_page
88
89\newif          \iftracesidefloats % public (might change)
90
91%D Defaults:
92
93\d_page_sides_vsize_reset -\onepoint
94%d_page_sides_vsize_reset  \zeropoint % could be an option, needs testing
95
96%D We have some basic (and colorful) tracing:
97
98\def\page_sides_floats_legend
99  {\showmessage\m!floatblocks{16}\empty
100   \glet\page_sides_floats_legend\relax}
101
102\installtextracker{floats.anchoring}
103  {\page_sides_floats_legend
104   \tracesidefloatstrue}
105  {\tracesidefloatsfalse}
106
107%D The horizontal shifts depend on the location: left or right in the text, margin
108%D or edge. These shifts are rather stable and don't interfere with the page flow
109%D as much as the vertical ones do.
110
111\def\page_sides_process_float_backspace  {\global\c_page_sides_float_type\plusone  \page_sides_handle_float}
112\def\page_sides_process_float_leftedge   {\global\c_page_sides_float_type\plustwo  \page_sides_handle_float}
113\def\page_sides_process_float_leftmargin {\global\c_page_sides_float_type\plusthree\page_sides_handle_float}
114\def\page_sides_process_float_left       {\global\c_page_sides_float_type\plusfour \page_sides_handle_float}
115\def\page_sides_process_float_right      {\global\c_page_sides_float_type\plusfive \page_sides_handle_float}
116\def\page_sides_process_float_rightmargin{\global\c_page_sides_float_type\plussix  \page_sides_handle_float}
117\def\page_sides_process_float_rightedge  {\global\c_page_sides_float_type\plusseven\page_sides_handle_float}
118\def\page_sides_process_float_cutspace   {\global\c_page_sides_float_type\pluseight\page_sides_handle_float}
119\def\page_sides_process_float_margin     {\global\c_page_sides_float_type\pluseight\page_sides_handle_float}
120
121\def\page_sides_check_horizontal_skips
122  {\ifcase\c_page_sides_skipmode
123   \or % high
124   \or % low
125   \or % fit
126     \global\d_page_sides_margin\zeropoint
127   \fi}
128
129\def\page_sides_apply_horizontal_shift
130  {\ifdim\d_page_sides_maximum>\zeropoint
131     \ifcase\c_page_sides_float_type
132       % invalid
133     \or
134       % backspace
135     \or
136       \global\d_page_sides_shift\dimexpr
137         -\d_page_sides_maximum
138         -\rightorleftpageaction \leftedgedistance   \rightedgedistance
139         -\rightorleftpageaction \leftmarginwidth    \rightmarginwidth
140         -\rightorleftpageaction \leftmargindistance \rightmargindistance
141         -\compensatedinnermakeupmargin
142       \relax
143     \or
144       \global\d_page_sides_shift\dimexpr
145         -\d_page_sides_maximum
146         -\rightorleftpageaction \leftmargindistance \rightmargindistance
147         -\compensatedinnermakeupmargin
148       \relax
149     \or
150       % left
151     \or
152       % right
153     \or
154       \global\d_page_sides_shift\dimexpr
155         -\d_page_sides_maximum
156         -\rightorleftpageaction \leftmargindistance \rightmargindistance
157         -\compensatedinnermakeupmargin
158       \relax
159     \or
160       \global\d_page_sides_shift\dimexpr
161         -\d_page_sides_maximum
162         -\rightorleftpageaction \leftedgedistance   \rightedgedistance
163         -\rightorleftpageaction \leftmarginwidth    \rightmarginwidth
164         -\rightorleftpageaction \leftmargindistance \rightmargindistance
165         -\compensatedinnermakeupmargin
166       \relax
167     \or
168       % cutspace
169     \fi
170   \fi
171   \ifdim\d_page_sides_shift=\zeropoint \relax
172     \ifnum\c_page_sides_float_type=\plusfour
173       \global\advance\d_page_sides_shift\d_page_sides_extrashift
174       \global\d_page_sides_extrashift\zeropoint
175     \else\ifnum\c_page_sides_float_type=\plusfive
176       \global\advance\d_page_sides_shift\d_page_sides_extrashift
177       \global\d_page_sides_extrashift\zeropoint
178     \fi\fi
179   \else
180     \ifnum\c_page_sides_float_type<\plusfour
181       \global\c_page_sides_float_type\plusfour
182     \else\ifnum\c_page_sides_float_type>\plusfive
183       \global\c_page_sides_float_type\plusfive
184     \fi\fi
185   \fi}
186
187\def\page_sides_set_skips
188  {\global\d_page_sides_rightskip\zeropoint
189   \global\d_page_sides_leftskip \zeropoint
190   \ifcase\c_page_sides_float_type
191   \or % backspace
192     \global\d_page_sides_leftskip\dimexpr
193       +\rightorleftpageaction \backspace           \cutspace
194       +\compensatedinnermakeupmargin
195     \relax
196   \or % leftedge
197     \global\d_page_sides_leftskip\dimexpr
198       +\rightorleftpageaction \leftmargindistance  \rightmargindistance
199       +\rightorleftpageaction \leftmarginwidth     \rightmarginwidth
200       +\rightorleftpageaction \leftedgedistance    \rightedgedistance
201       +\compensatedinnermakeupmargin
202     \relax
203   \or % leftmargin
204     \global\d_page_sides_leftskip\dimexpr
205       +\rightorleftpageaction \leftmargindistance  \rightmargindistance
206       +\compensatedinnermakeupmargin
207     \relax
208   \or % leftside
209   \or % rightside
210   \or % rightmargin
211     \global\d_page_sides_rightskip\dimexpr
212       +\rightorleftpageaction \rightmargindistance \leftmargindistance
213       +\compensatedinnermakeupmargin
214     \relax
215   \or % rightedge
216     \global\d_page_sides_rightskip\dimexpr
217       +\rightorleftpageaction \rightmargindistance \leftmargindistance
218       +\rightorleftpageaction \rightmarginwidth    \leftmarginwidth
219       +\rightorleftpageaction \rightedgedistance   \leftedgedistance
220       +\compensatedinnermakeupmargin
221     \relax
222   \or % cutspace
223     \global\d_page_sides_rightskip\dimexpr
224       +\rightorleftpageaction \cutspace            \backspace
225       +\compensatedinnermakeupmargin
226     \relax
227   \fi
228   \global\d_page_sides_leftoffset \d_page_sides_rightskip
229   \global\d_page_sides_rightoffset\d_page_sides_leftskip
230   \ifdim\d_page_sides_rightskip>\zeropoint
231     \global\advance\d_page_sides_rightskip\rightskip
232   \fi
233   \ifdim\d_page_sides_leftskip >\zeropoint
234     \global\advance\d_page_sides_leftskip \leftskip
235   \fi}
236
237%D Shifts get applied to the float box:
238
239\def\page_sides_relocate_float#1%
240  {\global\setbox\floatbox\hpack
241     {\ifnum\c_page_sides_float_type=\plusfour
242        \kern\d_page_sides_leftshift
243      \else\ifnum\c_page_sides_float_type=\plusone
244        \kern\d_page_sides_leftshift
245      \fi\fi
246      \ifnum\c_page_sides_float_type>\plusfour
247        \kern-\d_page_sides_extrashift
248      \else
249        \kern\d_page_sides_shift
250      \fi
251      \vbox{#1\ifnum\c_page_sides_align=\plusfour \removedepth \fi}%
252      \ifnum\c_page_sides_float_type>\plusfour
253        \kern\d_page_sides_shift
254      \else
255        \kern-\d_page_sides_extrashift
256      \fi
257      \ifnum\c_page_sides_float_type=\pluseight
258        \kern\d_page_sides_rightshift
259      \else\ifnum\c_page_sides_float_type=\plusfive
260        \kern\d_page_sides_rightshift
261      \fi\fi}}
262
263%D The vertical skips are a nightmare and this mechanism is about as complex
264%D as one can get it.
265
266\def\page_sides_check_vertical_skips
267  {\ifdim\d_page_sides_topskip   <\zeropoint\d_page_sides_topskip   \zeropoint\fi
268   \ifdim\d_page_sides_bottomskip<\zeropoint\d_page_sides_bottomskip\zeropoint\fi
269   \ifdim\d_page_sides_midskip   <\zeropoint\d_page_sides_midskip   \zeropoint\fi
270   %
271   \global\d_page_sides_toptotal   \dimexpr\d_page_sides_topskip   +\d_page_sides_topoffset   \relax
272   \global\d_page_sides_bottomtotal\dimexpr\d_page_sides_bottomskip+\d_page_sides_bottomoffset\relax
273   \ifcase\c_page_sides_skipmode
274   \or % high
275     \global\d_page_sides_toptotal   \d_page_sides_topoffset
276   \or % low
277     \global\d_page_sides_bottomtotal\d_page_sides_bottomoffset
278   \or % fit
279     \global\d_page_sides_toptotal   \d_page_sides_topoffset
280     \global\d_page_sides_bottomtotal\d_page_sides_bottomoffset
281   \fi}
282
283%D These shifts get (selectively) applied with a bit of optional tracing.
284
285\def\page_sides_apply_vertical_shift_normal
286  {\global\setbox\floatbox\hpack % why extra box
287     {\vpack
288        {\forgetall
289         \hsize\wd\floatbox
290         \vskip\privatescratchdimen
291         \offinterlineskip
292         \box\floatbox
293         % somehow we need this \scratchbox magic, but at least it's the same as the
294         % tracer now
295         \setbox\scratchbox\emptyhbox
296         \wd\scratchbox\hsize
297         \ht\scratchbox\d_page_sides_bottomtotal
298         \box\scratchbox
299         \vskip-\d_page_sides_bottomtotal
300         \ifnum\c_page_sides_align=\plusfive
301           \vskip-\lineheight
302         \fi}}}
303
304\def\page_sides_apply_vertical_shift_traced
305  {\global\setbox\floatbox\hpack % why extra box
306     {\backgroundline[trace:r]{\ruledhpack{\vpack
307        {\forgetall
308         \hsize\wd\floatbox
309         \vskip\privatescratchdimen
310         \offinterlineskip
311         \backgroundline
312           [trace:g]%
313           {\ruledhpack{\box\floatbox}}%
314         \par
315         \blackrule
316           [\c!color=trace:s,%
317            \c!height=\d_page_sides_bottomtotal,%
318            \c!depth=\zeropoint,%
319            \c!width=\hsize]%
320         \vskip-\d_page_sides_bottomtotal
321         \ifnum\c_page_sides_align=\plusfive
322           \vskip-\lineheight
323         \fi}}}}}
324
325\def\page_sides_apply_vertical_shift
326  {\ifnum\c_page_sides_align=\plusfour
327     \getnoflines{\ht\floatbox}%
328     \privatescratchdimen\dimexpr\noflines\lineheight-\strutdp\relax
329     \getrawnoflines\d_page_sides_toptotal
330     \advance\privatescratchdimen\noflines\lineheight
331     \page_sides_force_depth
332     \ht\floatbox\privatescratchdimen
333     \dp\floatbox\zeropoint
334   \fi
335   \ifcase\c_page_sides_align \else
336     \global\d_page_sides_toptotal\zeropoint
337   \fi
338   \privatescratchdimen
339     \ifnum\c_page_sides_float_type<\plusfour
340       \d_page_sides_toptotal
341     \else\ifnum\c_page_sides_float_type>\plusfive
342       \d_page_sides_toptotal
343     \else
344       \zeropoint
345     \fi\fi
346   % the top of the box is at the previous baseline
347   \ifcase\c_page_sides_align
348       % 0 normal
349     \advance\privatescratchdimen\strutdp % or \openstrutdepth
350   \or % 1 height
351     \advance\privatescratchdimen\strutdp % or \openstrutdepth
352   \or % 2 line
353   \or % 3 depth
354     \advance\privatescratchdimen\lineheight % or \openlineheight
355     \advance\privatescratchdimen\strutdp    % or \openstrutdepth
356   \or % 4 grid
357     \privatescratchdimen\zeropoint
358   \or
359     \advance\privatescratchdimen\strutht % or \openstrutheight
360   \fi
361   % new
362   \global\c_page_sides_lines_done\zerocount
363   \ifnum\c_page_sides_n_of_lines>\zerocount
364     \advance\privatescratchdimen\c_page_sides_n_of_lines\lineheight
365   \fi
366   \iftracesidefloats
367     \page_sides_apply_vertical_shift_traced % uses \privatescratchdimen
368   \else
369     \page_sides_apply_vertical_shift_normal % uses \privatescratchdimen
370   \fi
371   \ifnum\c_page_sides_float_type<\plusfour
372     \global\d_page_sides_toptotal\zeropoint
373   \else\ifnum\c_page_sides_float_type>\plusfive
374     \global\d_page_sides_toptotal\zeropoint
375   \fi\fi
376   \global\d_page_sides_downshift\zeropoint}
377
378%D We have a few virtual dimensions. I'm not sure what to do with \type
379%D {\pagedepth} and \type {\pageshrink} in the next two. If we ever need
380%D that it will become options.
381
382\def\e_page_sides_flush_criterium
383  {\dimexpr
384      \d_page_sides_vsize
385     -\d_page_sides_bottomtotal
386     -\pagetotal
387   \relax}
388
389\def\e_page_sides_room_criterium
390  {\dimexpr
391      \d_page_sides_vsize
392     -\d_page_sides_bottomtotal % added here too
393     -\pagetotal
394   \relax}
395
396%D In order to get a consistent spacing we force a strutdepth unless the
397%D preceding material has more depth than that already. This way anchoring
398%D becomes predictable.
399
400\unexpanded\def\page_sides_force_depth
401  {\iftracesidefloats
402     \begingroup
403     \c_page_force_strut_depth_trace_mode\plusone
404     \ifconditional\c_page_sides_check_same_page
405       \forcestrutdepthplus
406     \else
407       \forcestrutdepth
408     \fi
409     \endgroup
410   \else
411     \ifconditional\c_page_sides_check_same_page
412       \forcestrutdepthplus
413     \else
414       \forcestrutdepth
415     \fi
416   \fi
417   \page_otr_command_set_vsize} % new
418
419\def\page_sides_flush_floats
420  {\par
421   \ifdim\e_page_sides_flush_criterium>\zeropoint
422     \page_sides_flush_floats_progress
423     \page_sides_flush_floats_after_next
424   \fi
425   \page_sides_flush_floats_reset}
426
427\def\page_sides_flush_floats_text
428  {\par
429   % what with \c_anch_backgrounds_text_level>\plusone
430   \ifdim\e_page_sides_flush_criterium>\zeropoint
431     \page_sides_flush_floats_progress
432     \page_sides_flush_floats_after_none
433   \fi
434   \page_sides_flush_floats_reset}
435
436\def\page_sides_flush_floats_reset
437  {\global\d_page_sides_vsize\d_page_sides_vsize_reset
438   % also here if used at all \global\holdinginserts\zerocount
439   \global\setfalse\c_page_sides_short
440   \global\setfalse\c_page_sides_flag
441   \global\c_page_sides_checks_done\zerocount}
442
443\def\page_sides_flush_floats_after_none % we force a flush
444  {\ifdim\d_page_sides_midskip>\zeropoint
445      \blank[\the\d_page_sides_midskip]
446   \fi
447   \ignoreparskip
448   \blank[\v!disable]}
449
450\def\page_sides_flush_floats_after_next % we have two successive ones
451  {\ifdim\d_page_sides_bottomskip>\zeropoint
452      \blank[\the\d_page_sides_bottomskip]
453   \fi
454   \ignoreparskip
455   \blank[\v!disable]}
456
457%D A rudimentary checker:
458
459\unexpanded\def\doifelsesidefloat
460  {\par
461   \ifdim\e_page_sides_room_criterium>\zeropoint % -\pagedepth
462     \expandafter\firstoftwoarguments
463   \else
464     \expandafter\secondoftwoarguments
465   \fi}
466
467\let\doifsidefloatelse\doifelsesidefloat
468
469%D Sometimes we need to fill up the space alongside a side float and this
470%D is where we define the helpers. A user can enforce a smaller step. We use
471%D large steps when possible.
472
473\installcorenamespace{sidefloatsteps}
474
475\setvalue{\??sidefloatsteps\v!line  }{\strut}
476\setvalue{\??sidefloatsteps\v!big   }{\strut}
477\setvalue{\??sidefloatsteps\v!medium}{\halflinestrut} % was \halfstrut
478\setvalue{\??sidefloatsteps\v!small }{\noheightstrut} % was \quarterstrut
479
480\def\page_sides_flush_floats_tracer
481  {\dontleavehmode
482   \ruledhpack\bgroup\backgroundline[trace:b]{%
483     \llap{\smash{\vrule\s!width4\points\s!height.4\points\s!depth.4\points}}%
484     \ifnum\recurselevel=\plusone
485       \llap{\smash{\smallinfofont\the\scratchdimen}\hskip.5\leftmargindistance}%
486     \else\ifodd\recurselevel
487       \llap{\smash{\smallinfofont\recurselevel}\hskip.5\leftmargindistance}%
488     \fi\fi
489     \page_sides_flush_floats_normal
490     \kern\hsize
491   \egroup}}
492
493\def\page_sides_flush_floats_normal
494  {\ifdim\scratchdimen>\htdp\strutbox
495     \strut
496   \else
497     \m_pages_strut
498   \fi}
499
500\def\page_sides_flush_floats_progress
501  {\begingroup
502   \page_sides_force_depth
503   \parskip\zeropoint
504   \let\page_sides_flush_floats\relax
505   \edef\m_pages_strut
506     {\ifcsname\??sidefloatsteps\rootfloatparameter\c!step\endcsname
507        \lastnamedcs
508      \else
509        \noheightstrut
510      \fi}%
511   \forgetall
512   \offinterlineskip
513   \doloop
514     {\scratchdimen\e_page_sides_flush_criterium
515      \ifdim\scratchdimen>\onepoint      % good enough, can become configurable
516        \ifnum\recurselevel>\plushundred % safeguard, sort of deadcycles
517          \exitloop
518        \else\iftracesidefloats
519          \page_sides_flush_floats_tracer\par
520        \else
521          \page_sides_flush_floats_normal\par
522        \fi\fi
523      \else
524        \page_sides_force_depth
525        \exitloop
526      \fi}%
527   \endgroup}
528
529%D We force a parskip and ignore it afterwards. We can nil it by setting the
530%D \type {spacebeforeside} parameter. We can have a leading blank so we need
531%D to make sure that we use blank to inject the parskip and then ignore
532%D the one injected by the engine.
533
534\def\page_sides_inject_before
535  {\page_sides_force_depth
536   \ifdim\parskip>\zeropoint
537     \ifdim\parskip>\d_strc_floats_top
538       \ifdim\d_strc_floats_top>\zeropoint
539         \ignoreparskip
540         \blank[\v!white]%
541       \else
542         \checkedblank[\rootfloatparameter\c!spacebeforeside]%
543       \fi
544     \else
545       \checkedblank[\rootfloatparameter\c!spacebeforeside]%
546     \fi
547   \else
548     \checkedblank[\rootfloatparameter\c!spacebeforeside]%
549   \fi}
550
551%D We are now done with \type {spacebefore} and the parskip is already
552%D injected. The dummy line makes sure that we anchor properly and it
553%D also can serve as tracer.
554
555\def\page_sides_inject_dummy_line_normal
556  {\hpack to \availablehsize{\strut\hss}}
557
558\def\page_sides_inject_dummy_line_traced
559  {\ruledhpack to \availablehsize{\backgroundline[trace:c]{\page_sides_inject_dummy_line_normal}}}
560
561\def\page_sides_inject_dummy_lines
562  {\par
563   \nointerlineskip
564 % \ifnum\lastpenalty>\zerocount
565 %   \penalty\plustenthousand
566 % \fi
567   \dontleavehmode
568   \iftracesidefloats
569     \page_sides_inject_dummy_line_traced
570   \else
571     \page_sides_inject_dummy_line_normal
572   \fi
573   \par
574   % on an empty page we have topskip, say 12pt
575   \ignoreparskip
576   % this can be 18.5pt
577   \kern-\dimexpr\lineheight+\strutdp\relax
578   % so we can actually have a -2.5pt skip on top
579   \ignoreparskip
580   \blank[\v!samepage]
581   \blank[\v!disable]
582   % now say we are negative now
583   \ifdim\pagetotal<\zeropoint
584      % then we're at the top of the page ... quite messy .. i really need to
585      % make the page builder a bit more flexible .. should we do something now?
586   \fi}
587
588%D Checkers:
589
590\def\page_sides_check_floats_after_par
591  {\page_sides_check_floats_indeed
592   \ifdim\d_page_sides_pagetotal=\pagetotal \else
593     \glet\page_sides_check_floats\page_sides_check_floats_indeed
594     \page_sides_flush_floats
595     \global\c_page_sides_n_of_lines\zerocount % here !
596   \fi}
597
598\unexpanded\def\page_sides_flush_floats_after_par
599  {\global\d_page_sides_pagetotal\pagetotal
600   \glet\page_sides_check_floats\page_sides_check_floats_after_par}
601
602\unexpanded\def\page_sides_forget_floats
603  {\global\d_page_sides_vsize\d_page_sides_vsize_reset
604   \global\c_page_sides_n_of_lines\zerocount
605   % also here if used at all \global\holdinginserts\zerocount
606   \global\setfalse\c_page_sides_short
607   \global\setfalse\c_page_sides_flag}
608
609%D Here comes the output routine. We either go the fast route or we use the
610%D normal one (stored in \type {\page_otr_command_side_float_output}. We no
611%D longer have this fuzzy code around with penalties and indentation and
612%D such.
613
614\def\page_sides_output_routine
615  {\page_otr_command_side_float_output
616   \ifconditional\c_page_sides_short
617     \global\setfalse\c_page_sides_short
618   \else
619     \global\d_page_sides_vsize\d_page_sides_vsize_reset
620     \global\c_page_sides_n_of_lines\zerocount
621   \fi}
622
623\def\page_sides_place_float
624  {\ifnum\c_page_sides_float_type=\plusfour \kern\d_page_sides_toptotal \fi
625   \ifnum\c_page_sides_float_type=\plusfive \kern\d_page_sides_toptotal \fi
626   \ifgridsnapping
627     \page_sides_place_float_grid
628   \else
629     \page_sides_place_float_normal
630   \fi
631   \par
632   \kern-\d_page_sides_height
633   \penalty10001 % oeps, this will change
634   \normalbaselines}
635
636\def\page_sides_place_float_normal
637  {\page_sides_push_float_inline\firstofoneargument}
638
639%D The following needs some more work .. consider this a quick hack. We probably
640%D need an mkiv hanging grid option.
641
642\def\page_sides_place_snap_to_grid#1%
643  {\edef\p_grid{\floatparameter\c!grid}%
644   \ifx\p_grid\empty\else
645     \snaptogrid[\p_grid]%
646   \fi
647   \hpack{#1}}
648
649\def\page_sides_place_float_grid
650  {\getrawnoflines\d_page_sides_height % raw ?
651   \d_page_sides_height\noflines\lineheight
652   \page_sides_push_float_inline\page_sides_place_snap_to_grid}
653
654\let\strc_floats_mark_par_as_free\relax
655
656\def\page_sides_push_float_inline#1%
657  {\begingroup
658   \reseteverypar % needed !
659   \parskip\zeropoint  % needed !
660   \nointerlineskip
661   \page_sides_set_skips
662   \page_floats_report_total
663   \relax
664   \lefttoright
665   \strc_floats_mark_par_as_free
666   \ifcase\c_page_sides_float_type
667     % invalid
668   \or % backspace
669     \noindent#1{\llap{\rlap{\box\floatbox}\kern\d_page_sides_leftskip}}\hfill
670   \or % leftedge
671     \noindent#1{\llap{\box\floatbox\kern\d_page_sides_leftskip}}\hfill
672   \or % leftmargin
673     \noindent#1{\llap{\box\floatbox\kern\d_page_sides_leftskip}}\hfill
674   \or % leftside
675     \noindent#1{\box\floatbox}\hfill
676   \or % rightside
677     \hfill#1{\box\floatbox}%
678   \or % rightmargin
679     \hfill#1{\rlap{\kern\d_page_sides_rightskip\box\floatbox}}%
680   \or % rightedge
681     \hfill#1{\rlap{\kern\d_page_sides_rightskip\box\floatbox}}%
682   \or % cutspace
683     \hfill#1{\rlap{\kern\d_page_sides_rightskip\llap{\box\floatbox}}}%
684   \fi
685   \endgroup}
686
687% \def\page_sides_analyse_progress
688%   {\d_page_sides_progress\d_page_sides_vsize
689%    \ifconditional\c_page_sides_flag
690%      \advance\d_page_sides_progress-\d_page_sides_page_total
691%      \global\setfalse\c_page_sides_flag
692%    \else
693%      \advance\d_page_sides_progress-\pagetotal
694%    \fi}
695
696% test case
697%
698% \usemodule[art-01]
699% \starttext
700%     \dorecurse{40}{\line{#1}}
701%     \placefigure[left]{}{}
702%     \input ward
703%     \startitemize
704%         \item word \item word \item word \item word
705%     \stopitemize
706%     \input ward
707%     \page
708% \stoptext
709
710\def\page_sides_analyse_progress
711  {%\page_otr_command_set_vsize % this is new, otherwise topfloats are not taken into account
712   \d_page_sides_progress\d_page_sides_vsize
713   \ifconditional\c_page_sides_flag
714     \advance\d_page_sides_progress-\d_page_sides_page_total
715     \global\setfalse\c_page_sides_flag
716   \else
717     \ifdim\dimexpr\d_page_sides_progress+\d_page_sides_bottomtotal\relax>\pagegoal
718       % we adapt pagegoal because we can already have placed something with
719       % everypar and we hope that it triggers a flush, see test above
720       \pagegoal\dimexpr\pagegoal-\d_page_sides_bottomtotal\relax
721     \fi
722     \advance\d_page_sides_progress-\pagetotal
723   \fi}
724
725\def\page_sides_analyse_space_stage_one
726  {\global\settrue\c_page_sides_flag
727% \ifdim\pagegoal=\maxdimen
728%     \pagegoal\textheight % maybe
729% \fi
730   \global\d_page_sides_page_total \pagetotal % global
731   \ifnum\c_page_sides_float_type<\plusfour
732     \global\d_page_sides_width \zeropoint
733   \else\ifnum\c_page_sides_float_type>\plusfive
734     \global\d_page_sides_width\zeropoint
735   \else
736     \global\d_page_sides_width\dimexpr\wd\floatbox+\d_page_sides_margin\relax
737   \fi\fi
738   \ifdim\d_page_sides_width<\zeropoint
739     \global\d_page_sides_width\zeropoint
740   \fi
741   \global\d_page_sides_hsize \dimexpr\hsize-\d_page_sides_width\relax
742   \global\d_page_sides_height\dimexpr\ht\floatbox+\dp\floatbox+\d_page_sides_toptotal\relax
743   \global\d_page_sides_vsize \dimexpr\d_page_sides_height+\d_page_sides_page_total\relax
744   \scratchdimenone\d_page_sides_vsize
745   \scratchdimentwo\pagegoal
746   \ifcase\c_page_sides_tolerance
747     \ifcase\c_page_sides_method
748       % method 0 : raw
749     \or
750       % method 1 : safe (default)
751       \advance\scratchdimentwo -\strutdp
752     \or
753       % method 2 : tight (grid default)
754       \advance\scratchdimenone -\onepoint
755     \fi
756   \or
757     % tolerant
758     \advance\scratchdimentwo -.5\strutdp
759   \or
760     % verytolerant
761   % \advance\scratchdimenone -\onepoint (maybe)
762   \else
763     \advance\scratchdimentwo -\strutdp
764   \fi}
765
766\def\page_sides_analyse_space_stage_two
767  {% how about \pagedepth
768   \ifdim\scratchdimenone>\scratchdimentwo
769     \global\setfalse\c_page_floats_room
770   \else
771     \ifdim\dimexpr\pagegoal-\d_page_sides_vsize\relax<\d_page_sides_bottomtotal
772      % just weird: \global\advance\d_page_sides_vsize \scratchdimenone
773       \global\settrue\c_page_sides_short
774       % why was this \global\holdinginserts\plusone
775     \else
776       \global\advance\d_page_sides_vsize \d_page_sides_bottomtotal % wins over inbetween
777       \global\setfalse\c_page_sides_short
778     \fi
779     \global\settrue\c_page_floats_room
780   \fi}
781
782\def\page_sides_analyse_space
783  {\page_sides_analyse_space_stage_one
784   \ifconditional\c_page_sides_check_same_page
785     \ifdim\d_spac_prevcontent>\zeropoint
786       \ifdim\dimexpr\scratchdimenone+\d_spac_prevcontent>\scratchdimentwo
787         \clf_pushatsame
788         \setbox\scratchbox\vpack{\clf_popatsame}%
789         \page
790         \box\scratchbox
791         \vskip-\lineskip
792         \page_sides_analyse_space_stage_one
793       \fi
794     \fi
795   \fi
796   \page_sides_analyse_space_stage_two}
797
798%D As we have no clear end of one or more paragraphs we only have pre float
799%D skips.
800
801\newconstant\c_page_sides_page_method % will be: \c_page_sides_page_method\plusone
802
803\def\page_otr_force_new_page_one
804  {\vskip\d_page_sides_height
805   \penalty\outputpenalty
806   \vskip-\dimexpr\d_page_sides_height-\strutdp\relax
807   \prevdepth\strutdp}
808  %\ignoreparskip}
809
810\def\page_sides_handle_float#1%
811  {\page_sides_initialize_checker
812   \page_sides_check_horizontal_skips
813   \page_sides_check_vertical_skips
814   \page_sides_apply_horizontal_shift
815   \page_sides_check_previous_float
816   \page_sides_inject_before
817   \page_sides_inject_dummy_lines
818   \page_sides_relocate_float{#1}%
819   \page_sides_apply_vertical_shift
820   \page_sides_analyse_space
821   \ifconditional\c_page_floats_room
822     \global\setfalse\c_page_sides_delayed
823     % we're ok
824   \else
825     \global\settrue\c_page_sides_delayed
826     \global\c_page_sides_m_of_lines\c_page_sides_n_of_lines
827     \ifcase\c_page_sides_page_method
828       \page_otr_fill_and_eject_page
829     \or
830       \page_otr_force_new_page_one
831     \else
832       \page_otr_fill_and_eject_page
833     \fi
834     \global\c_page_sides_n_of_lines\c_page_sides_m_of_lines
835     \page_sides_analyse_space
836    %\page_sides_inject_before
837     \page_sides_inject_dummy_lines
838   \fi
839   \page_sides_place_float
840   \global\setfalse\c_page_sides_delayed
841   \page_sides_check_floats_reset
842   \page_sides_wrapup}
843
844\def\page_sides_wrapup
845  {% we need to do this aftergroup
846   \aftergroup\par
847   \aftergroup\ignoreparskip
848   \aftergroup\ignorespaces}
849
850\def\page_sides_check_floats_indeed
851  {\page_sides_analyse_progress
852   \ifdim\d_page_sides_progress>\zeropoint
853     \page_sides_check_floats_set
854   \else
855     \page_sides_check_floats_reset
856   \fi
857   \parskip\s_spac_whitespace_parskip} % not needed
858
859% \let\page_sides_check_floats\page_sides_check_floats_indeed
860
861\let\page_sides_check_floats\relax
862
863\def\page_sides_initialize_checker
864  {\ifx\page_sides_check_floats\relax
865     \glet\page_sides_check_floats\page_sides_check_floats_indeed
866     \clf_enablesidefloatchecker
867     \glet\page_sides_initialize_checker\relax
868   \fi}
869
870\unexpanded\def\page_sides_check_floats_tracer
871  {\begingroup
872   \dontleavehmode
873   \ifnum\c_page_sides_float_type>\plusfour
874     \rlap
875       {\hskip\availablehsize % d_page_sides_width % kern
876        \color[trace:o]%
877          {\rlap{\kern.25\bodyfontsize\showstruts\strut}%
878           \vrule\s!height.5\points\s!depth.5\points\s!width\d_page_sides_width}}%
879   \else
880     \hskip-\d_page_sides_width % kern
881     \color[trace:o]%
882       {\vrule\s!height.5\points\s!depth.5\points\s!width\d_page_sides_width
883        \llap{\showstruts\strut\kern.25\bodyfontsize}}%
884   \fi
885   \endgroup}
886
887% tricky test:
888
889% \starttext
890%     \dorecurse{33}{\line{#1}}
891%     \placefigure[left]{}{}
892%     \input ward
893%     \startitemize
894%         \item word \item word \item word \item word
895%     \stopitemize
896%     \input ward
897%     \page
898%     \placefigure[left]{}{}
899%     \dontleavehmode \begingroup \input ward \par \endgroup
900%     \dontleavehmode \begingroup \input ward \par \endgroup
901%     \dontleavehmode \begingroup \input ward \par \endgroup
902%     \input ward
903% \stoptext
904
905\unexpanded\def\page_sides_check_floats_set
906  {\edef\p_sidethreshold{\floatparameter\c!sidethreshold}%
907   \ifconditional\c_page_sides_delayed
908     % For Alan's hanging right float that moved to the next page.
909     \d_page_sides_progress\zeropoint
910   \fi
911   \ifx\p_sidethreshold\v!old
912     \d_page_sides_progression\dimexpr\d_page_sides_progress+\strutht-\roundingeps\relax
913     \c_page_sides_n_of_hang\d_page_sides_progression
914     \divide\c_page_sides_n_of_hang \baselineskip\relax
915   \else
916     \d_page_sides_progression
917       \ifx\p_sidethreshold\empty
918         \d_page_sides_progress
919       \else
920         \dimexpr\d_page_sides_progress-\p_sidethreshold\relax
921       \fi
922     \getnoflines\d_page_sides_progression
923     % this can be an option
924     \ifdim\dimexpr\noflines\lineheight>\dimexpr\pagegoal-\pagetotal\relax
925       \getrawnoflines\d_page_sides_progression
926     \fi
927     %
928     \c_page_sides_n_of_hang\noflines
929   \fi
930   \global\c_page_sides_hangafter\zerocount
931   \ifnum\c_page_sides_n_of_hang>\zerocount
932     \ifcase\c_page_sides_n_of_lines
933     \else
934       \ifcase\c_page_sides_lines_done
935         \global\c_page_sides_lines_done\c_page_sides_n_of_hang
936       \else
937         \privatescratchcounter\c_page_sides_lines_done
938         \advance\privatescratchcounter-\c_page_sides_n_of_hang
939         \global\advance\c_page_sides_n_of_lines-\privatescratchcounter
940       \fi
941     \fi
942     \ifnum\c_page_sides_n_of_lines>\zerocount
943       \privatescratchtoks\emptytoks
944       \privatescratchcounter\c_page_sides_n_of_lines
945       \privatescratchdimen\dimexpr\hsize-\d_page_sides_width\relax
946       \dorecurse\c_page_sides_n_of_lines
947         {\toksapp\privatescratchtoks{\zeropoint\hsize}}%
948       \ifnum\c_page_sides_n_of_hang>\c_page_sides_n_of_lines
949         \advance\c_page_sides_n_of_hang -\c_page_sides_n_of_lines\relax
950         \advance\privatescratchcounter\c_page_sides_n_of_hang
951         \dorecurse\c_page_sides_n_of_hang % weird, shouldn't that be scratchcounter
952           {\ifnum\c_page_sides_float_type>\plusfour
953              \toksapp\privatescratchtoks{\zeropoint\privatescratchdimen}%
954            \else
955              \toksapp\privatescratchtoks{\d_page_sides_width\privatescratchdimen}%
956            \fi}%
957       \fi
958       \parshape
959         \numexpr\privatescratchcounter+\plusone\relax
960         \the\privatescratchtoks
961         \zeropoint \hsize
962       \relax
963     \else
964       \hangindent \ifnum\c_page_sides_float_type>\plusfour -\fi\d_page_sides_width
965       \hangafter-\c_page_sides_n_of_hang
966       \global\c_page_sides_hangafter\hangafter
967     \fi
968   \fi
969   \global\advance\c_page_sides_checks_done \plusone
970   \iftracesidefloats
971     \page_sides_check_floats_tracer
972   \fi}
973
974\unexpanded\def\page_sides_check_floats_reset
975  {\ifcase\c_page_sides_checks_done\else
976     \ifcase\c_page_sides_hangafter\else
977       % we need to deal with par's ending in a group which would restore
978       % hang parameters
979       \global\c_page_sides_hangafter\zerocount
980       \hangindent\zeropoint
981     \fi
982   % \global % no, otherwise a next hangindent won't work
983     \c_page_sides_checks_done\zerocount
984   \fi}
985
986\unexpanded\def\page_sides_synchronize_floats
987  {\ifinner \else
988     \page_sides_check_floats
989   \fi}
990
991\unexpanded\def\page_sides_check_previous_float
992  {\page_sides_analyse_progress
993   \ifdim\d_page_sides_progress>\zeropoint \relax
994     \ifconditional\c_page_sides_short
995       \global\setfalse\c_page_sides_short
996       \page_otr_fill_and_eject_page
997     \else
998       \kern\d_page_sides_progress
999     \fi
1000   \fi}
1001
1002% \def\adjustsidefloatdisplaylines % public, will change
1003%   {\aftergroup\page_sides_adjust_display_lines}
1004%
1005% \def\page_sides_adjust_display_lines
1006%   {\par
1007%    \noindent
1008%    \ignorespaces}
1009
1010%D We need to hook it into the other otr's. This code will be adapted once we rename
1011%D the callers. We use \type {\def} as they can be redefined! Some will become obsolete
1012
1013\unexpanded\def\checksidefloat         {\page_sides_check_floats}
1014\unexpanded\def\flushsidefloats        {\page_sides_flush_floats_text}
1015\unexpanded\def\flushsidefloatsafterpar{\page_sides_flush_floats_after_par}
1016\unexpanded\def\forgetsidefloats       {\page_sides_forget_floats}
1017%unexpanded\def\synchronizesidefloats  {\page_sides_synchronize_floats}
1018
1019\protect \endinput
1020