\NeedsTeXFormat{LaTeX2e}%
\ProvidesPackage{assoccnt}[2014/08/13 v0.2 -- Associate counters stepping]%
%%%
%% License: LaTeX Project Public License
%% Copyright (2014) Dr. Christian Hupfer 
%% Author: Christian Hupfer christian.hupfer@siebenfelsen.de
%%
%%
%%%%
%%% Some options later on
%%%%

\RequirePackage{etoolbox}[2011/01/03 2.2]%



\let\@@assoccnt@standardstepcounter\stepcounter%

\let\@@assoccnt@standardrefstepcounter\refstepcounter%


% Just for a quick suffix
\newcommand{\@@associatedcounterslistsuffix}{%
AssociatedCountersList%
}%



%%% Internal macro to generate the name of the list of associated counters
\newcommand{\@@assoccnt@@generatelistname}[1]{%
% #1 Name of the driver counter
@#1\@@associatedcounterslistsuffix
}%


\newcommand{\@@assoccnt@@addassociatedcounter}[2]{%
  \ifcsdef{#1}{%
    \ifinlistcs{#2}{#1}{%
      % Do nothing, since counter is already in the list
    }{%
      \listcsadd{#1}{#2}%
    }%
  }{%
    % Nothing in here
  }%
}%




% This command defines a list of counters, that should be stepped also if the driver counter
% is `\stepcounter`ed. 
% A self - association is not possible, as this would lead to inconsistent counting
\newcommand{\DeclareAssociatedCounters}[2]{%
% #1 --> driver counter 
% #2 --> CSV list of other counters, that should be stepped, if the driver counter is stepped
  \ifcsdef{\@@assoccnt@@generatelistname{#1}}{%
    %  % Nothing to be done --> List already exists
    \GenericWarning{}{Warning: List of associated counters for counter #1 already exists}%
  }{%
    \csgdef{\@@assoccnt@@generatelistname{#1}}{}%   Define some global list 
  }%
  % Now add the counter names from #2 to the list 
  % Note: Currently, it is not checked whether a counter is already added!
  \forcsvlist{\@@assoccnt@@addassociatedcounter{\@@assoccnt@@generatelistname{#1}}}{#2}%
  % Now remove an accidental self-association
  \RemoveAssociatedCounter{#1}{#1}% 
}%



%%% A generic macro, that removes a list entry from the list by
%%% defining a temporary list and omitting the 
\newcommand{\@@assoccnt@removefromlist}[2]{%
% #1 list name
% #2 element to be removed
  \ifcsdef{#1}{%
    \gdef\@@mytemplist{}%
    \renewcommand*{\do}[1]{%
      \ifstrequal{##1}{#2}{
        % Later one some success routine etc. ???
      }{%
        \listgadd{\@@mytemplist}{##1}%
      }%
    }%
    \dolistcsloop{#1}%
    \csxdef{#1}{\@@mytemplist}%
  }{%
    % The list is not defined at all, can't remove something from something not existing...
  }%
}%



%% Remove a particular counter from the list 
\newcommand{\RemoveAssociatedCounter}[2]{%
% #1 arg: driver counter
% #2 arg: counter name to be removed
  \@@assoccnt@removefromlist{\@@assoccnt@@generatelistname{#1}}{#2}%
}%

%% Remove a CSV list of counters from the list of associated counters 

\newcommand{\RemoveAssociatedCounters}[2]{%
% #1 arg: driver counter
% #2 arg: CSV list of counters to be removed
  \forcsvlist{\RemoveAssociatedCounter{#1}}{#2}%
}%

%% Remove all associated counters from the list 
\newcommand{\ClearAssociatedCountersList}[1]{%
% #1 arg: driver counter
  \csundef{\@@assoccnt@@generatelistname{#1}}%
}%


%% Test if a counter is an associated counter of driver counter 
\newcommand{\IfIsAssociatedCounter}[4]{%
% #1 arg: driver counter
% #2 arg: (possibly) associated counter
% #3 arg: Code for execution on true branch
% #4 arg: Code for execution on false branch
  \ifcsdef{\@@assoccnt@@generatelistname{#1}}{%
    \ifinlistcs{#2}{\@@assoccnt@@generatelistname{#1}}{%
      #3%
    }{%
      #4%
    }%
  }{% List does not exist, so it's not associated
    #4%
  }%
}%


%%% The stepcounter wrapper for the standard stepcounter command
%%% This is just for convenience, if the command as to be improved/extended later on in future
\newcommand{\@@assoccnt@stepcounter}[1]{%  
  \@@assoccnt@standardstepcounter{#1}%
}%

%%% Not needed so far
\newcommand{\@@assoccnt@refstepcounter}[1]{%  
  \@@assoccnt@standardrefstepcounter{#1}%
}%

%%%% Redefinition of the \stepcounter command 
\renewcommand{\stepcounter}[1]{%
  \@@assoccnt@standardstepcounter{#1}%   Traditional behaviour, since this is expected!
  \ifcsdef{\@@assoccnt@@generatelistname{#1}}{%    Check first, whether the list exists at all, 
    \forlistcsloop{\@@assoccnt@stepcounter}{\@@assoccnt@@generatelistname{#1}}%  March through the list
  }{% 
    %No list -> do nothing at all
  }%
}%



%%%% Redefinition of the \stepcounter command 
\renewcommand{\refstepcounter}[1]{%
  \@@assoccnt@standardstepcounter{#1}%   Traditional behaviour, since this is expected!
  \protected@edef\@currentlabel%
  {\csname p@#1\endcsname\csname the#1\endcsname}%
  \ifcsdef{\@@assoccnt@@generatelistname{#1}}{%    Check first, whether the list exists at all, 
    \forlistcsloop{\@@assoccnt@stepcounter}{\@@assoccnt@@generatelistname{#1}}%  March through the list
  }{% 
    %No list -> do nothing at all
  }%
}%


\endinput%