summaryrefslogtreecommitdiff
path: root/tex/context/base/supp-box.tex
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/supp-box.tex')
-rw-r--r--tex/context/base/supp-box.tex2668
1 files changed, 1560 insertions, 1108 deletions
diff --git a/tex/context/base/supp-box.tex b/tex/context/base/supp-box.tex
index fb9e1e2d1..87c2c78f7 100644
--- a/tex/context/base/supp-box.tex
+++ b/tex/context/base/supp-box.tex
@@ -1,1108 +1,1560 @@
-% NEW
-
-\unprotect
-
-% limitatetext -> beter {text} als laatste !!
-
-% \limitvbox
-% \limithbox
-
-\def\limitatelines#1#2% size sentinel
- {\dowithnextbox
- {\dimen0=#1\hsize
- \ifdim\wd\nextbox>\dimen0
- \setbox\nextbox=\hbox
- {\advance\dimen0 by -.1\hsize
- \limitatetext{\unhbox\nextbox}{\dimen0}{\nobreak#2}}%
- \fi
- \unhbox\nextbox}
- \hbox}
-
-\def\fittoptobaselinegrid% weg hier
- {\dowithnextbox
- {\bgroup
- \par
- \dimen0=\ht\nextbox
- \ht\nextbox=\ht\strutbox
- \dp\nextbox=\dp\strutbox
- \hbox{\box\nextbox}
- \prevdepth\dp\strutbox
- \doloop
- {\advance\dimen0 by -\lineheight
- \ifdim\dimen0<\!!zeropoint
- \exitloop
- \else
- \nobreak
- \hbox{\strut}
- \fi}
- \egroup}
- \vbox}
-
-\protect
-
-%D \module
-%D [ file=supp-box,
-%D version=1995.10.10,
-%D title=\CONTEXT\ Support Macros,
-%D subtitle=Boxes,
-%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. Non||commercial use is
-%C granted.
-
-%D This module implements some box manipulation macros. Some
-%D are quite simple, some are more advanced and when understood
-%D well, all can be of use.
-
-\writestatus{loading}{Context Support Macros / Boxes}
-
-\unprotect
-
-%D \macros
-%D {nextdepth}
-%D {}
-%D
-%D Let's start with a rather simple declaration. Sometimes we
-%D need to save the \TEX\ \DIMENSION\ \type{\prevdepth} and
-%D append it later on. The name \type{\nextdepth} suits
-%D this purpose well.
-
-\newdimen\nextdepth
-
-%D \macros
-%D {smashbox}
-%D {}
-%D
-%D Smashing is introduced in \PLAIN\ \TEX, and stands for
-%D reducing the dimensions of a box to zero. The most resolute
-%D one is presented first.
-
-\def\smashbox#1%
- {\wd#1=\!!zeropoint
- \ht#1=\!!zeropoint
- \dp#1=\!!zeropoint}
-
-%D \macros
-%D {hsmashbox,vsmashbox}
-%D {}
-%D
-%D Smashing can be used for overlaying boxes. Depending on
-%D the mode, horizontal or vertical, one can use:
-
-\def\hsmashbox#1%
- {\wd#1=\!!zeropoint}
-
-\def\vsmashbox#1%
- {\ht#1=\!!zeropoint
- \dp#1=\!!zeropoint}
-
-%D \macros
-%D {hsmash,vsmash,
-%D hsmashed,vsmashed}
-%D {}
-%D
-%D While the previous macros expected a \BOX, the next act on a
-%D content. They are some subtle differences betreen the smash
-%D and smashed alternatives. The later ones reduce all
-%D dimensions to zero.
-
-\def\hsmash#1%
- {\bgroup
- \setbox0=\normalhbox{#1}%
- \hsmashbox0%
- \box0
- \egroup}
-
-\def\vsmash#1%
- {\bgroup
- \setbox0=\normalvbox{#1}%
- \vsmashbox0%
- \box0
- \egroup}
-
-\def\hsmashed#1%
- {\bgroup
- \setbox0=\normalhbox{#1}%
- \smashbox0%
- \box0
- \egroup}
-
-\def\vsmashed#1%
- {\bgroup
- \setbox0=\normalvbox{#1}%
- \smashbox0%
- \box0
- \egroup}
-
-%D \macros
-%D {getboxheight}
-%D {}
-%D
-%D Although often needed, \TEX\ does not support arithmics
-%D like:
-%D
-%D \starttypen
-%D \dimen0 = \ht0 + \dp0
-%D \stoptypen
-%D
-%D so we implemented:
-%D
-%D \starttypen
-%D \getboxheight ... \of \box...
-%D \stoptypen
-%D
-%D For instance,
-%D
-%D \starttypen
-%D \getboxheight \dimen0 \of \box0
-%D \getboxheight \someheight \of \box \tempbox
-%D \stoptypen
-
-\def\getboxheight#1\of#2\box#3%
- {#1=\ht#3%
- \advance#1 by \dp#3\relax}
-
-%D \macros
-%D {dowithnextbox,
-%D nextbox}
-%D {}
-%D
-%D Sometimes we want a macro to grab a box and do something
-%D on the content. One could pass an argument to a box, but
-%D this can violate the specific \CATCODES\ of its content and
-%D leads to unexpected results. The next macro treats the
-%D following braced text as the content of a box and
-%D manipulates it afterwards in a predefined way.
-%D
-%D The first argument specifies what to do with the content.
-%D This content is available in \type{\nextbox}. The second
-%D argument is one of \type{\hbox}, \type{\vbox} or
-%D \type{\vtop}. The third argument must be grouped with
-%D \type{\bgroup} and \type{\egroup}, \type{{...}} or can be
-%D a \type{\box} specification.
-%D
-%D In \CONTEXT\ this macro is used for picking up a box and
-%D treating it according to earlier specifications. We use for
-%D instance something like:
-%D
-%D \starttypen
-%D \def\getfloat%
-%D {\def\handlefloat{...\box\nextbox...}
-%D \dowithnextbox\handlefloat\vbox}
-%D \stoptypen
-%D
-%D in stead of:
-%D
-%D \starttypen
-%D \def\getfloat#1%
-%D {...#1...}
-%D \stoptypen
-%D
-%D In this implementation the \type{\aftergroup} construction
-%D is needed because \type{\afterassignment} is executed inside
-%D the box.
-
-\newbox\nextbox
-
-\long\def\dowithnextbox#1%
- {\long\def\dodowithnextbox{#1}%
- \afterassignment\dododowithnextbox
- \setbox\nextbox}
-
-\def\dododowithnextbox%
- {\aftergroup\dodowithnextbox}
-
-%D So in fact we get:
-%D
-%D \starttypen
-%D \setbox\nextbox { \aftergroup\dodowithnextbox ... }
-%D \stoptypen
-%D
-%D or
-%D
-%D \starttypen
-%D \setbox\nextbox { ... } \dodowithnextbox
-%D \stoptypen
-%D
-%D A slower but more versatile implementation is:
-%D
-%D \starttypen
-%D \long\def\dowithnextbox#1#2%
-%D {\long\def\dodowithnextbox{#1}%
-%D \ifx#2\hbox
-%D \afterassignment\dododowithnextbox
-%D \else\ifx#2\vbox
-%D \afterassignment\dododowithnextbox
-%D \else\ifx#2\vtop
-%D \afterassignment\dododowithnextbox
-%D \else\ifx#2\vcenter
-%D \afterassignment\dododowithnextbox
-%D \else
-%D \afterassignment\dodowithnextbox
-%D \fi\fi\fi\fi
-%D \setbox\nextbox#2}
-%D \stoptypen
-%D
-%D This alternative also accepts \type{\box0} and alike, but
-%D we don't really need this functionality now.
-
-%D \macros
-%D {beginofshapebox,
-%D reshapebox, doreshapebox,
-%D flushshapebox,
-%D shapebox,
-%D ifreshapingbox}
-%D {}
-%D
-%D The next utility macro originates from some linenumbering
-%D mechanism. Due to \TEX's advanced way of typesetting
-%D paragraphs, it's not easy to do things on a line||by||line
-%D basis. This macro is able to reprocess a given box and can
-%D act upon its vertical boxed components, such as lines. The
-%D unwinding sequence in this macro is inspired by a \NTG\
-%D workshop of David Salomon in June 1992.
-%D
-%D First we have to grab the piece of text we want to act
-%D upon. This is done by means of the duo macros:
-%D
-%D \starttypen
-%D \beginofshapebox
-%D a piece of text
-%D \endofshapebox
-%D \stoptypen
-%D
-%D When all texts is collected, we can call \type{\reshapebox}
-%D and do something with it's vertical components. We can make
-%D as much passes as needed. When we're done, the box can be
-%D unloaded with \type{\flushshapebox}. The only condition in
-%D this scheme is that \type{\reshapebox} must somehow unload
-%D the \BOX\ \type{\shapebox}.
-%D
-%D An important aspect is that the content is unrolled
-%D bottom||up. The next example illustrates this maybe
-%D unexpected characteristic.
-%D
-%D \startbuffer
-%D \beginofshapebox
-%D \em \input tufte
-%D \endofshapebox
-%D
-%D \newcounter\LineNumber
-%D
-%D \reshapebox
-%D {\doglobal\increment\LineNumber
-%D \hbox{\llap{\LineNumber\hskip2em}\box\shapebox}}
-%D
-%D \flushshapebox
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \haalbuffer
-%D
-%D As we can see, when some kind of numbering is done, we have
-%D to add a second pass.
-%D
-%D \startbuffer
-%D \newcounter\LineNumber
-%D \newcounter\NumberOfLines
-%D
-%D \reshapebox
-%D {\doglobal\increment\NumberOfLines
-%D \box\shapebox}
-%D
-%D \reshapebox
-%D {\doglobal\increment\LineNumber
-%D \hbox
-%D {\llap{\LineNumber\ (\NumberOfLines)\hskip2em}%
-%D \box\shapebox}%
-%D \doglobal\decrement\NumberOfLines}
-%D
-%D \flushshapebox
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \haalbuffer
-%D
-%D This example shows that the content of the box is still
-%D available after flushing. Another feature is that only the
-%D last reshaping counts. Multiple reshaping can be done by:
-%D
-%D \startbuffer
-%D \beginofshapebox
-%D \flushshapebox
-%D \endofshapebox
-%D
-%D \reshapebox
-%D {\doglobal\increment\LineNumber
-%D \hbox{\llap{$\star$\hskip1em}\box\shapebox}%
-%D \doglobal\decrement\NumberOfLines}
-%D
-%D \flushshapebox
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \haalbuffer
-%D
-%D The macros are surprisingly easy to follow and in fact
-%D introduce no new concepts. Nearly all books on \TEX\ show
-%D similar solutions for unwinding \BOXES.
-%D
-%D Some macros, like footnote ones, can be sensitive for
-%D reshaping, which can result in an endless loop. We
-%D therefore offer:
-%D
-%D \starttypen
-%D \ifreshapingbox
-%D \stoptypen
-%D
-%D Some \CONTEXT\ commands are protected this way. Anyhow,
-%D reshaping is aborted after 100 dead cycles.
-%D
-%D By the way, changing the height and depth of \BOX\
-%D \type{\shapebox} results in bad spacing. This means that
-%D for instance linenumbers etc. should be given zero height
-%D and depth before being lapped into the margin. The
-%D previous examples ignore this side effect, but beware!
-
-\newif\ifsomeshapeleft
-\newif\ifreshapingbox
-
-\def\shapesignal {.12345678pt}
-
-\newbox \shapebox
-\newcount \shapepenalty
-\newdimen \shapekern
-\newskip \shapeskip
-
-\newbox\newshapebox
-\newbox\oldshapebox
-
-\newcount\shapecounter
-
-\def\reshapebox#1%
- {\doreshapebox
- {#1}
- {\penalty\shapepenalty}
- {\kern\shapekern}
- {\vskip\shapeskip}}
-
-\def\doreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
- {\setbox\newshapebox=\normalvbox
- \bgroup
- \unvcopy\oldshapebox
- \setbox\newshapebox=\box\voidb@x
- \shapecounter=0
- \loop
- \someshapelefttrue
- \ifdim\lastskip=\!!zeropoint\relax
- \ifdim\lastkern=\!!zeropoint\relax
- \ifnum\lastpenalty=0
- \setbox\shapebox=\lastbox
- \ifvoid\shapebox
- \unskip\unpenalty\unkern
- \else
- \ifdim\wd\shapebox=\shapesignal\relax
- \someshapeleftfalse
- \else
- \shapecounter=0
- \setbox\newshapebox=
- \normalvbox{#1\unvbox\newshapebox}
- \fi
- \fi
- \else
- \shapepenalty=\lastpenalty
- \setbox\newshapebox=
- \normalvbox{#2\unvbox\newshapebox}
- \unpenalty
- \fi
- \else
- \shapekern=\lastkern
- \setbox\newshapebox=
- \normalvbox{#3\unvbox\newshapebox}
- \unkern
- \fi
- \else
- \shapeskip=\lastskip
- \setbox\newshapebox=
- \normalvbox{#4\unvbox\newshapebox}
- \unskip
- \fi
- \ifnum\shapecounter>100 % can be less
- \message{<<forced exit from shapebox>>}%
- \someshapeleftfalse
- \else
- \advance\shapecounter by 1
- \fi
- \ifsomeshapeleft \repeat
- \unvbox\newshapebox
- \egroup}
-
-\def\beginofshapebox%
- {\setbox\oldshapebox=\normalvbox
- \bgroup
- \reshapingboxtrue
- \hbox to \shapesignal{\hss}}
-
-\def\endofshapebox%
- {\endgraf
- \egroup}
-
-\let\beginshapebox=\beginofshapebox
-\let\endshapebox =\endofshapebox
-
-\def\flushshapebox%
- {\ifdim\ht\newshapebox=\!!zeropoint\relax
- \else
- % make \prevdepth legal
- \par
- % and take a look
- \ifdim\prevdepth=\hideskip\relax
- \prevdepth=\!!zeropoint
- \fi
- \ifdim\prevdepth<\!!zeropoint
- % something like a line or a signal or ...
- \else
- \ifinner
- % not watertight and not ok
- \else\ifdim\pagegoal=\maxdimen\else
- % give the previous line a normal depth
- \vbox to \!!zeropoint{}
- % go back one line
- \vskip-\lineheight
- \fi\fi
- \fi
- \unvcopy\newshapebox\relax
- % \prevdepth=0pt and \dp\newshapebox depend on last line
- \kern-\dp\newshapebox\relax
- % now \prevdepth=0pt
- \fi}
-
-%D For absolute control, one can use \type{\doreshapebox}
-%D directly. This macro takes four arguments, that take care
-%D of:
-%D
-%D \startopsomming[n,opelkaar]
-%D \som \type{\shapebox}
-%D \som \type{\shapepenalty}
-%D \som \type{\shapekern}
-%D \som \type{\shapeskip}
-%D \stopopsomming
-
-%D \macros
-%D {hyphenatedword,
-%D dohyphenateword}
-%D {}
-%D
-%D The next one is a tricky one. \PLAIN\ \TEX\ provides
-%D \type{\showhyphens} for showing macros on the terminal. When
-%D preparing a long list of words we decided to show the
-%D hyphens, but had to find out that the \PLAIN\ alternative
-%D can hardly be used and|/|or adapted to typesetting. The next
-%D two macros do the job and a little more.
-%D
-%D The simple command \type{\hyphenatedword} accepts one
-%D argument and gives the hyphenated word. This macro calls for
-%D
-%D \starttypen
-%D \dohyphenateword {n} {pre} {word}
-%D \stoptypen
-%D
-%D The next examples tell more than lots of words:
-%D
-%D \startbuffer
-%D \dohyphenateword{0} {} {dohyphenatedword}
-%D \dohyphenateword{1} {...} {dohyphenatedword}
-%D \dohyphenateword{2} {...} {dohyphenatedword}
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D Here, \type{\hyphenatedword{dohyphenatedword}} is the
-%D shorter alternative for the first line.
-%D
-%D \startvoorbeeld
-%D \haalbuffer
-%D \stopvoorbeeld
-%D
-%D These macros are slow but effective and not that hard to
-%D program at all.
-
-\def\dohyphenateword#1#2#3%
- {\bgroup
- \setbox0=\hbox
- {\mindermeldingen
- \widowpenalty=0
- \clubpenalty=0
- \setbox0=\vbox
- {\hsize\!!zeropoint \ #3}%
- \ifnum#1>0
- \dorecurse{#1}
- {\setbox2=\hbox
- {\vsplit0 to \baselineskip}}%
- #2%
- \fi
- \loop
- \setbox2=\hbox
- {\vsplit0 to \baselineskip}%
- \hbox
- {\unhbox2
- \setbox2=\lastbox
- \vbox
- {\unvbox2
- \setbox2=\lastbox
- \hbox{\unhbox2}}}%
- \ifdim\ht0>\!!zeropoint
- \repeat}%
- \ht0=\ht\strutbox
- \dp0=\dp\strutbox
- \box0
- \egroup}
-
-\def\hyphenatedword%
- {\dohyphenateword{0}{}}
-
-%D \macros
-%D {doboundtext}
-%D {}
-%D
-%D Sometimes there is not enough room to show the complete
-%D (line of) text. In such a situation we can strip of some
-%D characters by using \type{\doboundtext}. When the text is
-%D wider than the given width, it's split and the third
-%D argument is appended. When the text to be checked is packed
-%D in a command, we'll have to use \type{\expandafter}.
-%D
-%D \starttypen
-%D \doboundtext{a very, probably to long, text}{3cm}{...}
-%D \stoptypen
-%D
-%D When calculating the room needed, we take the width of the
-%D third argument into account, which leads to a bit more
-%D complex macro than needed at first sight.
-
-\def\dodoboundtext#1%
- {\setbox0=\hbox{\unhcopy0 #1}%
- \ifdim\wd0>\dimen0
- \let\dodoboundtext=\gobbleoneargument
- \else
- #1\relax
- \fi}
-
-\def\doboundtext#1#2#3%
- {\hbox
- {\setbox0=\hbox{#1}%
- \dimen0=#2\relax
- \ifdim\wd0>\dimen0
- \setbox2=\hbox{#3}%
- \advance\dimen0 by -\wd2
- \setbox0=\hbox{}%
- \processtokens
- {\dodoboundtext}
- {\dodoboundtext}
- {}
- {\space}
- {#1}%
- \box2
- \else
- \box0
- \fi}}
-
-%D \macros
-%D {limitatetext}
-%D {}
-%D
-%D A bit more beautiful alternative for the previous command is
-%D the next one. This command is more robust because we let
-%D \TEX\ do most of the job. The previous command works better
-%D on text that cannot be hyphenated.
-%D
-%D \starttypen
-%D \limitatetext {text} {width} {sentinel}
-%D \stoptypen
-%D
-%D When no width is given, the whole text comes available. The
-%D sentinel is optional.
-
-\def\limitatetext#1#2#3%
- {\doifelse{#2}{}
- {#1}
- {\bgroup
- \setbox0=\hbox{#1}%
- \dimen0=#2\relax
- \ifdim\wd0>\dimen0
- \setbox2=\hbox{\ #3}%
- \advance\dimen0 by -\wd2
- \setbox0=\vbox
- {\hsize=\dimen0\relax
- \hfuzz\maxdimen
- \raggedright
- \strut\unhbox0}%
- \vbox % if omitted: missing brace reported
- {\setbox0=\vsplit0 to \ht\strutbox
- \unvbox0
- \setbox0=\lastbox
- \unhbox0\kern0pt\box2}%
- \else
- \unhbox0
- \fi
- \egroup}}
-
-%D \macros
-%D {processisolatedwords,betweenisolatedwords}
-%D {}
-%D
-%D References are often made up of one word or a combination
-%D of tightly connected words. The typeset text {\bf
-%D chapter~5} is for instance the results of the character
-%D sequence:
-%D
-%D \starttypen
-%D The typeset text \in{chapter}[texniques] is for instance
-%D \stoptypen
-%D
-%D When such words are made active in interactive texts, the
-%D combination cannot longer be hyphenated. Normally this is no
-%D problem, because \TEX\ tries to prevent hyphenation as best
-%D as can.
-%D
-%D Sometimes however we need a few more words to make things
-%D clear, like when we want to refer to {\bf \TEX\ by Topic}.
-%D The macros that are responsible for typesetting hyperlinks,
-%D take care of such sub||sentences by breaking them up in
-%D words. Long ago we processed words using the space as a
-%D separator, but the more advanced our interactive text became,
-%D the more we needed a robust solution. Well, here it is and
-%D it called as:
-%D
-%D \starttypen
-%D \processisolatedwords{some words}\someaction
-%D \stoptypen
-%D
-%D The second argument \type{someactions} handles the
-%D individual words, like in:
-%D
-%D \startbuffer
-%D \processisolatedwords{some more words} \ruledhbox \par
-%D \processisolatedwords{and some $x + y = z$ math} \ruledhbox \par
-%D \processisolatedwords{and a \hbox{$x + y = z$}} \ruledhbox \par
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D which let the words turn up as:
-%D
-%D \startvoorbeeld
-%D \haalbuffer
-%D \stopvoorbeeld
-%D
-%D The macro has been made a bit more clever than needed at
-%D first sight. This is due to the fact that we don't want to
-%D generate more overhead in terms of interactive commands than
-%D needed.
-%D
-%D \startbuffer
-%D \processisolatedwords{see this \ruledhskip1em} \ruledhbox
-%D \processisolatedwords{and \ruledhskip1em this one} \ruledhbox
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D becomes:
-%D
-%D \startvoorbeeld
-%D \startregels
-%D \haalbuffer
-%D \stopregels
-%D \stopvoorbeeld
-%D
-%D Single word arguments are treated without further
-%D processing. This was needed because this command is used in
-%D the \type{\goto} command, to which we sometimes pass very
-%D strange and|/|or complicated arguments or simply boxes
-%D whose dimensions are to be left intact.
-%D
-%D First we build a \type{\hbox}. This enables us to save the
-%D last skip. Next we fill a \type{\vbox} without hyphenating
-%D words. After we've tested if there is more than one word, we
-%D start processing the individual lines (words). We need some
-%D splitting, packing and unpacking to get the spacing and
-%D dimensions right.
-%D
-%D Normally the isolated words are separated by space, but
-%D one can overrule this separator by changing the next macros.
-
-\def\betweenisolatedwords%
- {\hskip\fontdimen2\font\!!plus\fontdimen3\font\!!minus\fontdimen4\font}
-
-\def\processisolatedwords#1#2%
- {\bgroup
- \mindermeldingen
- \forgetall
- \setbox0=\hbox
- {#1%
- \xdef\isolatedlastskip{\the\lastskip}}%
- \setbox2=\vbox
- {\hyphenpenalty10000
- \hsize\!!zeropoint
- \unhcopy0}% == #1
- \ifdim\ht0=\ht2
- #2{\unhcopy0}% == #2{#1}
- \else
- \setbox0=\hbox
- {\ignorespaces
- \loop
- \setbox4=\hbox
- {\vsplit2 to \baselineskip}%
- \hbox
- {\unhbox4
- \setbox4=\lastbox
- \vbox % outer \hbox needed
- {\unvbox4 % for nested use
- \setbox4=\lastbox
- \hbox{#2{\hbox{\unhbox4}}}}}%
- \ifdim\ht2>\!!zeropoint \betweenisolatedwords \repeat
- \unskip}%
- \unhbox0\unskip\hskip\isolatedlastskip
- \fi
- \egroup}
-
-%D \macros
-%D {sbox}
-%D {}
-%D
-%D This is a rather strange command. It grabs some box content
-%D and and limits the size to the height and depth of a
-%D \type{\strut}. The resulting bottom||alligned box can be used
-%D aside other ones, without disturbing the normal baseline
-%D distance.
-%D
-%D \startbuffer
-%D \ruledhbox to .5\hsize{\sbox{eerste\par tweede \par derde}}
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D Shows up as:
-%D
-%D \startvoorbeeld
-%D \vskip3\baselineskip
-%D \haalbuffer
-%D \stopvoorbeeld
-%D
-%D Before displaying the result we added some skip, otherwise
-%D the first two lines would have ended up in the text. This
-%D macro can be useful when building complicated menus, headers
-%D and footers and|/|or margin material.
-%D
-%D {\em This macro still needs some improvement.}
-
-\def\sbox% in handleiding, voorbeeld \inlinker{xx} \extern..
- {\dowithnextbox
- {\setbox0=\hbox
- {\strut
- \dp\nextbox=0pt
- \lower\strutdepth\box\nextbox}%
- \dp0=\strutdepth
- \ht0=\strutheight
- \box0}%
- \vbox}
-
-%D \macros
-%D {centeredbox}
-%D {}
-%D
-%D Here is another strange one. This one offers a sort of overlay
-%D with positive or negative offsets. This command can be used
-%D in well defined areas where no offset options are available.
-%D We first used it when building a button inside the margin
-%D footer, where the button should have a horizontal offset and
-%D should be centered with respect to the surrounding box. The
-%D last of the three examples we show below says:
-%D
-%D \starttypen
-%D \vsize=3cm
-%D \hsize=3cm
-%D \ruledvbox to \vsize
-%D {\centeredbox height .5cm width -1cm
-%D {\vrule width \hsize height \vsize}}}
-%D \stoptypen
-%D
-%D Here the \type{\ruledvbox} just shows the surrounding box
-%D and \type{\vrule} is used to show the centered box.
-%D
-%D \def\AnExample#1#2%
-%D {\vsize=3cm
-%D \hsize=3cm
-%D \ruledvbox to \vsize
-%D {\centeredbox height #1 width #2
-%D {\color[groen]{\vrule width \hsize height \vsize}}}}
-%D
-%D \startregelcorrectie
-%D \startcombinatie[3*1]
-%D {\AnExample {-1cm} {.5cm}} {}
-%D {\AnExample {.5cm} {-1cm}} {}
-%D {\AnExample {-1cm} {-.5cm}} {}
-%D \stopcombinatie
-%D \stopregelcorrectie
-%D
-%D This command takes two optional arguments: \type{width} and
-%D \type{height}. Observing readers can see that we use \TEX's
-%D own scanner for grabbing these arguments: \type{#1#} reads
-%D everyting till the next brace and passes it to both rules.
-%D The setting of the box dimensions at the end is needed for
-%D special cases. The dimensions of the surounding box are kept
-%D intact. This commands handles positive and negative
-%D dimensions (which is why we need two boxes with rules).
-
-\def\centeredbox#1#% height +/-dimen width +/-dimen
- {\bgroup
- \setbox0=\vbox to \vsize
- \bgroup
- \mindermeldingen
- \forgetall
- \setbox0=\hbox{\vrule\!!width\!!zeropoint#1}%
- \setbox2=\vbox{\hrule\!!height\!!zeropoint#1}%
- \advance\vsize by \ht2
- \advance\hsize by \wd0
- \vbox to \vsize
- \bgroup
- \vskip-\ht2
- \vss
- \hbox to \hsize
- \bgroup
- \dowithnextbox
- {\hskip-\wd0
- \hss
- \box\nextbox
- \hss
- \egroup
- \vss
- \egroup
- \egroup
- \wd0=\hsize
- \ht0=\vsize
- \box0
- \egroup}
- \hbox}
-
-%D \macros
-%D {setrigidcolumnhsize,rigidcolumnbalance}
-%D
-%D These macros are copied from the \TEX book, page~397, and
-%D extended by a macro that sets the \type{\hsize}.
-%D
-%D \starttypen
-%D \setrigidcolumnhsize {total width} {distance} {n}
-%D \rigidcolumnbalance {box} {n}
-%D \stoptypen
-%D
-%D Both these macros are for instance used in typesetting
-%D footnotes.
-%D
-%D Men kan het proces van breken enigzins beinvloeden met de
-%D volgende twee swithes:
-
-\newif\ifalignrigidcolumns
-\newif\ifstretchrigidcolumns
-
-%D De eerste switch bepaald het uitlijnen, de tweede rekt de
-%D individuele kolommen op naar \type{\vsize}.
-
-\def\setrigidcolumnhsize#1#2#3%
- {\hsize=#1\relax
- \scratchdimen=-#2\relax
- \multiply\scratchdimen by #3\relax
- \advance\scratchdimen by #2\relax
- \advance\hsize by \scratchdimen
- \divide\hsize by #3\relax}
-
-\def\rigidcolumnbalance#1#2%
- {\global\chardef\rigidcolumnbox=#1\relax
- \global\chardef\rigidcolumns=#2\relax
- \ifnum\rigidcolumns=1
- \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi\rigidcolumnbox
- \else
- \line
- {\vbadness=10000
- \tabskip\!!zeropoint
- \splittopskip=\ht\strutbox
- %\scratchdimen=\ht\rigidcolumnbox % sensitive for overflow
- %\divide\scratchdimen by \rigidcolumns % therefore we need the hack:
- \scratchdimen=1pt
- \divide\scratchdimen by \rigidcolumns
- \expanded{\scratchdimen=\withoutpt{\the\scratchdimen}\ht\rigidcolumnbox}%
- \advance\scratchdimen by \ht\strutbox
- \valign{##\vfill\cr\dorigidcolumnsplits}}%
- \fi}
-
-\def\dorigidcolumnsplits%
- {\ifnum\rigidcolumns>0
- \setbox\scratchbox=\vsplit\rigidcolumnbox to \scratchdimen
- \ifalignrigidcolumns
- \vbox to \ifstretchrigidcolumns\vsize\else\scratchdimen\fi
- {\unvbox\scratchbox}%
- \else
- \vbox{\unvbox\scratchbox}%
- \fi
- \doglobal\decrement\rigidcolumns
- \cr
- \ifnum\rigidcolumns>0\noalign{\hfil}\fi
- \expandafter\dorigidcolumnsplits
- \fi}
-
-%D \macros
-%D {startvboxtohbox,stopvboxtohbox,convertvboxtohbox}
-%D
-%D Here is another of Knuth's dirty tricks, as presented on
-%D pages 398 and 399 of the \TEX book. These macros can be used
-%D like:
-%D
-%D \starttypen
-%D \vbox
-%D \bgroup
-%D \startvboxtohbox ... \stopvboxtohbox
-%D \startvboxtohbox ... \stopvboxtohbox
-%D \startvboxtohbox ... \stopvboxtohbox
-%D \egroup
-%D
-%D \vbox
-%D \bgroup
-%D \converthboxtovbox
-%D \egroup
-%D \stoptypen
-%D
-%D These macros are used in reformatting footnotes, so they do
-%D what they're meant for.
-
-\def\setvboxtohbox%
- {\bgroup
- \ifdim\baselineskip<16pt \relax
- \dimen0=\baselineskip
- \multiply\dimen0 by 1024
- \else
- \message{cropping \baselineskip to 16pt}%
- \baselineskip=\maxdimen
- \fi
- \divide\dimen0 by \hsize
- \multiply\dimen0 by 64
- \xdef\vboxtohboxfactor{\expandafter\withoutpt\the\dimen0}%
- \egroup}
-
-\def\startvboxtohbox%
- {\bgroup
- \setvboxtohbox
- \setbox0=\hbox\bgroup}
-
-\def\stopvboxtohbox%
- {\egroup
- \dp0=\!!zeropoint
- \ht0=\vboxtohboxfactor\wd0
- \box0
- \egroup}
-
-\def\convertvboxtohbox%
- {\setvboxtohbox
- \makehboxofhboxes
- \setbox0=\hbox{\unhbox0 \removehboxes}%
- \noindent\unhbox0\par}
-
-\def\makehboxofhboxes%
- {\setbox0=\hbox{}%
- \loop
- \setbox2=\lastbox
- \ifhbox2
- \setbox0=\hbox{\box2\unhbox0}%
- \repeat}
-
-\def\removehboxes%
- {\setbox0=\lastbox
- \ifhbox0
- {\removehboxes}%
- \unhbox0
- \fi}
-
-%D \macros
-%D {doifcontent}
-%D
-%D When processing depends on the availability of content, one
-%D can gove the next macro a try.
-%D
-%D \starttypen
-%D \doifcontent{pre content}{post content}{no content}\somebox
-%D \stoptypen
-%D
-%D Where \type{\somebox} is either a \type{\hbox} or
-%D \type{\vbox}. If the dimension of this box suggest some
-%D content, the resulting box is unboxed and surrounded by the
-%D first two arguments, else the third arguments is executed.
-
-\def\doifcontent#1#2#3%
- {\dowithnextbox
- {\ifhbox\nextbox
- \ifdim\wd\nextbox>\!!zeropoint
- #1\unhbox\nextbox#2\relax
- \else
- #3\relax
- \fi
- \else
- \ifdim\ht\nextbox>\!!zeropoint
- #1\unvbox\nextbox#2\relax
- \else
- #3\relax
- \fi
- \fi}}
-
-%D So when we say:
-%D
-%D \startbuffer
-%D \doifcontent{[}{]}{}\hbox{content sensitive typesetting}
-%D
-%D \doifcontent{}{\pagina}{}\vbox{content sensitive typesetting}
-%D
-%D \doifcontent{}{}{\message{Didn't you forget something?}}\hbox{}
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D We get:
-%D
-%D \haalbuffer
-%D
-%D Where the last call of course does not show up in this
-%D document, but definitely generates a confusing message.
-
-% maybe some day we need this
-%
-% \def\appendvbox#1% % uses \box8
-% {\bgroup
-% \ifdim\prevdepth<\!!zeropoint
-% \ifdim\pagetotal=\!!zeropoint
-% \setbox8=\vtop{\unvcopy#1}%
-% \hrule\c!!height\!!zeropoint
-% \kern-\ht8
-% \box#1\relax
-% \else
-% \box#1\relax
-% \fi
-% \else
-% \dimen0=\prevdepth
-% \hrule\c!!height\!!zeropoint
-% \setbox8=\vtop{\unvcopy#1}%
-% \dimen2=\baselineskip
-% \advance\dimen2 by -\dimen0
-% \advance\dimen2 by -\ht8
-% \kern\dimen2
-% \box#1\relax
-% \fi
-% \egroup}
-
-\protect
-
-\endinput
- \ No newline at end of file
+%D \module
+%D [ file=supp-box,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=Boxes,
+%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. Non||commercial use is
+%C granted.
+
+%D This module implements some box manipulation macros. Some
+%D are quite simple, some are more advanced and when understood
+%D well, all can be of use.
+
+\writestatus{loading}{Context Support Macros / Boxes}
+
+\unprotect
+
+%D \macros
+%D {nextdepth}
+%D
+%D Let's start with a rather simple declaration. Sometimes we
+%D need to save the \TEX\ \DIMENSION\ \type{\prevdepth} and
+%D append it later on. The name \type{\nextdepth} suits
+%D this purpose well.
+
+\newdimen\nextdepth
+
+%D \macros
+%D {smashbox}
+%D
+%D Smashing is introduced in \PLAIN\ \TEX, and stands for
+%D reducing the dimensions of a box to zero. The most resolute
+%D one is presented first.
+
+\def\smashbox#1%
+ {\wd#1=\!!zeropoint
+ \ht#1=\!!zeropoint
+ \dp#1=\!!zeropoint}
+
+%D \macros
+%D {hsmashbox,vsmashbox}
+%D {}
+%D
+%D Smashing can be used for overlaying boxes. Depending on
+%D the mode, horizontal or vertical, one can use:
+
+\def\hsmashbox#1%
+ {\wd#1=\!!zeropoint}
+
+\def\vsmashbox#1%
+ {\ht#1=\!!zeropoint
+ \dp#1=\!!zeropoint}
+
+%D \macros
+%D {hsmash,vsmash,
+%D hsmashed,vsmashed}
+%D {}
+%D
+%D While the previous macros expected a \BOX, the next act on a
+%D content. They are some subtle differences betreen the smash
+%D and smashed alternatives. The later ones reduce all
+%D dimensions to zero.
+
+\def\hsmash#1%
+ {\bgroup
+ \setbox0=\normalhbox{#1}%
+ \hsmashbox0%
+ \box0
+ \egroup}
+
+\def\vsmash#1%
+ {\bgroup
+ \setbox0=\normalvbox{#1}%
+ \vsmashbox0%
+ \box0
+ \egroup}
+
+\def\hsmashed#1%
+ {\bgroup
+ \setbox0=\normalhbox{#1}%
+ \smashbox0%
+ \box0
+ \egroup}
+
+\def\vsmashed#1%
+ {\bgroup
+ \setbox0=\normalvbox{#1}%
+ \smashbox0%
+ \box0
+ \egroup}
+
+%D \macros
+%D {getboxheight}
+%D
+%D Although often needed, \TEX\ does not support arithmics
+%D like:
+%D
+%D \starttypen
+%D \dimen0 = \ht0 + \dp0
+%D \stoptypen
+%D
+%D so we implemented:
+%D
+%D \starttypen
+%D \getboxheight ... \of \box...
+%D \stoptypen
+%D
+%D For instance,
+%D
+%D \starttypen
+%D \getboxheight \dimen0 \of \box0
+%D \getboxheight \someheight \of \box \tempbox
+%D \stoptypen
+
+\def\getboxheight#1\of#2\box#3%
+ {#1=\ht#3%
+ \advance#1 by \dp#3\relax}
+
+%D \macros
+%D {doiftextelse, doiftext}
+%D
+%D When \type {\doifelse} cum suis hopelessly fail, for
+%D instance because we pass data, we can fall back on the next
+%D macro:
+%D
+%D \starttypen
+%D \doiftextelse {data} {then branch} {else branch}
+%D \doiftext {data} {then branch}
+%D \stoptypen
+
+\def\doiftextelse#1#2#3%
+ {\bgroup
+ \setbox0=\hbox{#1}%
+ \ifdim\wd0>\!!zeropoint
+ \egroup#2%
+ \else
+ \egroup#3%
+ \fi}
+
+\def\doiftext#1#2%
+ {\doiftextelse{#1}{#2}{}}
+
+%D \macros
+%D {dowithnextbox,
+%D nextbox}
+%D
+%D Sometimes we want a macro to grab a box and do something
+%D on the content. One could pass an argument to a box, but
+%D this can violate the specific \CATCODES\ of its content and
+%D leads to unexpected results. The next macro treats the
+%D following braced text as the content of a box and
+%D manipulates it afterwards in a predefined way.
+%D
+%D The first argument specifies what to do with the content.
+%D This content is available in \type{\nextbox}. The second
+%D argument is one of \type{\hbox}, \type{\vbox} or
+%D \type{\vtop}. The third argument must be grouped with
+%D \type{\bgroup} and \type{\egroup}, \type{{...}} or can be
+%D a \type{\box} specification.
+%D
+%D In \CONTEXT\ this macro is used for picking up a box and
+%D treating it according to earlier specifications. We use for
+%D instance something like:
+%D
+%D \starttypen
+%D \def\getfloat%
+%D {\def\handlefloat{...\box\nextbox...}
+%D \dowithnextbox\handlefloat\vbox}
+%D \stoptypen
+%D
+%D in stead of:
+%D
+%D \starttypen
+%D \def\getfloat#1%
+%D {...#1...}
+%D \stoptypen
+%D
+%D In this implementation the \type{\aftergroup} construction
+%D is needed because \type{\afterassignment} is executed inside
+%D the box.
+
+\newbox\nextbox
+
+\long\def\dowithnextbox#1%
+ {\long\def\dodowithnextbox{#1}%
+ \afterassignment\dododowithnextbox
+ \setbox\nextbox}
+
+% Better but first to be checked:
+%
+%\long\def\dowithnextbox#1%
+% {\bgroup\long\def\dodowithnextbox{#1\egroup}%
+% \afterassignment\dododowithnextbox
+% \setbox\nextbox}
+
+\def\dododowithnextbox%
+ {\aftergroup\dodowithnextbox}
+
+%D So in fact we get:
+%D
+%D \starttypen
+%D \setbox\nextbox { \aftergroup\dodowithnextbox ... }
+%D \stoptypen
+%D
+%D or
+%D
+%D \starttypen
+%D \setbox\nextbox { ... } \dodowithnextbox
+%D \stoptypen
+%D
+%D A slower but more versatile implementation is:
+%D
+%D \starttypen
+%D \long\def\dowithnextbox#1#2%
+%D {\long\def\dodowithnextbox{#1}%
+%D \ifx#2\hbox
+%D \afterassignment\dododowithnextbox
+%D \else\ifx#2\vbox
+%D \afterassignment\dododowithnextbox
+%D \else\ifx#2\vtop
+%D \afterassignment\dododowithnextbox
+%D \else\ifx#2\vcenter
+%D \afterassignment\dododowithnextbox
+%D \else
+%D \afterassignment\dodowithnextbox
+%D \fi\fi\fi\fi
+%D \setbox\nextbox#2}
+%D \stoptypen
+%D
+%D This alternative also accepts \type{\box0} and alike, but
+%D we don't really need this functionality now.
+
+%D \macros
+%D {beginofshapebox,
+%D reshapebox, doreshapebox,
+%D flushshapebox,
+%D innerflushshapebox,
+%D shapebox,
+%D ifreshapingbox}
+%D
+%D The next utility macro originates from some linenumbering
+%D mechanism. Due to \TEX's advanced way of typesetting
+%D paragraphs, it's not easy to do things on a line||by||line
+%D basis. This macro is able to reprocess a given box and can
+%D act upon its vertical boxed components, such as lines. The
+%D unwinding sequence in this macro is inspired by a \NTG\
+%D workshop of David Salomon in June 1992.
+%D
+%D First we have to grab the piece of text we want to act
+%D upon. This is done by means of the duo macros:
+%D
+%D \starttypen
+%D \beginofshapebox
+%D a piece of text
+%D \endofshapebox
+%D \stoptypen
+%D
+%D When all texts is collected, we can call \type{\reshapebox}
+%D and do something with it's vertical components. We can make
+%D as much passes as needed. When we're done, the box can be
+%D unloaded with \type{\flushshapebox}. The only condition in
+%D this scheme is that \type{\reshapebox} must somehow unload
+%D the \BOX\ \type{\shapebox}.
+%D
+%D An important aspect is that the content is unrolled
+%D bottom||up. The next example illustrates this maybe
+%D unexpected characteristic.
+%D
+%D \startbuffer
+%D \beginofshapebox
+%D \em \input tufte
+%D \endofshapebox
+%D
+%D \newcounter\LineNumber
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox{\llap{\LineNumber\hskip2em}\box\shapebox}}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \haalbuffer
+%D
+%D As we can see, when some kind of numbering is done, we have
+%D to add a second pass.
+%D
+%D \startbuffer
+%D \newcounter\LineNumber
+%D \newcounter\NumberOfLines
+%D
+%D \reshapebox
+%D {\doglobal\increment\NumberOfLines
+%D \box\shapebox}
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox
+%D {\llap{\LineNumber\ (\NumberOfLines)\hskip2em}%
+%D \box\shapebox}%
+%D \doglobal\decrement\NumberOfLines}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \haalbuffer
+%D
+%D This example shows that the content of the box is still
+%D available after flushing. Another feature is that only the
+%D last reshaping counts. Multiple reshaping can be done by:
+%D
+%D \startbuffer
+%D \beginofshapebox
+%D \flushshapebox
+%D \endofshapebox
+%D
+%D \reshapebox
+%D {\doglobal\increment\LineNumber
+%D \hbox{\llap{$\star$\hskip1em}\box\shapebox}%
+%D \doglobal\decrement\NumberOfLines}
+%D
+%D \flushshapebox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \haalbuffer
+%D
+%D The macros are surprisingly easy to follow and in fact
+%D introduce no new concepts. Nearly all books on \TEX\ show
+%D similar solutions for unwinding \BOXES.
+%D
+%D Some macros, like footnote ones, can be sensitive for
+%D reshaping, which can result in an endless loop. We
+%D therefore offer:
+%D
+%D \starttypen
+%D \ifreshapingbox
+%D \stoptypen
+%D
+%D Some \CONTEXT\ commands are protected this way. Anyhow,
+%D reshaping is aborted after 100 dead cycles.
+%D
+%D By the way, changing the height and depth of \BOX\
+%D \type{\shapebox} results in bad spacing. This means that
+%D for instance linenumbers etc. should be given zero height
+%D and depth before being lapped into the margin. The
+%D previous examples ignore this side effect, but beware!
+
+\newif\ifsomeshapeleft
+\newif\ifreshapingbox
+
+\def\shapesignal {.12345678pt}
+
+\newbox \shapebox
+\newcount \shapepenalty
+\newdimen \shapekern
+\newskip \shapeskip
+
+\newbox\newshapebox
+\newbox\oldshapebox
+
+\newcount\shapecounter
+
+\def\reshapebox#1%
+ {\doreshapebox
+ {#1}
+ {\penalty\shapepenalty}
+ {\kern\shapekern}
+ {\vskip\shapeskip}}
+
+\def\doreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
+ {\setbox\newshapebox=\normalvbox
+ \bgroup
+ \unvcopy\oldshapebox
+ \setbox\newshapebox=\box\voidb@x
+ \shapecounter=0
+ \loop
+ \someshapelefttrue
+ \ifdim\lastskip=\!!zeropoint\relax
+ \ifdim\lastkern=\!!zeropoint\relax
+ \ifnum\lastpenalty=0
+ \setbox\shapebox=\lastbox
+ \ifvoid\shapebox
+ \unskip\unpenalty\unkern
+ \else
+ \ifdim\wd\shapebox=\shapesignal\relax
+ \someshapeleftfalse
+ \else
+ \shapecounter=0
+ \setbox\newshapebox=
+ \normalvbox{#1\unvbox\newshapebox}
+ \fi
+ \fi
+ \else
+ \shapepenalty=\lastpenalty
+ \setbox\newshapebox=
+ \normalvbox{#2\unvbox\newshapebox}
+ \unpenalty
+ \fi
+ \else
+ \shapekern=\lastkern
+ \setbox\newshapebox=
+ \normalvbox{#3\unvbox\newshapebox}
+ \unkern
+ \fi
+ \else
+ \shapeskip=\lastskip
+ \setbox\newshapebox=
+ \normalvbox{#4\unvbox\newshapebox}
+ \unskip
+ \fi
+ \ifnum\shapecounter>100 % can be less
+ \message{<<forced exit from shapebox>>}%
+ \someshapeleftfalse
+ \else
+ \advance\shapecounter by 1
+ \fi
+ \ifsomeshapeleft \repeat
+ \unvbox\newshapebox
+ \egroup}
+
+\def\beginofshapebox%
+ {\setbox\oldshapebox=\normalvbox
+ \bgroup
+ \reshapingboxtrue
+ \hbox to \shapesignal{\hss}}
+
+\def\endofshapebox%
+ {\endgraf
+ \egroup}
+
+\let\beginshapebox=\beginofshapebox
+\let\endshapebox =\endofshapebox
+
+\def\flushshapebox%
+ {\ifdim\ht\newshapebox=\!!zeropoint\relax
+ \else
+ % make \prevdepth legal
+ % \par before the next \vskip gives far worse results
+ \ifdim\parskip>\!!zeropoint\vskip\parskip\else\par\fi
+ % and take a look
+ \ifdim\prevdepth=-1000pt
+ \prevdepth=\!!zeropoint
+ \fi
+ \ifdim\prevdepth<\!!zeropoint\relax
+ % something like a line or a signal or ...
+ \donetrue
+ \else\ifinner
+ % not watertight and not ok
+ \donefalse
+ \else\ifdim\pagegoal=\maxdimen
+ \donetrue
+ \else
+ % give the previous line a normal depth
+ \donetrue
+ \vbox{\forgetall\strut}\nobreak\kern-\lineheight % geen \vskip
+ \vskip-\dp\strutbox
+ \fi\fi\fi
+ \unvcopy\newshapebox\relax
+ % \prevdepth=0pt and \dp\newshapebox depend on last line
+ \kern-\dp\newshapebox\relax
+ % now \prevdepth=0pt
+ \ifdone
+ \kern\dp\strutbox
+ \prevdepth\dp\strutbox
+ \fi
+ \fi}
+
+%D In real inner situations we can use:
+%D
+%D \starttypen
+%D \flushinnershapebox
+%D \stoptypen
+%D
+%D This one is used in \type{\framed}.
+
+\def\innerflushshapebox%
+ {\ifdim\ht\newshapebox=\!!zeropoint\relax
+ \else
+ \unvcopy\newshapebox\relax
+ \kern-\dp\newshapebox\relax
+ \fi}
+
+%D For absolute control, one can use \type{\doreshapebox}
+%D directly. This macro takes four arguments, that take care
+%D of:
+%D
+%D \startopsomming[n,opelkaar]
+%D \som \type{\shapebox}
+%D \som \type{\shapepenalty}
+%D \som \type{\shapekern}
+%D \som \type{\shapeskip}
+%D \stopopsomming
+
+%D \macros
+%D {hyphenatedword,
+%D dohyphenateword}
+%D
+%D The next one is a tricky one. \PLAIN\ \TEX\ provides
+%D \type{\showhyphens} for showing macros on the terminal. When
+%D preparing a long list of words we decided to show the
+%D hyphens, but had to find out that the \PLAIN\ alternative
+%D can hardly be used and|/|or adapted to typesetting. The next
+%D two macros do the job and a little more.
+%D
+%D The simple command \type{\hyphenatedword} accepts one
+%D argument and gives the hyphenated word. This macro calls for
+%D
+%D \starttypen
+%D \dohyphenateword {n} {pre} {word}
+%D \stoptypen
+%D
+%D The next examples tell more than lots of words:
+%D
+%D \startbuffer
+%D \dohyphenateword{0} {} {dohyphenatedword}
+%D \dohyphenateword{1} {...} {dohyphenatedword}
+%D \dohyphenateword{2} {...} {dohyphenatedword}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here, \type{\hyphenatedword{dohyphenatedword}} is the
+%D shorter alternative for the first line.
+%D
+%D \startvoorbeeld
+%D \haalbuffer
+%D \stopvoorbeeld
+%D
+%D These macros are slow but effective and not that hard to
+%D program at all.
+
+\def\dohyphenateword#1#2#3%
+ {\bgroup
+ \setbox0=\hbox
+ {\mindermeldingen
+ \widowpenalty=0
+ \clubpenalty=0
+ \setbox0=\vbox
+ {\hsize\!!zeropoint \ #3}%
+ \ifnum#1>0
+ \dorecurse{#1}
+ {\setbox2=\hbox
+ {\splittopskip=\openstrutheight
+ \vsplit0 to \baselineskip}}%
+ #2%
+ \fi
+ \loop
+ \setbox2=\hbox
+ {\splittopskip=\openstrutheight
+ \vsplit0 to \baselineskip}%
+ \hbox
+ {\unhbox2
+ \setbox2=\lastbox
+ \vbox
+ {\unvbox2
+ \setbox2=\lastbox
+ \hbox{\unhbox2}}}%
+ \ifdim\ht0>\!!zeropoint
+ \repeat}%
+ \ht0=\ht\strutbox
+ \dp0=\dp\strutbox
+ \box0
+ \egroup}
+
+\def\hyphenatedword%
+ {\dohyphenateword{0}{}}
+
+%D \macros
+%D {doboundtext}
+%D
+%D Sometimes there is not enough room to show the complete
+%D (line of) text. In such a situation we can strip of some
+%D characters by using \type{\doboundtext}. When the text is
+%D wider than the given width, it's split and the third
+%D argument is appended. When the text to be checked is packed
+%D in a command, we'll have to use \type{\expandafter}.
+%D
+%D \starttypen
+%D \doboundtext{a very, probably to long, text}{3cm}{...}
+%D \stoptypen
+%D
+%D When calculating the room needed, we take the width of the
+%D third argument into account, which leads to a bit more
+%D complex macro than needed at first sight.
+
+\def\dodoboundtext#1%
+ {\setbox0=\hbox{\unhcopy0 #1}%
+ \ifdim\wd0>\dimen0
+ \let\dodoboundtext=\gobbleoneargument
+ \else
+ #1\relax
+ \fi}
+
+\def\doboundtext#1#2#3%
+ {\hbox
+ {\setbox0=\hbox{#1}%
+ \dimen0=#2\relax
+ \ifdim\wd0>\dimen0
+ \setbox2=\hbox{#3}%
+ \advance\dimen0 by -\wd2
+ \setbox0=\hbox{}%
+ \processtokens
+ {\dodoboundtext}
+ {\dodoboundtext}
+ {}
+ {\space}
+ {#1}%
+ \box2
+ \else
+ \box0
+ \fi}}
+
+%D \macros
+%D {limitatetext}
+%D
+%D A bit more beautiful alternative for the previous command is
+%D the next one. This command is more robust because we let
+%D \TEX\ do most of the job. The previous command works better
+%D on text that cannot be hyphenated.
+%D
+%D \starttypen
+%D \limitatetext {text} {width} {sentinel}
+%D \stoptypen
+%D
+%D When no width is given, the whole text comes available. The
+%D sentinel is optional. This is about the third version.
+
+\ifx\fakecompoundhyphen\undefined \let\fakecompoundhyphen\relax \fi
+
+\unexpanded\def\limitatetext%
+ {\bgroup
+ \dowithnextbox\dolimitatetext\hbox}
+
+\def\dolimitatetext#1#2%
+ {\doifelsenothing{#1}
+ {\unhbox\nextbox}
+ {\fakecompoundhyphen
+ \scratchdimen=#1\relax
+ \ifdim\wd\nextbox>\scratchdimen
+ \setbox\scratchbox=\hbox{ #2}%
+ \advance\scratchdimen by -\wd\scratchbox
+ \setbox\nextbox=\vbox
+ {\hsize=\scratchdimen
+ \hfuzz\maxdimen
+ \veryraggedright
+ \strut\unhbox\nextbox}%
+ \setbox\nextbox=\vbox % if omitted: missing brace reported
+ {\splittopskip=\openstrutheight
+ \setbox\nextbox=\vsplit\nextbox to \ht\strutbox
+ \unvbox\nextbox
+ \setbox\nextbox=\lastbox
+ \global\setbox1=\hbox
+ {\unhbox\nextbox\unskip\kern\!!zeropoint\box\scratchbox\unskip}}%
+ \unhbox1
+ \else
+ \unhbox\nextbox
+ \fi}%
+ \egroup}
+
+%D \macros
+%D {processisolatedwords,
+%D betweenisolatedwords,nothingbetweenisolatedwords}
+%D
+%D References are often made up of one word or a combination
+%D of tightly connected words. The typeset text {\bf
+%D chapter~5} is for instance the results of the character
+%D sequence:
+%D
+%D \starttypen
+%D The typeset text \in{chapter}[texniques] is for instance
+%D \stoptypen
+%D
+%D When such words are made active in interactive texts, the
+%D combination cannot longer be hyphenated. Normally this is no
+%D problem, because \TEX\ tries to prevent hyphenation as best
+%D as can.
+%D
+%D Sometimes however we need a few more words to make things
+%D clear, like when we want to refer to {\bf \TEX\ by Topic}.
+%D The macros that are responsible for typesetting hyperlinks,
+%D take care of such sub||sentences by breaking them up in
+%D words. Long ago we processed words using the space as a
+%D separator, but the more advanced our interactive text became,
+%D the more we needed a robust solution. Well, here it is and
+%D it called as:
+%D
+%D \starttypen
+%D \processisolatedwords{some words}\someaction
+%D \stoptypen
+%D
+%D The second argument \type{someactions} handles the
+%D individual words, like in:
+%D
+%D \startbuffer
+%D \processisolatedwords{some more words} \ruledhbox \par
+%D \processisolatedwords{and some $x + y = z$ math} \ruledhbox \par
+%D \processisolatedwords{and a \hbox{$x + y = z$}} \ruledhbox \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D which let the words turn up as:
+%D
+%D \startvoorbeeld
+%D \haalbuffer
+%D \stopvoorbeeld
+%D
+%D The macro has been made a bit more clever than needed at
+%D first sight. This is due to the fact that we don't want to
+%D generate more overhead in terms of interactive commands than
+%D needed.
+%D
+%D \startbuffer
+%D \processisolatedwords{see this \ruledhskip1em} \ruledhbox
+%D \processisolatedwords{and \ruledhskip1em this one} \ruledhbox
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D becomes:
+%D
+%D \startvoorbeeld
+%D \startregels
+%D \haalbuffer
+%D \stopregels
+%D \stopvoorbeeld
+%D
+%D Single word arguments are treated without further
+%D processing. This was needed because this command is used in
+%D the \type{\goto} command, to which we sometimes pass very
+%D strange and|/|or complicated arguments or simply boxes
+%D whose dimensions are to be left intact.
+%D
+%D First we build a \type{\hbox}. This enables us to save the
+%D last skip. Next we fill a \type{\vbox} without hyphenating
+%D words. After we've tested if there is more than one word, we
+%D start processing the individual lines (words). We need some
+%D splitting, packing and unpacking to get the spacing and
+%D dimensions right.
+%D
+%D Normally the isolated words are separated by space, but
+%D one can overrule this separator by changing the next macros.
+%D
+%D When needed, spacing can be suppressed by \type
+%D {\nothingbetweenisolatedwords}.
+
+\newif\ifisolatedwords
+
+\def\betweenisolatedwords%
+ {\hskip\currentspaceskip}
+
+\def\setbetweenisolatedwords#1%
+ {\gdef\localbetweenisolatedwords{#1}}
+
+\def\processisolatedwords#1#2%
+ {\bgroup
+ \fakecompoundhyphen
+ \mindermeldingen
+ \forgetall
+ \global\let\localbetweenisolatedwords\betweenisolatedwords
+ \setbox0=\hbox
+ {\ignorespaces#1%
+ \xdef\isolatedlastskip{\the\lastskip}}%
+ \setbox2=\vbox
+ {%\hyphenpenalty10000 % this one fails in \url breaking,
+ \lefthyphenmin=\!!maxcard % but this trick works ok, due to them
+ \righthyphenmin=\!!maxcard % total>63, when no hyphenation is done
+ \hsize\!!zeropoint
+ \unhcopy0}% == #1
+ \ifdim\ht0=\ht2
+ \isolatedwordsfalse
+ #2{\unhcopy0}% == #2{#1}
+ \else
+ \isolatedwordstrue
+ \setbox0=\hbox
+ {\ignorespaces
+ \loop
+ \setbox4=\hbox
+ {\splittopskip=\openstrutheight
+ \vsplit2 to \baselineskip}%
+ \hbox
+ {\unhbox4\unskip % recently added
+ \setbox4=\lastbox
+ \vbox % outer \hbox needed
+ {\unvbox4 % for nested use
+ \setbox4=\lastbox
+ \hbox{#2{\hbox{\unhbox4}}}}}%
+ \ifdim\ht2>\!!zeropoint \localbetweenisolatedwords \repeat
+ \unskip}%
+ \unhbox0\unskip\hskip\isolatedlastskip
+ \fi
+ \egroup}
+
+%D \macros
+%D {sbox}
+%D
+%D This is a rather strange command. It grabs some box content
+%D and and limits the size to the height and depth of a
+%D \type{\strut}. The resulting bottom||alligned box can be used
+%D aside other ones, without disturbing the normal baseline
+%D distance.
+%D
+%D \startbuffer
+%D \ruledhbox to .5\hsize{\sbox{eerste\par tweede \par derde}}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Shows up as:
+%D
+%D \startvoorbeeld
+%D \vskip3\baselineskip
+%D \haalbuffer
+%D \stopvoorbeeld
+%D
+%D Before displaying the result we added some skip, otherwise
+%D the first two lines would have ended up in the text. This
+%D macro can be useful when building complicated menus, headers
+%D and footers and|/|or margin material.
+%D
+%D {\em This macro still needs some improvement.}
+
+\def\sbox% in handleiding, voorbeeld \inlinker{xx} \extern..
+ {\dowithnextbox
+ {\setbox0=\hbox
+ {\strut
+ \dp\nextbox=0pt
+ \lower\strutdepth\box\nextbox}%
+ \dp0=\strutdepth
+ \ht0=\strutheight
+ \box0}%
+ \vbox}
+
+%D \macros
+%D {centeredbox, centerednextbox}
+%D
+%D Here is another strange one. This one offers a sort of overlay
+%D with positive or negative offsets. This command can be used
+%D in well defined areas where no offset options are available.
+%D We first used it when building a button inside the margin
+%D footer, where the button should have a horizontal offset and
+%D should be centered with respect to the surrounding box. The
+%D last of the three examples we show below says:
+%D
+%D \starttypen
+%D \vsize=3cm
+%D \hsize=3cm
+%D \ruledvbox to \vsize
+%D {\centeredbox height .5cm width -1cm
+%D {\vrule width \hsize height \vsize}}}
+%D \stoptypen
+%D
+%D Here the \type{\ruledvbox} just shows the surrounding box
+%D and \type{\vrule} is used to show the centered box.
+%D
+%D \def\AnExample#1#2%
+%D {\vsize=3cm
+%D \hsize=3cm
+%D \ruledvbox to \vsize
+%D {\centeredbox height #1 width #2
+%D {\color[groen]{\vrule width \hsize height \vsize}}}}
+%D
+%D \startregelcorrectie
+%D \startcombinatie[3*1]
+%D {\AnExample {-1cm} {.5cm}} {}
+%D {\AnExample {.5cm} {-1cm}} {}
+%D {\AnExample {-1cm} {-.5cm}} {}
+%D \stopcombinatie
+%D \stopregelcorrectie
+%D
+%D This command takes two optional arguments: \type{width} and
+%D \type{height}. Observing readers can see that we use \TEX's
+%D own scanner for grabbing these arguments: \type{#1#} reads
+%D everyting till the next brace and passes it to both rules.
+%D The setting of the box dimensions at the end is needed for
+%D special cases. The dimensions of the surrounding box are kept
+%D intact. This commands handles positive and negative
+%D dimensions (which is why we need two boxes with rules).
+
+\def\centeredbox#1#% height +/-dimen width +/-dimen
+ {\bgroup
+ \setbox0=\vbox to \vsize
+ \bgroup
+ \mindermeldingen
+ \forgetall
+ \setbox0=\hbox{\vrule\!!width\!!zeropoint#1}%
+ \setbox2=\vbox{\hrule\!!height\!!zeropoint#1}%
+ \advance\vsize by \ht2
+ \advance\hsize by \wd0
+ \vbox to \vsize
+ \bgroup
+ \vskip-\ht2
+ \vss
+ \hbox to \hsize
+ \bgroup
+ \dowithnextbox
+ {\hskip-\wd0
+ \hss
+ \box\nextbox
+ \hss
+ \egroup
+ \vss
+ \egroup
+ \egroup
+ \wd0=\hsize
+ \ht0=\vsize
+ \box0
+ \egroup}
+ \hbox}
+
+%D For those who don't want to deal with \type {\hsize}
+%D and \type {\vsize}, we have:
+%D
+%D \starttypen
+%D \centerednextbox width 2bp height 2bp
+%D {\framed[width=100bp,height=100bp]{}}
+%D \stoptypen
+%D
+%D Do you see what we call this one \type {next}?
+
+\def\centerednextbox#1#%
+ {\bgroup
+ \dowithnextbox
+ {\hsize\wd\nextbox
+ \vsize\ht\nextbox
+ \centeredbox#1{\box\nextbox}%
+ \egroup}
+ \hbox}
+
+%D \macros
+%D {centerbox}
+%D
+%D Centering on the available space is done by:
+%D
+%D \starttypen
+%D \centeredbox <optional specs> {content}
+%D \stoptypen
+%D
+%D When omitted, the current \type {\hsize} and \type
+%D {\vsize} are used. Local dimensions are supported.
+
+\def\centerbox#1#% optional height +/-dimen width +/-dimen
+ {\bgroup
+ \dowithnextbox
+ {\setlocalhsize
+ \setbox0=\hbox{\vrule\!!width\!!zeropoint#1}%
+ \setbox2=\vbox{\hrule\!!height\!!zeropoint#1}%
+ \hsize\ifdim\wd0=\!!zeropoint\hsize\else\wd0\fi
+ \vsize\ifdim\ht2=\!!zeropoint\vsize\else\ht2\fi
+ \vbox to \vsize{\vss\hbox to \hsize{\hss\box\nextbox\hss}\vss}%
+ \egroup}%
+ \hbox}
+
+%D \macros
+%D {setrigidcolumnhsize,rigidcolumnbalance}
+%D
+%D These macros are copied from the \TEX book, page~397, and
+%D extended by a macro that sets the \type{\hsize}.
+%D
+%D \starttypen
+%D \setrigidcolumnhsize {total width} {distance} {n}
+%D \rigidcolumnbalance {box}
+%D \stoptypen
+%D
+%D Both these macros are for instance used in typesetting
+%D footnotes.
+%D
+%D Men kan het proces van breken enigzins beinvloeden met de
+%D volgende twee swithes:
+
+\newif\ifalignrigidcolumns
+\newif\ifstretchrigidcolumns
+
+%D De eerste switch bepaald het uitlijnen, de tweede rekt de
+%D individuele kolommen op naar \type{\vsize}.
+
+\def\setrigidcolumnhsize#1#2#3%
+ {\hsize=#1\relax
+ \global\chardef\rigidcolumns=#3\relax
+ \scratchdimen=-#2\relax
+ \multiply\scratchdimen by #3\relax
+ \advance\scratchdimen by #2\relax
+ \advance\hsize by \scratchdimen
+ \divide\hsize by #3\relax}
+
+\def\rigidcolumnbalance#1%
+ {\global\chardef\rigidcolumnbox=#1\relax
+ \ifnum\rigidcolumns=1
+ \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi\rigidcolumnbox
+ \else
+ \line
+ {\vbadness=10000
+ \tabskip\!!zeropoint
+ \splittopskip=\openstrutheight
+ %\scratchdimen=\ht\rigidcolumnbox % sensitive for overflow
+ %\divide\scratchdimen by \rigidcolumns % therefore we need the hack:
+ \scratchdimen=1pt
+ \divide\scratchdimen by \rigidcolumns
+ \expanded{\scratchdimen=\withoutpt{\the\scratchdimen}\ht\rigidcolumnbox}%
+ \advance\scratchdimen by \ht\strutbox
+ \valign{##\vfill\cr\dorigidcolumnsplits}}%
+ \fi}
+
+\def\dorigidcolumnsplits%
+ {\ifnum\rigidcolumns>0
+ \setbox\scratchbox=\vsplit\rigidcolumnbox to \scratchdimen
+ \ifalignrigidcolumns
+ \vbox to \ifstretchrigidcolumns\vsize\else\scratchdimen\fi
+ {\unvbox\scratchbox}%
+ \else
+ \vbox{\unvbox\scratchbox}%
+ \fi
+ \doglobal\decrement\rigidcolumns
+ \cr
+ \ifnum\rigidcolumns>0\noalign{\hfil}\fi
+ \expandafter\dorigidcolumnsplits
+ \fi}
+
+%D \macros
+%D {startvboxtohbox,stopvboxtohbox,convertvboxtohbox}
+%D
+%D Here is another of Knuth's dirty tricks, as presented on
+%D pages 398 and 399 of the \TEX book. These macros can be used
+%D like:
+%D
+%D \starttypen
+%D \vbox
+%D \bgroup
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \startvboxtohbox ... \stopvboxtohbox
+%D \egroup
+%D
+%D \vbox
+%D \bgroup
+%D \converthboxtovbox
+%D \egroup
+%D \stoptypen
+%D
+%D These macros are used in reformatting footnotes, so they do
+%D what they're meant for.
+
+\def\setvboxtohbox%
+ {\bgroup
+ \ifdim\baselineskip<16pt \relax
+ \dimen0=\baselineskip
+ \multiply\dimen0 by 1024
+ \else
+ \message{cropping \baselineskip to 16pt}%
+ \baselineskip=\maxdimen
+ \fi
+ \divide\dimen0 by \hsize
+ \multiply\dimen0 by 64
+ \xdef\vboxtohboxfactor{\expandafter\withoutpt\the\dimen0}%
+ \egroup}
+
+\def\startvboxtohbox%
+ {\bgroup
+ \setvboxtohbox
+ \setbox0=\hbox\bgroup}
+
+\def\stopvboxtohbox%
+ {\egroup
+ \dp0=\!!zeropoint
+ \ht0=\vboxtohboxfactor\wd0
+ \box0
+ \egroup}
+
+\def\convertvboxtohbox%
+ {\setvboxtohbox
+ \makehboxofhboxes
+ \setbox0=\hbox{\unhbox0 \removehboxes}%
+ \noindent\unhbox0\par}
+
+\def\makehboxofhboxes%
+ {\setbox0=\hbox{}%
+ \loop % \doloop { .. \exitloop .. }
+ \setbox2=\lastbox
+ \ifhbox2
+ \setbox0=\hbox{\box2\unhbox0}%
+ \repeat}
+
+\def\removehboxes%
+ {\setbox0=\lastbox
+ \ifhbox0
+ {\removehboxes}%
+ \unhbox0
+ \fi}
+
+%D \macros
+%D {unhhbox}
+%D
+%D The next macro is used in typesetting inline headings.
+%D Let's first look at the macro and then show an example.
+
+\newbox \unhhedbox
+\newbox \hhbox
+\newdimen \lasthhboxwidth
+\newskip \hhboxindent
+
+\def\unhhbox#1\with#2%
+ {\bgroup
+ \mindermeldingen
+ \forgetall
+ \setbox\unhhedbox=\vbox{\hskip\hhboxindent\strut\unhbox#1}% => \hsize
+ \doloop
+ {\setbox\hhbox=\vsplit\unhhedbox to \lineheight
+ \ifvoid\unhhedbox
+ \setbox\hhbox=\hbox{\strut\hboxofvbox\hhbox}%
+ \fi
+ \ht\hhbox=\ht\strutbox
+ \dp\hhbox=\dp\strutbox
+ \ifdim\hhboxindent=\!!zeropoint\else
+ \setbox\hhbox=\hbox{\hskip-\hhboxindent\box\hhbox}%
+ \hhboxindent=\!!zeropoint
+ \fi
+ \global\lasthhboxwidth=\wd\hhbox
+ #2\relax
+ \ifvoid\unhhedbox
+ \exitloop
+ \else
+ \hskip\!!zeropoint \!!plus \!!zeropoint
+ \fi}%
+ \egroup}
+
+\def\dohboxofvbox%
+ {\setbox0=\vbox{\unvbox\scratchcounter\global\setbox1=\lastbox}%
+ \unhbox1
+ \egroup}
+
+\def\hboxofvbox%
+ {\bgroup
+ \afterassignment\dohboxofvbox
+ \scratchcounter=}
+
+%D This macro can be used to break a paragraph apart and treat
+%D each line seperately, for instance, making it clickable. The
+%D main complication is that we want to be able to continue the
+%D paragraph, something that's needed in the in line section
+%D headers.
+%D
+%D \startbuffer
+%D \setbox0=\hbox{\input tufte \relax}
+%D \setbox2=\hbox{\input knuth \relax}
+%D \unhhbox0\with{\ruledhbox{\box\hhbox}}
+%D \hskip1em plus 1em minus 1em
+%D \hhboxindent=\lasthhboxwidth
+%D \advance\hhboxindent by \lastskip
+%D \unhhbox2\with{\ruledhbox{\box\hhbox}}
+%D \stopbuffer
+%D
+%D \haalbuffer
+%D
+%D This piece of text was typeset by saying:
+%D
+%D \typebuffer
+%D
+%D Not that nice a definition, but effective. Note the stretch
+%D we've build in the line that connects the two paragraphs.
+
+%D \macros
+%D {doifcontent}
+%D
+%D When processing depends on the availability of content, one
+%D can give the next macro a try.
+%D
+%D \starttypen
+%D \doifcontent{pre content}{post content}{no content}\somebox
+%D \stoptypen
+%D
+%D Where \type{\somebox} is either a \type{\hbox} or
+%D \type{\vbox}. If the dimension of this box suggest some
+%D content, the resulting box is unboxed and surrounded by the
+%D first two arguments, else the third arguments is executed.
+
+\def\doifcontent#1#2#3%
+ {\dowithnextbox
+ {\ifhbox\nextbox
+ \ifdim\wd\nextbox>\!!zeropoint
+ #1\unhbox\nextbox#2\relax
+ \else
+ #3\relax
+ \fi
+ \else
+ \ifdim\ht\nextbox>\!!zeropoint
+ #1\unvbox\nextbox#2\relax
+ \else
+ #3\relax
+ \fi
+ \fi}}
+
+%D So when we say:
+%D
+%D \startbuffer
+%D \doifcontent{[}{]}{}\hbox{content sensitive typesetting}
+%D
+%D \doifcontent{}{\pagina}{}\vbox{content sensitive typesetting}
+%D
+%D \doifcontent{}{}{\message{Didn't you forget something?}}\hbox{}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D We get:
+%D
+%D \haalbuffer
+%D
+%D Where the last call of course does not show up in this
+%D document, but definitely generates a confusing message.
+
+%D \macros
+%D {processboxes}
+%D
+%D The next macro gobble boxes and is for instance used for
+%D overlays. First we show the general handler.
+
+\newbox\processbox
+
+\def\processboxes#1%
+ {\bgroup
+ \def\doprocessbox{#1}% #1 can be redefined halfway
+ \setbox\processbox=\box\voidb@x
+ \afterassignment\dogetprocessbox\let\next=}
+
+\def\endprocessboxes%
+ {\ifhmode\unskip\fi
+ \box\processbox
+ \next
+ \egroup}
+
+\def\dogetprocessbox%
+ {\ifx\next\bgroup
+ \expandafter\dodogetprocessbox
+ \else
+ \expandafter\endprocessboxes
+ \fi}
+
+\def\dodogetprocessbox%
+ {\dowithnextbox
+ {\ifhmode\unskip\fi\doprocessbox % takes \nextbox makes \processbox
+ \afterassignment\dogetprocessbox\let\next=}
+ \hbox\bgroup}
+
+%D \macros
+%D {startoverlay}
+%D
+%D We can overlay boxes by saying:
+%D
+%D \startbuffer
+%D \startoverlay
+%D {\omlijnd{hans}}
+%D {\omlijnd[breedte=3cm]{ton}}
+%D {\omlijnd[hoogte=2cm]{oeps}}
+%D \stopoverlay
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows up as:
+%D
+%D \leavevmode\haalbuffer
+
+% \def\dooverlaybox%
+% {\ifhmode\unskip\fi
+% \ifdim\ht\nextbox>\ht\processbox
+% \setbox\processbox=\vbox to \ht\nextbox
+% {\vss\box\processbox\vss}%
+% \else
+% \setbox\nextbox=\vbox to \ht\processbox
+% {\vss\box\nextbox\vss}%
+% \fi
+% \scratchdimen=\wd
+% \ifdim\wd\nextbox>\wd\processbox
+% \nextbox
+% \else
+% \processbox
+% \fi
+% \setbox\processbox=\hbox to \scratchdimen
+% {\hbox to \scratchdimen{\hss\box\processbox\hss}%
+% \hskip-\scratchdimen
+% \hbox to \scratchdimen{\hss\box\nextbox\hss}}}
+%
+% \def\startoverlay%
+% {\bgroup
+% \let\stopoverlay\egroup
+% \processboxes\dooverlaybox}
+
+\def\dooverlaybox%
+ {\ifhmode\unskip\fi
+ \scratchdimen=\dp
+ \ifdim\dp\nextbox>\dp\processbox
+ \nextbox
+ \else
+ \processbox
+ \fi
+ \ifdim\ht\nextbox>\ht\processbox
+ \setbox\processbox=\vbox to \ht\nextbox
+ {\dp\processbox=\!!zeropoint\vss\box\processbox\vss}%
+ \else
+ \setbox\nextbox=\vbox to \ht\processbox
+ {\dp\nextbox=\!!zeropoint\vss\box\nextbox\vss}%
+ \fi
+ \dp\nextbox=\scratchdimen
+ \dp\processbox=\scratchdimen
+ \scratchdimen=\wd
+ \ifdim\wd\nextbox>\wd\processbox
+ \nextbox
+ \else
+ \processbox
+ \fi
+ \setbox\processbox=\hbox to \scratchdimen
+ {\hbox to \scratchdimen{\hss\box\processbox\hss}%
+ \hskip-\scratchdimen
+ \hbox to \scratchdimen{\hss\box\nextbox\hss}}}
+
+\def\startoverlay%
+ {\bgroup
+ \let\stopoverlay\egroup
+ \processboxes\dooverlaybox}
+
+% %D \macros
+% %D {starthspread}
+% %D
+% %D In a similar way we can build a horizontal box, spread
+% %D over the available width.
+% %D
+% %D \startbuffer
+% %D \starthspread
+% %D {hans}
+% %D {ton}
+% %D {oeps}
+% %D \stophspread
+% %D
+% %D \stopbuffer
+% %D
+% %D \typebuffer
+% %D
+% %D shows up as:
+% %D
+% %D \leavevmode\haalbuffer
+%
+% \def\dohspread%
+% {\box\nextbox
+% \def\dohspread{\hfil\box\nextbox}}
+%
+% \def\starthspread%
+% {\hbox to \hsize \bgroup
+% \let\stophspread\egroup
+% \processboxes\dohspread}
+
+%D \macros
+%D {fakebox}
+%D
+%D The next macro is a rather silly one, but saves space.
+%D
+%D \starttypen
+%D \hbox{\fakebox0}
+%D \stoptypen
+%D
+%D returns an empty box with the dimensions of the box
+%D specified, here being zero.
+
+\def\dofakebox%
+ {\setbox\scratchbox=\null
+ \wd\scratchbox=\wd\scratchcounter
+ \ht\scratchbox=\ht\scratchcounter
+ \dp\scratchbox=\dp\scratchcounter
+ \ifhbox\scratchcounter\hbox\else\vbox\fi{\box\scratchbox}%
+ \egroup}
+
+\def\fakebox%
+ {\bgroup
+ \afterassignment\dofakebox\scratchcounter}
+
+%D \macros
+%D {lbox,rbox,cbox,tbox,bbox}
+%D
+%D Here are some convenient alternative box types:
+%D
+%D \starttypen
+%D \lbox{text ...}
+%D \cbox{text ...}
+%D \rbox{text ...}
+%D \stoptypen
+%D
+%D Are similar to \type {\vbox}, which means that they also
+%D accept something like \type{to 3cm}, but align to the left,
+%D middle and right. These box types can be used to typeset
+%D paragraphs.
+
+\def\lbox{\lrcbox\raggedleft}
+\def\cbox{\lrcbox\raggedcenter}
+\def\rbox{\lrcbox\raggedright}
+
+\def\lrcbox#1#2#%
+ {\vbox#2\bgroup
+ \let\\=\endgraf
+ \forgetall#1\let\next=}
+
+%D The alternatives \type {\tbox} and \type {\bbox} can be used
+%D to properly allign boxes, like in:
+%D
+%D \startbuffer
+%D \starttabel[|||]
+%D \HL
+%D \VL \tbox{\externfiguur[koe][hoogte=3cm,kader=aan]} \VL top aligned \VL\SR
+%D \HL
+%D \VL \bbox{\externfiguur[koe][hoogte=3cm,kader=aan]} \VL bottom aligned \VL\SR
+%D \HL
+%D \stoptabel
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D The positioning depends on the strut settings:
+%D
+%D \haalbuffer
+
+\def\tbox{\tbbox\ht\dp}
+\def\bbox{\tbbox\dp\ht}
+
+\def\tbbox#1#2%
+ {\hbox\bgroup
+ \dowithnextbox
+ {\scratchdimen=\ht\nextbox
+ \advance\scratchdimen\dp\nextbox
+ \advance\scratchdimen-#1\strutbox
+ #1\nextbox=#1\strutbox
+ #2\nextbox=\scratchdimen
+ \setbox\nextbox=\hbox
+ {\lower\dp\nextbox\box\nextbox}%
+ #1\nextbox=#1\strutbox
+ #2\nextbox=\scratchdimen
+ \box\nextbox
+ \egroup}
+ \hbox}
+
+%D Some new, still undocumented features:
+
+% limitatetext -> beter {text} als laatste !!
+%
+% \limitvbox
+% \limithbox
+
+\def\limitatelines#1#2% size sentinel
+ {\dowithnextbox
+ {\dimen0=#1\hsize
+ \ifdim\wd\nextbox>\dimen0
+ \setbox\nextbox=\hbox
+ {\advance\dimen0 by -.1\hsize
+ \limitatetext{\unhbox\nextbox}{\dimen0}{\nobreak#2}}%
+ \fi
+ \unhbox\nextbox}
+ \hbox}
+
+\def\fittoptobaselinegrid% weg hier
+ {\dowithnextbox
+ {\bgroup
+ \par
+ \dimen0=\ht\nextbox
+ \ht\nextbox=\ht\strutbox
+ \dp\nextbox=\dp\strutbox
+ \hbox{\box\nextbox}
+ \prevdepth\dp\strutbox
+ \doloop
+ {\advance\dimen0 by -\lineheight
+ \ifdim\dimen0<\!!zeropoint
+ \exitloop
+ \else
+ \nobreak
+ \hbox{\strut}
+ \fi}
+ \egroup}
+ \vbox}
+
+% Handy:
+
+\def\removedepth%
+ {\ifvmode\ifdim\prevdepth>\!!zeropoint
+ \kern-\prevdepth
+ \fi\fi}
+
+% maybe some day we need this
+%
+% \def\appendvbox#1% % uses \box8
+% {\bgroup
+% \ifdim\prevdepth<\!!zeropoint
+% \ifdim\pagetotal=\!!zeropoint
+% \setbox8=\vtop{\unvcopy#1}%
+% \hrule\c!!height\!!zeropoint
+% \kern-\ht8
+% \box#1\relax
+% \else
+% \box#1\relax
+% \fi
+% \else
+% \dimen0=\prevdepth
+% \hrule\c!!height\!!zeropoint
+% \setbox8=\vtop{\unvcopy#1}%
+% \dimen2=\baselineskip
+% \advance\dimen2 by -\dimen0
+% \advance\dimen2 by -\ht8
+% \kern\dimen2
+% \box#1\relax
+% \fi
+% \egroup}
+
+%D Also new:
+%D
+%D \startbuffer
+%D \normbox[1cm][bba]{m} % b(efore) a(fter) v(box) s(trut) f(rame)
+%D \normbox[1cm][bba]{m}
+%D \normbox[1cm][bba]{m}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \haalbuffer
+%
+% \def\dodonormbox#1#2#3#4#5#6#7%
+% {\doifnumberelse{#1}
+% {\dimen0=#1}{\setbox0=#3{#1}\dimen0=#50}%
+% \doifinstringelse{f}{#2}
+% {\let\next#4}{\let\next#3}%
+% \next to \dimen0
+% {\counttoken b\in#2\to\!!counta\dorecurse{\!!counta}{#6}#6%
+% #7\nextbox
+% \counttoken a\in#2\to\!!counta\dorecurse{\!!counta}{#6}#6}}
+%
+% \def\donormbox[#1][#2]%
+% {\bgroup
+% \doifinstringelse{v}{#2}
+% {\let\next\vbox}
+% {\let\next\hbox}%
+% \dowithnextbox
+% {\ifvbox\nextbox
+% \let\\=\par
+% \dodonormbox{#1}{#2}\vbox\ruledvbox\ht\vfil\unvbox
+% \else
+% \let\\=\space
+% \dodonormbox{#1}{#2}\hbox\ruledhbox\wd\hfil\unhbox
+% \fi
+% \egroup}%
+% \next}
+%
+% \def\normbox%
+% {\dodoubleempty\donormbox}
+
+\protect
+
+\endinput