strc-num.mkiv / last modification: 2020-01-30 14:16
%D \module
%D   [       file=strc-num,
%D        version=2008.10.20,
%D          title=\CONTEXT\ Structure Macros,
%D       subtitle=Basic Numbering,
%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 Structure Macros / Basic Numbering}

\registerctxluafile{strc-num}{}

\unprotect

\startcontextdefinitioncode

% work in progress
% to be checked: can we use the command handler code here?
% all settings will move to lua

\installcorenamespace{counter}

\installcommandhandler \??counter {counter} \??counter

\let\setupcounters\setupcounter

\let\setupstructurecounting\setupcounter % will disappear

\setupcounter
  [\c!way=\v!by\v!chapter,
%  \c!blockway=,
%  \c!prefixstarter=,
%  \c!prefixstopper=,
   \c!prefixconnector=.,
   \c!prefixsegments=\autostructureprefixsegments\rootcounterparameter,
   \c!start=\zerocount,
   \c!prefix=\v!yes,
   \c!state=\v!start]

\def\autostructureprefixsegments#1% todo: \c!prefixsegments=\v!auto
  {2:\thenamedheadlevel{\clf_way{#1\c!way}}}

\appendtoks
    \resetcounterparameter\s!counter
\to \everypresetcounter

\appendtoks
    \ifx\currentcounterparent\empty
        \edef\p_start{\counterparameter\c!start}%
        \clf_definecounter
           name    {\currentcounter}%
           start   \ifx\p_start\empty\zerocount\else\numexpr\p_start\relax\fi
           counter {\counterparameter\s!counter}%
           method  {\counterparameter\c!method}%
        \relax
        \letcounterparameter\s!name\currentcounter
    \else
      % \letcounterparameter\s!name\currentcounterparent % we need a chained clone
        \setexpandedcounterparameter\s!name{\namedcounterparameter\currentcounterparent\s!name}%
    \fi
    \strc_counters_check_setup
\to \everydefinecounter

\appendtoks
    \ifx\currentcounter\empty \else
        \edef\p_number{\counterparameter\c!number}%
        \ifx\p_number\empty \else
          \clf_setcounter{\counterparameter\s!name}\numexpr\p_number\relax
          \letcounterparameter\c!number\empty
        \fi
        \edef\p_start{\counterparameter\c!start}%
        \setexpandedcounterparameter\c!start{\ifx\p_start\empty0\else\number\p_start\fi}%
        \strc_counters_check_setup
    \fi
\to \everysetupcounter

% % % %

\def\strc_counters_way#1{\clf_way{\namedcounterparameter{#1}\c!way}}

\def\thenamedcounterlevel#1%
  {\xthenamedheadlevel{\clf_way{\namedcounterparameter{#1}\c!way}}}

\unexpanded\def\strc_counters_check_setup
  {\edef\p_name{\directcounterparameter\s!name}%
   \ifx\currentcounter\p_name
     \edef\currentcounterlevel{\thenamedcounterlevel\currentcounter}%
     \edef\p_start{\counterparameter\c!start}%
     \clf_checkcountersetup
       {\currentcounter}%
       \numexpr\currentcounterlevel\relax
       \numexpr\ifx\p_start\empty\zerocount\else\p_start\fi\relax % bug in scanner
       {\counterparameter\c!state}%
   \fi}

\unexpanded\def\doifelsecounter #1{\clf_doifelsecounter{\namedcounterparameter{#1}\s!name}}
\unexpanded\def\doifcounter     #1{\clf_doifcounter    {\namedcounterparameter{#1}\s!name}}
\unexpanded\def\doifnotcounter  #1{\clf_doifnotcounter {\namedcounterparameter{#1}\s!name}}

\let\doifcounterelse\doifelsecounter

\unexpanded\def\setcounter        {\dotripleempty   \strc_counters_set_interfaced}
\unexpanded\def\setcounterown     {\dotripleempty   \strc_counters_setown_interfaced}
\unexpanded\def\restartcounter    {\dotripleempty   \strc_counters_restart_interfaced}
\unexpanded\def\resetcounter      {\dodoubleempty   \strc_counters_reset_interfaced}
\unexpanded\def\incrementcounter  {\dodoubleempty   \strc_counters_increment_interfaced}
\unexpanded\def\decrementcounter  {\dodoubleempty   \strc_counters_decrement_interfaced}

\unexpanded\def\rawcounter        {\dodoubleargument\strc_counters_raw_interfaced}
\unexpanded\def\lastcounter       {\dodoubleargument\strc_counters_last_interfaced}
\unexpanded\def\firstcounter      {\dodoubleargument\strc_counters_first_interfaced}
\unexpanded\def\nextcounter       {\dodoubleargument\strc_counters_next_interfaced}
\unexpanded\def\prevcounter       {\dodoubleargument\strc_counters_prev_interfaced}
\unexpanded\def\countersubs       {\dodoubleargument\strc_counters_subs_interfaced}

\unexpanded\def\savecounter       {\dosingleempty   \strc_counters_save_interfaced}
\unexpanded\def\restorecounter    {\dosingleempty   \strc_counters_restore_interfaced}

\def\strc_counters_set_interfaced
  {\ifthirdargument
     \singleexpandafter\strc_counters_set_two
   \else\ifsecondargument
     \doubleexpandafter\strc_counters_set_one
   \else
     \doubleexpandafter\gobblethreeoptionals
   \fi\fi}

\def\strc_counters_setown_interfaced
  {\ifthirdargument
     \singleexpandafter\strc_counters_setown_two
   \else\ifsecondargument
     \doubleexpandafter\strc_counters_setown_one
   \else
     \doubleexpandafter\gobblethreeoptionals
   \fi\fi}

\def\strc_counters_restart_interfaced
  {\ifthirdargument
     \singleexpandafter\strc_counters_restart_two
   \else\ifsecondargument
     \doubleexpandafter\strc_counters_restart_one
   \else
     \doubleexpandafter\gobblethreeoptionals
   \fi\fi}

\def\strc_counters_reset_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_reset_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_reset_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_increment_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_increment_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_increment_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_decrement_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_decrement_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_decrement_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_raw_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_raw_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_raw_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_last_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_last_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_last_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_first_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_first_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_first_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_prev_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_prev_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_prev_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_next_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_next_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_next_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_subs_interfaced
  {\ifsecondargument
     \singleexpandafter\strc_counters_subs_two
   \else\iffirstargument
     \doubleexpandafter\strc_counters_subs_one
   \else
     \doubleexpandafter\gobbletwooptionals
   \fi\fi}

\def\strc_counters_save_interfaced
  {\iffirstargument
     \expandafter\strc_counters_save_one
   \else
     \expandafter\gobbleoneoptional
   \fi}

\def\strc_counters_restore_interfaced
  {\iffirstargument
     \expandafter\strc_counters_restore_one
   \else
     \expandafter\gobbleoneoptional
   \fi}

\def\strc_counters_set_two           [#1][#2][#3]{\clf_setsubcounter          {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax}
\def\strc_counters_setown_two        [#1][#2][#3]{\clf_setownsubcounter       {\namedcounterparameter{#1}\s!name}\numexpr#2\relax{#3}}
\def\strc_counters_restart_two       [#1][#2][#3]{\clf_restartsubcounter      {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax}
\def\strc_counters_reset_two             [#1][#2]{\clf_resetsubcounter        {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
%def\strc_counters_increment_two         [#1][#2]{\clf_incrementsubcounter    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\def\strc_counters_decrement_two         [#1][#2]{\clf_decrementsubcounter    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}

\def\strc_counters_raw_two               [#1][#2]{\clf_subcountervalue        {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\def\strc_counters_last_two              [#1][#2]{\clf_lastsubcountervalue    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\def\strc_counters_first_two             [#1][#2]{\clf_firstsubcountervalue   {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\def\strc_counters_next_two              [#1][#2]{\clf_nextsubcountervalue    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\def\strc_counters_prev_two              [#1][#2]{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\def\strc_counters_subs_two              [#1][#2]{\clf_subsubcountervalues    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}

\def\strc_counters_set_one           [#1][#2][#3]{\clf_setcounter             {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\def\strc_counters_setown_one        [#1][#2][#3]{\clf_setowncounter          {\namedcounterparameter{#1}\s!name}{#2}}
\def\strc_counters_restart_one       [#1][#2][#3]{\clf_restartcounter         {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\def\strc_counters_reset_one             [#1][#2]{\clf_resetcounter           {\namedcounterparameter{#1}\s!name}}
%def\strc_counters_increment_one         [#1][#2]{\clf_incrementcounter       {\namedcounterparameter{#1}\s!name}}
\def\strc_counters_decrement_one         [#1][#2]{\clf_decrementcounter       {\namedcounterparameter{#1}\s!name}}

\def\strc_counters_raw_one               [#1][#2]{\clf_countervalue           {\namedcounterparameter{#1}\s!name}}
\def\strc_counters_last_one              [#1][#2]{\clf_lastcountervalue       {\namedcounterparameter{#1}\s!name}}
\def\strc_counters_first_one             [#1][#2]{\clf_firstcountervalue      {\namedcounterparameter{#1}\s!name}}
\def\strc_counters_next_one              [#1][#2]{\clf_nextcountervalue       {\namedcounterparameter{#1}\s!name}}
\def\strc_counters_prev_one              [#1][#2]{\clf_previouscountervalue   {\namedcounterparameter{#1}\s!name}}
\def\strc_counters_subs_one              [#1][#2]{\clf_subcountervalues       {\namedcounterparameter{#1}\s!name}}

\def\strc_counters_save_one                  [#1]{\clf_savecounter            {\namedcounterparameter{#1}\s!name}}
\def\strc_counters_restore_one               [#1]{\clf_restorecounter         {\namedcounterparameter{#1}\s!name}}

\unexpanded\def\strc_counters_set            #1#2{\clf_setcounter             {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\unexpanded\def\strc_counters_setown         #1#2{\clf_setowncounter          {\namedcounterparameter{#1}\s!name}{#2}}
\unexpanded\def\strc_counters_restart        #1#2{\clf_restartcounter         {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\unexpanded\def\strc_counters_reset            #1{\clf_resetcounter           {\namedcounterparameter{#1}\s!name}}
%unexpanded\def\strc_counters_increment        #1{\clf_incrementcounter       {\namedcounterparameter{#1}\s!name}}
\unexpanded\def\strc_counters_decrement        #1{\clf_decrementcounter       {\namedcounterparameter{#1}\s!name}}

           \def\strc_counters_raw              #1{\clf_countervalue           {\namedcounterparameter{#1}\s!name}}
           \def\strc_counters_last             #1{\clf_lastcountervalue       {\namedcounterparameter{#1}\s!name}}
           \def\strc_counters_first            #1{\clf_firstcountervalue      {\namedcounterparameter{#1}\s!name}}
           \def\strc_counters_next             #1{\clf_nextcountervalue       {\namedcounterparameter{#1}\s!name}}
           \def\strc_counters_prev             #1{\clf_previouscountervalue   {\namedcounterparameter{#1}\s!name}}
           \def\strc_counters_subs             #1{\clf_subcountervalues       {\namedcounterparameter{#1}\s!name}}

\unexpanded\def\strc_counters_set_sub      #1#2#3{\clf_setsubcounter          {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax}
\unexpanded\def\strc_counters_setown_sub   #1#2#3{\clf_setownsubcounter       {\namedcounterparameter{#1}\s!name}\numexpr#2\relax{#3}}
\unexpanded\def\strc_counters_restart_sub  #1#2#3{\clf_restartsubcounter      {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax}
\unexpanded\def\strc_counters_reset_sub      #1#2{\clf_resetsubcounter        {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
%unexpanded\def\strc_counters_increment_sub  #1#2{\clf_incrementsubcounter    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
\unexpanded\def\strc_counters_decrement_sub  #1#2{\clf_decrementsubcounter    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}

           \def\strc_counters_raw_sub        #1#2{\clf_subcountervalue        {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} % maybe raw
           \def\strc_counters_last_sub       #1#2{\clf_lastsubcountervalue    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
           \def\strc_counters_first_sub      #1#2{\clf_firstsubcountervalue   {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
           \def\strc_counters_next_sub       #1#2{\clf_nextsubcountervalue    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
           \def\strc_counters_prev_sub       #1#2{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax}
           \def\strc_counters_subs_sub       #1#2{\clf_subsubcountervalues    {\namedcounterparameter{#1}\s!name}\numexpr#2\relax}

\unexpanded\def\strc_counters_save             #1{\clf_savecounter            {\namedcounterparameter{#1}\s!name}}
\unexpanded\def\strc_counters_restore          #1{\clf_restorecounter         {\namedcounterparameter{#1}\s!name}}

\unexpanded\def\strc_counters_incremented      #1{\clf_incrementedcounter     {\namedcounterparameter{#1}\s!name}}
\unexpanded\def\strc_counters_decremented      #1{\clf_decrementedcounter     {\namedcounterparameter{#1}\s!name}}

\unexpanded\def\showcounter                  [#1]{\clf_showcounter            {\namedcounterparameter{#1}\s!name}}

\unexpanded\def\incrementedcounter           [#1]{\clf_incrementedcounter     {\namedcounterparameter{#1}\s!name}} % no \dosingleargument
\unexpanded\def\decrementedcounter           [#1]{\clf_decrementedcounter     {\namedcounterparameter{#1}\s!name}} % no \dosingleargument

% public variants ... beware, for old cases, from now on the value variants are the
% ones that are expandable

\def\rawcountervalue     [#1]{\clf_countervalue        {\namedcounterparameter{#1}\s!name}}
\def\lastcountervalue    [#1]{\clf_lastcountervalue    {\namedcounterparameter{#1}\s!name}}
\def\firstcountervalue   [#1]{\clf_firstcountervalue   {\namedcounterparameter{#1}\s!name}}
\def\nextcountervalue    [#1]{\clf_nextcountervalue    {\namedcounterparameter{#1}\s!name}}
\def\prevcountervalue    [#1]{\clf_previouscountervalue{\namedcounterparameter{#1}\s!name}}

\def\rawsubcountervalue  [#1]#2[#3]{\clf_subcountervalue        {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
\def\lastsubcountervalue [#1]#2[#3]{\clf_lastsubcountervalue    {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
\def\firstsubcountervalue[#1]#2[#3]{\clf_firstsubcountervalue   {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
\def\nextsubcountervalue [#1]#2[#3]{\clf_nextsubcountervalue    {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
\def\prevsubcountervalue [#1]#2[#3]{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#3\relax}

% The bypage check needs a multipass reference and therefore we only check for it when we increment
% and know that some content will be placed. We could also check for spreads.

\unexpanded\def\strc_counters_increment_sub#1#2%
  {% this will be combined into one lua call
   \edef\m_strc_counters_way{\strc_counters_way{#1}}%
   \ifx\m_strc_counters_way\v!page
     \checkpagechange{#1}%
     \ifpagechanged
       \strc_counters_reset{#1}%
     \fi
   \fi
   \clf_incrementsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax}

% We also need to redefine these because of the page check:

           \def\strc_counters_increment_two [#1][#2]{\strc_counters_increment_sub{#1}{#2}}
           \def\strc_counters_increment_one [#1][#2]{\strc_counters_increment_sub{#1}\plusone}
\unexpanded\def\strc_counters_increment           #1{\strc_counters_increment_sub{#1}\plusone}

% so far for the hack

\unexpanded\def\convertedcounter
  {\dodoubleempty\strc_counters_converted}

\def\strc_counters_converted[#1][#2]%
  {\begingroup
   \edef\currentcounter{#1}%
   \ifsecondargument\setupcurrentcounter[#2]\fi
   \clf_prefixedconverted
     {\counterparameter\s!name}
     {
       prefix        {\counterparameter\c!prefix}
       separatorset  {\counterparameter\c!prefixseparatorset}
       conversion    {\counterparameter\c!prefixconversion}
       conversionset {\counterparameter\c!prefixconversionset}
       starter       {\counterparameter\c!prefixstarter}
       stopper       {\counterparameter\c!prefixstopper}
       set           {\counterparameter\c!prefixset}
       segments      {\counterparameter\c!prefixsegments}
       connector     {\counterparameter\c!prefixconnector}
     }
     {
       order         {\counterparameter\c!numberorder}
       separatorset  {\counterparameter\c!numberseparatorset}
       conversion    {\counterparameter\c!numberconversion}
       conversionset {\counterparameter\c!numberconversionset}
       starter       {\counterparameter\c!numberstarter}
       stopper       {\counterparameter\c!numberstopper}
       segments      {\counterparameter\c!numbersegments}
       type          {\counterparameter\c!type}
       criterium     {\counterparameter\c!criterium}
     }
   \relax
   \endgroup}

\def\directconvertedcounter#1#2% name, type
  {\clf_prefixedconverted
     {\namedcounterparameter{#1}\s!name}
     {
       prefix        {\namedcounterparameter{#1}\c!prefix}
       separatorset  {\namedcounterparameter{#1}\c!prefixseparatorset}
       conversion    {\namedcounterparameter{#1}\c!prefixconversion}
       conversionset {\namedcounterparameter{#1}\c!prefixconversionset}
    %  starter       {\namedcounterparameter{#1}\c!prefixstarter}
    %  stopper       {\namedcounterparameter{#1}\c!prefixstopper}
       set           {\namedcounterparameter{#1}\c!prefixset}
       segments      {\namedcounterparameter{#1}\c!prefixsegments}
       connector     {\namedcounterparameter{#1}\c!prefixconnector}
     }
     {
       order         {\namedcounterparameter{#1}\c!numberorder}
       separatorset  {\namedcounterparameter{#1}\c!numberseparatorset}
       conversion    {\namedcounterparameter{#1}\c!numberconversion}
       conversionset {\namedcounterparameter{#1}\c!numberconversionset}
       starter       {\namedcounterparameter{#1}\c!numberstarter}
       stopper       {\namedcounterparameter{#1}\c!numberstopper}
       segments      {\namedcounterparameter{#1}\c!numbersegments}
       type          {#2}
     }
   \relax}

\unexpanded\def\convertedsubcounter
  {\dotripleempty\strc_counters_converted_sub}

\def\strc_counters_converted_sub[#1][#2][#3]% #2 can be n or n:m
  {\ifsecondargument
     \strc_counters_converted[#1][\c!numbersegments=#2,#3]%
   \else
     \secondargumentfalse\strc_counters_converted[#1][]%
   \fi}

% \unexpanded\def\doifdefinedcounter#1%
%   {\ifcsname\namedcounterhash{#1}\s!name\endcsname
%      \expandafter\firstofoneargument
%    \else
%      \expandafter\gobbleoneargument
%    \fi}
%
% \unexpanded\def\doifundefinedcounter#1%
%   {\ifcsname\namedcounterhash{#1}\s!name\endcsname
%      \expandafter\gobbleoneargument
%    \else
%      \expandafter\firstofoneargument
%    \fi}
%
% \unexpanded\def\doifdefinedcounterelse#1%
%   {\ifcsname\namedcounterhash{#1}\s!name\endcsname
%      \expandafter\firstoftwoarguments
%    \else
%      \expandafter\secondoftwoarguments
%    \fi}

\unexpanded\def\doifdefinedcounter    {\doifcommandhandler    \??counter}
\unexpanded\def\doifundefinedcounter  {\doifnotcommandhandler \??counter}
\unexpanded\def\doifelsedefinedcounter{\doifelsecommandhandler\??counter}

\let\doifdefinedcounterelse\doifelsedefinedcounter

%D What follows is a compatibility layer.

\let \numberparameter       \namedcounterparameter  % {name}\c!key

\let \definenumber          \definecounter          % [name]
\let \setupnumber           \setupcounter           % [name][setups]

\let \setnumber             \setcounter             % [name]{value}
\let \resetnumber           \resetcounter           % [name]
\let \savenumber            \savecounter            % [name]
\let \restorenumber         \restorecounter         % [name]
\let \incrementnumber       \incrementcounter       % [name]
\let \decrementnumber       \decrementcounter       % [name]
\let \rawnumber             \rawcounter             % [name]
\let \getnumber             \convertedcounter       % [name]
\let \convertednumber       \convertedcounter       % [name]

\let \doifdefinednumber     \doifdefinedcounter     % {number}{true}
\let \doifundefinednumber   \doifnotdefinedcounter  % {number}{true}
\let \doifelsedefinednumber \doifelsedefinedcounter % {number}{true}{false}
\let \doifdefinednumberelse \doifelsedefinedcounter % {number}{true}{false}

\let \setupnumbering        \setupcounter

%D Helpers:

% call:
%
% \strc_counters_register_component
%   \currentfloat
%   \getfloatparameters \floatparameter \detokenizedfloatparameter
%   \hascaption \hastitle \hasnumber
%   [settings][userdata]
%
% sets:
%
% \m_strc_counters_last_registered_index
% \m_strc_counters_last_registered_attribute
% \m_strc_counters_last_registered_synchronize

% currentstructurecomponent => \strc_current_ or just \m_strc_

\unexpanded\def\strc_counters_register_component#1#2#3#4#5#6#7[#8][#9]% maybe also nolist
  {\begingroup
   %
   #2[\s!haslevel=1,#8]%
   \edef\p_haslevel  {#3\s!haslevel}%
   \edef\p_hascaption{#3\s!hascaption}%
   \edef\p_hastitle  {#3\s!hastitle}%
   \edef\p_hasnumber {#3\s!hasnumber}%
   %
   \edef\p_prefixsegments{#3\c!prefixsegments}%
   \ifx\p_prefixsegments\v!auto
     \edef\p_prefixsegments{\autostructureprefixsegments#3}%
   \fi
   %
   \edef\currentname{#3\s!name}%
   \ifx\currentname\empty
     \edef\currentname{#1}%
   \fi
   \edef\currentcounter{#3\s!counter}%
   \ifx\currentcounter\empty
     \let\currentcounter\currentname
   \fi
   %
   \ifx\p_hascaption\v!yes
     \strc_counters_register_component_list{#1}{#3}{#4}{#9}%
   \else\ifx\currentstructurecomponentreference\empty
     \strc_counters_register_component_none
   \else
     \strc_counters_register_component_page{#3}%
   \fi\fi
   \endgroup}

\def\strc_counters_register_component_none
  {\glet\m_strc_counters_last_registered_index      \relax
   \glet\m_strc_counters_last_registered_attribute  \attributeunsetvalue
   \glet\m_strc_counters_last_registered_synchronize\relax}

\def\strc_counters_register_component_check_prefix
  {\ifx\currentstructurecomponentreferenceprefix\empty
     \let\currentstructurecomponentreferenceprefix\currentstructurereferenceprefix
   \fi
   \ifx\currentstructurecomponentreferenceprefix\empty
     \let\currentstructurecomponentreferenceprefix\referenceprefix
   \fi
   \ifdefined\currentstructurecomponentreferenceprefix\else
     \let\currentstructurecomponentreferenceprefix\empty
   \fi}

\def\strc_counters_register_component_page#1%
  {\xdef\currentstructurecomponentreference      {#1\c!reference}%
   \xdef\currentstructurecomponentreferenceprefix{#1\c!referenceprefix}%
   \strc_counters_register_component_check_prefix
   \setnextinternalreference
   \clf_setdestinationattribute
        {%
            references {%
                  internal  \locationcount
                % block     {\currentsectionblock}% move to lua
                  view      {\interactionparameter\c!focus}%
                  prefix    {\currentstructurecomponentreferenceprefix}%
                  reference {\currentstructurecomponentreference}%
            }%
            metadata {%
                kind {\s!page}%
            }%
        }%
   \relax
   \xdef\m_strc_counters_last_registered_attribute  {\the\lastdestinationattribute}%
   \glet\m_strc_counters_last_registered_index      \relax
   \glet\m_strc_counters_last_registered_synchronize\relax}

\def\strc_counters_register_component_list#1#2#3#4%
  {\xdef\currentstructurecomponentname           {#2\s!name}%
   \xdef\currentstructurecomponentlevel          {#2\c!level}%
   \edef\currentstructurecomponentexpansion      {#2\c!expansion}%
   \xdef\currentstructurecomponentxmlsetup       {#2\c!xmlsetup}%
   \xdef\currentstructurecomponentcatcodes       {#2\s!catcodes}%
   \xdef\currentstructurecomponentlabel          {#2\c!label}%
   \xdef\currentstructurecomponentreference      {#2\c!reference}%
   \xdef\currentstructurecomponentreferenceprefix{#2\c!referenceprefix}%
   \strc_counters_register_component_check_prefix
   \ifx\currentstructurecomponentexpansion\s!xml
     \xmlstartraw
       \xdef\currentstructurecomponenttitle   {#2\c!title}%
       \xdef\currentstructurecomponentbookmark{#2\c!bookmark}%
       \xdef\currentstructurecomponentmarking {#2\c!marking}%
       \xdef\currentstructurecomponentlist    {#2\c!list}%
     \xmlstopraw
     \ifx\currentstructurecomponentlist\empty
       \glet\currentstructurecomponentlist\currentstructurecomponenttitle
     \fi
     \glet\currentstructurecomponentcoding\s!xml
   \else
     \ifx\currentstructurecomponentexpansion\v!yes
       \xdef\currentstructurecomponenttitle   {#2\c!title}%
       \xdef\currentstructurecomponentbookmark{#2\c!bookmark}%
       \xdef\currentstructurecomponentmarking {#2\c!marking}%
       \xdef\currentstructurecomponentlist    {#2\c!list}%
     \else
       \xdef\currentstructurecomponenttitle   {#3\c!title}%
       \xdef\currentstructurecomponentbookmark{#3\c!bookmark}%
       \xdef\currentstructurecomponentmarking {#3\c!marking}%
       \xdef\currentstructurecomponentlist    {#3\c!list}%
       \iflocation \ifx\currentstructurecomponentbookmark\empty
         \begingroup
         \simplifycommands
         \xdef\currentstructurecomponentbookmark{\detokenize\expandafter{\normalexpanded{#2\c!title}}}%
        \endgroup
       \fi \fi
     \fi
     \ifx\currentstructurecomponentlist\empty
       \glet\currentstructurecomponentlist\currentstructurecomponenttitle
     \fi
     \glet\currentstructurecomponentcoding\s!tex
   \fi
   %
   \setnextinternalreference
   \scratchcounter\clf_addtolist %{
      metadata {
          kind     {#1}
          name     {\currentname}
        % level    structures.sections.currentlevel()
          catcodes \ifx\currentstructurecomponentcatcodes\empty\catcodetable\else\csname\currentstructurecomponentcatcodes\endcsname\fi
          coding   {\currentstructurecomponentcoding}
      \ifx\currentstructurecomponentcoding\s!xml
          xmlroot  {\xmldocument}
      \fi
      \ifx\currentstructurecomponentxmlsetup\empty \else
          xmlsetup {\currentstructurexmlsetup}
      \fi
      }
      references {
          internal  \locationcount
        % block     {\currentsectionblock}
          reference {\currentstructurecomponentreference}
          prefix    {\currentstructurecomponentreferenceprefix}
        % section   structures.sections.currentid()
          view      {\interactionparameter\c!focus}%
      }
      titledata {
          label    {\detokenize\expandafter{\currentstructurecomponentlabel}}
          title    {\detokenize\expandafter{\currentstructurecomponenttitle}}
      \ifx\currentstructurecomponentbookmark\currentstructurecomponenttitle \else
          bookmark {\detokenize\expandafter{\currentstructurecomponentbookmark}}
      \fi
      \ifx\currentstructurecomponentmarking\currentstructurecomponenttitle \else
          marking  {\detokenize\expandafter{\currentstructurecomponentmarking}}
      \fi
      \ifx\currentstructurecomponentlist\currentstructurecomponenttitle \else
          list     {\detokenize\expandafter{\currentstructurecomponentlist}}
      \fi
      }
  \ifx\p_hasnumber\v!yes
      prefixdata {
          prefix        {#2\c!prefix}
          separatorset  {#2\c!prefixseparatorset}
          conversion    {#2\c!prefixconversion}
          conversionset {#2\c!prefixconversionset}
          set           {#2\c!prefixset}
       %  segments      {#2\c!prefixsegments}
          segments      {\p_prefixsegments}
          connector     {#2\c!prefixconnector}
      }
      numberdata { % more helpers here, like compact elsewhere
          numbers       {\currentcounter}
          group         {#2\c!group}
          groupsuffix   {#2\c!groupsuffix}
          counter       {\currentcounter}
          separatorset  {#2\c!numberseparatorset}
          conversion    {#2\c!numberconversion}
          conversionset {#2\c!numberconversionset}
          starter       {#2\c!numberstarter}
          stopper       {#2\c!numberstopper}
          segments      {#2\c!numbersegments}
      }
  \fi
      userdata {\detokenize{#4}}
   %}
   \relax
   \xdef\m_strc_counters_last_registered_index{\the\scratchcounter}%
   \setstructurecomponentsynchronization\m_strc_counters_last_registered_index
   \glet\m_strc_counters_last_registered_attribute  \currentstructurecomponentattribute
   \glet\m_strc_counters_last_registered_synchronize\currentstructurecomponentsynchronize}

\let\m_strc_counters_last_registered_index      \relax
\let\m_strc_counters_last_registered_attribute  \relax
\let\m_strc_counters_last_registered_synchronize\relax

% This can be improved as we don't need to pas all these variables
% each time (we can set them up once).

\unexpanded\def\strc_counter_preset_using_parameter#1#2% \setupcommand \someparameter
  {#1%
    [\c!way                =#2\c!way,
     \c!prefix             =#2\c!prefix,
     \c!prefixseparatorset =#2\c!prefixseparatorset,
     \c!prefixconversion   =#2\c!prefixconversion,
     \c!prefixconversionset=#2\c!prefixconversionset,
     \c!prefixstarter      =#2\c!prefixstarter,
     \c!prefixstopper      =#2\c!prefixstopper,
     \c!prefixsegments     =#2\c!prefixsegments,
     \c!prefixset          =#2\c!prefixset,
     \c!prefixconnector    =#2\c!prefixconnector,
     \c!numberseparatorset =#2\c!numberseparatorset,
     \c!numberconversion   =#2\c!numberconversion,
     \c!numberconversionset=#2\c!numberconversionset,
     \c!numberstarter      =#2\c!numberstarter,
     \c!numberstopper      =#2\c!numberstopper,
     \c!numbersegments     =#2\c!numbersegments]}

% \unexpanded\def\strc_counter_setup_using_parameter#1#2% name \someparameter
%   {\setupcounter
%      [#1]
%      [              \c!start=#2\c!start,
%                     \c!state=#2\c!state, % beware, "" == start
%                       \c!way=#2\c!way,
%                             %
%                    \c!prefix=#2\c!prefix,
%        \c!prefixseparatorset=#2\c!prefixseparatorset,
%          \c!prefixconversion=#2\c!prefixconversion,
%       \c!prefixconversionset=#2\c!prefixconversionset,
%             \c!prefixstarter=#2\c!prefixstarter,
%             \c!prefixstopper=#2\c!prefixstopper,
%                 \c!prefixset=#2\c!prefixset,
%            \c!prefixsegments=#2\c!prefixsegments,
%                 \c!prefixset=#2\c!prefixset,
%           \c!prefixconnector=#2\c!prefixconnector,
%                             %
%        \c!numberseparatorset=#2\c!numberseparatorset,
%          \c!numberconversion=#2\c!numberconversion,
%       \c!numberconversionset=#2\c!numberconversionset,
%             \c!numberstarter=#2\c!numberstarter,
%             \c!numberstopper=#2\c!numberstopper,
%            \c!numbersegments=#2\c!numbersegments]}

\unexpanded\def\strc_counter_setup_using_parameter#1#2% name \someparameter
  {\edef\currentcounter{#1}%
   %
   \setcounterparameter              \c!start{#2\c!start}%
   \setcounterparameter              \c!state{#2\c!state}% % beware, "" == start
   \setcounterparameter                \c!way{#2\c!way}%
   %
   \setcounterparameter             \c!prefix{#2\c!prefix}%
   \setcounterparameter \c!prefixseparatorset{#2\c!prefixseparatorset}%
   \setcounterparameter   \c!prefixconversion{#2\c!prefixconversion}%
   \setcounterparameter\c!prefixconversionset{#2\c!prefixconversionset}%
   \setcounterparameter      \c!prefixstarter{#2\c!prefixstarter}%
   \setcounterparameter      \c!prefixstopper{#2\c!prefixstopper}%
   \setcounterparameter          \c!prefixset{#2\c!prefixset}%
   \setcounterparameter     \c!prefixsegments{#2\c!prefixsegments}%
   \setcounterparameter          \c!prefixset{#2\c!prefixset}%
   \setcounterparameter    \c!prefixconnector{#2\c!prefixconnector}%
   %
   \setcounterparameter \c!numberseparatorset{#2\c!numberseparatorset}%
   \setcounterparameter   \c!numberconversion{#2\c!numberconversion}%
   \setcounterparameter\c!numberconversionset{#2\c!numberconversionset}%
   \setcounterparameter      \c!numberstarter{#2\c!numberstarter}%
   \setcounterparameter      \c!numberstopper{#2\c!numberstopper}%
   \setcounterparameter     \c!numbersegments{#2\c!numbersegments}%
   %
   \the\everysetupcounter}

\unexpanded\def\mult_interfaces_counter_association#1#2#3#4#5#6#7% tag current setup parameter list sync register
  {\strc_counter_preset_using_parameter#3\rootcounterparameter
   \newtoks#5%
   \unexpanded\def   #6{\ifx#2\empty\the#5\else\strc_counter_setup_using_parameter#2#4\fi}% sync
   \unexpanded\def#7##1{\normalexpanded{#5{\the#5\strc_counter_setup_using_parameter{##1}\noexpand#4}}}} % register

\unexpanded\def\installcounterassociation#1% => synchronize#1counters register#1counter
  {\normalexpanded
     {\mult_interfaces_counter_association
        {#1}% not \??xx but xx
        \expandafter\noexpand\csname current#1\endcsname
        \expandafter\noexpand\csname setup#1\endcsname
        \expandafter\noexpand\csname #1parameter\endcsname
        \expandafter\noexpand\csname counter_association_list_#1\endcsname
        \expandafter\noexpand\csname synchronize#1counters\endcsname
        \expandafter\noexpand\csname register#1counter\endcsname}}

% needs testing:
%
% \unexpanded\def\strc_counter_setup_push#1#2#3% \someparameter \directsomeparameter \setexpandedsomeparameter
%   {\let\savedcounterparameter           \counterparameter
%    \let\saveddirectcounterparameter     \directcounterparameter
%    \let\savedsetexpandedcounterparameter\setexpandedcounterparameter
%    % remap
%    \let\counterparameter                #1%
%    \let\directcounterparameter          #2%
%    \let\setexpandedcounterparameter     #3}
%
% \unexpanded\def\strc_counter_setup_pop
%   {\let\counterparameter                \savedcounterparameter
%    \let\directcounterparameter          \saveddirectcounterparameter
%    \let\setexpandedcounterparameter     \savedsetexpandedcounterparameter}
%
% \unexpanded\def\mult_interfaces_counter_association#1#2#3#4#5#6#7% tag current setup parameter list sync register
%   {\strc_counter_preset_using_parameter#3\rootcounterparameter
%    \newtoks#5%
%    \unexpanded\def#6% sync
%      {\strc_counter_setup_push
%       \ifx#2\empty
%         \the#5%
%       \else
%         \let\currentcounter\empty
%         \the\everysetupcounter
%       \fi
%       \strc_counter_setup_pop}%
%    \unexpanded\def#7##1% register
%       {\normalexpanded{#5{\the#5\edef\noexpand\currentcounter{##1}\noexpand\the\everysetupcounter}}}}

%D For good old times (easier to explain in manuals):
%D
%D \starttyping
%D \setcounter[userpage][9]
%D \setupcounter[userpage][number=9]
%D \setupuserpagenumber[number=9]
%D \stoptyping

% needs testing: we might have conflicts with mixins
%
% \appendtoks
%     \ifx\currentcounter\empty \else
%         \edef\p_number{\counterparameter\c!number}%
%         \ifx\p_number\empty \else
%             \strc_counters_set\currentcounter\p_number
%             \letcounterparameter\c!number\empty
%         \fi
%     \fi
% \to \everysetupcounter

\stopcontextdefinitioncode

\protect \endinput