spac-ver.mkxl /size: 81 Kb    last modification: 2024-01-16 09:03
1%D \module
2%D   [       file=spac-ver,
3%D        version=2009.10.16, % 1997.03.31, was core-spa.tex
4%D          title=\CONTEXT\ Spacing Macros,
5%D       subtitle=Vertical,
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 Spacing Macros / Vertical}
15
16\unprotect
17
18\newgluespec\bodyfontlineheight        % why a skip
19\newdimen   \bodyfontstrutheight
20\newdimen   \bodyfontstrutdepth
21
22\newgluespec\globalbodyfontlineheight  % why a skip
23\newdimen   \globalbodyfontstrutheight
24\newdimen   \globalbodyfontstrutdepth
25
26\newgluespec \s_spac_vspacing_predefined
27\newdimension\d_spac_overlay
28\newinteger  \c_spac_vspacing_ignore_parskip
29
30% \overloaded\let\strutht  \undefined \newdimen\strutht   % already defined
31% \overloaded\let\strutdp  \undefined \newdimen\strutdp
32% \overloaded\let\struthtdp\undefined \newdimen\struthtdp
33
34\registerctxluafile{spac-ver}{autosuffix}
35
36% todo: use usernodes ?
37
38% todo: itemize : intro ... only when there is one or two lines preceding and then
39% keep these together i.e. \blank[intro]
40
41% Isn't it about time to get rid of topskip i.e. make it equivalent to
42% \openstrutheight so that we can remove delta code.
43%
44% There might be more namespace protection.
45
46%D There are two ways to influence the interline spacing. The most general and often
47%D most consistent way is using
48%D
49%D \showsetup{setupinterlinespace}
50%D
51%D For instance
52%D
53%D \starttyping
54%D \setupinterlinespace[line=2.8ex]
55%D \stoptyping
56%D
57%D This setting adapts itself to the bodyfontsize, while for instance saying
58%D
59%D \starttyping
60%D \setupinterlinespace[line=12pt]
61%D \stoptyping
62%D
63%D sets things fixed for all sizes, which is definitely not what we want. Therefore
64%D one can also say:
65%D
66%D \starttyping
67%D \definebodyfontenvironment[9pt][interlinespace=11pt]
68%D \stoptyping
69%D
70%D One can still use \type {\setupinterlinespace} (without arguments) to set the
71%D interline space according to the current font, e.g. a \type {\bfa}.
72
73% will be cleaned up but it will stay messy because we accept so
74% many variants
75
76\newif\iflocalinterlinespace
77
78\newgluespec\s_spac_vspacing_temp \s_spac_vspacing_temp\bigskipamount
79
80\mutable\def\skipfactor    {.75}
81\mutable\def\skipgluefactor{.25}
82
83\permanent\def\normalskipamount
84  {\openlineheight
85     \ifgridsnapping \orelse \ifconditional\c_spac_whitespace_flexible
86       \s!plus \skipgluefactor\openlineheight
87       \s!minus\skipgluefactor\openlineheight
88     \fi
89   \relax}
90
91\ifdefined\bodyfontinterlinespace \else
92  \lettonothing\bodyfontinterlinespace
93\fi
94
95% \permanent\protected\def\presetnormallineheight % each bodyfont
96%   {\edef\normallineheight{\interlinespaceparameter\c!line}%
97%    \iflocalinterlinespace \else
98%      \edef\m_spac_normallineheight{\bodyfontinterlinespace}%
99%      \ifempty\m_spac_normallineheight \else
100%        \let\normallineheight\m_spac_normallineheight
101%      \fi
102%    \fi}
103
104\permanent\protected\def\presetnormallineheight % each bodyfont
105  {\edef\normallineheight{\interlinespaceparameter\c!line}%
106   \iflocalinterlinespace \else
107     \edef\m_spac_normallineheight{\bodyfontinterlinespace}%
108     \ifempty\m_spac_normallineheight
109     \orelse\ifchkdimension\m_spac_normallineheight\or
110       \let\normallineheight\m_spac_normallineheight
111     \else
112       \edef\normallineheight{\todimension\m_spac_normallineheight\dimexpr\fontbody\relax}%
113     \fi
114   \fi}
115
116\permanent\protected\def\setupspecifiedinterlinespace[#S#1]%
117  {\setupcurrentinterlinespace[#1]%
118   \spac_linespacing_setup_specified_interline_space}
119
120\def\spac_linespacing_setup_specified_interline_space
121  {\edef\strutheightfactor    {\interlinespaceparameter\c!height   }%
122   \edef\strutdepthfactor     {\interlinespaceparameter\c!depth    }%
123   \edef\minimumstrutheight   {\interlinespaceparameter\c!minheight}%
124   \edef\minimumstrutdepth    {\interlinespaceparameter\c!mindepth }%
125   \edef\minimumlinedistance  {\interlinespaceparameter\c!distance }%
126   \edef\normallineheight     {\interlinespaceparameter\c!line     }%
127   \edef\topskipfactor        {\interlinespaceparameter\c!top      }%
128   \edef\ntopskipfactor       {\interlinespaceparameter\c!ntop     }%
129   \edef\maxdepthfactor       {\interlinespaceparameter\c!bottom   }%
130   \edef\m_spac_vertical_baseline_stretch_factor{\interlinespaceparameter\c!stretch}%
131   \edef\m_spac_vertical_baseline_shrink_factor {\interlinespaceparameter\c!shrink }%
132   % often topskip does more bad than good, so:
133   \ifx\topskipfactor\v!height
134     \let\topskipfactor\strutheightfactor
135   \fi
136   \setfontparameters % redundant, can be \setstrut, test first
137   \updateraggedskips} % yes indeed
138
139\installcorenamespace{interlinespacerelative}
140
141\aliased\let\setrelativeinterlinespace\relax % used elsewhere
142
143\mutable\lettonothing\currentrelativeinterlinespace
144
145\defcsname\??interlinespacerelative\v!on   \endcsname{\oninterlineskip}
146\defcsname\??interlinespacerelative\v!off  \endcsname{\offinterlineskip}
147\defcsname\??interlinespacerelative\v!reset\endcsname{\enforced\lettonothing\currentrelativeinterlinespace
148                                                      \enforced\let\setrelativeinterlinespace\relax
149                                                      \setfontparameters}
150\defcsname\??interlinespacerelative\v!auto \endcsname{\enforced\let\setrelativeinterlinespace\spac_linespacing_set_relative_interlinespace}
151
152\def\spac_linespacing_set_specified_relative_interlinespace#1% fragile?
153  {\doifelsedimenstring{#1}%
154     {\setupspecifiedinterlinespace[\c!line=#1]}%
155     {\assignvalue{#1}\currentrelativeinterlinespace{1.00}{1.25}{1.50}%
156      \spacing\currentrelativeinterlinespace}}
157
158\permanent\protected\def\setuprelativeinterlinespace[#1]%
159  {\processcommalist[#1]\spac_linespacing_setup_relative_interlinespace}
160
161\def\spac_linespacing_setup_relative_interlinespace#1%
162  {\ifcsname\??interlinespacerelative#1\endcsname
163     \lastnamedcs
164   \else
165     \spac_linespacing_set_specified_relative_interlinespace{#1}%
166   \fi}
167
168\permanent\protected\def\spac_linespacing_set_relative_interlinespace
169  {\ifempty\currentrelativeinterlinespace\else
170     \spacing\currentrelativeinterlinespace
171   \fi}
172
173\protected\def\spac_linespacing_setup_use
174  {\ifcsname\namedinterlinespacehash\m_spac_interlinespace\s!parent\endcsname
175     \let\currentinterlinespace\m_spac_interlinespace
176     \spac_linespacing_setup_specified_interline_space
177 % \else
178     % we only support named interlinespaces
179   \fi}
180
181\permanent\protected\def\useinterlinespaceparameter#1% see footnotes
182  {\edef\m_spac_interlinespace{#1\c!interlinespace}%
183   \ifempty\m_spac_interlinespace \else
184     \spac_linespacing_setup_use
185   \fi}
186
187\newtoks\everysetupglobalinterlinespace
188\newtoks\everysetuplocalinterlinespace
189
190\newconditional\interlinespaceisset
191
192\installcorenamespace{interlinespace}
193
194\installcommandhandler \??interlinespace {interlinespace} \??interlinespace
195
196\installmacrostack\currentinterlinespace
197
198\permanent\overloaded\tolerant\protected\def\setupinterlinespace[#S#1]%
199  {\ifarguments
200     \interlinespaceisset\conditionaltrue
201     \spac_linespacing_synchronize_local
202   \else
203     \interlinespaceisset\conditionaltrue
204     \ifcsname\namedinterlinespacehash{#1}\s!parent\endcsname
205        \cdef\currentinterlinespace{#1}%
206        \spac_linespacing_setup_specified_interline_space
207       %\dosetupspecifiedinterlinespaceindeed
208     \else
209       \spac_linespacing_setup_specified_or_relative[#1]%
210     \fi
211   \fi}
212
213\def\spac_linespacing_setup_specified_or_relative[#S#1]%
214  {\doifelseassignment{#1}\setupspecifiedinterlinespace\setuprelativeinterlinespace[#1]%
215   \expandtoks\iflocalinterlinespace\everysetuplocalinterlinespace\else\everysetupglobalinterlinespace\fi}
216
217\def\spac_linespacing_synchronize_local % adapts to the font
218  {\localinterlinespacetrue
219   \setfontparameters
220   \updateraggedskips % funny one here
221   \expandtoks\everysetuplocalinterlinespace
222   \localinterlinespacefalse}
223
224\permanent\protected\def\dosetupcheckedinterlinespace#1% often a chain
225  {\edef\p_spac_checked_interlinespace{#1}%
226   \ifempty\p_spac_checked_interlinespace
227     \spac_linespacing_synchronize_local
228   \orelse\ifcsname\namedinterlinespacehash\p_spac_checked_interlinespace\s!parent\endcsname % we could have a \s!check
229     \push_macro_currentinterlinespace
230     \let\currentinterlinespace\p_spac_checked_interlinespace
231     \spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed
232     \iflocalinterlinespace
233       \expandtoks\everysetuplocalinterlinespace
234     \else
235       \localinterlinespacetrue
236       \expandtoks\everysetuplocalinterlinespace
237       \localinterlinespacefalse
238     \fi
239     \pop_macro_currentinterlinespace
240   \else
241     \normalexpanded{\noexpand\doifelseassignment{\p_spac_checked_interlinespace}%
242       \setupspecifiedinterlinespace\setuprelativeinterlinespace[\p_spac_checked_interlinespace]}%
243     \iflocalinterlinespace
244       \expandtoks\everysetuplocalinterlinespace
245     \else
246       \localinterlinespacetrue
247       \expandtoks\everysetuplocalinterlinespace
248       \localinterlinespacefalse
249     \fi
250   \fi}
251
252\permanent\protected\def\setuplocalinterlinespace[#S#1]%
253  {\localinterlinespacetrue
254   \push_macro_currentinterlinespace
255   \setupinterlinespace[#1]%
256   \pop_macro_currentinterlinespace
257   \localinterlinespacefalse}
258
259\aliased\let\switchtointerlinespace\setuplocalinterlinespace
260
261%D Helpers
262
263\newgluespec \s_spac_lastskip
264\newdimension\d_spac_prevdepth
265\newinteger  \c_spac_spacefactor
266%newdimension\d_spac_prevcontent % set by lua (no longer it seems)
267
268% \permanent\overloaded\protected\def\removelastskip
269%   {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
270
271\permanent\def\doifoutervmode
272  {\unless\ifvmode
273     \expandafter\gobbleoneargument
274   \orelse\ifinner
275     \expandafter\gobbleoneargument
276   \else
277     \expandafter\firstofoneargument
278   \fi}
279
280\permanent\protected\def\dosomebreak#1% should be replaced by something \blank
281  {\doifoutervmode
282     {\s_spac_lastskip\lastskip
283      \removelastskip
284      #1\relax
285      \ifzeropt\s_spac_lastskip
286        % avoid interference with footnotes
287      \else
288        \vskip\s_spac_lastskip
289      \fi}}
290
291\permanent\protected\def\packed
292  {\nointerlineskip}
293
294\permanent\protected\def\godown[#1]%
295  {\relax
296   \ifhmode\endgraf\fi
297   \ifvmode\nointerlineskip\vskip#1\relax\fi}
298
299\permanent\protected\def\smallskip{\vskip\smallskipamount}
300\permanent\protected\def\medskip  {\vskip\medskipamount}
301\permanent\protected\def\bigskip  {\vskip\bigskipamount}
302
303\permanent\protected\def\smallbreak
304  {\par
305   \ifvmode\ifdim\lastskip<\smallskipamount
306     \removelastskip
307     \penalty-\plusfifty
308     \smallskip
309   \fi\fi}
310
311\permanent\protected\def\medbreak
312  {\par
313   \ifvmode\ifdim\lastskip<\medskipamount
314     \removelastskip
315     \penalty-\plusonehundred
316     \medskip
317   \fi\fi}
318
319\permanent\protected\def\bigbreak
320  {\par
321   \ifvmode\ifdim\lastskip<\bigskipamount
322     \removelastskip
323     \penalty-\plustwohundred
324     \bigskip
325   \fi\fi}
326
327\permanent\protected\def\break     {\penalty-\plustenthousand} % can be hmode or vmode
328\permanent\protected\def\nobreak   {\penalty \plustenthousand} % can be hmode or vmode
329\permanent\protected\def\allowbreak{\penalty \zerocount}       % can be hmode or vmode
330
331\permanent\protected\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi}       % forces vmode
332\permanent\protected\def\filbreak  {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode
333
334%D Made slightly more readable:
335
336\permanent\protected\def\vglue  {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=}
337\permanent\protected\def\hglue  {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=}
338\permanent\protected\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi}
339
340\def\spac_helpers_vglue_indeed
341  {\par
342   \ifvmode
343     \d_spac_prevdepth\prevdepth
344     \hrule\s!height\zeropoint
345     \nobreak
346     \vskip\s_spac_lastskip
347     \prevdepth\d_spac_prevdepth
348   \fi}
349
350\def\spac_helpers_hglue_indeed
351  {\dontleavehmode
352   \c_spac_spacefactor\spacefactor
353   \vrule\s!width\zeropoint
354   \nobreak
355   \hskip\s_spac_lastskip
356   \spacefactor\c_spac_spacefactor}
357
358%D We adapt plain's \type {\removelastskip} a bit:
359
360\pushoverloadmode
361
362\permanent\overloaded\protected\def\removelastskip % also in supp-box
363  {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
364
365\popoverloadmode
366
367% The whitespace handler. We could cache settings but normally there are not
368% that many in a set.
369
370\installcorenamespace{whitespacemethod}
371
372\newgluespec   \s_spac_whitespace_parskip
373\newconditional\c_spac_whitespace_flexible  \c_spac_whitespace_flexible\conditionaltrue
374\newconstant   \c_spac_whitespace_grid_mode % option in layout / 1=permit_half_lines
375
376%def\v_spac_whitespace_current{\zeropoint}
377\let\v_spac_whitespace_current\v!none
378
379\permanent\tolerant\protected\def\setupwhitespace[#1]%
380  {\ifarguments
381     \spac_whitespace_setup_nop
382   \orelse\ifempty{#1}%
383     \spac_whitespace_setup_nop
384   \else
385     \edef\v_spac_whitespace_current{#1}%
386     \spac_whitespace_setup
387   \fi}
388
389\permanent\protected\def\spac_whitespace_setup_nop
390  {\ifx\v_spac_whitespace_current\v!none\else
391     \spac_whitespace_setup
392   \fi}
393
394\aliased\let\synchronizewhitespace\spac_whitespace_setup_nop
395
396\def\spac_whitespace_setup % quick test for no list
397  {\ifcsname\??whitespacemethod\v_spac_whitespace_current\endcsname
398     \lastnamedcs
399   \else
400     \expandafter\processcommalist\expandafter[\v_spac_whitespace_current]\spac_whitespace_setup_method % can be raw
401   \fi\relax
402   \ifgridsnapping
403     \spac_whitespace_setup_grid
404   \else
405     \spac_whitespace_setup_normal
406   \fi
407   \parskip\s_spac_whitespace_parskip}
408
409\def\spac_whitespace_setup_normal
410  {\ifconditional\c_spac_whitespace_flexible \else
411     \s_spac_whitespace_parskip\plusone\s_spac_whitespace_parskip
412   \fi}
413
414\def\spac_whitespace_setup_grid
415  {\c_spac_whitespace_flexible\conditionalfalse
416   \ifdim\s_spac_whitespace_parskip>\zeropoint
417     \s_spac_whitespace_parskip
418       \ifcase\c_spac_whitespace_grid_mode
419         \baselineskip
420       \or
421         \ifdim\scratchdimen=\baselineskip % maybe range
422           \baselineskip
423         \else
424           \numexpr\s_spac_whitespace_parskip/\dimexpr.5\lineheight\relax\relax\dimexpr.5\lineheight\relax
425         \fi
426       \else
427         \baselineskip
428       \fi
429   \fi}
430
431\permanent\protected\def\installwhitespacemethod#1#2%
432  {\defcsname\??whitespacemethod#1\endcsname{#2}}
433
434\installwhitespacemethod \v!fix         {}
435\installwhitespacemethod \v!fixed       {\c_spac_whitespace_flexible\conditionalfalse}
436\installwhitespacemethod \v!flexible    {\c_spac_whitespace_flexible\conditionaltrue}
437
438\installwhitespacemethod \v!line        {\s_spac_whitespace_parskip   \baselineskip}
439\installwhitespacemethod \v!halfline    {\s_spac_whitespace_parskip .5\baselineskip}
440\installwhitespacemethod \v!quarterline {\s_spac_whitespace_parskip.25\baselineskip}
441\installwhitespacemethod \v!none        {\s_spac_whitespace_parskip   \zeroskip}
442\installwhitespacemethod \v!big         {\s_spac_whitespace_parskip   \bigskipamount}
443\installwhitespacemethod \v!medium      {\s_spac_whitespace_parskip   \medskipamount}
444\installwhitespacemethod \v!small       {\s_spac_whitespace_parskip   \smallskipamount}
445
446\installwhitespacemethod \s!default     {\spac_whitespace_setup_nop} % also covers none
447
448\def\spac_whitespace_setup_method#1%
449  {\ifcsname\??whitespacemethod#1\endcsname
450     \lastnamedcs
451   \else
452     \s_spac_whitespace_parskip#1%
453   \fi\relax}
454
455\permanent\protected\def\forgetparskip
456  {\s_spac_whitespace_parskip\zeroskip
457   \parskip\zeroskip
458   \let\v_spac_whitespace_current\v!none}
459
460\appendtoks
461    \forgetparskip
462\to \everyforgetall
463
464% \installwhitespacemethod \s!unknown  {\s_spac_whitespace_parskip\commalistelement\relax}
465%
466% \def\spac_whitespace_setup_method#1%
467%   {\csname\??whitespacemethod\ifcsname\??whitespacemethod#1\endcsname#1\else\s!unknown\endcsname\relax}
468
469\permanent\protected\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]}
470\permanent\protected\def\whitespace  {\directcheckedvspacing\v!white}   % {\vspacing[\v!white]}
471
472\setupwhitespace
473  [\v!none]
474
475% Packed:
476
477% todo: when packed blocks blank, we need to enable forced
478
479\newconditional\c_spac_packed_blank \c_spac_packed_blank\conditionaltrue
480\newinteger    \c_spac_packed_level
481
482\permanent\tolerant\protected\def\startpacked[#1]%
483  {\global\advanceby\c_spac_packed_level\plusone
484   \par
485   \ifnum\c_spac_packed_level=\plusone \ifvmode
486     \begingroup
487     \whitespace % not combined
488     \directcheckedvspacing\v!disable % \blank[\v!disable]% or \inhibitblank
489     \ifcstok{#1}\v!blank
490       \c_spac_packed_blank\conditionaltrue
491     \else
492       \c_spac_packed_blank\conditionalfalse
493     \fi
494     \setupwhitespace[\v!none]% or \forgetparskip
495   \fi \fi}
496
497\permanent\protected\def\stoppacked
498  {\par
499   \ifnum\c_spac_packed_level=\plusone \ifvmode
500     \endgroup
501   \fi \fi
502   \global\advanceby\c_spac_packed_level\minusone}
503
504\permanent\protected\def\startunpacked
505  {\directdefaultvspacing % \blank
506   \begingroup}
507
508\permanent\protected\def\stopunpacked
509  {\endgroup
510   \directdefaultvspacing}% \blank}
511
512% \prevdepth crosses pageboundaries!
513%
514% todo: a version that works ok inside a box
515
516% global : outer hsize + keep skips
517% local  : inner hsize + reset skips
518
519\installcorenamespace{linesaround}
520
521\let\spac_lines_vbox\vbox
522
523\installtextracker
524  {linecorrection.boxes}
525  {\enforced\let\spac_lines_vbox\ruledvbox}
526  {\enforced\let\spac_lines_vbox\vbox}
527
528\let\v_spac_lines_around_action_set\relax
529
530\lettonothing\spac_lines_action_around_before
531\lettonothing\spac_lines_action_around_after
532
533\newconstant\c_spac_lines_correction_mode
534
535\installcorenamespace{linecorrection}
536
537\installsetuponlycommandhandler \??linecorrection {linecorrection}
538
539\permanent\tolerant\protected\def\startlinecorrection     [#S#1]{\spac_lines_start_correction\plusone{#1}}
540\permanent\tolerant\protected\def\startlocallinecorrection[#S#1]{\spac_lines_start_correction\plustwo{#1}}
541
542\permanent\protected\def\spac_lines_start_correction_box
543  {\setbox\scratchbox\spac_lines_vbox\bgroup
544     \ifcase\c_spac_lines_correction_mode
545       % nothing
546     \or
547       % global
548     \or
549       % local
550       \setlocalhsize
551       \hsize\localhsize
552       \forgetbothskips
553     \fi
554     \ignorespaces}
555
556\permanent\protected\def\spac_lines_stop_correction_box
557  {\removeunwantedspaces
558   \egroup}
559
560\permanent\protected\def\spac_lines_start_correction#1#2%
561  {\endgraf
562   \begingroup
563   \c_spac_lines_correction_mode#1%
564   % a bit of history
565   \ifhastok={#2}%
566     \setupcurrentlinecorrection[#2]%
567     \def\spac_lines_action_around_before{\linecorrectionparameter\c!before}%
568     \def\spac_lines_action_around_after {\linecorrectionparameter\c!after}%
569   \orelse\ifempty{#2}%
570     \def\spac_lines_action_around_before{\linecorrectionparameter\c!before}%
571     \def\spac_lines_action_around_after {\linecorrectionparameter\c!after}%
572   \orelse\ifcstok{#2}\v!blank
573     \def\spac_lines_action_around_before{\blank}%
574     \let\spac_lines_action_around_after \spac_lines_action_around_before
575   \else
576     \def\spac_lines_action_around_before{\blank[#2]}%
577     \let\spac_lines_action_around_after \spac_lines_action_around_before
578   \fi
579   \ifgridsnapping
580     \spac_lines_start_correction_ongrid
581   \else
582     \spac_lines_start_correction_normal
583   \fi}
584
585\permanent\protected\def\spac_lines_stop_correction
586  {\ifgridsnapping
587     \spac_lines_stop_correction_ongrid
588   \else
589     \spac_lines_stop_correction_normal
590   \fi
591   \endgroup}
592
593\permanent\protected\def\spac_lines_start_correction_normal
594  {\spac_lines_action_around_before
595   \d_spac_prevdepth\prevdepth
596   \spac_lines_initialize_corrections
597   \offbaselinecorrection % ???
598   \spac_lines_start_correction_box}
599
600\newconstant\linecorrectionmode
601
602% \linecorrectionmode\plusone % better for end of column and depth alignment
603
604\permanent\protected\def\spac_lines_stop_correction_normal
605  {\spac_lines_stop_correction_box
606   \ifnum\linecorrectionmode=\plusone
607     \forcestrutdepth
608     \iftrue
609       \penalty\zerocount % works too
610     \else
611         %\tracingpages\plusone \tracingonline\plustwo
612       \pageboundary\plustenthousand % becomes a penalty (after triggering the callback) (experimental!)
613         %\tracingpages\zerocount
614     \fi
615   \else
616     \directcheckedvspacing\v!nowhite % \blank[\v!nowhite]%
617     \ifdim\parskip>\zeropoint
618        % too fuzzy otherwise
619     \orelse\ifdim\d_spac_prevdepth<\maxdimen
620       \unless\ifdim\d_spac_prevdepth<\zeropoint
621         \ifdim\d_spac_prevdepth<\strutdp \relax
622           \pushlastnode
623           \ifdim\d_spac_prevdepth>\zeropoint
624               \kern-\d_spac_prevdepth
625           \fi
626           \kern\strutdp
627           \prevdepth\strutdp
628           \poplastnode
629         \fi
630       \fi
631     \fi
632   \fi
633   \ifdim\pagegoal<\maxdimen
634   % \blank[\v!white,\the\d_spac_lines_correction_before]% \blank[\v!white]\dotopbaselinecorrection
635     \directcheckedvspacing{\v!white,\the\d_spac_lines_correction_before}% \blank[\v!white]\dotopbaselinecorrection
636   \fi
637   \nointerlineskip % relatively new
638   \noindent % not \dontleavehmode !
639   \ifcase\c_spac_lines_correction_mode
640     % nothing
641   \or
642     % global
643     \hskip-\leftskip % more tricky would be hangindent so we ignore that one
644   \or
645     % local
646   \fi
647   \box\scratchbox
648   \endgraf
649   %
650   % eventually i'll get it right ... (i also need to check all whitespace code elsewhere)
651   %
652 % \blank[\the\d_spac_lines_correction_after]% \dobotbaselinecorrection
653 % \directcheckedvspacing{\the\d_spac_lines_correction_after}% \dobotbaselinecorrection
654   \directcheckedvspacing{\v!white,\the\d_spac_lines_correction_after}% \dobotbaselinecorrection
655 % \allowbreak % new, otherwise problems when many in a row
656   \prevdepth\strutdp
657   \spac_lines_action_around_after}
658
659% this needs checking: a double before .. use lmtx tricks
660
661\permanent\protected\def\spac_lines_start_correction_ongrid
662  {\spac_lines_action_around_before
663   \d_spac_prevdepth\prevdepth
664   \spac_lines_initialize_corrections
665   \offbaselinecorrection % ???
666   \spac_lines_start_correction_box}
667
668\permanent\protected\def\spac_lines_stop_correction_ongrid
669  {\spac_lines_stop_correction_box
670   \directcheckedvspacing\v!white % \blank[\v!white]%
671   \spac_lines_action_around_before
672   \snaptogrid\hpack{\box\scratchbox}%
673   \directcheckedvspacing\v!white
674   \spac_lines_action_around_after}
675
676\aliased\let\stoplinecorrection     \spac_lines_stop_correction
677\aliased\let\stoplocallinecorrection\spac_lines_stop_correction
678
679% todo:
680
681\permanent\protected\def\correctwhitespace
682  {\dowithnextboxcs\correctwhitespacefinish\vbox}
683
684\permanent\protected\def\correctwhitespacefinish
685  {\startbaselinecorrection
686   \flushnextbox
687   \stopbaselinecorrection}
688
689\permanent\protected\def\verticalstrut  {\vpack{\hsize\zeropoint\forgetall\strut}}
690\permanent\protected\def\horizontalstrut{\hpack                          {\strut}}
691
692%D Here follow some presets related to interline spacing and therefore also struts.
693%D The values 2.8, 0.07, 0.72 and 0.28 originate in \INRSTEX, a package that we used
694%D a while after we decided that \LATEX\ was not flexible enough. After that
695%D \CONTEXT\ evolved, from some wrapper code around (old) \LATEX\ (on a floppy
696%D disk), to using modules from \INRSTEX\ (which also fit on a floppy) and finally
697%D all written from scratch. I simply didn't understand all that \TEX\ code at that
698%D time, and it was easier to figure it out myself. But \unknown\ some settings
699%D stayed, as the height|/|depth ratios, and they never proved to be bad ones! The
700%D same is true for the font size relations.
701
702%D \starttabulate
703%D \NC  \type {\lineheight}        \NC the height of a line \NC \NR
704%D \NC  \type {\spacing{number}}   \NC adapting the interline space \NC \NR
705%D \NC  \type {\normalbaselines}   \NC initialize the interline spacing \NC \NR
706%D \NC  \type {\setstrut}          \NC initialize \type {\strut} \NC \NR
707%D \NC  \type {\setnostrut}        \NC disable the \type {\strut}, \type {\endstrut}, \type {\begstrut} \NC \NR
708%D \NC  \type {\setteststrut}      \NC initialize the visual \type {\strut} \NC \NR
709%D \NC  \type {\resetteststrut}    \NC disable the visual \type {\strut} \NC \NR
710%D \NC  \type {\setfontparameters} \NC synchronize parameters with foints \NC \NR
711%D \stoptabulate
712%D
713%D \unknown\ and many more (this is a decades old list).
714%D
715%D The lineheight is the sum of the height and depth of \type {strut}, which is
716%D an invisible blob that can be used to enforce the proper dimensions.
717%D
718%D Such a blob, when placed at the beginning of a paragraph can have side effects
719%D that can be prevented with \type {\dontleavehmode}. Never use \type
720%D {\leavevmode}!
721
722\newdimension\strutdimen        % not used
723\newdimension\lineheight
724\newdimension\openlineheight
725\newdimension\openstrutheight
726\newdimension\openstrutdepth
727\newdimension\topskipgap
728
729\newdimension\strutheight
730\newdimension\strutdepth
731\newdimension\struttotal
732\newdimension\strutwidth
733
734\let\m_spac_vertical_baseline_stretch_factor \zerocount
735\let\m_spac_vertical_baseline_shrink_factor  \zerocount
736
737\mutable\def\strutheightfactor   {.72}
738\mutable\def\strutdepthfactor    {.28}
739\mutable\def\baselinefactor      {2.8}
740\mutable\def\topskipfactor       {1.0}
741\mutable\def\maxdepthfactor      {0.5}
742\mutable\let\ntopskipfactor      \minusone
743
744\mutable\def\minimumstrutheight  {\zeropoint}
745\mutable\def\minimumstrutdepth   {\zeropoint}
746
747\mutable\def\normallineheight    {\baselinefactor\exheight}
748\mutable\def\minimumlinedistance {\lineskip}
749
750\mutable\let\spacingfactor        \plusone
751
752\mutable\def\systemtopskipfactor {\topskipfactor}
753\mutable\def\systemmaxdepthfactor{\maxdepthfactor}
754
755\ifdefined\globalbodyfontsize \else
756    \newdimension\globalbodyfontsize
757    \globalbodyfontsize=12pt
758\fi
759
760\ifdefined\normalizedbodyfontsize \else
761    \def\normalizedbodyfontsize{12pt}
762\fi
763
764\permanent\protected\def\topskipcorrection
765  {\simpletopskipcorrection
766   \vskip-\struttotal
767   \verticalstrut}
768
769\permanent\protected\def\simpletopskipcorrection
770  {\ifdim\topskip>\openstrutheight
771     % == \vskip\topskipgap
772     \vskip\topskip
773     \vskip-\openstrutheight
774   \fi}
775
776% \permanent\protected\def\settopskip % the extra test is needed for the lbr family
777%   {\topskip
778%      \ifgridsnapping
779%        \zeropoint
780%      \else
781%        \systemtopskipfactor\globalbodyfontsize
782%        \ifcase\bottomraggednessmode % ragged bottom
783%          \s!plus
784%          \ifnum\ntopskipfactor<\zerocount
785%            5\globalbodyfontsize % old hard coded value
786%          \else
787%             \ntopskipfactor\openlineheight
788%          \fi
789%        \fi
790%    \fi
791%    %\relax
792%    \topskipgap\topskip
793%    \advanceby\topskipgap -\openstrutheight\relax
794%    \ifdim\minimumstrutheight>\zeropoint
795%      \ifdim\topskip<\minimumstrutheight
796%        \topskip\minimumstrutheight\relax
797%      \fi
798%    \else
799%      \ifdim\topskip<\strutheightfactor\openlineheight
800%        \topskip\strutheightfactor\openlineheight\relax
801%      \fi
802%    \fi}
803
804\permanent\protected\def\settopskip % the extra test is needed for the lbr family
805  {\topskip
806     \ifgridsnapping
807       \zeroskip
808       \initialpageskip\zeroskip
809     \else
810       \systemtopskipfactor\globalbodyfontsize
811       \relax
812       \initialpageskip\zeropoint
813         \ifcase\bottomraggednessmode % ragged bottom
814           \s!plus \ntopskipfactor\openlineheight
815         \fi
816       \relax
817   \fi
818   \topskipgap\topskip
819   \advanceby\topskipgap -\openstrutheight\relax
820   \ifdim\minimumstrutheight>\zeropoint
821     \ifdim\topskip<\minimumstrutheight
822       \topskip\minimumstrutheight\relax
823     \fi
824   \else
825     \ifdim\topskip<\strutheightfactor\openlineheight
826       \topskip\strutheightfactor\openlineheight\relax
827     \fi
828   \fi}
829
830\permanent\protected\def\setmaxdepth
831  {\maxdepth\systemmaxdepthfactor\globalbodyfontsize}
832
833\newgluespec \usedbaselineskip  % These used to be \normal... but that isn't pretty
834\newgluespec \usedlineskip      % in the token interface, so these few now have new
835\newdimension\usedlineskiplimit % names. They are public but not really user commands.
836
837\permanent\protected\def\normalbaselines
838  {\baselineskip \usedbaselineskip
839   \lineskip     \usedlineskip
840   \lineskiplimit\usedlineskiplimit}
841
842% \permanent\protected\def\flexiblebaselines
843%   {\baselineskip  \usedbaselineskip
844%    \lineskip     1\usedlineskip \s!plus 1\s!fill
845%    \lineskiplimit \usedlineskiplimit}
846
847\permanent\protected\def\flexiblebaselines
848  {\baselineskip 1\usedbaselineskip \s!plus 1\s!fill
849   \lineskip      \usedlineskip
850   \lineskiplimit \usedlineskiplimit}
851
852\permanent\protected\def\setnormalbaselines % used in overload
853  {\ifdim\normallineheight>\zeropoint
854     \lineheight\normallineheight
855   \fi
856   \openlineheight\spacingfactor\lineheight
857   \openstrutheight \ifdim\minimumstrutheight>\zeropoint
858     \minimumstrutheight % new
859   \else
860     \strutheightfactor\openlineheight
861   \fi
862   \openstrutdepth \ifdim\minimumstrutdepth>\zeropoint
863     \minimumstrutdepth % new
864   \else
865     \strutdepthfactor \openlineheight
866   \fi
867   \ifdim\dimexpr\minimumstrutdepth+\minimumstrutheight\relax>\zeropoint
868     \openlineheight\dimexpr\openstrutheight+\openstrutdepth\relax % new
869   \fi
870   \usedbaselineskip\openlineheight
871     \ifgridsnapping\else
872       \s!plus \m_spac_vertical_baseline_stretch_factor\openlineheight
873       \s!minus\m_spac_vertical_baseline_shrink_factor \openlineheight
874     \fi
875   \usedlineskip\minimumlinedistance\relax % \onepoint\relax
876   \usedlineskiplimit\zeropoint\relax
877   \normalbaselines}
878
879\permanent\protected\def\spacing#1% vertical
880  {\ifgridsnapping
881     \let\spacingfactor\plusone
882   \else
883     \permanent\edef\spacingfactor{#1}%
884   \fi
885   \edef\systemtopskipfactor {\thewithoutunit\dimexpr#1\dimexpr\topskipfactor \points}%
886   \edef\systemmaxdepthfactor{\thewithoutunit\dimexpr#1\dimexpr\maxdepthfactor\points}%
887   \setnormalbaselines
888   \setstrut}
889
890% \protected\def\forgetverticalstretch % \forgetspacing
891%   {\spacing\plusone}
892
893\permanent\protected\def\forgetverticalstretch
894  {\let\spacingfactor       \plusone
895   \let\systemtopskipfactor \topskipfactor
896   \let\systemmaxdepthfactor\maxdepthfactor
897   \setnormalbaselines
898   \setstrut}
899
900\appendtoks
901    \forgetverticalstretch
902\to \everyforgetall % needed in otr
903
904%D Sometimes one needs to freeze the interlinespacing
905%D
906%D \starttyping
907%D \rm \saveinterlinespace .... {\ss \restoreinterlinespace .... \endgraf}
908%D \stoptyping
909%D
910%D This is no longer needed.
911
912\aliased\let\restoreinterlinespace\relax
913
914\permanent\protected\def\saveinterlinespace
915  {\enforced\permanent\protected\edef\restoreinterlinespace
916     {\lineheight         \the\lineheight
917      \openstrutheight    \the\openstrutheight
918      \openstrutdepth     \the\openstrutdepth
919      \openlineheight     \the\openlineheight
920      \usedbaselineskip   \the\usedbaselineskip
921      \usedlineskip       \the\usedlineskip
922      \usedlineskiplimit  \the\usedlineskiplimit
923      \noexpand\def\noexpand\normallineheight{\the\dimexpr\normallineheight}%
924      \noexpand\normalbaselines}}
925
926%D This is the plain definition:
927%D
928%D \starttyping
929%D \def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
930%D \stoptyping
931%D
932%D which could be:
933%D
934%D \starttyping
935%D \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
936%D \stoptyping
937%D
938%D But we do things differently.
939
940\newbox\b_strut_box
941\newbox\b_strut_tmp
942
943\permanent\protected\def\strutbox % not to be used but this is sort of an alias
944  {\beginlocalcontrol
945   \setbox\b_strut_tmp\hpack{\normalsrule\s!height\strutht\s!depth\strutdp}% just a start
946   \endlocalcontrol
947   \b_strut_tmp}
948
949%D The double \type {\hbox} construction enables us to backtrack boxes.
950
951% \overloaded\let\strutht  \undefined \newdimension\strutht    % see above
952% \overloaded\let\strutdp  \undefined \newdimension\strutdp
953% \overloaded\let\struthtdp\undefined \newdimension\struthtdp
954
955\permanent\protected\def\setstrut
956  {\ifgridsnapping
957     \setstrutgridyes
958   \else
959     \setstrutgridnop
960   \fi}
961
962\permanent\protected\def\setstrutgridyes
963  {\strutht\spacingfactor\dimexpr
964     \ifdim\minimumstrutheight>\zeropoint
965       \minimumstrutheight
966     \else
967       \strutheightfactor\dimexpr\normallineheight
968     \fi
969   \relax
970   \strutdp\dimexpr
971     \ifdim\minimumstrutdepth>\zeropoint
972       \minimumstrutdepth
973     \else
974       \normallineheight-\strutht
975     \fi
976   \relax
977   \dosetstrut}
978
979\permanent\protected\def\setstrutgridnop
980  {\strutht\spacingfactor\dimexpr
981     \ifdim\minimumstrutheight>\zeropoint
982       \minimumstrutheight
983     \else
984       \strutheightfactor\dimexpr\normallineheight
985     \fi
986   \relax
987   \strutdp\spacingfactor\dimexpr
988     \ifdim\minimumstrutdepth>\zeropoint
989       \minimumstrutdepth
990     \else
991       \strutdepthfactor\dimexpr\normallineheight
992     \fi
993   \relax
994   \dosetstrut}
995
996\permanent\protected\def\setcharstrut#1%
997  {\setbox\b_strut_box\hbox{#1}% no \hpack, in case we have smallcaps
998   \strutht\ht\b_strut_box
999   \strutdp\dp\b_strut_box
1000   \dosetstrut}
1001
1002\permanent\protected\def\settightstrut
1003  {\setcharstrut{(}}
1004
1005\permanent\protected\def\setfontstrut
1006  {\setcharstrut{(gplQT}}
1007
1008\permanent\protected\def\setcapstrut% could be M, but Q has descender
1009  {\setcharstrut{Q}}
1010
1011%D Handy for math (used in mathml):
1012
1013\permanent\protected\def\charhtstrut
1014  {\begingroup
1015   \setcharstrut{GJY}%
1016   \normalsrule
1017     \s!depth \zeropoint
1018     \s!height\strutht
1019   \endgroup}
1020
1021\permanent\protected\def\chardpstrut
1022  {\begingroup
1023   \setcharstrut{gjy}%
1024   \normalsrule
1025     \s!depth \strutdp
1026     \s!height\zeropoint
1027   \endgroup}
1028
1029%D Because of all the callbacks in mkiv, we avoid unnecessary boxes ... maybe use an
1030%D attribute so that we can tag boxes that don't need a treatment; tests with using
1031%D an attribute so far have shown that it's slower because testing the attribute
1032%D takes time too.
1033
1034\permanent\protected\def\dosetstrut
1035  {\enforced\let\strut\normalstrut
1036   \struthtdp\dimexpr\strutht+\strutdp\relax
1037   \ifabsnum\dimexpr\struthtdp-\lineheight\relax<\plustwo
1038     % compensate rounding error /- 1sp to avoid too many
1039     % 1sp baselineskips in for instance verbatim
1040     % \strutht\dimexpr\lineheight-\strutdp\relax
1041     % better:
1042     \strutdp\dimexpr\lineheight-\strutht\relax
1043     \struthtdp\lineheight
1044   \fi
1045   \strutheight\strutht
1046   \strutdepth \strutdp
1047   \struttotal \struthtdp}
1048
1049\newconstant\c_strut_visual_mode
1050
1051%D The dimen \type {\struttotal} holds the exact size of the strut; occasionally a
1052%D one scaled point difference can show up with the lineheight. This is more
1053%D efficient (less callbacks):
1054
1055\permanent\protected\def\strut % still callbacks for \hbox{\strut}
1056  {\relax
1057   \dontleavehmode
1058   \normalsrule
1059      \s!height\strutht
1060      \s!depth \strutdp
1061   \relax}
1062
1063\aliased\let\normalstrut\strut
1064
1065\permanent\protected\def\halfstrut
1066  {\relax
1067   \dontleavehmode
1068   \normalsrule
1069      \s!height.5\strutht
1070      \s!depth .5\strutdp
1071   \relax}
1072
1073\permanent\protected\def\quarterstrut
1074  {\relax
1075   \dontleavehmode
1076   \normalsrule
1077      \s!height.25\strutht
1078      \s!depth .25\strutdp
1079   \relax}
1080
1081\permanent\protected\def\depthstrut
1082  {\relax
1083   \dontleavehmode
1084   \normalsrule
1085      \s!height\dimexpr\strutht-\struthtdp/\plustwo\relax
1086      \s!depth \strutdp
1087   \relax}
1088
1089\permanent\protected\def\halflinestrut
1090  {\relax
1091   \dontleavehmode
1092   \normalsrule
1093      \s!height\dimexpr\strutht-.5\struthtdp\relax
1094      \s!depth \strutdp
1095   \relax}
1096
1097\permanent\protected\def\noheightstrut
1098  {\relax
1099   \dontleavehmode
1100   \normalsrule
1101      \s!height\zeropoint
1102      \s!depth \strutdp
1103   \relax}
1104
1105\permanent\protected\def\nodepthstrut
1106  {\relax
1107   \dontleavehmode
1108   \normalsrule
1109      \s!height\strutht
1110      \s!depth \zeropoint
1111   \relax}
1112
1113%D Sometimes a capstrut comes in handy
1114%D
1115%D \starttabulate[|Tl|l|l|]
1116%D \NC yes          \NC normal strut               \NC {\showstruts\setupstrut[yes]\strut}  \NC \NR
1117%D \NC no           \NC no strut                   \NC {\showstruts\setupstrut[no]\strut}  \NC \NR
1118%D \NC kap          \NC a capital strut (i.e. Q)   \NC {\showstruts\setupstrut[cap]\strut} \NC \NR
1119%D \NC A B \unknown \NC a character strut (e.g. A) \NC {\showstruts\setupstrut[A]\strut}   \NC \NR
1120%D \NC              \NC a normal strut             \NC {\showstruts\setupstrut\strut}      \NC \NR
1121%D \stoptabulate
1122%D
1123%D Beware: using an unknown value results in char struts.
1124
1125\installcorenamespace{struts}
1126
1127\permanent\tolerant\protected\def\setupstrut[#1]%
1128  {\edef\m_strut{#1}%
1129   \ifcsname\??struts\m_strut\endcsname
1130     \lastnamedcs
1131   \else
1132     \setcharstrut\m_strut
1133   \fi}
1134
1135\permanent\protected\def\synchronizestrut#1% no [] parsing, faster for internal
1136  {\edef\m_strut{#1}%
1137   \ifcsname\??struts\m_strut\endcsname
1138     \lastnamedcs
1139   \else
1140     \setcharstrut\m_strut
1141   \fi}
1142
1143\permanent\protected\def\dosynchronizestrut#1% no [] parsing, faster for internal
1144  {\ifcsname\??struts#1\endcsname
1145     \lastnamedcs
1146   \else
1147     \setcharstrut{#1}%
1148   \fi}
1149
1150\permanent\protected\def\showstruts % adapts .. is wrong
1151  {\showmakeup[strut]%
1152   \settestcrlf}
1153
1154\aliased\let\showcolorstruts\showstruts
1155
1156\mutable\def\autostrutfactor{1.1}
1157
1158\permanent\protected\def\setautostrut
1159  {\begingroup
1160   \setbox\scratchbox\copy\b_strut_box
1161   \setstrut
1162   \ifdim\strutht>\autostrutfactor\ht\scratchbox
1163     \endgroup \setstrut
1164   \orelse\ifdim\strutdp>\autostrutfactor\dp\scratchbox
1165     \endgroup \setstrut
1166   \else
1167     \endgroup
1168   \fi}
1169
1170\newbox\nostrutbox \setbox\nostrutbox\emptyhbox
1171
1172\newtoks\everysetnostrut
1173
1174\permanent\protected\def\setnostrut
1175  {\expandtoks\everysetnostrut}
1176
1177\appendtoks
1178 %  \setbox\strutbox\copy\nostrutbox
1179    \enforced\lettonothing\strut
1180    \enforced\lettonothing\endstrut
1181    \enforced\lettonothing\begstrut
1182\to \everysetnostrut
1183
1184%D When enabled, sigstruts will remove themselves if nothing goes inbetween. For
1185%D practical reasons we define some boundary characters here.
1186
1187\permanent\protected\def\leftboundary   {\protrusionboundary\plusone}
1188\permanent\protected\def\rightboundary  {\protrusionboundary\plustwo}
1189\permanent\protected\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals
1190
1191%D \starttyping
1192%D $ \ifhmode H1\fi x \ifhmode H2\fi $\par
1193%D $ \ifmmode M1\fi x \ifmmode M2\fi $\par
1194%D $$\ifvmode H1\fi x \ifvmode H2\fi$$\par
1195%D $$\ifvmode M1\fi x \ifvmode M2\fi$$\par
1196%D \stoptyping
1197
1198\permanent\protected\def\begstrut
1199  {\ifmmode
1200     \strut
1201   \else
1202     \dontleavehmode
1203     \ifcase\struthtdp\else
1204       \spac_struts_beg
1205     \fi
1206   \fi
1207   \ignorespaces}
1208
1209\def\spac_struts_beg
1210  {\boundary\plusone
1211   \strut
1212  %\boundary\plusone
1213   \penalty\plustenthousand
1214  %\boundary\plusone
1215   \hskip\zeroskip}
1216
1217\permanent\protected\def\endstrut
1218  {% \ifmmode M\fi
1219   % \ifinner I\fi
1220   \relax\ifhmode
1221    %\removeunwantedspaces
1222     \spac_helpers_remove_unwantedspace
1223     \ifcase\struthtdp\else
1224       \spac_struts_end
1225     \fi
1226   \orelse\ifmmode
1227    %\removeunwantedspaces hmode only anyway
1228     \spac_helpers_remove_unwantedspace
1229     \strut
1230   \fi}
1231
1232\def\spac_struts_end
1233  {\penalty\plustenthousand
1234  %\boundary\plustwo
1235   \hskip\zeroskip
1236  %\boundary\plustwo
1237   \strut
1238   \boundary\plustwo}
1239
1240% unsave:
1241%
1242% \def\pseudostrut
1243%   {\bgroup
1244%    \setnostrut
1245%    \normalstrut
1246%    \egroup}
1247%
1248% try:
1249%
1250% \startchemie
1251%   \chemie[ONE,Z0,SB15,MOV1,SB15,Z0][C,C]
1252% \stopchemie
1253%
1254% so:
1255
1256\permanent\protected\def\pseudostrut
1257  {\noindent} % better: \dontleavehmode
1258
1259\aliased\let\pseudobegstrut\pseudostrut
1260\aliased\let\pseudoendstrut\removeunwantedspaces
1261
1262\permanent\protected\def\resetteststrut
1263  {\strutwidth\zeropoint
1264   \setstrut}
1265
1266\ifdefined\setfontparameters \else
1267    \def\setfontparameters{\expandtoks\everybodyfont}
1268\fi
1269
1270%D Keyword based strutting:
1271
1272\letcsname\??struts\v!yes    \endcsname\setstrut
1273\letcsname\??struts\v!auto   \endcsname\setautostrut
1274\letcsname\??struts\v!no     \endcsname\setnostrut
1275\letcsname\??struts\v!cap    \endcsname\setcapstrut
1276\letcsname\??struts\v!fit    \endcsname\setfontstrut
1277\letcsname\??struts\v!line   \endcsname\setstrut
1278\letcsname\??struts\s!default\endcsname\setstrut
1279\letcsname\??struts\empty    \endcsname\setstrut
1280
1281%D Handy:
1282
1283\permanent\def\baselinedistance{\the\lineheight}
1284
1285%D We need \type {\normaloffinterlineskip} because the new definition contains an
1286%D assignment, and |<|don't ask me why|>| this assignment gives troubles in for
1287%D instance the visual debugger.
1288
1289\pushoverloadmode
1290
1291\overloaded\permanent\protected\def\offinterlineskip % later we will overload this with a push pop
1292  {\baselineskip \ignoredepthcriterion % -\thousandpoint
1293   \lineskip     \zeroskip
1294   \lineskiplimit\maxdimen
1295   % We also need this here now; thanks to taco for figuring that out!
1296   \let\minimumlinedistance\zeropoint}
1297
1298\overloaded\permanent\protected\def\nointerlineskip
1299  {\prevdepth\ignoredepthcriterion}% -\thousandpoint
1300
1301\aliased\let\normaloffinterlineskip\offinterlineskip % knuth's original
1302
1303\popoverloadmode
1304
1305%D This is tricky. The prevdepth value is still set to the last one even if there is
1306%D nothing on the page. The same is true for prevgraf, which doesn't resemble the
1307%D value on the current page.
1308%D
1309%D So, here we kick in a checker but it has to happen after the output group and it
1310%D only has to be done once (output can trigger itself!).
1311%D
1312%D However, prevgraf is somehow bound to hangindent so we can get very nasty side
1313%D effects. So, in tne end we use our own variable!
1314
1315\ifdefined\getnofpreviouslines
1316    % defined public at the lua end
1317\else
1318    \let\getnofpreviouslines\!!zerocount
1319\fi
1320
1321\protected\def\page_otr_synchronize_page_yes
1322  {\aftergroup\page_otr_synchronize_page_indeed
1323   \global\enforced\let\page_otr_synchronize_page\relax}
1324
1325% This has to become an otr method: \s!page_otr_command_synchonize_page
1326
1327\protected\def\page_otr_synchronize_page_indeed
1328  {\ifx\currentoutputroutine\s!multicolumn\else\clf_synchronizepage\fi
1329   \global\enforced\let\page_otr_synchronize_page\page_otr_synchronize_page_yes}
1330
1331\let\page_otr_synchronize_page\page_otr_synchronize_page_yes
1332
1333\appendtoks
1334    \page_otr_synchronize_page
1335\to \everyaftershipout
1336
1337%D My own one:
1338
1339\protected\def\spac_helpers_push_interlineskip_yes
1340  {\enforced\edef\oninterlineskip
1341     {\baselineskip \the\baselineskip
1342      \lineskip     \the\lineskip
1343      \lineskiplimit\the\lineskiplimit
1344      \noexpand\edef\noexpand\minimumlinedistance{\the\dimexpr\minimumlinedistance}%
1345      \enforced\let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed
1346
1347\protected\def\spac_helpers_push_interlineskip_nop
1348  {\enforced\let\oninterlineskip\setnormalbaselines}
1349
1350\pushoverloadmode
1351
1352\overloaded\permanent\protected\def\offinterlineskip
1353  {\ifdim\baselineskip>\zeropoint
1354     \spac_helpers_push_interlineskip_yes
1355   \else
1356     \spac_helpers_push_interlineskip_nop
1357   \fi
1358   \normaloffinterlineskip}
1359
1360\permanent\let\oninterlineskip\relax
1361
1362\popoverloadmode
1363
1364\permanent\protected\def\resetpenalties#1%
1365  {\ifdefined#1%
1366     \frozen#1\minusone
1367   \fi}
1368
1369\permanent\protected\def\setpenalties#1#2#3%
1370  {\ifdefined#1% space before #3 prevents lookahead problems, needed when #3=text
1371     \frozen#1\numexpr#2+\plusone\relax\space\expandedrepeat\numexpr#2\relax{ #3}\zerocount\relax
1372   \fi}
1373
1374%D \macros
1375%D   {keeplinestogether}
1376%D
1377%D Dirty hack, needed in margin content that can run of a page.
1378
1379% just before margintexts ... will eventually be done differently in mkiv using
1380% attributes
1381
1382\newinteger\c_spac_keep_lines_together
1383
1384\permanent\protected\lettonothing\restoreinterlinepenalty
1385
1386\protected\def\spac_penalties_restore
1387  {\enforced\protected\glettonothing\restoreinterlinepenalty
1388   \overloaded\global\resetpenalties\interlinepenalties
1389   \global\c_spac_keep_lines_together\zerocount}
1390
1391\permanent\protected\def\keeplinestogether#1%
1392  {\ifnum#1>\c_spac_keep_lines_together
1393     \global\c_spac_keep_lines_together#1%
1394     \overloaded\global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand
1395     \global\enforced\let\restoreinterlinepenalty\spac_penalties_restore
1396   \fi}
1397
1398%D Here now only deal with penalties that relate to vertical breaking; the
1399%D horizontal ones have been moved to spac-pas.
1400
1401\immutable\integerdef\defaultdisplaywidowpenalty       50
1402\immutable\integerdef\defaultwidowpenalty            2000 % was: 1000
1403\immutable\integerdef\defaultclubpenalty             2000 % was:  800
1404\immutable\integerdef\defaultbrokenpenalty            100
1405
1406\immutable\integerdef\defaultgriddisplaywidowpenalty \zerocount
1407\immutable\integerdef\defaultgridwidowpenalty        \zerocount
1408\immutable\integerdef\defaultgridclubpenalty         \zerocount
1409\immutable\integerdef\defaultgridbrokenpenalty       \zerocount
1410
1411% \linebreakcriterion\optimallinebreakcriterion
1412% \divide \adjdemerits \plustwo
1413
1414\permanent\protected\def\nopenalties
1415  {\frozen\widowpenalty \zerocount
1416   \frozen\clubpenalty  \zerocount
1417   \frozen\brokenpenalty\zerocount}
1418
1419\permanent\protected\def\setdefaultpenalties
1420  {\directsetup{\systemsetupsprefix\s!default}}
1421
1422\startsetups [\systemsetupsprefix\s!reset]
1423    \resetpenalties\widowpenalties
1424    \resetpenalties\clubpenalties
1425    \resetpenalties\interlinepenalties
1426\stopsetups
1427
1428%D We use \directsetup because it's faster and we know there is no csl:
1429
1430\startsetups [\systemsetupsprefix\s!default]
1431
1432    \directsetup{\systemsetupsprefix\s!reset}
1433
1434    \frozen\widowpenalty        \defaultwidowpenalty
1435    \frozen\clubpenalty         \defaultclubpenalty
1436    \frozen\displaywidowpenalty \defaultdisplaywidowpenalty
1437    \frozen\brokenpenalty       \defaultbrokenpenalty
1438
1439\stopsetups
1440
1441\startsetups [\v!grid] [\systemsetupsprefix\s!default]
1442
1443    \directsetup{\systemsetupsprefix\s!reset}
1444
1445    \frozen\widowpenalty        \defaultgridwidowpenalty
1446    \frozen\clubpenalty         \defaultgridclubpenalty
1447    \frozen\displaywidowpenalty \defaultgriddisplaywidowpenalty
1448    \frozen\brokenpenalty       \defaultgridbrokenpenalty
1449
1450\stopsetups
1451
1452%D As an illustration:
1453
1454\startsetups [\systemsetupsprefix\v!strict]
1455
1456    \directsetup{\systemsetupsprefix\s!reset}
1457
1458    \setpenalties \widowpenalties      \plustwo  \maxdimen
1459    \setpenalties \clubpenalties       \plustwo  \maxdimen
1460    \setpenalties \orphanpenalties     \zerocount
1461          \frozen \brokenpenalty                 \maxdimen
1462
1463\stopsetups
1464
1465%D To be checked:
1466
1467% \newbox\b_spac_struts_saved
1468%
1469% \permanent\protected\def\savestrut {\setbox\b_spac_struts_saved\copy\b_strut_box}
1470% \permanent\protected\def\savedstrut{\copy  \b_spac_struts_saved}
1471
1472%D Good old blank redone:
1473
1474%definesystemattribute[kernchars]    [public]
1475\definesystemattribute[skipcategory] [public]
1476\definesystemattribute[skippenalty]  [public]
1477\definesystemattribute[skiporder]    [public]
1478\definesystemattribute[snapmethod]   [public]
1479\definesystemattribute[snapvbox]     [public]
1480%definesystemattribute[snapcategory] [public]
1481
1482% TODO: NAMED SNAPPERS
1483
1484\installcorenamespace{gridsnappers}
1485\installcorenamespace{gridsnapperattributes}
1486\installcorenamespace{gridsnappersets}
1487
1488% \newgluespec \bodyfontlineheight  % see top
1489% \newdimension\bodyfontstrutheight % see top
1490% \newdimension\bodyfontstrutdepth  % see top
1491
1492% \newgluespec \globalbodyfontlineheight  % see top
1493% \newdimension\globalbodyfontstrutheight % see top
1494% \newdimension\globalbodyfontstrutdepth  % see top
1495
1496\permanent\def\snappedvboxattribute{\ifgridsnapping attr\snapvboxattribute\c_attr_snapmethod\fi}
1497\permanent\def\setlocalgridsnapping{\ifgridsnapping \c_attr_snapvbox \c_attr_snapmethod\fi}
1498
1499\def\spac_grids_set_local_snapping#1%
1500  {\ifgridsnapping
1501     \ifempty{#1}\else
1502       \spac_grids_snap_value_set{#1}%
1503       \c_attr_snapvbox\c_attr_snapmethod
1504     \fi
1505   \fi}
1506
1507\def\spac_grids_expand_snapper#1%
1508  {\edef\m_spac_snapper
1509     {\ifempty\m_spac_snapper\else\m_spac_snapper,\fi
1510      \ifcsname\??gridsnappersets#1\endcsname\lastnamedcs\else#1\fi}}
1511
1512\permanent\protected\def\installsnapvalues#1#2%
1513  {\lettonothing\m_spac_snapper
1514   \rawprocesscommacommand[#2]\spac_grids_expand_snapper
1515   \edef\p_spac_snapper{#1:\m_spac_snapper}%
1516   \ifcsname\??gridsnapperattributes\p_spac_snapper\endcsname
1517     \scratchcounter\lastnamedcs % already defined
1518   \else
1519     \scratchcounter\clf_definesnapmethod{#1}{\m_spac_snapper}%
1520     \edefcsname\??gridsnapperattributes\p_spac_snapper\endcsname{\the\scratchcounter}%
1521   \fi
1522   \edefcsname\??gridsnappers#1\endcsname{\c_attr_snapmethod\the\scratchcounter\relax}%
1523   \letcsname\??gridsnappersets#1\endcsname\m_spac_snapper}
1524
1525\permanent\def\theexpandedsnapperset#1{\begincsname\??gridsnappersets#1\endcsname} % only for manuals
1526
1527\permanent\protected\def\usegridparameter#1% no checking here
1528  {\edef\m_spac_grid_asked{#1\c!grid}%
1529   \ifempty\m_spac_grid_asked
1530     \c_attr_snapvbox\attributeunsetvalue
1531   \else
1532     \spac_grids_snap_value_set\m_spac_grid_asked
1533     \c_attr_snapvbox\c_attr_snapmethod
1534   \fi}
1535
1536\permanent\tolerant\protected\def\definegridsnapping[#1]#*[#2]%
1537  {\installsnapvalues{#1}{#2}}
1538
1539\edef\spac_grids_snap_value_reset
1540  {%\gridsnappingfalse
1541   \c_attr_snapmethod\attributeunsetvalue}
1542
1543\def\spac_grids_snap_value_set#1%
1544  {%\gridsnappingtrue
1545   \begincsname\??gridsnappers#1\endcsname}
1546
1547% maybe:
1548%
1549% \def\spac_grids_snap_value_set#1%
1550%   {%\gridsnappingtrue
1551%    \ifcsname\??gridsnappers#1\endcsname
1552%      \lastnamedcs
1553%    \else
1554%      \definegridsnapping[#1][#1]%
1555%      \begincsname\??gridsnappers#1\endcsname
1556%    \fi}
1557
1558\def\spac_grids_snap_value_auto#1%
1559  {\ifcsname\??gridsnappers#1\endcsname
1560     \lastnamedcs
1561   \else
1562     \installsnapvalues\s!dummy{#1}%
1563     \csname\??gridsnappers\s!dummy\endcsname
1564   \fi}
1565
1566% \installsnapvalues{loose} {\v!maxdepth:0.8,\v!maxheight:0.8,\v!strut}
1567% \installsnapvalues{normal}{\v!maxdepth:1.0,\v!maxheight:1.0,\v!strut}
1568% \installsnapvalues{tight} {\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut}
1569
1570% none             don't enlarge
1571% halfline         enlarge by halfline/halfline
1572% line             enlarge by line/line
1573% strut            enlarge by ht/dp (default)
1574% first            align to top line
1575% last             align to bottom line
1576% mindepth         round depth down
1577% maxdepth         round depth up
1578% minheight        round height down
1579% maxheight        round height up
1580% local            use local interline space
1581% offset:-3tp      vertical shift within box
1582% bottom:lines
1583% top:lines
1584% box              centers a box rounded upwards (box:.5 -> tolerance)
1585% min              centers a box rounded downwards
1586% max              centers a box rounded upwards
1587
1588%D We're not downward compatible with \MKII ! Not yet in interface file:
1589
1590\definegridsnapping[\v!normal]           [\v!maxheight,\v!maxdepth,\v!strut]
1591\definegridsnapping[\v!standard]         [\v!maxheight,\v!maxdepth,\v!strut]
1592\definegridsnapping[\v!yes]              [\v!maxheight,\v!maxdepth,\v!strut]
1593
1594\definegridsnapping[\v!strict]           [\v!maxdepth:0.8,\v!maxheight:0.8,\v!strut]
1595\definegridsnapping[\v!tolerant]         [\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut]
1596\definegridsnapping[\v!verytolerant]     [\v!maxdepth:1.4,\v!maxheight:1.4,\v!strut]
1597
1598\definegridsnapping[\v!tolerant:10]      [\v!maxdepth:1.1,\v!maxheight:1.1,\v!strut] % 10 pct tolerance
1599\definegridsnapping[\v!tolerant:20]      [\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut] % 20 pct tolerance
1600\definegridsnapping[\v!tolerant:30]      [\v!maxdepth:1.3,\v!maxheight:1.3,\v!strut] % 30 pct tolerance
1601\definegridsnapping[\v!tolerant:40]      [\v!maxdepth:1.4,\v!maxheight:1.4,\v!strut] % 40 pct tolerance
1602
1603\definegridsnapping[\v!top]              [\v!minheight,\v!maxdepth,\v!strut]
1604\definegridsnapping[\v!bottom]           [\v!maxheight,\v!mindepth,\v!strut]
1605\definegridsnapping[\v!both]             [\v!minheight,\v!mindepth,\v!strut]
1606
1607\definegridsnapping[\v!broad]            [\v!maxheight,\v!maxdepth,\v!strut,0.8] % maybe 0.85
1608\definegridsnapping[\v!fit]              [\v!maxheight,\v!maxdepth,\v!strut,1.2] % tight 0.15
1609
1610\definegridsnapping[\v!first]            [\v!first]
1611\definegridsnapping[\v!last]             [\v!last]
1612\definegridsnapping[\v!high]             [\v!minheight,\v!maxdepth,\v!none]
1613\definegridsnapping[\v!one]              [\v!minheight,\v!mindepth]
1614\definegridsnapping[\v!low]              [\v!maxheight,\v!mindepth,\v!none]
1615\definegridsnapping[\v!none]             [\v!none]
1616\definegridsnapping[\v!line]             [\v!line]
1617\definegridsnapping[\v!strut]            [\v!strut]
1618\definegridsnapping[\v!box]              [\v!box]
1619\definegridsnapping[\v!min]              [\v!min]
1620\definegridsnapping[\v!max]              [\v!max]
1621
1622\definegridsnapping[\v!middle]           [\v!maxheight,\v!maxdepth] % used in placement
1623
1624\definegridsnapping[\v!math]             [\v!maxdepth:1.05,\v!maxheight:1.05,\v!strut] % experimental, maybe 1.1
1625\definegridsnapping[\v!math:\v!line]     [\v!math,\v!line,\v!split]
1626\definegridsnapping[\v!math:\v!halfline] [\v!math,\v!halfline,\v!split]
1627\definegridsnapping[\v!math:-\v!line]    [\v!math,-\v!line,\v!split]
1628\definegridsnapping[\v!math:-\v!halfline][\v!math,-\v!halfline,\v!split]
1629
1630\permanent\protected\def\synchronizelocallinespecs
1631  {\bodyfontlineheight \normallineheight
1632   \bodyfontstrutheight\strutht
1633   \bodyfontstrutdepth \strutdp}
1634
1635\permanent\protected\def\synchronizegloballinespecs
1636  {\global\globalbodyfontlineheight \normallineheight
1637   \global\globalbodyfontstrutheight\strutht
1638   \global\globalbodyfontstrutdepth \strutdp}
1639
1640\appendtoks
1641    \synchronizegloballinespecs
1642    \synchronizelocallinespecs
1643\to \everysetupglobalinterlinespace
1644
1645\appendtoks
1646    \synchronizelocallinespecs
1647\to \everysetuplocalinterlinespace
1648
1649%D More might be added here:
1650
1651\def\restoreglobalinterlinespace
1652  {\mutable\let\normallineheight\globalbodyfontlineheight
1653   \bodyfontlineheight \globalbodyfontlineheight
1654   \bodyfontstrutheight\globalbodyfontstrutheight
1655   \bodyfontstrutdepth \globalbodyfontstrutdepth}
1656
1657% \appendtoks
1658%     \restoreglobalinterlinespace % done elsewhere
1659% \to \everybeforepagebody
1660
1661%D We still have to synchronize these:
1662
1663\permanent\protected\def\synchronizeskipamounts
1664  {\bigskipamount
1665                 \skipfactor\baselineskip
1666      \s!plus\skipgluefactor\baselineskip
1667     \s!minus\skipgluefactor\baselineskip
1668   \relax
1669   \medskipamount  \bigskipamount \divideby\medskipamount  \plustwo
1670   \smallskipamount\bigskipamount \divideby\smallskipamount\plusfour}
1671
1672%D Snapping.
1673
1674% \newif\ifgridsnapping % already defined
1675
1676\permanent\tolerant\protected\def\startgridsnapping[#1]%
1677  {\snaptogrid[#1]\vbox\bgroup}
1678
1679\permanent\protected\def\stopgridsnapping
1680  {\egroup}
1681
1682\permanent\tolerant\protected\def\placeongrid[#1]%
1683  {\snaptogrid[#1]\vbox} % mark as done
1684
1685\permanent\tolerant\protected\def\snaptogrid[#1]% list or predefined
1686  {\ifgridsnapping
1687     \expandafter\spac_grids_snap_to_indeed % todo: move inline
1688   \else
1689     \expandafter\gobbleoneargument
1690   \fi{#1}}
1691
1692\def\spac_grids_snap_to_indeed#1%
1693  {\bgroup
1694   \spac_grids_snap_value_reset
1695   \dowithnextbox{\spac_grids_snap_to_finish{#1}}}
1696
1697% eventually there will always be a line snap
1698
1699\def\spac_grids_snap_to_finish#1%
1700  {\ifvbox\nextbox % this will go away
1701     \clf_vspacingcollapse\nextbox\relax % isn't that already done?
1702   \fi
1703   \ifempty{#1}%
1704     \spac_grids_snap_value_set\v!normal
1705   \else
1706     \spac_grids_snap_value_set{#1}%
1707   \fi
1708   \clf_vspacingsnap\nextbox\c_attr_snapmethod\relax
1709   \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% no pack (?), we snap
1710   \egroup}
1711
1712\def\spac_grids_check_nop
1713  {\gridsnappingfalse
1714   \resetsystemmode\v!grid
1715   \spac_grids_snap_value_reset}
1716
1717\def\spac_grids_check_yes
1718  {\gridsnappingtrue
1719   \setsystemmode\v!grid
1720   \spac_grids_snap_value_set\p_grid}
1721
1722\permanent\protected\def\synchronizegridsnapping
1723  {\edef\p_grid{\layoutparameter\c!grid}%
1724   \ifx\p_grid\v!no         % official
1725     \spac_grids_check_nop
1726   \orelse\ifx\p_grid\v!off % for taco and luigi
1727     \spac_grids_check_nop
1728   \orelse\ifempty\p_grid   % to be sure
1729     \spac_grids_check_nop
1730   \else
1731     \spac_grids_check_yes
1732   \fi}
1733
1734\permanent\protected\def\setupgridsnapping[#1]% less overhead than setuplayout (needs testing)
1735  {\setlayoutparameter\c!grid{#1}\synchronizegridsnapping}
1736
1737\mutable\lettonothing\checkedgridmethod % this can become private
1738
1739\mutable\let\checkedgridscope\v!local % this can become private
1740
1741\permanent\protected\def\checkgridmethod#1%
1742  {\edef\p_grid{#1}%
1743   \ifempty\p_grid
1744     \lettonothing\checkedgridmethod
1745     \let\checkedgridscope\v!local
1746   \else
1747     \splitatcolon\p_grid\checkedgridscope\checkedgridmethod
1748     \ifempty\checkedgridmethod
1749       \ifx\checkedgridscope\v!local\orelse\ifx\checkedgridscope\v!global\else
1750         \let\checkedgridmethod\checkedgridscope
1751         \let\checkedgridscope \v!local
1752       \fi
1753     \fi
1754   \fi}
1755
1756\permanent\protected\def\applygridmethod#1#2#3% content localsettings (used in head rendering)
1757   {\checkgridmethod{#1}%
1758    \ifx\checkedgridscope\v!global
1759      \ifempty\checkedgridmethod \else
1760        % we assume that the call is grouped because grouping here has the side
1761        % effect that the eventually constructed line will get the value outside
1762        % the group
1763        %
1764        % overkill: \setupgridsnapping[\checkedgridmethod]%
1765        % maybe   : \spac_grids_snap_value_auto\checkedgridmethod
1766        \spac_grids_snap_value_set\checkedgridmethod
1767      \fi
1768      \hbox{#3}%
1769    \else
1770      % the extra hbox will trigger the global snapper on top of the local and
1771      % we really need that in this case (compatibility etc etc) so here we don't
1772      % het an already done hit (otherwise we would not snap)
1773      \hbox\bgroup
1774        \ifempty\checkedgridmethod\orelse\ifconditional\headisdisplay
1775          #2%
1776        \fi
1777        \snaptogrid[\checkedgridmethod]\hbox{#3}%
1778      \egroup
1779    \fi}
1780
1781\protected\gdef\page_layouts_calculate_overshoot
1782  {\ifgridsnapping\ifcase\layoutlines
1783     \getnoflines\textheight
1784     \textovershoot\dimexpr\noflines\globalbodyfontlineheight-\textheight\relax
1785   \fi\fi}
1786
1787\protected\def\page_layouts_report_overshoot
1788  {\page_layouts_calculate_overshoot
1789   \ifdim\textovershoot>\zeropoint
1790     \writestatus\m!layouts{gridmode,\space
1791       noflines: \the\noflines,\space
1792       textheight: \the\textheight,\space
1793       textovershoot: \the\textovershoot\space
1794       (maybe set number of lines instead)%
1795    }%
1796  \fi
1797  \glet\page_layouts_report_overshoot\page_layouts_calculate_overshoot}
1798
1799\appendtoks
1800    \page_layouts_report_overshoot
1801\to \everybeforepagebody
1802
1803%D Visualization:
1804
1805\definepalet
1806  [grid]
1807  [  one=red,
1808     two=green,
1809   three=blue,
1810    four=gray]
1811
1812\permanent\protected\def\setgridtracebox#1[#2]% % maybe reverse the order
1813  {\setbox\nextbox#1%
1814     {\hbox
1815        {\hbox to \zeropoint
1816           {\setlayoutcomponentattribute{\v!grid:\v!test}%
1817            \color[grid:#2]{\ruledhbox \layoutcomponentboxattribute {\fakebox\nextbox}}%
1818            \hss}%
1819         \flushnextbox}}}
1820
1821\setnewconstant\gridboxlinenomode\plusone % 0:nothing 1:all 2:lines 3:frame 4:l/r
1822\setnewconstant\gridboxlinemode  \plusone
1823
1824\permanent\protected\def\gridboxvbox
1825  {\ifcase\gridboxlinemode
1826     \vpack
1827   \or
1828     \ruledvpack
1829   \or
1830     \vpack
1831   \or
1832     \ruledvpack
1833   \else
1834     \ruledvpack
1835   \fi}
1836
1837\permanent\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth}
1838
1839\permanent\protected\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
1840  {\setbox#1\gridboxvbox to #3 % given size
1841     {\forgetall
1842      \resetvisualizers
1843      \resetteststrut
1844      \offinterlineskip
1845      \hsize#2%
1846      \ifcase\gridboxlinenomode\or\or\or
1847        \gridboxlinenomode\doifoddpageelse\plusone\plustwo % 3: outer
1848      \or
1849        \gridboxlinenomode\doifoddpageelse\plustwo\plusone % 4: inner
1850      \fi
1851      \topskipcorrection
1852      \gridboxvbox % calculated size
1853        {\getrawnoflines{#3}% \getnoflines{#3}%
1854         \scratchdimen\dimexpr#2+\lineheight\relax
1855         \localcontrolledrepeat\noflines
1856           {\strut
1857            \hskip-.5\lineheight\relax
1858            \ifcase\gridboxlinenomode\or
1859              \rlap
1860                {\kern\dimexpr.2\bodyfontsize+\scratchdimen\relax
1861                 \infofont\hbox to \emwidth{\hss\the\currentloopiterator}}%
1862            \or
1863              \llap
1864                {\infofont\hbox to \emwidth{\hss\the\currentloopiterator}%
1865                 \kern.2\bodyfontsize}%
1866            \fi
1867            \vrule
1868              \s!height \gridboxwidth
1869              \s!depth  \gridboxwidth
1870              \s!width  \scratchdimen
1871            \par}}%
1872      \vfill}}
1873
1874%D This has become obsolete:
1875
1876% \def\moveboxontogrid#1#2#3% will become obsolete, but it needs checking
1877%   {}
1878
1879%D Helper:
1880
1881\protected\def\spac_helpers_assign_skip#1#2% ook nog \v!halfline+fuzzysnap
1882  {\ifcstok{#2}\v!line
1883     #1\ifgridsnapping
1884       \bodyfontlineheight
1885     \else
1886       \openlineheight
1887     \fi
1888   \else
1889     \ifgridsnapping
1890       \assigndimension{#2}{#1}{.25\bodyfontlineheight}{.5\bodyfontlineheight}\bodyfontlineheight
1891     \else
1892       \assigndimension{#2}{#1}\smallskipamount\medskipamount\bigskipamount
1893     \fi
1894   \fi
1895   \relax}
1896
1897% \start \dosetstretch{.25em} \setuptolerance[tolerant,stretch] \input tufte \endgraf \stop
1898% \start \dosetstretch{.5em} effe flink doorfietsen \stop
1899
1900% experimental code, not yet interfaced:
1901
1902% category:
1903%
1904%  0 == discard                             discard
1905%  1 == only if larger                      largest
1906%  2 == force even if smaller               force
1907%  3 == only take penalty component         penalty
1908%  4 == add to existing skip                add
1909%  5 == disable (ignore following)          disable
1910%  6 == kill whitespace                     nowhite
1911%  7 == discard previous                    back
1912% 10 == no topskip
1913%
1914% penalty: larger wins
1915% order: larger wins
1916% category:2,order:5,penalty:10000,skip:value|kw
1917%
1918% \defineblankmethod  [\v!joinedup] {\ifvmode\nointerlineskip\fi}
1919
1920% todo, in grid mode: builders.vspacing.fixed = false
1921%
1922% \ifgridsnapping will go
1923
1924\installcorenamespace{vspacing}
1925\installcorenamespace{vspacingamount}
1926
1927\permanent\tolerant\protected\def\definevspacingamount[#1]#*[#2]#*[#3]% can be combined
1928  {\ifarguments
1929     %defcsname\??vspacingamount#1\endcsname{\lineheight}%
1930   \or
1931     \defcsname\??vspacingamount#1\endcsname{\lineheight}%
1932   \or
1933     \defcsname\??vspacingamount#1\endcsname{\ifgridsnapping\lineheight\else#2\fi}%
1934   \or
1935     \defcsname\??vspacingamount#1\endcsname{\ifgridsnapping#3\else#2\fi}%
1936   \fi
1937   \clf_vspacingsetamount{#1}}
1938
1939\def\spac_vspacing_no_topskip % use grouped
1940  {\c_attr_skipcategory\pluseleven}
1941
1942%permanent\def\vspacingfromscratchtoks  {\scratchdimen\dimexpr\csname\??vspacingamount\the\scratchtoks\endcsname\relax}
1943\permanent\def\vspacingpredefinedvalue#1{\s_spac_vspacing_predefined\glueexpr\csname\??vspacingamount#1\endcsname\relax}
1944%permanent\def\vspacingfromtempstring   {\scratchdimen\dimexpr\csname\??vspacingamount\tempstring\endcsname\relax}
1945
1946% \installcorenamespace{vspacingamountnormal}
1947% \installcorenamespace{vspacingamountgrid}
1948
1949% \def\spac_vspacing_define_amount[#1][#2][#3]% can be combined
1950%   {\ifcsname n>#1\endcsname\else
1951%      \expandafter\newtoks\csname n>#1\endcsname
1952%      \expandafter\newtoks\csname g>#1\endcsname
1953%    \fi
1954%    \csname n>#1\endcsname{#2}%
1955%    \csname g>#1\endcsname{#3}%
1956%    \clf_vspacingsetamount{#1}}
1957
1958\permanent\tolerant\protected\def\definevspacing[#1]#*[#2]%
1959  {\clf_vspacingdefine{#1}{#2}}
1960
1961%D The injector code (generated at the \LUA\ end). This will go away!
1962
1963% \newtoks\everybeforeblankhandling
1964% \newtoks\everyafterblankhandling
1965%
1966% \newconditional\c_space_vspacing_done
1967% \newconditional\c_space_vspacing_fixed
1968% \newconditional\c_space_ignore_parskip
1969%
1970% \appendtoks
1971%     \s_spac_vspacing_temp\zeropoint
1972%     \c_attr_skipcategory\plusone
1973%     \c_attr_skippenalty \attributeunsetvalue
1974%     \c_attr_skiporder   \attributeunsetvalue
1975%     \ifgridsnapping
1976%         \c_space_vspacing_fixed\conditionaltrue
1977%     \else
1978%         \c_space_vspacing_fixed\conditionalfalse
1979%     \fi
1980% \to \everybeforeblankhandling
1981%
1982% \appendtoks
1983%     \s_spac_vspacing_temp\plusone\s_spac_vspacing_temp
1984%       \ifconditional\c_space_vspacing_fixed \else
1985%         \s!plus \skipgluefactor\s_spac_vspacing_temp
1986%         \s!minus\skipgluefactor\s_spac_vspacing_temp
1987%       \fi
1988%     \relax
1989% \to \everyafterblankhandling
1990
1991% The main spacer:
1992
1993\permanent\tolerant\protected\def\vspacing[#1]%
1994  {\ifarguments
1995     \spac_vspacing_yes[\currentvspacing]% in the new mechanism no [] needed
1996   \else
1997     \spac_vspacing_yes[#1]% in the new mechanism no [] needed
1998   \fi}
1999
2000\def\spac_vspacing_yes
2001  {\ifinpagebody % somewhat weird
2002     \expandafter\spac_vspacing_yes_indeed
2003   \orelse\ifconditional\c_spac_packed_blank
2004     \expandafter\spac_vspacing_yes_indeed
2005   \else
2006     \expandafter\spac_vspacing_yes_ignore
2007   \fi}
2008
2009\def\spac_vspacing_nop
2010  {\ifinpagebody % somewhat weird
2011     \expandafter\spac_vspacing_nop_indeed
2012   \orelse\ifconditional\c_spac_packed_blank
2013     \expandafter\spac_vspacing_nop_indeed
2014   \else
2015     \expandafter\spac_vspacing_nop_ignore
2016   \fi}
2017
2018\def\spac_vspacing_yes_indeed[#1]{\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{#1}\fi\fi}
2019\def\spac_vspacing_nop_indeed    {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\currentvspacing}\fi\fi}
2020
2021\def\spac_vspacing_yes_ignore[#1]{\ifmmode\else\par\fi}
2022\def\spac_vspacing_nop_ignore    {\ifmmode\else\par\fi}
2023
2024\permanent\protected\def\directvspacing#1%
2025 {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\ifempty{#1}\currentvspacing\else#1\fi}\fi\fi}
2026
2027\permanent\protected\def\directdefaultvspacing
2028  {\ifinpagebody % somewhat weird
2029     \directvspacing\currentvspacing
2030   \orelse\ifconditional\c_spac_packed_blank
2031     \directvspacing\currentvspacing
2032   \fi}
2033
2034\permanent\protected\def\directcheckedvspacing
2035  {\ifinpagebody % somewhat weird
2036     \expandafter\directvspacing
2037   \orelse\ifconditional\c_spac_packed_blank
2038     \expandafter\directvspacing
2039   \else
2040     \expandafter\gobbleoneargument
2041   \fi}
2042
2043\permanent\protected\def\useblankparameter#1% faster local variant
2044  {\edef\m_spac_blank_asked{#1\c!blank}%
2045   \ifempty\m_spac_blank_asked\else
2046     \directvspacing\m_spac_blank_asked
2047   \fi}
2048
2049%D Handy (and faster):
2050
2051\permanent\protected\def\directvpenalty#1{\ifmmode\else\par\ifvmode\clf_injectvpenalty#1\relax\fi\fi}
2052\permanent\protected\def\directvskip   #1{\ifmmode\else\par\ifvmode\clf_injectvskip   #1\relax\fi\fi}
2053
2054%D These depend on bigskipamount cum suis so we'd better sync them:
2055
2056\mutable\let\currentvspacing\s!default % hm, default, standard ...
2057
2058\permanent\tolerant\protected\def\setupvspacing[#1]%
2059  {\ifarguments\else
2060     \edef\currentvspacing{#1}%
2061   \fi
2062   \synchronizevspacing}
2063
2064\permanent\protected\def\synchronizevspacing
2065  {\ifempty\currentvspacing % mistakenly had an \else
2066     \let\currentvspacing\s!default
2067   \fi
2068   \spac_whitespace_setup_nop}
2069
2070\permanent\protected\def\restorestandardblank % or default ?
2071  {\let\currentvspacing\v!standard}
2072
2073%D The \type {category:4} is default.
2074
2075\definevspacingamount[\v!none]        [\zeroskip]          [\zeroskip]
2076\definevspacingamount[\v!big]         [\bigskipamount]     [\bodyfontlineheight]
2077\definevspacingamount[\v!medium]      [\medskipamount]     [.5\bodyfontlineheight]
2078\definevspacingamount[\v!small]       [\smallskipamount]   [.25\bodyfontlineheight]
2079\definevspacingamount[\v!line]        [\openlineheight]    [\bodyfontlineheight]
2080\definevspacingamount[\v!halfline]    [.5\openlineheight]  [.5\bodyfontlineheight]
2081\definevspacingamount[\v!quarterline] [.25\openlineheight] [.25\bodyfontlineheight]
2082\definevspacingamount[\v!formula]     [\medskipamount]     [.5\bodyfontlineheight]
2083\definevspacingamount[\v!white]       [\parskip]           [\bodyfontwhitespace]
2084\definevspacingamount[\v!height]      [\strutht]           [\bodyfontstrutheight]
2085\definevspacingamount[\v!depth]       [\strutdp]           [\bodyfontstrutdepth]
2086
2087\definevspacingamount[\v!standard]    [.75\openlineheight] [.75\openlineheight] % mkii compatible
2088
2089\permanent\def\bodyfontwhitespace
2090  {\dimexpr
2091     \ifzeropt\parskip
2092       \zeropoint
2093     \orelse\ifgridsnapping
2094       \bodyfontlineheight
2095     \else
2096       \parskip
2097     \fi
2098   \relax}
2099
2100%D used in itemize \unknown\ always test this:
2101
2102\def\spac_overlay_lines
2103  {\directcheckedvspacing{\v!back,\v!overlay}% \blank[\v!back,\v!overlay]%
2104   \nointerlineskip}
2105
2106% \startitemize[n]
2107%     \item \input zapf
2108%     \item \startitemize[a]
2109%         \item \input knuth
2110%     \stopitemize
2111% \stopitemize
2112%
2113% \strut \hfill first line \blank[overlay] second line \hfill \strut
2114%
2115% \ruledvbox {
2116%     \strut \hfill line 1 \blank[overlay]
2117%     line 2 \hfill \strut \blank[overlay]
2118%     \strut \hfill line 3 \hfill \strut
2119% }
2120%
2121% \dorecurse{50}
2122%   {\startitemize[n] \startitem \startitemize[a] \item #1 \stopitemize \stopitem \stopitemize}
2123
2124\definevspacing[\v!preference][penalty:-500]  % goodbreak
2125\definevspacing[\v!samepage]  [penalty:10000] % nobreak
2126
2127\definevspacing[\v!always]    [category:0] % hm, internally it's discard
2128\definevspacing[\v!max]       [category:1]
2129\definevspacing[\v!force]     [category:2]
2130\definevspacing[\v!disable]   [category:5]
2131\definevspacing[\v!nowhite]   [category:6]
2132\definevspacing[\v!back]      [category:7]
2133\definevspacing[\v!packed]    [category:8]  % noparskip (kind of special)
2134\definevspacing[\v!overlay]   [category:9]
2135\definevspacing[\v!enable]    [category:10]
2136
2137%definevspacing[\v!noparskip] [category:8]
2138%definevspacing[\v!notopskip] [category:11]
2139
2140\definevspacing[\v!weak]      [order:0]
2141\definevspacing[\v!strong]    [order:100]
2142
2143\definevspacing[\s!default]   [\v!white] % was big for a while
2144
2145\newinteger\c_spac_vspacing_special_base \c_spac_vspacing_special_base = 32250 % 4000
2146\newinteger\c_spac_vspacing_special_step \c_spac_vspacing_special_step =    10 %  250
2147\newinteger\c_spac_vspacing_special_done
2148
2149% 2019-05-31 : upgraded a bit to more distinctive samepage-[level]-[0|1|2] names
2150
2151\protected\def\spac_vspacing_define_same_step#1#2% alternatively we could have samepage-n-m
2152  {\begingroup
2153   \scratchcounterone\numexpr\plusthree*#1+#2\relax
2154   \scratchcountertwo\numexpr\c_spac_vspacing_special_base+\c_spac_vspacing_special_step*\scratchcounterone\relax
2155  %\writestatus{defined}{\v!samepage-\number#1-\number#2\space=>\space penalty:\the\scratchcountertwo}%
2156   \normalexpanded{\definevspacing[\v!samepage-\number#1-\number#2][penalty:\the\scratchcountertwo]}%
2157   \endgroup}
2158
2159% \protected\def\spac_vspacing_define_same_page#1%
2160%   {\dostepwiserecurse\c_spac_vspacing_special_done{#1}\plusone
2161%      {\spac_vspacing_define_same_step\recurselevel\zerocount % before
2162%       \spac_vspacing_define_same_step\recurselevel\plusone   % after
2163%       \spac_vspacing_define_same_step\recurselevel\plustwo}% % whatever
2164%    \global\c_spac_vspacing_special_done#1\relax}
2165
2166\protected\def\spac_vspacing_define_same_page#1%
2167  {\localcontrolledloop\c_spac_vspacing_special_done=#1=\plusone
2168     {\spac_vspacing_define_same_step\currentloopiterator\zerocount % before
2169      \spac_vspacing_define_same_step\currentloopiterator\plusone   % after
2170      \spac_vspacing_define_same_step\currentloopiterator\plustwo}% % whatever
2171   \global\c_spac_vspacing_special_done#1\relax}
2172
2173\spac_vspacing_define_same_page{12} % 12 levels should be more than enough as a start
2174
2175\def\spac_vspacing_same_page#1#2% level offset (starts at 0)
2176  {\ifnum#1>\c_spac_vspacing_special_done
2177     \spac_vspacing_define_same_page{#1}%
2178   \fi
2179  %\writestatus{used}{\v!samepage-\number#1-\number#2}%
2180   \vspacing[\v!samepage-\number#1-\number#2]}
2181
2182\definevspacing[\v!default]  [\v!big]      % todo: needs to adapt to \setupblank
2183\definevspacing[\v!before]   [\v!default]  % but we need to avoid circular references
2184\definevspacing[\v!inbetween][\v!default]  % then
2185\definevspacing[\v!after]    [\v!before]
2186
2187\setupvspacing
2188  [\v!big] % alternatively [\v!standard]
2189
2190%D Maybe at some point we will differ between \type {\vspacing} and \type {\blank}
2191%D (we needed the first one while playing with the new code).
2192
2193% We keep this one as reference
2194%
2195% \protected\def\inhibitblank
2196%   {\vspacing[\v!disable]}
2197%
2198% but use the following more efficient variant instead:
2199
2200\permanent\protected\def\inhibitblank{\ifmmode\else\par\ifvmode\clf_injectdisable\fi\fi}
2201
2202\aliased\let\doinhibitblank\inhibitblank % keep this command for a while, used in styles
2203
2204%D We use \type {vspacing} because at some point we had the blank mechanism alongside
2205%D a new experimental variant and I aliased it locally till it all worked out well. So,
2206%D we're kind of stuck with synonyms now. Some day we will drop the vspacing and use the
2207%D old aliases instead.
2208
2209\aliased\let\defineblank      \definevspacing
2210\aliased\let\setupblank       \setupvspacing
2211\aliased\let\blank            \vspacing
2212\aliased\let\synchronizeblank \synchronizevspacing
2213\aliased\let\defineblankmethod\definevspacingamount
2214
2215%D The following command is for Wolfgang. It has to be used with care as it does
2216%D {\em not} work in tandem with the other spacing commands.
2217
2218\installcorenamespace{vspace}
2219
2220\permanent\tolerant\protected\def\definevspace[#1]#*[#2]#*[#3]%
2221  {\ifarguments
2222   \or
2223     \letcsname\??vspace:#1\endcsname\empty
2224   \or
2225     \defcsname\??vspace:#1\endcsname{#2}%
2226   \or
2227     \defcsname\??vspace#1:#2\endcsname{#3}%
2228   \fi}
2229
2230\letcsname\??vspace:\s!unknown\endcsname\zeropoint
2231
2232\def\spac_vspace_unknown
2233  {\csname\??vspace:\s!unknown\endcsname} % why not a let?
2234
2235\permanent\tolerant\protected\def\vspace[#1]#*[#2]%
2236  {\par
2237   \ifvmode
2238     \removelastskip
2239     \vskip
2240       \ifparameter#2\or
2241         \ifcsname\??vspace#1:#2\endcsname
2242           \lastnamedcs
2243         \orelse\ifcsname\??vspace:#2\endcsname
2244           \lastnamedcs
2245         \else
2246           \spac_vspace_unknown
2247         \fi
2248       \orelse\ifparameter#1\or
2249         \ifcsname\??vspace:#1\endcsname
2250           \lastnamedcs
2251         \else
2252           \spac_vspace_unknown
2253         \fi
2254       \else
2255         \ifcsname\??vspace:\s!default\endcsname
2256           \lastnamedcs
2257         \else
2258           \spac_vspace_unknown
2259         \fi
2260       \fi
2261     \relax
2262   \fi}
2263
2264%D Some preliminary code: a simple and fast hanger, for usage in macros.
2265
2266\installcorenamespace {hanging}
2267
2268\installdirectcommandhandler \??hanging {hanging}
2269
2270\setuphanging
2271  [\c!distance=.5\emwidth,
2272   \c!location=\v!left,
2273   \c!n=\zerocount]
2274
2275\lettonothing\m_spac_hanging_location
2276
2277\permanent\tolerant\protected\def\starthanging[#1]%
2278  {\dontleavehmode\bgroup
2279   \ifhastok={#1}%
2280     \lettonothing\m_spac_hanging_location
2281     \setupcurrenthanging[#1]%
2282   \else
2283     \edef\m_spac_hanging_location{#1}%
2284   \fi
2285   \ifempty\m_spac_hanging_location
2286     \edef\m_spac_hanging_location{\directhangingparameter\c!location}%
2287   \fi
2288   \dowithnextboxcs\spac_hanging_finish\hbox}
2289
2290\permanent\protected\def\stophanging
2291  {\endgraf
2292   \egroup}
2293
2294\def\spac_hanging_finish
2295  {\scratchdistance\directhangingparameter\c!distance\relax
2296   \ifdim\ht\nextbox>\strutht
2297     \setbox\nextbox\tbox{\box\nextbox}%
2298   \fi
2299   \scratchcounter\directhangingparameter\c!n\relax
2300   \ifnum\scratchcounter>\zerocount
2301     \frozen\hangafter-\scratchcounter
2302   \else
2303     \getboxheight\scratchdimen\of\box\nextbox
2304     \getnoflines\scratchdimen
2305     \frozen\hangafter-\noflines
2306   \fi
2307   \ht\nextbox\strutht
2308   \dp\nextbox\strutdp
2309   \scratchwidth\dimexpr\wd\nextbox+\scratchdistance\relax
2310   \ifx\m_spac_hanging_location\v!right
2311     \frozen\hangindent\ifconditional\displaylefttoright-\fi\scratchwidth
2312     \rlap{\kern\dimexpr\hsize-\leftskip-\wd\nextbox\relax\box\nextbox}% \leftskip is new
2313   \else
2314     \frozen\hangindent\ifconditional\displaylefttoright\else-\fi\scratchwidth
2315     \llap{\box\nextbox\kern\scratchdistance}%
2316   \fi
2317   \ignorespaces}
2318
2319%D \macros
2320%D   {startfixed}
2321%D
2322%D \starttyping
2323%D \startitemize
2324%D     \startitem \externalfigure[cow][height=1cm] \stopitem
2325%D     \startitem \externalfigure[cow][height=1cm] \stopitem
2326%D
2327%D     \startitem \startfixed      \externalfigure[cow][height=1cm]\stopfixed \stopitem
2328%D     \startitem \startfixed[high]\externalfigure[cow][height=1cm]\stopfixed \stopitem
2329%D     \startitem \startfixed[low] \externalfigure[cow][height=1cm]\stopfixed \stopitem
2330%D     \startitem \startfixed[lohi]\externalfigure[cow][height=1cm]\stopfixed \stopitem
2331%D
2332%D     \startitem test \par \startfixed      \externalfigure[koe][height=1cm]\stopfixed \stopitem
2333%D     \startitem test \par \startfixed[high]\externalfigure[koe][height=1cm]\stopfixed \stopitem
2334%D     \startitem test \par \startfixed[low] \externalfigure[koe][height=1cm]\stopfixed \stopitem
2335%D     \startitem test \par \startfixed[lohi]\externalfigure[koe][height=1cm]\stopfixed \stopitem
2336%D \stopitemize
2337%D \stopbuffer
2338%D
2339%D \typebuffer \getbuffer
2340
2341\installcorenamespace{fixedalternatives}
2342
2343\permanent\protected\lettonothing\stopfixed
2344
2345\permanent\protected\def\startfixed
2346  {\bgroup
2347   \ifhmode
2348     \expandafter\typo_fixed_start_h
2349   \else
2350     \expandafter\typo_fixed_start_v
2351   \fi}
2352
2353\tolerant\def\typo_fixed_start_h[#1]%
2354  {\enforced\let\stopfixed\typo_fixed_stop_h
2355   \dowithnextbox{\typo_fixed_finish{#1}}%
2356   \vbox\bgroup
2357   %ignorespaces
2358   \setlocalhsize}
2359
2360\protected\def\typo_fixed_stop_h
2361  {%removeunwantedspaces
2362   \egroup
2363   \egroup}
2364
2365\tolerant\def\typo_fixed_start_v[#1]%
2366  {\enforced\let\stopfixed\typo_fixed_stop_v
2367   \startbaselinecorrection}
2368
2369\protected\def\typo_fixed_stop_v
2370  {\stopbaselinecorrection
2371   \egroup}
2372
2373\letcsname\??fixedalternatives   \v!high\endcsname\bbox
2374\letcsname\??fixedalternatives    \v!low\endcsname\tbox
2375\letcsname\??fixedalternatives \v!middle\endcsname\vcenter
2376\letcsname\??fixedalternatives   \v!lohi\endcsname\vcenter
2377\letcsname\??fixedalternatives\s!unknown\endcsname\tbox
2378\letcsname\??fixedalternatives\s!default\endcsname\tbox
2379
2380\protected\def\typo_fixed_finish#1%
2381  {\expandnamespacevalue\??fixedalternatives{#1}\s!default{\box\nextbox}}
2382
2383% %D Forgotten already:
2384%
2385% \def\shapefill{\vskip\zeropoint\s!plus\lineheight\s!minus\lineheight\relax}
2386
2387%D Nasty:
2388
2389% \writestatus{1}{\the\prevdepth} \blank[force,5*big] { \writestatus{1}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
2390% \writestatus{2}{\the\prevdepth} \blank[force,5*big] { \writestatus{2}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
2391% \writestatus{3}{\the\prevdepth} \blank[force,5*big] { \writestatus{3}{\the\prevdepth} \baselineskip5cm xxxxxxxxx \par } \page
2392% \writestatus{4}{\the\prevdepth} \input tufte                                                                            \page
2393% \writestatus{5}{\the\prevdepth} \input tufte                                                                            \page
2394% \writestatus{6}{\the\prevdepth} \blank[force,5*big] { \writestatus{6}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
2395
2396% \writestatus{1}{\the\prevdepth} \null\vskip4cm      { \writestatus{1}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
2397% \writestatus{2}{\the\prevdepth} \null\vskip4cm      { \writestatus{2}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
2398% \writestatus{3}{\the\prevdepth} \null\vskip4cm      { \writestatus{3}{\the\prevdepth} \baselineskip5cm xxxxxxxxx \par } \page
2399% \writestatus{4}{\the\prevdepth} \input tufte                                                                            \page
2400% \writestatus{5}{\the\prevdepth} \input tufte                                                                            \page
2401% \writestatus{6}{\the\prevdepth} \null\vskip4cm      { \writestatus{6}{\the\prevdepth} \baselineskip1cm xxxxxxxxx \par } \page
2402
2403\appendtoks
2404    \ifvmode\prevdepth\zeropoint\fi % consistent, else first page -1000pt .. needed for fixed,3*big first/successive pages consistency
2405\to \everystarttext
2406
2407\prevdepth\zeropoint
2408
2409%D Helper:
2410
2411\permanent\protected\def\checkedblank[#1]%
2412  {\edef\p_blank{#1}%
2413   \ifempty\p_blank
2414     % ignore
2415   \orelse\ifx\p_blank\v!none
2416     % ignore
2417   \else
2418     \blank[\p_blank]%
2419   \fi}
2420
2421% \setupwhitespace[line]
2422% \prerollblank[2*line]  \the\prerolledblank
2423% \prerollblank[-2*line] \the\prerolledblank
2424
2425\newgluespec\prerolledblank
2426
2427\permanent\protected\def\prerollblank[#1]%
2428  {\begingroup
2429   \edef\p_blank{#1}%
2430   \ifempty\p_blank
2431     \global\prerolledblank\zeropoint
2432   \orelse\ifx\p_blank\v!none
2433     \global\prerolledblank\zeropoint
2434   \else
2435     % don't mess with \arskip here!
2436     \scratchskip\plusten\lineheight
2437     \setbox\scratchbox\vbox
2438       {\vskip\scratchskip
2439        \kern\zeropoint
2440        \blank[\p_blank]}%
2441     % \dimexpr doesn't work well with skips
2442     \advanceby\scratchskip-\ht\scratchbox
2443     \global\prerolledblank-\scratchskip
2444   \fi
2445   \endgroup}
2446
2447% \setupwhitespace[line]
2448% \setuphead[subject][after={\blank[packed]},style=\bfb]
2449% \subject{foo}
2450% test \par
2451% test \par
2452% \blank[packed] % \ignoreparskip
2453% test \par
2454% test \par
2455% \ignoreparskip
2456% test \par
2457% test \par
2458% \setuphead[subject][after={\blank[nowhite]},style=\bfb]
2459% \subject{foo}
2460% test \par
2461% test \par
2462
2463\permanent\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone}
2464
2465%D New, use with care:
2466%D
2467%D \starttyping
2468%D test test test \hfill\break
2469%D test \blankbefore test
2470%D test \blankbefore[2*line] test
2471%D test \blankbefore test
2472%D test test test \hfill\break
2473%D test \blankbefore test
2474%D test \blankbefore test
2475%D test \blankbefore test
2476%D test test test \hfill\break
2477%D test \blankafter test
2478%D test \blankafter test
2479%D test \blankafter test
2480%D test test test \hfill\break
2481%D test test test \hfill\break
2482%D \stoptyping
2483
2484\permanent\tolerant\protected\def\blankbefore[#1]{\vadjust pre {\ifempty{#1}\blank\else\blank[#1]\fi}}
2485\permanent\tolerant\protected\def\blankafter [#1]{\vadjust post{\ifempty{#1}\blank\else\blank[#1]\fi}}
2486
2487%D Experimental:
2488
2489\installcorenamespace{textdisplay}
2490
2491\installcommandhandler \??textdisplay {textdisplay} \??textdisplay
2492
2493\appendtoks
2494    \frozen\protected\edefcsname\e!start\currenttextdisplay\endcsname{\spac_textdisplay_start{\currenttextdisplay}}%
2495    \frozen\protected\edefcsname\e!stop \currenttextdisplay\endcsname{\spac_textdisplay_stop}%
2496\to \everydefinetextdisplay
2497
2498\setuptextdisplay
2499  [\c!factor=.5,
2500   \c!after=\textdisplayparameter\c!before]
2501
2502\tolerant\protected\def\spac_textdisplay_start#1#:[#S#2]%
2503  {\par
2504   \begingroup
2505   \whitespace
2506   \forgetall
2507   \edef\currenttextdisplay{#1}%
2508   \setupcurrenttextdisplay[#2]%
2509   \textdisplayparameter\c!before
2510   \dpack
2511   \bgroup
2512   \strut
2513   \vskip-\lineheight
2514   \vpack
2515   \s!yoffset -\textdisplayparameter\c!factor\strutdp
2516   \bgroup}
2517
2518\protected\def\spac_textdisplay_stop
2519  {\egroup
2520   \vskip-\lineheight
2521   \strut
2522   \egroup
2523   \textdisplayparameter\c!after
2524   \endgroup
2525   \par}
2526
2527\definetextdisplay[\v!textdisplay]
2528
2529% \useMPlibrary[dum]
2530%
2531% \definetextdisplay[steppedbystep][before={\blank[halfline]}]
2532%
2533% \starttext \showmakeup[line]
2534%   \dostepwiserecurse{10}{25}{1}{
2535%       xxxxxxxxxxxxxxxx\par
2536%       \starttextdisplay
2537%         \externalfigure[dummydummy][height=#1mm,text=no]%
2538%       \stoptextdisplay
2539%       xxxxxxxxxxxxxxxx\par
2540%       \starttextdisplay[before=\blank,after=\blank] % factor=.5
2541%         \externalfigure[dummydummy][height=#1mm,text=no]%
2542%       \stoptextdisplay
2543%       xxxxxxxxxxxxxxxx\par
2544%       \startsteppedbystep
2545%         \externalfigure[dummydummy][height=#1mm,text=no]%
2546%       \stopsteppedbystep
2547%       xxxxxxxxxxxxxxxx\par
2548%       \page
2549%   }
2550% \stoptext
2551
2552\protect \endinput
2553