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

%D In retrospect I should have gone futher and move more to the
%D \LUA\ end but here we are now. Maybe some day.

\writestatus{loading}{ConTeXt Structure Macros / Sectioning}

\unprotect

\startcontextdefinitioncode

\installcorenamespace{structure}

\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters

\setupstructure % not a user command so we might need to change the name
  [\c!number=,
   \c!level=,
   \c!name=,
   \c!title=,
   \c!bookmark=,
   \c!marking=,
   \c!list=,
   \c!label=,
   \c!coupling=,
   \c!ownnumber=,
 % \c!interaction=\v!list,
   \c!sectionseparatorset=\s!default,
   \c!sectionconversionset=\s!default,
   \c!sectionstopper=,
   \c!sectionstarter=,
   \c!sectionsegments=,
   \c!sectionresetset=,
   \c!reference=,
   \c!backreference=,
   \c!expansion=\v!no,
   \c!xmlsetup=,
   \s!catcodes=,
   \c!saveinlist=\v!yes]

% maybe flags for list, bm, mark

\def\m_strc_references_prefix_yes{+}
\def\m_strc_references_prefix_nop{-}

\let\currentstructurereferenceprefix\empty

\installglobalmacrostack\currentstructurereferenceprefix

\def\strc_sectioning_set_reference_prefix
  {\ifx\currentstructurereferenceprefix\empty
     % nothing
   \else\ifx\currentstructurereferenceprefix\m_strc_references_prefix_yes
     \global\advance\prefixcounter \plusone % temp here
     \setupglobalreferenceprefix[\the\prefixcounter]%
   \else\ifx\currentstructurereferenceprefix\m_strc_references_prefix_nop
     \setupglobalreferenceprefix[]%
   \else
     \setupglobalreferenceprefix[\currentstructurereferenceprefix]%
   \fi\fi\fi
   \glet\currentstructurereferenceprefix\referenceprefix}

% why xdef ?

\setupstructure
  [\c!label={\headparameter{\currentsectionblock\c!label}},
   \c!incrementnumber=\ifconditional\c_strc_sectioning_increment\v!yes\else\v!no\fi, % not that needed
   \c!saveinlist=\ifconditional\c_strc_sectioning_to_list\v!yes\else\v!no\fi,
   \c!level=\currentheadlevel,
   \c!number=\ifconditional\c_strc_sectioning_increment\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi,
   \c!expansion=\headparameter\c!expansion,
   \c!xmlsetup=\headparameter\c!xmlsetup,
   \s!catcodes=\headparameter\s!catcodes,
   \c!sectionresetset=\headparameter\c!sectionresetset,
   \c!sectionseparatorset=\headparameter\c!sectionseparatorset,
   \c!sectionconversionset=\headparameter\c!sectionconversionset,
   \c!sectionconversion=\headparameter\c!conversion, % just for compatibility
   \c!sectionstarter=\headparameter\c!sectionstarter,
   \c!sectionstopper=\headparameter\c!sectionstopper,
   \c!sectionset=\headparameter\c!sectionset,
   \c!sectionsegments=\headparameter\c!sectionsegments,
   \c!reference=\headparameter\c!reference,
   \c!referenceprefix=\headparameter\c!referenceprefix,
   \c!criterium=\headparameter\c!criterium]

% see lists/neat-001.tex for usage of:

\def\namedstructureheadlocation#1% expandable, maybe [#1]
  {\csname\??savedinternalreference\ifcsname\??savedinternalreference#1\endcsname#1\else\s!default\fi\endcsname}

% The next directive only makes sense when we have sort of garanteed outcome (math is not so
% nice for instance).
%
% \enabledirectives[references.bookmarks.preroll]

\newconditional\c_strc_bookmarks_preroll

\installtexdirective
  {references.bookmarks.preroll}
  {\settrue \c_strc_bookmarks_preroll}
  {\setfalse\c_strc_bookmarks_preroll}

\def\strc_sectioning_autobookmark#1%
  {\begingroup
 % \settrialtypesetting
   \the\everypreroll
   \nodestostring\tempstring{#1}%
   \glet\currentstructurebookmark\tempstring
   \endgroup}

% zeros:
%
% \setuphead[subsection][criterium=all]
%
% \dorecurse{3} {
%     \chapter{Blabla}                 \subsection{bla 1 1} \subsection{bla 1 2}
%                      \section{bla 2} \subsection{bla 2 1} \subsection{bla 2 2}
% }

\unexpanded\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported)
  {\begingroup
   \setupstructure[\c!name={#1},#2]%
   \xdef\currentstructurename           {\structureparameter\c!name}%
   \xdef\currentstructurecoupling       {\structureparameter\c!coupling}%
   \xdef\currentstructureownnumber      {\structureparameter\c!ownnumber}% optional own number
   \xdef\currentstructurelevel          {\structureparameter\c!level}%
   \edef\currentstructureexpansion      {\structureparameter\c!expansion}%
   \xdef\currentstructurexmlsetup       {\structureparameter\c!xmlsetup}%
   \xdef\currentstructurecatcodes       {\structureparameter\s!catcodes}%
   \xdef\currentstructurelabel          {\structureparameter\c!label}%
   \xdef\currentstructurereference      {\structureparameter\c!reference}%
   \xdef\currentstructurereferenceprefix{\structureparameter\c!referenceprefix}%
   \xdef\currentstructurebackreference  {\structureparameter\c!backreference}%
   \xdef\currentstructureshownumber     {\structureparameter\c!number}%
   \xdef\currentstructuresaveinlist     {\structureparameter\c!saveinlist}%
   \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}%
   \ifx\currentstructureexpansion\s!xml
     \xmlstartraw
       \xdef\currentstructuretitle   {\structureparameter\c!title}%
       \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
       \xdef\currentstructuremarking {\structureparameter\c!marking}%
       \xdef\currentstructurelist    {\structureparameter\c!list}%
     \xmlstopraw
     \iflocation \ifx\currentstructurebookmark\empty \ifconditional\c_strc_bookmarks_preroll
       \strc_sectioning_autobookmark\currentstructuretitle
     \fi \fi \fi
     \ifx\currentstructurelist\empty
       \glet\currentstructurelist\currentstructuretitle
     \fi
     \glet\currentstructurecoding\s!xml
   \else
     \ifx\currentstructureexpansion\v!yes
       \xdef\currentstructuretitle   {\structureparameter\c!title}%
       \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
       \xdef\currentstructuremarking {\structureparameter\c!marking}%
       \xdef\currentstructurelist    {\structureparameter\c!list}%
       \iflocation \ifx\currentstructurebookmark\empty \ifconditional\c_strc_bookmarks_preroll
         \strc_sectioning_autobookmark\currentstructuretitle
       \fi \fi \fi
     \else
       \xdef\currentstructuretitle   {\detokenizedstructureparameter\c!title}%
       \xdef\currentstructurebookmark{\detokenizedstructureparameter\c!bookmark}%
       \xdef\currentstructuremarking {\detokenizedstructureparameter\c!marking}%
       \xdef\currentstructurelist    {\detokenizedstructureparameter\c!list}%
       \iflocation \ifx\currentstructurebookmark\empty
         \ifconditional\c_strc_bookmarks_preroll
           \strc_sectioning_autobookmark{\structureparameter\c!title}%
         \else
           \begingroup
           \simplifycommands
           \xdef\currentstructurebookmark{\detokenize\expandafter{\normalexpanded{\structureparameter\c!title}}}%
           \endgroup
         \fi
       \fi \fi
     \fi
     \ifx\currentstructurelist\empty
       \glet\currentstructurelist\currentstructuretitle
     \fi
     \glet\currentstructurecoding\s!tex
   \fi
   \setnextinternalreference
   \storeinternalreference\currentstructurename{\the\locationcount}%
   \strc_sectioning_set_reference_prefix
   \clf_setsectionentry
        references {
            internal      \locationcount
          % block         {\currentsectionblock}
            prefix        {\currentstructurereferenceprefix}
            reference     {\currentstructurereference}
            backreference {\currentstructurebackreference}
        }
        directives {
            resetset {\structureparameter\c!sectionresetset}
        }
        metadata {
            kind      {section}
            name      {\currentstructurename}
            catcodes  \ifx\currentstructurecatcodes\empty\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi\space
            coding    {\currentstructurecoding}
        \ifx\currentstructurecoding\s!xml
            xmlroot   {\xmldocument}
        \fi
        \ifx\currentstructurexmlsetup\empty \else
            xmlsetup  {\currentstructurexmlsetup}
        \fi
        \ifx\currentstructuresaveinlist\v!no
            nolist \space true\space
        \fi
        \ifx\currentstructureincrementnumber\v!yes
            increment {\currentstructureincrementnumber}
        \fi
        }
        titledata {
            label    {\detokenize\expandafter{\currentstructurelabel}}
            title    {\detokenize\expandafter{\currentstructuretitle}}
        \ifx\currentstructurebookmark\currentstructuretitle \else
            bookmark {\detokenize\expandafter{\currentstructurebookmark}}
        \fi
        \ifx\currentstructuremarking\currentstructuretitle \else
            marking  {\detokenize\expandafter{\currentstructuremarking}}
        \fi
        \ifx\currentstructuresaveinlist\v!no \else
          \ifx\currentstructurelist\currentstructuretitle \else
            list     {\detokenize\expandafter{\currentstructurelist}}
          \fi
        \fi
        }
        numberdata {
          % block         {\currentsectionblock}
        \ifx\currentstructureshownumber\v!no
            hidenumber    \space true\space % space needed for parser
        \fi
            separatorset  {\structureparameter\c!sectionseparatorset}
            conversionset {\structureparameter\c!sectionconversionset}
            conversion    {\structureparameter\c!sectionconversion}
            starter       {\structureparameter\c!sectionstarter}
            stopper       {\structureparameter\c!sectionstopper}
            set           {\structureparameter\c!sectionset}
            segments      {\structureparameter\c!sectionsegments}
            ownnumber     {\currentstructureownnumber}
            language      {\currentlanguage}% for the moment, needed for bookmarks conversion
            criterium     {\structureparameter\c!criterium}
        }
        userdata {\detokenize{#3}}% will be converted to table at the lua end
   \relax
   \xdef\currentstructurelistnumber{\clf_currentsectiontolist}%
 % \currentstructuresynchronize has to be called someplace, since it introduces a node
   \setstructuresynchronization\currentstructurelistnumber
   \endgroup}

\let\currentsectioncountervalue \!!zerocount % redefined later
\let\previoussectioncountervalue\!!zerocount % redefined later

% We can access the (stored) data with the following macros.
%
% \def\MyHeadCommand  #1#2{\framed{#1}\framed{#2 / \structureuservariable{subtitle}}}
% \def\MyListCommand#1#2#3{\externalfigure[\structurelistuservariable{figure}][height=5mm]#2}
%
% \setuphead[chapter][command=\MyHeadCommand]
% \setuplist[chapter][alternative=command,command=\MyListCommand]
%
% \starttext
%     \setupheadertexts[chapter]
%     \setupinteraction[state=start]
%     \placebookmarks[chapter]
%     \placelist[chapter]
%     \startchapter[ownnumber=10,title=Ton,list=Hans,marking=Kees,bookmark=Bram][figure=cow.pdf,subtitle=oeps]
%     \stopchapter
% \stoptext

% todo: #1 => "#1" ... adapt lua code for name and number

\def\structurenumber               {\clf_structurenumber}
\def\structuretitle                {\clf_structuretitle}
\def\structurevariable           #1{\clf_structurevariable         {#1}}
\def\structureuservariable       #1{\clf_structureuservariable     {#1}}
\def\structurecatcodedget        #1{\clf_structurecatcodedget      {#1}}    % bad name
\def\structuregivencatcodedget #1#2{\clf_structuregivencatcodedget {#1}#2 } % bad name
\def\structureautocatcodedget  #1#2{\clf_structureautocatcodedget  {#1}{#2}}
\def\namedstructurevariable    #1#2{\clf_namedstructurevariable    {#1}{#2}}
\def\namedstructureuservariable#1#2{\clf_namedstructureuservariable{#1}{#2}}

% compatibility issue:
%
% \def\setfullsectionnumber #1{}
% \def\preparefullnumber    #1{}
% \def\fullsectionnumber    {1--1--1}
% \def\makesectionnumber    [#1]{}
% \def\makesectionformat    {}
% \def\sectionformat        {1--1-1-1-1-1-1}
% \def\composedsectionnumber{}
% \def\@@kolist{}

% \setuphead[section]   [separator=\separatorlist{?,!,*}]
% \setuphead[subsection][separator=\separatorlist{??,!!,**}]
%
% \let\spr\separatorlist % this will enable this feature
%
% \setuphead[section]   [separator={?,!,*}]
% \setuphead[subsection][separator={??,!!,**}]
%
% \setupheads[separator={A,B,C,D,E,F}]
% \chapter{test}
% \section{test} \subsection{test} \subsection{test}
% \section{test} \subsection{test} \subsection{test}

% lua interface / names and interface might change

% \newconditional\c_strc_rendering_continuous % not used (mkii ?)

\def\setstructurelevel         #1#2{\clf_setstructurelevel         {#1}{#2}}         % name, level|parent
\def\getstructurelevel           #1{\clf_getstructurelevel         {#1}}             % name
\def\setstructurenumber        #1#2{\clf_setstructurenumber         #1{#2}}          % level, number (+/-)
\def\getstructurenumber          #1{\clf_getstructurenumber         \numexpr#1\relax} % level
\def\getsomestructurenumber    #1#2{\clf_getsomestructurenumber     #1{#2}}           % level, what
\def\getfullstructurenumber      #1{\clf_getfullstructurenumber     \numexpr#1\relax} % level
\def\getsomefullstructurenumber#1#2{\clf_getsomefullstructurenumber #1{#2}}           % level, what
\def\getspecificstructuretitle   #1{\clf_getspecificstructuretitle {#1}{\headparameter\s!catcodes}}

% structure heads (like \startchapter)

% \c!deeptextcommand, \c!deepnumbercommand: undefined !
% \c!before \c!after \c!distance
% \c!page \c!header  \c!text \c!footer=,
% \c!numbercommand \c!textcommand \c!ownnumber \c!number
% \c!file \c!grid \c!margintext
% \c!expansion \c!xmlsetup \s!catcode

\installcorenamespace{head}
\installcorenamespace{headlevel}
\installcorenamespace{headincrement}
\installcorenamespace{headplace}
\installcorenamespace{headmarkyes}
\installcorenamespace{headmarknop}

\installcommandhandler \??head {head} \??head

\installmacrostack\currenthead
\installmacrostack\currentheadparent

\setuphead [%
    %\c!after=,
    %\c!align=,
    %\c!aligntitle=,
    \c!alternative=\v!normal,
    %\c!before=,
    %\c!color=,
    %\c!command=,
    \c!continue=\v!yes,
    %\c!coupling=,
    %\c!deepnumbercommand=,
    %\c!deeptextcommand=,
    %\c!default=,
    \c!distance=\zeropoint,
    \c!textdistance=\zeropoint,
    \c!textwidth=\zeropoint,   % signal too
    \c!numberwidth=\zeropoint, % signal too
    \c!width=\zeropoint,       % signal too
    \c!expansion=\v!no,
    %\c!file=,
    %\c!footer=,
    %\c!grid=,
    \c!hang=\v!none,
    %\c!header=,
    \c!incrementnumber=\v!yes,
    \c!indentnext=\v!no,
    %\c!label=,
    %\c!limittext=\languageparameter\c!limittext,
    \c!margin=\zeropoint,
    %\c!margintext=,
    \c!number=\v!yes,
    \c!numbercolor=\headparameter\c!color,
    \c!textcolor=\headparameter\c!color,
    \c!numberstyle=\headparameter\c!style,
    \c!textstyle=\headparameter\c!style,
    %\c!numbercommand=,
    %\c!textcommand=,
    \c!ownnumber=\v!no,
    %\c!page=,
    \c!placehead=\v!yes,
    \c!sectionconversionset=\s!default,
    \c!sectionnumber=\v!yes,
    %\c!sectionsegments=,
    \c!sectionseparatorset=\s!default,
    \c!sectionset=\v!all,
    \c!interlinespace=,
    %\c!sectionstopper=,
    %\c!sectionstarter=,
    %\c!strut=,
    %\c!style=,
    %\c!text=,
    %\c!tolerance=,
    %\c!beforesection=\directsetup{document:\currenthead:start},  % these might become defaults i.e. acpect document: namespace
    %\c!insidesection=\directsetup{document:\currenthead:inside}, % these might become defaults i.e. acpect document: namespace
    %\c!aftersection=\directsetup{document:\currenthead:stop},    % these might become defaults i.e. acpect document: namespace
   ]

\let\setupheads\setuphead % will go

\appendtoks
    \ifx\currentheadparent\empty
        \edef\currentheaddefault{\headparameter\c!default}%
        \edef\currentheadsection{\headparameter\c!section}%
        \ifx\currenthead\currentheaddefault
          \let\currentheadparent\currentheadsection
        \else\ifx\currentheaddefault\empty
          \let\currentheadparent\currentheadsection
        \else
          \let\currentheadparent\currentheaddefault
        \fi\fi
        \normalexpanded {%
            \setheadparameter{\c!label}{\currenthead}%
            \setheadparameter{\c!coupling}{\currenthead}%
            \setheadparameter{\s!parent}{\??head\currentheadparent}%
            \definemarking[\currenthead]         [\currentheadsection]%
            \definemarking[\currenthead\v!number][\currentheadsection]%
            \setupmarking [\currenthead]         [\c!filtercommand=\noexpand\sectionheadmarkingtitle {\currenthead}]%
            \setupmarking [\currenthead\v!number][\c!filtercommand=\noexpand\sectionheadmarkingnumber{\currenthead}]%
        }%
        \doifelselist\currenthead\donothing
          {\definelist[\currenthead][\c!prefix=\v!no]}%
        % we can't do this now for backward compatibility reasons
      % \doifelselist\currenthead\donothing
      %   {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}%
    \else
        \normalexpanded {%
            \setheadparameter{\c!label}{\currenthead}%
            \setheadparameter{\c!coupling}{\currentheadparent}%
            \definemarking[\currenthead]         [\currentheadparent]%
            \definemarking[\currenthead\v!number][\currentheadparent\c!number]%
        }%
        \doifelselist\currenthead\donothing
          {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}%
    \fi
    \presetlabeltext[\currenthead=]%
    \the\everysetuphead
\to \everydefinehead

\newtoks\everyredefinehead

\appendtoks
    \the\everyredefinehead
\to \everydefinehead

\appendtoks
   \setstructurelevel\currenthead{\thenamedheadlevel\currenthead}%
\to \everyredefinehead

\appendtoks
    % beware, this is a global register
    \begingroup
    \edef\currentsectionheadcoupling{\sectionheadcoupling\currenthead}%
    \edef\currentsectionheadsection {\sectionheadsection \currentsectionheadcoupling}%
    \edef\currentsectionlevel       {\sectionlevel       \currentsectionheadsection}%
    \clf_registersection {\currenthead} {
        coupling {\currentsectionheadcoupling}
        section  {\currentsectionheadsection}
        level    \space \currentsectionlevel \space % space needed for parser
        parent   {\currentheadparent}
    }%
    \endgroup
\to \everyredefinehead

\appendtoks
 % \setevalue{\e!next \currenthead}{\donexthead [\currenthead]}%
   \setuevalue{\e!start\currenthead}{\strc_sectioning_start[\currenthead]}%
   \setuevalue{\e!stop \currenthead}{\strc_sectioning_stop [\currenthead]}%
\to \everydefinehead

% so \subject as well as \section will need two commands when ownnumber
% is used (one can disable it anyway for subject) .. this is not downward
% compatible but better

\appendtoks
    \ifx\currenthead\empty \else
      \doifelse{\headparameter\c!ownnumber}\v!yes
        {\setuevalue\currenthead{\strc_sectioning_handle_own[\currenthead]}}
        {\setuevalue\currenthead{\strc_sectioning_handle_nop[\currenthead]}}%
    \fi
\to \everysetuphead

\unexpanded\def\doredefinehead#1#2% called at lua end
  {\push_macro_currenthead
   \push_macro_currentheadparent
   \edef\currenthead{#1}%
   \edef\currentheadparent{#2}%
   \the\everyredefinehead\relax
   \pop_macro_currentheadparent
   \pop_macro_currenthead}

\let\currentnamedsection\empty

\installmacrostack\currentnamedsection

\unexpanded\def\startnamedsection
  {\dotripleempty\strc_sectioning_start_named_section}

% todo: add grouping but where: before/after trickery .. probably inside because one can always add
% grouping to the before/after settings

\unexpanded\def\stopnamedsection
  {\normalexpanded{\strc_sectioning_stop[\currentnamedsection]}}

% structure sections (the parents of chapter etc)

\let\firstsectionname\empty
\let\lastsectionname \empty

\let\resetallstructuremarks            \relax
\let\resetcurrentstructuremarks        \relax
\let\resetcurrentstructuremarkswithpage\relax

\def\resetallstructuremarks            {\resetmarking[\firstsectionname]} % will become option (was \v!section-1)
\def\resetcurrentstructuremarks        {\resetmarking[\lastsectionname]}  % will become option
%def\resetcurrentstructuremarkswithpage{\resetmarking[\lastsectionname]}  % will become option

% We could use a commandhandler here but sections are somewhat special in the
% sense that we have two ways of chaining: the main section (levels) as well
% as rendering (head).

% -2 = text
% -1 = manual
%  0 = block
% +1 = structurelevel 1 .. n

\newcount\maxstructuredepth

\def\sectionlevel#1%
  {\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname}

\def\namedsectionlevel#1#2% direct indirect
  {\csname\??headlevel
     \ifcsname\??headlevel#1\endcsname
       #1%
     \else\ifcsname\??headlevel#2\endcsname
       #2%
     \else
       \v!none
     \fi\fi
   \endcsname}

\def\xthenamedheadlevel#1%
  {\namedsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}}

\setvalue{\??headlevel\v!block}{0}
\setvalue{\??headlevel\v!none }{-1}
\setvalue{\??headlevel\v!text }{-2}
\setvalue{\??headlevel\v!head }{-3}

\newtoks\everydefinesection

\unexpanded\def\definesection[#1]%
  {\ifcsname\??headlevel#1\endcsname \else
     \edef\currentsection{#1}% not used, will go
     \edef\currenthead{#1}%
     \global\advance\maxstructuredepth\plusone
     \setevalue{\??headlevel#1}{\the\maxstructuredepth}%
     \setstructurelevel{#1}{\sectionlevel{#1}}%
     \normalexpanded{\setheadparameter{\s!parent}{\??head\lastsectionname}}% TO BE CHECKED, WE HAVE A HELPER
     \the\everydefinesection
     % so far for these default inheritances
     \definemarking[#1]%
     \ifnum\maxstructuredepth>\plusone
       \normalexpanded{\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child
     \fi
     \xdef\lastsectionname{#1}%
     \ifx\firstsectionname\empty
        \glet\firstsectionname\lastsectionname
     \fi
   \fi}

\unexpanded\def\setupsection
  {\dotripleempty\strc_sectioning_setup}

\def\strc_sectioning_setup[#1][#2][#3]%
  {\ifcsname\??headlevel#1\endcsname
     \strc_sectioning_setup_indeed[#1][#2][#3]%
   \else
     \strc_sectioning_setup_indeed[\sectionheadsection{#1}][#2][#3]%
   \fi}

\def\strc_sectioning_setup_indeed[#1][#2][#3]%
  {\push_macro_currenthead
   \ifthirdargument
     \edef\currenthead{#1#2}%     % not used at any more in mkiv (sets now)
     \setupcurrenthead[#3]%
   \else
     \edef\currenthead{#1}%
     \setupcurrenthead[#2]%
   \fi
   \pop_macro_currenthead}

% we share the parameters as sections are roots of heads so eventually we can
% consider \definesection -> \definehead with one argument

\appendtoks
    % This is a rather practical default that we don't want to
    % be part of the parent chain lookup mechanism; it's also
    % mkii compatible. Somewhat weird that it's part of the
    % top level structure but it will be flattened anyway.
    \let\currenthead\currentsection %
    \setheadparameter\c!textstyle  {\directheadparameter\c!style}%
    \setheadparameter\c!textcolor  {\directheadparameter\c!color}%
    \setheadparameter\c!numberstyle{\directheadparameter\c!style}%
    \setheadparameter\c!numbercolor{\directheadparameter\c!color}%
\to \everydefinesection

% head -> head

\def\sectionheadmarkingtitle #1#2{\clf_markingtitle {#1}{#2}}
\def\sectionheadmarkingnumber#1#2{\clf_markingnumber{#1}{#2}}

\def\sectionheadcoupling#1{\namedheadparameter{#1}\c!coupling}
\def\sectionheadsection #1{\namedheadparameter{#1}\c!section}

% head construction

\unexpanded\def\strc_sectioning_handle_own{\dodoubleempty\strc_sectioning_handle_own_indeed}   % [ref] {nr} {title}
\unexpanded\def\strc_sectioning_handle_nop{\dodoubleempty\strc_sectioning_handle_nop_indeed}   % [ref] {title}
\unexpanded\def\strc_sectioning_start     {\dotripleempty\strc_sectioning_start_named_section} % [settings] [userdata] !!! also used at lua end

\newconditional\currentstructureown

\newtoks\everybeforehead % hook, todo: before/after keys
\newtoks\everyafterhead  % hook, todo: before/after keys

\unexpanded\def\strc_sectioning_handle_own_indeed[#1][#2]#3#4%
  {\settrue\currentstructureown
   \triggerautostructurelevel
   \strc_sectioning_handle{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title --

% \unexpanded\def\strc_sectioning_handle_nop_indeed[#1][#2]% for taco: [key=value] variant
%   {\setfalse\currentstructureown
%    \triggerautostructurelevel
%    \doifelseassignment{#2}\strc_sectioning_handle_nop_indeed_yes\strc_sectioning_handle_nop_indeed_nop{#1}{#2}}

\unexpanded\def\strc_sectioning_handle_nop_indeed[#1][#2]% for taco: [key=value] variant
  {\setfalse\currentstructureown
   \triggerautostructurelevel
   \ifcondition\validassignment{#2}%
     \expandafter\strc_sectioning_handle_nop_indeed_yes
   \else
     \expandafter\strc_sectioning_handle_nop_indeed_nop
   \fi
   {#1}{#2}}

\unexpanded\def\strc_sectioning_handle_nop_indeed_yes#1#2%
  {\strc_sectioning_handle{#1}{#2}{}}

\unexpanded\def\strc_sectioning_handle_nop_indeed_nop#1#2#3%
  {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --

\unexpanded\def\strc_sectioning_start_named_section[#1][#2][#3]% for the moment no grouping, too annoying with page breaks
  {\push_macro_currentnamedsection
   \push_macro_currentstructurereferenceprefix
   \edef\currentnamedsection{#1}%
   \setfalse\currentstructureown
  %\globalpushmacro\currenthead % this does not work out well
   \xdef\currenthead{#1}%
   \setsystemmode\currenthead % new, also here now
   \headparameter\c!beforesection % beware, no users vars set yet
   \the\everybeforehead
   \strc_sectioning_handle{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here)
   % potential: \bgroup (can be optional: grouped = yes)
   \headparameter\c!insidesection}

\unexpanded\def\strc_sectioning_stop[#1]% !!! also used at lua end
  {\dostoptagged
   \dostoptagged
   % potential: \egroup
  %\globalpopmacro\currenthead % so we do a hard recover
   \xdef\currenthead{#1}% recover
   \headparameter\c!aftersection
   \the\everyafterhead
   \resetsystemmode\currenthead
   \pop_macro_currentstructurereferenceprefix
   \pop_macro_currentnamedsection} % new, also here now

\let\dostarthead\strc_sectioning_start % used at lua end
\let\dostophead \strc_sectioning_stop  % used at lua end

% \newconditional\structurereversesectionnumbers  % todo: key/val

\newconditional\c_strc_sectioning_to_list
\newconditional\c_strc_sectioning_increment
\newconditional\c_strc_sectioning_place
\newconditional\c_strc_sectioning_empty
\newconditional\c_strc_sectioning_hidden
\newconditional\c_strc_sectioning_section

\newconditional\headshownumber  % public
\newconditional\headisdisplay   % public
\newconditional\headissomewhere % public

\setvalue{\??headincrement\v!yes  }{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
\setvalue{\??headincrement\v!no   }{\setfalse\c_strc_sectioning_increment\setfalse\c_strc_sectioning_to_list}
\setvalue{\??headincrement\v!list }{\setfalse\c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
\setvalue{\??headincrement\s!empty}{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}

\unexpanded\def\strc_sectioning_initialize_increment
  {\edef\currentheadincrement{\headparameter\c!incrementnumber}%
   \ifcsname\??headincrement\currentheadincrement\endcsname
     \lastnamedcs
   \else
     \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list
     % \filterheadnumber
   \fi}

\def\filterheadnumber
  {\settrue\c_strc_sectioning_increment
   \settrue\c_strc_sectioning_to_list
   \ifx\currentproduct\empty
     % todo : filter from other toc (number, file, title)
     % use  : \currentheadincrement as spec
   \fi}

\setvalue{\??headplace\v!yes}%
  {\setfalse\c_strc_sectioning_empty
   \settrue \c_strc_sectioning_place
   \setfalse\c_strc_sectioning_hidden
   \setfalse\c_strc_sectioning_section}

\setvalue{\??headplace\v!empty}%
  {\settrue \c_strc_sectioning_empty
   \settrue \c_strc_sectioning_place
   \setfalse\c_strc_sectioning_hidden
   \setfalse\c_strc_sectioning_section}

\setvalue{\??headplace\v!no}%
  {\settrue \c_strc_sectioning_empty
   \setfalse\c_strc_sectioning_place
   \setfalse\c_strc_sectioning_hidden
   \setfalse\c_strc_sectioning_section}

\setvalue{\??headplace\v!hidden}%
  {\settrue \c_strc_sectioning_empty
   \setfalse\c_strc_sectioning_place
   \settrue \c_strc_sectioning_hidden
   \setfalse\c_strc_sectioning_section}

\setvalue{\??headplace\v!section}%
  {\settrue \c_strc_sectioning_empty
   \setfalse\c_strc_sectioning_place
   \settrue \c_strc_sectioning_hidden
   \settrue \c_strc_sectioning_section}

\unexpanded\def\strc_sectioning_initialize_placement
  {\expandnamespaceparameter\??headplace\headparameter\c!placehead\v!yes}

\newmode\v!sectionnumber

\def\dosetstructureheadnumbercontent
  {\setsystemmode\v!sectionnumber
   \settrue\headshownumber} % why ?

\def\doresetstructureheadnumbercontent
  {\resetsystemmode\v!sectionnumber
   \setfalse\headshownumber} % why ?

\unexpanded\def\strc_sectioning_initialize_number
  {\edef\p_number{\sectionblockparameter\c!number}%
   \ifx\p_number\v!yes
      \edef\p_number{\headparameter\c!number}%
      \ifx\p_number\v!yes
        \settrue\headshownumber
      \else
        \setfalse\headshownumber
      \fi
   \else
     \setfalse\headshownumber
   \fi}

% Beware, we do need some node for anchoring marks and normally a zwnj will
% do but it interferes so we deal with it at the \LUA\ end.

\newtoks\everyheadsynchronization

% \appendtoks
%     \currentstructuresynchronize
% \to \everyheadsynchronization

\let\currentstructuresynchronize\donothing

\appendtoks
    \currentstructuresynchronize
    \glet\currentstructuresynchronize\donothing
\to \everyheadsynchronization

\unexpanded\def\theheadsynchonization
  {% no, interferes: \signalcharacter
   \the\everyheadsynchronization}

% BEWARE: \marking[section]{my text} does not work as we use list indices instead
% so we need a 'keep track of raw set option' (or maybe a funny internal prefix)

\unexpanded\def\setheadmarking % li:: so that we can use \marking[section]{Taco needed this}
  {\strc_sectioning_delayed_flush
   \normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}}

\let\deepstructurenumbercommand\relax
\let\deepstructuretitlecommand \relax

\unexpanded\def\fullheadnumber
  {\edef\currentheadlabeltag{\currentsectionblock\c!label}%
   \dostarttagged\t!sectionnumber\empty
   \labeltexts
     {\headparameter\currentheadlabeltag}
     {\ifx\deepstructurenumbercommand\relax
        \structurenumber
      \else
        \normalexpanded{\noexpand\deepstructurenumbercommand{\structurenumber}}%
      \fi}%
   \dostoptagged}

\unexpanded\def\fullheadtitle
  {\dostarttagged\t!sectiontitle\empty
   \ifx\deepstructuretitlecommand\relax
     \structuretitle
   \else
     \normalexpanded{\noexpand\deepstructuretitlecommand{\structuretitle}}%
   \fi
   \dostoptagged}

\let\currenthead        \empty
\let\currentheadcoupling\empty
\let\currentheadsection \empty
\let\currentheadlevel   \!!zerocount
\let\currentheadcounter \!!zerocount

\let\strc_show_used\relax

\installtextracker
  {structures.showused}
  {\let\strc_show_used\clf_showstructure}
  {\let\strc_show_used\relax}

\appendtoks
    \strc_show_used
\to \everystoptext

\unexpanded\def\placeheadtext  {\dosingleempty\strc_sectioning_place_head_text  } % use with care
\unexpanded\def\placeheadnumber{\dosingleempty\strc_sectioning_place_head_number} % use with care

\unexpanded\def\strc_sectioning_report{\clf_reportstructure}

\ifdefined\strc_rendering_initialize_style_and_color \else

    \unexpanded\def\strc_rendering_initialize_style_and_color#1#2%
      {\dontconvertfont
       \useheadstyleandcolor\c!style\c!color
       \useheadstyleandcolor#1#2%
       \setupinterlinespace}

\fi

\def\strc_sectioning_place_head_text[#1]%
  {\dontleavehmode
   \begingroup
   \unexpanded\def\\{\space}% messy here, but the default (and needs to be grouped)
   \global\settrue\headisdisplay % triggers interlinespace checking
   \edef\currenthead{#1}%
   \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor
   \relax
   \getspecificstructuretitle{\thenamedheadlevel{#1}}%
   \endgraf
   \endgroup}

\def\strc_sectioning_place_head_number[#1]%
  {\dontleavehmode
   \begingroup
   \global\settrue\headisdisplay % triggers interlinespace checking
   \edef\currenthead{#1}%
   \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor
   \relax
   \getfullstructurenumber{\thenamedheadlevel{#1}}%
   \endgraf
   \endgroup}

\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi

\newtoks\everybeforesectionheadhandle
\newtoks\everyaftersectionheadhandle

\def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller)
  {\xdef\currenthead        {#1}%
   \xdef\currentheadcoupling{\sectionheadcoupling\currenthead}%
   \xdef\currentheadsection {\sectionheadsection \currentheadcoupling}%
   \xdef\currentheadlevel   {\sectionlevel       \currentheadsection}%
   %
   %\writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}%
   %
   \strc_sectioning_initialize_autolevel
   \strc_sectioning_initialize_increment
   \strc_sectioning_initialize_placement
   \strc_sectioning_initialize_number
   %
   \the\everybeforesectionheadhandle
   %
   % todo: also mark (for header)
   %
   % we might remove the lower level
   %
   % not here, after optional \page: \strc_sectioning_register{#1}{#2}{#3}%
   %
%    \xdef\currentheadcounter{\currentsectioncountervalue}% lua call
   %
   % \currentstructuresynchronize % will move
   %
   \let\getheadnumber\empty
   \let\getheadtitle \empty
   \let\getheadsyncs \empty
   \ifconditional\c_strc_sectioning_increment
     \ifconditional\c_strc_sectioning_place
       \strc_sectioning_before_yes
       \strc_sectioning_register{#1}{#2}{#3}% after optional \page
       \strc_sectioning_report
       \dostarttagged\t!sectioncaption\empty
       \let\getheadsyncs\theheadsynchonization
       \let\getheadtitle\fullheadtitle
       \ifconditional\headshownumber
         \let\getheadnumber\fullheadnumber
         \strc_rendering_place_head_number_and_text
       \else
         \strc_rendering_place_head_text
       \fi
       \dostoptagged
       \strc_sectioning_after_yes
     \else\ifconditional\c_strc_sectioning_hidden
       \strc_sectioning_register{#1}{#2}{#3}% after optional \page
       \strc_sectioning_report
       \dostarttagged\t!sectioncaption\empty
       \let\getheadsyncs\theheadsynchonization
       \ifconditional\c_strc_sectioning_section
         \strc_rendering_place_head_section
       \else
         \strc_rendering_place_head_hidden % only something when tracing
       \fi
       \dostoptagged
     \else
       \strc_sectioning_before_nop % toegevoegd ivm subpaginanr / tug sheets
       \strc_sectioning_register{#1}{#2}{#3}% after optional \page
       \strc_sectioning_report
       \dostarttagged\t!sectioncaption\empty
       \let\getheadsyncs\theheadsynchonization
       \strc_rendering_place_head_empty % just flush 'm
       \dostoptagged
       \strc_sectioning_after_nop
     \fi\fi
   \else
     \ifconditional\c_strc_sectioning_place
       \strc_sectioning_before_yes
       \strc_sectioning_register{#1}{#2}{#3}% after optional \page
       \strc_sectioning_report
       \dostarttagged\t!sectioncaption\empty
       \let\getheadsyncs\theheadsynchonization
       \let\getheadtitle\fullheadtitle
       \strc_rendering_place_head_text
       \dostoptagged
       \strc_sectioning_after_yes
     \else\ifconditional\c_strc_sectioning_hidden
       \strc_sectioning_register{#1}{#2}{#3}% after optional \page
       \strc_sectioning_report
       \let\getheadsyncs\theheadsynchonization
       \dostarttagged\t!sectioncaption\empty
       \ifconditional\c_strc_sectioning_section
         \strc_rendering_place_head_section
       \else
         \strc_rendering_place_head_hidden % only something when tracing
       \fi
       \dostoptagged
     \else
       % do nothing / should be vbox to 0pt
       \strc_sectioning_before_nop
       \strc_sectioning_register{#1}{#2}{#3}% after optional \page
       \strc_sectioning_report
       \dostarttagged\t!sectioncaption\empty
       \let\getheadsyncs\theheadsynchonization
       \strc_rendering_place_head_empty % just flush 'm
       \dostoptagged
       \strc_sectioning_after_nop
     \fi\fi
   \fi
   %
   \the\everyaftersectionheadhandle
   %
   \setfalse\c_strc_sectioning_ignore_page
   % ignorespaces prevents spaces creeping in when after=\dontleavehmode
   \dostarttagged\t!sectioncontent\empty
   \ifconditional\headisdisplay
     \ignorespaces
   \else
     \expandafter\GotoPar
   \fi}

% typesetting (the getters are public)

\unexpanded\def\strc_rendering_place_head_number_and_text
  {\setheadmarking
   \getheadnumber/\getheadtitle
   \getheadsyncs}

\unexpanded\def\strc_rendering_place_head_text
  {\setheadmarking
   \getheadtitle
   \getheadsyncs}

\unexpanded\def\strc_rendering_place_head_empty
  {\setheadmarking
   \getheadsyncs}

\installcorenamespace{hiddenheadattr}
\installcorenamespace{hiddenheadsync}

% todo: when in the page builder we need to resolve the marking immediately
% because otherwise we have an async

\newbox\b_sectioning_delayed

\def\strc_sectioning_delayed_flush
  {\ifvoid\b_sectioning_delayed\else
     \smashboxed\b_sectioning_delayed
   \fi}

\unexpanded\def\strc_rendering_place_head_section % see hidden below
  {\global\setbox\b_sectioning_delayed\hpack\bgroup
     \setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}%
     \hpack\headreferenceattributes{}% also does the mark
     \theheadsynchonization
   \egroup}

\unexpanded\def\strc_rendering_place_head_hidden % maybe trialtypesetting check
  {\setxvalue{\??hiddenheadattr\currenthead}%
     {\headreferenceattributes}% can be used when making a box
   \setxvalue{\??hiddenheadsync\currenthead}%
     {\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax
      \noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}%
      \hpack\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference
      \theheadsynchonization}} % and it's a node anyway

\def\synchronizehead           #1{\csname\??hiddenheadsync#1\endcsname}
\def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname}

\unexpanded\def\placerawheaddata  [#1]{\synchronizehead{#1}}
\unexpanded\def\placerawheadtext  [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}}
\unexpanded\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}}

\unexpanded\def\repeathead[#1]%
  {\begingroup
   \setupinteraction[\c!state=\v!stop]%
   \def\currenthead{#1}
   \strc_sectioning_initialize_placement
   \strc_sectioning_initialize_number
   \dostarttagged\t!sectioncaption\empty
   \let\getheadsyncs \relax
   \def\getheadtitle {\getmarking[#1]}
   \def\getheadnumber{\getmarking[#1\v!number]}
   \strc_sectioning_before_yes
   \ifconditional\headshownumber
      \strc_rendering_place_head_number_and_text
   \else
      \strc_rendering_place_head_text
   \fi
   \dostoptagged
   \strc_sectioning_after_yes
   \endgroup}

% \setuphead[chapter][placehead=hidden]
% \chapter {test}
%
% %(\synchronizehead{chapter}) % \getheadsyncs
% %(\getfullstructurenumber{\thenamedheadlevel{chapter}})
% %(\getspecificstructuretitle{\thenamedheadlevel{chapter}})
%
% (\placerawheaddata  [chapter])
% (\placerawheadnumber[chapter])
% (\placerawheadtext  [chapter])

% pagebreaks

\letvalue{\??headmarknop\v!page   }\donothing
\setvalue{\??headmarknop\v!reset  }{\resetcurrentstructuremarks}
\letvalue{\??headmarknop\s!unknown}\donothing

\letvalue{\??headmarkyes\v!page   }\donothing  % to be checked: {\resetcurrentstructuremarks}
\setvalue{\??headmarkyes\v!reset  }{\resetcurrentstructuremarks}
\letvalue{\??headmarkyes\s!unknown}\donothing

\def\strc_sectioning_check_layout
  {\edef\p_page{\headparameter\c!page}%
   \ifx\p_page\empty
     \strc_sectioning_check_layout_nop
   \else
     \strc_sectioning_check_layout_yes
   \fi}

\def\strc_sectioning_check_layout_nop
  {\expandnamespaceparameter\??headmarknop\headparameter\c!marking\s!unknown}

\def\strc_sectioning_check_layout_yes
  {\page[\p_page]%
   \expandnamespaceparameter\??headmarkyes\headparameter\c!marking\s!unknown
   \edef\p_header{\headparameter\c!header}%
   \ifx\p_header\empty \else
     \doifelselayouttextline\v!header{\normalexpanded{\setuplayouttext[\v!header][\c!state=\p_header]}}\donothing
   \fi
   \edef\p_text{\headparameter\c!text}%
   \ifx\p_text\empty \else
     \doifelselayouttextline\v!text  {\normalexpanded{\setuplayouttext[\v!text  ][\c!state=\p_text  ]}}\donothing
   \fi
   \edef\p_footer{\headparameter\c!footer}%
   \ifx\p_footer\empty \else
     \doifelselayouttextline\v!footer{\normalexpanded{\setuplayouttext[\v!footer][\c!state=\p_footer]}}\donothing
   \fi}

\newcount      \c_strc_sectioning_preceding_level     \c_strc_sectioning_preceding_level\plusone
\newconditional\c_strc_sectioning_auto_break          \settrue\c_strc_sectioning_auto_break
\newconditional\c_strc_sectioning_ignore_page
\newsignal     \s_strc_sectioning_continuous_signal

\unexpanded\def\strc_sectioning_inject_continuous_signal
  {\ifhmode
     \hskip\s_strc_sectioning_continuous_signal\relax
   \fi}

% \let\dotagsectionlevel\relax

\def\strc_sectioning_before_yes
  {\strc_sectioning_check_before\strc_sectioning_handle_page_yes
   \headparameter\c!inbetween
   \dostarttaggedchained\t!section\currenthead\??head
%    \dotagsectionlevel
   }

\def\strc_sectioning_before_nop
  {\strc_sectioning_check_before\strc_sectioning_handle_page_nop
   \headparameter\c!inbetween
   \dostarttagged\currenthead\empty} % this is a weird one .. needs checking

\def\strc_sectioning_empty_correction
  {\ifconditional\c_strc_sectioning_empty
     % this needs checking
     \penalty\plustenthousand
     \vskip-\lineheight
     \kern\zeropoint
     \prevdepth\strutdepth
   \fi}

\def\strc_sectioning_after_nop
  {}

\def\strc_sectioning_check_before#1%
  {\ifhmode
     \scratchcounter\lastpenalty
     \unpenalty % no beauty in this
     \ifdim\lastskip=\s_strc_sectioning_continuous_signal
       % no page break
       \ifconditional\c_strc_sectioning_ignore_page
         \setfalse\c_strc_sectioning_ignore_page
       \else
         \global\c_strc_sectioning_preceding_level\currentheadlevel
         \nobreak
       \fi
     % \global\settrue\c_strc_rendering_continuous
     \else
       \penalty\scratchcounter
     % \global\setfalse\c_strc_rendering_continuous
       #1%
     \fi
   \else
   % \global\setfalse\c_strc_rendering_continuous
     #1%
   \fi}

\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax}
\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax}

% \def\strc_sectioning_handle_page_nop
%   {\edef\p_continue{\headparameter\c!continue}%
%    \ifx\p_continue\v!yes
%      \ifnum\previoussectioncountervalue=\zerocount
%        \strc_sectioning_check_layout
%      \else\ifnum\currentsectioncountervalue>\zerocount
%        \strc_sectioning_check_layout
%      \fi\fi
%    \else
%      \strc_sectioning_check_layout
%    \fi}

\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax}
%def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax}
\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\previoushead\relax}

\let\previoushead\empty

\def\strc_sectioning_handle_page_nop
  {\edef\p_continue{\headparameter\c!continue}%
   \ifx\p_continue\v!yes
     \ifx\currenthead\previoushead % not really needed
        \strc_sectioning_check_layout
     \else\ifnum\previoussectioncountervalue=\zerocount
        \strc_sectioning_check_layout
     \else\ifnum\currentsectioncountervalue>\zerocount
        \strc_sectioning_check_layout
     \fi\fi\fi
   \else
     \strc_sectioning_check_layout
   \fi
   \glet\previoushead\currenthead}

% \def\strc_sectioning_handle_page_yes
%   {\ifconditional\c_strc_sectioning_ignore_page
%      \setfalse\c_strc_sectioning_ignore_page
%    \else
%      % beware, these numbers are not yet know here
%      \strc_sectioning_handle_page_nop
%      \edef\p_aligntitle{\headparameter\c!aligntitle}%
%      \ifx\p_aligntitle\v!float
%          \ifconditional\c_strc_sectioning_auto_break
%            \vspacing[\v!samepage-\currentheadlevel]%
%          \fi
%          \headparameter\c!before\relax
%          \indent
%      \else
%          \page_otr_command_flush_side_floats
%          \ifconditional\c_strc_sectioning_auto_break
%            \vspacing[\v!samepage-\currentheadlevel]%
%          \fi
%          \headparameter\c!before\relax
%      \fi
%      \global\c_strc_sectioning_preceding_level\currentheadlevel
%    \fi
%    \glet\previoushead\currenthead}
%
% \unexpanded\def\strc_sectioning_prevent_page_break% see strc-con
%   {\ifconditional\c_strc_sectioning_auto_break
%       \vspacing[\v!samepage-\the\numexpr\currentheadlevel+\plusone\relax]%
%    \fi}
%
% \def\strc_sectioning_after_yes
%   {\ifconditional\headisdisplay
%      \ifconditional\c_strc_sectioning_auto_break
%      % \vspacing[\v!samepage-\currentheadlevel]%
%        \vspacing[\v!samepage]%
%      \fi
%      \strc_sectioning_empty_correction
%      \headparameter\c!after
%    \fi}

% This works better in columns ... but also elsewhere?

\def\strc_sectioning_handle_page_yes
  {\ifconditional\c_strc_sectioning_ignore_page
     \setfalse\c_strc_sectioning_ignore_page
   \else
     % beware, these numbers are not yet know here
     \strc_sectioning_handle_page_nop
     \edef\p_aligntitle{\headparameter\c!aligntitle}%
     \ifx\p_aligntitle\v!float
         \ifconditional\c_strc_sectioning_auto_break
           \spac_vspacing_same_page\currentheadlevel\zerocount
         \fi
         \headparameter\c!before\relax
         \indent
     \else
         \page_otr_command_flush_side_floats
         \ifconditional\c_strc_sectioning_auto_break
           \spac_vspacing_same_page\currentheadlevel\zerocount
         \fi
         \headparameter\c!before\relax
     \fi
     \global\c_strc_sectioning_preceding_level\currentheadlevel
   \fi
   \glet\previoushead\currenthead}

\def\strc_sectioning_after_yes
  {\ifconditional\headisdisplay
     \ifconditional\c_strc_sectioning_auto_break
       \spac_vspacing_same_page\currentheadlevel\plusone
     \fi
     \strc_sectioning_empty_correction
     \headparameter\c!after
   \fi}

\unexpanded\def\strc_sectioning_prevent_page_break % see strc-con
  {\ifconditional\c_strc_sectioning_auto_break
     \spac_vspacing_same_page\currentheadlevel\plustwo
   \fi}


% We do support negative numbers but it can have side effects that we won't catch:
%
% \chapter{some} \setupheadnumber[chapter][3] \chapter{more}
% \setupheadnumber[section][8] \section{b} \section{c} \setupheadnumber[section][-1] \section{d}

\def\thenamedheadlevel#1%
  {\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}}

\unexpanded\def\setupheadnumber
  {\dodoubleargument\strc_sectioning_setup_number}

\def\strc_sectioning_setup_number[#1][#2]% todo: reset if at other level
  {\setstructurenumber{\thenamedheadlevel{#1}}{\number#2}}

\def\currentheadnumber{0} % ==> \currentheadnumber

\unexpanded\def\determineheadnumber[#1]%
  {\xdef\currentheadnumber{\getstructurenumber{\thenamedheadlevel{#1}}}}

% The previous macro is been replaced by the expandable:

\def\namedheadnumber      #1{\getstructurenumber    {\thenamedheadlevel{#1}}}
\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}}

\unexpanded\def\headnumber
  {\dodoubleempty\strc_sectioning_number}

\def\strc_sectioning_number[#1][#2]% simple case is just a number
  {\getsomefullstructurenumber{\iffirstargument\thenamedheadlevel{#1}\fi}{#2}}

\unexpanded\def\someheadnumber
  {\dodoubleempty\strc_sectioning_number_some}

\def\strc_sectioning_number_some[#1][#2]%
  {\dontleavehmode
   \begingroup
   \edef\currenthead{#1}%
   \getsomefullstructurenumber{\thenamedheadlevel{#1}}{#2}%
   \endgroup}

\let\sectioncountervalue\structurevalue

\def\currentheadtext{obsolete,\space use marks}

% list references, will be redone in lua when we need it

\let\startlistreferences\relax
\let\stoplistreferences \relax

% experimental

\newconditional\c_strc_sectioning_auto_levels

\appendtoks
    \settrue\c_strc_sectioning_auto_levels
\to \everyenableelements

\unexpanded\def\strc_sectioning_initialize_autolevel
  {\ifconditional\c_strc_sectioning_auto_levels
     \clf_autonextstructurelevel\currentheadlevel\relax
     \global\setfalse\c_strc_sectioning_auto_levels
   \fi}

\unexpanded\def\triggerautostructurelevel
  {\global\settrue\c_strc_sectioning_auto_levels}

\unexpanded\def\finalizeautostructurelevels
  {\clf_autofinishstructurelevels}

\unexpanded\def\finalizeautostructurelevel
  {\dostoptagged
   \dostoptagged}

\appendtoks
    \finalizeautostructurelevels
\to \everystoptext

\stopcontextdefinitioncode

\protect \endinput