%D \module
%D   [       file=math-stc,
%D        version=2012.12.29,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Stackers,
%D        comment=This replaces math-arr and friends,
%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.

\writestatus{loading}{ConTeXt Math Macros / Stackers}

\unprotect

%D WARNING: If the code here changes, the export needs to be checked! Stackers are rather
%D special because the order in mathml matters, so we flush in [base under over] order. We
%D also do some analysis at the \TEX\ end (passing the right variant). It's easy in the
%D export to deal with it but in the pdf stream less trivial as we don't actually analyze
%D there.

%D At some point the \MKII\ arrow mechanism has been converted to \MKIV, but we kept
%D most of the logic. We now have a more generic variant dealing with extensibles.
%D There are a few demands than we need to meet:
%D
%D \startitemize
%D \startitem The width of the extensible need to adapt itself automatically. \stopitem
%D \startitem We need to be able to control horizontal and vertical offsets. \stopitem
%D \startitem We best have a math as well as a text variant (which is handy for chemistry). \stopitem
%D \startitem For historic reasons we need to deal with optional arguments in a special (reverse) way. \stopitem
%D \startitem We need alternatives for extensibles on top, in the middle and at the bottom. \stopitem
%D \stopitemize
%D
%D After I had experimented a bit with virtual characters for two headed arrows I
%D discussed the issue with the Gyre folks and we came to the conclusion that it
%D made sense to have real extensibles instead of constructing them out of snippets.
%D After all, \OPENTYPE\ math provides for it. So, in December 2013 beta versions of
%D Latin Modern and Gyre fonts came available that had these! Because we still want
%D to support the traditional Latin Modern Virtual math font those were extended
%D with a couple of virtual extensibles as well.
%D
%D {\em For the moment we still have some mess here: we can deal with known dimensions, but
%D fillers (like \type {\rightarrowfil} don't work with \OPENTYPE\ extensibles yet
%D because there is no way to let them stretch like leaders. At some point \LUATEX\
%D might provide a auto||fit||to||encapsulated||box and if not I will cook up a \LUA\
%D based variant.}
%D
%D We could mess with something like \type {$mid\limits^{top}_{bottom}$} but we like
%D a bit more control. At some point we need to add some hacks to get exports
%D working well.
%D
%D In the end we have a more flexible mechanism which also handles text variants.

%D When wrapping up some math developments I decided to add mp support here
%D as well. A nice evening job with Joe Bonamassa performing live on the big
%D screen (real nice bluray's). See meta-imp-mat.mkiv for examples.

% possible improvements:
%
% - we could skip the left/right offsets when offset=normal, this saves some access time
%   at the lua end and some checking: use \mathhorizontalcode or \mathextensiblecode
%   but in practice arrows etc are not used that often

\installcorenamespace {mathextensiblefallbacks}

% currently no italic correction ... problem is that we don't know yet if we have an italic
% below so we we need to postpone

\def\math_stackers_fallback
  {\hbox to \scratchwidth{\csname\??mathextensiblefallbacks\ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname\number\scratchunicode\fi\endcsname}}
 %{\csname\??mathextensiblefallbacks\ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname\number\scratchunicode\fi\endcsname }

% \def\math_stackers_regular
%   {\mathstylehbox{\Umathaccent\fam\zerocount\scratchunicode{\hskip\scratchwidth}}}

\def\math_stackers_regular
  {\mathstylehbox{\usemathstackerscolorparameter\c!color
                  \Umathaccent\fam\zerocount\scratchunicode{\hskip\scratchwidth}}}

\def\math_stackers_stretch % we don't have that one yet
  {\mathstylehbox{\usemathstackerscolorparameter\c!color
                  \Umathaccent\fam\zerocount\scratchunicode{\hskip\hsize}}}

% these delimiters are a unuseable as they don't center for small arguments:
%
% $\Umathaccent   0 0 "2190{x}$ \par $\Umathaccent   0 0 "27F8{x}$\par
% $\Udelimiterunder 0 "2190{x}$ \par $\Udelimiterunder 0 "27F8{x}$\par

\setvalue{\??mathextensiblefallbacks}{\hbox{\vrule\!!width\scratchwidth\!!height.1\exheight\!!depth\zeropoint}}

% \def\math_stackers_with_fallback#codepoint%
%   {\begingroup
%    \scratchunicode#codepoint\relax
%    \ifcase\mathextensiblecode\fam\scratchunicode\relax
%      \math_stackers_fallback
%    \else
%      \math_stackers_stretch
%    \fi
%    \endgroup}

%D We don't really need this because we can assume that fonts have the right
%D extensibles. If needed I will make a general virtual extender for \OPENTYPE\
%D fonts.
%D
%D Because we have quite some control over positioning, we have somewhat extensive
%D tracing built in.

\let\math_stackers_top   \relax
\let\math_stackers_middle\relax
\let\math_stackers_bottom\relax
\let\math_stackers_skip  \hskip

\installtextracker
  {math.stackers.texts}
  {\let\math_stackers_top   \filledhboxb
   \let\math_stackers_middle\filledhboxr
   \let\math_stackers_bottom\filledhboxg
   \let\math_stackers_skip  \math_stackers_skip_indeed}
  {\let\math_stackers_top   \relax
   \let\math_stackers_middle\relax
   \let\math_stackers_bottom\relax
   \let\math_stackers_skip  \hskip}

\def\math_stackers_skip_indeed#amount%
  {\filledhboxk{\unsetteststrut\strut\hskip#amount}} % \dontshowstruts

\let\math_stackers_start_tagged_mid\relax
\let\math_stackers_start_tagged_top\relax
\let\math_stackers_start_tagged_bot\relax
\let\math_stackers_stop_tagged     \relax

\appendtoks
    \def\math_stackers_start_tagged_mid{\dostarttagged\t!mathstackermid\empty\hbox\bgroup}%
    \def\math_stackers_start_tagged_top{\dostarttagged\t!mathstackertop\empty\hbox\bgroup}%
    \def\math_stackers_start_tagged_bot{\dostarttagged\t!mathstackerbot\empty\hbox\bgroup}%
    \def\math_stackers_stop_tagged     {\egroup\dostoptagged}%
\to \everysetuptagging

%D We define a full featured command handler.

\installcorenamespace {mathstackers}

\installcommandhandler \??mathstackers {mathstackers} \??mathstackers

\setupmathstackers
  [%c!alternative=\v!text,    % text | mathematics
   \c!left=,
   \c!right=,
   \c!mathclass=\s!rel,
   \c!alternative=\v!normal,
   \c!mp=math:stacker:\number\scratchunicode,
   \c!mpheight=\exheight,
   \c!mpdepth=\exheight,
   \c!mpoffset=.25\exheight,
   \c!voffset=.25\exheight,
   \c!hoffset=.5\emwidth,
   \c!distance=\mathstackersparameter\c!voffset, % distance between symbol and base (can be different from voffset)
   \c!minheight=\exheight,
   \c!mindepth=\zeropoint,
   \c!minwidth=.5\emwidth,
   \c!order=\v!normal,
   \c!strut=,
   \c!color=, % todo: when I need it
   \c!topcommand=,
   \c!middlecommand=,
   \c!bottomcommand=,
   \c!offset=\v!normal,       % normal | min | max
   \c!location=\v!top]        % none | normal | small | medium | big

%D We assume that the middle characters (that can be an extensible) to sit on
%D top of the baseline by default.

\installcorenamespace {mathstackerslocation}
\installcorenamespace {mathstackersalternative}

\letvalue{\??mathstackerslocation\v!top    }\plusone   % on top of baseline
\letvalue{\??mathstackerslocation\v!high   }\plustwo   % 25 % down
\letvalue{\??mathstackerslocation\v!middle }\plusthree % centered
\letvalue{\??mathstackerslocation\v!low    }\plusfour  % 75 % down
\letvalue{\??mathstackerslocation\v!bottom }\plusfive  % below baseline
\letvalue{\??mathstackerslocation          }\zerocount

%D First we implement the helper that deals with an extensible in the middle and
%D top and|/|or bottom texts:

\let\m_math_stackers_text_top   \empty
\let\m_math_stackers_text_bottom\empty
\let\m_math_stackers_text_middle\empty

\def\math_stackers_flushtext#command#text%
  {\ifdim\scratchleftoffset >\zeropoint\math_stackers_skip\scratchleftoffset \fi
   \ifx\p_strut\v!no \else
     \strut
   \fi
   \mathstackersparameter#command#text%
   \ifdim\scratchrightoffset>\zeropoint\math_stackers_skip\scratchrightoffset\fi}

\def\math_stackers_toptext   {\math_stackers_flushtext\c!topcommand   \m_math_stackers_text_top   }
\def\math_stackers_bottomtext{\math_stackers_flushtext\c!bottomcommand\m_math_stackers_text_bottom}
\def\math_stackers_middletext{\math_stackers_flushtext\c!middlecommand\m_math_stackers_text_middle}

\def\math_stackers_content
  {\ifcase\scratchcounter
     \math_stackers_fallback
   \or % left
     \math_stackers_regular
   \or % right
     \math_stackers_regular
   \or % horizontal
     \math_stackers_regular
   \else
     \math_stackers_fallback
   \fi}

% no checking, we assume sane use

\letvalue{\??mathstackersalternative\v!normal }\math_stackers_content
\letvalue{\??mathstackersalternative\v!default}\math_stackers_content

\setvalue{\??mathstackersalternative\v!mp}%
  {\hbox\bgroup %  todo: add code key + tag
   \d_overlay_width    \scratchwidth
   \d_overlay_height   \dimexpr\mathstackersparameter\c!mpheight
   \d_overlay_depth    \dimexpr\mathstackersparameter\c!mpdepth
   \d_overlay_offset   \dimexpr\mathstackersparameter\c!mpoffset
   \d_overlay_linewidth\linewidth
   \edef\overlaylinecolor{\mathstackersparameter\c!color}%
   \edef\p_mp{\mathstackersparameter\c!mp}%
   \uniqueMPgraphic{\p_mp}%
   \egroup}

\def\math_stackers_check_unicode#codepoint%
  {\scratchunicode#codepoint\relax
   \scratchhoffset\mathstackersparameter\c!hoffset\relax
   \scratchvoffset\mathstackersparameter\c!voffset\relax
   \scratchcounter\mathhorizontalcode\fam\scratchunicode\relax % also sets \leftscratchoffset and \rightscratchoffset
   \ifx\p_offset\v!max
     % heads/tails + hoffset
   \else\ifx\p_offset\v!min
     % heads/tails - hoffset
     \advance\scratchleftoffset-\scratchhoffset
     \advance\scratchrightoffset-\scratchhoffset
   \else % \v!normal
     % hoffset
     \scratchleftoffset\zeropoint
     \scratchrightoffset\zeropoint
   \fi\fi
   \ifdim\scratchleftoffset<\zeropoint
     \scratchleftoffset\zeropoint
   \fi
   \ifdim\scratchrightoffset<\zeropoint
     \scratchrightoffset\zeropoint
   \fi}

\def\math_stackers_normalize_three
  {\scratchheight\ht\scratchboxthree
   \scratchdepth \dp\scratchboxthree
   \scratchtopoffset   \scratchheight
   \scratchbottomoffset\scratchdepth
   \scratchdimen\mathstackersparameter\c!minheight\relax
   \ifdim\scratchheight<\scratchdimen
     \scratchheight\scratchdimen
     \ht\scratchboxthree\scratchheight
   \fi
   \scratchdimen\mathstackersparameter\c!mindepth\relax
   \ifdim\scratchdepth<\scratchdimen
     \scratchdepth\scratchdimen
     \dp\scratchboxthree\scratchdepth
   \fi
   \advance\scratchtopoffset   -\scratchheight
   \advance\scratchbottomoffset-\scratchdepth
   \ifdim\scratchtopoffset<\zeropoint
     \scratchtopoffset\zeropoint
   \fi
   \ifdim\scratchbottomoffset<\zeropoint
     \scratchbottomoffset\zeropoint
   \fi}

\unexpanded\def\math_stackers_triplet#method#category#codepoint#toptext#bottomtext%
 %{\math_stackers_start_group{#category}%
  {\begingroup
   \edef\currentmathstackers{#category}%
   \mathstackersparameter\c!left\relax
   \dostarttagged\t!mathstacker\currentmathstackers
   \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
     {\edef\p_offset     {\mathstackersparameter\c!offset}%
      \edef\p_location   {\mathstackersparameter\c!location}%
      \edef\p_order      {\mathstackersparameter\c!order}%
      \edef\p_strut      {\mathstackersparameter\c!strut}%
      \edef\p_alternative{\mathstackersparameter\c!alternative}%
      \ifx\p_order\v!reverse
        \edef\m_math_stackers_text_top   {#bottomtext}%
        \edef\m_math_stackers_text_bottom{#toptext}%
      \else
        \edef\m_math_stackers_text_top   {#toptext}%
        \edef\m_math_stackers_text_bottom{#bottomtext}%
      \fi
      \scratchleftoffset \zeropoint
      \scratchrightoffset\zeropoint
      \ifcase#method\relax
        \math_stackers_check_unicode{#codepoint}%
      \else
        \edef\m_math_stackers_text_middle{#codepoint}%
      \fi
      \ifx\m_math_stackers_text_top\empty
        \setbox\scratchboxone\emptyhbox
      \else
        \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_toptext}%
      \fi
      \ifx\m_math_stackers_text_bottom\empty
        \setbox\scratchboxtwo\emptyhbox
      \else
        \setmathsmalltextbox\scratchboxtwo\hbox{\math_stackers_bottomtext}%
      \fi
      %
      \ifcase#method\relax
        \scratchwidth\wd
          \ifdim\wd\scratchboxone>\wd\scratchboxtwo
            \scratchboxone
          \else
            \scratchboxtwo
          \fi
        \relax
      \else
        \ifx\m_math_stackers_text_middle\empty
          \setbox\scratchboxthree\emptyhbox
        \else
          \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}%
        \fi
        \scratchwidth\wd
          \ifdim\wd\scratchboxone>\wd\scratchboxtwo
            \ifdim\wd\scratchboxone>\wd\scratchboxthree
              \scratchboxone
            \else
              \scratchboxthree
            \fi
          \else\ifdim\wd\scratchboxtwo>\wd\scratchboxthree
            \scratchboxtwo
          \else
            \scratchboxthree
          \fi\fi
        \relax
      \fi
      %
      \scratchdimen\mathstackersparameter\c!minwidth\relax
      \ifdim\scratchwidth<\scratchdimen
         \scratchwidth\scratchdimen
      \fi
      \advance\scratchwidth2\scratchhoffset
      %
      \ifcase#method\relax
        \dostarttagged\t!mathstackermid\empty
        \setbox\scratchboxthree\csname\??mathstackersalternative\p_alternative\endcsname
        \dostoptagged
      \fi
      %
      \ifdim\wd\scratchboxone<\scratchwidth
        \setbox\scratchboxone\hbox to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work
      \fi
      \ifdim\wd\scratchboxtwo<\scratchwidth
        \setbox\scratchboxtwo\hbox to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}%
      \fi
      \ifdim\wd\scratchboxthree<\scratchwidth
        \setbox\scratchboxthree\hbox to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
      \fi
      %
      \ifcsname\??mathstackerslocation\p_location\endcsname
        \ifcase\csname\??mathstackerslocation\p_location\endcsname\relax
          \scratchdistance\zeropoint
        \or
          % top
          \scratchdistance\zeropoint
        \or
          % high
          \scratchdistance.25\htdp\scratchboxthree
        \or
          % centered
          \scratchdistance.5\htdp\scratchboxthree
        \or
          % low
          \scratchdistance.75\htdp\scratchboxthree
        \or
          % bottom
          \scratchdistance\htdp\scratchboxthree
        \else
          \scratchdistance\zeropoint
        \fi
      \else
        \scratchdistance\p_location\htdp\scratchboxthree
      \fi
      %
      \ifzeropt\scratchdistance\else
        \setbox\scratchboxthree\hbox{\lower\scratchdistance\box\scratchboxthree}%
      \fi
      %
      \math_stackers_normalize_three
      % analysis
      \ifdim\htdp\scratchboxtwo>\zeropoint
        \ifdim\htdp\scratchboxone>\zeropoint
          \dosettagproperty\s!subtype\t!munderover
        \else
          \dosettagproperty\s!subtype\t!munder
        \fi
      \else
        \ifdim\htdp\scratchboxone>\zeropoint
          \dosettagproperty\s!subtype\t!mover
        \else
          % brrr
        \fi
      \fi
      % base
      \math_stackers_start_tagged_mid
        \math_stackers_middle\bgroup
          \box\scratchboxthree
        \egroup
      \math_stackers_stop_tagged
      % under
      \ifdim\htdp\scratchboxtwo>\zeropoint
        \math_stackers_start_tagged_bot
          \scratchoffset\scratchvoffset
          \kern-\scratchwidth
          \math_stackers_bottom\bgroup
            \lower\dimexpr\ht\scratchboxtwo+\scratchdepth+\scratchoffset+\scratchbottomoffset\relax
            \box\scratchboxtwo
          \egroup
        \math_stackers_stop_tagged
      \fi
      % over
      \ifdim\htdp\scratchboxone>\zeropoint
        \math_stackers_start_tagged_top
          \scratchoffset\scratchvoffset
          \kern-\scratchwidth
          \math_stackers_top\bgroup
            \raise\dimexpr\dp\scratchboxone+\scratchheight+\scratchoffset+\scratchtopoffset\relax
            \box\scratchboxone
          \egroup
        \math_stackers_stop_tagged
      \fi
      %
      }%
  \dostoptagged
  \mathstackersparameter\c!right\relax
  \endgroup}
 %\math_stackers_start_group}

\unexpanded\def\definemathextensible
  {\dotripleempty\math_stackers_define_normal}

\def\math_stackers_define_normal[#1][#2][#3]% category name unicode
  {\ifthirdargument
     \setuevalue{#2}{\math_stackers_auto_normal{#1}{\number#3}}%
   \else
     \setuevalue{#1}{\math_stackers_auto_normal\noexpand\currentmathstackers{\number#2}}%
   \fi}

\unexpanded\def\math_stackers_auto_normal#category#codepoint%
  {\begingroup
   \edef\currentmathstackers{#category}%
   \scratchcounter#codepoint\relax
   \dosingleempty\math_stackers_auto_normal_first}

\unexpanded\def\math_stackers_auto_normal_first[#category]% [#2]% #2 gobble spaces
  {\iffirstargument\edef\currentmathstackers{#category}\fi
   \permitspacesbetweengroups
   \dodoublegroupempty\math_stackers_auto_normal_second}

\def\math_stackers_auto_normal_second#toptext#bottomtext%
  {\math_stackers_triplet\zerocount\currentmathstackers\scratchcounter{#toptext}{#bottomtext}%
   \endgroup}

%D A few direct accessors:

\unexpanded\def\mathextensible{\begingroup\dosingleempty\math_stackers_handle_math}
\unexpanded\def\textextensible{\begingroup\dosingleempty\math_stackers_handle_text}

\unexpanded\def\math_stackers_handle_math[#category]%
  {\math_stackers_handle_extensible{\iffirstargument#category\else\v!mathematics\fi}} % will be defined later on

\unexpanded\def\math_stackers_handle_text[#category]%
  {\math_stackers_handle_extensible{\iffirstargument#category\else\v!text       \fi}} % will be defined later on

\def\math_stackers_handle_extensible#category#codepoint#toptext#bottomtext%
  {\math_stackers_triplet\zerocount{#category}{#codepoint}{#toptext}{#bottomtext}%
   \endgroup}

%D The next one deals with under and over extensibles (arrows mostly):

\installcorenamespace {mathclasses}

\letvalue{\??mathclasses    }\mathord
\letvalue{\??mathclasses rel}\mathrel
\letvalue{\??mathclasses ord}\mathord

\def\math_class_by_parameter#1%
  {\normalexpanded{\noexpand\math_class_by_parameter_indeed{#1\c!mathclass}}}

\def\math_class_by_parameter_indeed#1%
  {\csname\??mathclasses\ifcsname\??mathclasses#1\endcsname#1\fi\endcsname}

% 1 0 name n 0 | 0 1 name n 0 | 1 1 name n n

\unexpanded\def\math_stackers_start_group#category%
  {\begingroup
   \edef\currentmathstackers{#category}%
   \edef\p_limits{\mathstackersparameter\c!mathlimits}%
   \ifx\p_limits\v!yes
     \def\math_stackers_stop_group{\egroup\endgroup\limits}%
     \mathop\bgroup
   \else
     \let\math_stackers_stop_group\endgroup
   \fi}

\unexpanded\def\math_stackers_make_double#top#bottom#category#codepoint#codeextra#text%
  {\math_stackers_start_group{#category}%
   \mathstackersparameter\c!left\relax
   \dostarttagged\t!mathstacker\currentmathstackers
   \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
     {\edef\m_math_stackers_text_middle {#text}%
      %
      \edef\p_offset     {\mathstackersparameter\c!offset}%
      \edef\p_location   {\mathstackersparameter\c!location}%
      \edef\p_strut      {\mathstackersparameter\c!strut}%
      \edef\p_alternative{\mathstackersparameter\c!alternative}%
      %
      \scratchleftoffset \zeropoint
      \scratchrightoffset\zeropoint
      %
      \math_stackers_check_unicode{#codepoint}%
      %
      \ifx\math_stackers_middle\empty
        \setbox\scratchboxthree\emptyhbox
      \else
        \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}%
      \fi
      \scratchwidth\wd\scratchboxthree
      %
      \scratchdimen\mathstackersparameter\c!minwidth\relax
      \ifdim\scratchwidth<\scratchdimen
         \scratchwidth\scratchdimen
      \fi
      \advance\scratchwidth2\scratchhoffset
      %
      \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
      \setbox\scratchboxthree\hbox to \scratchwidth{\hss\box\scratchboxthree\hss}%
      %
      \scratchunicode#codeextra\relax
      \ifcase\scratchunicode\else
        \setbox\scratchboxone\csname\??mathstackersalternative\p_alternative\endcsname
      \fi
      %
      \math_stackers_normalize_three
      % analysis
      \ifcase#bottom\relax
        \ifcase#top\relax
            \dosettagproperty\s!subtype\t!munderover
        \else
            \dosettagproperty\s!subtype\t!mover
        \fi
      \else
        \ifcase#top\relax
            \dosettagproperty\s!subtype\t!munder
        \else
            % brrr
        \fi
      \fi
      % base
      \math_stackers_start_tagged_mid
        \math_stackers_middle\bgroup
          \box\scratchboxthree
        \egroup
      \math_stackers_stop_tagged
      %
      \ifdim\htdp\scratchboxtwo>\zeropoint
        \ifcase#bottom\else
          \kern-\scratchwidth
          % under
          \math_stackers_start_tagged_bot
            \math_stackers_bottom\bgroup
              \lower\dimexpr
                 \scratchdepth
                +\ht\scratchboxtwo
                +\mathstackersparameter\c!distance % was \c!voffset
              \relax
              \ifcase#top\relax
                \box\scratchboxtwo
              \else
                \box\scratchboxone
              \fi
            \egroup
          \math_stackers_stop_tagged
        \fi
        \ifcase#top\else
          \kern-\scratchwidth
          % over
          \math_stackers_start_tagged_top
            \math_stackers_top\bgroup
              \raise\dimexpr
                 \scratchheight
                +\dp\scratchboxtwo % new
                +\mathstackersparameter\c!distance % was \c!voffset
              \relax
              \box\scratchboxtwo
            \egroup
          \math_stackers_stop_tagged
        \fi
        %
      \fi}%
  \dostoptagged
  \mathstackersparameter\c!right\relax
  \math_stackers_stop_group}

\unexpanded\def\definemathoverextensible  {\dotripleempty   \math_extensibles_define_over }
\unexpanded\def\definemathunderextensible {\dotripleempty   \math_extensibles_define_under}
\unexpanded\def\definemathdoubleextensible{\doquadrupleempty\math_extensibles_define_double}

\def\math_extensibles_define_over[#1][#2][#3]%
  {\ifthirdargument
     \setuevalue{#2}{\math_stackers_make_double\plusone  \zerocount{#1}{\number#3}{0}}%
   \else
     \setuevalue{#1}{\math_stackers_make_double\plusone  \zerocount\noexpand\currentmathstackers{\number#2}{0}}%
   \fi}

\def\math_extensibles_define_under[#1][#2][#3]%
  {\ifthirdargument
     \setuevalue{#2}{\math_stackers_make_double\zerocount\plusone{#1}{\number#3}{0}}%
   \else
     \setuevalue{#1}{\math_stackers_make_double\zerocount\plusone\noexpand\currentmathstackers{\number#2}{0}}%
   \fi}

\def\math_extensibles_define_double[#1][#2][#3][#4]%
  {\iffourthargument
     \setuevalue{#2}{\math_stackers_make_double\plusone  \plusone{#1}{\number#3}{\number#4}}%
   \else
     \setuevalue{#1}{\math_stackers_make_double\plusone  \plusone\noexpand\currentmathstackers{\number#2}{\number#3}}%
   \fi}

\unexpanded\def\mathover  {\begingroup\dosingleempty\math_stackers_handle_over  }
\unexpanded\def\mathunder {\begingroup\dosingleempty\math_stackers_handle_under }
\unexpanded\def\mathdouble{\begingroup\dodoubleempty\math_stackers_handle_double}

\def\math_stackers_handle_over[#category]%
  {\math_stackers_direct_double\plusone\zerocount{\iffirstargument#category\else\v!top   \fi}} % will be defined later on

\def\math_stackers_handle_under[#category]%
  {\math_stackers_direct_double\zerocount\plusone{\iffirstargument#category\else\v!bottom\fi}} % will be defined later on

\def\math_stackers_handle_double[#category]%
  {\math_stackers_direct_double\plusone\plusone  {\iffirstargument#category\else\v!bottom\fi}} % will be defined later on

\def\math_stackers_direct_double#top#bottom#category#codepoint#text%
  {\math_stackers_make_double#top#bottom{#category}{#codepoint}{0}{#text}%
   \endgroup}

%D A relative new one is a combination of accents and text (as needed in mathml):

\unexpanded\def\math_stackers_make_double_text#where#category#codepoint#text#extra%
  {\math_stackers_start_group{#category}%
   \mathstackersparameter\c!left\relax
   \dostarttagged\t!mathstacker\currentmathstackers
   \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
     {\edef\currentmathstackers{#category}%
      %
      \edef\p_offset     {\mathstackersparameter\c!offset}%
      \edef\p_location   {\mathstackersparameter\c!location}%
      \edef\p_strut      {\mathstackersparameter\c!strut}%
      \edef\p_alternative{\mathstackersparameter\c!alternative}%
      %
      \scratchleftoffset \zeropoint
      \scratchrightoffset\zeropoint
      %
      \edef\m_math_stackers_text_middle{#text}%
      \math_stackers_check_unicode{#codepoint}%
      \scratchunicode#codepoint\relax
      %
      \ifx\math_stackers_middle\empty
        \setbox\scratchboxthree\emptyhbox
      \else
        \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}%
      \fi
      %
      \ifcase#where\relax
        \edef\m_math_stackers_text_top{#extra}%
        \ifx\math_stackers_top\empty
          \setbox\scratchboxone\emptyhbox
        \else
          \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_toptext}%
        \fi
      \else
        \edef\m_math_stackers_text_bottom{#extra}%
        \ifx\math_stackers_bottom\empty
          \setbox\scratchboxone\emptyhbox
        \else
          \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_bottomtext}%
        \fi
      \fi
      %
      \scratchwidth\wd
        \ifdim\wd\scratchboxone>\wd\scratchboxthree
          \scratchboxone
        \else
          \scratchboxthree
        \fi
      \relax
      \scratchdimen\mathstackersparameter\c!minwidth\relax
      \ifdim\scratchwidth<\scratchdimen
         \scratchwidth\scratchdimen
      \fi
      \advance\scratchwidth2\scratchhoffset
      %
      \ifdim\wd\scratchboxone<\scratchwidth
        \setbox\scratchboxone\hbox to \scratchwidth{\hss\unhbox\scratchboxone\hss}%
      \fi
      \ifdim\wd\scratchboxthree<\scratchwidth
        \setbox\scratchboxthree\hbox to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
      \fi
      %
      \math_stackers_normalize_three
      % analysis
      \dosettagproperty\s!subtype\t!munderover
      % base
      \math_stackers_start_tagged_mid
        \math_stackers_middle\bgroup
          \box\scratchboxthree
        \egroup
      \math_stackers_stop_tagged
      %
      \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
      \kern-\scratchwidth
      \ifcase#where\relax
        % under
        \math_stackers_start_tagged_bot
          \math_stackers_bottom\bgroup
            \lower\dimexpr
              \scratchdepth
             +\ht\scratchboxtwo
             +\mathstackersparameter\c!distance
            \relax
            \box\scratchboxtwo % accent
          \egroup
        \math_stackers_stop_tagged
        \kern-\scratchwidth
        % over
        \math_stackers_start_tagged_top
          \math_stackers_top\bgroup
            \raise\dimexpr
               \scratchheight
              +\dp\scratchboxone
              +\mathstackersparameter\c!voffset
            \relax
            \box\scratchboxone % toptext
          \egroup
        \math_stackers_stop_tagged
      \else
        % under
        \math_stackers_start_tagged_bot
          \math_stackers_bottom\bgroup
            \lower\dimexpr
               \scratchdepth
              +\ht\scratchboxone
              +\mathstackersparameter\c!voffset
            \relax
            \box\scratchboxone % bottext
          \egroup
        \math_stackers_stop_tagged
        \kern-\scratchwidth
        % over
        \math_stackers_start_tagged_top
          \math_stackers_top\bgroup
            \raise\dimexpr
               \scratchheight
              +\dp\scratchboxtwo % new
              +\mathstackersparameter\c!distance
            \relax
            \box\scratchboxtwo % accent
          \egroup
        \math_stackers_stop_tagged
      \fi
      }%
   \dostoptagged
   \mathstackersparameter\c!right\relax
   \math_stackers_stop_group}

\unexpanded\def\definemathovertextextensible {\dotripleempty\math_extensibles_define_over_text }
\unexpanded\def\definemathundertextextensible{\dotripleempty\math_extensibles_define_under_text}

\def\math_extensibles_define_over_text[#1][#2][#3]%
  {\ifthirdargument
     \setuevalue{#2}{\math_stackers_make_double_text\plusone  {#1}{\number#3}}%
   \else
     \setuevalue{#1}{\math_stackers_make_double_text\plusone  \noexpand\currentmathstackers{\number#2}}%
   \fi}

\def\math_extensibles_define_under_text[#1][#2][#3]%
  {\ifthirdargument
     \setuevalue{#2}{\math_stackers_make_double_text\zerocount{#1}{\number#3}}%
   \else
     \setuevalue{#1}{\math_stackers_make_double_text\zerocount\noexpand\currentmathstackers{\number#2}}%
   \fi}

\unexpanded\def\mathovertext {\begingroup\dosingleempty\math_stackers_handle_over_text  }
\unexpanded\def\mathundertext{\begingroup\dosingleempty\math_stackers_handle_under_text }

\def\math_stackers_handle_over_text[#category]%
  {\math_stackers_direct_double_text\plusone  {\iffirstargument#category\else\v!top   \fi}} % will be defined later on

\def\math_stackers_handle_under_text[#category]%
  {\math_stackers_direct_double_text\zerocount{\iffirstargument#category\else\v!bottom\fi}} % will be defined later on

\def\math_stackers_direct_double_text#where#category#codepoint#text#extra%%
  {\math_stackers_make_double_text#where{#category}{#codepoint}{#text}{#extra}%
   \endgroup}

%D Here is a bonus macro that takes three texts. It can be used to get consistent
%D mixed usage.

\unexpanded\def\mathtriplet
  {\begingroup
   \dosingleempty\math_stackers_handle_triplet}

\def\math_stackers_handle_triplet[#category]#middletext#toptext#bottomtext%
  {\math_stackers_triplet\plusone{\iffirstargument#category\else\currentmathstackers\fi}{#middletext}{#toptext}{#bottomtext}%
   \endgroup}

\unexpanded\def\definemathtriplet
  {\dotripleempty\math_stackers_define_triplet}

\def\math_stackers_define_triplet[#1][#2][#3]% category name default
  {\ifthirdargument
     \setuevalue{#2}{\math_stackers_auto_triplet_yes{#1}{#3}}%
   \else\ifsecondargument
     \setuevalue{#2}{\math_stackers_auto_triplet_nop{#1}}%
   \else
     \setuevalue{#1}{\math_stackers_auto_triplet_nop\noexpand\currentmathstackers}%
   \fi\fi}

\unexpanded\def\math_stackers_auto_triplet_yes#category#middletext%
  {\begingroup
   \edef\currentmathstackers  {#category}%
   \def \m_math_stackers_text_middle{#middletext}%
   \dosingleempty\math_stackers_auto_triplet_yes_first}

\unexpanded\def\math_stackers_auto_triplet_yes_first[#category]% [#2]% #2 gobble spaces
  {\iffirstargument\edef\currentmathstackers{#category}\fi
   \permitspacesbetweengroups
   \dodoublegroupempty\math_stackers_auto_triplet_yes_second}

\def\math_stackers_auto_triplet_yes_second#toptext#bottomtext%
  {\math_stackers_triplet\plusone\currentmathstackers\m_math_stackers_text_middle{#toptext}{#bottomtext}%
   \endgroup}

\unexpanded\def\math_stackers_auto_triplet_nop#category%
  {\begingroup
   \edef\currentmathstackers{#category}%
   \dosingleempty\math_stackers_auto_triplet_nop_first}

\unexpanded\def\math_stackers_auto_triplet_nop_first[#category]% [#2]% #2 gobble spaces
  {\iffirstargument\edef\currentmathstackers{#category}\fi
   \permitspacesbetweengroups
   \dotriplegroupempty\math_stackers_auto_triplet_nop_second}

\def\math_stackers_auto_triplet_nop_second#middletext#toptext#bottomtext%
  {\math_stackers_triplet\plusone\currentmathstackers{#middletext}{#toptext}{#bottomtext}%
   \endgroup}

%D Definitions:

\definemathstackers
  [\v!mathematics]
  [\c!topcommand=\mathematics,
   \c!middlecommand=\mathematics,
   \c!bottomcommand=\mathematics]

\definemathstackers
  [\s!math]
  [\v!mathematics]

\definemathstackers
  [\v!text]
  [\v!mathematics]
  [\c!topcommand=,
   \c!middlecommand=\mathematics,
   \c!bottomcommand=]

\definemathstackers
  [\v!reverse]
  [\v!mathematics]
  [\c!order=\v!reverse]

\definemathstackers
  [\v!both]
  [\v!mathematics]
  [\c!location=\v!top, % ?
   \c!strut=\v!no,
   \c!middlecommand=\mathematics,
   \c!hoffset=\zeropoint]

\definemathstackers
  [\v!top]
  [\v!both]

\definemathstackers
  [\v!bottom]
  [\v!both]

\definemathstackers
  [\v!vfenced]
  [\v!both]
  [\c!mathclass=\s!ord,
   \c!mathlimits=\v!yes]

% these are needed for mathml:

% \setupmathstackers
%   [\v!both]
%   [\c!hoffset=1pt,
%    \c!voffset=1pt]

\definemathstackers
  [\v!bothtext]
  [\v!both]
  [\c!strut=\v!yes]

% These are compatibity definitions, math only.

% todo: top= bottom= middle= is nicer (compare math-fen)

%D We save a few definitions that we automatically got from the \type {char-def.lua}
%D database.

% Be careful in choosing what accents you take (the code below uses a
% combining one):
%
% \startbuffer
% % $\Umathaccent top        0 0 "20D7 {example}$
% % $\Umathaccent top  fixed 0 0 "20D7 {example}$
% $\Umathaccent              0 0 "20D7 {example}$
% $\Umathaccent        fixed 0 0 "20D7 {example}$
% $\Umathaccent bottom       0 0 "20D7 {example}$
% $\Umathaccent bottom fixed 0 0 "20D7 {example}$
% $\Umathaccent both         0 0 "20D7
%                            0 0 "20D7 {example}$
% $\Umathaccent both fixed   0 0 "20D7
%                    fixed   0 0 "20D7 {example}$
% $\Umathaccent both         0 0 "20D7
%                    fixed   0 0 "20D7 {example}$
% $\Umathaccent both fixed   0 0 "20D7
%                            0 0 "20D7 {example}$
% \stopbuffer
%
% \setupbodyfont[modern]  \getbuffer
% \setupbodyfont[xits]    \getbuffer
% \setupbodyfont[cambria] \getbuffer

\unexpanded\def\normaldoublebrace {\Umathaccents 0 \defaultmathfamily "23DE 0 \defaultmathfamily "23DF }
\unexpanded\def\normaldoubleparent{\Umathaccents 0 \defaultmathfamily "23DC 0 \defaultmathfamily "23DD }

% let's keep this

\let\normaloverbrace      \overbrace
\let\normalunderbrace     \underbrace
\let\normaloverparent     \overparent
\let\normalunderparent    \underparent
\let\normaloverbracket    \overbracket
\let\normalunderbracket   \underbracket
\let\normalunderleftarrow \underleftarrow
\let\normaloverleftarrow  \overleftarrow
\let\normalunderrightarrow\underrightarrow
\let\normaloverrightarrow \overrightarrow

\let\lceil                \lceiling
\let\rceil                \rceiling

%D Here come the new ones:

\definemathstackers [\v!none]   [\v!mathematics] [\c!hoffset=\zeropoint]
\definemathstackers [\v!normal] [\v!mathematics] [\c!hoffset=0.5\emwidth] % the default
\definemathstackers [\v!small]  [\v!mathematics] [\c!hoffset=1\emwidth]
\definemathstackers [\v!medium] [\v!mathematics] [\c!hoffset=1.5\emwidth]
\definemathstackers [\v!big]    [\v!mathematics] [\c!hoffset=2\emwidth]

\definemathextensible [\v!reverse] [xrel]                ["002D]
\definemathextensible [\v!reverse] [xequal]              ["003D]
\definemathextensible [\v!reverse] [xleftarrow]          ["2190] % ["27F5]
\definemathextensible [\v!reverse] [xrightarrow]         ["2192] % ["27F6]
\definemathextensible [\v!reverse] [xleftrightarrow]     ["27F7]
\definemathextensible [\v!reverse] [xLeftarrow]          ["27F8]
\definemathextensible [\v!reverse] [xRightarrow]         ["27F9]
\definemathextensible [\v!reverse] [xLeftrightarrow]     ["27FA]
\definemathextensible [\v!reverse] [xtwoheadleftarrow]   ["219E]
\definemathextensible [\v!reverse] [xtwoheadrightarrow]  ["21A0]
\definemathextensible [\v!reverse] [xmapsto]             ["21A6]
\definemathextensible [\v!reverse] [xhookleftarrow]      ["21A9]
\definemathextensible [\v!reverse] [xhookrightarrow]     ["21AA]
\definemathextensible [\v!reverse] [xleftharpoondown]    ["21BD]
\definemathextensible [\v!reverse] [xleftharpoonup]      ["21BC]
\definemathextensible [\v!reverse] [xrightharpoondown]   ["21C1]
\definemathextensible [\v!reverse] [xrightharpoonup]     ["21C0]
\definemathextensible [\v!reverse] [xrightoverleftarrow] ["21C4]
\definemathextensible [\v!reverse] [xleftrightharpoons]  ["21CB]
\definemathextensible [\v!reverse] [xrightleftharpoons]  ["21CC]
\definemathextensible [\v!reverse] [xtriplerel]          ["2261]

\definemathextensible [\v!mathematics] [mrel]                ["002D]
\definemathextensible [\v!mathematics] [mequal]              ["003D]
\definemathextensible [\v!mathematics] [mleftarrow]          ["2190] % ["27F5]
\definemathextensible [\v!mathematics] [mrightarrow]         ["2192] % ["27F6]
\definemathextensible [\v!mathematics] [mleftrightarrow]     ["27F7]
\definemathextensible [\v!mathematics] [mLeftarrow]          ["27F8]
\definemathextensible [\v!mathematics] [mRightarrow]         ["27F9]
\definemathextensible [\v!mathematics] [mLeftrightarrow]     ["27FA]
\definemathextensible [\v!mathematics] [mtwoheadleftarrow]   ["219E]
\definemathextensible [\v!mathematics] [mtwoheadrightarrow]  ["21A0]
\definemathextensible [\v!mathematics] [mmapsto]             ["21A6]
\definemathextensible [\v!mathematics] [mhookleftarrow]      ["21A9]
\definemathextensible [\v!mathematics] [mhookrightarrow]     ["21AA]
\definemathextensible [\v!mathematics] [mleftharpoondown]    ["21BD]
\definemathextensible [\v!mathematics] [mleftharpoonup]      ["21BC]
\definemathextensible [\v!mathematics] [mrightharpoondown]   ["21C1]
\definemathextensible [\v!mathematics] [mrightharpoonup]     ["21C0]
\definemathextensible [\v!mathematics] [mrightoverleftarrow] ["21C4]
\definemathextensible [\v!mathematics] [mleftrightharpoons]  ["21CB]
\definemathextensible [\v!mathematics] [mrightleftharpoons]  ["21CC]
\definemathextensible [\v!mathematics] [mtriplerel]          ["2261]

\definemathextensible [\v!mathematics] [eleftarrowfill]         ["2190] % ["27F5]
\definemathextensible [\v!mathematics] [erightarrowfill]        ["2192] % ["27F6]
\definemathextensible [\v!mathematics] [eleftrightarrowfill]    ["27F7]
\definemathextensible [\v!mathematics] [etwoheadrightarrowfill] ["27F9]
\definemathextensible [\v!mathematics] [eleftharpoondownfill]   ["21BD]
\definemathextensible [\v!mathematics] [eleftharpoonupfill]     ["21BC]
\definemathextensible [\v!mathematics] [erightharpoondownfill]  ["21C1]
\definemathextensible [\v!mathematics] [erightharpoonupfill]    ["21C0]

\definemathextensible [\v!mathematics] [eoverbarfill]           ["FE33E]
\definemathextensible [\v!mathematics] [eunderbarfill]          ["FE33F]
\definemathextensible [\v!mathematics] [eoverbracefill]         ["FE3DE]
\definemathextensible [\v!mathematics] [eunderbracefill]        ["FE3DF]
\definemathextensible [\v!mathematics] [eoverparentfill]        ["FE3DC]
\definemathextensible [\v!mathematics] [eunderparentfill]       ["FE3DD]
\definemathextensible [\v!mathematics] [eoverbracketfill]       ["FE3B4]
\definemathextensible [\v!mathematics] [eunderbracketfill]      ["FE3B5]

\definemathextensible [\v!text] [trel]                ["002D]
\definemathextensible [\v!text] [tequal]              ["003D]
\definemathextensible [\v!text] [tmapsto]             ["21A6]
\definemathextensible [\v!text] [tleftarrow]          ["2190] % ["27F5]
\definemathextensible [\v!text] [trightarrow]         ["2192] % ["27F6]
\definemathextensible [\v!text] [tleftrightarrow]     ["27F7]
\definemathextensible [\v!text] [tLeftarrow]          ["27F8]
\definemathextensible [\v!text] [tRightarrow]         ["27F9]
\definemathextensible [\v!text] [tLeftrightarrow]     ["27FA]
\definemathextensible [\v!text] [ttwoheadleftarrow]   ["219E]
\definemathextensible [\v!text] [ttwoheadrightarrow]  ["21A0]
\definemathextensible [\v!text] [thookleftarrow]      ["21A9]
\definemathextensible [\v!text] [thookrightarrow]     ["21AA]
\definemathextensible [\v!text] [tleftharpoondown]    ["21BD]
\definemathextensible [\v!text] [tleftharpoonup]      ["21BC]
\definemathextensible [\v!text] [trightharpoondown]   ["21C1]
\definemathextensible [\v!text] [trightharpoonup]     ["21C0]
\definemathextensible [\v!text] [trightoverleftarrow] ["21C4]
\definemathextensible [\v!text] [tleftrightharpoons]  ["21CB]
\definemathextensible [\v!text] [trightleftharpoons]  ["21CC]
\definemathextensible [\v!text] [ttriplerel]          ["2261]

\definemathoverextensible [\v!top] [overleftarrow]         ["2190] % ["27F5]
\definemathoverextensible [\v!top] [overrightarrow]        ["2192] % ["27F6]
\definemathoverextensible [\v!top] [overleftrightarrow]    ["27F7]
\definemathoverextensible [\v!top] [overtwoheadleftarrow]  ["27F8]
\definemathoverextensible [\v!top] [overtwoheadrightarrow] ["27F9]
\definemathoverextensible [\v!top] [overleftharpoondown]   ["21BD]
\definemathoverextensible [\v!top] [overleftharpoonup]     ["21BC]
\definemathoverextensible [\v!top] [overrightharpoondown]  ["21C1]
\definemathoverextensible [\v!top] [overrightharpoonup]    ["21C0]

\definemathunderextensible [\v!bottom] [underleftarrow]         ["2190] % ["27F5]
\definemathunderextensible [\v!bottom] [underrightarrow]        ["2192] % ["27F6]
\definemathunderextensible [\v!bottom] [underleftrightarrow]    ["27F7]
\definemathunderextensible [\v!bottom] [undertwoheadleftarrow]  ["27F8]
\definemathunderextensible [\v!bottom] [undertwoheadrightarrow] ["27F9]
\definemathunderextensible [\v!bottom] [underleftharpoondown]   ["21BD]
\definemathunderextensible [\v!bottom] [underleftharpoonup]     ["21BC]
\definemathunderextensible [\v!bottom] [underrightharpoondown]  ["21C1]
\definemathunderextensible [\v!bottom] [underrightharpoonup]    ["21C0]

% We don't use overline and underline. This is one of the overlooked aspects of
% unicode cq. opentype math: why treat rules different than e.g. arrows and
% accents. It is a bit unfortunate that the opportunity to move math to new
% technologies happened outside the tex domain (and/or some aspects were kept
% while in fact they were side effects of limitations of traditional fonts).
% From the unicode aware tex engines' implementation point of view things
% could have been done a bit nicer but then: the community didn't seem to care
% too much and just has to follow now.
%
% Anyhow, we use a character based approach so that at least we get unicode
% stuff in the backend (okay, we still need to deal with some cut and paste
% issues but at least we now know what we deal with.

% alternatively we can move the original to FE*

\definemathoverextensible   [vfenced] [overbar]       ["FE33E]          % ["203E]
\definemathunderextensible  [vfenced] [underbar]               ["FE33F] % ["203E]
\definemathdoubleextensible [vfenced] [doublebar]     ["FE33E] ["FE33F]

\definemathoverextensible   [vfenced] [overbrace]     ["FE3DE]          % ["023DE]
\definemathunderextensible  [vfenced] [underbrace]             ["FE3DF] % ["023DF]
\definemathdoubleextensible [vfenced] [doublebrace]   ["FE3DE] ["FE3DF]

\definemathoverextensible   [vfenced] [overparent]    ["FE3DC]          % ["023DC]
\definemathunderextensible  [vfenced] [underparent]            ["FE3DD] % ["023DD]
\definemathdoubleextensible [vfenced] [doubleparent]  ["FE3DC] ["FE3DD]

\definemathoverextensible   [vfenced] [overbracket]   ["FE3B4]          % ["023B4]
\definemathunderextensible  [vfenced] [underbracket]           ["FE3B5] % ["023B5]
\definemathdoubleextensible [vfenced] [doublebracket] ["FE3B4] ["FE3B5]

% \unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}

%D For mathml:

\definemathdoubleextensible     [both]     [overbarunderbar]         ["FE33E] ["FE33F]
\definemathdoubleextensible     [both]     [overbraceunderbrace]     ["FE3DE] ["FE3DF]
\definemathdoubleextensible     [both]     [overparentunderparent]   ["FE3DC] ["FE3DD]
\definemathdoubleextensible     [both]     [overbracketunderbracket] ["FE3B4] ["FE3B5]

\definemathovertextextensible   [bothtext] [overbartext]             ["FE33E]
\definemathundertextextensible  [bothtext] [underbartext]                     ["FE33F]
\definemathovertextextensible   [bothtext] [overbracetext]           ["FE3DE]
\definemathundertextextensible  [bothtext] [underbracetext]                   ["FE3DF]
\definemathovertextextensible   [bothtext] [overparenttext]          ["FE3DC]
\definemathundertextextensible  [bothtext] [underparenttext]                  ["FE3DD]
\definemathovertextextensible   [bothtext] [overbrackettext]         ["FE3B4]
\definemathundertextextensible  [bothtext] [underbrackettext]                 ["FE3B5]

%D Some bonus ones (for the moment here):

\definemathstackers
  [\v!chemistry]
  [\c!offset=\v!max,
   \c!left=\enspace,
   \c!right=\enspace,
   \c!hoffset=.5\emwidth]

\definemathextensible [\v!chemistry] [cleftarrow]          ["2190]
\definemathextensible [\v!chemistry] [crightarrow]         ["2192]
\definemathextensible [\v!chemistry] [crightoverleftarrow] ["21C4]

% for the moment:

\def\math_stackers_hacked_fill#1#2#3%
  {\mathematics
     {\begingroup
      \mathsurround\zeropoint
      \thickmuskip \zeromuskip
      \medmuskip   \zeromuskip
      \thinmuskip  \zeromuskip
      #1%
      \mkern-7\onemuskip
      \cleaders\mathstylehbox{\mkern-2\onemuskip#2\mkern-2\onemuskip}\hfill
      \mkern-7\onemuskip
      #3%
      \endgroup}}

% These will be defined in char-def as well once we have \leaders<number>

\unexpanded\def\rightarrowfill        {\math_stackers_hacked_fill \relbar                   \relbar                      \rightarrow}
\unexpanded\def\leftarrowfill         {\math_stackers_hacked_fill \leftarrow                \relbar                      \relbar    }
\unexpanded\def\rightoverleftarrowfill{\math_stackers_hacked_fill \ctxdoublearrowfillleftend\ctxdoublearrowfillmiddlepart\ctxdoublearrowfillrightend}
\unexpanded\def\equalfill             {\math_stackers_hacked_fill \Relbar                   \Relbar                      \Relbar}
\unexpanded\def\Rightarrowfill        {\math_stackers_hacked_fill \Relbar                   \Relbar                      \Rightarrow}
\unexpanded\def\Leftarrowfill         {\math_stackers_hacked_fill \Leftarrow                \Relbar                      \Relbar}
\unexpanded\def\Leftrightarrowfill    {\math_stackers_hacked_fill \Leftarrow                \Relbar                      \Rightarrow}
\unexpanded\def\leftrightarrowfill    {\math_stackers_hacked_fill \leftarrow                \relbar                      \rightarrow}
\unexpanded\def\mapstofill            {\math_stackers_hacked_fill{\mapstochar\relbar}       \relbar                      \rightarrow}
\unexpanded\def\twoheadrightarrowfill {\math_stackers_hacked_fill \relbar                   \relbar                      \twoheadrightarrow}
\unexpanded\def\twoheadleftarrowfill  {\math_stackers_hacked_fill \twoheadleftarrow         \relbar                      \relbar}
\unexpanded\def\rightharpoondownfill  {\math_stackers_hacked_fill \relbar                   \relbar                      \rightharpoondown}
\unexpanded\def\rightharpoonupfill    {\math_stackers_hacked_fill \relbar                   \relbar                      \rightharpoonup}
\unexpanded\def\leftharpoondownfill   {\math_stackers_hacked_fill \leftharpoondown          \relbar                      \relbar}
\unexpanded\def\leftharpoonupfill     {\math_stackers_hacked_fill \leftharpoonup            \relbar                      \relbar}
\unexpanded\def\hookleftfill          {\math_stackers_hacked_fill \leftarrow                \relbar                     {\relbar\joinrel\rhook}}
\unexpanded\def\hookrightfill         {\math_stackers_hacked_fill{\lhook\joinrel\relbar}    \relbar                      \rightarrow}
\unexpanded\def\relfill               {\math_stackers_hacked_fill \relbar                   \relbar                      \relbar}
\unexpanded\def\triplerelfill         {\math_stackers_hacked_fill \equiv                    \equiv                       \equiv}

\unexpanded\def\singlebond            {{\xrel}} % or \def\singlebond{{\xrel[2]}}
\unexpanded\def\doublebond            {{\xequal}}
\unexpanded\def\triplebond            {{\xtriplerel}}

\unexpanded\def\defineextensiblefiller
  {\dodoubleargument\math_stackers_define_filler}

\def\math_stackers_define_filler[#1][#2]%
  {\setuevalue{#1}{\leaders\number#2\hfill}}

%D For the moment:

\def\math_stackers_define_filler[#1][#2]%
  {\expandafter\let\csname\??mathextensiblefallbacks\number#2\expandafter\endcsname\csname#1\endcsname
   \expandafter\let\csname                                 #1\expandafter\endcsname\csname#1\endcsname}

\defineextensiblefiller [barfill]                ["203E]
\defineextensiblefiller [relfill]                ["002D]
\defineextensiblefiller [equalfill]              ["003D]
\defineextensiblefiller [leftarrowfill]          ["2190]
\defineextensiblefiller [rightarrowfill]         ["2192]
\defineextensiblefiller [twoheadleftarrowfill]   ["219E]
\defineextensiblefiller [twoheadrightarrowfill]  ["21A0]
\defineextensiblefiller [mapstofill]             ["21A6]
\defineextensiblefiller [hookleftarrowfill]      ["21A9]
\defineextensiblefiller [hookrightarrowfill]     ["21AA]
\defineextensiblefiller [leftharpoondownfill]    ["21BD]
\defineextensiblefiller [leftharpoonupfill]      ["21BC]
\defineextensiblefiller [rightharpoondownfill]   ["21C1]
\defineextensiblefiller [rightharpoonupfill]     ["21C0]
\defineextensiblefiller [rightoverleftarrowfill] ["21C4]
\defineextensiblefiller [leftrightharpoonsfill]  ["21CB]
\defineextensiblefiller [rightleftharpoonsfill]  ["21CC]
\defineextensiblefiller [triplerelfill]          ["2261]
\defineextensiblefiller [leftrightarrowfill]     ["27F7]
\defineextensiblefiller [Leftarrowfill]          ["27F8]
\defineextensiblefiller [Rightarrowfill]         ["27F9]
\defineextensiblefiller [Leftrightarrowfill]     ["27FA]
\defineextensiblefiller [Leftrightarrowfill]     ["27FA]

%defineextensiblefiller [overbarfill]            ["FE33E] % untested
%defineextensiblefiller [underbarfill]           ["FE33F] % untested
\defineextensiblefiller [overbracefill]          ["FE3DE] % untested
\defineextensiblefiller [underbracefill]         ["FE3DF] % untested
\defineextensiblefiller [overparentfill]         ["FE3DC] % untested
\defineextensiblefiller [underparentfill]        ["FE3DD] % untested
\defineextensiblefiller [overbracketfill]        ["FE3B4] % untested
\defineextensiblefiller [underbracketfill]       ["FE3B5] % untested

%D Extra:

\unexpanded\edef\singlebond{\mathematics{\mathsurround\zeropoint\char\number"002D}}
\unexpanded\edef\doublebond{\mathematics{\mathsurround\zeropoint\char\number"003D}}
\unexpanded\edef\triplebond{\mathematics{\mathsurround\zeropoint\char\number"2261}}

% \mathchardef\singlebond"002D
% \mathchardef\doublebond"003D
% \mathchardef\triplebond"2261

%D Also handy:

\unexpanded\def\definemathunstacked
  {\dotripleempty\math_stackers_define_unstacked_normal}

\def\math_stackers_define_unstacked_normal[#1][#2][#3]% category name unicode
  {\ifthirdargument
     \setuevalue{#2}{\math_stackers_unstacked_normal{#1}{\number#3}}%
   \else
     \setuevalue{#1}{\math_stackers_unstacked_normal\noexpand\currentmathstackers{\number#2}}%
   \fi}

\unexpanded\def\math_stackers_unstacked_normal#category#codepoint%
  {\begingroup
   \edef\currentmathstackers{#category}%
   \edef\p_moffset{\mathstackersparameter\c!moffset}%
   \ifx\p_moffset\empty \else
     \mskip\scratchmuskip
   \fi
   \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
     {\usemathstackerscolorparameter\c!color
      \Umathchar\zerocount\defaultmathfamily#codepoint}%
   \ifx\p_moffset\empty \else
     \mskip\scratchmuskip
   \fi
   \endgroup}

\definemathstackers  [\v!wide] [\c!moffset=\thickmuskip,\c!mathclass=\s!rel]

\definemathunstacked [\v!wide] [And]       ["0026] % \mathrel{\;&\;}
\definemathunstacked [\v!wide] [impliedby] ["27F8] % \mathrel{\;\Longleftarrow\;}
\definemathunstacked [\v!wide] [implies]   ["27F9] % \mathrel{\;\Longrightarrow\;}
\definemathunstacked [\v!wide] [iff]       ["27FA] % \mathrel{\;\Longleftrightarrow\;}

\protect \endinput

% \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}
% \limits\normalsuperscript{\box0}\normalsubscript{\box2}}%

% $\Uoverdelimiter \defaultmathfamily "2194 {xxxx}$
% $\Udelimiterover \defaultmathfamily "2194 {xxxx}$
% $\Uunderdelimiter\defaultmathfamily "2194 {xxxx}$
% $\Udelimiterunder\defaultmathfamily "2194 {xxxx}$
% $\Udelimiterover \defaultmathfamily "219A {\Udelimiterunder \defaultmathfamily "219B {xxxx}}$

% $a \mathrel{\mathop{\filledhboxr{mid}}}\limits^{\filledhboxg{\strut top}}_{\filledhboxb{\strut bottom}} b$
