prop-ini.mkii / last modification: 2020-01-30 14:15
%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 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 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\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}%
   \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\defineproperty
  {\dotripleempty\dodefineproperty}

\def\dodefineproperty[#1]%
  {\ifcsname\??py#1\c!global\endcsname
     \expandafter\nododefineproperty
   \else
     \expandafter\dododefineproperty
   \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 ! ! ! !
   \ifcsname\??py:l:#2\endcsname \else
     \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
   \fi
   \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}

\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