% --------------------------------------------------------------------------
% the CNTFORMATS package
% 
%   A different way to read counters
%
% This package is part of the exsheets bundle
% --------------------------------------------------------------------------
% Clemens Niederberger
% Web:    https://bitbucket.org/cgnieder/exsheets/
% E-Mail: contact@mychemistry.eu
% --------------------------------------------------------------------------
% Copyright 2012 Clemens Niederberger
% 
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
% 
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Clemens Niederberger.
% --------------------------------------------------------------------------
% The cntformats package consists of the files
%  - cntformats.sty
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
\def\@cntfmts@date{2012/11/08}
\def\@cntfmts@version{v0.4}

\ProvidesPackage{cntformats}[\@cntfmts@date\space \@cntfmts@version\space A different way to read counters.]
\RequirePackage{etoolbox}
% --------------------------------------------------------------------------
% message handling
\def\@cntfmts@error@message{%
  For details have a look at the `exsheets' manual.}

\def\@cntfmts@create@message#1{%
  \ifstrequal{#1}{Error}
    {%
      \lowercase{\csdef{@cntfmts@#1}}##1{%
        \csuse{Package#1}{cntformats}{##1}{\@cntfmts@error@message}}%
    }{%
      \lowercase{\csdef{@cntfmts@#1}}##1{%
        \csuse{Package#1}{cntformats}{##1}}%
    }}
\@cntfmts@create@message{Error}
\@cntfmts@create@message{Warning}
\@cntfmts@create@message{WarningNoLine}
\@cntfmts@create@message{Info}

\def\@cntfmts@err@already@defined#1{%
  \@cntfmts@error{The counter `#1' already exists!}}
\def\@cntfmts@err@unknown@counter#1{%
  \@cntfmts@error{The counter `#1' is undefined!}}
\def\@cntfmts@err@pattern@defined#1#2{%
  \@cntfmts@error{The pattern `#2' for module `#1' is already defined!}}
\def\@cntfmts@err@pattern@undefined#1#2{%
  \@cntfmts@error{The pattern `#2' for module `#1' is undefined!}}

% ----------------------------------------------------------------------------
% tokenlist analyzing and manipulating
%   if you happen to read this code and notice some obvious reasons why these
%   macros shoudn't be used like this, please send me your improved version
%   (seriously! But please explain why yours is better)
\def\ifintl#1#2{%
  \def\@cntfmts@intl@tmpa##1#2{}%
  \expandafter\if\expandafter\relax\expandafter
  \detokenize\expandafter{\@cntfmts@intl@tmpa#1{}{}#2}\relax%
    \expandafter\@secondoftwo
  \else
    \expandafter\@firstoftwo
  \fi
}
\def\ifintlcs#1{%
  \expandafter\ifintl\expandafter{#1}}

\long\def\replaceonceincs#1#2#3{%
  \ifintlcs#1{#2}%
    {\@cntfmts@replace@once@incs#1{#2}{#3}}{}%
}
\long\def\@cntfmts@replace@once@incs#1#2#3{%
  \def\@cntfmts@replo@tmpa##1#2##2\q@stop{%
    \def#1{##1#3##2}}%
  \expandafter\@cntfmts@replo@tmpa#1\q@stop
}

\long\def\replaceallin#1#2#3{%
  \def\@cntfmts@repla@tmpa{#1}%
  \replaceonceincs\@cntfmts@repla@tmpa{#2}{#3}%
  \ifintlcs\@cntfmts@repla@tmpa{#2}%
    {\expandafter\replaceallin\expandafter{\@cntfmts@repla@tmpa}{#2}{#3}}%
    {\expandonce\@cntfmts@repla@tmpa}%
}
\long\def\replaceallincs#1#2#3{%
  \replaceonceincs#1{#2}{#3}%
  \ifintlcs#1{#2}{\replaceallincs#1{#2}{#3}}{}%
}

% ----------------------------------------------------------------------------
% expansion tools
%   heavily inspired by expl3's \exp_args:N<spec>
\long\def\@cntfmts@getnextbraced#1#2#3{#2\@cntfmts@firstofone{#3{#1}}}
\long\def\@cntfmts@firstofone#1{#1}
\long\def\@cntfmts@braced@unexpanded#1\@cntfmts@firstofone#2#3{%
  #1\@cntfmts@firstofone{#2{#3}}}
\long\def\@cntfmts@braced@expandedonce#1\@cntfmts@firstofone#2#3{%
  \expandafter\@cntfmts@getnextbraced\expandafter{#3}{#1}{#2}}

\long\def\@cntfmts@expand@first{%
  \@cntfmts@braced@expandedonce
  \@cntfmts@firstofone}

\long\def\@cntfmts@expand@second{%
  \@cntfmts@braced@unexpanded
  \@cntfmts@braced@expandedonce
  \@cntfmts@firstofone}

\long\def\@cntfmts@expand@third{%
  \@cntfmts@braced@unexpanded
  \@cntfmts@braced@unexpanded
  \@cntfmts@braced@expandedonce
  \@cntfmts@firstofone}

% ----------------------------------------------------------------------------
% expandable commands with optional argument (and no mandatory)
%   this is probably not very robust. If you know what you're doing you're
%   probably able to define a better version yourself. If not, don't use it
\long\def\@cntfmts@isopt@#1[#2\q@marker#3#{%
  \if\relax\detokenize{#1#2}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}
\long\def\@cntfmts@isopt#1#2#3{%
  \@cntfmts@isopt@#1\q@marker[\q@marker{#2#1}{#2[{#3}]{#1}}}

\long\def\@cntfmts@defwopt#1[#2]#3{%
  \long\def#1##1{\@cntfmts@isopt{##1}{\csuse{\@cntfmts@strip@bs#1@opt}}{#2}}%
  \long\csdef{\@cntfmts@strip@bs#1@opt}[##1]{#3}}

\def\@cntfmts@strip@bs{\expandafter\@gobble\string}

% ----------------------------------------------------------------------------
% #1: module
% #2: counter
\def\@cntfmts@def@counter@read#1#2#3{%
  \@cntfmts@expand@second\csdef
    {@#1@read@#3@counter}%
    {\csname @#1@read@#2@counter\endcsname}}

% create pattern for an existing counter:
% #1: module
% #2: counter
% #3: id
\newcommand*\@cntfmts@add@counter@pattern[3][cntfmts]{%
  \ifcsdef{the#2}
    {}{\@cntfmts@err@unknown@counter{#2}}%
  \ifcsdef{@#1@#2@counter}
    {\@cntfmts@err@pattern@defined{#1}{#2}}
    {\csdef{@#1@#2@counter}{}}%
  \listcsadd{@#1@counter@ids}{#3}%
  \@cntfmts@def@counter@read{#1}{#2}{#3}%
}

\newcommand*\@cntfmts@add@counter@pattern@nostar[3][cntfmts]{%
  \@cntfmts@add@counter@pattern[#1]{#2}{#3}%
  \@cntfmts@expand@third
    \@cntfmts@create@read@counter{#1}{#2}{\csname c@#2\endcsname}}

\newrobustcmd*\AddCounterPattern{%
  \@ifstar
    {\@cntfmts@add@counter@pattern}
    {\@cntfmts@add@counter@pattern@nostar}}
\@onlypreamble\AddCounterPattern

% create pattern for a new counter
% #1: counter
% #2: id
\newcommand*\@cntfmts@new@counter@pattern[3][cntfmts]{%
  \ifcsdef{the#2}
    {\@cntfmts@err@counter@defined{#2}}{}%
  \newcounter{#2}%
  \listcsadd{@#1@counter@ids}{#3}%
  \@cntfmts@def@counter@read{#1}{#2}{#3}%
  \csdef{@#1@#2@counter}{}
}

\newcommand*\@cntfmts@new@counter@pattern@nostar[3][cntfmts]{%
  \@cntfmts@new@counter@pattern[#1]{#2}{#3}%
  \@cntfmts@expand@third
    \@cntfmts@create@read@counter{#1}{#2}{\csname c@#2\endcsname}}

\newrobustcmd*\NewCounterPattern{%
  \@ifstar
    {\@cntfmts@new@counter@pattern}
    {\@cntfmts@new@counter@pattern@nostar}}
\@onlypreamble\NewCounterPattern

% renew pattern:
\newcommand*\@cntfmts@renew@counter@pattern[3][cntfmts]{%
  \ifcsdef{the#2}
    {}{\@cntfmts@err@unknown@counter{#2}}%
  \ifcsdef{@#1@#2@counter}{}
    {\@cntfmts@err@pattern@undefined{#1}{#2}}%
  \ifinlistcs{@#1@counter@ids}{#3}
    {}{\listcsadd{@#1@counter@ids}{#3}}%
  \@cntfmts@def@counter@read{#1}{#2}{#3}%
}

\newcommand*\@cntfmts@renew@counter@pattern@nostar[3][cntfmts]{%
  \@cntfmts@renew@counter@pattern[#1]{#2}{#3}%
  \@cntfmts@expand@third
    \@cntfmts@create@read@counter{#1}{#2}{\csname c@#2\endcsname}}

\newrobustcmd\RenewCounterPattern{%
  \@ifstar
    {\@cntfmts@renew@counter@pattern}
    {\@cntfmts@renew@counter@pattern@nostar}}
\@onlypreamble\RenewCounterPattern

% ----------------------------------------------------------------------------
% assign a different internal command to <counter> than \c@<counter>
% can/must be used after a call from \AddCounterPattern* or
% \NewCounterPattern*
% #1: module
% #2: counter
% #3: internal command
\def\@cntfmts@create@read@counter#1#2#3{%
  \expandafter\@cntfmts@defwopt\csname @#1@read@#2@counter\endcsname[]{%
    \ifblank{##1}
      {\@arabic{#3}}
      {\csuse{@cntfmts@counter@type@##1}{#3}}%
  }%
}

\newrobustcmd*\ReadCounterFrom[3][cntfmts]{%
  \@cntfmts@create@read@counter{#1}{#2}{#3}}

% ----------------------------------------------------------------------------
% pattern formats
% #1: key
% #2: number presentation command like \@alph
\def\@cntfmts@new@pattern@format#1#2{%
  \csdef{@cntfmts@counter@type@#1}{#2}}

\newrobustcmd*\NewPatternFormat[2]{%
  \@cntfmts@new@pattern@format{#1}{#2}}
\@onlypreamble\NewPatternFormat

% ----------------------------------------------------------------------------
% interpret and print pattern:
% #1: module
% #2: list
% #3: pattern
\def\@cntfmts@read@counter@pattern#1#2#3{%
  \def\@cntfmts@parsed@pattern{#3\relax}%
  \forlistcsloop{\@cntfmts@replace@pattern{#1}}{#2}%
}
% #1: module
% #2: pattern-key
\def\@cntfmts@replace@pattern#1#2{%
  \replaceallincs\@cntfmts@parsed@pattern
    {#2}{{}\csuse{@#1@read@#2@counter}}}

\newrobustcmd*\ReadCounterPattern[2][cntfmts]{%
  \@cntfmts@read@counter@pattern{#1}{@#1@counter@ids}{#2}\@cntfmts@parsed@pattern}

\newrobustcmd*\ReadCounterPatternFrom[2][cntfmts]{%
  \@cntfmts@expand@third\@cntfmts@read@counter@pattern{#1}{@#1@counter@ids}{#2}%
  \@cntfmts@parsed@pattern}

% #1: save pattern in
% #2: save interpretation in
% #3: pattern
% #4: module
\newcommand*\@cntfmts@save@counter@pattern[4]{%
  \@cntfmts@read@counter@pattern{#4}{@#4@counter@ids}{#3}%
  \let#2\@cntfmts@parsed@pattern
  \def#1{#3}%
}

\newcommand*\@cntfmts@esave@counter@pattern[4]{%
  \@cntfmts@read@counter@pattern{#4}{@#4@counter@ids}{#3}%
  \edef#2{\@cntfmts@parsed@pattern}%
  \def#1{#3}%
}

\newrobustcmd*\SaveCounterPattern[4][cntfmts]{%
  \@cntfmts@save@counter@pattern{#2}{#3}{#4}{#1}}

\newrobustcmd*\SaveCounterPatternFrom[4][cntfmts]{%
  \@cntfmts@expand@third\@cntfmts@save@counter@pattern{#2}{#3}{#4}{#1}}

\newrobustcmd*\eSaveCounterPattern[4][cntfmts]{%
  \@cntfmts@esave@counter@pattern{#2}{#3}{#4}{#1}}

\newrobustcmd*\eSaveCounterPatternFrom[4][cntfmts]{%
  \@cntfmts@expand@third\@cntfmts@esave@counter@pattern{#2}{#3}{#4}{#1}}

% ----------------------------------------------------------------------------
% predefined formats and pattern
\NewPatternFormat{a}{\@alph}
\NewPatternFormat{A}{\@Alph}
\NewPatternFormat{1}{\@arabic}
\NewPatternFormat{r}{\@roman}
\NewPatternFormat{R}{\@Roman}

\ifdef\theparagraph
  {\AddCounterPattern{paragraph}{pg}}{}
\ifdef\thesubsubsection
  {\AddCounterPattern{subsubsection}{ssse}}{}
\ifdef\thesubsection
  {\AddCounterPattern{subsection}{sse}}{}
\ifdef\thesection
  {\AddCounterPattern{section}{se}}{}
\ifdef\thechapter
  {\AddCounterPattern{chapter}{ch}}{}

\endinput