%%
%% This is file `pdfmathaccents.sty'.
%%
%% Copyright 2026 Joris Pinkse
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either
%% version 1.3c of this license or (at your option) any later
%% version. The latest version of this license is in
%%    https://www.latex-project.org/lppl.txt
%% and version 1.3c or later is part of all distributions of
%% LaTeX version 2008 or later.
%%
%% This work has the LPPL maintenance status `maintained'.
%% The Current Maintainer of this work is Joris Pinkse.
%%
%% This work consists of the files pdfmathaccents.sty,
%% pdfmathaccents-doc.tex, and pdfmathaccents-doc.pdf.
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{pdfmathaccents}%
  [2026/07/27 v1.0 Unicode combining accents in math input (pdfTeX)]

% Under any engine other than pdfTeX, stop the run immediately: math
% material that relies on this package would otherwise be typeset as
% garbage (combining characters passed through to the fonts).
\RequirePackage{iftex}
\ifPDFTeX
\else
  \PackageError{pdfmathaccents}
    {pdfLaTeX is required; the run will now end}
    {pdfmathaccents works only with pdfLaTeX. With LuaLaTeX, use the
     companion package luamathaccents instead.}%
  \expandafter\@@end
\fi

% pdfTeX cannot rewrite the input line the way LuaTeX does, so this
% package works at the token level instead: every ASCII letter and
% digit is given mathcode "8000, which makes it act as an active
% character in math mode (the technique used by, e.g., icomma).  Its
% definition looks ahead one token.  If that token is the lead byte of
% the UTF-8 encoding of a supported combining character (0xCC for
% U+0300--U+033F, 0xE2 for U+2000--U+2FFF), the character's bytes are
% absorbed and the corresponding accent command is applied to the base
% character; otherwise the base character is typeset with its original
% mathcode, saved at load time, and nothing else changes.

% The lead bytes as they are tokenized in the document (active
% characters under standard UTF-8 input handling).
\let\pdfMA@byteCC= ^^cc%
\let\pdfMA@byteEtwo= ^^e2%

% The active definition of a base character starts with \bgroup so
% that after ^ or _ the whole construction is read as one math field;
% the group also keeps all assignments below local.  Every path
% through the machinery closes the group with \egroup.
\def\pdfMA@base#1{%
  \expandafter\let\expandafter\pdfMA@cur
    \csname pdfMA@mc@\string#1\endcsname
  \futurelet\pdfMA@next\pdfMA@check}

\def\pdfMA@check{%
  \ifx\pdfMA@next\pdfMA@byteCC
    \let\pdfMA@next@\pdfMA@two
  \else\ifx\pdfMA@next\pdfMA@byteEtwo
    \let\pdfMA@next@\pdfMA@three
  \else
    \let\pdfMA@next@\pdfMA@done
  \fi\fi
  \pdfMA@next@}

\def\pdfMA@done{\pdfMA@cur\egroup}

% #1#2 (#1#2#3) are the bytes of one UTF-8 character.  A supported
% combining character becomes its accent command applied to the base
% character; anything else is put back so that it is handled exactly
% as it would be without this package.
\def\pdfMA@two#1#2{%
  \ifcsname pdfMA@u@\string#1\string#2\endcsname
    \csname pdfMA@u@\string#1\string#2\endcsname{\pdfMA@cur}%
  \else
    \pdfMA@cur#1#2%
  \fi
  \egroup}

\def\pdfMA@three#1#2#3{%
  \ifcsname pdfMA@u@\string#1\string#2\string#3\endcsname
    \csname pdfMA@u@\string#1\string#2\string#3\endcsname{\pdfMA@cur}%
  \else
    \pdfMA@cur#1#2#3%
  \fi
  \egroup}

\def\pdfMA@map#1#2#3{%
  \expandafter\def\csname pdfMA@u@\string#1\string#2\endcsname{#3}}
\def\pdfMA@mapiii#1#2#3#4{%
  \expandafter\def
    \csname pdfMA@u@\string#1\string#2\string#3\endcsname{#4}}

\pdfMA@map ^^cc^^80{\grave}     % U+0300 combining grave accent
\pdfMA@map ^^cc^^81{\acute}     % U+0301 combining acute accent
\pdfMA@map ^^cc^^82{\hat}       % U+0302 combining circumflex accent
\pdfMA@map ^^cc^^83{\tilde}     % U+0303 combining tilde
\pdfMA@map ^^cc^^84{\bar}       % U+0304 combining macron
\pdfMA@map ^^cc^^85{\bar}       % U+0305 combining overline
\pdfMA@map ^^cc^^86{\breve}     % U+0306 combining breve
\pdfMA@map ^^cc^^87{\dot}       % U+0307 combining dot above
\pdfMA@map ^^cc^^88{\ddot}      % U+0308 combining diaeresis
\pdfMA@map ^^cc^^8a{\mathring}  % U+030A combining ring above
\pdfMA@map ^^cc^^8c{\check}     % U+030C combining caron
\pdfMA@map ^^cc^^b1{\underline} % U+0331 combining macron below
\pdfMA@mapiii ^^e2^^83^^96{\overleftarrow} % U+20D6 combining left arrow above
\pdfMA@mapiii ^^e2^^83^^97{\vec}           % U+20D7 combining right arrow above
\AtBeginDocument{%
  \ifdefined\dddot
    \pdfMA@mapiii ^^e2^^83^^9b{\dddot}% U+20DB combining three dots above
  \fi
  \ifdefined\overleftrightarrow
    \pdfMA@mapiii ^^e2^^83^^a1{\overleftrightarrow}% U+20E1
  \fi}

% Precomposed (NFC) characters, such as U+0177 (y with circumflex),
% cannot be recognized by the look-ahead machinery: they arrive as a
% single character, with no separate base letter in front of them.  In
% math mode they end in one of two kernel error paths, neither of
% which mentions the actual problem.  A character known to the
% inputenc machinery applies its text accent command, which fails with
% "Please use \mathaccent"; an unknown character reports "not set up
% for use with LaTeX".  Wrap both paths so that a warning naming NFC
% normalization precedes the error.  Both macros are kernel internals,
% so they are wrapped only if they exist.
\def\pdfMA@nfc@hint{%
  \PackageWarning{pdfmathaccents}
    {A text accent appeared in math mode. The input probably
     contains a precomposed (NFC) accented character;
     pdfmathaccents recognizes only decomposed base+combining
     (NFD) sequences. Your editor may have normalized the file}}
\ifdefined\@inmathwarn
  \let\pdfMA@inmathwarn\@inmathwarn
  \def\@inmathwarn#1{%
    \ifmmode
      \in@{#1}{\`\'\^\~\=\u\.\"\r\v}%
      \ifin@\pdfMA@nfc@hint\fi
    \fi
    \pdfMA@inmathwarn#1}
\fi
\ifdefined\UTFviii@undefined@err
  \let\pdfMA@undefinederr\UTFviii@undefined@err
  \def\UTFviii@undefined@err#1{%
    \ifmmode
      \PackageWarning{pdfmathaccents}
        {If the character reported below is an accented letter, it
         is precomposed (NFC); pdfmathaccents recognizes only
         decomposed base+combining (NFD) sequences. Your editor may
         have normalized the file}%
    \fi
    \pdfMA@undefinederr{#1}}
\fi

% Make each base character math-active, saving its original mathcode.
% Characters that are already math-active (claimed by another package)
% are left alone.
\def\pdfMA@bases{abcdefghijklmnopqrstuvwxyz%
  ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789}

\def\pdfMA@activate#1{%
  \ifnum\mathcode`#1="8000\relax
  \else
    \expandafter\mathchardef\csname pdfMA@mc@\string#1\endcsname
      \mathcode`#1\relax
    \begingroup
      \lccode`\~=`#1\relax
      \lowercase{\endgroup\def~}{\bgroup\pdfMA@base#1}%
  \fi}
\def\pdfMA@doactivate#1{%
  \ifx\relax#1\else
    \pdfMA@activate#1%
    \expandafter\pdfMA@doactivate
  \fi}
\expandafter\pdfMA@doactivate\pdfMA@bases\relax

\def\pdfMA@on#1{%
  \ifx\relax#1\else
    \ifcsname pdfMA@mc@\string#1\endcsname
      \mathcode`#1="8000\relax
    \fi
    \expandafter\pdfMA@on
  \fi}
\def\pdfMA@off#1{%
  \ifx\relax#1\else
    \ifcsname pdfMA@mc@\string#1\endcsname
      \mathcode`#1=\csname pdfMA@mc@\string#1\endcsname
    \fi
    \expandafter\pdfMA@off
  \fi}

\newcommand*\PdfMathAccentsOn{\expandafter\pdfMA@on\pdfMA@bases\relax}
\newcommand*\PdfMathAccentsOff{\expandafter\pdfMA@off\pdfMA@bases\relax}

\PdfMathAccentsOn

\endinput
%%
%% End of file `pdfmathaccents.sty'.
