%D \module
%D   [       file=prop-ini,
%D        version=2003.04.20,
%D          title=\CONTEXT\ Property Macros,
%D       subtitle=Initialization,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%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 Property Macros / initialization}

%D Welcome to the third alternative of this yet undocumented module,
%D which means that there is no public interface yet!

\unprotect

\newcount\propertylevel

\def\currentpropertylevel {\csname\??py:l:\currentpropertytype\endcsname} % counter
\def\previouspropertylevel{\csname\??py:p:\currentpropertytype\endcsname} % counter

\def\currentproperty      {\csname\??py:c:\number\currentpropertylevel \endcsname} % string
\def\previousproperty     {\csname\??py:c:\number\previouspropertylevel\endcsname} % string

% more efficient:

\def\currentproperty      {\csname\??py:c:\number\propertylevel\endcsname} % string

% \def\previouspropertylevel{\numexpr(\csname\??py:p:\currentpropertytype\endcsname+1)}
% \letvalue{\??py:p:0}\empty

\def\currentpropertytype {\csname\??py\currentproperty\c!type\endcsname}

\def\docheckproperty % watch the s instead of e
  {\csname\s!check\currentpropertytype property\endcsname
   \global\expandafter\let\csname\??py\s!check\currentproperty\endcsname\empty}

% \def\checkproperty[#1]%
%   {\bgroup
%    \def\currentproperty{#1}%
%    \docheckproperty
%    \egroup}
%
% oeps, was wrong, no reset

\def\checkproperty[#1]%
  {\bgroup
   \def\currentproperty{#1}%
   \csname\??py\s!check\currentproperty\endcsname
   \egroup}

\unexpanded\def\property[#1]%
  {\groupedcommand{\dostartproperty{#1}}\dostopproperty}

\unexpanded\def\startproperty[#1]%
  {\dostartproperty{#1}}

\unexpanded\def\stopproperty
  {\dostopproperty}

\def\dostartgproperty
  {\begingroup\dostartproperty}

\def\dostopgproperty
  {\dostopproperty\endgroup}

\def\dostartproperty#1% evt pack: {current}{level}{
  {\global\advance\propertylevel\plusone
   \@EAEAEA\xdef\currentproperty{#1}%
   \global\advance\previouspropertylevel\plusone
   \global\advance\currentpropertylevel\plusone
   \csname\??py\s!check\currentproperty\endcsname
   \csname\s!start\currentpropertytype\s!property\endcsname}

\def\dostopproperty
  {\csname\s!stop\currentpropertytype\s!property\endcsname
   \global\advance\currentpropertylevel\minusone
   \global\advance\previouspropertylevel\minusone
   \global\advance\propertylevel\minusone}

% \def\propertyparameter       #1{\csname\??py\currentproperty#1\endcsname}
% \def\checkedpropertyparameter#1{\executeifdefined{\??py\currentproperty#1}}

\def\defineproperty
  {\dotripleempty\dodefineproperty}

% \def\dodefineproperty[#1][#2][#3]% global ! ! !
%   {\ifundefined{\??py#1\c!globaal}%
%      ... actions ...
%    \fi}
%
% since we may perform tests each time before a call, we prefer the faster:

\def\defineproperty
  {\dotripleempty\dodefineproperty}

\def\dodefineproperty[#1]%
  {\ifundefined{\??py#1\c!global}%
     \expandafter\dododefineproperty
   \else
     \expandafter\nododefineproperty
   \fi[#1]}

% due to initializations/counters, definitions are always global
%
% global : yes     : ungrouped
%          no      : grouped
% method : command : define commands
%          none    : no commands

\def\dododefineproperty[#1][#2][#3]% global ! ! !
  {\getgparameters[\??py#1][\c!global=\v!no,\c!type=#2,\c!method=\v!none,#3]% global ! ! ! !
   \expandafter\newcount\csname\??py:l:#2\endcsname % current level
   \expandafter\newcount\csname\??py:p:#2\endcsname % previous level
   \global\csname\??py:p:#2\endcsname\minusone
   \global\expandafter\expandafter\let\csname\??py:c:0\endcsname\empty
   \letgvalue{\??py\s!check#1}\docheckproperty
   \doifelsevalue{\??py#1\c!method}\v!command
     {\doifelsevalue{\??py#1\c!global}\v!yes
        {\setgvalue{\e!start#1}{\dostartproperty{#1}}%
         \letgvalue{\e!stop#1}\dostopproperty}%
        {\setgvalue{\e!start#1}{\dostartgproperty{#1}}%
         \letgvalue{\e!stop#1}\dostopgproperty}}%
     {\doifelsevalue{\??py#1\c!global}\v!yes
        {\setgvalue{\e!start#2}[##1]{\dostartproperty{##1}}%
         \letgvalue{\e!stop#2}\dostopproperty}%
        {\setgvalue{\e!start#2}[##1]{\dostartgproperty{##1}}%
         \letgvalue{\e!stop#2}\dostopgproperty}}}

\def\nododefineproperty[#1][#2][#3]%
  {}

\def\doifelseproperty#1{\doifdefinedelse{\??py#1\c!global}}

\def\setupproperty
  {\dodoubleempty\dosetupproperty}

\def\dosetupproperty[#1][#2]% local
  {\ifsecondargument
     \getparameters[\??py#1][#2]%
   \else
     \getparameters[\??py][#1]%
   \fi}

% \def\propertyparameter#1% expands to #1 when not defined (see \define...)
%   {\csname\??py
%      \ifcsname\??py\currentproperty#1\endcsname
%        \currentproperty#1%
%      \else\ifcsname\??py\currentpropertytype#1\endcsname
%        \currentpropertytype#1%
%      \else
%        :n:\currentproperty
%      \fi\fi
%    \endcsname}

\letvalue{\??py\s!empty}\empty

% beware, normally \*parameter concerns the current one

\def\propertyparameter#1#2% expands to #1 when not defined (see \define...)
  {\csname\??py
     \ifcsname\??py#1#2\endcsname
       #1#2%
     \else\ifcsname\??py\csname\??py#1\c!type\endcsname#2\endcsname
       \csname\??py#1\c!type\endcsname#2%
     \else
       \s!empty
     \fi\fi
   \endcsname}

\def\currentpropertyparameter % self and class
  {\propertyparameter\currentproperty}

\def\checkedpropertyparameter#1% only self
  {\executeifdefined{\??py\currentproperty#1}}

\def\definepropertyhandler#1{\setvalue{\??py*#1}}
\def\propertyhandler      #1{\getvalue{\??py*#1}}

\protect \endinput
