% This is the file dblaccnt.tex which implements support for multiple
% accents.
%
% written by Frank Mittelbach <frank.mittelbach@latex-project.org>
%
% slightly corrected and formatted by Werner Lemberg <wl@gnu.org>
%
%
% The code below handles only the case of
%
% \acc1 \acc2 ... glyph
%
% with or without nesting braces.
%
% \acc1 {\acc2 a}
%
% etc. will be handled correctly by removing the brace group during
% the scanning process.  This means in particular that conceptually
% any accent command can only handle single token arguments!
%
% It should also work for combinations generated from inputenc, i.e.,
% are presented as 8bit tokens or, after passing through something like
% an .aux file, as \IeC{\acc1} \IeC{\acc2} ...

\ProvidesPackage{dblaccnt}[2000/01/28 v1.0 double accent support]

\endlinechar \m@ne


% We must redefine two internal LaTeX commands to provide hooks for
% assembling accents.

% Here we test whether #1 (the command to be executed) is \chardef or
% #3 (the encoding) is `?'.  If both are false, \assemble@accent@cmds
% will be used.
%
% The first case catches \DeclareTextSymbol, the second catches
% \ProvideTextCommandDefault.  Both checks are ugly hacks which hopefully
% disappear in the near future.
%
\def\@dec@text@cmd#1#2#3{
  \ifx#1\chardef
    \expandafter\def\expandafter#2\expandafter{
      \csname#3-cmd\expandafter\endcsname
      \expandafter#2
      \csname#3\string#2\endcsname
    }
  \else
    \if#3?
      \expandafter\def\expandafter#2\expandafter{
        \csname#3-cmd\expandafter\endcsname
        \expandafter#2
        \csname#3\string#2\endcsname
      }
    \else
      \expandafter\def\expandafter#2\expandafter{
        % start looking for acc tokens
        \expandafter\assemble@accent@cmds
        \csname#3-cmd\expandafter\endcsname
        \expandafter#2
        \csname#3\string#2\endcsname
      }
    \fi
  \fi
  \let\@ifdefinable\@rc@ifdefinable
  \expandafter#1\csname#3\string#2\endcsname
}


% The redefined \@tabacckludge macro below assures that the top-level
% definition of the accents (which contains \assemble@accent@cmds)
% will be called.
%
\def\@make@tabacc#1#2{
  \expandafter\def\csname @tabacc\string#1\endcsname{#2}
}

\@make@tabacc{'}{\@acci}
\@make@tabacc{`}{\@accii}
\@make@tabacc{=}{\@acciii}


% Here the redefinition of second internal LaTeX macro.
%
\def\@tabacckludge#1{
  \csname @tabacc\string#1\endcsname
}

 
% We only look ahead for further accents if we are to typeset.
%
\def\assemble@accent@cmds{
  \ifx\protect\@typeset@protect
    \expandafter\assemble@tokensinit
  \fi
}


% The init is special as we have to parse over some of the expansion
% of the encoding specific command; for example, \^ might expand to
%
%   \assemble@accent@cmds \OT1-cmd \^ \OT1\^
%                                     ^^^^^^ one token
%
% We start \assemble@tokens with the number of hits so far (\@empty),
% zero the actual code for the current, e.g., \OT1\^ in the above
% example (resp. the corresponding macro in the current font
% encoding), and as a third argument we will pick up the next token
% or group in the input stream for testing.
%
\def\assemble@tokensinit#1#2#3{
  % the usual test for availability in the current encoding
  % similar to the test in \@changed@cmd
  \@inmathwarn#2
  \expandafter\ifx\csname\cf@encoding\string#2\endcsname\relax
    \expandafter\ifx\csname ?\string#2\endcsname\relax
      \expandafter\def\csname ?\string#2\endcsname{
        \TextSymbolUnavailable#2
      }
    \fi
    \global\expandafter\let
     \csname\cf@encoding \string#2\expandafter\endcsname
     \csname ?\string#2\endcsname
  \fi

  % here we substitute the current encoding
  \expandafter\assemble@tokens@\expandafter\@empty
    \csname\cf@encoding\string#2\endcsname
}


% The next commands should be considered only as a proof of concept
% -- they can most certainly be streamlined.  Here is roughly what
% they do:
%
% \assemble@tokens: If the picked up token is \IeC then get rid of it
%   and parse the next token (or group) which is expected to be the
%   argument of \IeC.  This is done by restarting the whole process.
%   Otherwise we have to figure out if the current token (#3) is an
%   8-bit from inputenc, i.e., expanding to \IeC{...}.  This is
%   handled by calling \assemble@tokensz passing an expansion of #3
%   as well as #3 (or more exactly, its first token since the braces
%   get removed in this process) itself.
%
% \assemble@tokensz: Test if the expansion start with \IeC in which
%   case it is assumed that it comes from an inputenc 8bit; the next
%   token will be considered as its argument and used for further
%   processing in \assemble@tokensx.  Otherwise the unexpanded #3
%   from above is used.
%
% \assemble@tokensx: If this cmd is called its third argument should
%   contain a normalized token from the input stream, i.e.
%
%     {..}      -> ..
%     \IeC{..}  -> ..
%     ^^xx (expanding to) \IeC{..}  -> ..
%
% Now all :-) that remains is testing whether the expansion of this
% token starts with \assemble@accent@cmds, since in this case we have
% found another accent cmd.
%
% #1 is the number of hits, #2 is the real definition in that
% encoding, and #3 is the next token (or group).
%
% The macros \assemble@tokens@ and \assemble@tokens@@ are
% intermediate steps to test whether #3 is empty; if yes, we simply
% expand #2.
%
\def\assemble@tokens@#1#2#3{
  \assemble@tokens@@{#1}{#2}{#3}{#3\@empty}
}

\def\assemble@tokens@@#1#2#3#4{
  \ifx#4\@empty
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {#2{}}
  {\assemble@tokens{#1}{#2}{#3}}
}

\def\assemble@tokens#1#2#3{
  \ifx\IeC#3
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  % try again but pick up argument of \IeC
  {\assemble@tokens@{#1}{#2}}
  % this will get rid of a group argument -- nasty :-)
  {\expandafter\assemble@tokensz#3\relax\assemble@tokensz{#1}{#2}#3}
}

\def\assemble@tokensz#1#2\assemble@tokensz#3#4#5{
  \ifx#1\IeC
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\assemble@tokensx{#3}{#4}#2}
  {\assemble@tokensx{#3}{#4}#5}
}

% \assemble@tokensx: This passes an expanded and unexpanded version
%   of #3 to \ifassemble@tokens to do the actual processing.
%
% \ifassemble@tokens: If we have found another accent command then
%   keep its name and record that we had another hit and restart the
%   scanning via \assemble@tokens, i.e., we append an `x' to the
%   ``hit'' argument that we carry around for no good reason, and we
%   append the official name of the accent command (which was picked
%   up as part of the expansion of the input token) to the argument,
%   storing the list of accents found so far.  Note that we do use
%   the official name, e.g. `\"', not `\OT1\"' -- the latter is only
%   used for the very first accent!
%
% If it turns out that we don't have an accent command here it is
% time to stop the scanning and do some processing.  Now finally the
% ``hit'' argument and the list of collected accents comes into play:
% We construct a command which name consists of the string
% ``handle@accent'', followed by a number of `x's each for each hit
% earlier on.  Thus in a situation like \"\^a we would execute
% \handle@accentx and in case of \"a \handle@accent.  This command
% gets as its arguments the collected accents followed by the token
% which stopped the scanning proccess, e.g.
%
%   \handle@accentx \OT1\" \^ {a}
%
% and its purpose is to determine how to produce a glyph from it
% (e.g. as a composite or as a part composite or ...)
%
\def\assemble@tokensx#1#2#3{
  \expandafter
   \ifassemble@tokens#3\@empty\@empty\@empty\ifassemble@tokens{#1}{#2}{#3}}

\def\ifassemble@tokens#1#2#3#4\ifassemble@tokens#5#6#7{
  % next token was defined via \DeclareText...
  \ifx#1\assemble@accent@cmds
    % thus #3 is its official name
    \expandafter\assemble@tokens@
  \else
    % execute what has been assembled and exit
    \csname handle@accent#5\endcsname#6{#7}
    \expandafter\@gobbletwo
  \fi
  % first two args to \assemble@tokens on next pass
  {#5x}{#6#3}
}


% Depending on the number of accents found, \handle@accent[x[x]] will
% be called.

% ONLY ONE: We check whether \#1-#2 is a known command (a composite)
% and execute it, otherwise try to execute #1{#2} as an accent
% command.
%
\def\handle@accent#1#2{
  \expandafter\ifx\csname\string#1-\string#2\endcsname\relax
    #1{#2}
  \else
    \csname\string#1-\string#2\endcsname
  \fi
}

% TWO IN A ROW: We check for \#1-#2-#3.  If undefined, we apply #1 to
% whatever is the result of #2{#3}.  One could think of a more
% complex algorithm here, e.g., if #1-#2 is known as a composite
% modifier (whatever that is) apply that before trying the above but
% this is probably not necessary.
%
\def\handle@accentx#1#2#3{
  \expandafter\ifx\csname\string#1-\string#2-\string#3\endcsname\relax
    #1{#2{#3}}
  \else
    \csname\string#1-\string#2-\string#3\endcsname
  \fi
}

% MORE THAN TWO: (Not handled so far.)  If there are more than three,
% then the parsing will die at some point when \handle@accentxx...
% will turn out to be \relax, and then one accent will become an
% argument of another -- too bad.
%
\def\handle@accentxx#1#2#3#4{
  % catch more than two accents in a row
  \errmessage{Too many accents, dropping first}
  #2#3#4
}


% This is simpler now.
%
\def\DeclareTextCompositeCommand#1#2#3#4{
  \expandafter\def\csname\expandafter\string\csname
    #2\endcsname\string#1-\string#3\endcsname{#4}
}

% This is new.
%
\def\DeclareTextDoubleCompositeCommand#1#2#3#4#5{
  \expandafter\def\csname\expandafter\string\csname
    #2\endcsname\string#1-\string#3-\string#4\endcsname{#5}
}

% This also.
%
\catcode\z@=11\relax
\def\DeclareTextDoubleComposite#1#2#3#4#5{
  \def\reserved@a{\DeclareTextDoubleCompositeCommand#1{#2}{#3}{#4}}
  \bgroup
    \lccode\z@#5
    \lowercase{
  \egroup
    \reserved@a ^^@}
}
\catcode\z@=15\relax


% Now we reinitialize the \@acc... macros to use our new definitions.
%
\AtBeginDocument{
  \let\@acci \'
  \let\@accii \`
  \let\@acciii \=
}


\endlinechar `\^^M

\endinput

% end of dblaccnt.tex
