%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. Non||commercial use is 
%C granted. 

%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
   \boxrulewidth=5\testrulewidth 
   #3#4\relax
   \setbox0=\normalhbox to \scratchdimen
     {#2{\ruledhbox to \scratchdimen
           {\vrule 
              #5 20\testrulewidth 
              \!!width \!!zeropoint
            \normalhss}}}%
   \smashbox0
   \normalpenalty\!!tenthousand
   \box0
   \egroup}

\def\ruledhanging%
  {\ifdim\hangindent>\!!zeropoint\relax
     \ifnum\hangafter<0
       \normalhbox 
         {\boxrulewidth=5\testrulewidth
          \setbox0=\ruledhbox to \hangindent
            {\scratchdimen=\ht\strutbox
             \advance\scratchdimen by \dp\strutbox
             \vrule
               \!!width\!!zeropoint
               \!!height\!!zeropoint
               \!!depth-\hangafter\scratchdimen}%
          \normalhskip-\hangindent
          \smashbox0
          \raise\ht\strutbox\box0}%
     \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\relax
     \showparagraphcue\parindent\relax\relax\relax\!!height 
   \else
     \showparagraphcue{40\testrulewidth}\llap\relax\relax\!!height 
   \fi
   \normalhskip\parindent}

\def\ruledleavevmode%
  {\relax
   \normalleavevmode
   \ifdim\parindent>\!!zeropoint\relax
     \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 \startsmaller
%D \voorbeeld \indent     
%D \voorbeeld \noindent   
%D \voorbeeld \leavevmode 
%D \stopsmaller
%D \egroup
%D
%D These examples also demonstrate the visualization of 
%D \type{\leftskip} and \type{\rightskip}. 

\newcounter\ruledbaselines

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

\def\ruledbaseline%
  {\vrule \!!width \!!zeropoint
   \bgroup
   \dontinterfere
   \doglobal\increment\ruledbaselines
   \scratchdimen=3\baselineskip
   \setbox\scratchbox=\normalvbox to 2\scratchdimen
     {\leaders
        \normalhbox
          {\strut
           \vrule
             \!!height \testrulewidth
             \!!depth \testrulewidth
             \!!width 120pt}
      \normalvfill}%
   \smashbox\scratchbox
   \advance\scratchdimen by \strutheightfactor\baselineskip
   \setbox\scratchbox=\normalhbox
     {\normalhskip -48pt
      \normalhbox to 24pt
        {\normalhss\debuggertext\ruledbaselines\normalhskip6pt}%
      \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
     {\ttxx           \vl 
      v:\the\vsize    \vl
      g:\the\pagegoal \vl 
      t:\the\pagetotal\vl}}

%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 \startregelcorrectie
%D \haalbuffer
%D \stopregelcorrectie
%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 \startregelcorrectie
%D \haalbuffer
%D \stopregelcorrectie
%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

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

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

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

\def\cutmarksymbols%
  {\setbox\scratchbox=\normalvbox to \cutmarklength
     {\normalvfill
      \normalhbox to \cutmarklength
        {\normalhfill\ssxx\cutmarksymbol\normalhfill}%
      \normalvfill}%
   \normalhbox to \ruledwidth
     {\scratchdimen=\cutmarklength
      \divide\scratchdimen by 2
      \llap{\copy\scratchbox\normalhskip\cutmarkoffset\scratchdimen}%
      \normalhfill
      \rlap{\normalhskip\cutmarkoffset\scratchdimen\copy\scratchbox}}}

\def\makecutbox#1%
  {\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 by 2
      \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
      \box\scratchbox
      \ifx\cutmarksymbol\relax \else
        \setbox\scratchbox=\normalvbox 
          {\setbox\scratchbox=\normalhbox{\cutmarksymbols}%
           \vskip-\cutmarkoffset\scratchdimen
           \vskip-\cutmarklength
           \copy\scratchbox
           \vskip\cutmarkoffset\scratchdimen
           \vskip\ruledheight
           \vskip\ruleddepth
           \vskip\cutmarkoffset\scratchdimen
           \copy\scratchbox}%
        \ht\scratchbox=\ruledheight
        \dp\scratchbox=\ruleddepth
        \wd\scratchbox=\!!zeropoint
        \box\scratchbox
      \fi
      \box#1}%
   \wd#1=\ruledwidth
   \ht#1=\ruledheight
   \dp#1=\ruleddepth}

\def\cuthbox%
  {\normalhbox\bgroup
   \dowithnextbox{\makecutbox\nextbox\box\nextbox\egroup}%
   \normalhbox}

\def\cutvbox%
  {\normalvbox\bgroup
   \dowithnextbox{\makecutbox\nextbox\box\nextbox\egroup}%
   \normalvbox}

\def\cutvtop%
  {\normalvtop\bgroup
   \dowithnextbox{\makecutbox\nextbox\box\nextbox\egroup}%
   \normalvtop}

%D \macros
%D   {colormarkbox}
%D
%D This macro is used in the pagebody routine. No other use 
%D is advocated here.
%D
%D \starttypen
%D \colormarkbox0
%D \stoptypen

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

\def\colorrangeA#1#2#3#4%
  {\vbox
     {\scratchdimen=-\colormarklength
      \multiply\scratchdimen by 4
      \advance\scratchdimen by \ruledheight 
      \advance\scratchdimen by \ruleddepth
      \divide\scratchdimen by 21
      \def\docommando##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\ifdim##1pt=0pt#1\else##1\fi\hss}%
                 \vss}%
            \fi}}%
      \offinterlineskip
      \processcommalist[1.00,0.95,0.75,0.50,0.25,0.05,0.00]\docommando}}

\def\colorrangeB%
  {\hbox
     {\scratchdimen=-\colormarklength
      \multiply\scratchdimen by 2
      \advance\scratchdimen by \ruledwidth
      \divide\scratchdimen by 11
      \def\docommando ##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\ifdim##2pt=.5pt##2~\fi##1\hss}
              \vss}%
         \fi}%
      \docommando C .5 \iftrue \iffalse\iffalse\iffalse
      \docommando M .5 \iffalse\iftrue \iffalse\iffalse
      \docommando Y .5 \iffalse\iffalse\iftrue \iffalse
      \docommando K .5 \iffalse\iffalse\iffalse\iftrue
      \docommando C 1  \iftrue \iffalse\iffalse\iffalse
      \docommando G 1  \iftrue \iffalse\iftrue \iffalse
      \docommando Y 1  \iffalse\iffalse\iftrue \iffalse
      \docommando R 1  \iffalse\iftrue \iftrue \iffalse
      \docommando M 1  \iffalse\iftrue \iffalse\iffalse
      \docommando B 1  \iftrue \iftrue \iffalse\iffalse
      \docommando K 1  \iffalse\iffalse\iffalse\iftrue}}

\def\colorrangeC%
  {\hbox
     {\scratchdimen=-\colormarklength
      \multiply\scratchdimen by 2
      \advance\scratchdimen by \ruledwidth
      \divide\scratchdimen by 14
      \def\docommando##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\hbox to \scratchdimen{\hss##1\hss}\vss}%
         \fi}%
      \processcommalist
        [1.00,0.95,0.90,0.85,0.80,0.75,
         0.70,0.60,0.50,0.40,0.30,0.20,0.10,0.00]\docommando}}

\def\docolormarkbox#1%
  {\edef\ruledheight{\the\ht#1}%
   \edef\ruleddepth {\the\dp#1}%
   \edef\ruledwidth {\the\wd#1}%
   \setbox#1=\hbox
     {\scratchdimen=\colormarklength
      \divide\scratchdimen by 2
      \forgetall
      \ssxx
      \setbox\scratchbox=\vbox 
        {\offinterlineskip
         \vskip-\colormarkoffset\scratchdimen
         \vskip-2\scratchdimen
         \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#1}%
   \wd#1=\ruledwidth
   \ht#1=\ruledheight
   \dp#1=\ruleddepth}

\def\colormarkbox#1%
  {\ifincolor
     \docolormarkbox{#1}%
   \fi}

%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 \stelkleurenin[status=start]
%D 
%D Whatsits show up \color[blue]{in color} and are 
%D characterized bij their first character.\voetnoot [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 is already superseded
  \let\supernormalmarks \normalmarks % mark is already 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}%
     \scratchdimen=1ex
     \ifdone
       \setbox\scratchbox=\hbox
         {\hskip#4\scratchdimen\box\scratchbox}%
     \else
       \setbox\scratchbox=\hbox
         {\raise#4\scratchdimen\box\scratchbox}%
     \fi 
     \smashbox\scratchbox
     \ifdone\nointerlineskip\fi
     \box\scratchbox
     \ifvmode\nointerlineskip\fi
     \popwhatsit
     \egroup
     \ifimmediatewrite
       \immediatewritefalse
       \expandafter\normalimmediate
     \fi}

  \def\pushwhatsit%
    {\ifdim\lastskip=\!!zeropoint
       \ifnum\lastpenalty=0 
         \ifnum\lastkern=0
           \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
 
\protect

\endinput
