%D \module
%D   [       file=strc-reg,
%D        version=2008.10.20,
%D          title=\CONTEXT\ Structure Macros,
%D       subtitle=Registers,
%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 / Registers}

\registerctxluafile{strc-reg}{autosuffix}

\unprotect

\startcontextdefinitioncode

% todo: tag:: becomes rendering
% todo: language, character, linked, location
% todo: fonts etc at sublevels (already defined)

% \starttext
% \placeregister[index]
% \chapter{a} \index{93} \index{456} \index{***} \index{*} \index{@}
% test \index{aa} test \startregister[index][x]{bb} test \page test \page test \page test \stopregister[index][x]
% test \index{aa} test \setregisterentry[index][label=x,entries=bb] test \page test \page test \page test \finishregisterentry[index][label=x]
% test \index{aa} test \setregisterentry[index][label=y] test \page test \page test \page test \finishregisterentry[index][label=y,entries=yy]
% \stoptext

%  \index                {entry}
%  \index[key]           {entry}
%  \index[pageclass::]   {entry}
%  \index[pageclass::key]{entry}
%  \index                {textclass::entry}
%  \index[key]           {textclass::entry}
%  \index[pageclass::]   {textclass::entry}
%  \index[pageclass::key]{textclass::entry}

% nice example:
%
% \setupregister[index]
%     [n=1,
%      pageleft=\hfilll,
%      pageright=\frozen\parfillleftskip 0pt plus 1fill\frozen\parfillrightskip 0pt\par]
%
% \starttext
%
% {\showmakeup \placeindex \page}
%
% % \dorecurse{10}{\dontleavehmode \index{AAA}\page}
% \dorecurse{100}{\dontleavehmode\index{AAA}\page}

% tzt variant with n entries, parameters and userdata (altnum)

\installcorenamespace{register}

\installcommandhandler\??register {register} \??register

\aliased\let\strc_registers_setup_saved\setupregister

% maybe we should drop the plural form

\let\strc_registers_setup_step\relax

\permanent\tolerant\protected\overloaded\def\setupregister[#S#1]#*[#S#2]#*[#S#3]%
  {\ifarguments\or
     \strc_registers_setup_saved[#1]%
   \or
     \strc_registers_setup_saved[#1][#2]%
   \or
     \def\strc_registers_setup_step##1{\strc_registers_setup_saved[#1:##1][#3]}%
     \processcommalist[#2]\strc_registers_setup_step
   \fi}

\permanent\tolerant\protected\def\setupregisters[#S#1]%
  {\strc_registers_setup_saved[#1]\relax}

\setupregister
  [\c!n=2,
   \c!balance=\v!yes,  % \v!no komt niet zo vaak voor
   \c!align=\v!flushleft,
   \c!tolerance=\v!stretch,
   \c!before=\blank,
  %\c!after=,
  %\c!symbol=,
   \c!compress=\v!no,
   \c!interaction=\v!pagenumber,
   \c!alternative=\v!a,
   \c!distance=\emwidth,
   \c!style=\v!bold,
   \c!pagestyle=\v!slanted,
   \c!indicator=\v!yes,
   \c!criterium=\v!all,
   \c!check=\v!yes, % check for weird see usage
  %\c!command=,
   \c!referencing=\v!on,
   \c!location=\v!middle,
  %\c!maxwidth=,
   \c!number=\v!no,
   \c!unknownreference=\v!empty,
   \c!prefix=\v!both,
  %\c!expansion=,
  %\c!xmlsetup=,
   \c!pagenumber=\v!yes,
   \c!pageprefixconnector=\endash,
   \c!pagesegments=2:2,
   \c!file=\jobname,
  %\c!deeptextcommand=, % undefined by default !
   \c!method=, % no default as we have them in the module, maybe some day in lang-*
   \c!numberorder=\v!numbers, % \v!characters
   \s!language=\currentmainlanguage]%

% yes or no shared ?

\setupregister
  [\c!label=,
   \c!entries=,
   \c!alternative=]

\definemixedcolumns
  [\v!register]
  [\c!define=\v!no,
   \c!n=\registerparameter\c!n,
   \c!balance=\registerparameter\c!balance,
   \c!align=\registerparameter\c!align,
   \c!tolerance=\registerparameter\c!tolerance]

%D \starttyping
%D \setupregister[index][1][textcolor=darkred]
%D \setupregister[index][2][textcolor=darkgreen,textstyle=bold]
%D
%D \placeregister[index][n=1] \blank[3*big]
%D
%D test \index{test+one} test \index{test+two} more \index{more}
%D \stoptyping

\mutable\lettonothing\currentregistercharacter
\mutable\lettonothing\currentregistercoding
\mutable\lettonothing\currentregisterentries
\mutable\lettonothing\currentregisterentriesa
\mutable\lettonothing\currentregisterentriesb
\mutable\lettonothing\currentregisterentriesc
\mutable\lettonothing\currentregisterexpansion
\mutable\lettonothing\currentregisterkeys
\mutable\lettonothing\currentregisterkeysa
\mutable\lettonothing\currentregisterkeysb
\mutable\lettonothing\currentregisterkeysc
\mutable\lettonothing\currentregisterlabel
\mutable\lettonothing\currentregistermaxwidth
\mutable\lettonothing\currentregistername
\mutable\lettonothing\currentregisternumber
\mutable\lettonothing\currentregisterownnumber
\mutable\lettonothing\currentregisterpageindex
\mutable\lettonothing\currentregisterpageprefix
\mutable\lettonothing\currentregisterpagesymbol
\mutable\lettonothing\currentregisterprocessors
\mutable\lettonothing\currentregisterprocessorsa
\mutable\lettonothing\currentregisterprocessorsb
\mutable\lettonothing\currentregisterprocessorsc
\mutable\lettonothing\currentregistersectionindex
\mutable\lettonothing\currentregisterseeindex
\mutable\lettonothing\currentregisterseeword
\mutable\lettonothing\currentregistersynchronize
\mutable\lettonothing\currentregisterxmlsetup

\newconditional\c_strc_registers_defining
\setnewconstant\c_strc_registers_maxlevel \plusfive
\newconditional\c_strc_registers_vertical \c_strc_registers_vertical\conditionaltrue

\ifdefined\Word \else \protected\def\Word#1{#1} \fi

\appendtoks
    \ifconditional\c_strc_registers_defining \else % todo: dosingle ...
      \c_strc_registers_defining\conditionaltrue
      \definemixedcolumns[\currentregister][\v!register]% first as otherwise it overloads start/stop
      \clf_defineregister{\currentregister}{\registerparameter\c!referencemethod}%
      \normalexpanded{\presetheadtext[\currentregister=\Word{\currentregister}]}%
      \frozen\instance\protected\edefcsname\currentregister\endcsname{\strc_registers_insert_entry[\currentregister]}%
      \frozen\instance\protected\edefcsname\e!see\currentregister\endcsname{\strc_registers_insert_see[\currentregister]}%
      %frozen\instance\protected\edefcsname\e!coupled\currentregister\endcsname{\dolinkedregister{\currentregister}}%
      % historic ballast
      \frozen\instance\protected\edefcsname\e!place\currentregister\endcsname{\placeregister[\currentregister]}%
      \frozen\instance\protected\edefcsname\e!complete\currentregister\endcsname{\completeregister[\currentregister]}%
      \frozen\instance\protected\edefcsname\e!setup\currentregister\e!endsetup\endcsname{\setupregister[\currentregister]}%
      \dorecurse\c_strc_registers_maxlevel{% weird, expanded should not be needed
        \normalexpanded{\defineregister[\currentregister:\recurselevel][\currentregister]}%
       %\defineregister[\currentregister:\recurselevel][\currentregister]%
        \resetregisterparameter{\c!entries:\recurselevel}% needed as we use detokenize (ok, we can
        \resetregisterparameter{\c!keys   :\recurselevel}% avoid it, but it's faster too)
      }%
      %
      \c_strc_registers_defining\conditionalfalse
    \fi
\to \everydefineregister

\appendtoks
    \clf_setregistermethod{\currentregister}{\registerparameter\c!referencemethod}%
\to \everysetupregister

%D Registering:

\glettonothing\currentregistername
\glet         \currentregisternumber\!!zerocount

\def\strc_registers_register_page_entry
  {\iftrialtypesetting
     \expandafter\gobblethreearguments
   \orelse\ifconditional\prerollrun
     \expandafter\gobblethreearguments
   \else
     \expandafter\strc_registers_register_page_entry_indeed
   \fi}

\def\strc_registers_register_page_expand_xml_entries
  {\xmlstartraw
     \xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}%
     \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
     \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
   \xmlstopraw
   \glet\currentregistercoding\s!xml}

\def\strc_registers_register_page_expand_yes_entries
  {\xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}%
   \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
   \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
   \glet\currentregistercoding\s!tex}

\def\strc_registers_register_page_expand_nop_entries
  {\xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}%
   \xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}%
   \xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}%
   \glet\currentregistercoding\s!tex}

\def\strc_registers_register_page_expand_xml
  {\xmlstartraw
     \xdef\currentregisterentries{\registerparameter\c!entries}%
   \xmlstopraw
   \glet\currentregistercoding\s!xml}

\def\strc_registers_register_page_expand_yes
  {\xdef\currentregisterentries{\registerparameter\c!entries}%
   \glet\currentregistercoding\s!tex}

\def\strc_registers_register_page_expand_nop
  {\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}%
   \glet\currentregistercoding\s!tex}

\def\strc_registers_register_page_expand_xml_keys
  {\xmlstartraw
     \xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}%
     \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}%
     \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}%
   \xmlstopraw}

\def\strc_registers_register_page_expand_yes_keys
  {\xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}%
   \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}%
   \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}}

\def\strc_registers_register_page_expand_processors
  {\xdef\currentregisterprocessorsa{\registerparameter{\c!processors:1}}%
   \xdef\currentregisterprocessorsb{\registerparameter{\c!processors:2}}%
   \xdef\currentregisterprocessorsc{\registerparameter{\c!processors:3}}}

\def\strc_registers_register_prepare_entry#1#2%
  {\cdef\currentregister{#1}%
   %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
   \setupcurrentregister[#2]%
   \edef\currentregisterlabel     {\registerparameter\c!label}%
   \edef\currentregisterexpansion {\registerparameter\c!expansion}%
   \edef\currentregisterownnumber {\registerparameter\c!ownnumber}%
   \xdef\currentregisterkeys      {\registerparameter\c!keys}%
   \xdef\currentregisterentries   {\registerparameter\c!entries}%
   \xdef\currentregisterprocessors{\registerparameter\c!processors}%
   \xdef\currentregisterxmlsetup  {\registerparameter\c!xmlsetup}%
   \ifempty\currentregisterentries
     \ifx\currentregisterexpansion\s!xml
       \strc_registers_register_page_expand_xml_entries
     \orelse\ifx\currentregisterexpansion\v!yes
       \strc_registers_register_page_expand_yes_entries
     \else
       \strc_registers_register_page_expand_nop_entries
     \fi
   \else
     \ifx\currentregisterexpansion\s!xml
       \strc_registers_register_page_expand_xml
     \orelse\ifx\currentregisterexpansion\v!yes
       \strc_registers_register_page_expand_yes
     \else
       \strc_registers_register_page_expand_nop
     \fi
   \fi
   \ifempty\currentregisterkeys
     \ifx\currentregistercoding\s!xml
       \strc_registers_register_page_expand_xml_keys
     \else
       \strc_registers_register_page_expand_yes_keys
     \fi
   \fi
   \strc_registers_register_page_expand_processors}

\def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata
  {\begingroup
   \strc_registers_register_prepare_entry{#1}{#2}%
   \setnextinternalreference
   % we could consider storing register entries in a list which we
   % could then sort
   \glet\currentregistername\currentregister
   \xdef\currentregisternumber{\clf_storeregister % 'own' should not be in metadata
        metadata {%
            name     {\currentregister}%
            coding   {\currentregistercoding}%
        \ifx\currentregisterownnumber\v!yes
            own      {\registerparameter\c!alternative}% can be used instead of pagenumber
        \fi
        \ifx\currentreferencecoding\s!xml
            xmlroot  {\xmldocument} % only useful when text
        \fi
        \ifempty\currentregisterxmlsetup \else
            xmlsetup {\currentregisterxmlsetup}%
        \fi
        }%
        references {%
        \ifempty\currentregisterlabel \else
            label    {\currentregisterlabel}%
        \fi
          % view     {\interactionparameter\c!focus}%
        }%
        entries {%
            % we need a special one for xml, this is just a single one
            \ifempty\currentregisterentries
                entries {
                    {\currentregisterentriesa}%
                    {\currentregisterentriesb}%
                    {\currentregisterentriesc}%
                }
            \else
                entry {\currentregisterentries}%
            \fi
            \ifempty\currentregisterkeys
                keys {
                    {\currentregisterkeysa}%
                    {\currentregisterkeysb}%
                    {\currentregisterkeysc}%
                }
            \else
                key {\currentregisterkeys}%
            \fi
            \ifempty\currentregisterprocessors
                processors {
                    {\currentregisterprocessorsa}%
                    {\currentregisterprocessorsb}%
                    {\currentregisterprocessorsc}%
                }
            \else
                processor {\currentregisterprocessors}%
            \fi
        }%
        userdata {\detokenize\expandafter{\normalexpanded{#3}}}
   }%
   \clf_setinternalreference
      internal \locationcount
      view     {\interactionparameter\c!focus}%
   \relax % this will change
   \ifx\currentregisterownnumber\v!yes
     \glet\currentregistersynchronize\relax
   \else
     \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
   \fi
   \currentregistersynchronize % here?
   % needs thinking ... bla\index{bla}. will break before the . but adding a
   % penalty is also no solution
   \dostarttagged\t!registerlocation\currentregister
   \c_attr_destination\lastdestinationattribute
   \signalcharacter % no \strut as it will be removed during cleanup
   \dotagregisterlocation
   \dostoptagged
   \endgroup}

\permanent\protected\def\dosetfastregisterentry#1#2#3#4#5% register entry key processor processor
  {\begingroup
   \cdef\currentregister{#1}%
   \setnextinternalreference
   \glet\currentregistername\currentregister
   \xdef\currentregisternumber{\clf_storeregister
     {%
        metadata {%
          name {\currentregister}%
        }
        entries {%
          entry {#2}%
          key   {#3}%
        }%
        processors {%
          entry {#4}%
          page  {#5}%
        }%
     }%
   }%
   % overlap with the above
 % \clf_setinternalreference
 %    internal \locationcount
 %    view     {\interactionparameter\c!focus}%
   \relax % this will change
   \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
   \currentregistersynchronize % here?
   \dostarttagged\t!registerlocation\currentregister
   \c_attr_destination\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
   \dotagregisterlocation
   \dostoptagged
   \endgroup}

\aliased\let\dotagregisterlocation\relax % experiment

\tolerant\protected\def\strc_registers_insert_entry[#1]#*[#S#2]%
  {\cdef\currentregister{#1}%
   \ifcstok{\registerparameter\c!ownnumber}\v!yes
     \expandafter\strc_registers_insert_entry_yes
   \else
     \expandafter\strc_registers_insert_entry_nop
   \fi{#2}}

% \def\strc_registers_insert_entry_nop#1#2%
%   {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}}
%
% \def\strc_registers_insert_entry_yes#1#2#3%
%   {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}}
%
% less tokens passed (nicer for tracing) .. could become installable

\def\strc_registers_insert_entry_nop
  {\ifvmode
     \expandafter\strc_registers_insert_entry_nop_par
   \else
     \expandafter\strc_registers_insert_entry_nop_txt
   \fi}

\def\strc_registers_insert_entry_yes
  {\ifvmode
     \expandafter\strc_registers_insert_entry_yes_par
   \else
     \expandafter\strc_registers_insert_entry_yes_txt
   \fi}

\def\strc_registers_insert_entry_nop_par#1#2%
  {\ifprerolling\else\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}\fi}

\def\strc_registers_insert_entry_yes_par#1#2#3%
  {\ifprerolling\else\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}\fi}

\def\strc_registers_insert_entry_nop_txt#1#2%
  {\ifprerolling\else\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}\fi}

\def\strc_registers_insert_entry_yes_txt#1#2#3%
  {\ifprerolling\else\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}\fi}

%D This is one of the few commands where a stop has arguments.

\permanent\tolerant\protected\def\startregister[#1]#*[#2]#*[#3]#*[#4]#*#:#5%
  {\ifparameter#4\or
     % #1=register #2=tag #3=own #4=sortkey #5=entry
     \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}%
   \else
     % #1=register #2=tag #3=sortkey #5=entry
     \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}%
   \fi}

\permanent\tolerant\protected\def\stopregister[#1]#*[#2]%
% {\normalexpanded{\ctxlatecommand{extendregister("#1","#2")}}}
  {\clf_extendregisterlate{#1}{#2}}

% a synonym, so that we can nest with overlap without syntax check problems

\aliased\let\openregisterrange \startregister
\aliased\let\closeregisterrange\stopregister

% not yet document, not sure if this will stay:

\permanent\tolerant\protected\def\setregisterentry[#1]#*[#2]#*[#3]%
  {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}}

\permanent\tolerant\protected\def\finishregisterentry[#1]#*[#2]#*[#3]%
  {\strc_registers_finish_entry_indeed{#1}{#2}{#3}}

\protected\def\strc_registers_finish_entry_indeed#1#2#3% register data userdata
  {\begingroup
   % I hate this kind of mess ... but it's a user request.
   \strc_registers_register_prepare_entry{#1}{#2}%
   \glet\currentregistername\currentregister
   \clf_extendregister { % 'own' should not be in metadata
        metadata {%
            name     {\currentregister}%
            coding   {\currentregistercoding}%
        \ifx\currentregisterownnumber\v!yes
            own      {\registerparameter\c!alternative}% can be used instead of pagenumber
        \fi
        \ifx\currentreferencecoding\s!xml
            xmlroot  {\xmldocument} % only useful when text
        \fi
        \ifempty\currentregisterxmlsetup \else
            xmlsetup {\currentregisterxmlsetup}%
        \fi
        }%
        references {%
        \ifempty\currentregisterlabel \else
            label    {\currentregisterlabel}%
        \fi
          % view     {\interactionparameter\c!focus}%
        }%
        entries {%
            % we need a special one for xml, this is just a single one
            \ifempty\currentregisterentries
                entries {
                    {\currentregisterentriesa}%
                    {\currentregisterentriesb}%
                    {\currentregisterentriesc}%
                }
            \else
                entry {\currentregisterentries}%
            \fi
            \ifempty\currentregisterkeys
                keys {
                    {\currentregisterkeysa}%
                    {\currentregisterkeysb}%
                    {\currentregisterkeysc}%
                }
            \else
                key {\currentregisterkeys}%
            \fi
            \ifempty\currentregisterprocessors
                processors {
                    {\currentregisterprocessorsa}%
                    {\currentregisterprocessorsb}%
                    {\currentregisterprocessorsc}%
                }
            \else
                processor {\currentregisterprocessors}%
            \fi
        }%
        userdata {\detokenize\expandafter{\normalexpanded{#3}}}
    }%
   \relax
   \endgroup}

% The following variants are meant for (for instance xml). There is some
% overlap with previously defined macros.
%
% \starttext
%     \setstructurepageregister[index][entries=alpha]a
%     \setstructurepageregister[index][entries=gamma]g
%     \setstructurepageregister[index][entries=beta]b
%     \setstructurepageregister[index][entries:1=alpha,keys:1=z]a
%     \setstructurepageregister[index][entries:1=gamma,keys:1=x]g
%     \setstructurepageregister[index][entries:1=beta, keys:1=y]b
%     \index{alpha}a
%     \index{gamma}g
%     \index{beta}b
%     \placeregister[index][n=1]
% \stoptext

% some overlap with previous

\permanent\tolerant\protected\def\setstructurepageregister[#1]#*[#2]#*[#S#3]% [register][settings][userdata]
  {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}}

\permanent\tolerant\protected\def\startstructurepageregister[#1]#*[#2]#*[#S#3]#*[#S#4]% [register][tag][settings][userdata]
  {\doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,#3}{#4}}}

\permanent\tolerant\protected\def\stopstructurepageregister[#1]#*[#2]%
  {\normalexpanded{\ctxlatecommand{structures.registers.extend("#1","#2")}}}

\aliased\let\openstructurepageregisterrange \startstructurepageregister
\aliased\let\closestructurepageregisterrange\stopstructurepageregister

% So far.

\tolerant\protected\def\strc_registers_insert_see[#1]#*[#2]#*#:#3#4%
  {\doflushatpar{\strc_registers_insert_see_indeed{#1}{#2}{#3}{#4}}}

\def\strc_registers_insert_see_indeed#1#2#3#4% register key entry seeword
  {\begingroup
   \cdef\currentregister{#1}%
   \edef\currentregisterexpansion{\registerparameter\c!expansion}%
   \ifx\currentregisterexpansion\s!xml
     \xmlstartraw
       \xdef\currentregisterentries{\detokenize{#3}}% not ok yet
       \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet
     \xmlstopraw
     \glet\currentregistercoding\s!xml
   \else
     \ifx\currentregisterexpansion\v!yes
       \xdef\currentregisterentries{#3}% not ok yet
       \xdef\currentregisterseeword{#4}% not ok yet
     \else
       \xdef\currentregisterentries{\detokenize{#3}}% not ok yet
       \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet
     \fi
     \glet\currentregistercoding\s!tex
   \fi
   \setnextinternalreference
   % we could consider storing register entries in list
   \edef\temp{\clf_storeregister{% \temp grabs the nofentries
     metadata {%
         kind {see}%
         name {\currentregister}%
     }%
     references {%
%         view  {\interactionparameter\c!focus}%
     }%
     entries {%
         % we need a special one for xml, this is just a single one
         entry {\currentregisterentries}%
         key   {#2}%
     }%
     seeword {%
         text  {\currentregisterseeword}%
     }%
   }}%
   \clf_setinternalreference
      internal \locationcount
      view     {\interactionparameter\c!focus}%
   \relax % this will change
   \dostarttagged\t!registerlocation\currentregister
   \c_attr_destination\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
   \dotagregisterlocation
   \dostoptagged
   \endgroup}

%D Rendering:

% todo: c!language ipv s!language

\permanent\def\utilityregisterlength{\listlength} % also in strc-lst (downward compatible name)

% \mutable\let\listlength\!!zerocount             % also in strc-lst

\permanent\tolerant\protected\def\determineregistercharacteristics[#1]#*[#S#2]%
  {\begingroup
   \setupregister[#1][#2]%
   \cdef\currentregister{\firstinset{#1}}%
   \normalexpanded{\endgroup\noexpand\xdef\noexpand\listlength{\clf_analyzeregister
     {\currentregister}%
     {%
        language    {\registerparameter\s!language}%
        method      {\registerparameter\c!method}%
        numberorder {\registerparameter\c!numberorder}%
        compress    {\registerparameter\c!compress}%
        criterium   {\registerparameter\c!criterium}%
        pagenumber  \ifempty\registerpageseparatorsymbol false\else true\fi
     }%
   }}%
   \ifcase\utilityregisterlength\relax
     \resetsystemmode\v!register
   \else
     \setsystemmode  \v!register
   \fi}

\newtoks\everyplaceregister

\appendtoks
    \dontcomplain
\to \everyplaceregister

\newconditional\c_strc_registers_text_interaction
\newconditional\c_strc_registers_page_done

\permanent\tolerant\protected\def\placeregister[#1]#*[#S#2]%
  {\ifarguments\else
     \begingroup
    %\forgetall
     \setupregister[#1][#2]% can be a list
     \cdef\currentregister{\firstinset{#1}}%
     \expand\everyplaceregister
     \ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone
       \startmixedcolumns[\currentregister]%
         \strc_registers_place_indeed{#1}%
       \stopmixedcolumns
     \else
       \strc_registers_place_indeed{#1}%
     \fi
     \endgroup
   \fi}

\def\strc_registers_place_indeed#1%
  {\ifcstok{\registerparameter\c!interaction}\v!text
     \c_strc_registers_text_interaction\conditionaltrue
   \else
     \c_strc_registers_text_interaction\conditionalfalse
   \fi
   \clf_processregister
     {#1}%
     {%
        language      {\registerparameter\s!language}%
        method        {\registerparameter\c!method}%
        numberorder   {\registerparameter\c!numberorder}%
        check         {\registerparameter\c!check}%
        compress      {\registerparameter\c!compress}%
        criterium     {\registerparameter\c!criterium}%
        pagemethod    {\registerparameter\c!pagemethod}%
        pagenumber    \ifempty\registerpageseparatorsymbol false\else true\fi
     }{%
        separatorset  {\registerparameter\c!pageprefixseparatorset}%
        conversionset {\registerparameter\c!pageprefixconversionset}%
        starter       {\registerparameter\c!pageprefixstarter}%
        stopper       {\registerparameter\c!pageprefixstopper}%
        set           {\registerparameter\c!pageprefixset}%
        segments      {\registerparameter\c!pageprefixsegments}%
        connector     {\registerparameter\c!pageprefixconnector}%
     }{%
        prefix        {\registerparameter\c!pageprefix}%
        separatorset  {\registerparameter\c!pageseparatorset}%
        conversionset {\registerparameter\c!pageconversionset}%
        starter       {\registerparameter\c!pagestarter}%
        stopper       {\registerparameter\c!pagestopper}%
        segments      {\registerparameter\c!pagesegments}%
     }%
   \relax}

% \def\strc_registers_limited_entry#1%
%   {\limitatetext{#1}\currentregistermaxwidth\unknown}%

\def\strc_registers_limited_entry#1%
  {\limitated left \currentregistermaxwidth sentinel {\unknown} text {#1} freeze true\relax}

\aliased\let\limitedregisterentry\firstofoneargument

\appendtoks
    \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}%
    \ifempty\currentregistermaxwidth
      \enforced\let\limitedregisterentry\firstofoneargument
    \else
      \enforced\let\limitedregisterentry\strc_registers_limited_entry
    \fi
\to \everyplaceregister

\permanent\tolerant\protected\def\completeregister[#1]#*[#S#2]%
  {\ifarguments\or
     \begingroup
     \cdef\currentregister{\firstinset{#1}}%
     \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}%
     \placeregister[#1][#2]%
     \page[\v!yes]%
     \stopnamedsection
     \endgroup
   \fi}

% test case for collapsing (experimental, for Steffen Wolfrum)
%
% \starttext
% \placeregister[index][compress=no]  \blank[2*big]
% \placeregister[index][compress=yes] \blank[2*big]
% \placeregister[index][compress=all] \page
% \dorecurse{10}{test 1:!\index{test} test \page}
% \dorecurse{5} {test 2:\recurselevel      \page}
% \dorecurse{10}{test 3:!\index{test} test \page}
% \dorecurse{5} {test 4:\recurselevel      \page}
% \dorecurse{1} {test 5:!\index{test} test \page}
% \dorecurse{5} {test 6:\recurselevel      \page}
% \dorecurse{10}{test 7:!\index{test} test \page}
% \dorecurse{5} {test 8:\recurselevel      \page}
% oeps \index{oeps}
% xxxx \index{xxxx}
% todo \index{todo}
% \stoptext

%D Kind of new:

% % index-1.tex:
%
% \setupinteraction[state=start]
% \starttext
%     test \index{entry    WB.1} \page empty \page
%     test \index{another  WB.1} \page empty \page
%     test \index{onemore  WB.1} \page empty \page
%     test \index{whatever WB.1} \page empty \page
%     test \index{common}        \page empty \page
%     \placeregister[index]
% \stoptext
%
% % index-2.tex:
%
% \setupinteraction[state=start]
% \defineregister[xedni]
% \useregister[workbook][index-1][index][WB ]
% \starttext
%     test \index{onemore TB.1} \page
%     test \index{another TB.1} \page
%     test \index{entry   TB.1} \page
%     test \index{common}       \page
%     test \xedni{onemore TB.2} \page
%     test \xedni{another TB.2} \page
%     test \xedni{entry   TB.2} \page
%     test \xedni{common}       \page
%     \placeregister[index,xedni,workbook]
% \stoptext

\permanent\protected\tolerant\def\useregister[#1]#*[#2]#*[#3]#*[#4]%  tag file class prefix
  {\doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
   \clf_useregister{#1}{#2}{#3}{#4}}

% \permanent\protected\tolerant\def\useregister[#1]#*[#2]#*[#3]#*[#4]%  tag file class prefix
%   {\begingroup
%    \doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
%    \ifhastok={#4}%
%      \getdummyparameters[\c!prefix=#1,\c!label=#1,#4]%
%    \else
%      \getdummyparameters[\c!prefix=#4,\c!label=#4]%
%    \fi
%    \clf_useregister
%      {#1}
%      {
%         filename {#2}
%         class    {#3}
%         prefix   {\dummyparameter\c!prefix}
%         label    {\dummyparameter\c!label}
%      }
%    \relax
%    \endgroup}

%D Character rendering (sections):

\installcorenamespace{registerindicator}

\permanent\def\defaultregistercharacter#1%
  {\edef\currentregistercharacter{#1}%
   \ifempty\currentregistercharacter
     % skip
   \orelse\ifx\currentregistercharacter\s!unknown
     % skip
   \orelse\ifcstok{\registerparameter\c!indicator}\v!yes
     \strc_registers_place_character_yes
   \else
     \strc_registers_place_character_nop
   \fi}

\def\strc_registers_place_character_yes
  {\expandnamespaceparameter\??registerindicator\registerparameter\c!alternative\v!a{\currentregistercharacter}}

\def\strc_registers_place_character_nop
  {\registerparameter\c!before
   \goodbreak}

% a = <before> <goodbreak> <character> <par> <after> <nobreak>

\def\strc_registers_indicator_a#1#2%
  {\registerparameter\c!before
   % bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight
   \typo_injectors_check_register
   \begingroup
   \useregisterstyleandcolor\c!style\c!color
   \dontleavehmode
   \typo_injectors_mark_register
   \strut
   \iflocation
     \dosetdirectpagereference{\currentregister:\v!section:#1}%
   \fi
   \registerparameter\c!command{#2}%
   \endgroup
   \blank[\v!samepage]%
   \registerparameter\c!after
   \endgraf
   \nobreak}

% b = <goodbreak> <before> <character> <after> <nobreak>

\def\strc_registers_indicator_b#1#2%
  {\registerparameter\c!before
   \typo_injectors_check_register
   \begingroup
   \useregisterstyleandcolor\c!style\c!color
   \dontleavehmode
   \typo_injectors_mark_register
   \strut
   \iflocation
     \dosetdirectpagereference{\currentregister:\v!section:#1}%
   \fi
   \registerparameter\c!command{#2}%
   \endgroup
   \registerparameter\c!after
   \nobreak}

\defcsname\??registerindicator a\endcsname#1{\strc_registers_indicator_a{#1}{#1}}
\defcsname\??registerindicator A\endcsname#1{\strc_registers_indicator_a{#1}{\WORD{#1}}}
\defcsname\??registerindicator b\endcsname#1{\strc_registers_indicator_b{#1}{#1}}
\defcsname\??registerindicator B\endcsname#1{\strc_registers_indicator_b{#1}{\WORD{#1}}}

%D The following macros are the interface to the rendering. These are
%D generated by \LUA. This might change.

% \showinjector
% \setinjector[register][2][\column]
%
% \starttext
%     first  \index{first}
%     second \index{second}
%     third  \index{third}
%     fourth \index{fourth}
%     \placeregister[index]
% \stoptext

\doinstallinjector\s!register

%D Beware, we get funny side effects when a dangling \index precedes an
%D placeindex as then flushing takes place inside the index. Took me hours
%D to notice that.

\newconstant \c_strc_registers_page_state % 0=nothing  1=page  2=see
\newdimension\d_strc_registers_distance
\newinteger  \c_strc_register_level

\def\strc_registers_update_text_properties
  {\ifx\m_current_register\currentregister\else
     \useregisterstyleandcolor\c!textstyle\c!textcolor
   \fi}

\def\strc_registers_update_page_properties
  {\ifx\m_current_register\currentregister\else
     \useregisterstyleandcolor\c!pagestyle\c!pagecolor
   \fi}

\permanent\protected\def\startregisteroutput
  {\endgraf
   \begingroup
   \d_strc_registers_distance\registerparameter\c!distance\relax
   \dostarttaggedchained\t!register\currentregister\??register
   \forgeteverypar
   \forgetparindent
   \forgetparskip}

\permanent\protected\def\stopregisteroutput
  {\endgraf
   \dostoptagged
   \endgroup}

\newdimension\d_strc_registers_hangindent
\newinteger  \c_strc_registers_hangafter

% \permanent\protected\def\usenestedregisterstyleandcolor#1#2% will change
%   {\useregisterstyleandcolor#1#2%
%    % how about style
%    \ifconditional\c_strc_registers_text_interaction
%      \ifempty\currentcolorparameter \else
%        \resetinteractionparameter\c!color
%        \resetinteractionparameter\c!contrastcolor
%      \fi
%    \fi}
%
% \permanent\protected\def\startregisterentries#1% depth
%   {\endgraf
%    \begingroup
%    \c_strc_register_level\ifnum#1>\c_strc_registers_maxlevel\c_strc_registers_maxlevel\else#1\fi\relax
%    \dostarttagged\t!registerentries\empty
%  % \let\savedcurrentregister\currentregister
%    \pushmacro\currentregister
%    \cdef\currentregister{\currentregister:\the\c_strc_register_level}%
%    \usenestedregisterstyleandcolor\c!textstyle\c!textcolor
%    \ifnum\c_strc_register_level>\plusone
%      \advanceby\leftskip\d_strc_registers_distance\relax
%    \fi
%    \d_strc_registers_hangindent\registerparameter\c!distance\relax
%    \c_strc_registers_hangafter \plusone
%    \blank[\v!samepage]%
%  % \let\currentregister\savedcurrentregister}
%    \popmacro\currentregister}
%
% \permanent\protected\def\stopregisterentries
%   {\endgraf
%    \dostoptagged
%    \endgroup}

%D See test suite \type {registers/horizontal-001.tex} for a more extensive example
%D of horizontal:
%D
%D \stoptyping
%D \defineregister
%D   [demo]
%D   [n=1,
%D    pagenumber=no,
%D    textalternative=horizontal,
%D    distance=0pt]
%D
%D \setupregister [demo] [2] [textstyle=bold,left={, }]
%D \setupregister [demo] [3] [textstyle=italic,left={, }]
%D
%D \setregisterentry [demo] [entries:1={alpha}, entries:2={one}, entries:3={first}]
%D \setregisterentry [demo] [entries:1={beta},  entries:2={two}, entries:3={last}]
%D
%D \starttext
%D     \starttitle[title=Demo]
%D         \placeregister[demo]
%D     \stoptitle
%D \stoptext
%D \stoptyping

\appendtoks
    \ifcstok{\registerparameter\c!textalternative}\v!horizontal
      \c_strc_registers_vertical\conditionalfalse
    \else
      \c_strc_registers_vertical\conditionaltrue
    \fi
\to \everysetupregister

\mutable\lettonothing\currentnestedregister

\permanent\protected\def\usenestedregisterstyleandcolor#1#2% will change
  {\useregisterstyleandcolor#1#2%
   % how about style
   \ifconditional\c_strc_registers_text_interaction
     \ifempty\currentcolorparameter \else
       \resetinteractionparameter\c!color
       \resetinteractionparameter\c!contrastcolor
     \fi
   \fi}

\permanent\protected\def\startregisterentries#1% depth
  {\ifconditional\c_strc_registers_vertical
     \endgraf
   \fi
   \begingroup
   \c_strc_register_level\ifnum#1>\c_strc_registers_maxlevel\c_strc_registers_maxlevel\else#1\fi\relax
   \dostarttagged\t!registerentries\empty
   \pushmacro\currentregister % bah
   \cdef\currentregister{\currentregister:\the\c_strc_register_level}%
   \let\currentnestedregister\currentregister
   \usenestedregisterstyleandcolor\c!textstyle\c!textcolor
   \ifnum\c_strc_register_level>\plusone
     \advanceby\leftskip\d_strc_registers_distance\relax
   \fi
   \d_strc_registers_hangindent\registerparameter\c!distance\relax
   \c_strc_registers_hangafter \plusone
   \ifconditional\c_strc_registers_vertical
     \blank[\v!samepage]%
   \fi
   \popmacro\currentregister}

\permanent\protected\def\stopregisterentries
  {\endgraf
   \dostoptagged
   \endgroup}

\permanent\protected\def\startregisterentry#1% todo: level
  {\typo_injectors_check_register
   \begingroup
   \dostarttagged\t!registerentry\empty
   \global\setconstant\c_strc_registers_page_state\zerocount
   \ifconditional\c_strc_registers_vertical
     \hangindent\d_strc_registers_hangindent
     \hangafter \c_strc_registers_hangafter
   \else
     \namedregisterparameter\currentnestedregister\c!left\relax
   \fi
   \typo_injectors_mark_register}

\permanent\protected\def\stopregisterentry
  {\ifconditional\c_strc_registers_vertical
     \endgraf
   \else
     \namedregisterparameter\currentnestedregister\c!right\relax
   \fi
   \global\setconstant\c_strc_registers_page_state\zerocount
   \dostoptagged
   \endgroup}

\permanent\protected\def\startregistersection#1% title
  {\dostarttagged\t!registersection\empty
   \dostarttagged\t!registertag\empty
   \registercharacter{#1}\endgraf
   \dostoptagged}

\permanent\protected\def\stopregistersection
  {\dostoptagged
   \endgraf}

\permanent\protected\def\startregisterpages
  {\begingroup
   \dostarttagged\t!registerpages\empty
   \useregisterstyleandcolor\c!pagestyle\c!pagecolor
   \registerparameter\c!pageleft}

\permanent\protected\def\stopregisterpages
  {\registerparameter\c!pageright
   \dostoptagged
   \endgroup}

\permanent\protected\def\startregisterseewords
  {\begingroup
   \dostarttagged\t!registerpage\empty
   \useregisterstyleandcolor\c!pagestyle\c!pagecolor}

\permanent\protected\def\stopregisterseewords
  {\dostoptagged
   \endgroup}

\permanent\protected\def\registerpageseparator % todo: , configurable
  {\ifcase\c_strc_registers_page_state
     \hskip\d_strc_registers_distance\relax
   \or
     \dostarttagged\t!registerseparator\empty
     \registerpageseparatorsymbol % page
     \dostoptagged
   \or
     \dostarttagged\t!registerseparator\empty
     \registerpageseparatorsymbol % see
     \dostoptagged
   \fi}

\permanent\protected\def\registeronepagerangeseparator
  {|\endash|} % todo use \prewordbreak

\let\currentregisterrealpage\!!zerocount % todo: more general accessor

% keep as reference
%
% \permanent\protected\def\withregisterpagecommand#1#2#3#4%
%   {\ifcase#3\relax
%      {\tt [entry\space not\space flushed]}%
%    \else
%      \def\currentregisterpageindex{#2}%
%      \def\currentregisterrealpage{#3}%
%      \iflocation
%        \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
%      \else
%        \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
%      \fi
%    \fi}
%
% todo: adapt \strc_references_goto_internal to take an extra argument, the ref

\permanent\protected\def\withregisterpagecommand#1#2#3#4% #1:processor #2:internal #3:realpage #4:page
  {\begingroup
   \ifcase#3\relax
     \tt [entry\space not\space flushed]%
   \else
     \def\currentregisterpageindex{#2}%
     \def\currentregisterrealpage{#3}%
     \ifchknum\currentregisterpageindex\or
       \lettonothing\currentregisterpageprefix
     \else
       \def\currentregisterpageprefix{\clf_registerlabel{\currentregisterpageindex}}%
     \fi
     \iflocation
       \ifempty\currentregisterpageprefix
         \strc_references_get_simple_reference{internal(\currentregisterpageindex)}%
       \else
         \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}%
       \fi
       \global\lastsavedreferenceattribute\currentreferenceattribute
       \c_attr_reference\currentreferenceattribute
       \setlocationattributes
     \fi
     \applyprocessor{#1}{\currentregisterpageprefix\registerparameter\c!pagecommand{#4}}%
   \fi
   \endgroup}

\lettonothing\m_current_register

\permanent\protected\def\pushcurrentregister#1%
  {\let\m_current_register\currentregister
   \cdef\currentregister{#1}}

\permanent\protected\def\popcurrentregister
  {\let\currentregister\m_current_register}

\permanent\protected\def\registeronepage#1#2#3#4#5% #1:class #2:processor content
  {\pushcurrentregister{#1}%
   \strc_registers_update_page_properties
   \ifcstok{\registerparameter\c!pagenumber}\v!no\else
     \registerpageseparator
     \global\setconstant\c_strc_registers_page_state\plusone
     \dostarttagged\t!registerpage\empty
     \withregisterpagecommand{#2}{#3}{#4}{#5}%
     \dostoptagged
   \fi
   \popcurrentregister}

\newconditional\c_strc_registers_following

\appendtoks
    \edef\p_compress{\registerparameter\c!compress}%
    \ifx\p_compress\v!text
      \c_strc_registers_following\conditionaltrue
      \letregisterparameter\c!compress\v!yes
    \else
      \c_strc_registers_following\conditionalfalse
    \fi
\to \everyplaceregister

\permanent\protected\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor  content, content todo: -- configurable
  {\pushcurrentregister{#1}%
   \strc_registers_update_page_properties
   \ifcstok{\registerparameter\c!pagenumber}\v!no\else
     \registerpageseparator
     \global\setconstant\c_strc_registers_page_state\plusone
     \dostarttagged\t!registerpagerange\empty
     \dostarttagged\t!registerfrompage\empty
     \withregisterpagecommand{#2}{#3}{#4}{#5}%
     \dostoptagged
     \ifconditional\c_strc_registers_following
       \ifnum#3=\numexpr#6-1\relax
         \labeltext{following:\s!singular}%
       \else
         \labeltext{following:\s!plural}%
       \fi
     \else
       \registeronepagerangeseparator
       \dostarttagged\t!registertopage\empty
       \withregisterpagecommand{#2}{#6}{#7}{#8}%
     \fi
     \dostoptagged
     \dostoptagged
   \fi
   \popcurrentregister}

\permanent\protected\def\defaultregisterentry#1#2#3#4#5% #1:class #2:processor #3:internal #4:seeindex #5:word
  {\pushcurrentregister{#1}%
   \strc_registers_update_text_properties
   \def\currentregisterpageindex{#3}%
   \iflocation
     \def\currentregisterseeindex{#4}%
     \ifconditional\c_strc_registers_text_interaction
       \ifchknum\currentregisterpageindex\or
         \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]%
       \fi
     \else
       \doapplyregisterentrycommand{#2}{#5}%
     \fi
   \else
     \lettonothing\currentregisterseeindex
     \doapplyregisterentrycommand{#2}{#5}%
   \fi
   \popcurrentregister}

\permanent\protected\def\doapplyregisterentrycommand#1#2% processor text
  {\dostarttagged\t!registercontent\empty
   \ifempty\currentregisterseeindex \else
     \dontleavehmode
     \dosetdirectpagereference{seeindex:\currentregisterseeindex}% maybe some day we will support an area
   \fi
   \applyprocessor{#1}{\registerparameter\c!textcommand{\limitedregisterentry{\registerparameter\c!deeptextcommand{#2}}}}%
   \dostoptagged}

\permanent\protected\def\doapplyregisterseecommand#1#2%
  {\ifempty\currentregisterseeindex
     \applyprocessor{#1}{#2}%
   \orelse\iflocation
     \strc_references_goto_internal{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]%
   \else
     \applyprocessor{#1}{#2}%
   \fi}

\permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word
  {\pushcurrentregister{#1}%
   \ifnum#2=\plusone
     \registerpageseparator
   \fi
   \global\setconstant\c_strc_registers_page_state\plustwo
   \def\currentregisterpageindex{#5}%
   \def\currentregisterseeindex{#6}%
   \dostarttagged\t!registersee\empty
   \c_strc_registers_page_done\conditionaltrue
   \ifchknum\currentregisterseeindex\or
     \lettonothing\currentregisterpageprefix
   \else
     \def\currentregisterpageprefix{\clf_registerlabel{\currentregisterseeindex}}%
   \fi
   \iflocation
     \ifempty\currentregisterpageprefix
       \strc_references_get_simple_reference{internal(\currentregisterseeindex)}%
     \else
       \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}%
     \fi
     \global\lastsavedreferenceattribute\currentreferenceattribute
     \c_attr_reference\currentreferenceattribute
     \setlocationattributes
   \fi
   \ifnum#2=\plusone
     \labeltexts\v!see{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}%
   \orelse\ifnum#2=#3\relax
     \labeltexts\v!and{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}%
   \else
     ,\space\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}%
   \fi
   \dostoptagged
   \popcurrentregister}

\permanent\protected\def\doapplyregistersectioncommand#1#2%
  {\ifempty\currentregistersectionindex
     \applyprocessor{#1}{#2}%
   \orelse\iflocation
     \strc_references_goto_internal{\applyprocessor{#1}{#2}}[sectionindex:\currentregistersectionindex]%
   \else
     \applyprocessor{#1}{#2}%
   \fi}

\permanent\protected\def\defaultregistersection#1#2#3#4#5#6#7% class i n #4:processor #5:internal #6:sectionindex #7:word
  {\pushcurrentregister{#1}%
   \ifnum#2=\plusone
     \registerpageseparator
   \fi
   \global\setconstant\c_strc_registers_page_state\plustwo
   \def\currentregisterpageindex{#5}%
   \dostarttagged\t!registersection\empty
   \c_strc_registers_page_done\conditionaltrue
   \iflocation
     \def\currentregistersectionindex{#6}%
   \else
     \lettonothing\currentregistersectionindex
   \fi
   \ifnum#2=\plusone\else
      ,\space
   \fi
   \doapplyregistersectioncommand{#4}{#7}%
   \dostoptagged
   \popcurrentregister}

\aliased\let\registersection  \defaultregistersection
\aliased\let\registerseeword  \defaultregisterseeword
\aliased\let\registerentry    \defaultregisterentry
\aliased\let\registercharacter\defaultregistercharacter

%D Experimental:
%D
%D \starttyping
%D \setupregister
%D   [index]
%D   [pagesegments=1:4,
%D    pagemethod=section]
%D
%D \starttext
%D
%D     \chapter {one} \section {alpha}
%D
%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
%D
%D     \chapter {one} \section {alpha}
%D
%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
%D
%D     \placeindex[n=1]
%D
%D \stoptext
%D \stoptyping

%D A few specific rendering variants:

% \def\doregisterpagelocation#1#2%
%   {\nextregisterpage
%    \hbox to 1em{\hss\doregisterpagehowto{#1}{#2}\hss}}

% todo: \installregisterpagehandler

% \def\MyRegisterPageCommand#1%
%   {#1\currentregisterpageuserdata{whatever}}
%
% \starttext
%     \setregisterentry[index][entries=aaa][whatever=f.] test \index{bbb} test
%     \placeregister[index][n=1,pagecommand=\MyRegisterPageCommand]
% \stoptext

\permanent\def\registerpageuserdata       #1#2{\clf_registeruserdata#1{#2}}
\permanent\def\currentregisterpageuserdata    {\registerpageuserdata\currentregisterpageindex} % {#1}

% not yet ok : new internal handler names

\lettonothing\registerpageseparatorsymbol

\permanent\protected\def\registerpagebuttonsymbol
  {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax}

\installcorenamespace{registersymbol}

\defcsname\??registersymbol n\endcsname
  {\enforced\frozen\def\registerpageseparatorsymbol{,\space}}

\defcsname\??registersymbol a\endcsname
  {\enforced\frozen\def\registerpageseparatorsymbol{,\space}} % now done via conversion

\defcsname\??registersymbol\v!none\endcsname
  {\enforced\frozen\lettonothing\registerpageseparatorsymbol
   \enforced\frozen\let\registeronepage\gobblefivearguments
   \enforced\frozen\let\registerpagerange\gobbleeightarguments}

\defcsname\??registersymbol 1\endcsname
  {\enforced\frozen\let\registerpageseparatorsymbol\space
   \enforced\frozen\def\registeronepage{\symbol[1]\gobblefivearguments}%
   \enforced\frozen\def\registerpagerange{\symbol[1]\gobbleeightarguments}}

\defcsname\??registersymbol 2\endcsname
  {\enforced\frozen\let\registerpageseparatorsymbol\space
   \enforced\frozen\def\registeronepage{\registerpagebuttonsymbol\gobblefivearguments}%
   \enforced\frozen\def\registerpagerange{\registerpagebuttonsymbol\gobbleeightarguments}}

\protected\def\strc_registers_set_page_rendering
  {\ifcstok{\registerparameter\c!pagenumber}\v!no
     \enforced\frozen\let\currentregisterpagesymbol\v!none
   \else
     \enforced\frozen\edef\currentregisterpagesymbol{\registerparameter\c!symbol}%
   \fi
   \ifempty\currentregisterpagesymbol
     \csname\??registersymbol n\endcsname
   \orelse\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname
     \csname\??registersymbol\currentregisterpagesymbol\endcsname
   \else
     \enforced\frozen\let\registerpageseparatorsymbol\space
     \enforced\frozen\def\registeronepage{\registerparameter\c!symbol\gobblefivearguments}%
     \enforced\frozen\def\registerpagerange{\registerparameter\c!symbol\gobbleeightarguments}%
   \fi}

\appendtoks
     \strc_registers_set_page_rendering
\to \everyplaceregister

%D The linked register code will be reimplemented (not that hard) when it's needed
%D again and/or when I'm bored.

\permanent          \def\findregisterinternal#1#2#3{\clf_findregisterinternal{#1}{#2}#3\relax}
\permanent\protected\def\pageofinternal          #1{\clf_pageofinternal#1\relax}

\permanent\protected\def\linkedregisterentrylink#1#2#3#4% tag where before after
  {\iflocation
     \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax
     \ifcase\scratchcounter\else
       #3\relax
       \goto{\symbol[#2]}[internal(\the\scratchcounter)]%
       #4\relax
     \fi
   \else
   % \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax
   % \ifcase\scratchcounter\else
   %   #3\relax
   %   \pageofinternal\scratchcounter
   %   #4\relax
   % \fi
   \fi}

\permanent\protected\def\linkedregisterentry#1%
  {\dontleavehmode
   \begingroup
   \setbox\scratchbox\hbox{#1}%
   \linkedregisterentrylink\currentregistername\v!previous\relax\nobreakspace
   \unhbox\scratchbox
   \linkedregisterentrylink\currentregistername\v!next\nobreakspace\relax
   \endgroup}

\permanent\protected\def\registerpacked#1#2%
  {\iflocation
     \hskip\d_strc_registers_distance\relax
     \nobreak
     \ifnum#1=#2\relax
       \goto{\symbol[\v!somewhere]}[internal(#1)]%
     \else
       \goto{\symbol[\v!first]}[internal(#1)]%
       \nobreakspace
       \goto{\symbol[\v!last]}[internal(#2)]%
     \fi
   \fi}

%D Default index:

\defineregister
  [\v!index]
%  [\v!indices]

\stopcontextdefinitioncode

\protect \endinput

% % maybe also more levels with [entries|keys|processors]:n
% %
% % \setregisterentry
% %   [index]
% %   [entries:1=one,
% %    entries:2=two,
% %    entries:3=three,
% %    entries:4=four]
% %
% % test \blank \placeregister[index][balance=no]
%
% \def\expanddetokenizedregistervalues#1#2%
%   {\edef\expandedregistervalue{\detokenizedregisterparameter{#1:#2}}%
%    \ifempty\expandedregistervalue\else
%       \letregisterparameter{#1:#2}\expandedregistervalue
%       \expandafter\expanddetokenizedregistervalues
%       \expandafter#1%
%       \expandafter{\the\numexpr#2+1}%
%    \fi}%
%
% \def\expandregistervalues#1#2%
%   {\edef\expandedregistervalue{\registerparameter{#1:#2}}%
%    \ifempty\expandedregistervalue\else
%       \letregisterparameter{#1:#2}\expandedregistervalue
%       \expandafter\expandregistervalues
%       \expandafter#1%
%       \expandafter{\the\numexpr#2+1}%
%    \fi}%
%
% % \def\injectregistervalues#1#2%
% %   {\beginlocalcontrol
% %    \edef\expandedregistervalue{\registerparameter{#1:\the\numexpr#2}}%
% %    \endlocalcontrol
% %    \ifempty\expandedregistervalue\else
% %       {\expandedregistervalue}%
% %       \injectregistervalues#1{#2+1}%
% %     \fi}%
%
% \def\injectregistervalues#1#2%
%   {\ifempty{\registerparameter{#1:\the\numexpr#2}}\else
%       \expandafter{\lastnamedcs}%
%       \injectregistervalues#1{#2+1}%
%     \fi}%
%
% \def\strc_registers_register_page_expand_xml_entries
%   {\xmlstartraw
%      \beginlocalcontrol
%      \expandregistervalues\c!entries1%
%      \endlocalcontrol
%    \xmlstopraw
%    \glet\currentregistercoding\s!xml}
%
% \def\strc_registers_register_page_expand_yes_entries
%   {\beginlocalcontrol
%    \expandregistervalues\c!entries1%
%    \endlocalcontrol
%    \glet\currentregistercoding\s!tex}
%
% \def\strc_registers_register_page_expand_nop_entries
%   {\beginlocalcontrol
%    \expanddetokenizesregistervalues\c!entries1%
%    \endlocalcontrol
%    \glet\currentregistercoding\s!tex}
%
% \def\strc_registers_register_page_expand_nop_entries
%   {\beginlocalcontrol
%    \expandregistervalues\c!entries1%
%    \endlocalcontrol
%    \glet\currentregistercoding\s!tex}
%
% \def\strc_registers_register_page_expand_xml_keys
%   {\xmlstartraw
%      \beginlocalcontrol
%      \expandregistervalues\c!keys1%
%      \endlocalcontrol
%    \xmlstopraw}
%
% \def\strc_registers_register_page_expand_yes_keys
%   {\beginlocalcontrol
%    \expandregistervalues\c!keys1%
%    \endlocalcontrol}
%
% \def\strc_registers_register_page_expand_processors
%   {\beginlocalcontrol
%    \expandregistervalues\c!processors1%
%    \endlocalcontrol}
%
% \def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata
%   {\begingroup
%    \cdef\currentregister{#1}%
%    %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
%    \setupcurrentregister[#2]%
%    \edef\currentregisterlabel     {\registerparameter\c!label}%
%    \edef\currentregisterexpansion {\registerparameter\c!expansion}%
%    \edef\currentregisterownnumber {\registerparameter\c!ownnumber}%
%    \xdef\currentregisterkeys      {\registerparameter\c!keys}%
%    \xdef\currentregisterentries   {\registerparameter\c!entries}%
%    \xdef\currentregisterprocessors{\registerparameter\c!processors}%
%    \xdef\currentregisterxmlsetup  {\registerparameter\c!xmlsetup}%
%    \ifempty\currentregisterentries
%      \ifx\currentregisterexpansion\s!xml
%        \strc_registers_register_page_expand_xml_entries
%      \orelse\ifx\currentregisterexpansion\v!yes
%        \strc_registers_register_page_expand_yes_entries
%      \else
%        \strc_registers_register_page_expand_nop_entries
%      \fi
%    \else
%      \ifx\currentregisterexpansion\s!xml
%        \strc_registers_register_page_expand_xml
%      \orelse\ifx\currentregisterexpansion\v!yes
%        \strc_registers_register_page_expand_yes
%      \else
%        \strc_registers_register_page_expand_nop
%      \fi
%    \fi
%    \ifempty\currentregisterkeys
%      \ifx\currentregistercoding\s!xml
%        \strc_registers_register_page_expand_xml_keys
%      \else
%        \strc_registers_register_page_expand_yes_keys
%      \fi
%    \fi
%    \strc_registers_register_page_expand_processors
%    \setnextinternalreference
%    % we could consider storing register entries in a list which we
%    % could then sort
%    \glet\currentregistername\currentregister
%    \xdef\currentregisternumber{\clf_storeregister % 'own' should not be in metadata
%         metadata {%
%             name     {\currentregister}%
%             coding   {\currentregistercoding}%
%         \ifx\currentregisterownnumber\v!yes
%             own      {\registerparameter\c!alternative}% can be used instead of pagenumber
%         \fi
%         \ifx\currentreferencecoding\s!xml
%             xmlroot  {\xmldocument} % only useful when text
%         \fi
%         \ifempty\currentregisterxmlsetup \else
%             xmlsetup {\currentregisterxmlsetup}%
%         \fi
%         }%
%         references {%
%         \ifempty\currentregisterlabel \else
%             label    {\currentregisterlabel}%
%         \fi
%          %  view     {\interactionparameter\c!focus}%
%         }%
%         entries {%
%             % we need a special one for xml, this is just a single one
%             \ifempty\currentregisterentries
%                 entries {\injectregistervalues\c!entries1}%
%             \else
%                 entry {\currentregisterentries}%
%             \fi
%             \ifempty\currentregisterkeys
%                 keys {\injectregistervalues\c!keys1}%
%             \else
%                 key {\currentregisterkeys}%
%             \fi
%             \ifempty\currentregisterprocessors
%                 processors {\injectregistervalues\c!processors1}%
%             \else
%                 processor {\currentregisterprocessors}%
%             \fi
%         }%
%         userdata {\detokenize\expandafter{\normalexpanded{#3}}}
%    }%
%    \clf_setinternalreference
%       internal \locationcount
%       view     {\interactionparameter\c!focus}%
%    \relax % this will change
%    \ifx\currentregisterownnumber\v!yes
%      \glet\currentregistersynchronize\relax
%    \else
%      \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
%    \fi
%    \currentregistersynchronize % here?
%    % needs thinking ... bla\index{bla}. will break before the . but adding a
%    % penalty is also no solution
%    \dostarttagged\t!registerlocation\currentregister
%    \c_attr_destination\lastdestinationattribute
%    \signalcharacter % no \strut as it will be removed during cleanup
%    \dotagregisterlocation
%    \dostoptagged
%    \endgroup}

