%D \module
%D   [       file=core-reg,
%D        version=1999.12.27,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Register Management,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{Context Core Macros / Register Management}

\newif \ifautoregisterhack % for the moment a private hack

% new: eigennummer=ja => eerste {} ipv pag nummer

\unprotect

%D Isolated but still indocumented.

%  Formaat tex-utility-input-file <jobname.tui>:
%
%    i e {tag} {loc} {pure} {entry+..} {p:c:p:sp:ssp=>page} {realpage}
%    i s {tag} {loc} {pure} {entry+..} {other entry}
%
%  In plaats van + kan een & worden gebruikt. Ook kan als
%  eerste karakter worden opgegeven wat de scheider is.
%
%  \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}
%
%  Deze file wordt met het Perl script TeXUtil omgezet in
%  een in te lezen file met de commando's:
%
%    \registerentrya {tag} {ingang}
%    \registerentryb {tag} {subingang}
%    \registerentryc {tag} {subsubingang}
%
%    \registerpage   {tag} {pag,txt} {volgnummer} {paginanummer} {volgnummer}
%
%    \registersee    {tag} {pag,txt} {andere ingang}
%
%    \registerentry  {tag} {letter}

\def\dosetupregister[#1][#2][#3]%
  {\ifthirdargument
     \def\dodosetupregister##1%
       {\getparameters[\??id##1#2][#3]%
        \preparepageprefix{\??id##1}}%
   \else
     \def\dodosetupregister##1%
       {\getparameters[\??id##1][#2]%
        \doifvalue{\??id##1\c!coupling}\v!yes
          {\appendtoks\coupleregister[##1][#2]\to\everystarttext}%
        \preparepageprefix{\??id##1}}%
   \fi
   \processcommalist[#1]\dodosetupregister}

\def\setupregister
  {\dotripleempty\dosetupregister}

\def\getlastregisterentry#1%
  {\def\docommando##1%
     {\def\!!stringa{##1}}%
   \processseparatedlist[#1][+]\docommando
   \!!stringa}

\def\registerparameter#1{\csname\??id\currentregister#1\endcsname}

% \enableregime[windows] \setupregister[index][keyexpansion=strict]
%
% \index[Ätsch]{Ätsch} test \index{QÄtsch} test \index[ratsch]{RÄtsch} test

\def\doprocesspageregister[#1]#2#3% key altnum entry
  {\begingroup
   \thisisnextinternal\s!ind
   \ifduplicate\getlastregisterentry{#3}\fi
   \convertexpanded{\registerparameter\c!keyexpansion}{#1}\asciiregisterentryA
   \convertexpanded{\registerparameter\c!expansion   }{#3}\asciiregisterentryB
   \doifsomething{\registerparameter\c!keyexpansion}
     {\ifx\asciiregisterentryA\empty
       \convertexpanded{\registerparameter\c!keyexpansion}{#3}\asciiregisterentryA
      \fi}%
   \makesectionformat
   \doifelse{\registerparameter\c!ownnumber}\v!yes
     \donetrue\donefalse
   % the spaces between } { are essential for texutil's split
   \expanded
     {\writeutility%
        {r \ifcase\registerpagestatus\space\or e \or f \or t \fi
         {\currentregister} %
         {\nextinternalreference} %
         {\asciiregisterentryA} %
         {\asciiregisterentryB} %
         {\sectionformat\sectionseparator\sectionseparator
          \ifdone#2\else\noexpand\pagenumber\fi} %
         {\noexpand\realfolio}}}%
   \getfirstcharacter\currentregister
   \registerinfo{> \firstcharacter}{#3}%
   \endgroup}

\def\doregister#1%
  {\chardef\registerpagestatus\plusone
   \def\currentregister{#1}%
   \doifelse{\registerparameter\c!ownnumber}\v!yes
     {\dosingleempty\dodoregister}
     {\dosingleempty\donoregister}}

\def\donoregister[#1]%
  {\dodoregister[#1]{}}

% \def\dodoregister[#1]#2#3%
%   {\doprocesspageregister[#1]{#2}{#3}%
%    \ifvmode\nobreak\fi
%    \GotoPar}

\def\dodoregister[#1]#2#3%
  {\dogotopar{\doprocesspageregister[#1]{#2}{#3}}}

\def\writetoregister[#1]% to be documented
  {\doregister{#1}}

% \def\startregister
%   {\dodoubleargument\dostartregister}

% \def\dostartregister[#1][#2]#3%
%   {\chardef\registerpagestatus\plustwo
%    \def\currentregister{#1}%
%    \setgvalue{\??id#1\??id#2}{\dodostopregister[#1][#2]{#3}}%
%    \donoregister[#2]{#3}}

\def\startregister
  {\dotripleempty\dostartregister}

\def\dostartregister[#1][#2][#3]#4%
  {\chardef\registerpagestatus\plustwo
   \def\currentregister{#1}%
   \setgvalue{\??id#1\??id#2}{\dodostopregister[#1][#3]{#4}}%
   \dodoregister[#3]{}{#4}}

\def\stopregister
  {\dodoubleargument\dostopregister}

\def\dostopregister[#1][#2]%
  {\getvalue{\??id#1\??id#2}\letgvalue{\??id#1\??id#2}\relax}

% \def\dodostopregister[#1][#2]%
%   {\chardef\registerpagestatus\plusthree
%    \def\currentregister{#1}%
%    \donoregister[#2]}

\def\dodostopregister[#1][#2]#3%
  {\chardef\registerpagestatus\plusthree
   \def\currentregister{#1}%
   \dodoregister[#2]{}{#3}} % key altnum entry

\def\complexdoseeregister[#1]#2#3%
  {\begingroup
     \thisisnextinternal\s!ind
     \ifduplicate\getlastregisterentry{#2}\fi
     \convertexpanded{\registerparameter\c!keyexpansion}{#1}\asciiregisterentryA
     \convertexpanded{\registerparameter\c!expansion   }{#2}\asciiregisterentryB
     \convertexpanded{\registerparameter\c!expansion   }{#3}\asciiregisterentryC
\doifsomething{\registerparameter\c!keyexpansion}
  {\ifx\asciiregisterentryA\empty
     \convertexpanded{\registerparameter\c!keyexpansion}{#2}\asciiregisterentryA
   \fi}%
     \makesectionformat
     \expanded
       {\writeutility%
          {r s %
           {\currentregister} %
           {\nextinternalreference} %
           {\asciiregisterentryA} %
           {\asciiregisterentryB} %
           {\asciiregisterentryC} %
           {\sectionformat}}}%
   \endgroup
   \registerinfo{> see}{#2}%
   \GotoPar}

\def\doseeregister#1%
  {\def\currentregister{#1}%
   \complexorsimpleempty\doseeregister}

\def\dowritetoregister[#1]%  % de twee-traps-aanroep is nodig
  {\edef\currentregister{#1}%    % om gebruik van \ExpandBothAfter
   \doprocesspageregister{}}     % mogelijk te maken

\def\writetoregister
  {\dodoubleempty\dowritetoregister}

\def\ifregistergeplaatst{\ifutilitydone}

\newif\iffirstregisterpage
\newif\iffirstregisterentry

\let\c!entrya\empty
\let\c!entryb\empty
\let\c!entryc\empty

\def\nextregisterpage
  {\iffirstregisterpage
     \doglobal\newcounter\registerpagenumber
   \fi
   \doglobal\increment\registerpagenumber}

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

\def\setregisterpage#1%
  {\let\registerpageseparator\empty
   \processaction
     [\getvalue{\??id#1\c!symbol}]
     [      \c!n=>{\def\doregisterpage##1[##2]%
                     {\doregisterpagelocation{#1}{\registerpagenumber}\/}},
            \c!a=>{\def\doregisterpage##1[##2]%
                     {\doregisterpagelocation{#1}{\character{\registerpagenumber}\/}}},
               1=>{\def\doregisterpage##1[##2]%
                     {\doregisterpagelocation{#1}{$\bullet$}}},
               2=>{\def\doregisterpage##1[##2]%
                     {\doregisterpagelocation{#1}{\vrule\!!width1em\!!height1ex\!!depth\!!zeropoint}}},
         \v!none=>{\def\doregisterpage##1[##2]{}},%
      \s!unknown=>{\def\registerpagesymbol{\getvalue{\??id#1\c!symbol}}%
                   \def\doregisterpage##1[##2]%
                     {\doregisterpagelocation{#1}{\registerpagesymbol}}},
      \s!default=>{\def\registerpageseparator%
                     {,}%
                   \def\doregisterpage##1[##2]%
                     {\doregisterpagehowto{##1}
                        {\strut
                         \pageprefix{\??id##1}[##2]%
                         \translatednumber[##2]}}}]}

\let\registerpagehowto\empty
\let\registertexthowto\empty

\def\setregisterhowto[#1,#2]%
  {\def\registerpagehowto{#1}%
   \def\registertexthowto{#2}}%

\def\doregistertexthowto#1#2%
  {\dostartattributes{\??id#1\registertexthowto}\c!textstyle\c!textcolor\empty
   \getvalue{\??id#1\c!textcommand}{#2}%
   \dostopattributes}

\def\doregisterpagehowto#1#2%
  {\dostartattributes{\??id#1\registerpagehowto}\c!pagestyle\c!pagecolor\empty
   \getvalue{\??id#1\c!pagecommand}{#2}%
   \dostopattributes}

\def\registerentry #1{\executeifdefined{#1\s!entry }\gobbleoneargument   }
\def\registerentrya#1{\executeifdefined{#1\s!entrya}\gobbleoneargument   }
\def\registerentryb#1{\executeifdefined{#1\s!entryb}\gobbleoneargument   }
\def\registerentryc#1{\executeifdefined{#1\s!entryc}\gobbleoneargument   }
\def\registersee   #1{\executeifdefined{#1\s!see   }\gobblethreearguments}
\def\registerpage  #1{\executeifdefined{#1\s!page  }\gobblefourarguments }
\def\registerfrom  #1{\executeifdefined{#1\s!from  }\gobblefourarguments }
\def\registerto    #1{\executeifdefined{#1\s!to    }\gobblefourarguments }

\def\doresetregister#1%
  {\letvalue{#1\s!entrya}\gobbleoneargument
   \letvalue{#1\s!entryb}\gobbleoneargument
   \letvalue{#1\s!entryc}\gobbleoneargument
   \letvalue{#1\s!see   }\gobblethreearguments
   \letvalue{#1\s!page  }\gobblefourarguments
   \letvalue{#1\s!from  }\gobblefourarguments
   \letvalue{#1\s!to    }\gobblefourarguments
   \letvalue{#1\s!entry }\gobbleoneargument}

\newif\iffirstsubentry
\newif\iffirstsubsubentry

\newcounter\currententrylevel

\let\c!entryletter   =\empty
\let\c!entryreference=\empty
\let\c!entrya        =\relax
\let\c!entryb        =\relax
\let\c!entryc        =\relax

\chardef\lastregisterpagestatus=0

\def\limitedregisterentry#1#2%
  {\getvalue{\??id#1\c!textcommand}%
     {\doifelsenothing{\??id#1\c!maxwidth}
        {#2}
        {\limitatetext{#2}{\getvalue{\??id#1\c!maxwidth}}{\unknown}}}}

\def\dosetpageregisterpage#1#2#3#4#5#6%
  {\doifreglevelelse[#5]{\dodosetpageregisterpage{#1}{#2}{#3}{#4}{#5}{#6}}{}}

\def\dodosetpageregisterpage#1#2#3#4#5#6%
   {\global\utilitydonetrue
    \c!entryletter
    \setregisterhowto[#3]%
    \def\dohandleregisterentry##1%
      {\bgroup
       \if!!donea % \strut nieuw
         %\setbox0\hbox{\showlocation{\doregistertexthowto{#2}
         %  {\strut\limitedregisterentry{#2}{##1}}}}%
         % \gotonextinternal\s!ind{#4}{#6}{\box0}%
         %
         \hhboxindent\hangindent % maybe also left and right skip
         \setbox0\hbox{\doregistertexthowto{#2}{\strut\limitedregisterentry{#2}{##1}}}%
         \unhhbox0\with{\gotonextinternal\s!ind{#4}{#6}{\box\hhbox}}%
         %
       \else
         \doregistertexthowto{#2}{##1}%
       \fi
       \egroup
       \!!doneafalse}%
    \!!doneafalse
    \doifelsevalue{\??id#2\c!interaction}\v!text
      {\ifcase\currententrylevel                 \or
         \!!doneatrue\c!entrya\c!entryb\c!entryc \or
         \c!entrya\!!doneatrue\c!entryb\c!entryc \or
         \c!entrya\c!entryb\!!doneatrue\c!entryc \fi}
      {\c!entrya\c!entryb\c!entryc}%
    \global\let\c!entrya\relax
    \global\let\c!entryb\relax
    \global\let\c!entryc\relax
    \global\let\c!entryletter\relax
    \global\let\c!entryreference\relax
   % \global\firstregisterentrytrue
    \iffirstregisterpage
      \global\chardef\lastregisterpagestatus\zerocount
      \expandafter\hskip\getvalue{\??id#2\c!distance}\relax
      \donetrue
    \else\ifnum#1=3
      |--|\relax % -- !
      \donetrue
    \else\ifnum\lastregisterpagestatus=2
      \donefalse % waiting for "to" pagenumber
    \else
      \registerpageseparator
      |\space|\relax % \relax needed because | looks ahead
      \donetrue
    \fi\fi\fi
    \ifdone
      \begingroup
%
\doifelsevalue{\??id#2\c!prefix}\v!none % default v!both
  {\chardef\pageprefixmode\zerocount}%
  {\doifvalue{\??id#2\c!prefix}\v!first % only first in range (1.2-4)
     {\ifnum#1=3 \chardef\pageprefixmode\zerocount \fi}}%
%
      \doifelsevalue{\??id#2\c!interaction}\v!pagenumber
        {\bgroup
         \setbox0\hbox
           {\showlocation{\doregisterpage{#2}[#5]\ifnum#1=2\/\fi}}%
         \gotonextinternal{\s!ind}{#4}{#6}{\box0}%{\copy0}%
         \egroup}
        {\hbox{\doregisterpage{#2}[#5]\ifnum#1=2\/\fi}}%
\endgroup
      \ignorespaces
      \global\chardef\lastregisterpagestatus#1\relax
    \fi
    \global\firstregisterpagefalse}

\def\dosetpageregistersee#1#2#3#4% ugly separator hack
  {\expanded{\doifreglevelelse[#4\sectionseparator\sectionseparator0]}%
     {{\global\utilitydonetrue
       \setregisterhowto[#2]%
       \def\dohandleregisterentry##1% dubbelop | \strut nieuw
         {\doregistertexthowto{#1}{\strut\limitedregisterentry{#1}{##1}}}%
       \getvalue
         {#1\ifcase\currententrylevel\s!entrya\or\s!entryb\else\s!entryc\fi}%
         {\doregisterpagehowto{#1}{\labeltexts\v!see{#3}}}%
       \c!entryletter\c!entrya\c!entryb\c!entryc
       \global\let\c!entrya\relax
       \global\let\c!entryb\relax
       \global\let\c!entryc\relax
       \global\let\c!entryletter\relax
       \global\let\c!entryreference\relax
       \global\chardef\lastregisterpagestatus\zerocount
    %   \global\firstregisterentrytrue
       \global\firstregisterpagefalse}}
     {}}

%D Extended with variant:

\def\doregistercharacter[#1]#2%
  {\global\firstregisterentrytrue
   \doifelsevalue{\??id#1\c!indicator}\v!yes
     {\executeifdefined
        {\strippedcsname\doregistercharacter\getvalue{\??id#1\c!alternative}}%
        \doregistercharactera
        [#1]{#2}}
     {\noregistercharacter[#1]{#2}}}

\def\noregistercharacter[#1]#2%
  {\getvalue{\??id#1\c!before}%
   \goodbreak}

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

\def\doregistercharactera[#1]#2%
  {\getvalue{\??id#1\c!before}%
   \vskip\lineheight\goodbreak\vskip-\lineheight
   \ifhmode\unskip\else\noindent\fi % brrr
   \getvalue{\??id#1\c!command}{\doattributes{\??id#1}\c!style\c!color{\strut\ignorespaces#2}}%
   \getvalue{\??id#1\c!after}%
   \par\nobreak}

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

\def\doregistercharacterb[#1]#2% here no lineheight hackery ! ! !
  {\getvalue{\??id#1\c!before}%
   \ifhmode\unskip\else\noindent\fi % brrr
   \getvalue{\??id#1\c!command}%
     {\doattributes{\??id#1}\c!style\c!color{\strut\ignorespaces#2}}%
   \getvalue{\??id#1\c!after}%
   \nobreak}

\def\doregistercharacterA[#1]#2{\doregistercharactera[#1]{\WORD{#2}}}
\def\doregistercharacterB[#1]#2{\doregistercharacterb[#1]{\WORD{#2}}}

%D Don't use \type{\string#2}; another hack is needed, since
%D \type {#2} can be \type {\string} itself.

\def\doregisterreference[#1]#2%
  {\doifvalue{\??id#1\c!referencing}\v!on
     {\pagereference[#1:#2]}}

\def\dosetpageregisterletter#1#2%
  {\gdef\c!entryreference
     {\global\let\c!entryreference\relax
      \doregisterreference[#1]{#2}}%
   \gdef\c!entryletter
     {\global\utilitydonetrue
      \global\let\c!entryletter\relax
      \doregistercharacter[#1]{#2}}}

\def\dosetpageregisterentrya#1#2%
  {\edef\currententrylevel{1}%
   \global\let\c!entryb\relax
   \global\let\c!entryc\relax
   \gdef\c!entrya
     {\iffirstregisterentry\else\endgraf\fi % new
      \global\firstregisterpagetrue
      \hangindent1em\noindent\c!entryreference
      \dohandleregisterentry{#2}%
      \global\firstregisterentryfalse
      \global\firstsubentrytrue
      \global\firstsubsubentrytrue}}

\def\dosetpageregisterentryb#1#2%
  {\edef\currententrylevel{2}%
   \global\let\c!entryc\relax
   \global\def\c!entryb
     {\iffirstregisterentry\else\endgraf\fi % new
      \global\firstregisterpagetrue
      \global\let\c!entrya\relax
      \iffirstsubentry\nobreak\fi
      \hangindent2em\noindent\c!entryreference\hskip1em\relax
      \dohandleregisterentry{#2}%
      \global\firstregisterentryfalse
      \global\firstsubentryfalse
      \global\firstsubsubentrytrue}}

\def\dosetpageregisterentryc#1#2%
  {\edef\currententrylevel{3}%
   \gdef\c!entryc
     {\iffirstregisterentry\else\endgraf\fi % new
      \global\firstregisterpagetrue
      \global\let\c!entrya\relax
      \global\let\c!entryb\relax
      \iffirstsubsubentry\nobreak\fi
      \hangindent3em\noindent\c!entryreference\hskip2em\relax
      \dohandleregisterentry{#2}%
      \global\firstregisterentryfalse
      \global\firstsubsubentryfalse}}

\def\dosetpageregister#1% \currentregister gebruiken
  {\dosetreglevel{#1}%
   \global\let\currentregisterentry\empty
   \global\firstsubentrytrue
   \global\firstsubsubentrytrue
   \setregisterpage{#1}%
   \chardef\lastregisterpagestatus\zerocount
   \setvalue{#1\s!entrya}{\dosetpageregisterentrya {#1}}%
   \setvalue{#1\s!entryb}{\dosetpageregisterentryb {#1}}%
   \setvalue{#1\s!entryc}{\dosetpageregisterentryc {#1}}%
   \setvalue{#1\s!page  }{\dosetpageregisterpage{1}{#1}}%
   \setvalue{#1\s!from  }{\dosetpageregisterpage{2}{#1}}%
   \setvalue{#1\s!to    }{\dosetpageregisterpage{3}{#1}}%
   \setvalue{#1\s!see   }{\dosetpageregistersee    {#1}}%
   \setvalue{#1\s!entry }{\dosetpageregisterletter {#1}}}

\def\dosetreglevel#1%
  {\dosetfilterlevel{\getvalue{\??id#1\c!criterium}}\empty}

\def\getalllistreferences#1#2%
  {\doglobal\convertexpanded{\getvalue{\??id#1\c!expansion}}{#2}\currentregisterentry
   \doifdefinedelse{\??id#1\??id\currentregisterentry}
     {\edef\alllistreferences%
        {\getvalue{\??id#1\??id\currentregisterentry}}%
      \beforesplitstring\alllistreferences\at::\to\internallistreference
      \aftersplitstring \alllistreferences\at::\to\alllistreferences}
     {\let\alllistreferences\empty
      \def\internallistreference{0}}}

\def\dosetlinkregister#1% is die page reference echt nodig?
  {\dosetreglevel{#1}%
   \setregisterpage{#1}%
   \global\let\currentregisterentry\empty
   \global\firstsubentrytrue % not needed
   \global\firstsubsubentrytrue % not needed too
   \setvalue{#1\s!entrya}##1{\dosetlinkregisterentrya{#1}{##1}}%
   \setvalue{#1\s!entry }##1{\dosetpageregisterletter{#1}{##1}}}

\def\dosetlinkregisterentrya#1#2%
   {\global\utilitydonetrue
    \c!entryletter
    \iflocation
      \getalllistreferences{#1}{#2}%
% \endgraf
      \hangindent1em\noindent\c!entryreference
      %
      %\thisissomeinternal{\s!lin}{\internallistreference}%
      %
      \pagereference[-:\s!lin:\internallistreference]% -: added
      %
      \getcommacommandsize[\alllistreferences]%
      \getfromcommacommand[\alllistreferences][1]%
      \ifnum\commalistsize=1
        \let\firstlistreference\empty
        \let\midlistreference\commalistelement
        \let\lastlistreference\empty
      \else
        \let\firstlistreference\commalistelement
        \getfromcommacommand[\alllistreferences][\commalistsize]%
        \let\lastlistreference\commalistelement
        \ifnum\commalistsize=2
          \let\midlistreference\empty
        \else
          \!!counta\commalistsize
          \divide\!!counta 2
          \getfromcommacommand[\alllistreferences][\!!counta]%
          \let\midlistreference\commalistelement
        \fi
      \fi
      % aangepast
      \def\dodocommando[##1-##2]%
        {\gotonextinternal{\s!ind}{##1}{##2}{\box0}}%
      \doifelsevalue{\??id#1\c!interaction}\v!pagenumber
        {\limitedregisterentry{#1}{#2}} % paginanummer
        {{\setbox0\hbox{\limitedregisterentry{#1}{\begstrut#2}}%
          \ifx\firstlistreference\empty  % tekst,alles
            \ifx\midlistreference\empty
              \box0
            \else
              \expandafter\dodocommando\expandafter[\midlistreference]%
            \fi
          \else
            \expandafter\dodocommando\expandafter[\firstlistreference]%
          \fi}}%
      \doifvalue{\??id#1\c!number}\v!yes
        {\hskip\getvalue{\??id#1\c!distance}(\commalistsize)}%
      \doifnotvalue{\??id#1\c!interaction}\v!text % paginanummer,alles
        {\def\docommando##1##2%
           {{\setbox0\hbox{\showlocation{\hbox to 1em{\hss\symbol[##2]\hss}}}%
             \ifx##1\empty
               % \hskip\wd0 % (optioneel maken)
             \else
               \expandafter\dodocommando\expandafter[##1]%
             \fi}}%
         \hskip\getvalue{\??id#1\c!distance}%
         \docommando\firstlistreference\v!previous
         \docommando\midlistreference\v!somewhere
         \docommando\lastlistreference\v!next}%
      % tot hier
    \else
% \endgraf
      \noindent\c!entryreference
      \limitedregisterentry{#1}{#2}%
    \fi
\endgraf}

\def\dosetregister#1%
  {\doifelsevalue{\??id#1\c!coupling}\v!yes
     {\ifautoregisterhack
        \dosetautoregister{#1}%
      \else
        \dosetlinkregister{#1}%
      \fi}
     {\dosetpageregister{#1}}}

\newcounter\internallistreference

\def\doloadregisterlinks#1%
  {\dosetreglevel{#1}%
   \setregisterpage{#1}%
   \global\let\currentregisterentry\empty
   \global\firstregisterpagetrue
   \setvalue{#1\s!entrya}##1%
     {\global\firstregisterpagetrue
      \doglobal\convertargument##1\to\currentregisterentry % \doglobal nodig?
      \doglobal\increment\internallistreference}%
   \setvalue{#1\s!from}%
     {\getvalue{#1\s!page}}%
\ifautoregisterhack
   \setvalue{#1\s!page}##1##2##3##4%
     {\doifreglevelelse[##3]
        {\global\utilitydonetrue
         \iffirstregisterpage
           \@EA\xdef\csname\??id#1\??id\currentregisterentry\endcsname
             {\internallistreference::##4}%
         \else % catches errors in index
           \ifcsname\??id#1\??id\currentregisterentry\endcsname
             \@EA\xdef\csname\??id#1\??id\currentregisterentry\endcsname
               {\csname\??id#1\??id\currentregisterentry\endcsname,##4}%
           \fi
         \fi}
        {}}%
\else
   \setvalue{#1\s!page}##1##2##3##4%
     {\doifreglevelelse[##3]
        {\global\utilitydonetrue
         \iffirstregisterpage
           \global\firstregisterpagefalse
           \@EA\xdef\csname\??id#1\??id\currentregisterentry\endcsname
             {\internallistreference::##2-##4}%
         \else % catches errors in index
           \ifcsname\??id#1\??id\currentregisterentry\endcsname
             \@EA\xdef\csname\??id#1\??id\currentregisterentry\endcsname
               {\csname\??id#1\??id\currentregisterentry\endcsname,##2-##4}%
           \fi
         \fi}
        {}}%
\fi}

\def\docoupleregister[#1][#2]%
  {\iflocation
     \ifcase0\countervalue{autolink:#1}\relax % only once
       \begingroup
       \let\dosetregister\doloadregisterlinks
       \setupregister[#1][#2]%
       \doutilities{#1}\jobname{#1}\relax\relax
       \endgroup
       \ifautoregisterhack
         \doinitializeautoregister{#1}%
       \else
         \doinitializelinkregister{#1}%
       \fi
     \fi
   \fi}

\def\coupleregister
  {\dodoubleempty\docoupleregister}

\def\dodocommandoprolinrefAA[#1-#2]%
  {\def\lastlistreference{#1-#2}}

\def\dodocommandoprolinrefA[#1-#2]%
  {\def\lastlistreference{#1-#2}%
   \ifx\firstlistreference\empty
     \let\firstlistreference\lastlistreference
   \fi
   \ifnum#1<\nextinternalreference\relax
     \let\prevlistreference\lastlistreference
   \else\ifnum#1>\nextinternalreference\relax
     \let\nextlistreference\lastlistreference
     \let\dodocommandoprolinrefA\dodocommandoprolinrefAA
   \else
     \let\selflistreference\lastlistreference
   \fi\fi}

\def\docommandoprolinrefA#1%
  {\dodocommandoprolinrefA[#1]}

\def\dodocommandoprolinrefB[#1-#2]%
  {\gotonextinternal{\s!ind}{#1}{#2}{\box0}}

\def\docommandoprolinrefB#1#2#3%
  {\bgroup
   \ifx#2\empty
     \doifvalue{\??id#1\c!unknownreference}\v!empty{\hskip1em}%
   \else
     \setbox0\hbox to 1em{\hss\showlocation{\symbol[#3]}\hss}%
     \expandafter\dodocommandoprolinrefB\expandafter[#2]%
   \fi
   \egroup}

\def\doprocesslinkregister[#1][#2]#3%
  {\hbox
     {\doprocesspageregister[#2]{}{#3}%
      \let\firstlistreference\empty
      \let\lastlistreference\empty
      \let\selflistreference\empty
      \let\prevlistreference\empty
      \let\nextlistreference\empty
      \getalllistreferences{#1}{#3}%
      \ifx\alllistreferences\empty \else
        \expanded{\rawprocesscommalist[\alllistreferences]}\docommandoprolinrefA
      \fi
       \ifx\prevlistreference\empty
         \let\prevlistreference\lastlistreference
       \fi
       \ifx\nextlistreference\empty
         \let\nextlistreference\firstlistreference
       \fi
       \ifx\prevlistreference\selflistreference
         \let\prevlistreference\empty
         \let\nextlistreference\empty
       \fi
       \setalignmentswitch{\getvalue{\??id#1\c!location}}%
       \ifcase\alignmentswitch
         % links
         \docommandoprolinrefB{#1}\prevlistreference\v!previous
         \docommandoprolinrefB{#1}\nextlistreference\v!next
       \or
         % midden
         \docommandoprolinrefB{#1}\prevlistreference\v!previous
       \or
         % rechts
       \fi
       \doifreferencefoundelse{\s!lin:\internallistreference}
         {\gotosomeinternal
            \s!lin \internallistreference \currentrealreference
            {\showlocation{\limitedregisterentry{#1}{#3}}}}
         {\hbox{\limitedregisterentry{#1}{#3}}}%
       \ifcase\alignmentswitch
         % links
       \or
         % midden
         \docommandoprolinrefB{#1}\nextlistreference\v!next
       \or
         % rechts
         \docommandoprolinrefB{#1}\prevlistreference\v!previous
         \docommandoprolinrefB{#1}\nextlistreference\v!next
       \fi}}

\def\dodolinkedregister[#1][#2]#3% page auto link
  {\bgroup
   \chardef\registerpagestatus\plusone
   \def\currentregister{#1}%
   \iflocation
     \ifautoregisterhack
       \def\next{\doprocessautoregister[#1][#2]}%
     \else
       \def\next{\doprocesslinkregister[#1][#2]}%
     \fi
   \else
     \def\next{\doprocesspageregister[#2]{}}%
   \fi
   \next{#3}%
   \egroup
   \ifvmode\nobreak\fi
   \GotoPar}

\def\dolinkedregister#1%
  {\dodoubleempty\dodolinkedregister[#1]}

\def\dosetautoregister#1%
  {\makecounter{autolink:#1}%
   \dosetreglevel{#1}%
   \setregisterpage{#1}%
   \global\let\currentregisterentry\empty
   \global\firstsubentrytrue % not needed
   \global\firstsubsubentrytrue % not needed too
   \setvalue{#1\s!entrya}##1{\dosetautoregisterentrya{#1}{##1}}%
   \setvalue{#1\s!entry }##1{\dosetpageregisterletter{#1}{##1}}}

\def\dosetautoregisterentrya#1#2%
  {\global\utilitydonetrue
   \c!entryletter
   \iflocation
     \getalllistreferences{#1}{#2}%
     \endgraf\hangindent1em\noindent\c!entryreference
     \pagereference[-:\s!lin:\internallistreference]%
     \pluscounter{autolink:#1}%
     \bgroup
    %\setupinteraction[\c!color=,\c!contrastcolor=,\c!style=]% kan sneller
     \resetinteractionparameter\c!color
     \resetinteractionparameter\c!contrastcolor
     \resetinteractionparameter\c!style
     \gotobox
       {\limitedregisterentry{#1}{\begstrut#2}}%
       [JS(SetRegisterEntry{\v!register,\countervalue{autolink:#1},#2,{\alllistreferences}})]%
     \egroup
   \else
     \endgraf\noindent\c!entryreference
     \limitedregisterentry{#1}{#2}%
   \fi}

\def\doprocessautoregister[#1][#2]#3%
  {\hbox
     {\doprocesspageregister[#2]{}{#3}%
      \doifreferencefoundelse{\s!lin:\internallistreference}
        {\gotosomeinternal \s!lin
           {\internallistreference}{\currentrealreference}
           {\showlocation{\limitedregisterentry{#1}{#3}}}}
        {\hbox{\limitedregisterentry{#1}{#3}}}}}

% \appendmacro aan openpaginaactie (in shipout)

%D The first implementation used one main field with clones.
%D In a 2500 page document this resulted in a rather (anoying)
%D long start||up time. This \quote {every page its own field}
%D solution, combined with a \quote {page open action}, works
%D much faster, but is conceptually pretty weak.

\def\complexregisterfield[#1]%
  {\definefield[#1:\realfolio][line][\v!register]%
   \field[#1:\realfolio]}

\def\simpleregisterfield
  {\complexregisterfield[\v!register]}

\definecomplexorsimple\registerfield

\setupfield
  [\v!register]
  [\c!width=10em,
   \c!height=3ex,
   \c!align=\v!middle,
   \c!option=\v!readonly,
   \c!location=\v!low]

\def\doinitializeautoregister#1%
  {\useJSscripts[reg]%
   \useJSpreamblenow{LinkedRegisters}%
   \setupinteraction[\c!openpageaction=JS(UpdateRegisterField{\v!register})]%
   \definereference[\v!reset\v!register][JS(ResetRegisterEntry{\v!register})]%
   \definereference[\v!first\v!register][JS(GotoFirstRegisterEntry{\v!register})]%
   \definereference[\v!previous\v!register][JS(GotoPreviousRegisterEntry{\v!register})]%
   \definereference[\v!next\v!register][JS(GotoNextRegisterEntry{\v!register})]%
   \definereference[\v!last\v!register][JS(GotoLastRegisterEntry{\v!register})]}

\def\doinitializelinkregister#1%
  {}

% todo ruwe register

\def\placeregister
  {\dodoubleempty\doplaceregister}

\def\doplaceregister[#1][#2]%
  {\iffirstargument
     \begingroup
     \edef\currentregister{#1}%
     \setupregister[\currentregister][#2]%
     \raggedright
     \startcolumns
       [\c!n=\registerparameter\c!n,
        \c!balance=\registerparameter\c!balance,
        \c!align=\registerparameter\c!align]%
     \dontcomplain
     \startpacked[\v!blank]%
     \doutilities\currentregister\jobname\currentregister\relax\par
     \stoppacked
     \stopcolumns
     \endgroup
   \fi}

\def\completeregister
  {\dodoubleempty\docompleteregister}

\def\docompleteregister[#1][#2]%
  {\iffirstargument
     \begingroup
     \edef\currentregister{#1}%
     % the expansion is needed because we don't want \v!'s in the tuo file (french)
     \expanded{\systemsuppliedchapter[\currentregister]{\noexpand\headtext{\currentregister}}}%
     \placeregister[\currentregister][#2]%
     \page[\v!yes]%
     \endgroup
   \fi}

\def\dodefineregister[#1][#2]%
  {\setupregister[#1]%
     [\c!n=2,
      \c!balance=\v!yes,  % \v!no komt niet zo vaak voor
      \c!align=\v!no,
      \c!before=\blank,      % binnen kolommen: \blank[\v!line]
      \c!after=,
      \c!symbol=,
      \c!interaction=\v!pagenumber,
      \c!alternative=\v!a,
      \c!distance=1em,
      \c!style=\v!bold,
      \c!pagestyle=\v!slanted,
      \c!indicator=\v!yes,
      \v!part\v!number=\v!yes, % v
      \v!chapter\c!number=\v!no,
      \c!criterium=\v!all,
      \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!keyexpansion=]%
   \presetheadtext[#1=\Word{#1}]%
   \addutilityreset{#1}%
   \setvalue{#1}{\doregister{#1}}%
   \setvalue{\e!coupled#1}{\dolinkedregister{#1}}%
   \setvalue{\s!set#1}{\dosetregister{#1}}%
   \setvalue{\s!reset#1}{\doresetregister{#1}}%
   \setvalue{\e!see#1}{\doseeregister{#1}}%
   \setvalue{\e!place#1}{\placeregister[#1]}%
   \setvalue{\e!complete#1}{\completeregister[#1]}%
   \setvalue{\e!setup#1\e!endsetup}[##1]{\getparameters[\??id#1][##1]}}

\def\defineregister
  {\dodoubleargument\dodefineregister}

\def\registerlengte{\utilityregisterlength}

\def\utilityregisterlength{0}

\def\dodetermineregistercharacteristics[#1][#2]%
  {\begingroup
   \setupregister[#1][#2]%
   \dosetreglevel{#1}%
   \setvalue{#1\s!from}%
     {\getvalue{#1\s!page}}%
   \setvalue{#1\s!page}##1##2##3##4%
     {\doifreglevelelse[##3]
        {\doglobal\increment\utilitylistlength
         \global\utilitydonetrue}
        {}}%
   \doglobal\newcounter\utilityregisterlength
   \setbox0\vbox
     {\doutilities{#1}\jobname{#1}\relax\relax}%
   \endgroup
   \ifregistergeplaatst
     \setsystemmode  \v!register
   \else
     \resetsystemmode\v!register
   \fi}

\def\determineregistercharacteristics
  {\dodoubleempty\dodetermineregistercharacteristics}

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

% \setupregister[index][koppeling=ja]
%
% \stelveldenin
%   [register][achtergrond=raster,kader=uit]
%
% \stelvoettekstenin
%   [{\field[index]}]
%
% \stelhoofdtekstenin
%   [{\naar   {first}[eersteindex]\quad
%     \naar{previous}[vorigeindex]\quad
%     \naar    {next}[volgendeindex]\quad
%     \naar    {last}[laatsteindex]\quad\quad
%     \naar   {index}[index]}]
%
% \starttekst
%
% oeps~~~\gekoppeldeindex{oeps} \blanko
% flop~~~\gekoppeldeindex{flop} \blanko
% test~~~\gekoppeldeindex{test} \pagina
% flop~~~\gekoppeldeindex{flop} \blanko
% test~~~\gekoppeldeindex{test} \pagina
% oeps~~~\gekoppeldeindex{oeps} \blanko
% test~~~\gekoppeldeindex{test} \pagina
% flop~~~\gekoppeldeindex{flop} \blanko
% oeps~~~\gekoppeldeindex{oeps} \pagina
%
% \volledigeindex

\protect \endinput
