%D \module
%D   [       file=math-acc,
%D        version=2013.07.31,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Accents,
%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 / Accents}

% There are probably errors ... too distracted by amazing (piano) music videos running
% on top of scite ... so: experimental code.

\unprotect

%D This module permits overloading of accents so that we can do fancy things. The
%D implementation is similar to stackers. By default accenst are defined in a simple
%D way. Contrary to extensibles accents cannot grow indefinitely. Alas the
%D implementation of accents is different too, in the sense that they are
%D prepositioned i.e. are already raised. (In my opinion for no real reason as they
%D need to adapt anyway).
%D
%D In \MKIV\ we used virtual characters in the "FE* range but in \LMTX\ we do it a bit
%D different as we have a more powerful virtual subsystem. For details on the older
%D but neat approach see the lua and mkiv files.
%D
%D Older implementations are kept in the \MKII\ and \MKIV\ modules for educational
%D purposes.

%D Only very few fonts provide flat accents but we emulate them for those that don't
%D have them. We also need to fix the related font parameter for a few fonts like
%D Lucida and Garamond.

% \startbuffer
% \im{
%     \dostepwiserecurse{`A}{`Z}{1}{
%         \blackrule[height=\the\Umathflattenedaccentbaseheight\textstyle,depth=0pt,width=0.05ts]
%         \hat{\char#1}
%     }
% }
% \stopbuffer
%
% \start % TEXpage[offset=1ts]
%     \showglyphs
%     \switchtobodyfont[modern]     \getbuffer\par
%     \switchtobodyfont[erewhon]    \getbuffer\par
%     \switchtobodyfont[concrete]   \getbuffer\par
%     \switchtobodyfont[libertinus] \getbuffer\par
%     \switchtobodyfont[stixtwo]    \getbuffer\par
%     \switchtobodyfont[kpfonts]    \getbuffer\par
%     \switchtobodyfont[minion]     \getbuffer\par
%     \switchtobodyfont[schola]     \getbuffer\par
%     \switchtobodyfont[lucida]     \getbuffer\par
%     \switchtobodyfont[xcharter]   \getbuffer\par
%     \switchtobodyfont[libertinus] \getbuffer\par
%     \switchtobodyfont[termes]     \getbuffer\par
% \stop %TEXpage

% scale:
%
%   no   : only use base
%   yes  : use base, variants and extensible, stretch and shrink when set
%   keep : use base, variants and extensible, stretch and shrink when set, but keep base
%
% alignsymbol:
%
%   center when accent is wider than base
%
% stretch|shrink:
%
%   scale accent to fit (base and variants depending on 'scale' value)

\installcorenamespace{mathaccents}

\installcommandhandler \??mathaccents {mathaccent} \??mathaccents

\aliased\let\setupmathaccents\setupmathaccent

\setupmathaccents
  [\c!top=,
   \c!bottom=,
   \c!mathstyle=,
   \c!color=,
   \c!symbolcolor=\mathaccentparameter\c!color,
   \c!textcolor=\mathaccentparameter\c!color,
   \c!scale=\v!no,
   \c!alignsymbol=\v!yes,
  %\c!stretch=\v!no,
  %\c!shrink=\v!no,
   \c!define=\v!yes, % not used
   \c!snap=\mathematicsparameter\c!snap]

\definemathaccent
  [\v!both]

\definemathaccent
  [\v!top]
  [\v!both]

\definemathaccent
  [\v!bottom]
  [\v!both]

\setupmathaccents
  [\v!top]
  [i=\v!auto]

\setupmathaccents
  [\v!both]
  [i=\v!auto]

\setupmathaccents
  [\v!bottom]
  [i=]

% \permanent\tolerant\protected\def\definemathtopaccent[#1]#*[#2]#*[#3]% class name top
%   {\ifparameter#3\or
%      \protected\frozen\instance\edefcsname#2\endcsname{\math_accent_common                      {#1}{#2}\plusone{\number#3}\zerocount}%
%    \else
%      \protected\frozen\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plusone{\number#2}\zerocount}%
%    \fi}

% \permanent\tolerant\protected\def\definemathbottomaccent[#1]#*[#2]#*[#3]% class name bottom
%   {\ifparameter#3\or
%      \protected\frozen\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plustwo\zerocount{\number#3}}%
%    \else
%      \protected\frozen\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plustwo\zerocount{\number#2}}%
%    \fi}

% \permanent\tolerant\protected\def\definemathdoubleaccent[#1]#*[#2]#*[#3]#*[#4]% class name top bottom
%   {\ifparameter#4\or
%      \protected\frozen\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plusthree{\number#3}{\number#4}}%
%    \else
%      \protected\frozen\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plusthree{\number#2}{\number#3}}%
%    \fi}

% \installlocalcurrenthandler \??mathaccents {mathaccent}

\permanent\tolerant\protected\def\definemathtopaccent[#1]#*[#2]#*[#3]% class name top
  {\ifparameter#3\or
     \definemathaccent[#2][#1]%
     \protected\frozen\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plusone{\number#3}\zerocount}%
   \else
     \definemathaccent[#1]%
     \protected\frozen\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plusone{\number#2}\zerocount}%
   \fi}

\permanent\tolerant\protected\def\definemathbottomaccent[#1]#*[#2]#*[#3]% class name bottom
  {\ifparameter#3\or
     \definemathaccent[#2][#1]%
     \protected\frozen\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plustwo\zerocount{\number#3}}%
   \else
     \definemathaccent[#1]%
     \protected\frozen\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plustwo\zerocount{\number#2}}%
   \fi}

\permanent\tolerant\protected\def\definemathdoubleaccent[#1]#*[#2]#*[#3]#*[#4]% class name top bottom
  {\ifparameter#4\or
     \definemathaccent[#2][#1]%
     \protected\frozen\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plusthree{\number#3}{\number#4}}%
   \else
     \definemathaccent[#1]%
     \protected\frozen\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plusthree{\number#2}{\number#3}}%
   \fi}

%D \starttyping
%D \im { \showboxes \showglyphs
%D     \hat{\tilde{\dot{x}}}
%D }
%D \im { \showboxes \showglyphs
%D     \hat[align=middle]{\tilde[align=middle]{\dot{x}}}
%D }
%D \stoptyping

\tolerant\protected\def\math_accent_common#class#name#kind#top#bottom#*[#settings]#:#content%
  {\beginmathgroup
 % \setlocalmathaccentcurrent{#class}% \edef\currentmathaccent{#class}%
   \cdef\currentmathaccent{#name}% \edef\currentmathaccent{#class}%
   \setupcurrentmathaccent[#settings]%
   \edef\p_scale{\mathaccentparameter\c!scale}%
   \ifx\p_scale\v!keep
     \lettonothing\m_fixed
   \orelse\ifx\p_scale\v!yes
     \lettonothing\m_fixed
   \else
     \let\m_fixed\s!fixed
   \fi
   \ifcstok{\mathaccentparameter\c!plugin}\v!mp
     \edef\p_mp{\mathaccentparameter\c!mp}%
     \ifempty\p_mp\else
       \clf_set_extensible_data
           mp     {\p_mp}
           left   \scratchcounterthree
           right  \scratchcounterthree
           middle \scratchcounterthree
        \relax
     \fi
   \else
     \lettonothing\p_mp
   \fi
   \math_tags_mfunctionlab\plustwo{#name}{\ifcase#kind\or\v!top\or\v!bottom\else\v!both\fi}%
   \Umathaccent
     \usedsymbolcolorparameterattributes{\mathaccentparameter\c!symbolcolor}%
 % nooverflow % there is never na overflow anyway but we do accept the key
   \ifcstok{\mathaccentparameter\c!align}\v!middle
     \s!center\relaxedspace
   \fi
   \ifcstok{\mathaccentparameter\c!stretch}\v!yes
     \s!stretch\relaxedspace
   \fi
   \ifcstok{\mathaccentparameter\c!shrink}\v!yes
     \s!shrink\relaxedspace
   \fi
   \ifcstok{\mathaccentparameter\c!snap}\v!yes
     \s!single\relaxedspace
   \fi
   \ifempty\p_mp\else
     \s!usecallback\relaxedspace
   \fi
   \ifx\p_scale\v!keep
     \s!keepbase\relaxedspace
   \fi
   \ifcstok{\mathaccentparameter\c!alignsymbol}\v!yes
     \s!nooverflow\relaxedspace
   \fi
   \ifcstok{\mathaccentparameter\c!offset}\v!auto
     \s!base\relaxedspace
   \fi
   \ifcase#kind\or
     \s!top\relaxedspace
     \m_fixed
     \fam\zerocount#top
% \fam\mathaccentcode#top % class is signal
   \or
     \s!bottom\relaxedspace
     \m_fixed
     \fam\zerocount#bottom
% \fam\mathaccentcode#bottom % class is signal
   \or
     \s!both\relaxedspace
     \m_fixed
     \fam\zerocount#bottom
     \fam\zerocount#top
%      \fam\mathaccentcode#bottom % class is signal
%      \fam\mathaccentcode#top % class is signal
   \fi
   {\usemathaccentcolorparameter\c!textcolor
    \startusemathstyleparameter\mathaccentparameter\c!mathstyle
    \ifcstok{\mathaccentparameter{i}}\v!auto\mathdotless\fi
    #content%
    \stopusemathstyleparameter}%
   \endmathgroup}

%D Relative new:

% \newconditional\c_math_accent_auto_dotless \c_math_accent_auto_dotless\conditionaltrue % cf opentype math

% \aliased\let\normalgrave\grave
% \aliased\let\normalddot \ddot
% \aliased\let\normalbar  \bar
% \aliased\let\normalacute\acute
% \aliased\let\normalhat  \hat     \aliased\let\normalwidehat  \widehat
% \aliased\let\normalcheck\check
% \aliased\let\normalbreve\breve
% \aliased\let\normaldot  \dot
% \aliased\let\normalring \ring
% \aliased\let\normaltilde\tilde
% \aliased\let\normaldddot\dddot

\pushoverloadmode

% These retain the given unicode values ... but can stretch when configured
% to do so: \setupmathaccent[\v!top][\c!scale=\v!yes]

% Extended/modified below
%
% \definemathtopaccent[\v!top][grave]["0060] % these are old school
% \definemathtopaccent[\v!top][ddot] ["00A8]
% \definemathtopaccent[\v!top][bar]  ["00AF]
% \definemathtopaccent[\v!top][acute]["00B4]
% \definemathtopaccent[\v!top][hat]  ["02C6]
% \definemathtopaccent[\v!top][check]["02C7]
% \definemathtopaccent[\v!top][breve]["02D8]
% \definemathtopaccent[\v!top][dot]  ["02D9]
% \definemathtopaccent[\v!top][ring] ["02DA]
% \definemathtopaccent[\v!top][tilde]["02DC]
% \definemathtopaccent[\v!top][dddot]["20DB]

\definemathtopaccent[\v!top][grave]   ["0300]
\definemathtopaccent[\v!top][acute]   ["0301]
\definemathtopaccent[\v!top][hat]     ["0302]
\definemathtopaccent[\v!top][tilde]   ["0303]
\definemathtopaccent[\v!top][bar]     ["0305]
%definemathtopaccent[\v!top][overbar] ["0305]% We expect overbar to stretch, so later
\definemathtopaccent[\v!top][breve]   ["0306]
\definemathtopaccent[\v!top][dot]     ["0307]
\definemathtopaccent[\v!top][ddot]    ["0308]
\definemathtopaccent[\v!top][overhook]["0309]
\definemathtopaccent[\v!top][ring]    ["030A]
\definemathtopaccent[\v!top][check]   ["030C]

% Here starts the weird unicode ones

%definemathtopaccent[\v!top][candra]               ["0310]
%definemathtopaccent[\v!top][overturnedcomma]      ["0312]
%definemathtopaccent[\v!top][overcommatopright]    ["0315]
%definemathtopaccent[\v!top][leftangleabove]       ["031A]
\definemathtopaccent[\v!top][overleftharpoon]      ["20D0]
\definemathtopaccent[\v!top][overrightharpoon]     ["20D1]
%definemathtopaccent[\v!top][verticaloverlayaccent]["20D2]
%definemathtopaccent[\v!top][vec]                  ["20D7]% We expect vec to stretch, so later
\definemathtopaccent[\v!top][dddot]                ["20DB]
\definemathtopaccent[\v!top][ddddot]               ["20DC]
%definemathtopaccent[\v!top][annuityaccent]        ["20E7]
%definemathtopaccent[\v!top][overbracketaccent]    ["20E9]
%definemathtopaccent[\v!top][asterixaccent]        ["20F0]

% Weird ones (why no single and double underdots in unicode?)

%definemathbottomaccent[\v!bottom][underdot]  ["0323]%Conflicting
%definemathbottomaccent[\v!bottom][underddot] ["0324]
%definemathbottomaccent[\v!bottom][underdddot]["20E8]

\definemathaccent
  [\v!top:\v!stretch]
  [\v!top]
  [\c!scale=\v!keep,\c!stretch=\v!yes,\c!shrink=\v!yes]

\definemathaccent
  [\v!bottom:\v!stretch]
  [\v!bottom]
  [\c!scale=\v!keep,\c!stretch=\v!yes,\c!shrink=\v!yes]

\definemathaccent
  [\v!both:\v!stretch]
  [\v!both]
  [\c!scale=\v!keep,\c!stretch=\v!yes,\c!shrink=\v!yes]

\definemathaccent
  [\v!top:\v!dot]
  [\v!top:\v!stretch]
  [i=]

%D We have a problem. We can use stackers but then we need to adapt the dimensions
%D which is font dependent. So, for now we keep them as accents.

\definemathtopaccent[\v!top:\v!stretch][widegrave]["0300] % these are generic modern
\definemathtopaccent[\v!top:\v!stretch][wideacute]["0301]
\definemathtopaccent[\v!top:\v!stretch][widehat]  ["0302]
\definemathtopaccent[\v!top:\v!stretch][widetilde]["0303]
\definemathtopaccent[\v!top:\v!stretch][widebar]  ["0305]% (not 304, the caret)
\definemathtopaccent[\v!top:\v!stretch][widebreve]["0306]
\definemathtopaccent[\v!top:\v!stretch][widedot]  ["0307]
\definemathtopaccent[\v!top:\v!stretch][wideddot] ["0308]
\definemathtopaccent[\v!top:\v!stretch][widering] ["030A]
\definemathtopaccent[\v!top:\v!stretch][widecheck]["030C]
\definemathtopaccent[\v!top:\v!stretch][widedddot]["20DB]

\definemathtopaccent[\v!top:\v!stretch][cev]["20D6] % clumsy notation for vectors
\definemathtopaccent[\v!top:\v!stretch][vec]["20D7] % clumsy notation for vectors

\definemathtopaccent[\v!top:\v!stretch][wideoverleftharpoon]   ["20D0]
\definemathtopaccent[\v!top:\v!stretch][wideoverrightharpoon]  ["20D1]
\definemathtopaccent[\v!top:\v!stretch][wideoverleftarrow]     ["20D6]
\definemathtopaccent[\v!top:\v!stretch][wideoverrightarrow]    ["20D7]
\definemathtopaccent[\v!top:\v!stretch][wideoverleftrightarrow]["20E1]

\definemathbottomaccent[\v!bottom:\v!stretch][wideundertilde]         ["0330]
\definemathbottomaccent[\v!bottom:\v!stretch][wideunderbar]           ["0332]
\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftrightarrow]["034D] % weird code
\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightharpoon]  ["20EC]
\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftharpoon]   ["20ED]
\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftarrow]     ["20EE]
\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightarrow]    ["20EF]

% For complex conjugate: i below keeps the dot
%
% \im { \widebar  {\cos\theta + \ii \sin\theta} = \cos\theta - \ii\sin\theta }\par
% \im { \conjugate{\cos\theta + \ii \sin\theta} = \cos\theta - \ii\sin\theta }

\definemathtopaccent[\v!top:\v!dot][conjugate]["0305]
\definemathtopaccent[\v!top:\v!dot][closure]  ["0305]
\definemathtopaccent[\v!top:\v!dot][conjugate]["0305]

\aliased\let\mathring\ring % for a while

% \permanent\protected\def\not#1{\Umathaccent class \mathordinarycode exact overlay 0 0 "338 {#1}}
% \permanent\protected\def\not#1{\Umathaccent class \mathrelationcode exact overlay 0 0 "338 {#1}}
% \permanent\protected\def\not#1{\Umathaccent class \mathbinarycode   exact overlay 0 0 "338 {#1}}
%
% \definemathcommand[slashD][ordinary]{\Umathaccent class \mathordinarycode exact  overlay 0 0 "338 {D}}
% \definemathcommand[slashD][ordinary]{\Umathaccent class \mathordinarycode center overlay 0 0 "338 {D}}

\permanent\tolerant\protected\def\slashed[#1]#:#2%
  {\Umathaccent
     \usedcolorparameterattributes{\mathaccentparameter\c!symbolcolor}%
     \s!class  \mathcodechecked{#1}%
     \s!center \relaxedspace
     \s!overlay\relaxedspace
     \zerocount \zerocount \forwardslashasciicode
   {\usemathaccentcolorparameter\c!textcolor
    #2}} % exact when =

% \definemathcommand[slashD]{\slashed[ordinary]{D}}
% \definemathcommand[slashD]{\slashed{D}}

\popoverloadmode

\protect \endinput
