%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

\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 next macros are derived from the \PLAIN\ \TEX\ one, but also supports
%D nesting. The \type{$} keeps us in horizontal mode and at the same time
%D applies grouping.
%D
%D \showsetup{underbar}
%D \showsetup{underbars}
%D \showsetup{overbar}
%D \showsetup{overbars}
%D \showsetup{overstrike}
%D \showsetup{overstrikes}
%D
%D \showsetup{setupunderbar}
%D
%D Nested bars can be configured by appending \type {:<index>} to the category.
%D Normally units in combination with a unitless thickness specification but
%D there units can be used too.
%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]

\registerctxluafile{node-rul}{1.001}

\installcorenamespace{bar}
\installcorenamespace{barindex}
\installcorenamespace{barattribute}
\installcorenamespace{barstack}

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

\newtoks\t_node_rules_checklist

\let\c_node_rules_index\relax % temporary synonym
\let\p_node_rules_color\empty

\let\setupbars\setupbar

\appendtoks
    \ifsecondargument
        \node_rules_define
    \else
        \the\t_node_rules_checklist
    \fi
\to \everysetupbar

\appendtoks
    \ifcsname\??barindex\currentbar\endcsname
        \csname\??barindex\currentbar\endcsname\zerocount
    \else
        \expandafter\newcount\csname\??barindex\currentbar\endcsname
    \fi
    \normalexpanded{\t_node_rules_checklist{\node_rules_redefine{\currentbar}\the\t_node_rules_checklist}}%
    \node_rules_define
    \setuevalue\currentbar{\node_rules_direct{\currentbar}}%
\to \everydefinebar

\unexpanded\def\node_rules_define
  {\edef\p_node_rules_color{\barparameter\c!color}%
   \setevalue{\??barattribute\currentbar}{\number\ctxlua{nodes.rules.define {
        method        = \barparameter\c!method,
        offset        = \barparameter\c!offset,
        continue      = "\barparameter\c!continue",
        dy            = \barparameter\c!dy,
        rulethickness = "\barparameter\c!rulethickness",
        unit          = "\barparameter\c!unit",
        order         = "\barparameter\c!order",
        max           = \barparameter\c!max,
        ma            = \thecolormodelattribute,
        ca            = \thecolorattribute\p_node_rules_color,
        ta            = \thetransparencyattribute\p_node_rules_color
      }}}}

\unexpanded\def\node_rules_redefine#1%
  {\def\currentbar{#1}\node_rules_define}

\unexpanded\def\node_rules_direct#1%
  {\groupedcommand{\node_rules_set{#1}}\relax}

\def\node_rules_set
  {\ctxlua{nodes.rules.enable()}% will be moved to lua
   \glet\node_rules_set\node_rules_set_indeed
   \node_rules_set}

\def\node_rules_set_indeed#1% maybe reverse the 1000 (also maybe use more attributes instead of settings)
  {\edef\currentbar{#1}%
   \expandafter\let\expandafter\c_node_rules_index\csname\??barindex#1\endcsname
   \advance\c_node_rules_index\plusone
   \usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor
   \attribute\ruledattribute\numexpr
      \plusthousand*\c_node_rules_index
     +\csname\??barattribute#1\ifcsname\??bar#1:\number\c_node_rules_index\s!parent\endcsname:\number\c_node_rules_index\fi\endcsname
   \relax}

\unexpanded\def\startbar[#1]%
  {\begingroup
   \node_rules_set{#1}}

\unexpanded\def\stopbar
  {\endgroup}

% ungrouped

\newcount\c_node_rules_nesting % todo: same as colors

\unexpanded\def\pushbar[#1]%
  {\global\advance\c_node_rules_nesting\plusone
   \expandafter\edef\csname\??barstack\number\c_node_rules_nesting\endcsname{\attribute\ruledattribute\the\attribute\ruledattribute}%
   \node_rules_set{#1}}

\unexpanded\def\popbar
  {\csname\??barstack\number\c_node_rules_nesting\endcsname
   \global\advance\c_node_rules_nesting\minusone}

\setupbars
  [\c!method=0,                 % new: 0=center nested, 1=stack nested
   \c!continue=\v!no,
   \c!offset=0,                 % upwards, replaces: topoffset bottomoffset
   \c!dy=0,
   \c!max=3,
   \c!style=,
   \c!rulethickness=.1,
   \c!order=\v!foreground,
   \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]

\definebar[\v!overstrike][\c!method=0,\c!dy=0.4,\c!offset=0.5,\c!continue=\v!yes]
\definebar[\v!underbar]  [\c!method=1,\c!dy=-0.4,\c!offset=-0.3,\c!continue=\v!yes]
\definebar[\v!overbar]   [\c!method=1,\c!dy=0.4,\c!offset=1.8,\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!overstrikes] [\v!overstrike] [\c!continue=\v!no]
\definebar[\v!underbars]   [\v!underbar]   [\c!continue=\v!no]
\definebar[\v!overbars]    [\v!overbar]    [\c!continue=\v!no]
\definebar[\v!understrikes][\v!understrike][\c!continue=\v!no]

% we want these always so ...

\expandafter\let\expandafter\overstrike \csname\v!overstrike \endcsname
\expandafter\let\expandafter\underbar   \csname\v!underbar   \endcsname
\expandafter\let\expandafter\overbar    \csname\v!overbar    \endcsname
\expandafter\let\expandafter\overstrikes\csname\v!overstrikes\endcsname
\expandafter\let\expandafter\underbars  \csname\v!underbars  \endcsname
\expandafter\let\expandafter\overbars   \csname\v!overbars   \endcsname

\unexpanded\def\setupunderbar[#1]% too incompatible for the moment
  {}

%D This will move: (a bit duplicated)

\installcorenamespace{shift}
\installcorenamespace{shiftindex}
\installcorenamespace{shiftattribute}

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

\newtoks\t_node_shifts_checklist

\let\c_node_shifts_index\relax % temporary synonym

\let\setupshifts\setupshift

\appendtoks
    \ifsecondargument
        \node_shifts_define
    \else
        \the\t_node_shifts_checklist
    \fi
\to \everysetupshift

\appendtoks
    \ifcsname\??shiftindex\currentshift\endcsname
        \csname\??shiftindex\currentshift\endcsname\zerocount
    \else
        \expandafter\newcount\csname\??shiftindex\currentshift\endcsname
    \fi
    \normalexpanded{\t_node_shifts_checklist{\node_shifts_redefine{\currentshift}\the\t_node_shifts_checklist}}%
    \node_shifts_define
    \setuevalue\currentshift{\node_shifts_direct{\currentshift}}%
\to \everydefineshift

\unexpanded\def\node_shifts_define
  {\setevalue{\??shiftattribute\currentshift}{\number\ctxlua{nodes.shifts.define {
        method   = \shiftparameter\c!method,
        continue = "\shiftparameter\c!continue",
        dy       = \shiftparameter\c!dy,
        unit     = "\shiftparameter\c!unit",
   }}}}

\unexpanded\def\node_shifts_redefine#1%
  {\def\currentshift{#1}\node_shifts_define}

\unexpanded\def\node_shifts_set
  {\ctxlua{nodes.shifts.enable()}%
   \glet\node_shifts_set\node_shifts_set_indeed
   \node_shifts_set}

% \unexpanded\def\node_shifts_direct#1%
%   {\doisolatedgroupedalign{\node_shifts_set{#1}}\donothing}

\unexpanded\def\node_shifts_direct#1%
  {\groupedcommand
     {\begingroup\dostartisolation\begingroup\node_shifts_set{#1}}
     {\endgroup\dostopisolation\endgroup}}

\def\node_shifts_set_indeed#1% todo: check parent !
  {\def\currentshift{#1}%
   \expandafter\let\expandafter\c_node_shifts_index\csname\??shiftindex#1\endcsname
   \advance\c_node_shifts_index\plusone
   \attribute\shiftedattribute\numexpr
      \plusthousand*\c_node_shifts_index
     +\csname\??shiftattribute#1\ifcsname\??shift#1:\number\c_node_shifts_index\s!parent\endcsname:\number\c_node_shifts_index\fi\endcsname
   \relax
   \useshiftstyleandcolor\c!style\c!color
   \dosetupisolatedalign{\shiftparameter\c!align}}

\unexpanded\def\startshift[#1]%
  {\begingroup
   \node_shifts_set{#1}}

\unexpanded\def\stopshift
  {\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:

\unexpanded\def\dostartisolation{\signalcharacter}
\unexpanded\def\dostopisolation {\signalcharacter}
\unexpanded\def\doisolator      {\signalcharacter}

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

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

\protect \endinput
