%D \module
%D   [       file=core-vis,
%D        version=1996.06.01,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Visualization,
%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.

%D This module adds some more visualization cues to the ones
%D supplied in the support module.
%D
%D %\everypar   dual character, \the\everypar and \everypar=
%D %\hrule      cannot be grabbed in advance, switches mode
%D %\vrule      cannot be grabbed in advance, switches mode
%D %
%D %\indent     only explicit ones
%D %\noindent   only explicit ones
%D %\par        only explicit ones
%D
%D %\leftskip   only if explicit one
%D %\rightskip  only if explicit one

\writestatus{loading}{Context Support Macros / Visualization}

\unprotect

%D \macros
%D   {indent, noindent,
%D    leavevmode,
%D    par}
%D
%D \TeX\ acts upon paragraphs. In mosts documents paragraphs
%D are separated by empty lines, which internally are handled as
%D \type{\par}. Paragraphs can be indented or not, depending on
%D the setting of \type{\parindent}, the first token of a
%D paragraph and/or user suppressed or forced indentation.
%D
%D Because the actual typesetting is based on both explicit
%D user and implicit system actions, visualization is only
%D possible for the user supplied \type{\indent},
%D \type{\noindent}, \type{\leavevmode} and \type{\par}. Other
%D 'clever' tricks will quite certainly lead to more failures
%D than successes, so we only support these three explicit
%D primitives and one macro:

\let\normalnoindent   = \noindent
\let\normalindent     = \indent
\let\normalpar        = \par

\let\normalleavevmode = \leavevmode

\def\showparagraphcue#1#2#3#4#5%
  {\bgroup
   \scratchdimen#1\relax
   \dontinterfere
   \dontcomplain
   \boxrulewidth5\testrulewidth
   #3#4\relax
   \setbox\scratchbox\normalhbox to \scratchdimen
     {#2{\ruledhbox to \scratchdimen
           {\vrule #5 20\testrulewidth \!!width \zeropoint
            \normalhss}}}%
   \smashbox\scratchbox
   \normalpenalty\!!tenthousand
   \box\scratchbox
   \egroup}

\def\ruledhanging
  {\ifdim\hangindent>\zeropoint
     \ifnum\hangafter<\zerocount
       \normalhbox
         {\boxrulewidth5\testrulewidth
          \setbox\scratchbox\ruledhbox to \hangindent
            {\scratchdimen\strutht
             \advance\scratchdimen \strutdp
             \vrule
               \!!width  \zeropoint
               \!!height \zeropoint
               \!!depth -\hangafter\scratchdimen}%
          \normalhskip-\hangindent
          \smashbox\scratchbox
          \raise\strutht\box\scratchbox}%
     \fi
   \fi}

\def\ruledparagraphcues
  {\bgroup
   \dontcomplain
   \normalhbox to \zeropoint
     {\ifdim\leftskip>\zeropoint\relax
        \showparagraphcue\leftskip\llap\relax\relax\!!depth
        \normalhskip-\leftskip
      \fi
      \ruledhanging
      \normalhskip\hsize
      \ifdim\rightskip>\zeropoint\relax
        \normalhskip-\rightskip
        \showparagraphcue\rightskip\relax\relax\relax\!!depth
      \fi}%
   \egroup}

\def\ruledpar
  {\relax
   \ifhmode
     \showparagraphcue{40\testrulewidth}\relax\rightrulefalse\relax\!!height
   \fi
   \normalpar}

\def\rulednoindent
  {\relax
   \normalnoindent
   \ruledparagraphcues
   \showparagraphcue{40\testrulewidth}\llap\leftrulefalse\relax\!!height}

\def\ruledindent
  {\relax
   \normalnoindent
   \ruledparagraphcues
   \ifdim\parindent>\zeropoint
     \showparagraphcue\parindent\relax\relax\relax\!!height
   \else
     \showparagraphcue{40\testrulewidth}\llap\relax\relax\!!height
   \fi
   \normalhskip\parindent}

\def\ruledleavevmode
  {\relax
   \normalleavevmode
   \ifdim\parindent>\zeropoint
     \normalhskip-\parindent
     \ruledparagraphcues
     \showparagraphcue\parindent\relax\leftrulefalse\rightrulefalse\!!height
     \normalhskip\parindent
   \else
     \ruledparagraphcues
     \showparagraphcue{40\testrulewidth}\llap\leftrulefalse\rightrulefalse\!!height
   \fi}

\def\dontshowimplicits
  {\let\noindent   \normalnoindent
   \let\indent     \normalindent
   \let\leavevmode \normalleavevmode
   \let\par        \normalpar}

\def\showimplicits
  {\testrulewidth  \defaulttestrulewidth
   \let\noindent   \rulednoindent
   \let\indent     \ruledindent
   \let\leavevmode \ruledleavevmode
   \let\par        \ruledpar}

%D The next few||line examples show the four cues. Keep in
%D mind that we only see them when we explicitly open or close
%D a paragraph.
%D
%D \bgroup
%D \def\voorbeeld#1%
%D   {#1Visualizing some \TeX\ primitives and Plain \TeX\
%D    macros can be very instructive, at least it is to me.
%D    Here we see {\tt\string#1} and {\tt\string\ruledpar} in
%D    action, while {\tt\string\parindent} equals
%D    {\tt\the\parindent}.\ruledpar}
%D
%D \showimplicits
%D
%D \voorbeeld \indent
%D \voorbeeld \noindent
%D \voorbeeld \leavevmode
%D
%D \parindent=60pt
%D
%D \voorbeeld \indent
%D \voorbeeld \noindent
%D \voorbeeld \leavevmode
%D
%D \startnarrower
%D \voorbeeld \indent
%D \voorbeeld \noindent
%D \voorbeeld \leavevmode
%D \stopnarrower
%D \egroup
%D
%D These examples also demonstrate the visualization of
%D \type {\leftskip} and \type {\rightskip}. The macro
%D \type {\nofruledbaselines} determines the number of lines
%D shown.

\newcounter\ruledbaselines

\def\nofruledbaselines{3}

\def\debuggertext#1%
  {\ifx\ttxx\undefined
     $\scriptscriptstyle#1$%
   \else
     {\ttxx#1}%
   \fi}

\def\ruledbaseline
  {\vrule \!!width \zeropoint
   \bgroup
   \dontinterfere
   \doglobal\increment\ruledbaselines
   \scratchdimen\nofruledbaselines\baselineskip
   \setbox\scratchbox\normalvbox to 2\scratchdimen
     {\leaders
        \normalhbox
          {\strut
           \vrule
             \!!height \testrulewidth
             \!!depth \testrulewidth
             \!!width 120\points}
      \normalvfill}%
   \smashbox\scratchbox
   \advance\scratchdimen \strutheightfactor\baselineskip
   \setbox\scratchbox\normalhbox
     {\normalhskip -48\points
      \normalhbox to 24\points
        {\normalhss\debuggertext\ruledbaselines\normalhskip6\points}%
      \raise\scratchdimen\box\scratchbox}%
   \smashbox\scratchbox
   \box\scratchbox
   \egroup}

\def\showbaselines
  {\testrulewidth\defaulttestrulewidth
   \EveryPar{\ruledbaseline}}

%D \macros
%D   {showpagebuilder}
%D
%D The next tracing option probaly is only of use to me and a
%D few \CONTEXT\ hackers.

\def\showpagebuilder
  {\EveryPar{\doshowpagebuilder}}

\def\doshowpagebuilder
  {\strut\llap
     {\startcolor[blue]\vl
      \high{\infofont v:\the\vsize    }\vl
      \high{\infofont g:\the\pagegoal }\vl
      \high{\infofont t:\the\pagetotal}\vl
      \stopcolor}}

%D \macros
%D   {makecutbox, cuthbox, cutvbox, cutvtop}
%D
%D Although mainly used for marking the page, these macros can
%D also serve local use.
%D
%D \startbuffer
%D \setbox0=\vbox{a real \crlf vertical box} \makecutbox0
%D \stopbuffer
%D
%D \typebuffer
%D
%D This marked \type{\vbox} shows up as:
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D The alternative macros are used as:
%D
%D \startbuffer
%D \cuthbox{a made cut box}
%D \stopbuffer
%D
%D \typebuffer
%D
%D This is typeset as:
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D By setting the next macros one can influence the length of
%D the marks as well as the horizontal and vertical divisions.

\def\cutmarklength           {2\bodyfontsize}
\chardef\horizontalcutmarks = 2
\chardef\verticalcutmarks   = 2
\chardef\cutmarkoffset      = 1
\let\cutmarksymbol          = \relax
\let\cutmarktoptext         = \empty
\let\cutmarkbottomtext      = \empty

\def\horizontalcuts
  {\normalhbox to \ruledwidth
     {\dorecurse\horizontalcutmarks
        {\vrule\!!width\boxrulewidth\!!height\cutmarklength\normalhfill}%
      \unskip}}

\def\verticalcuts
  {\scratchdimen\ruledheight
   \advance\scratchdimen \ruleddepth
   \normalvbox to \scratchdimen
     {\hsize\cutmarklength
      \dorecurse\verticalcutmarks
        {\vrule\!!height\boxrulewidth\!!width\hsize\normalvfill}%
      \unskip}}

\def\baselinecuts
  {\ifdim\ruleddepth>\zeropoint
     \scratchdimen\ruledheight
     \advance\scratchdimen \ruleddepth
     \normalvbox to \scratchdimen
       {\scratchdimen\cutmarklength
        \divide\scratchdimen 2
        \hsize\scratchdimen
        \normalvskip\zeropoint\!!plus\ruledheight
        \vrule\!!height\boxrulewidth\!!width\hsize
        \normalvskip\zeropoint\!!plus\ruleddepth}%
   \fi}

\def\cutmarksymbols#1%
  {\normalhbox to \ruledwidth
     {\setbox\scratchbox\normalhbox to \cutmarklength
        {\normalhss\infofont\cutmarksymbol\normalhss}%
      \normalhss
      \normalvbox to \cutmarklength
        {\scratchdimen\cutmarklength
         \divide\scratchdimen \plustwo
         \normalvss
         \hbox to \ruledwidth
           {\llap{\copy\scratchbox\normalhskip\cutmarkoffset\scratchdimen}%
            \normalhskip\scratchdimen\hss\infofont#1\hss\normalhskip\scratchdimen
            \rlap{\normalhskip\cutmarkoffset\scratchdimen\copy\scratchbox}}%
         \normalvss}%
      \normalhss}}

\def\makecutbox#1% simplier with layers, todo
  {\edef\ruledheight{\the\ht#1}%
   \edef\ruleddepth {\the\dp#1}%
   \edef\ruledwidth {\the\wd#1}%
   \setbox#1\normalhbox
     {\dontcomplain
      \forgetall
      \boxmaxdepth\maxdimen
      \offinterlineskip
      \scratchdimen\cutmarklength
      \divide\scratchdimen \plustwo
      \hsize\ruledwidth
      \setbox\scratchbox\normalvbox
        {\setbox\scratchbox\normalhbox{\horizontalcuts}%
         \normalvskip-\cutmarkoffset\scratchdimen
         \normalvskip-2\scratchdimen
         \copy\scratchbox
         \normalvskip\cutmarkoffset\scratchdimen
         \hbox to \ruledwidth
           {\setbox\scratchbox\normalhbox{\verticalcuts}%
            \llap{\copy\scratchbox\normalhskip\cutmarkoffset\scratchdimen}%
            \bgroup
            \setbox\scratchbox\normalhbox{\baselinecuts}%
            \llap{\copy\scratchbox\normalhskip\cutmarkoffset\scratchdimen}%
            \normalhfill
            \rlap{\normalhskip\cutmarkoffset\scratchdimen\copy\scratchbox}%
            \egroup
            \rlap{\normalhskip\cutmarkoffset\scratchdimen\copy\scratchbox}}%
         \normalvskip\cutmarkoffset\scratchdimen
         \copy\scratchbox}%
      \ht\scratchbox\ruledheight
      \dp\scratchbox\ruleddepth
      \wd\scratchbox\zeropoint
      \resetcolorseparation
      \localstartcolor[\defaulttextcolor]%
      \box\scratchbox
      \ifx\cutmarksymbol\relax \else
        \setbox\scratchbox\normalvbox
          {\vskip-\cutmarkoffset\scratchdimen
           \vskip-\cutmarklength
           \normalhbox{\cutmarksymbols\cutmarktoptext}%
           \vskip\cutmarkoffset\scratchdimen
           \vskip\ruledheight
           \vskip\ruleddepth
           \vskip\cutmarkoffset\scratchdimen
           \normalhbox{\cutmarksymbols\cutmarkbottomtext}}%
        \ht\scratchbox\ruledheight
        \dp\scratchbox\ruleddepth
        \wd\scratchbox\zeropoint
        \box\scratchbox
      \fi
      \localstopcolor
      \box#1}%
   \wd#1=\ruledwidth
   \ht#1=\ruledheight
   \dp#1=\ruleddepth}

\def\cuthbox
  {\normalhbox\bgroup
   \dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalhbox}

\def\cutvbox
  {\normalvbox\bgroup
   \dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvbox}

\def\cutvtop
  {\normalvtop\bgroup
   \dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvtop}

%D \macros
%D   {colormarkbox,rastermarkbox}
%D
%D This macro is used in the pagebody routine. No other use
%D is advocated here.
%D
%D \starttyping
%D \colormarkbox0
%D \stoptyping

\def\colormarkoffset{\cutmarkoffset}
\def\colormarklength{\cutmarklength}

\def\colorrangeA#1#2#3#4%
  {\vbox
     {\scratchdimen-\colormarklength
      \multiply\scratchdimen 4
      \advance\scratchdimen \ruledheight
      \advance\scratchdimen \ruleddepth
      \divide\scratchdimen 21
      \def\docommand##1%
        {\vbox
           {\hsize3em % \scratchdimen
            \definecolor
              [\s!dummy]
              [\c!c=#2##1\else0\fi,
               \c!m=#3##1\else0\fi,
               \c!y=#4##1\else0\fi,
               \c!k=0]%
            \localstartcolor[\s!dummy]%
            \hrule
              \!!width 3em
              \!!height \scratchdimen
              \!!depth  \zeropoint
            \localstopcolor
            \ifdim\scratchdimen>1ex
              \vskip-\scratchdimen
              \vbox to \scratchdimen
                {\vss
                 \hbox to 3em
                   {\hss
                    \localstartcolor[\s!white]%
                    \ifdim##1\points=\zeropoint#1\else##1\fi
                    \localstopcolor
                    \hss}%
                 \vss}%
            \fi}}%
      \offinterlineskip
      \processcommalist[1.00,0.95,0.75,0.50,0.25,0.05,0.00]\docommand}}

\def\colorrangeB
  {\hbox
     {\scratchdimen-\colormarklength
      \multiply\scratchdimen \plustwo
      \advance\scratchdimen \ruledwidth
      \divide\scratchdimen 11
      \def\docommand ##1 ##2 ##3##4##5##6%
        {\definecolor
           [\s!dummy]
           [\c!c=##3##2\else0\fi,
            \c!m=##4##2\else0\fi,
            \c!y=##5##2\else0\fi,
            \c!k=##6##2\else0\fi]%
         \localstartcolor[\s!dummy]%
         \vrule
           \!!width  \scratchdimen
           \!!height \colormarklength
           \!!depth  \zeropoint
         \localstopcolor
         \ifdim\scratchdimen>2em
           \hskip-\scratchdimen
           \vbox to \colormarklength
             {\vss
              \hbox to \scratchdimen
                {\hss
                 \localstartcolor[\s!white]%
                 \ifdim##2\points=.5\points##2~\fi##1%
                 \localstopcolor
                 \hss}
              \vss}%
         \fi}%
      \docommand C .5 \iftrue \iffalse\iffalse\iffalse
      \docommand M .5 \iffalse\iftrue \iffalse\iffalse
      \docommand Y .5 \iffalse\iffalse\iftrue \iffalse
      \docommand K .5 \iffalse\iffalse\iffalse\iftrue
      \docommand C 1  \iftrue \iffalse\iffalse\iffalse
      \docommand G 1  \iftrue \iffalse\iftrue \iffalse
      \docommand Y 1  \iffalse\iffalse\iftrue \iffalse
      \docommand R 1  \iffalse\iftrue \iftrue \iffalse
      \docommand M 1  \iffalse\iftrue \iffalse\iffalse
      \docommand B 1  \iftrue \iftrue \iffalse\iffalse
      \docommand K 1  \iffalse\iffalse\iffalse\iftrue}}

\def\colorrangeC
  {\hbox
     {\resetcolorseparation
      \scratchdimen-\colormarklength
      \multiply\scratchdimen 2
      \advance\scratchdimen \ruledwidth
      \divide\scratchdimen 14
      \def\docommand##1%
        {\definecolor[\s!dummy][\c!s=##1]%
         \localstartcolor[\s!dummy]%
         \vrule
           \!!width  \scratchdimen
           \!!height \colormarklength
           \!!depth  \zeropoint
         \localstopcolor
         \ifdim\scratchdimen>2em
           \hskip-\scratchdimen
           \vbox to \colormarklength
             {\vss
              \localstartcolor[\s!white]%
              \hbox to \scratchdimen{\hss##1\hss}
              \localstopcolor
             \vss}%
         \fi}%
      \processcommalist[1,.95,.9,.85,.8,.75,.7,.6,.5,.4,.3,.2,.1,0]\docommand}}

\def\docolormarkbox#1#2%
  {\edef\ruledheight{\the\ht#2}%
   \edef\ruleddepth {\the\dp#2}%
   \edef\ruledwidth {\the\wd#2}%
   \setbox#2\hbox
     {\scratchdimen\colormarklength
      \divide\scratchdimen \plustwo
      \forgetall
      \ssxx
      \setbox\scratchbox\vbox
        {\offinterlineskip
         \vskip-\colormarkoffset\scratchdimen
         \vskip-2\scratchdimen\relax % relax needed
         % beware: no \ifcase, due to nested \iftrue/\iffalse
         % and lacking \fi's
         \doifelse{#1}{0}%
           {\vskip\colormarklength
            \vskip\colormarkoffset\scratchdimen
            \vskip\ruledheight}
           {\hbox to \ruledwidth{\hss\hbox{\colorrangeB}\hss}%
            \vskip\colormarkoffset\scratchdimen
            \vbox to \ruledheight
              {\vss
               \hbox to \ruledwidth
                 {\llap{\colorrangeA C\iftrue\iffalse\iffalse\hskip\colormarkoffset\scratchdimen}%
                  \hfill
                  \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA R\iffalse\iftrue\iftrue}}%
               \vss
               \hbox to \ruledwidth
                 {\llap{\colorrangeA M\iffalse\iftrue\iffalse\hskip\colormarkoffset\scratchdimen}%
                  \hfill
                  \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA G\iftrue\iffalse\iftrue}}%
               \vss
               \hbox to \ruledwidth
                 {\llap{\colorrangeA Y\iffalse\iffalse\iftrue\hskip\colormarkoffset\scratchdimen}%
                  \hfill
                  \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA B\iftrue\iftrue\iffalse}}%
               \vss}}%
         \vskip\colormarkoffset\scratchdimen
         \hbox to \ruledwidth
           {\hss\lower\ruleddepth\hbox{\colorrangeC}\hss}}%
      \ht\scratchbox\ruledheight
      \dp\scratchbox\ruleddepth
      \wd\scratchbox\zeropoint
      \box\scratchbox
      \box#2}%
   \wd#2=\ruledwidth
   \ht#2=\ruledheight
   \dp#2=\ruleddepth}

\def\colormarkbox % #1
  {\ifincolor\@EA\docolormarkbox\else\@EA\gobbletwoarguments\fi1}

\def\rastermarkbox % #1
  {\ifincolor\@EA\docolormarkbox\else\@EA\gobbletwoarguments\fi0}

%D \macros
%D   {showwhatsits, dontshowwhatsits}
%D
%D \TEX\ has three so called whatsits: \type {\mark}, \type
%D {\write} and \type {\special}. The first one keeps track of
%D the current state at page boundaries, the last two are used
%D to communicate to the outside world. Due to fact that
%D especially \type {\write} is often used in conjunction with
%D \type {\edef}, we can only savely support that one in \ETEX.
%D
%D \bgroup \showwhatsits \setupcolors[state=start]
%D
%D Whatsits show up \color[blue]{in color} and are
%D characterized bij their first character.\footnote [some note]
%D {So we may encounter \type {w}, \type {m} and \type{s}.}
%D They are \writestatus{dummy}{demo}\color[yellow]{stacked}.
%D
%D \egroup

\newif\ifimmediatewrite

\ifx\eTeXversion\undefined

  \let\showwhatsits    \relax
  \let\dontshowwhatsits\relax

\else

  \let\supernormalmark  \normalmark  % mark may already been superseded
  \let\supernormalmarks \normalmarks % mark may already been superseded

  \def\showwhatsits
    {\protected\def\normalmark {\visualwhatsit100+m\supernormalmark }%
     \protected\def\normalmarks{\visualwhatsit100+m\supernormalmarks}%
     \protected\def\special    {\visualwhatsit0100s\normalspecial   }%
     \protected\def\write      {\visualwhatsit001-w\normalwrite     }%
     \let\immediate\immediatewhatsit
     \appendtoks\dontshowwhatsits\to\everystoptext}

  \def\immediatewhatsit
    {\bgroup\futurelet\next\doimmediatewhatsit}

  \def\doimmediatewhatsit
    {\ifx\next\write
       \egroup\immediatewritetrue
     \else
       \egroup\expandafter\normalimmediate
     \fi}

  \def\dontshowwhatsits
    {\let\immediate \normalimmediate
     \let\normalmark\supernormalmark
     \let\special   \normalspecial
     \let\write     \normalwrite}

  \def\visualwhatsit#1#2#3#4#5%
    {\bgroup
     \pushwhatsit
     \dontinterfere
     \dontcomplain
     \dontshowcomposition
     \dontshowwhatsits
     \ttx
     \ifvmode\donetrue\else\donefalse\fi
     \setbox\scratchbox\hbox
       {\ifdone\dostartgraycolormode0\else\dostartrgbcolormode#1#2#3\fi
        #5\dostopcolormode}%
     \setbox\scratchbox\hbox
       {\ifdone\dostartrgbcolormode#1#2#3\else\dostartgraycolormode0\fi
        \vrule\!!width\wd\scratchbox\dostopcolormode
        \hskip-\wd\scratchbox\box\scratchbox}%
     \scratchdimen1ex
     \setbox\scratchbox\hbox
       {\ifdone\hskip\else\raise#4\fi\scratchdimen\box\scratchbox}%
     \smashbox\scratchbox
     \ifdone\nointerlineskip\fi
     \box\scratchbox
     \ifvmode\nointerlineskip\fi
     \popwhatsit
     \egroup
     \ifimmediatewrite
       \immediatewritefalse
       \expandafter\normalimmediate
     \fi}

  \def\pushwhatsit
    {\ifzeropt\lastskip
       \ifcase\lastpenalty
         \ifzeropt\lastkern
           \ifhmode
             \let\popwhatsit\relax
           \else
             \edef\popwhatsit{\prevdepth\the\prevdepth}%
           \fi
         \else
           \ifhmode
             \edef\popwhatsit{\kern\the\lastkern}\unkern
           \else
             \edef\popwhatsit{\kern\the\lastkern\prevdepth\the\prevdepth}%
             \kern-\lastkern
           \fi
         \fi
       \else
         \ifhmode
           \edef\popwhatsit{\the\lastpenalty}%
           \unpenalty
         \else
           \edef\popwhatsit{\penalty\the\lastpenalty\prevdepth\the\prevdepth}%
          %\nobreak
         \fi
       \fi
     \else
       \ifhmode
         \edef\popwhatsit{\hskip\the\lastskip}\unskip
       \else
         \edef\popwhatsit{\vskip\the\lastskip\prevdepth\the\prevdepth}%
         \vskip-\lastskip
       \fi
     \fi}

\fi

%D The next macro can be used to keep track of classes of
%D boxes (handy for development cq.\ tracing).

\def\dodotagbox#1#2#3% can be reimplemented
  {\def\next##1##2##3##4%
     {\vbox to \ht#2{##3\hbox to \wd#2{##1#3##2}##4}}%
   \processaction
     [#1]
     [        l=>\next\relax\hfill\vfill\vfill,
              r=>\next\hfill\relax\vfill\vfill,
              t=>\next\hfill\hfill\relax\vfill,
              b=>\next\hfill\hfill\vfill\relax,
             lt=>\next\relax\hfill\relax\vfill,
             lb=>\next\relax\hfill\vfill\relax,
             rt=>\next\hfill\relax\relax\vfill,
             rb=>\next\hfill\relax\vfill\relax,
             tl=>\next\relax\hfill\relax\vfill,
             bl=>\next\relax\hfill\vfill\relax,
             tr=>\next\hfill\relax\relax\vfill,
             br=>\next\hfill\relax\vfill\relax,
     \s!default=>\next\hfill\hfill\vfill\vfill,
     \s!unknown=>\next\hfill\hfill\vfill\vfill]}

\def\dotagbox[#1]#2%
  {\bgroup
   \dowithnextbox
     {\setbox\scratchbox\flushnextbox
      \setbox\nextbox\ifhbox\nextbox\hbox\else\vbox\fi
        \bgroup
          \startoverlay
            {\copy\scratchbox}
            {\dodotagbox{#1}\scratchbox{\framed
               [\c!background=\v!screen,\c!backgroundscreen=1]{#2}}}
          \stopoverlay
        \egroup
      \nextboxwd\the\wd\scratchbox
      \nextboxht\the\ht\scratchbox
      \nextboxdp\the\dp\scratchbox
      \flushnextbox
      \egroup}}

\def\tagbox
  {\dosingleempty\dotagbox}

%D \macros
%D   {coloredhbox,coloredvbox,coloredvtop,
%D    coloredstrut}
%D
%D The following visualizations are used in some of the manuals:

\definecolor[boxcolor:ht][r=.5,g=.75,b=.5]
\definecolor[boxcolor:dp][r=.5,g=.5,b=.75]
\definecolor[boxcolor:wd][r=.75,g=.5,b=.5]
\definecolor[strutcolor] [r=.5,g=.25,b=.25]

\def\coloredbox#1%
  {\dowithnextbox{#1{\hbox
     {\blackrule[\c!width=\nextboxwd,\c!height=\nextboxht,\c!depth=\zeropoint,\c!color=boxcolor:ht]%
      \hskip-\nextboxwd
      \blackrule[\c!width=\nextboxwd,\c!height=\zeropoint,\c!depth=\nextboxdp,\c!color=boxcolor:dp]%
      \hskip-\nextboxwd
      \box\nextbox}}}#1}

\def\coloredhbox{\coloredbox\hbox}
\def\coloredvbox{\coloredbox\vbox}
\def\coloredvtop{\coloredbox\vtop}

\def\coloredstrut
  {\color[strutcolor]{\def\strutwidth{2\points}\setstrut\strut}}

\protect \endinput
