summaryrefslogtreecommitdiff
path: root/tex/context/base/spac-ver.mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/spac-ver.mkiv')
-rw-r--r--tex/context/base/spac-ver.mkiv1485
1 files changed, 1485 insertions, 0 deletions
diff --git a/tex/context/base/spac-ver.mkiv b/tex/context/base/spac-ver.mkiv
new file mode 100644
index 000000000..8e612579d
--- /dev/null
+++ b/tex/context/base/spac-ver.mkiv
@@ -0,0 +1,1485 @@
+%D \module
+%D [ file=spac-ver,
+%D version=2009.10.16, % 1997.03.31, was core-spa.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Vertical,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Spacing Macros / Vertical}
+
+\unprotect
+
+\registerctxluafile{spac-ver}{1.001}
+
+\newskip\blankskip \blankskip=\bigskipamount
+
+\def\skipfactor {.75}
+\def\skipgluefactor{.25}
+
+\def\normalskipamount
+ {\openlineheight
+ \ifgridsnapping \else \ifblankflexible
+ \!!plus \skipgluefactor\openlineheight
+ \!!minus\skipgluefactor\openlineheight
+ \fi \fi
+ \relax}
+
+\def\linedistance {\normalskipamount}
+\def\appliedblankskip{\skipfactor\linedistance}
+\def\lastblankskip {\blankskip}
+\def\currentblank {\v!big}
+\def\oldprevdepth {\prevdepth}
+\def\newprevdepth {-1001pt}
+\def\mindimen {1sp} % was: 0.00002pt
+
+%D There are two ways to influence the interline spacing. The
+%D most general and often most consistent way is using
+%D
+%D \showsetup{setupinterlinespace}
+%D
+%D For instance
+%D
+%D \starttyping
+%D \setupinterlinespace[line=2.8ex]
+%D \stoptyping
+%D
+%D This setting adapts itself to the bodyfontsize, while for
+%D instance saying
+%D
+%D \starttyping
+%D \setupinterlinespace[line=12pt]
+%D \stoptyping
+%D
+%D sets things fixed for all sizes, which is definitely not
+%D what we want. Therefore one can also say:
+%D
+%D \starttyping
+%D \definebodyfontenvironment[9pt][interlinespace=11pt]
+%D \stoptyping
+%D
+%D One can still use \type{\setupinterlinespace} (without
+%D arguments) to set the interline space according to the
+%D current font, e.g. a \type{\bfa}.
+
+\newif\iflocalinterlinespace
+
+% font-ini
+
+\ifx\bodyfontinterlinespecs\undefined
+
+ \let\bodyfontinterlinespecs\empty
+ \let\bodyfontinterlinespace\empty
+
+\fi
+
+\def\presetnormallineheight
+ {\edef\normallineheight{\@@itline}%
+% done elsewhere : \spacing\!!plusone % new per 10/08/2004, else problems in otr / !! needed
+ \iflocalinterlinespace \else
+ \doifdefined\bodyfontinterlinespecs
+ {\doifsomething\bodyfontinterlinespace
+ {\edef\normallineheight{\bodyfontinterlinespace}}}%
+ \fi}
+
+\def\setupspecifiedinterlinespace[#1]%
+ {\getparameters[\??it][#1]%
+ \scratchdimen0\@@itheight\points
+ \advance\scratchdimen 0\@@itdepth\points
+ \ifdim\scratchdimen>\onepoint
+ \showmessage\m!layouts{10}{\@@itheight,\@@itdepth}%
+ \let\@@itheight\strutheightfactor
+ \let\@@itdepth \strutdepthfactor
+ \else
+ \let\strutheightfactor\@@itheight
+ \let\strutdepthfactor \@@itdepth
+ \fi
+ \let\minimumstrutheight \@@itminheight
+ \let\minimumstrutdepth \@@itmindepth
+ \let\minimumlinedistance\@@itdistance
+ \let\normallineheight \@@itline % let ! ! ! ! ! ivm ex
+ \doifelse\@@ittop\v!height % new, topskip does more bad than good
+ {\let\topskipfactor \@@itheight}
+ {\let\topskipfactor \@@ittop }%
+ \let\maxdepthfactor \@@itbottom
+ \let\baselinegluefactor \@@itstretch
+ \setfontparameters % redundant, can be \setstrut, test first
+ \updateraggedskips} % yes indeed
+
+\let\currentrelativeinterlinespace\empty
+
+\def\setuprelativeinterlinespace[#1]%
+ {\processallactionsinset
+ [#1]
+ [ \v!on=>\oninterlineskip,
+ \v!off=>\offinterlineskip,
+ \v!reset=>\let\currentrelativeinterlinespace\empty
+ \let\setrelativeinterlinespace\relax
+ \setfontparameters,
+ \v!auto=>\let\setrelativeinterlinespace\dosetrelativeinterlinespace,
+ \s!unknown=>\assignvalue\commalistelement\currentrelativeinterlinespace{1.00}{1.25}{1.50}%
+ \spacing\currentrelativeinterlinespace]}
+
+\def\dosetrelativeinterlinespace
+ {\ifx\currentrelativeinterlinespace\empty\else
+ \spacing\currentrelativeinterlinespace
+ \fi}
+
+\let\setrelativeinterlinespace\relax
+
+% \appendtoks \setrelativeinterlinespace \to \everybodyfont
+
+\def\complexsetupinterlinespace[#1]% \commalistelement ipv #1
+ {\doifassignmentelse{#1}\setupspecifiedinterlinespace\setuprelativeinterlinespace[#1]}
+
+\def\setuplocalinterlinespace[#1]%
+ {\localinterlinespacetrue
+ \setupinterlinespace[#1]%
+ \localinterlinespacefalse}
+
+\def\simplesetupinterlinespace
+ {\localinterlinespacetrue
+ \setfontparameters
+ \updateraggedskips % funny one here
+ \localinterlinespacefalse}
+
+\definecomplexorsimple\setupinterlinespace
+
+\def\removelastskip % a redefinition of plain
+ {\ifvmode\ifdim\lastskip=\zeropoint\else\vskip-\lastskip\fi\fi}
+
+\def\doifoutervmode#1%
+ {\ifvmode\ifinner\else#1\fi\fi}
+
+\ifx\dosomebreak\undefined % defined in mkiv
+
+ \def\dosomebreak#1%
+ {\doifoutervmode
+ {\scratchskip\lastskip
+ \removelastskip
+ %\leavevmode\type{#1}%
+ #1\relax
+ \ifdim\scratchskip=\zeropoint % else interference with footnotes
+ \else
+ \vskip\scratchskip
+ \fi}}
+
+\fi
+
+\def\packed
+ {\nointerlineskip}
+
+\def\godown[#1]%
+ {\relax
+ \ifhmode\endgraf\fi
+ \ifvmode\nointerlineskip\vskip#1\relax\fi}
+
+\ifx\smallskip\undefined
+
+ \def\smallskip{\vskip\smallskipamount}
+ \def\medskip {\vskip\medskipamount}
+ \def\bigskip {\vskip\bigskipamount}
+
+\fi
+
+\ifx\allowbreak\undefined
+
+ \def\break {\penalty\ifhmode-\plustenthousand\else\ejectpenalty\fi}
+ \def\nobreak {\penalty \plustenthousand}
+ \def\allowbreak{\penalty \zeropoint}
+ \def\filbreak {\par\vfil\penalty-200\vfilneg}
+ \def\goodbreak {\par\penalty-500 }
+
+\fi
+
+%D Made slightly more readable:
+
+\ifx\vglue\undefined
+
+ \def\vglue {\afterassignment\dovglue\scratchskip=}
+ \def\hglue {\afterassignment\dohglue\scratchskip=}
+ \def\topglue{\nointerlineskip\vglue-\topskip\vglue}
+
+ \def\dovglue
+ {\par
+ \scratchdimen\prevdepth
+ \hrule\!!height\zeropoint
+ \nobreak\vskip\scratchskip
+ \prevdepth\scratchdimen}
+
+ \def\dohglue
+ {\dontleavehmode % \leavevmode
+ \scratchcounter\spacefactor
+ \vrule\!!width\zeropoint
+ \nobreak\hskip\scratchskip
+ \spacefactor\scratchcounter}
+
+\fi
+
+\ifx\eject\undefined
+
+ \def\eject{\par\break}
+
+\fi
+
+\ifx\supereject\undefined
+
+ \def\supereject{\par\penalty\superpenalty}
+
+\fi
+
+\ifx\dosupereject\undefined
+
+ \def\dosupereject
+ {\ifnum\insertpenalties>\zerocount % something is being held over
+ \line{}
+ \kern-\topskip
+ \nobreak
+ \vfill\supereject
+ \fi}
+
+\fi
+
+%D We adapt plain's \type {\removelastskip} a bit:
+
+\ifx\removelastskip\undefined
+
+ \def\removelastskip
+ {\ifvmode \ifdim\lastskip=\zeropoint \else
+ \vskip-\lastskip
+ \fi \fi}
+
+\fi
+
+\ifx\smallbreak\undefined
+
+\def\smallbreak
+ {\par
+ \ifdim\lastskip<\smallskipamount
+ \removelastskip
+ \penalty-50
+ \smallskip
+ \fi}
+
+\def\medbreak
+ {\par
+ \ifdim\lastskip<\medskipamount
+ \removelastskip
+ \penalty-100
+ \medskip
+ \fi}
+
+\def\bigbreak
+ {\par
+ \ifdim\lastskip<\bigskipamount
+ \removelastskip
+ \penalty-200
+ \bigskip
+ \fi}
+
+\fi
+
+\newskip\ctxparskip \ctxparskip\zeropoint
+
+\newconditional \flexiblewhitespace \settrue\flexiblewhitespace
+
+\def\currentwhitespace {\zeropoint}
+
+\definecomplexorsimple\setupwhitespace
+
+\def\simplesetupwhitespace
+ {\doifnot\currentwhitespace\v!none\dosetupwhitespace}
+
+\def\complexsetupwhitespace[#1]%
+ {\edef\nextcurrentwhitespace{#1}%
+ \ifx\nextcurrentwhitespace\empty
+ \simplesetupwhitespace
+ \else
+ \let\currentwhitespace\nextcurrentwhitespace
+ \dosetupwhitespace
+ \fi}
+
+\def\dosetupwhitespace % quick test for no list
+ {\ifcsname\??ws\??ws\currentwhitespace\endcsname
+ \csname\??ws\??ws\currentwhitespace\endcsname
+ \else
+ \expandafter\processcommalist\expandafter[\currentwhitespace]\dowhitespacemethod % can be raw
+ \fi\relax
+ \ifgridsnapping
+ \setfalse\flexiblewhitespace
+ \ifdim\ctxparskip>\zeropoint
+ \ctxparskip
+ \ifcase\baselinegridmode
+ \baselineskip % normal ! ! ! ! !!
+ \or
+ \ifdim\scratchdimen=\baselineskip % maybe range
+ \baselineskip % normal ! ! ! ! !!
+ \else
+ \numexpr\ctxparskip/\dimexpr.5\lineheight\relax\relax\dimexpr.5\lineheight\relax
+ \fi
+ \else
+ \baselineskip % normal ! ! ! ! !!
+ \fi
+ \fi
+ \else
+ \ifconditional\flexiblewhitespace \else \ctxparskip1\ctxparskip \fi
+ \fi
+ \parskip\ctxparskip}
+
+\chardef\baselinegridmode=0 % option in layout / 1=permit_half_lines
+
+\def\dodosetupwhitespace
+ {\ifgridsnapping
+ \setfalse\flexiblewhitespace
+ \ctxparskip1\ctxparskip
+ \ifdim\ctxparskip>\zeropoint
+ \ifcase\baselinegridmode
+ \ctxparskip\baselineskip % normal ! ! ! ! !!
+ \or
+ \ifdim\scratchdimen=\baselineskip % maybe range
+ \ctxparskip\baselineskip % normal ! ! ! ! !!
+ \else
+ \ctxparskip\numexpr\ctxparskip/\dimexpr.5\lineheight\relax\relax\dimexpr.5\lineheight\relax
+ \fi
+ \else
+ \ctxparskip\baselineskip % normal ! ! ! ! !!
+ \fi
+ \fi
+ \else
+ \ifconditional\flexiblewhitespace \else \ctxparskip1\ctxparskip \fi
+ \fi
+ \parskip\ctxparskip}
+
+\definesystemvariable {ws} % whitespace
+
+\def\definewhitespacemethod[#1]#2{\setvalue{\??ws\??ws#1}{#2}}
+
+\definewhitespacemethod [\v!fix] {}
+\definewhitespacemethod [\v!fixed] {\setfalse\flexiblewhitespace}
+\definewhitespacemethod [\v!flexible] {\settrue\flexiblewhitespace}
+\definewhitespacemethod [\v!line] {\ctxparskip \baselineskip}
+\definewhitespacemethod [\v!halfline] {\ctxparskip.5\baselineskip}
+\definewhitespacemethod [\v!none] {\ctxparskip \zeropoint}
+\definewhitespacemethod [\v!big] {\ctxparskip \bigskipamount}
+\definewhitespacemethod [\v!medium] {\ctxparskip \medskipamount}
+\definewhitespacemethod [\v!small] {\ctxparskip \smallskipamount}
+
+\definewhitespacemethod [\s!default] {\simplesetupwhitespace} % {\stelwitruimteopnieuwin}
+
+% \def\dowhitespacemethod#1%
+% {\executeifdefined{\??ws\??ws#1}{\ctxparskip#1}\relax}
+
+\def\dowhitespacemethod#1%
+ {\ifcsname\??ws\??ws#1\endcsname\csname\??ws\??ws#1\endcsname\else\ctxparskip#1\fi\relax}
+
+% \def\nowhitespace
+% {\ifdim\parskip>\zeropoint\relax
+% \ifdim\lastskip=-\parskip
+% \else
+% \vskip-\parskip
+% \fi
+% \fi}
+
+\def\nowhitespace
+ {}
+
+\def\nowhitespaceunlessskip
+ {\ifdim\lastskip>\zeropoint \else
+ \nowhitespace
+ \fi}
+
+\def\redowhitespace
+ {\ifdim\lastskip>-\parskip \else
+ \vskip\parskip
+ \fi}
+
+\def\savecurrentwhitespace {\edef\savedcurrentwhitespace{\currentwhitespace}}
+\def\restorecurrentwhitespace{\edef\currentwhitespace{\savedcurrentwhitespace}}
+
+\def\savedcurrentwhitespace{\currentwhitespace}
+
+% deze variant is nodig binnen \startopelkaar
+% steeds testen:
+%
+% \hoofdstuk{..}
+% \plaatslijst[..]
+% \hoofdstuk{..}
+% \input tufte
+%
+% met/zonder witruimte
+
+% \def\whitespace
+% {\par
+% \ifdim\parskip>\zeropoint\relax
+% %\ifdim\lastskip>\parskip \else
+% % \removelastskip interferes with blanko blokkeer en klein
+% \vskip\parskip
+% %\fi
+% \fi}
+
+\def\whitespace
+ {\vspacing[\v!white]}
+
+% De onderstaande macro handelt ook de situatie dat er geen
+% tekst tussen \start ... \stop is geplaatst. Daartoe wordt de
+% laatste skip over de lege tekst heen gehaald. Dit komt goed
+% van pas bij het plaatsen van (mogelijk lege) lijsten.
+
+\newif\ifopelkaar
+
+\newsignal \noparskipsignal % \def\noparskipsignal {0.00001pt}
+\def\lastdoneparskip {0pt}
+
+\def\startpacked
+ {\dosingleempty\dostartpacked}
+
+\def\dostartpacked[#1]% nesting afvangen
+ {\par
+ \ifvmode
+ \bgroup
+ \blank[\v!disable]
+ \setupwhitespace[\v!none]
+ \fi}
+
+\def\stoppacked
+ {\par
+ \ifvmode
+ \egroup
+ \fi}
+
+\def\startunpacked
+ {\blank
+ \bgroup}
+
+\def\stopunpacked
+ {\egroup
+ \blank}
+
+% De onderstaande macro's moeten nog eens nader worden uitgewerkt.
+% Ze spelen een rol bij de spatiering rond omkaderde teksten
+% en/of boxen zonder diepte.
+
+% \prevdepth crosses pageboundaries!
+%
+% todo: a version that works ok inside a box
+
+\let\doaroundlinecorrection\relax
+
+\def\startlinecorrection
+ {\dodoubleempty\dostartlinecorrection}
+
+\def\dostartlinecorrection[#1][#2]% #2 gobbles spaces
+ {\bgroup
+ \processaction
+ [#1]
+ [ \v!blank=>\let\doaroundlinecorrection\blank,
+ \s!default=>\let\doaroundlinecorrection\relax,
+ \s!unknown=>{\def\doaroundlinecorrection{\blank[#1]}}]%
+ \doaroundlinecorrection
+ \startbaselinecorrection
+ \offbaselinecorrection
+ \ignorespaces}
+
+\def\stoplinecorrection
+ {\stopbaselinecorrection
+ \doaroundlinecorrection
+ \egroup}
+
+\def\correctwhitespace
+ {\dowithnextbox
+ {\startbaselinecorrection
+ \flushnextbox
+ \stopbaselinecorrection}%
+ \vbox}
+
+\def\verticalstrut {\normalvbox{\hsize\zeropoint\forgetall\strut}}
+\def\horizontalstrut{\normalhbox {\strut}}
+
+% Hieronder volgen enkele instellingen en macro's ten behoeve
+% van de interlinie en \strut. De waarden 2.8, 0.07, 0.72 en
+% 0.28 zijn ooit eens ontleend aan INRS-TEX en moeten wellicht
+% nog eens instelbaar worden.
+%
+% \lineheight : de hoogte van een regel
+% \spacing{getal} : instellen interlinie
+% \normalbaselines : instellen regelafstend
+%
+% \setstrut : instellen \strut
+% \setnostrut : resetten \strut, \endstrut, \begstrut
+%
+% \setteststrut : instellen zichtbare struts
+% \resetteststrut : instellen onzichtbare struts
+%
+% \setfontparameters : instellen na fontset
+%
+% De hoogte van een regel (\lineheight) is gelijk aan de
+% som van de hoogte (\ht) en diepte (\dp) van \strutbox.
+%
+% \strut : denkbeeldig blokje met hoogte en diepte
+%
+% Een \hbox kan als deze aan het begin van een regel staat
+% een breedte \hsize krijgen. Dit is soms te voorkomen met het
+% commando \leavevmode. Binnen een \vbox geeft dit echter
+% niet altijd het gewenste resultaat, vandaar het commando
+%
+% \leaveoutervmode
+
+% Pas op: niet zomaar \topskip en \baselineskip aanpassen
+% en zeker niet \widowpenalty. Dit kan ernstige gevolgen
+% hebben voor kolommen.
+%
+% Enige glue kan op zich geen kwaad, echter als blanko=vast,
+% dan moet ook de rek 0 zijn. Binnen kolommen is rek ook
+% niet bepaald mooi. Een hele kleine waarde (0.025) voldoet,
+% omdat een positieve glue eindeloos rekbaar is.
+
+\newdimen\strutdimen
+\newdimen\lineheight
+\newdimen\openlineheight
+\newdimen\openstrutheight
+\newdimen\openstrutdepth
+\newdimen\topskipgap
+\newdimen\struttotal
+
+\def\strutheightfactor {.72}
+\def\strutdepthfactor {.28}
+
+\def\baselinefactor {2.8}
+\def\baselinegluefactor {0}
+
+\def\minimumstrutheight {0pt}
+\def\minimumstrutdepth {0pt}
+
+\def\normallineheight {\baselinefactor ex}
+\def\minimumlinedistance {\lineskip}
+
+\def\strutheight {0pt}
+\def\strutdepth {0pt}
+\def\strutwidth {0pt}
+
+\let\spacingfactor \plusone
+
+\def\topskipfactor {1.0}
+\def\maxdepthfactor {0.5}
+
+\def\systemtopskipfactor {\topskipfactor}
+\def\systemmaxdepthfactor {\maxdepthfactor}
+
+% De onderstaande definitie wordt in de font-module overruled
+
+\ifdefined\globalbodyfontsize\else
+ \newdimen\globalbodyfontsize
+ \globalbodyfontsize=12pt
+\fi
+
+\ifx\normalizedbodyfontsize\undefined
+ \def\normalizedbodyfontsize{12pt}
+\fi
+
+% door een \dimen. Dit is geen probleem omdat (1) de default
+% korpsgrootte 12pt is en (2) de fonts nog niet geladen zijn
+% en de instellingen bij het laden nogmaals plaatsvinden.
+
+\def\topskipcorrection
+ {\simpletopskipcorrection
+ \vskip-\struttotal
+ \verticalstrut}
+
+\def\simpletopskipcorrection
+ {\ifdim\topskip>\openstrutheight
+ % == \vskip\topskipgap
+ \vskip\topskip
+ \vskip-\openstrutheight
+ \fi}
+
+\def\settopskip % the extra test is needed for the lbr family
+ {\topskip\systemtopskipfactor\globalbodyfontsize
+ \ifgridsnapping \else
+ \ifr@ggedbottom\!!plus5\globalbodyfontsize\fi
+ \fi
+ \relax % the skip
+ \topskipgap\topskip
+ \advance\topskipgap -\openstrutheight\relax
+\ifdim\minimumstrutheight>\zeropoint
+ \ifdim\topskip<\minimumstrutheight
+ \topskip\minimumstrutheight\relax
+ \fi
+\else
+ \ifdim\topskip<\strutheightfactor\openlineheight
+ \topskip\strutheightfactor\openlineheight\relax
+ \fi
+\fi}
+
+\def\setmaxdepth
+ {\maxdepth\systemmaxdepthfactor\globalbodyfontsize}
+
+\def\normalbaselines
+ {\baselineskip \normalbaselineskip
+ \lineskip \normallineskip
+ \lineskiplimit\normallineskiplimit}
+
+\def\setnormalbaselines
+ {\ifdim\normallineheight>\zeropoint
+ \lineheight\normallineheight
+ \fi
+ \openlineheight\spacingfactor\lineheight
+ \openstrutheight \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight % new
+ \else
+ \strutheightfactor\openlineheight
+ \fi
+ \openstrutdepth \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth % new
+ \else
+ \strutdepthfactor \openlineheight
+ \fi
+ \ifdim\dimexpr\minimumstrutdepth+\minimumstrutheight\relax>\zeropoint
+ \openlineheight\dimexpr\openstrutheight+\openstrutdepth\relax % new
+ \fi
+ \normalbaselineskip\openlineheight
+ \ifgridsnapping\else
+ \!!plus \baselinegluefactor\openlineheight
+ \!!minus\baselinegluefactor\openlineheight
+ \fi
+ \normallineskip\minimumlinedistance\relax % \onepoint\relax
+ \normallineskiplimit\zeropoint\relax
+ \normalbaselines
+ \dosetupgridsnapping}
+
+\def\spacing#1%
+ {\ifgridsnapping
+ %\ifdim#1\points=\onepoint\else\showmessage\m!layouts{11}{\withoutpt\the\dimexpr#1\points\relax}\fi
+ \let\spacingfactor\plusone
+ \else
+ \edef\spacingfactor{#1}%
+ \fi
+ \edef\systemtopskipfactor {\withoutpt\the\dimexpr#1\dimexpr\topskipfactor \points}%
+ \edef\systemmaxdepthfactor{\withoutpt\the\dimexpr#1\dimexpr\maxdepthfactor\points}%
+ \setnormalbaselines
+ \setstrut}
+
+%D Sometimes one needs to freeze the interlinespacing
+%D
+%D \starttyping
+%D \rm \saveinterlinespace .... {\ss \restoreinterlinespace .... \endgraf}
+%D \stoptyping
+
+\let\restoreinterlinespace\relax
+
+\def\saveinterlinespace
+ {\edef\restoreinterlinespace
+ {\lineheight \the\lineheight
+ \openstrutheight \the\openstrutheight
+ \openstrutdepth \the\openstrutdepth
+ \openlineheight \the\openlineheight
+ \normalbaselineskip \the\normalbaselineskip
+ \normallineskip \the\normallineskip
+ \normallineskiplimit\the\normallineskiplimit
+ \noexpand\def\noexpand\normallineheight{\the\dimexpr\normallineheight}%
+ \noexpand\normalbaselines}}
+
+% plain definition:
+%
+% \def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
+%
+% could be:
+%
+% \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
+
+\ifx\strutbox\undefined
+
+ \newbox\strutbox
+
+ \setbox\strutbox\normalhbox{\vrule height8.5pt depth3.5pt width\zeropoint}
+
+ \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
+
+\fi
+
+\let\normalstrut\strut
+
+% The double \hbox construction enables us to \backtrack
+% boxes.
+
+\let\strutht\undefined \newdimen\strutht
+\let\strutdp\undefined \newdimen\strutdp
+
+\unexpanded\def\setstrut
+ {\ifgridsnapping
+ \setstrutgridyes
+ \else
+ \setstrutgridnop
+ \fi}
+
+\unexpanded\def\setstrutgridyes
+ {\strutht\spacingfactor\dimexpr
+ \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight
+ \else
+ \strutheightfactor\dimexpr\normallineheight
+ \fi
+ \strutdp\dimexpr
+ \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth
+ \else
+ \normallineheight-\strutht
+ \fi
+ \dosetstrut}
+
+\unexpanded\def\setstrutgridnop
+ {\strutht\spacingfactor\dimexpr
+ \ifdim\minimumstrutheight>\zeropoint
+ \minimumstrutheight
+ \else
+ \strutheightfactor\dimexpr\normallineheight
+ \fi
+ \strutdp\spacingfactor\dimexpr
+ \ifdim\minimumstrutdepth>\zeropoint
+ \minimumstrutdepth
+ \else
+ \strutdepthfactor\dimexpr\normallineheight
+ \fi
+ \dosetstrut}
+
+\unexpanded\def\setcharstrut#1%
+ {\setbox\strutbox\normalhbox{#1}%
+ \strutht\ht\strutbox
+ \strutdp\dp\strutbox
+ \dosetstrut}
+
+\unexpanded\def\setfontstrut
+ {\setcharstrut{(gplQT}}
+
+\unexpanded\def\setcapstrut% could be M, but Q has descender
+ {\setcharstrut{Q}}
+
+%D Handy for math (used in mathml):
+
+\def\charhtstrut
+ {\begingroup
+ \setcharstrut{GJY}%
+ \vrule\!!width\zeropoint\!!depth\zeropoint\!!height\strutht
+ \endgroup}
+
+\def\chardpstrut
+ {\begingroup
+ \setcharstrut{gjy}%
+ \vrule\!!width\zeropoint\!!depth\strutdp\!!height\zeropoint
+ \endgroup}
+
+% because of all the callbacks in mkiv, we avoid unnecessary boxes ...
+% maybe use an attribute so that we can tag boxes that don't need a
+% treatment; tests with using an attribute so far have shown that
+% it's slower because testing the attribute takes time too
+
+\def\dosetstrut
+ {\let\strut\normalstrut
+ \edef\strutheight{\the\strutht}%
+ \edef\strutdepth {\the\strutdp}%
+ \ifdim\strutwidth=\zeropoint
+ \dosetstruthide
+ \else
+ \dosetstrutvide
+ \fi
+ \struttotal\dimexpr\strutht+\strutdp\relax}
+
+\def\dosetstruthide
+ {\setbox\strutbox\normalhbox
+ {\vrule
+ \!!width \zeropoint
+ \!!height\strutht
+ \!!depth \strutdp}}
+
+\def\dosetstrutvide
+ {\setbox\strutbox\normalhbox
+ {\normalhbox to \zeropoint
+ {% \hss % new, will be option
+ \vrule
+ \!!width \strutwidth
+ \!!height\strutht
+ \!!depth \strutdp
+ \hss}}}
+
+%D The dimen \type {\struttotal} holds the exact size of the
+%D strut; occasionally a one scaled point difference can show
+%D up with the lineheight.
+
+% experiment
+
+\newbox\emptystrutbox \setbox\emptystrutbox\hbox{}
+
+\def\dosetstruthide
+ {\setbox\strutbox\copy\emptystrutbox
+ \ht\strutbox\strutht
+ \dp\strutbox\strutdp}
+
+\def\strut{\relax\dontleavehmode\copy\strutbox} % still callbacks for \hbox{\strut}
+
+
+\let\normalstrut\strut
+
+%D Sometimes a capstrut comes in handy
+%D
+%D \starttabulate[|Tl|l|l|]
+%D \NC yes \NC normal strut \NC {\showstruts\setupstrut[yes]\strut} \NC \NR
+%D \NC no \NC no strut \NC {\showstruts\setupstrut[no]\strut} \NC \NR
+%D \NC kap \NC a capital strut (i.e. Q) \NC {\showstruts\setupstrut[cap]\strut} \NC \NR
+%D \NC A B \unknown \NC a character strut (e.g. A) \NC {\showstruts\setupstrut[A]\strut} \NC \NR
+%D \NC \NC a normal strut \NC {\showstruts\setupstrut\strut} \NC \NR
+%D \stoptabulate
+
+\def\setupstrut
+ {\dosingleempty\dosetupstrut}
+
+\def\dosetupstrut[#1]% yet undocumented, todo: fontstrut
+ {\processaction
+ [#1]
+ [ \v!yes=>\setstrut,
+ \v!auto=>\setautostrut,
+ \v!no=>\setnostrut,
+ \v!cap=>\setcapstrut,
+ \v!fit=>\setfontstrut,
+ \v!line=>\setstrut,
+ \s!default=>\setstrut,
+ \s!unknown=>\setcharstrut\commalistelement]}
+
+\def\showstruts
+ {\setteststrut
+ \settestcrlf}
+
+\def\setteststrut
+ {\def\strutwidth{.8pt}%
+ \setstrut}
+
+\def\autostrutfactor{1.1}
+
+\def\setautostrut
+ {\begingroup
+ \setbox\scratchbox\copy\strutbox
+ \setstrut
+ \ifdim\strutht>\autostrutfactor\ht\scratchbox
+ \endgroup \setstrut
+ \else\ifdim\strutdp>\autostrutfactor\dp\scratchbox
+ \endgroup \setstrut
+ \else
+ \endgroup
+ \fi\fi}
+
+% when enabled, sigstruts will remove themselves if nothing
+% goes inbetween
+
+\newsignal\strutsignal \setfalse\sigstruts
+
+\def\begstrut
+ {\relax\ifcase\strutht\else
+ \ifconditional\sigstruts
+ \noindent\horizontalstrut
+ \normalpenalty\plustenthousand
+ \normalhskip-\strutsignal
+ \normalhskip\strutsignal
+ \else
+ \strut
+ \normalpenalty\plustenthousand
+ \normalhskip\zeropoint
+ \fi
+ \expandafter \ignorespaces
+ \fi}
+
+\def\endstrut
+ {\relax\ifhmode\ifcase\strutht\else
+ \ifconditional\sigstruts
+ \ifdim\lastskip=\strutsignal
+ \unskip\unskip\unpenalty\setbox\scratchbox\lastbox
+ \else
+ \normalpenalty\plustenthousand
+ \normalhskip\zeropoint
+ \strut
+ \fi
+ \else
+ \removeunwantedspaces
+ \normalpenalty\plustenthousand
+ \normalhskip\zeropoint
+ \strut
+ \fi
+ \fi\fi}
+
+\newbox\nostrutbox \setbox\nostrutbox\normalhbox{} % {\normalhbox{}}
+
+\def\setnostrut
+ {\setbox\strutbox\copy\nostrutbox
+ \let\strut\empty
+ \let\endstrut\empty
+ \let\begstrut\empty
+ \let\crlfplaceholder\empty}
+
+% unsave:
+%
+% \def\pseudostrut
+% {\bgroup
+% \setnostrut
+% \normalstrut
+% \egroup}
+%
+% try:
+%
+% \startchemie
+% \chemie[ONE,Z0,SB15,MOV1,SB15,Z0][C,C]
+% \stopchemie
+%
+% so:
+
+\def\pseudostrut
+ {\noindent} % better: \dontleavehmode
+
+\let\pseudobegstrut\pseudostrut
+
+\let\pseudoendstrut\removeunwantedspaces
+
+\def\resetteststrut
+ {\let\strutwidth\zeropoint
+ \setstrut}
+
+\ifx\setfontparameters\undefined
+ % problems ! ! ! !
+ \def\setfontparameters{\the\everybodyfont}
+\fi
+
+%D Handy:
+
+\def\baselinedistance{\the\lineheight}
+
+%D We need \type{\normaloffinterlineskip} because the new
+%D definition contains an assignment, and |<|don't ask me
+%D why|>| this assignment gives troubles in for instance the
+%D visual debugger.
+
+%D The plain ones:
+
+\def\offinterlineskip
+ {\baselineskip-\thousandpoint
+ \lineskip\zeropoint
+ \lineskiplimit\maxdimen}
+
+\def\nointerlineskip
+ {\prevdepth-\thousandpoint}
+
+\let\normaloffinterlineskip=\offinterlineskip % knuth's original
+
+%D My own one:
+
+\def\dopushinterlineskip
+ {\edef\oninterlineskip
+ {\baselineskip\the\baselineskip
+ \lineskip\the\lineskip
+ \lineskiplimit\the\lineskiplimit
+ \let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}}
+
+\def\nopushinterlineskip
+ {\let\oninterlineskip\setnormalbaselines}
+
+\def\offinterlineskip
+ {\ifdim\baselineskip>\zeropoint
+ \dopushinterlineskip
+ \else
+ \nopushinterlineskip
+ \fi
+ \normaloffinterlineskip}
+
+\let\oninterlineskip=\relax
+
+\def\leaveoutervmode
+ {\ifvmode\ifinner\else
+ \leavevmode
+ \fi\fi}
+
+% We stellen enkele penalties anders in dan Plain TEX:
+
+% oud
+%
+% \widowpenalty=\defaultwidowpenalty\relax
+% \clubpenalty =\defaultclubpenalty \relax
+
+\def\resetpenalties#1%
+ {\ifx#1\undefined\else
+ #1\minusone
+ \fi}
+
+\def\setpenalties#1#2#3%
+ {\ifx#1\undefined\else % space before #3 prevents lookahead problems, needed when #3=text
+ #1\numexpr#2+\plusone\relax\space\doexpandedrecurse{\the\numexpr#2\relax}{ #3}\zerocount\relax
+ \fi}
+
+\def\doexpandedrecurse#1#2%
+ {\ifnum#1>\zerocount#2\@EA\doexpandedrecurse\@EA{\the\numexpr#1-1\relax}{#2}\fi}
+
+%D \macros
+%D {keeplinestogether}
+%D
+%D Dirty hack, needed in margin content that can run of a page.
+
+% just before margintexts ... will eventually be done differently in mkiv using
+% attributes
+
+\newcount\nofkeeplinestogether
+\let\restoreinterlinepenalty\relax
+
+\def\dorestoreinterlinepenalty
+ {\global\let\restoreinterlinepenalty\relax
+ \global\resetpenalties\interlinepenalties
+ \global\nofkeeplinestogether\zerocount}
+
+\def\keeplinestogether#1%
+ {\ifnum#1>\nofkeeplinestogether
+ \global\nofkeeplinestogether#1%
+ \global\setpenalties\interlinepenalties\nofkeeplinestogether\plustenthousand
+ \global\let\restoreinterlinepenalty\dorestoreinterlinepenalty
+ \fi}
+
+\newif\ifgridsnapping % to be sure
+
+\def\defaultwidowpenalty {2000} % was: 1000
+\def\defaultclubpenalty {2000} % was: 800
+\def\defaultdisplaywidowpenalty {50}
+\def\defaultbrokenpenalty {100}
+
+\def\defaultgridwidowpenalty {0}
+\def\defaultgridclubpenalty {0}
+\def\defaultgriddisplaywidowpenalty {0}
+\def\defaultgridbrokenpenalty {0}
+
+\def\nopenalties
+ {\widowpenalty \zerocount
+ \clubpenalty \zerocount
+ \brokenpenalty \zerocount
+ \doublehyphendemerits\zerocount
+ \finalhyphendemerits \zerocount
+ \adjdemerits \zerocount}
+
+\def\setdefaultpenalties
+ {\directsetup{\systemsetupsprefix\s!default}}
+
+\startsetups [\systemsetupsprefix\s!reset]
+ \resetpenalties\widowpenalties
+ \resetpenalties\clubpenalties
+ \resetpenalties\interlinepenalties
+\stopsetups
+
+% we use \directsetup because it's faster and we know there is no csl
+
+\startsetups [\systemsetupsprefix\s!default]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \widowpenalty \defaultwidowpenalty
+ \clubpenalty \defaultclubpenalty
+ \displaywidowpenalty\defaultdisplaywidowpenalty
+ \brokenpenalty \defaultbrokenpenalty
+
+\stopsetups
+
+\startsetups [\v!grid] [\systemsetupsprefix\s!default]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \widowpenalty \defaultgridwidowpenalty
+ \clubpenalty \defaultgridclubpenalty
+ \displaywidowpenalty\defaultgriddisplaywidowpenalty
+ \brokenpenalty \defaultgridbrokenpenalty
+
+\stopsetups
+
+% as an illustration:
+
+\startsetups [\systemsetupsprefix\v!strict]
+
+ \directsetup{\systemsetupsprefix\s!reset}
+
+ \setpenalties\widowpenalties2\maxdimen
+ \setpenalties\clubpenalties 2\maxdimen
+ \brokenpenalty \maxdimen
+
+\stopsetups
+
+\setdefaultpenalties % will happen later in \setuplayout
+
+%D To be checked:
+
+\ifx\savedstrutbox\undefined \newbox\savedstrutbox \fi
+
+\def\savestrut {\setbox\savedstrutbox\copy\strutbox}
+\def\savedstrut{\copy \savedstrutbox}
+
+%D Page spacing
+
+\chardef\bottomraggedness=0 % 0=ragged 1=normal/align 2=baseline
+
+\def\bottomalignlimit{3\lineheight}
+
+\newif\ifn@rmalbottom
+\newif\ifr@ggedbottom
+\newif\ifb@selinebottom
+
+\def\normalbottom
+ {% \topskip 10pt
+ \r@ggedbottomfalse}
+
+\def\raggedbottom
+ {\chardef\bottomraggedness\zerocount
+ \n@rmalbottomfalse
+ \r@ggedbottomtrue
+ \b@selinebottomfalse
+ \settopskip}
+
+\def\alignbottom
+ {\chardef\bottomraggedness\plusone
+ \n@rmalbottomtrue
+ \r@ggedbottomfalse
+ \b@selinebottomfalse
+ \settopskip}
+
+\def\baselinebottom
+ {\chardef\bottomraggedness\plustwo
+ \n@rmalbottomfalse
+ \r@ggedbottomfalse
+ \b@selinebottomtrue
+ \settopskip}
+
+\let\normalbottom=\alignbottom % downward compatible
+
+% so, the new one will be
+%
+% \chardef\bottomraggedness=0 % 0=ragged 1=normal/align 2=baseline
+%
+% \def\bottomalignlimit{3\lineheight} % will be settable
+%
+% \def\raggedbottom {\chardef\bottomraggedness=0 \settopskip}
+% \def\alignbottom {\chardef\bottomraggedness=1 \settopskip}
+% \def\baselinebottom{\chardef\bottomraggedness=2 \settopskip}
+%
+% \let\normalbottom =\alignbottom
+
+%D Good old blank:
+
+\definesystemattribute[kern-chars]
+\definesystemattribute[skip-category] \chardef\skipcategoryattribute \dogetattributeid{skip-category}
+\definesystemattribute[skip-penalty] \chardef\skippenaltyattribute \dogetattributeid{skip-penalty}
+\definesystemattribute[skip-order] \chardef\skiporderattribute \dogetattributeid{skip-order}
+\definesystemattribute[snap-category]
+\definesystemattribute[display-math]
+
+% \start \dosetstretch{.25em} \setuptolerance[tolerant,stretch] \input tufte \endgraf \stop
+% \start \dosetstretch{.5em} effe flink doorfietsen \stop
+
+\def\dosetupgridsnapping % calls too often, only needed in gridsnapping
+ {\ctxlua{nodes.setsnapvalue(1,\number\openstrutheight,\number\openstrutdepth)}}
+
+\def\doenablegridsnapping
+ {\dosetattribute{snap-category}{1}%
+ \topskip\strutht
+ \offinterlineskip}
+
+\def\dodisablegridsnapping
+ {\doresetattribute{snap-category}%
+ % reset topskip
+ \oninterlineskip}
+
+% experimental code, not yet interfaced:
+
+% category:
+% 0 == discard discard
+% 1 == only if larger largest
+% 2 == force even if smaller force
+% 3 == only take penalty component penalty
+% 4 == add to existing skip add
+% 5 == disable (ignore following) disable
+% 6 == kill whitespace nowhite
+% 7 == discard previous back
+%
+% penalty: larger wins
+% order: larger wins
+% category:2,order:5,penalty:10000,skip:value|kw
+%
+% always -- obsolete
+% none -- obsolete
+% outer -- obsolete
+% reset -- obsolete
+% \defineblankmethod [\v!joinedup] {\ifvmode\nointerlineskip\fi}
+
+% todo, in grid mode: vspacing.fixed = false
+
+\let\saveouterspacing \relax % for old times sake
+\let\restoreouterspacing\relax % for old times sake
+
+\newtoks\everybeforeblankhandling
+\newtoks\everyafterblankhandling
+
+\appendtoks
+ \blankskip\zeropoint
+ \attribute\skipcategoryattribute\plusone
+ \attribute\skippenaltyattribute \attributeunsetvalue
+ \attribute\skiporderattribute \attributeunsetvalue
+ \ifgridsnapping % \ifblankflexible
+ \setfalse\blankisfixed
+ \else
+ \settrue\blankisfixed
+ \fi
+\to \everybeforeblankhandling
+
+\appendtoks
+ \ifconditional\blankisfixed
+ \blankskip1\blankskip
+ \else
+ \blankskip1\blankskip\!!plus\skipgluefactor\blankskip\!!minus\skipgluefactor\blankskip
+ \fi
+\to \everyafterblankhandling
+
+\def\setblankcategory#1{\attribute\skipcategoryattribute#1\relax}
+\def\setblankorder #1{\attribute\skiporderattribute #1\relax}
+\def\setblankpenalty #1{\attribute\skippenaltyattribute #1\relax}
+\def\addblankskip#1#2#3{\advance\blankskip#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax}
+\def\fixedblankskip {\settrue \blankisfixed} % \blankskip1\blankskip}
+\def\flexibleblankskip {\setfalse\blankisfixed} % \blankskip1\blankskip\!!plus\skipgluefactor\blankskip\!!minus\skipgluefactor\blankskip}
+
+\def\startblankhandling
+ {\begingroup
+ \the\everybeforeblankhandling}
+
+\def\stopblankhandling
+ {\the\everyafterblankhandling
+ \vskip\blankskip
+ \endgroup}
+
+\def\flushblankhandling
+ {\the\everyafterblankhandling
+ \vskip\blankskip
+ \the\everybeforeblankhandling}
+
+% % % %
+
+\def\definevspacingamount
+ {\dotripleempty\dodefinevspacingamount}
+
+\def\dodefinevspacingamount[#1][#2][#3]%
+ {\ctxlua{vspacing.setskip("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}}
+
+\def\definevspacing
+ {\dodoubleempty\dodefinevspacing}
+
+\def\dodefinevspacing[#1][#2]%
+ {\ctxlua{vspacing.setmap("#1","#2")}}
+
+\unexpanded\def\vspacing
+ {\dosingleempty\dovspacing}
+
+\def\dovspacing[#1]%
+ {\ctxlua{vspacing.analyse("\iffirstargument#1\else\s!default\fi")}}
+
+% todo: checm them and make them faster:
+
+\definecomplexorsimple\setupvspacing
+
+\let\currentvspacing\empty
+
+\def\complexsetupvspacing[#1]%
+ {\edef\currentvspacing{#1}}
+
+\def\simplesetupvspacing
+ {\ifx\empty\currentvspacing\else
+ \let\currentvspacing\s!default
+ \fi
+ \simplesetupwhitespace}
+
+\def\restorestandardblank
+ {\let\currentvspacing\v!standard}
+
+% used both
+
+\def\doinhibitblank{\vspacing[\v!disable]} % can be made faster
+\def\inhibitblank {\vspacing[\v!disable]} % can be made faster
+
+\let\setupblank \setupvspacing
+\let\simplesetupblank\simplesetupvspacing
+\let\blank \vspacing
+
+% category:4 is default
+
+\definevspacingamount[\v!big] [\bigskipamount] [\openlineheight]
+\definevspacingamount[\v!medium] [\medskipamount] [0.50\openlineheight]
+\definevspacingamount[\v!small] [\smallskipamount] [0.25\openlineheight]
+\definevspacingamount[\v!line] [\openlineheight] [\openlineheight]
+\definevspacingamount[\v!halfline][0.50\openlineheight][0.50\openlineheight]
+\definevspacingamount[\v!formula] [\medskipamount] [0.50\openlineheight]
+\definevspacingamount[\v!white] [\parskip] [\openlineheight]
+\definevspacingamount[\v!height] [\strutheight] [\strutheight]
+\definevspacingamount[\v!depth] [\strutdepth] [\strutdepth]
+
+\definevspacing[\v!samepage][penalty:10000]
+\definevspacing[\v!max] [category:1]
+\definevspacing[\v!force] [category:2]
+\definevspacing[\v!disable] [category:5]
+\definevspacing[\v!nowhite] [category:6]
+\definevspacing[\v!back] [category:7]
+\definevspacing[\v!always] [category:0]
+\definevspacing[\v!weak] [order:0]
+\definevspacing[\v!strong] [order:100]
+
+\definevspacing[\s!default] [\v!white] % was big for a while
+
+\setfalse\vspacingenabled
+
+\newtoks\everyenablevspacing
+\newtoks\everydisablevspacing
+
+\def\enablevspacing {\the\everyenablevspacing}
+\def\disablevspacing{\the\everydisablevspacing}
+
+\appendtoks
+ \writestatus\m!systems{! ! enabling vspacing ! !}%
+ \settrue\vspacingenabled
+ \ctxlua{vspacing.enable()}%
+\to \everyenablevspacing
+
+\appendtoks
+ \writestatus\m!systems{! ! disabling vspacing ! !}%
+ \setfalse\vspacingenabled
+ \ctxlua{vspacing.disable()}%
+\to \everydisablevspacing
+
+\global\let\blank \vspacing
+\global\let\defineblank\definevspacing
+
+% moved from page-lin
+
+%D When spacing is active we need to handle commands in
+%D a special way:
+%D
+%D \starttyping
+%D \setuplines[space=on]
+%D
+%D \startlines
+%D Let's talk about this{\ttsl\gobbleoneargument or}that.
+%D \stoplines
+%D
+%D \startlines
+%D Let's talk about this{\getvalue{ttsl}or}that.
+%D \stoplines
+%D \stoptyping
+%D
+%D One can indent in several ways:
+%D
+%D \starttyping
+%D \setupindenting[medium] \setuplines[indenting=odd] % no yes odd even
+%D
+%D \startlines
+%D first
+%D second
+%D third
+%D fourth
+%D \stoplines
+%D \stoptyping
+
+\def\setuplines
+ {\dodoubleargument\getparameters[\??rg]}
+
+\def\startlines
+ {\@@rgbefore
+ \pushmacro\checkindentation
+ \whitespace
+ %\page[\v!preference]} gaat mis na koppen, nieuw: later \nobreak
+ \begingroup
+ \setupindenting[\@@rgindenting]%
+ \typesettinglinestrue
+ \setupwhitespace[\v!none]%
+ \obeylines
+ \ignorespaces
+ \gdef\afterfirstobeyedline % tzt two pass, net als opsomming
+ {\gdef\afterfirstobeyedline
+ {\nobreak
+ \doifnot\@@rgoption\v!packed{\global\let\afterfirstobeyedline\relax}}}%
+ \def\obeyedline
+ {\par
+ \futurelet\next\dobetweenthelines}%
+ \activatespacehandler\@@rgspace
+ \GotoPar}
+
+\def\stoplines
+ {\endgroup
+ \popmacro\checkindentation
+ \@@rgafter}
+
+\def\dobetweenthelines
+ {\doifmeaningelse\next\obeyedline
+ {\@@rginbetween}
+ {\afterfirstobeyedline}}
+
+\setuplines
+ [\c!option=,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!inbetween=\blank,
+ \c!indenting=\v!no,
+ \c!space=\v!default]
+
+\def\emptylines
+ {\dosingleempty\doemptylines}
+
+\def\doemptylines[#1]%
+ {\endgraf\dorecurse{\iffirstargument#1\else3\fi}\crlf}
+
+\protect \endinput
+
+\dorecurse{2}{
+ $2^{2^{2^{2}}}$ $2_{2_{2_{2}}}^{2^{2^{2^{2^{2^{2^{2^{2^{2}}}}}}}}}$
+ \input tufte \inframed {tufte}
+ \par
+}
+
+\dorecurse{100} {
+
+ \kern \recurselevel pt
+
+ \vbox {
+ \endgraf \strut first \endgraf
+ {\dosetattribute{skip-category}{1}\vskip10pt}
+ {\dosetattribute{skip-category}{1}\vskip40pt}
+ {\dosetattribute{skip-category}{1}\vskip20pt}
+ {\dosetattribute{skip-category}{2}\vskip10pt}
+ \endgraf \strut second \endgraf
+ }
+
+ \endgraf \strut first \endgraf
+ {\dosetattribute{skip-category}{1}\vskip10pt}
+ {\dosetattribute{skip-category}{1}\vskip40pt}
+ {\dosetattribute{skip-category}{1}\vskip20pt}
+ {\dosetattribute{skip-category}{1}\vskip40pt}
+ \endgraf \strut second \endgraf
+
+ {\dosetattribute{skip-category}{0}\vskip10pt} % remove
+ {\dosetattribute{skip-category}{1}\vskip10pt} % take largest
+ {\dosetattribute{skip-category}{1}\vskip40pt}
+ {\dosetattribute{skip-category}{1}\vskip40pt}
+ {\dosetattribute{skip-category}{1}\vskip40pt}
+ {\dosetattribute{skip-category}{1}\vskip40pt}
+ {\dosetattribute{skip-category}{1}\vskip40pt}
+ {\dosetattribute{skip-category}{1}\dosetattribute{skip-order}{10}\vskip20pt}
+ {\dosetattribute{skip-category}{4}\dosetattribute{skip-order}{10}\vskip20pt}
+ {\dosetattribute{skip-category}{1}\vskip60pt}
+ {\dosetattribute{skip-category}{1}\vskip20pt}
+ {\dosetattribute{skip-category}{0}\vskip10pt}
+
+ third (no break after this)
+
+ {\dosetattribute{skip-category}{1}\dosetattribute{skip-penalty}{100000}\vskip10pt}
+ {\dosetattribute{skip-category}{1}\dosetattribute{skip-penalty}{100000}\vskip20pt}
+ {\dosetattribute{skip-category}{1}\vskip10pt}
+ {\dosetattribute{skip-category}{1}\vskip20pt}
+
+ fourth
+ \vskip10pt
+ fifth
+}