%D \module
%D   [       file=core-itm, % updated
%D        version=1997.03.31,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=itemgroups,
%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.

% new: text + lefttext=(,righttext=)
%      start=

\writestatus{loading}{Context Core Macros / Itemgroups}

\startmessages  dutch  library: layouts
      9: momenteel maximaal -- niveaus in opsommingen
\stopmessages

\startmessages  english  library: layouts
      9: currently no more than -- levels in itemizations
\stopmessages

\startmessages  german  library: layouts
      9: z.Z. nicht mehr als -- Niveaus in Posten
\stopmessages

\startmessages  czech  library: layouts
      9: aktualne ne vice nez -- urovne/urovni vyctu
\stopmessages

\startmessages  italian  library: layouts
      9: attualmente non più di -- livelli di elencazione
\stopmessages

\startmessages  norwegian  library: layouts
      9: for øyeblikket maksimalt -- nivåer i opplisting
\stopmessages

\startmessages  romanian  library: layouts
      9: acum nu se supota mai mult de -- nivele de adancime la iteratii
\stopmessages

\unprotect

% - instellingen in macro
% - [0] voor start op 0
% - start=2

\newif\ifsubitem        \subitemfalse
\newif\ifsymbolitem     \symbolitemfalse
\newif\ifheaditem       \headitemfalse
\newif\ifitemintro      \itemintrofalse
\newif\ifautoitemintro  \autoitemintrofalse
\newif\ifoptimizeitems  \optimizeitemstrue
\newif\ifpackeditems    \packeditemsfalse
\newif\iffirstlist      \firstlistfalse
\newif\ifparagraphitems \paragraphitemsfalse
\newif\iftextitems      \textitemsfalse

\newcounter\noflists
\newcounter\itemlevel
\newcounter\itemcolumndepth
\newcounter\maxitemlevel

\definetwopasslist\s!list

\let\currentitemgroup\empty

\def\unknownitemreference{0} \let\itemreferences\unknownitemreference

% #1=level #2=parameter

\def\getitemparameter #1#2{\csname\??op\currentitemgroup#1#2\endcsname}
\def\setitemparameter #1#2{\@EA\def\csname\??op\currentitemgroup#1#2\endcsname}
\def\letitemparameter #1#2{\@EA\let\csname\??op\currentitemgroup#1#2\endcsname}

\def\doitemattributes   #1{\doattributes{\??op\currentitemgroup#1}}

\def\@@globalitemsymbol #1{\??op\currentitemgroup\c!symbol\s!global#1}
\def\@@localitemsymbol  #1{\??op\currentitemgroup\c!symbol\s!local #1}
\def\@@currentitemsymbol#1{\??op\currentitemgroup\c!symbol         #1}

\def\@@itemcounter{\s!itemcount\currentitemgroup}

% \def\doitembreak#1{\iftextitems\else\dosomebreak#1\fi}
%
% s-pre-61 / pre-dis, test extensively, 2004/5

\def\doitembreak#1{\ifoptimizeitems\iftextitems\else\dosomebreak#1\fi\fi}

\def\dolistreference
  {\immediatewriteutilitycommand
     {\twopassentry
        {\s!list}%
        {\currentlist}%
        {\currentlist:\noflistelements}}}

\def\initializeitemgroupslevel#1%
  {\ifundefined{\@@globalitemsymbol{#1}}%
     \edef\itemreferences{\itemreferences,#1}%
     \makecounter{\@@itemcounter#1}%
     \setevalue{\@@globalitemsymbol{#1}}{#1}%
   \fi}

\def\initializeitemgrouplevel#1% safeguard
  {\ifundefined{\??op\currentitemgroup#1\c!width}%
     \doinitializeitemgrouplevel{#1}%
   \fi}

\def\doinitializeitemgrouplevel#1%
  {\copyparameters
     [\??op\currentitemgroup#1][\??oo]
     [\c!width,\c!factor,\c!distance,\c!align,\c!option,
      \c!style,\c!marstyle,\c!symstyle,\c!headstyle,
      \c!color,\c!marcolor,\c!symcolor,\c!headcolor,
      \c!beforehead,\c!afterhead,\c!before,\c!inbetween,\c!after,
      \c!stopper,\c!placestopper,\c!indenting,
      \c!n,\c!inner,\c!symbol,\c!margin,\c!items,
      \c!leftmargin,\c!rightmargin,
      \c!start,\c!lefttext,\c!righttext]}

\def\setupitemgroups
  {\dosingleargument\dosetupitemgroups}

\def\dosetupitemgroups[#1]% still undocumented
  {\getparameters[\??oo][\c!levels=4,#1]%
   % will change (remove)
   \ifnum\@@oolevels>\maxitemlevel
     \edef\maxitemlevel{\@@oolevels}%
     \dorecurse\maxitemlevel{\initializeitemgroupslevel\recurselevel}%
   \fi}

\def\doitemreference#1,#2,#3\\%
  {\ifnum\itemlevel>#1\relax
     \ifnum#1>\zerocount \tempsymbol \fi
     \getvalue{\@@currentitemsymbol{#2}}%
     \doitemreference#2,#3\\%
   \fi}

\def\itemreference
  {\expandafter\doitemreference\itemreferences,,\\}

\def\packitems
  {\ifcase\itemlevel \else \packeditemstrue \fi}

\def\dosetupitemgroupvariable[#1]% [#2]%  niveau instellingen
  {\doifelsenothing{#1}
     {\getparameters[\??op\currentitemgroup\itemlevel]}% [#2]}%
     {\getparameters[\??op\currentitemgroup#1]}}%        [#2]}}

\newconditional\inlinelistitem \setfalse\inlinelistitem

\def\dododosetupitemgroupconstant[#1][#2#3#4]% * permits [2]
  {\processaction
     [#2#3#4]
     [   \v!packed*=>\packitems,
          \v!intro*=>\itemintrotrue,
      \v!autointro*=>\autoitemintrotrue,
          \v!broad*=>\setitemparameter{#1}\c!factor{1},
     #2#3*\v!broad*=>\setitemparameter{#1}\c!factor{#2#3},
       #2*\v!broad*=>\setitemparameter{#1}\c!factor{#2},
           \v!text*=>\textitemstrue
                     \settrue\inlinelistitem
                     \dosetuppackeditemgroup{#1}%
                     \packitems,
        \v!columns*=>\packitems,
         \v!margin*=>\setitemparameter{#1}\c!width{-2em}, % signal
       \v!inmargin*=>\setitemparameter{#1}\c!width{-2em}, % signal
       \v!atmargin*=>\doifnot{#1}{1}{\setitemparameter{#1}\c!width{0em}}, % signal
         \v!intext*=>\settrue\inlinelistitem, % new
          \v!loose*=>\optimizeitemsfalse,
      \v!paragraph*=>\paragraphitemstrue
                     \packitems,
       \v!joinedup*=>\dosetuppackeditemgroup{#1}%
                     \packitems,
        \v!serried*=>\setitemparameter{#1}\c!factor{-1},
   #2#3*\v!serried*=>\setitemparameter{#1}\c!factor{-#2#3},
     #2*\v!serried*=>\setitemparameter{#1}\c!factor{-#2},
        \v!stopper*=>\setitemparameter{#1}\c!placestopper\v!yes,
       \v!unpacked*=>\packeditemsfalse,
         \v!repeat*=>\settrue\repeatlistitem, % new
       \v!standard*=>\dosetupstandarditemgroup{#1}]}

\def\dosetupstandarditemgroup#1%
  {\getparameters
     [\??op\currentitemgroup#1]
     [\c!width=1.5em,
      \c!factor=0,
      \c!distance=.5em,
      \c!beforehead=,
      \c!afterhead=\blank,
      \c!before=\blank,
      \c!inbetween=\blank,
      \c!after=\blank,
      \c!inner=]}

\def\dosetuppackeditemgroup#1%
  {\letitemparameter{#1}\c!beforehead\empty
   \letitemparameter{#1}\c!afterhead \empty
   \letitemparameter{#1}\c!before    \empty
   \letitemparameter{#1}\c!after     \empty
   \letitemparameter{#1}\c!inbetween \empty}

% \def\dosetupitemgroupconstant[#1][#2]%
%   {\def\dodosetupitemgroupconstant##1%
%      {\dododosetupitemgroupconstant[#1][##1*]}%
%    \processcommacommand[#2]\dodosetupitemgroupconstant} % expansion of #2 is handy for xml

\def\dosetupitemgroupconstant[#1][#2]%
  {\def\dodosetupitemgroupconstant##1% catches empty in [a,b,] handy for xml
     {\doifsomething{##1}{\dododosetupitemgroupconstant[#1][##1*]}}%
   \processcommacommand[#2]\dodosetupitemgroupconstant} % expansion of #2 is handy for xml

%\def\dododododosetupitemgroup[#1][#2]%
%  {\doifassignmentelse{#2}
%     {\dosetupitemgroupvariable[#1][#2]}
%     {\setitemparameter{#1}\empty{\dosetupitemgroupconstant[#1][#2]}}}%

\def\dododododosetupitemgroup[#1][#2]%
  {\doifassignmentelse{#2}%
     {\dosetupitemgroupvariable[#1][#2]}%
     {\setitemparameter{#1}\c!option{#2}}}%

\def\dodododosetupitemgroup[#1][#2]%
  {\ConvertToConstant\doifnot{#2}{}
     {\doifelse{#1}\v!each
        {\dorecurse\maxitemlevel{\ExpandFirstAfter\dododododosetupitemgroup[\recurselevel][#2]}}
        {\ExpandFirstAfter\dododododosetupitemgroup[#1][#2]}}}

\def\dododosetupitemgroup[#1][#2]%
  {\ConvertToConstant\doifelse{#2}{}
     {\ifcase\itemlevel\relax
        \dodododosetupitemgroup[\v!each][#1]%
      \else
        \dodododosetupitemgroup[\itemlevel][#1]%
      \fi}
     {\doifelsenothing{#1}
        {\dodododosetupitemgroup[\itemlevel][#2]}
        {\dodododosetupitemgroup[#1][#2]}}}

\def\dodosetupitemgroup[#1][#2][#3][#4]%
  {\pushmacro\currentitemgroup
   \def\currentitemgroup{#1}%
   \dododosetupitemgroup[#2][#3]%
   \ConvertToConstant\doifnot{#4}{}  % anders wordt #2 overruled
     {\dododosetupitemgroup[#2][#4]}%
   \popmacro\currentitemgroup}

\def\dosetupitemgroup[#1][#2][#3][#4]%
  {\def\docommando##1{\dodosetupitemgroup[##1][#2][#3][#4]}%
   \processcommalist[#1]\docommando}

\def\setupitemgroup
  {\doquadrupleempty\dosetupitemgroup}

\def\doadvanceitem
  {\ifsubitem\else\ifsymbolitem\else
     \pluscounter{\@@itemcounter\itemlevel}%
   \fi\fi}

% \def\setitemlevel#1%
%   {\ifnum\itemlevel>0\relax
%      \firstlisttrue
%      \doifnotinset\v!verder{#1}
%        {\resetcounter{\@@itemcounter\itemlevel}}%
%      \def\tempnumber%
%        {\countervalue{\@@itemcounter\itemlevel}}%
%      \doifelse{\getitemparameter\itemlevel\c!plaatsafsluiter}\v!ja
%        {\def\tempsymbol{\getitemparameter\itemlevel\c!afsluiter}}
%        {\let\tempsymbol\empty}%
%    \fi}

\def\setitemlevel#1%
  {\ifnum\itemlevel>\zerocount
     \firstlisttrue
     \doifnotinset\v!continue{#1}
       {\doifinset{0}{#1}{\setitemparameter\itemlevel\c!start{0}}%
        \doifsomething{\getitemparameter\itemlevel\c!start}
          {\setcounter{\@@itemcounter\itemlevel}{\getitemparameter\itemlevel\c!start}%
           \minuscounter{\@@itemcounter\itemlevel}%
           \letitemparameter\itemlevel\c!start\empty}}%
     \def\tempnumber
       {\countervalue{\@@itemcounter\itemlevel}}%
     \doifelse{\getitemparameter\itemlevel\c!placestopper}\v!yes
       {\def\tempsymbol{\getitemparameter\itemlevel\c!stopper}}
       {\let\tempsymbol\empty}%
   \fi}

% PAS OP: ook 'opelkaar' en zo worden getest, nog eens afvangen!

\def\unknownitemsymbol{?}

\def\setitemmark#1% % en pas op: resets \docommando
  {\doifsymboldefinedelse{#1}
     {\edef\currentitemsymbol{#1}%
      \setxvalue{\@@globalitemsymbol\itemlevel}{\currentitemsymbol}%
      \setgvalue{\@@localitemsymbol \itemlevel}{\unknownitemsymbol}%
      \def\listitem{\symbol[\currentitemsymbol]}%
      \let\@@opsymbol\empty}% \let\docommando\gobbleoneargument}
     {\doifconversiondefinedelse{#1}
        {\edef\currentitemsymbol{#1}%
         \setxvalue{\@@globalitemsymbol\itemlevel}{\currentitemsymbol}%
         \setgvalue{\@@localitemsymbol \itemlevel}%
           {\convertnumber{\currentitemsymbol}{\countervalue{\@@itemcounter\itemlevel}}}%
         \iftextitems
           \doifsomething{\getitemparameter\itemlevel\c!lefttext}
             {\let\tempsymbol\empty}%
         \fi
         \def\listitem
           {\getitemparameter\itemlevel
              {\iftextitems\c!lefttext\else\c!left\fi}%
            \getvalue{\@@localitemsymbol\itemlevel}\tempsymbol
            \getitemparameter\itemlevel
              {\iftextitems\c!righttext\else\c!right\fi}}%
        \let\@@opsymbol\empty}%\let\docommando\gobbleoneargument}
       {}}}

\def\calculatelistwidth#1#2% distance deals with 'broad'
  {#2=\getitemparameter{#1}\c!distance\relax
   \ifnum\getitemparameter{#1}\c!factor>\zerocount
     \ifdim#2=\zeropoint #2=.5em\fi
   \fi
   \multiply#2 \getitemparameter{#1}\c!factor
   \advance #2 \getitemparameter{#1}\c!width\relax}

% The next conditionals deal with \item \startitemgroup. It
% looks like a hack to skip back, but that way we preserve
% the indentation and bullet placement. It's a rather
% untested feature.

\newconditional\concatnextitem     \setfalse\concatnextitem
\newconditional\autoconcatnextitem \settrue \autoconcatnextitem
\newsignal     \itemsignal

\def\startitemgroup
  {\dotripleempty\dostartitemgroup}

\def\dostartitemgroup[#1][#2][#3]%
  {\bgroup
   \def\currentitemgroup{#1}%
   \ifthirdargument
     \dodostartitemgroup[#2][#3]%
   \else
     \doifassignmentelse{#2}
       {\dodostartitemgroup[][#2]}
       {\dodostartitemgroup[#2][]}%
   \fi}

\def\dodostartitemgroup[#1]% [#2]%
  {\relax % prevents lookahead
   \ifnum\itemlevel=\maxitemlevel\relax
     \showmessage\m!layouts9\maxitemlevel
     \let\itemincrement\zerocount
   \else
     \let\itemincrement\plusone
   \fi
   \doglobal\increment(\itemlevel,\itemincrement)%
   \initializeitemgrouplevel\itemlevel % safeguard
   \edef\itemgroupoptions{\getitemparameter\itemlevel\c!option}%
   \ifx\itemgroupoptions\empty
     \edef\itemgroupoptions{#1}%
   \else
     \doifsomething{#1}{\edef\itemgroupoptions{\itemgroupoptions,#1}}%
   \fi
   \expanded{\redostartitemgroup[\itemgroupoptions]}}% [#2]

\def\redostartitemgroup[#1][#2]%
  {\setfalse\inlinelistitem % new, no indent (leftskip)
   \setfalse\concatnextitem % new, concat
   \ifhmode
     \ifconditional\autoconcatnextitem % new, concat
       \ifdim\lastskip=\itemsignal     % new, concat
         \settrue\concatnextitem       % new, concat
       \fi                             % new, concat
     \fi                               % new, concat
     \iftextitems\else\doifnotinset\v!text{#1}\par\fi % suboptimal
   \fi
   \begingroup
   \ifnum\itemlevel=\plusone % NIEUW
     \doadaptleftskip {\getitemparameter1\c!margin}%
     \doadaptleftskip {\getitemparameter1\c!leftmargin}%
     \doadaptrightskip{\getitemparameter1\c!rightmargin}%
   \fi
   \dosetraggedcommand{\getitemparameter\itemlevel\c!align}\raggedcommand
   \doifsomething{\getitemparameter\itemlevel\c!indenting}
     {% is \expanded needed?
      \expanded{\setupindenting[\getitemparameter\itemlevel\c!indenting]}}%
   \doifinset\v!columns{#1}%
     {\ifinsidecolumns\else\ifnum\itemcolumndepth=\zerocount
        \globallet\itemcolumndepth\itemlevel
        \getitemparameter\itemlevel\c!before
        \processfirstactioninset
          [#1]
          [  \v!one=>\!!counta1\relax,
             \v!two=>\!!counta2\relax,
           \v!three=>\!!counta3\relax,
            \v!four=>\!!counta4\relax,
            \v!five=>\!!counta5\relax,
         \s!unknown=>\@EA\!!counta\getitemparameter\itemlevel\c!n]%
        % new
% now handled in column routines
%         \edef\columneditemleftskip{\the\leftskip}%
%         \def\postprocesscolumnbox##1%
%           {\scratchdimen\columneditemleftskip
%            \divide\scratchdimen \nofcolumns
%            \hbox{\hskip\columneditemleftskip\hbox{\box##1}}}%
%         \scratchdimen-\columneditemleftskip
%         \multiply\scratchdimen \nofcolumns
%         \advance\scratchdimen \columneditemleftskip
%         \advance\scratchdimen \hsize
%         \edef\columntextwidth{\the\scratchdimen}%
%         \leftskip\zeropoint
        % so far
        \startcolumns
          [\c!n=\!!counta, % netter \??op\itemlevel\c!n
           \c!height=,
           \c!rule=\v!off,
           \c!balance=\v!yes,
           \c!align=\v!no]%
      \fi\fi}%
   \doifinsetelse\v!intro{#1}\itemintrotrue\itemintrofalse
   \doglobal\increment\noflists
   \let\currentlist\noflists
   \newcounter\noflistelements
   \headitemfalse
   \subitemfalse
   \symbolitemfalse
   \let\marsymbol\relax
   \globallet\somdestination\empty
   \let\symsymbol\empty
   \the\itemgroupcommands
   \setitemlevel{#1}%
  %\getitemparameter\itemlevel\empty
   \let\listitem\empty % ** start value
   \doifelsenothing{#1} % iffirstargument
     {\edef\@@opsymbol{\getitemparameter\itemlevel\c!symbol}%
      \letgvalueempty{\@@globalitemsymbol\itemlevel}%
      \global\letitemparameter\itemlevel\v!continue\empty
    % \setitemmark\@@opsymbol % ** default value
      \dosetupitemgroupvariable[\itemlevel][#2]}
     {\dosetupitemgroupconstant[\itemlevel][#1]%
      \dosetupitemgroupvariable[\itemlevel][#2]%
      \doifinsetelse\v!continue{#1}% \noexpand, else problems in non-etex with chinese
        {\edef\@@opsymbol{\noexpand\getvalue{\@@globalitemsymbol\itemlevel}}%
         \getitemparameter\itemlevel\v!continue}
        {\edef\@@opsymbol{\noexpand\getitemparameter{\itemlevel}{\c!symbol}}%
         \global\setitemparameter\itemlevel\v!continue
           {\dosetupitemgroupconstant[\itemlevel][#1]%
            \dosetupitemgroupvariable[\itemlevel][#2]}}%
      \def\docommando##1% \setitemmark resets \docommando
        {\doifnot{##1}{0}{\setitemmark{##1}}}%
    % \processcommalist[#1,\@@opsymbol]\docommando
      \processcommalist[#1]\docommando}% ** preset sequence or provided sequence
   \ifx\listitem\empty
     \setitemmark\@@opsymbol % ** default value
     \ifx\listitem\empty
       \edef\currentitemsymbol{\itemlevel}% ** fall back
     \fi
   \fi
   \ifautoitemintro\ifnum\prevgraf<3
     \itemintrotrue
   \fi\fi
   \ifparagraphitems
     \ifnum\itemlevel>\plusone
       \letitemparameter\itemlevel\c!inbetween\empty
     \fi
   \else\ifpackeditems
     \letitemparameter\itemlevel\c!inbetween\empty
   \fi\fi
   \calculatelistwidth\itemlevel{\dimen0}%
   \ifdim\dimen0>\zeropoint\relax
     \ifconditional\inlinelistitem\else
       \advance\leftskip \dimen0\relax
     \fi
   \fi}

% test / example
%
% \startnarrower[left] \startcolumns[n=3] \startitemize
% \item \input ward \item \input ward \item \input ward
% \stopitemize \stopcolumns\stopnarrower \blank
%
% \startnarrower[left] \startitemize[columns,three]
% \item \input ward \item \input ward \item \input ward
% \stopitemize \stopnarrower \blank
%
% \setupitemize[leftmargin=1.5em] \startitemize[columns,three]
% \item \input ward \item \input ward \item \input ward
% \stopitemize \blank

\def\stopitemgroup
  {\iftextitems
     \removeunwantedspaces\space\ignorespaces
   \else
     \par
   \fi
   \ifnum\itemcolumndepth=\zerocount \dolistreference \fi % beware !
   \iffirstlist \else \endgroup \fi % toegevoegd, eerste \som opent groep
   \ifnum\itemcolumndepth=\itemlevel\relax
     \stopcolumns
     \doglobal\newcounter\itemcolumndepth
     \getitemparameter\itemlevel\c!after
   \else
     \ifnum\itemlevel=\plusone
       \doitembreak\allowbreak           % toegevoegd
       \getitemparameter1\c!after
       \dochecknextindentation\??oo
     \else
       % nieuw, not yet nobreak handling
       \ifcase\autoitemgroupspacing
         \getitemparameter\itemlevel\c!after
       \or
         \getitemparameter\itemlevel\c!after
       \fi
     \fi
   \fi
   \endgroup
   \doglobal\decrement(\itemlevel,\itemincrement)%
   \egroup
   % new needed in sidefloats (surfaced in volker's proceedings)
   \iftextitems\else\par\fi}

\newtoks\itemgroupcommands

\def\itemgroupitem
  {\doitemgroupitem}

\def\itemgroupbutton[#1]%
  {\gdef\somdestination{#1}%
   \itemgroupitem}

\def\itemgroupdummy
  {\itemgroupsymbol{\strut}\strut}

\def\itemgroupsubitem
  {\subitemtrue\itemgroupitem}

\def\itemgroupsymbol#1%
  {\def\symsymbol{\doitemattributes\itemlevel\c!symstyle\c!symcolor{#1}}%
   \symbolitemtrue
   \itemgroupitem}

\def\itemgroupedge#1%
  {\itemgroupsymbol
     {\calculatelistwidth\itemlevel{\dimen0}%
      \hbox to \dimen0
        {#1\hskip\getitemparameter\itemlevel\c!distance}}}

\def\itemgrouphead
  {\headitemtrue\doitemgrouphead}

\def\itemgroupitems
  {\dosingleempty\doitemgroupitems}

\def\doitemgroupitems[#1]%
  {\itemgroupedge
     {\dorecurse{0\getitemparameter\itemlevel\c!items}{\listitem\hss}%
      \unskip}}

\def\itemgroupmargin#1%
  {\def\marsymbol
     {\llap
        {\doitemattributes\itemlevel\c!marstyle\c!marcolor{#1}%
         \hskip\leftskip\hskip\leftmargindistance}}%
   \itemgroupitem}

\appendtoks \let\item        \itemgroupitem    \to \itemgroupcommands
\appendtoks \let\itm         \itemgroupitem    \to \itemgroupcommands
\appendtoks \let\but         \itemgroupbutton  \to \itemgroupcommands
\appendtoks \let\nop         \itemgroupdummy   \to \itemgroupcommands
\appendtoks \letvalue\v!sub  \itemgroupsubitem \to \itemgroupcommands
\appendtoks \letvalue\v!sym  \itemgroupsymbol  \to \itemgroupcommands
\appendtoks \letvalue\v!ran  \itemgroupedge    \to \itemgroupcommands
\appendtoks \letvalue\v!head \itemgrouphead    \to \itemgroupcommands
\appendtoks \letvalue\v!its  \itemgroupitems   \to \itemgroupcommands
\appendtoks \letvalue\v!mar  \itemgroupmargin  \to \itemgroupcommands

% Sometimes the user demands get pretty weird:
%
% \startitemize
%   \item test
%   \item test
%   \headsym{xx} test \par test
% \stopitemize

\def\itemgroupheadsym#1%
  {\def\symsymbol{\doitemattributes\itemlevel\c!symstyle\c!symcolor{#1}}%
   \symbolitemtrue
   \headitemtrue
   \doitemgrouphead}

\appendtoks \let\headsym    \itemgroupheadsym \to \itemgroupcommands

\def\itembreak   % -10
  {\flushnotes\penalty-5\relax}

\def\itemnobreak %  +5
  {\flushnotes\penalty+5\ifinsidecolumns\else00\fi\relax}

\def\dolistitem % evt aantal items opslaan per niveau, scheelt zoeken
  {\iftextitems
    % begin of item
   \else
     \par
   \fi
   \ignorespaces
   \increment\noflistelements
   \ifnum\itemcolumndepth=\zerocount \ifoptimizeitems
     \ifnum\noflistelements=\plusone        % tgv bv kolommen/nesting
       \findtwopassdata\s!list{\noflists:}% % wordt soms de volgorde
     \fi                                    % verstoord, vandaar \find
     \iftwopassdatafound
       \ifcase0\twopassdata\relax \twopassdatafoundfalse \fi
     \fi
     \iftwopassdatafound
       \ifnum\twopassdata=3
         \ifnum\noflistelements>1
           \doitembreak\itemnobreak
         \fi
       \else\ifnum\twopassdata>3
         \ifnum\noflistelements=2
           \ifitemintro
             \doitembreak\nobreak
           \else
             \doitembreak\itemnobreak
           \fi
         \else\ifnum\twopassdata=\noflistelements\relax
           \doitembreak\itemnobreak
         \else\ifnum\noflistelements>2
           \doitembreak\itembreak
         \else
           \ifitemintro\else\doitembreak\itembreak\fi
         \fi\fi\fi
       \fi\fi
     \fi
   \fi\fi
   \noindent
   \setbox8\hbox
     {\ifheaditem
        \doitemattributes\itemlevel\c!headstyle\c!headcolor{\listitem}%
      \else\ifsymbolitem
        \symsymbol
      \else
        \doitemattributes\itemlevel\c!style\c!color{\listitem}%
      \fi\fi}%
   \doifsomething\somdestination
     {\setbox8\hbox{\goto{\box8}[\somdestination]}}%
   \globallet\somdestination\empty
   \dimen2=\getitemparameter\itemlevel\c!width\relax
   % new, prevents loops when symbol is (not yet found) graphic
   \ht8=\strutheight
   \dp8=\strutdepth
   % so that content differs per run (esp mp graphics afterwards)
\checkforrepeatedlistitem
   \ifdim\dimen2<\zeropoint\relax
     \llap{\ifsubitem\llap{+}\fi\box8\hskip\leftmargindistance}%
   \else
     \ifdim\dimen2=\zeropoint\relax
       \calculatelistwidth1{\dimen0}%
     \else
       \calculatelistwidth\itemlevel{\dimen0}%
     \fi
     \iftextitems
       \hbox{\ifsubitem+\fi\box8\hskip\fontdimen2\font}\nobreak
     \else
       \ifconditional\inlinelistitem
         \hbox to \dimen0{\ifsubitem\llap{+}\fi\box8\hfill}%
       \else
         % todo: align+marge binnen de hbox
         \llap{\hbox to \dimen0{\ifsubitem\llap{+}\fi\box8\hfill}}%
       \fi
     \fi
   \fi
\forceunexpanded % needed for m conversion (\os) / i need to look into this
   \setevalue{\@@currentitemsymbol\itemlevel}%
     {\getvalue{\@@localitemsymbol\itemlevel}}% still problems with \uchar ?
    %{\noexpand\getvalue{\@@localitemsymbol\itemlevel}}% no, spoils subrefs
   \resetunexpanded
   \headitemfalse
   \subitemfalse
   \symbolitemfalse
   \EveryPar{\ignorespaces}%
   \ignorespaces}

% For Frank Grieshaber and Mojca Miklavec:

\newconditional\repeatlistitem

\def\checkforrepeatedlistitem
  {\ifnum\itemlevel=\plusone \ifnum\itemlevel=\plusone
     \initializeboxstack{item}%
   \fi \fi
   \ifconditional\repeatlistitem
     \savebox{item}{\itemlevel}{\hbox{\ifnum\itemlevel>\plusone \copy8\else\fi}}%
     \setbox8\hbox
       {\setbox\scratchbox\hbox{\foundbox{item}{\itemlevel}}%
        \ifnum\itemlevel>\plusone
          \hskip-\wd\scratchbox
          \ifnum\countervalue{\@@itemcounter\itemlevel}>\plusone
            \llap{\box\scratchbox}%
          \fi
        \fi
        \box8}%
   \fi}

\chardef\autoitemgroupspacing=2 % 0 = voor/na, 1=tussen als geen voor 2=(prev)tussen=old/normal

\def\complexdoitemgroupitem[#1]%
  {\iftextitems
     % begin of item
   \else
     \par
   \fi
   \ignorespaces
   \ifconditional\concatnextitem % new, concat
     \doitembreak\nobreak        % new, concat
   \fi                           % new, concat
   \doadvanceitem
   \ifnum\itemcolumndepth=0\relax\ifnum\noflistelements>0\relax
     \doitembreak\nobreak
   \fi\fi
   \iffirstlist
     \firstlistfalse
     \begingroup
     \ifcase\itemlevel
     \or % 1
       \ifnum\itemcolumndepth=0\relax
         \ifitemintro\doitembreak\nobreak\fi
         \getitemparameter1\c!before
         \ifitemintro\doitembreak\nobreak\fi
       \fi
     \else % 2 en hoger
       \ifparagraphitems \else
         \let\previtemlevel\itemlevel
         \decrement\previtemlevel
         \ifcase\autoitemgroupspacing\relax % nieuw
           \getitemparameter\itemlevel\c!before
         \or
            \doifelsenothing{\getitemparameter\itemlevel\c!before}
              {\getitemparameter\itemlevel\c!before}
              {\getitemparameter\previtemlevel\c!inbetween}%
         \else
           \getitemparameter\previtemlevel\c!inbetween % == itemlevel-1
         \fi
       \fi
     \fi
   \else
     \getitemparameter\itemlevel\c!inbetween
   \fi
   \ifconditional\concatnextitem % new, concat
     \vskip-\lastskip            % new, concat
     \vskip-\lineheight          % new, concat
     \nobreak                    % new, concat
   \fi                           % new, concat
   \ignorespaces
   \dolistitem
   \ifpackeditems
     \setupwhitespace[\v!none]%
   \fi
   \getitemparameter\itemlevel\c!inner
   \marsymbol
   \let\marsymbol\relax
   \doifsomething{#1}
     {\doifnot\itemreference\unknownitemreference
        {\bgroup
         \protectconversion
         \rawreference\s!lst{#1}\itemreference
         \egroup}}%
   \strut % added 11-08-99
   \setfalse\concatnextitem % new, concat
   \hskip\itemsignal        % new, concat
   \ignorespaces}

\def\complexitem[#1]#2\par % todo: no two pass data
  {\startitemgroup[#1]
   \complexdoitemgroupitem[]\ignorespaces\begstrut#2\unskip\endstrut\par
   \stopitemgroup}

\definecomplexorsimpleempty\item
\definecomplexorsimpleempty\doitemgroupitem

\def\complexhead[#1]#2\par#3\par
  {\startitemgroup[#1]%
   \complexdoitemgrouphead[]\ignorespaces#2\par#3\par
   \stopitemgroup}

% \def\complexdoitemgrouphead[#1]#2\par% % beter in \complexdosom hangen met een if
%   {\iffirstlist\else\doitembreak\allowbreak\fi
%    \ifpackeditems\else\getitemparameter\itemlevel\c!beforehead\fi
%    \iffirstlist\ifitemintro\else\ifcase\itemlevel % incr in \complexdosom
%       \doitembreak\allowbreak
%    \fi\fi\fi
%    \complexdoitemgroupitem[#1]{\doitemattributes\itemlevel\c!headstyle\c!headcolor
%      {\ignorespaces#2}}%
%    \iftextitems
%      \removeunwantedspaces\space\ignorespaces
%    \else
%      \par
%    \fi
%    \doitembreak\nobreak
%    \ifpackeditems\else\getitemparameter\itemlevel\c!afterhead\fi
%    \doitembreak\nobreak
%    \noindentation}
%
% the next solution accepts \head test \type{x{x}x} test ...

\def\dostartitemattributes#1{\dostartattributes{\??op\currentitemgroup#1}}
\def\dostopitemattributes   {\dostopattributes}

\def\complexdoitemgrouphead[#1]% beter in \complexdosom hangen met een if
  {\iffirstlist\else\doitembreak\allowbreak\fi
   \ifpackeditems\else\getitemparameter\itemlevel\c!beforehead\fi
   \iffirstlist\ifitemintro\else\ifcase\itemlevel % incr in \complexdosom
     \doitembreak\allowbreak
   \fi\fi\fi
   \complexdoitemgroupitem[#1]%
     \bgroup
     \dostartitemattributes\itemlevel\c!headstyle\c!headcolor\empty
     \ignorespaces
     \let\par\enditemhead} % brrrr but simple anyway

\def\enditemhead
  {\removeunwantedspaces
   \dostopitemattributes
   \egroup
   \iftextitems
     \space\ignorespaces
   \else
     \par
   \fi
   \doitembreak\nobreak
   \ifpackeditems\else\getitemparameter\itemlevel\c!afterhead\fi
   \doitembreak\nobreak
   \noindentation}

\definecomplexorsimpleempty\head
\definecomplexorsimpleempty\doitemgrouphead

% \def\sym#1%
%   {\noindent
%    \begingroup
%    \setbox\scratchbox\hbox{\trialtypesettingtrue#1}%
%    \setbox\scratchbox\hbox
%      \ifdim\wd\scratchbox<1em to 1.5\else spread 1\fi em{#1\hfil}%
%    \hangindent\wd\scratchbox
%    \box\scratchbox
%    \endgroup
%    \ignorespaces}

\def\sym#1%
  {\noindent
   \begingroup
   \setbox\scratchbox\hbox{\trialtypesettingtrue#1}%
   \setbox\scratchbox\hbox
     \ifdim\wd\scratchbox<1em to 1.5\else spread 1\fi em{#1\hfil}%
   \expanded{\box\scratchbox\endgroup\hangindent\the\wd\scratchbox}%
   \ignorespaces}

\setupitemgroups % undocumented
  [\c!levels=6,
   \c!margin=\zeropoint,
   \c!leftmargin=\zeropoint,
   \c!rightmargin=\zeropoint,
   \c!indentnext=\v!yes,
   \c!width=1.5em,
   \c!factor=0,
   \c!distance=.5em,
  %\c!align=\v!normal, % definitely not \v!normal, see mails and
   \c!align=, % debug reports of David A & Patrick G on context list
   \c!color=,
   \c!indenting=, % untouched if empty
   \c!color=,
   \c!style=, % kan tzt weg
   \c!marstyle=\c!type,  % \c! ???
   \c!symstyle=,
   \c!headstyle=,
   \c!marcolor=,
   \c!symcolor=,
   \c!headcolor=,
   \c!beforehead=,
   \c!afterhead=\blank,
   \c!before=\blank,
   \c!inbetween=\blank,
   \c!after=\blank,
   \c!stopper=.,
   \c!placestopper=\v!yes,
   \c!inner=,
   \c!n=2,
   \c!items=4,
   \c!lefttext=(,
   \c!righttext=),
   \c!start=1,
   \c!option=,
   \c!symbol=\itemlevel] % \v!niveau

\def\defineitemgroup
  {\dodoubleempty\dodefineitemgroup}

\def\dodefineitemgroup[#1][#2]%
  {\doifsomething{#1}
     {\pushmacro\currentitemgroup
      \def\currentitemgroup{#1}%
      \setvalue{\e!start#1}{\startitemgroup[#1]}%
      \setvalue{\e!stop#1}{\stopitemgroup}%
      \setvalue{\e!setup#1\e!endsetup}{\setupitemgroup[#1]}%
      \getparameters[\??ig#1][\c!levels=3,#2]%
      \ifnum\getvalue{\??ig#1\c!levels}<\maxitemlevel\relax
        \letvalue{\??ig#1\c!levels}\maxitemlevel
      \fi
      \dorecurse{\getvalue{\??ig#1\c!levels}}{\initializeitemgrouplevel\recurselevel}%
      \popmacro\currentitemgroup}}

% efficient default itemize as well as upward compatible
% definition:

\defineitemgroup [\v!itemize] [\c!levels=6]

% keep these, needed for styles:

% \def\startitemize {\startitemgroup[\v!itemize]}
% \def\stopitemize  {\stopitemgroup}
% \def\setupitemize {\setupitemgroup[\v!itemize]}

\protect \endinput
