%D \module
%D   [       file=node-rul,
%D        version=2009.11.03, % 1995.10.10,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Bars,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

% todo: ex and and em traveling with attribute
% todo: this will move to typo-rul + ctxcommands

\writestatus{loading}{ConTeXt Core Macros / Bars}

%D \macros
%D   {underbar,underbars,
%D    overbar,overbars,
%D    overstrike,overstrikes,
%D    setupbar}
%D
%D In the rare case that we need undelined words, for instance because all font
%D alternatives are already in use, one can use \type {\underbar} and \type
%D {\overstrike} and their plural forms.
%D
%D \startbuffer
%D \underbars {drawing \underbar{bars} under words is a typewriter leftover}
%D \overstrikes {striking words makes them \overstrike {unreadable} but
%D sometimes even \overbar {top lines} come into view.}
%D \stopbuffer
%D
%D \typebuffer
%D
%D \startlines
%D \getbuffer
%D \stoplines
%D
%D The formal definitions are:
%D
%D \showsetup{underbar}
%D \showsetup{underbars}
%D \showsetup{overbar}
%D \showsetup{overbars}
%D \showsetup{overstrike}
%D \showsetup{overstrikes}
%D
%D \showsetup{setupbars}
%D
%D Units can be any normal \TEX\ unit:
%D
%D \startbuffer
%D \setupbars[unit=mm,rulethickness=1]     bar\startbar[underbar]foo\stopbar bar\blank
%D \setupbars[unit=ex,rulethickness=1]     bar\startbar[underbar]foo\stopbar bar\blank
%D \setupbars[unit=pt,rulethickness=1]     bar\startbar[underbar]foo\stopbar bar\blank
%D \setupbars[unit=pt,rulethickness=10pt]  bar\startbar[underbar]foo\stopbar bar
%D \stopbuffer
%D
%D \typebuffer \blank \getbuffer \blank
%D
%D As with many early usage of \LUA\ in \MKIV\ this mechanism explores a way
%D to deal with local settings at the \TEX\ end and remembering parameters
%D at the \LUA\ end. We might do things differently now, but as settings normally
%D don't change that often, we're not in a hurry to do that now. The problem at
%D the \LUA\ end is that we don't know when to clean up.

\unprotect

%definesystemattribute[ruled]
%definesystemattribute[shifted]

\newdimension\d_rule_width
\newdimension\d_rule_height
\newdimension\d_rule_depth
\newdimension\d_rule_h
\newdimension\d_rule_v
\newdimension\d_rule_line
\newdimension\d_rule_offset
\newdimension\d_rule_factor

\lettonothing\m_rule_color

\registerctxluafile{node-rul}{autosuffix}

\installcorenamespace{bar}
\installcorenamespace{barstack}

\installcommandhandler \??bar {bar} \??bar

\lettonothing\p_node_color
\lettonothing\p_node_continue
\lettonothing\p_node_offset
\lettonothing\p_node_text

\aliased\let\setupbars\setupbar

\appendtoks
    \frozen\protected\instance\edefcsname\currentbar\endcsname{\node_rules_direct{\currentbar}}%
\to \everydefinebar

% \protected\def\node_rules_direct#1%
%   {\groupedcommand
%      {\node_rules_set{#1}\barparameter\c!left}%
%      {\relax\barparameter\c!right}}

\protected\def\node_rules_direct#1%
  {\groupedcommand
     {\dontleavehmode % this should not be needed but it is in \bTD
      \node_rules_set{#1}%
      \barparameter\c!left
      }%\ignorespaces}%
     {%\removeunwantedspaces
      \barparameter\c!right}}

\permanent\protected\def\inlinebar[#1]%
  {\node_rules_direct{#1}}

%D \overbar{Über} \underbar{Unterstrich \underbar{steigt \overbar{auf} den \underbar{Unterberg}}}.
%D
%D \underbar {\underbar {\samplefile{tufte}}}\par
%D \underbar {\underdot {\samplefile{tufte}}}\par
%D \underbar {\underdot {\samplefile{tufte}}}\par
%D \underdot {\underbar {\samplefile{tufte}}}\par
%D \underbars{\underdot {\samplefile{tufte}}}\par
%D \underbar {\underdots{\samplefile{tufte}}}\par
%D \underdots{\underdots{\samplefile{tufte}}}\par

\newinteger\c_node_rules_nesting % todo: same as colors
\newinteger\c_node_rules_level
\newinteger\c_node_rules_up
\newinteger\c_node_rules_down

\permanent\protected\def\node_rules_set#1%
  {\cdef\currentbar{#1}%
   \advanceby\c_node_rules_level\plusone
   \usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor
   \edef\p_node_color   {\barparameter\c!color}% todo
   \edef\p_node_offset  {\barparameter\c!offset}%
   \edef\p_node_continue{\barparameter\c!continue}%
   % better is a dedicated key: up/down .. todo
   \scratchcounter\barparameter\c!method\relax
   \ifnum\scratchcounter=\plustwo
     % offset is dimension
   \orelse\ifnum\scratchcounter=\plusthree
     % offset is dimension
   \else
     % offset is number
     \advanceby\ifdim\p_node_offset\onepoint<\zeropoint\c_node_rules_down\else\c_node_rules_up\fi\plusone
   \fi
   \ifx\p_node_continue\v!always
      \attribute\runningtextattribute \minusone
      \let\p_node_continue\v!yes % not needed
   \fi
   \clf_setrule
         method        \scratchcounter
         continue      {\p_node_continue}%
         rulethickness {\barparameter\c!rulethickness}%
         mp            {\includeMPgraphic{\barparameter\c!mp}}
         ma            \c_attr_colormodel
         ca            \rawcolorattribute\p_node_color
         ta            \rawtransparencyattribute\p_node_color
         order         {\barparameter\c!order}%
     \ifnum\scratchcounter=\plustwo
         height        {\barparameter\c!height}%
         depth         {\barparameter\c!depth}%
       \ifchkdimexpr\p_node_offset\or
         offset        \number\lastchkdimension % dimension
       \fi
     \orelse\ifnum\scratchcounter=\plusthree
         height        {\barparameter\c!height}%
         depth         {\barparameter\c!depth}%
       \ifchkdimexpr\p_node_offset\or
         offset        \number\lastchkdimension % dimension
      \fi
     \else
         unit          {\barparameter\c!unit}%
         level         \c_node_rules_level
         stack         \ifdim\p_node_offset\onepoint<\zeropoint\c_node_rules_down\else\c_node_rules_up\fi
         max           \barparameter\c!max\relaxedspace % number
         offset        \p_node_offset\relaxedspace % number
         dy            \barparameter\c!dy\relaxedspace % number, also fraction
         empty         {\barparameter\c!empty}%
       \ifempty{\barparameter\c!text}\else
         text          \hbox{\lastnamedcs}%
         repeat        {\barparameter\c!repeat}%
       \fi
     \fi
   \relax}

\permanent\protected\def\resetbar
  {\c_attr_ruled\attributeunsetvalue}

\permanent\protected\def\nobar
  {\groupedcommand
     {\resetbar\barparameter\c!left}%
     {\relax\barparameter\c!right}}

\permanent\protected\def\startbar[#1]%
  {\begingroup
   \node_rules_set{#1}%
   \ignorespaces
   \barparameter\c!left}

\permanent\protected\def\stopbar
  {\removeunwantedspaces
   \barparameter\c!right
   \endgroup}

\permanent\protected\def\setbar[#1]%
  {\node_rules_set{#1}}

\aliased\let\directsetbar\node_rules_set

% ungrouped % todo: use the lua based stacker

\permanent\protected\def\pushbar[#1]%
  {\global\advanceby\c_node_rules_nesting\plusone
   \edefcsname\??barstack\the\c_node_rules_nesting\endcsname
     {\c_node_rules_level\the\c_node_rules_level
      \c_attr_ruled      \the\c_attr_ruled}%
   \node_rules_set{#1}}

\permanent\protected\def\popbar
  {\csname\??barstack\the\c_node_rules_nesting\endcsname\relax
   \global\advanceby\c_node_rules_nesting\minusone}

% we can save some by havign defaults at the lua end

\setupbars
  [\c!method=0,                 % new: 0=center nested, 1=stack nested
   \c!continue=\v!no,
   \c!level=\v!yes,
   \c!empty=,                   % new: yes = hide text
   \c!offset=0,                 % upwards, replaces: topoffset bottomoffset
   \c!dy=0,
   \c!max=3,
   \c!style=,
   \c!rulethickness=.1,
   \c!order=\v!foreground,
   \c!height=\zeropoint,
   \c!depth=\zeropoint,
   \c!unit=ex,                  % so now we are relative
   \c!color=]                   % replaces: rulecolor

% \definebar[touchbar]    [\c!method=0,\c!dy=-0.4,\c!offset=-0.0]
% \definebar[touchbars]   [touchbar]   [\c!continue=\v!yes]

\pushoverloadmode

\aliased\let\normalmathoverbar    \overbar
\aliased\let\normalmathunderbar   \underbar
%aliased\let\normalmathoverstrike \overstrike
%aliased\let\normalmathunderstrike\understrike

\definebar[\v!overbar]   [\c!method=1,\c!dy=0.4,\c!offset=1.8,\c!continue=\v!yes]
\definebar[\v!underbar]  [\c!method=1,\c!dy=-0.4,\c!offset=-0.3,\c!continue=\v!yes]
\definebar[\v!overstrike][\c!method=0,\c!dy=0.4,\c!offset=0.5,\c!continue=\v!yes]

\definebar
  [\v!understrike]
  [\c!method=0,
   \c!offset=1.375,
   \c!rulethickness=2.5,
   \c!continue=\v!yes,
   \c!order=\v!background,
   \c!color=lightgray]

\definebar[\v!overbars]    [\v!overbar]    [\c!continue=\v!no]
\definebar[\v!underbars]   [\v!underbar]   [\c!continue=\v!no]
\definebar[\v!overstrikes] [\v!overstrike] [\c!continue=\v!no]
\definebar[\v!understrikes][\v!understrike][\c!continue=\v!no]

\definebar
  [\v!hiddenbar]
  [\v!underbar]
  [\c!continue=\v!yes,
   \c!empty=\v!yes,
   \c!left=\zwj,
   \c!right=\zwj]

\definebar
  [\v!outline]
  [\c!method=2,
   \c!offset=\zeropoint,
   \c!rulethickness=0.25,
   \c!continue=\v!yes,
   \c!order=\v!background,
   \c!color=lightgray]

\definebar
  [\v!outlined]
  [\v!outline]
  [\c!height=\strutht,
   \c!depth=\strutdp]

%D \starttyping
%D \definebar[mybar][backgroundbar][offset=.25ex,color=red]
%D
%D \startformula
%D             a      \alignhere= b + c \breakhere
%D     \mybar {d + e} \alignhere= f     \breakhere
%D             g      \alignhere= h + i
%D \stopformula
%D \stoptyping

\definebar
  [\v!backgroundbar] % joke
  [\c!method=3,
   \c!offset=0,
   \c!rulethickness=0.25,
   \c!continue=\v!yes,
   \c!order=\v!background,
   \c!color=lightgray]

\definebar
  [mathbackground]
  [backgroundbar]
  [\c!continue=\v!always,
   \c!max=1,
   \c!height=\strutht,
   \c!depth=\strutdp]

% \setupbar[\v!overstrike][continue=all]

% we want these always so ...

\ifdefined\normalmathunderbar
    \enforced\permanent\expandafter\let\expandafter\normaltextunderbar\csname\v!underbar\endcsname
    \enforced\permanent\protected\def\underbar{\mathortext\normalmathunderbar\normaltextunderbar}
\else
    \enforced\permanent\expandafter\let\expandafter\underbar\csname\v!underbar\endcsname
\fi

\ifdefined\normalmathoverbar
    \enforced\permanent\expandafter\let\expandafter\normaltextoverbar\csname\v!overbar\endcsname
    \enforced\permanent\protected\def\overbar{\mathortext\normalmathoverbar\normaltextoverbar}
\else
    \enforced\permanent\expandafter\let\expandafter\overbar\csname\v!overbar\endcsname
\fi

% \ifdefined\normalmathunderstrike
%     \enforced\permanent\expandafter\let\expandafter\normaltextunderstrike\csname\v!understrike\endcsname
%     \enforced\permanent\protected\def\understrike{\mathortext\normalmathunderstrike\normaltextunderstrike}
% \else
%     \enforced\permanent\expandafter\let\expandafter\understrike\csname\v!understrike\endcsname
% \fi
%
% \ifdefined\normalmathoverstrike
%     \enforced\permanent\expandafter\let\expandafter\normaltextoverstrike\csname\v!overstrike\endcsname
%     \enforced\permanent\protected\def\overstrike{\mathortext\normalmathoverstrike \normaltextoverstrike}
% \else
%     \enforced\permanent\expandafter\let\expandafter\overstrike\csname\v!overstrike\endcsname
% \fi

\enforced\permanent\expandafter\let\expandafter\overstrikes\csname\v!overstrikes\endcsname
\enforced\permanent\expandafter\let\expandafter\underbars  \csname\v!underbars  \endcsname
\enforced\permanent\expandafter\let\expandafter\overbars   \csname\v!overbars   \endcsname

\enforced\permanent\protected\def\setupunderbar[#1]% too incompatible for the moment
  {}

\popoverloadmode

%D An experimental new feature:
%D
%D \startbuffer
%D test {\red\underrandoms{test me}} and \underrandom{test} or \underrandom{grep} \blank
%D test {\red\underdashes {test me}} and \underdash  {test} or \underdash  {grep} \blank
%D test {\red\underdots   {test me}} and \underdot   {test} or \underdot   {grep} \blank
%D \stopbuffer
%D
%D \typebuffer \getbuffer

\startuseMPgraphic{rules:under:random}
    draw
        ((0,RuleDepth) ... (RuleWidth,RuleDepth)) randomized (4*RuleThickness)
        shifted (0,RuleFactor*RuleOffset)
        withpen pencircle scaled RuleThickness
        withcolor RuleColor ;
    setbounds currentpicture to unitsquare xysized(RuleWidth,RuleHeight) ;
\stopuseMPgraphic

\startuseMPgraphic{rules:under:dash}
    draw
        ((0,RuleDepth) -- (RuleWidth,RuleDepth))
        shifted (0,RuleFactor*RuleOffset)
        dashed dashpattern(on RuleFactor/2 off RuleFactor/2)
        withpen pencircle scaled RuleThickness
        withcolor RuleColor ;
    setbounds currentpicture to unitsquare xysized(RuleWidth,RuleHeight) ;
\stopuseMPgraphic

\startuseMPgraphic{rules:under:dots}
    path p ; p := (0,RuleDepth) -- (RuleWidth,RuleDepth) ;
    numeric l ; l := arclength(p);
    l := l mod RuleThickness/4;
    draw
        p
        shifted (l,RuleFactor*RuleOffset)
        dashed dashpattern(off 2RuleThickness+l on 0 off 2RuleThickness)
        withpen pencircle scaled 2RuleThickness
        withcolor RuleColor ;
    setbounds currentpicture to unitsquare xysized(RuleWidth,RuleHeight) ;
\stopuseMPgraphic

\definebar
  [undergraphic]
  [\c!mp=rules:under:dash,
   \c!level=\v!auto,
   \c!offset=-.2,
   \c!dy=.4,
   \c!continue=\v!yes,
   \c!order=\v!background]

\definebar[underrandom] [undergraphic][\c!mp=rules:under:random,]
\definebar[underrandoms][underrandom] [\c!continue=\v!no]

\definebar[underdash]   [undergraphic][\c!mp=rules:under:dash]
\definebar[underdashes] [underdash]   [\c!continue=\v!no]

\definebar[underdot]    [undergraphic][\c!mp=rules:under:dots]
\definebar[underdots]   [underdot]    [\c!continue=\v!no]

%D This will move: (a bit duplicated)

\installcorenamespace{shift}

\installcommandhandler \??shift {shift} \??shift

\let\setupshifts\setupshift

\appendtoks
    \frozen\protected\instance\edefcsname\currentshift\endcsname{\node_shifts_direct{\currentshift}}%
\to \everydefineshift

\protected\def\node_shifts_set#1% todo: check parent ! todo: move attr etc to lua
  {\ifhastok={#1}%
     \setupcurrentshift[#1]%
   \else
     \cdef\currentshift{#1}%
   \fi
   \useshiftstyleandcolor\c!style\c!color
   \dosetupisolatedalign{\shiftparameter\c!align}% a weird feature that i probably needed once
   \clf_setshift
       continue {\shiftparameter\c!continue}%
       unit     {\shiftparameter\c!unit}%
       method    \shiftparameter\c!method
       dy        \shiftparameter\c!dy % number
   \relax}

\permanent\protected\def\startshift[#1]%
  {\begingroup
   \node_shifts_set{#1}%
   \ignorespaces}

\permanent\protected\def\stopshift
  {\removeunwantedspaces
   \endgroup}

\protected\def\node_shifts_direct#1%
  {\groupedcommand
     {\begingroup\dostartisolation\begingroup\node_shifts_set{#1}\ignorespaces}
     {\removeunwantedspaces\endgroup\dostopisolation\endgroup}}

\setupshifts
  [\c!method=0,
   \c!continue=\v!no,
   \c!dy=0,
   \c!unit=ex,
   \c!align=,
   \c!style=,
   \c!color=]

\defineshift [\v!shiftup]   [\c!method=0,\c!dy=-1,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=]
\defineshift [\v!shiftdown] [\c!method=1,\c!dy=.3,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=]

% we want these always so ...

\expandafter\let\expandafter\shiftup  \csname\v!shiftup  \endcsname
\expandafter\let\expandafter\shiftdown\csname\v!shiftdown\endcsname

% This is a weird helper.. these might go away:

\permanent\protected\def\dostartisolation{\signalcharacter}
\permanent\protected\def\dostopisolation {\signalcharacter}
\permanent\protected\def\doisolator      {\signalcharacter}

\permanent\protected\def\dosetupisolatedalign#1%
  {\doisolator
   \setupalign[#1]\relax}

\permanent\protected\def\doisolatedgroupedalign#1#2%
  {\groupedcommand
     {\begingroup\dostartisolation\begingroup#1}
     {#2\endgroup\dostopisolation\endgroup}}

%D More rules.

% The following code rocks and was written with the Toto Live in Poland bluray
% in loop mode on my 5.1 surround development setup (the Toto lineup with Simon
% Phillips on drums). The Amsterdam concert is equally energizing.

\installcorenamespace{linefiller}

\installcommandhandler \??linefiller {linefiller} \??linefiller

\definesystemattribute[linefiller][public]

\aliased\let\setuplinefillers\setuplinefiller

\protected\def\node_linefiller_set#1% todo: check parent ! todo: move attr etc to lua
  {\cdef\currentlinefiller{#1}%
   \edef\p_node_color{\linefillerparameter\c!color}%
   \clf_setlinefiller
      %method         \linefillerparameter\c!method
       location      {\linefillerparameter\c!location}%
       scope         {\linefillerparameter\c!scope}%
       mp            {\includeMPgraphic{\linefillerparameter\c!mp}}%
       ma             \c_attr_colormodel
       ca             \rawcolorattribute\p_node_color
       ta             \rawtransparencyattribute\p_node_color
       height         {\linefillerparameter\c!height}%
       depth          {\linefillerparameter\c!depth}%
       distance       {\linefillerparameter\c!distance}%
       threshold      {\linefillerparameter\c!threshold}%
       rulethickness  {\linefillerparameter\c!rulethickness}%
   \relax}

\permanent\tolerant\protected\def\startlinefiller[#1]#*[#S#2]%
  {\begingroup
   \par
   \cdef\currentlinefiller{#1}%
   \ifparameter#2\or
     % we need to update settings
     \setuplinefiller[#1][#2]% no \setupcurrentlinefiller as we need to update settings
   \fi
   \node_linefiller_set{#1}%
   \linefillerparameter\c!before
   \usealignparameter\linefillerparameter
   \uselinefillerstyleandcolor\c!textstyle\c!textcolor} % bars have foregroundcolor

\permanent\protected\def\stoplinefiller
  {\par
   \linefillerparameter\c!after
   \endgroup}

\permanent\protected\def\setlinefiller[#1]%
  {\node_linefiller_set{#1}}

\setuplinefillers
  [%c!method=0,
   %c!mp=,
   \c!location=\v!both,
   \c!scope=\v!local,
   \c!distance=\zeropoint,
   \c!threshold=\zeropoint,
   \c!rulethickness=\linewidth,
   \c!height=\linewidth,
   \c!depth=\zeropoint,
  %\c!textcolor=,
  %\c!textstyle=,
  %\c!align=,
  %\c!before=,
  %\c!after=,
   \c!color=]

\definelinefiller
  [filler]
  [\c!height=.75\exheight,
  %\c!mp=rules:filler:demo,
  %\c!threshold=.25\emwidth,
   \c!distance=.25\emwidth,
   \c!rulethickness=.25\exheight]

%D Bonus:
%D
%D \starttyping
%D \startuseMPgraphic{foo}
%D     fill unitsquare
%D         xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8)
%D         shifted  (-ExHeight/8,ExHeight/16)
%D         withcolor RuleColor ;
%D \stopuseMPgraphic
%D
%D \definelinefiller[foo][mp=foo,color=darkred]
%D
%D \linefillerhbox[foo]{OEPS}
%D \stoptyping

\protected\def\node_backgrounds_filler_box#1#2[#3]%
  {\bgroup
   \clf_enablebackgroundboxes
   \dowithnextbox{%
     \node_linefiller_set{#3}% already sets the attribute
     #1%
        attr \backgroundattribute \plusone
       {\box\nextbox}%
     \egroup}%
   #2}

\permanent\protected\def\linefillerhbox{\node_backgrounds_filler_box\hpack\hbox}
\permanent\protected\def\linefillervbox{\node_backgrounds_filler_box\vpack\vbox}
\permanent\protected\def\linefillervtop{\node_backgrounds_filler_box\tpack\vtop}

%D Bonus:

% \autorule : defined at the lua end

%D A joke:

%D This will move: (a bit duplicated)

\installcorenamespace{shadow}

\installcommandhandler \??shadow {shadow} \??shadow

\let\setupshadows\setupshadow

\appendtoks
    \frozen\protected\instance\edefcsname\currentshadow\endcsname{\node_shadows_direct{\currentshadow}}%
\to \everydefineshadow

\protected\def\node_shadows_set#1% todo: check parent ! todo: move attr etc to lua
  {\ifhastok={#1}%
     \setupcurrentshadow[#1]%
   \else
     \cdef\currentshadow{#1}%
   \fi
   \useshadowstyleandcolor\c!style\c!color
   \edef\p_node_color{\shadowparameter\c!contrastcolor}% todo
   \clf_setshadow
       continue {\shadowparameter\c!continue}%
       unit     {\shadowparameter\c!unit}%
       weight   {\shadowparameter\c!weight}%
       method   \shadowparameter\c!method
       dx       \shadowparameter\c!dx\relaxedspace % number
       dy       \shadowparameter\c!dy\relaxedspace % number
       %
       ma       \c_attr_colormodel
       ca       \rawcolorattribute\p_node_color
       ta       \rawtransparencyattribute\p_node_color
   \relax}

\permanent\protected\def\startshadow[#1]%
  {\begingroup
   \node_shadows_set{#1}%
   \ignorespaces}

\permanent\protected\def\stopshadow
  {\removeunwantedspaces
   \endgroup}

\protected\def\node_shadows_direct#1%
  {\groupedcommand
     {\begingroup\dostartisolation\begingroup\node_shadows_set{#1}\ignorespaces}
     {\removeunwantedspaces\endgroup\dostopisolation\endgroup}}

\setupshadows
  [\c!method=0,
   \c!continue=\v!yes,
   \c!dx=.04,
   \c!dy=-.04,
   \c!unit=ex,
   \c!style=,
   \c!color=,
   \c!weight=100,
   \c!contrastcolor=middlegray] % otherwise we don't see anything, users should set it anyway

\defineshadow [shadowed]

% \startTEXpage[offset=1ts]
%     \samplefile{tufte}\removeunwantedspaces\space
%     \startshadow[contrastcolor=red]\samplefile{tufte}\removeunwantedspaces\stopshadow\space
%     \samplefile{tufte}
% \stopTEXpage

%D Quick and dirty, but useful in math matrices:

\installcorenamespace{graphiclines}
\installcorenamespace{graphiccolor}

\newdimen\d_grph_line_width
\newdimen\d_grph_line_offset
\newcount\c_grph_line_action

\defcsname\??graphiclines s\endcsname{\strut}
\defcsname\??graphiclines m\endcsname{\setstrut\strutht.85\strutht\strutdp.85\strutdp}
\defcsname\??graphiclines a\endcsname{\d_grph_line_offset 1ma}
\defcsname\??graphiclines x\endcsname{\d_grph_line_offset 1ex}
\defcsname\??graphiclines h\endcsname{\d_grph_line_offset \strutht}
\defcsname\??graphiclines d\endcsname{\d_grph_line_offset-\strutdp}
\defcsname\??graphiclines o\endcsname{\d_grph_line_offset \zeropoint}
\defcsname\??graphiclines e\endcsname{\c_grph_line_action \plusone}  % end
\defcsname\??graphiclines c\endcsname{\c_grph_line_action \plustwo}  % close + end
\defcsname\??graphiclines r\endcsname{\c_grph_line_action \plusthree}% reset
\defcsname\??graphiclines t\endcsname{\d_grph_line_offset \strutht}
\defcsname\??graphiclines b\endcsname{\d_grph_line_offset-\strutdp\c_grph_line_action\plusone}
\defcsname\??graphiclines T\endcsname{\d_grph_line_offset .75\strutht}
\defcsname\??graphiclines B\endcsname{\d_grph_line_offset-.25\strutdp\c_grph_line_action\plusone}

\def\grph_line_inject_step#1%
  {\ifcsname\??graphiclines#1\endcsname
     \lastnamedcs
   \orelse\ifchkdim#1\or
      \d_grph_line_width#1\relax
 % \orelse\ifchknum#1\or
   \orelse\ifchkdim#1pt\or
      \d_grph_line_width#1\d_grph_line_width % \dimexpr\mathmatrixparameter\c!rulethickness\relax
   \else
     \edef\m_rule_color{#1}%
   \fi}

% \setupmathmatrix[rulethickness=3pt]

\tolerant\permanent\protected\def\grph_line_inject
  {\dontleavehmode
   \iftrialtypesetting
     \expandafter\gobbletwooptionals
   \else
     \expandafter\grph_line_inject_yes
   \fi}

\def\grph_line_inject_yes[#1]#*[#2]%
  {\begingroup
   \edef\m_rule_color{\mathmatrixparameter\c!rulecolor}%
   \d_grph_line_width{\mathmatrixparameter\c!rulethickness}%
   \d_grph_line_offset\zeropoint
   \c_grph_line_action\zerocount
   \processcommacommand[#2]\grph_line_inject_step % use fast one
   \ifcase\c_grph_line_action
     \ifcstok{\begincsname\??graphiccolor#1\endcsname}\empty
        \gletcsname\??graphiccolor#1\endcsname\m_rule_color
     \fi
   \orelse\ifempty{#1}%
     % ignore
   \else
     % we have to color the last node
     \colo_helpers_direct_activate{\begincsname\??graphiccolor#1\endcsname}%
     \gletcsname\??graphiccolor#1\endcsname\empty
   \fi
   \hpack \ifzeropt\d_grph_line_offset\else\s!yoffset\d_grph_line_offset\fi
     {%\signalcharacter
      \clf_linesegment
        {#1}%
        \c_math_eqalign_row
        \c_math_eqalign_column
        \c_grph_line_action
        \d_grph_line_width}%
   \endgroup}

\let\graphicline\grph_line_inject

\protect \endinput