%D \module
%D   [       file=supp-fun,
%D        version=1995.10.10,
%D          title=\CONTEXT\ Support Macros,
%D       subtitle=Fun Stuff,
%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. 

\unprotect

%D This module implements some typographics tricks that can 
%D be fun when designing document layouts. The examples use
%D macros that are typical to \CONTEXT, but non \CONTEXT\
%D users can use the drop caps and first line treatment 
%D macros without problems. This module will be extended
%D when the need for more of such tricks arises.

\ifx \undefined \writestatus \input supp-mis.tex \relax \fi

\writestatus{loading}{Context Support Macros / Fun Stuff}

\ifx\definefont\undefined
  \def\definedfont[#1]{\font\temp#1\relax\temp}
\fi

%D \macros
%D   {DroppedCaps, DroppedString, DroppedIndent, DroppedLines}
%D     
%D \startbuffer
%D \DroppedCaps 
%D   {\color[green]} {cmbx12} 
%D   {2.2\baselineskip} {2pt} {\baselineskip} {2} 
%D   Let's start
%D \stopbuffer
%D
%D \haalbuffer with dropped caps, those blown up first
%D characters of a paragraph. It's hard to implement a general
%D mechanism that suits all situations, but dropped caps are so 
%D seldomly used that we can permit ourselves a rather user
%D unfriendly implementation.
%D
%D \typebuffer
%D
%D As we will see, there are 7 different settings involved. The
%D first argument takes a command that is used to do whatever
%D fancy things we want to do, but normally this one will be
%D empty. The second argument takes the font. Because we're
%D dealing with something very typographic, there is no real
%D reason to adopt complicated font switching schemes, a mere
%D name will do. Font encodings can bring no harm, because the
%D alphanumeric characters are nearly always located at their
%D natural position in the encoding vector.
%D
%D \startbuffer
%D \DroppedCaps 
%D   {\color[red]} {cmbx12} 
%D   {\baselineskip} {0pt} {0pt} {1} 
%D   This simple
%D \stopbuffer
%D
%D \haalbuffer case shows us what happens when we apply minimal
%D values. Here we used:
%D
%D \typebuffer
%D
%D \startbuffer
%D \DroppedCaps 
%D   {\color[red]} {cmbx12} 
%D   {2\baselineskip} {0pt} {\baselineskip} {2} 
%D   Is this ugly 
%D \stopbuffer
%D 
%D \haalbuffer example the third argument tells 
%D this macro that we want a dropped capital scaled to the 
%D baseline distance. The two zero point arguments are the 
%D horizontal and vertical offsets and the last arguments
%D determines the hanging indentation. In this paragraph we 
%D set the height to two times the baselinedistance and use 
%D two hanging lines: 
%D 
%D \typebuffer
%D 
%D Here, the first character is moved down one baseline. Here
%D we also see why the horizontal offset is important. The
%D first example (showing the~L) sets this to a few points and
%D also used a slightly larger height. 
%D
%D Of course common users (typist) are not supposed to see this
%D kind of fuzzy definitions, but fortunately \TEX\ permits us
%D to hide them in macros. Using a macro also enables us to
%D garantee consistency throughout the document:
%D
%D \startbuffer
%D \def\MyDroppedCaps%
%D   {\DroppedCaps 
%D      {\color[green]} {cmbx12} 
%D      {5\baselineskip} {3pt} {3\baselineskip} {4}}
%D
%D \MyDroppedCaps The implementation
%D \stopbuffer
%D 
%D \typebuffer
%D 
%D \haalbuffer of the general macro is rather simple and only
%D depends on the arguments given and the dimensions of the
%D strut box. We explicitly load the font, which is no problem
%D because \TEX\ does not load a font twice. We could have
%D combined some arguments, like the height, vertical offset
%D and the number of lines, but the current implementation
%D proved to be the most flexible. One should be aware of the
%D fact that the offsets depend on the design of the glyphs 
%D used. 

\let\DroppedIndent\!!zeropoint \def\DroppedLines{0}

\def\DroppedString%
  {ABCDEFGHIJKLMNOPQRSTUVWXYZ}

% \def\DroppedCaps#1#2#3#4#5#6#7% 
%   {\ExpandBothAfter\doifinstringelse{#7}{\DroppedString} % 
%      {\ifvmode % this one is \EveryPar save, precede by \par if needed
%         \vskip#6\baselineskip
%         \penalty-200
%         \vskip-#6\baselineskip
%       \fi
%       \ifhmode
%         \hskip-\parindent
%       \fi
%       \setbox0=\hbox
%         {\definedfont[#2 at #3]#1{#7}\hskip#4}%
%          \ifdim\dp0>\strutdp % one of those Q's , will be option
%            \setbox2=\hbox{\raise\dp0\hbox{\lower\strutdp\copy0}}%
%            \ht2=\ht0 \dp0=\strutdp \setbox0=\box2
%          \fi
%       \setbox0\hbox
%         {\lower#5\box0}%
%       \ht0\strutht
%       \dp0\strutdp
%       \edef\DroppedIndent{\the\wd0}%
%       \edef\DroppedLines {\number#6}%
%       \hangindent\DroppedIndent
%       \hangafter-\DroppedLines
%       \noindent
%       \hskip-\DroppedIndent
%       \vbox{\forgetall\box0}%
%       \nobreak
%       \ignorespaces} % Could be a one character word ! 
%      {\edef\DroppedIndent{0pt}%
%       \edef\DroppedLines {\number\maxdimen}%
%       #7}}

\let\globaldropcaps\global % will be an option, but on by default

\def\localdropcaps{\let\globaldropcaps\relax}

\chardef\DroppedStatus=0 % 0=done 1=starting 2=doing 3=error

% \def\DroppedCaps#1#2#3#4#5#6#7% does not yet handle accented chars
%   {\convertargument            #7\to\asciia
%    \convertcommand \DroppedString\to\asciib
%    \ExpandBothAfter\doifinstringelse{\asciia}{\asciib}
%      {\ifvmode % this one is \EveryPar save, precede by \par if needed
%         \vskip#6\baselineskip
%         \penalty-200
%         \vskip-#6\baselineskip
%       \fi
%       \ifhmode
%         \hskip-\parindent
%       \fi
%       \setbox0\hbox
%         {\definedfont[#2 at #3]#1{#7}\hskip#4}%
%          \ifdim\dp0>\strutdp % one of those Q's , will be option
%            \setbox2\hbox{\raise\dp0\hbox{\lower\strutdp\copy0}}%
%            \ht2\ht0 \dp0\strutdp \setbox0\box2
%          \fi
%       \setbox0\hbox
%         {\lower#5\box0}%
%       \ht0\strutht
%       \dp0\strutdp
%       \globaldropcaps\edef\DroppedIndent{\the\wd0}%
%       \globaldropcaps\edef\DroppedLines {\number#6}%
%       \globaldropcaps\chardef\DroppedStatus2
%       \globaldropcaps\hangindent\DroppedIndent
%       \globaldropcaps\hangafter-\DroppedLines
%       \noindent
%       \hskip-\DroppedIndent
%       \vbox{\forgetall\box0}%
%       \nobreak
%       \let\next\ignorespaces} % Could be a one character word !
%      {\globaldropcaps\let\DroppedIndent\!!zeropoint
%       \globaldropcaps\edef\DroppedLines{\number\maxdimen}%
%       \globaldropcaps\chardef\DroppedStatus3
%       \def\next{#7}}%
%    \let\globaldropcaps\global 
%    \next}

\chardef\DropMode=0 % 1 == marginhang 

\def\DroppedCaps#1#2#3#4#5#6#7% does not yet handle accented chars
  {\convertargument            #7\to\asciia
   \convertcommand \DroppedString\to\asciib
   \ExpandBothAfter\doifinstringelse\asciia\asciib
     {\ifvmode % this one is \EveryPar save, precede by \par if needed
        \vskip#6\baselineskip
        \penalty-200
        \vskip-#6\baselineskip
      \fi
      \ifhmode
        \hskip-\parindent
      \fi
      \setbox0\hbox
        {\definedfont[#2 at #3]#1{#7}\hskip#4}%
         \ifdim\dp0>\strutdp % one of those Q's , will be option
           \setbox2\hbox{\raise\dp0\hbox{\lower\strutdp\copy0}}%
           \ht2\ht0
           \dp0\strutdp
           \setbox0\box2
         \fi
      \setbox0\hbox
        {\ifnum\DropMode=\plusone
           \hskip-\wd0\wd0\zeropoint
         \fi
         \lower#5\box0}%
      \ht0\strutht
      \dp0\strutdp
      \ifnum\DropMode=\plusone
        \globaldropcaps\let\DroppedIndent\!!zeropoint
        \globaldropcaps\edef\DroppedLines{\number\maxdimen}%
        \globaldropcaps\chardef\DroppedStatus3
      \else
        \globaldropcaps\edef\DroppedIndent{\the\wd0}%
        \globaldropcaps\edef\DroppedLines {\number#6}%
        \globaldropcaps\chardef\DroppedStatus2
        \globaldropcaps\hangindent\DroppedIndent
        \globaldropcaps\hangafter-\DroppedLines
        \noindent
        \hskip-\DroppedIndent
      \fi
      \vbox{\forgetall\box0}%
      \nobreak
      \let\next\ignorespaces} % Could be a one character word !
     {\globaldropcaps\let\DroppedIndent\!!zeropoint
      \globaldropcaps\edef\DroppedLines{\number\maxdimen}%
      \globaldropcaps\chardef\DroppedStatus3
      \def\next{#7}}%
   \let\globaldropcaps\global 
   \next}

%D Before we go to the next topic, we summarize this command:
%D
%D \starttypen
%D \DroppedCaps 
%D   {command} {font} 
%D   {height} {hoffset} {voffset} {lines}
%D \stoptypen
%D 
%D Sometimes you need to make sure that the global settings are
%D kept local, as in:  
%D 
% %D \startbuffer
% %D \defineparagraphs[SomePar][n=2,rule=on]
% %D \setupparagraphs [SomePar][1][width=.5\textwidth]
% %D \setupparagraphs [SomePar][2][width=.5\textwidth]
%D \startbuffer
%D \definieeralineas[SomePar][n=2,rule=on]
%D \stelalineasin [SomePar][1][width=.5\textwidth]
%D \stelalineasin [SomePar][2][width=.5\textwidth]
%D 
%D \startSomePar
%D   \localdropcaps\NiceDroppedCaps{}{cmr12}{0pt}{2}Here we need
%D   to explicitly keep the hanging indentation local, like it or
%D   not. 
%D \SomePar
%D   \localdropcaps\NiceDroppedCaps{}{cmr12}{0pt}{2}Here we need
%D   to explicitly keep the hanging indentation local, like it or
%D   not. 
%D \stopSomePar
%D \stopbuffer
%D 
%D \typebuffer \getbuffer

%D \macros 
%D   {AutoDroppedCaps, CheckDroppedCaps}
%D
%D {\em To be documented.}

% example usage 
%
% \def\bpar{\ifvmode\CheckDroppedCaps\fi}
% \def\epar{\ifhmode\par\fi\CheckDroppedCaps}

\newcount\lastprevgraf
\newcount\droppedlines

\def\CheckDroppedCaps
  {\global\lastprevgraf\prevgraf}

\def\AutoDroppedCaps % will be proper core stuff since it
  {\globaldropcaps\chardef\DroppedStatus\plusone
   \global\lastprevgraf\zerocount
   \global\droppedlines\zerocount
   \EveryPar{\doAutoDroppedCaps}}

\let\AutoDroppedNext\relax
  
\def\doAutoDroppedCaps
  {\ifcase\DroppedStatus % done
     \let\next\relax  
   \or % starting
   % \ifnum\lastprevgraf>0 % tricky, probably a wrong par 
   %   \globaldropcaps\chardef\DroppedStatus=3 % and inhibits dropped
   %   \let\next\relax % caps after titles and more than once
   % \else % so let's nill this rubishly code fragment 
       \def\next{\NiceDroppedCaps{}{\@@dcfont}{.125em}{\@@dcn}}%
   % \fi % and hope for the best 
   \or % doing
     \global\advance\droppedlines \lastprevgraf
     \ifnum\droppedlines=\zerocount
       \globaldropcaps\chardef\DroppedStatus\zerocount
       \let\next\relax
     \else\ifnum\droppedlines>\zerocount
       \ifnum\droppedlines<\DroppedLines\relax
         \globaldropcaps\hangindent\DroppedIndent
         \globaldropcaps\hangafter-\DroppedLines
         \globaldropcaps\advance\hangafter \droppedlines
         \hskip-\parindent
         \let\next\AutoDroppedNext
       \else
         \globaldropcaps\chardef\DroppedStatus\zerocount
         \let\next\relax
       \fi
     \else
       \globaldropcaps\chardef\DroppedStatus\zerocount
       \let\next\relax
     \fi\fi
   \or % error
     \globaldropcaps\chardef\DroppedStatus\zerocount
     \let\next\relax
   \fi
   \next}

%D \macros 
%D   {LineDroppedCaps, NiceDroppedCaps}
%D
%D To save definitions, we also provide: 
%D
%D \starttypen
%D \LineDroppedCaps {command} {font} {hoffset} {lines}
%D \NiceDroppedCaps {command} {font} {hoffset} {lines}
%D \stoptypen
%D
%D The first command scales the font to the exact height, while 
%D the second command scales the font to a nice 2.5 times the 
%D line height, a value that gives a pleasant grayness. 

\def\DoLineDroppedCaps#1#2#3#4#5% compensation command font offset lines 
  {\scratchcounter#5%
   \advance\scratchcounter \minusone
   \scratchdimen\scratchcounter\baselineskip
   \advance\scratchdimen #1%
   \NormalizeFontHeight\DummyFont{W}\scratchdimen{#3}%
   \DroppedCaps{#2}{#3}\TheNormalizedFontSize{#4}
     {\scratchcounter\baselineskip}{#5}}

\def\LineDroppedCaps% command font offset lines
  {\DoLineDroppedCaps{\strutht}}

\def\NiceDroppedCaps% command font offset lines
  {\DoLineDroppedCaps{.5\baselineskip}}

%D \macros
%D   {TreatFirstLine}
%D
%D \startbuffer
%D \TreatFirstLine {\sc} {} {} {}
%D Instead of limiting its action to one token, the next macro
%D treats the whole first line. This paragraph was typeset by
%D saying:
%D \stopbuffer
%D
%D \haalbuffer
%D
%D \typebuffer
%D
%D \startbuffer
%D \TreatFirstLine {\startcolor[red]\bf} {\stopcolor} {} {}
%D The combined color and font effect is also possible,
%D although one must be careful in using macros that accumulate
%D grouping, but the commands used here are pretty save in that
%D respect.
%D \stopbuffer
%D
%D \haalbuffer
%D
%D \typebuffer
%D 
%D Before we explain the third and fourth argument, we show the
%D implementation. Those who know a bit about the way \TEX\ 
%D treats tokens, will probably see in one glance that this
%D alternative works all right for most text||only situations
%D in which there is enough text available for the first line,
%D but that more complicated things will blow. One has to live
%D with that. A workaround is rather trivial but obscures the
%D principles used. 

\def\TreatFirstLine#1#2#3#4% before, after, first, next
  {\leavevmode
   \bgroup
   \forgetall
   \bgroup
   #1%
   \setbox0\box\voidb@x
   \setbox2\box\voidb@x
   \def\grabfirstline##1 %
     {\setbox2\hbox
        {\ifvoid0
           {#3{\ignorespaces##1}}%
         \else
           \unhcopy0\ {#4{##1}}%
         \fi}%
      \ifdim\wd2=\zeropoint
        \setbox0\box\voidb@x
        \setbox2\box\voidb@x
        \@EA\grabfirstline
      \else\ifdim\wd2>\hsize
        \hbox to \hsize{\strut\unhbox0}#2\egroup
        \break##1\ 
        \egroup
      \else
        \setbox0\box2
        \@EAEAES\grabfirstline
      \fi\fi}%
   \grabfirstline}

%D \startbuffer
%D \gdef\FunnyCommand
%D   {\getrandomfloat\FunnyR{0}{1}%
%D    \getrandomfloat\FunnyG{0}{1}%
%D    \getrandomfloat\FunnyB{0}{1}%
%D    \definecolor[FunnyColor][r=\FunnyR,g=\FunnyG,b=\FunnyB]%
%D    \color[FunnyColor]}
%D 
%D \TreatFirstLine {\bf} {} {\FunnyCommand} {\FunnyCommand}
%D The third and fourth argument can be used to gain special 
%D effects on the individual words. Of course one needs ...
%D \stopbuffer
%D 
%D \haalbuffer 
%D to know a bit more about the macro package used to get real 
%D nice effects, but this example probably demonstrates the 
%D principles well. 
%D 
%D \typebuffer
%D 
%D Like in dropped caps case, one can hide such treatments in a
%D macro, like:
%D
%D \starttypen
%D \def\MyTreatFirstLine%
%D   {\TreatFirstLine{\bf}{}{\FunnyCommand}{\FunnyCommand}}
%D \stoptypen

%D \macros 
%D   {reshapebox}
%D 
%D \startbuffer 
%D \beginofshapebox
%D When using \CONTEXT, one can also apply this funny command 
%D to whole lines by using the reshape mechanism. Describing 
%D this interesting mechanism falls outside the scope of this 
%D module, so we only show the trick. This is an example of 
%D low level \CONTEXT\ functionality: it's all there, and it's 
%D stable, but not entirely meant for novice users. 
%D \endofshapebox
%D 
%D \reshapebox{\FunnyCommand{\box\shapebox}} \flushshapebox
%D \stopbuffer
%D 
%D \haalbuffer
%D 
%D \typebuffer
%D
%D This mechanism permits hyphenation and therefore gives 
%D better results than the previously discussed macro 
%D \type{\TreatFirstLine}. 

%D \macros
%D   {TreatFirstCharacter}
%D
%D \startbuffer
%D \TreatFirstCharacter{\bf\color[green]} Just to be 
%D \stopbuffer
%D
%D \haalbuffer complete we also offer a very simple one 
%D character alternative, that is not that hard to understand:

\def\TreatFirstCharacter#1#2% command, character
  {{#1{#2}}}

%D A previous paragraph started with:
%D
%D \typebuffer

%D \macros
%D   {StackCharacters}
%D
%D The next hack deals with vertical stacking.

\def\StackCharacters#1#2#3#4% sequence vsize vskip command
  {\vbox #2
     {\forgetall
      \baselineskip\zeropoint
      \def\StackCharacter##1{#4{##1}\cr\noalign{#3}}%
      \halign
        {\hss##\hss&##\cr
         \handletokens#1\with\StackCharacter\cr}}}

%D \startbuffer
%D \StackCharacters{CONTEXT}{}{\vskip.2ex}{\FunnyCommand}
%D \stopbuffer
%D 
%D Such a stack looks like:
%D 
%D \startregelcorrectie
%D \hbox to \hsize
%D    {$\hss\bfd
%D     \vcenter{\StackCharacters{TEX}    {}{\vskip.2ex}{\FunnyCommand}}%
%D     \hss
%D     \vcenter{\StackCharacters{CON}    {}{\vskip.2ex}{\FunnyCommand}}
%D     \hss
%D     \vcenter{\StackCharacters{TEXT}   {}{\vskip.2ex}{\FunnyCommand}}
%D     \hss
%D     \vcenter{\StackCharacters{CONTEXT}{}{\vskip.2ex}{\FunnyCommand}}
%D     \hss$}
%D \stopregelcorrectie
%D 
%D and is typeset by saying:
%D
%D \typebuffer
%D
%D An alternative would have been
%D
%D \starttypen
%D \StackCharacters {CONTEXT} {to 5cm} {\vfill} {\FunnyCommand}
%D \stoptypen

%D \macros
%D   {processtokens}
%D
%D At a lower level horizontal and vertical manipulations are
%D already supported by:
%D
%D \starttypen
%D \processtokens {begin} {between} {end} {space} {text}
%D \stoptypen
%D
%D \startbuffer[a]
%D \processtokens 
%D   {\hbox to .5\hsize\bgroup} {\hfill} 
%D   {\egroup} {\space} {LET'S HAVE}
%D \stopbuffer
%D  
%D \startbuffer[b]
%D \processtokens 
%D   {\vbox\bgroup\raggedcenter\hsize1em} 
%D   {\vskip.25ex} {\egroup} {\strut} {FUN}
%D \stopbuffer
%D
%D This macro is able to typeset: 
%D
%D \leavevmode\hbox to \hsize
%D   {$\hfil\hfil
%D    \vcenter{\bf\haalbuffer[a]}%
%D    \hfil
%D    \vcenter{\bfd\haalbuffer[b]}%
%D    \hfil\hfil$}
%D
%D which was specified as:
%D
%D \typebuffer[a]
%D \typebuffer[b]

%D \macros
%D   {NormalizeFontHeight, NormalizeFontWidth, 
%D    TheNormalizedFontSize}
%D
%D Next we introduce some font manipulation macros. When we
%D want to typeset some text spread in a well defined area, it
%D can be considered bad practice to manipulate character and
%D word spacing. In such situations the next few macros can be
%D of help: 
%D 
%D \starttypen
%D \NormalizeFontHeight \name {sample text} {height} {font}
%D \NormalizeFontWidth  \name {sample text} {width}  {font}
%D \stoptypen
%D 
%D These are implemented using an auxilliary macro:

\def\NormalizeFontHeight{\NormalizeFontSize\ht}
\def\NormalizeFontWidth {\NormalizeFontSize\wd} 

% \def\NormalizeFontSize#1#2#3#4#5%
%   {\bgroup
%    \dimen0=#4% #4 can be \ht0 or so
%    \setbox0\hbox{\definedfont[#5 at 10pt]#3}%
%    \ifdim\wd0>\zeropoint
%      \dimen2=#10 % #1 is \wd or \ht
%      \dimen4=10000pt
%      \divide\dimen4 \dimen2
%      \divide\dimen0 \plusthousand
%      \dimen0=\number\dimen4\dimen0
%      \xdef\TheNormalizedFontSize{\the\dimen0}%
%    \else
%      \dimen0\bodyfontsize
%    \fi
%    \definedfont[#5 at \the\dimen0]%
%    \expandafter
%    \egroup
%    \expandafter\font\expandafter#2\fontname\font\relax}
%
% the familiar struggle with accuracy forces us to use: 

\def\NormalizeFontSize#1#2#3#4#5% 
  {\bgroup
   \dimen0=#4% #4 can be \ht0 or so
   \setbox0\hbox{\definedfont[#5 at 5pt]#3}% 10pt
   \ifdim\wd0>\zeropoint
     \dimen2=#10 % #1 is \wd or \ht
     \dimen4=\maxdimen % 10000pt
     \divide\dimen4 \dimen2
     \divide\dimen0 1638 % 1000
     \dimen0=\number\dimen4\dimen0
     \divide \dimen0 \plustwo % ...
     \xdef\TheNormalizedFontSize{\the\dimen0}%
   \else
     \dimen0\bodyfontsize
   \fi
   \definedfont[#5 at \the\dimen0]%
   \expandafter
   \egroup
   \expandafter\font\expandafter#2\fontname\font\relax}

%D Afterwards, we have access to the calculated size by: 

\let\TheNormalizedFontSize\!!zeropoint

%D Extra: 

\def\WidthSpanningText#1#2#3% text width font 
  {\hbox{\NormalizeFontWidth\temp{#1}{#2}{#3}\temp\the\everydefinedfont#1}}

%D Consider for instance:
%D 
%D \startbuffer
%D \NormalizeFontHeight \tmp {X} {2\baselineskip} {cmr10}
%D 
%D {\tmp To Be Or Not To Be}
%D \stopbuffer
%D 
%D \typebuffer
%D 
%D This shows up as (we also show the baselines):
%D  
%D {\showbaselines\haalbuffer}
%D 
%D The horizontal counterpart is:
%D 
%D \startbuffer
%D \NormalizeFontWidth \tmp {This Line Fits} {\hsize} {cmr10}
%D 
%D \hbox{\tmp This Line Fits}
%D \stopbuffer
%D 
%D \typebuffer
%D 
%D The calculated font scale is avaliable in the macro 
%D \type{\NormalizedFontSize}. 
%D
%D \startregelcorrectie
%D \ruledhbox{\haalbuffer}
%D \stopregelcorrectie
%D
%D One can of course combine these macros with the ones 
%D described earlier, like in:
%D 
%D \starttypen
%D \NormalizeFontHeight {text} \DroppedFont {2\baselineskip} {cmbx12}
%D 
%D \def\NicelyDroppedCaps
%D   {\DroppedCaps 
%D      {\kleur[groen]} 
%D      {\DroppedFont} 
%D      {2pt} 
%D      {\baselineskip} 
%D      {2}}
%D \stoptypen
%D
%D It's up to the reader to test this one. 

\unexpanded\def\FirstNCharacters#1#2% \FirstNCharacters{3}{fr{\"o}beln}
  {\bgroup
   \scratchcounter\zerocount
   \def\docommando##1%
     {\ifnum\scratchcounter=#1\else
        ##1\relax % catches ##1 = \"e and alike
        \advance\scratchcounter\plusone
      \fi}
   \handletokens#2\with\docommando
   \egroup}

%D \macros 
%D   {FittingText}
%D
%D First used in Pascal (demo-bbv):  
%D 
%D \startbuffer
%D \ruledvbox{\FittingText{3cm}{1cm}{Serif}{24pt}{1pt}{1}
%D   {\veryraggedright
%D    \hangindent1em\hangafter1\relax 
%D    \begstrut \dorecurse{8}{Bram Marta }\unskip \endstrut}}
%D
%D \ruledvbox{\FittingText{3cm}{1cm}{Serif}{24pt}{1pt}{1}
%D   {\raggedleft\begstrut Bram\\Marta \unskip\endstrut}}
%D \stopbuffer
%D
%D \typebuffer
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection

% #1 width #2 height #3 font #4 size #5 step #6 interlinie #7 text 

\long\def\FittingText#1#2#3#4#5#6#7% 
  {\bgroup
   \forgetall
   \dontcomplain
   \setuptolerance[\v!zeersoepel]% == \tolerance4500
   \hsize#1% 
   \def\\{\softbreak}%
   \!!heighta#4%
   \!!heightb#2%
   \doloop
     {\ifdim\!!heighta>\!!onepoint
        \expanded{\definefont[\s!dummy][#3 at \the\!!heighta][\c!interlinie=#6]}%
        \getvalue\s!dummy
        \setbox\scratchbox\vbox{#7\endgraf}%
        \ifdim\ht\scratchbox>\!!heightb
          \advance\!!heighta-#5%
        \else
          \beginshapebox
          \unvcopy\scratchbox
          \endshapebox
          \global\dimen1\hsize
          \reshapebox
            {\setbox\shapebox\hbox{\unhbox\shapebox}%
             \ifdim\wd\shapebox>\dimen1 
               \global\dimen1\wd\shapebox
             \fi}%
          \ifdim\dimen1>\hsize 
            \advance\!!heighta-#5%
          \else
            \exitloop
          \fi 
        \fi
      \else
        \exitloop
      \fi}%
   \writestatus{\strippedcsname\FittingText}{height: \the\!!heighta}%
   \unvbox\scratchbox
   \egroup}

%D New: 

% \font width gap font spec text 

\def\NormalizeFontWidthSpread#1#2#3#4#5#6% 
  {\global\setfalse\NFSpread
   \scratchdimen#3%
   \scratchdimen-.5\scratchdimen
   \advance\scratchdimen#2\relax
   \NormalizeFontWidth  
     #1%
     {\def\+{\global\settrue\NFSpread\gobbleuntil\relax}%
      \def\\{\gobbleuntil\relax}% newline 
      \setupspacing
      #6\relax}%
     {\scratchdimen}%
     {#4}%
   \ifconditional\NFSpread
     % de gap valt in de binding 
   \else
     \definefont[\strippedcsname#1][#4 #5]%
   \fi}

\def\SpreadGapText#1#2%
% {{\def\+{\blackrule[\c!breedte=#1]}#2}}
  {{\def\+{\kern#1}#2}}

\def\GapText#1#2#3#4#5% width distance font spec title
  {\bgroup
   \NormalizeFontWidthSpread\DummyFont{#1}{#2}{#3}{#4}{#5}%
   \DummyFont\setupspacing\SpreadGapText{#2}{#5}\endgraf
   \egroup}

\protect \endinput
