summaryrefslogtreecommitdiff
path: root/tex/context/base/strc-reg.mkiv
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2010-07-04 15:32:09 +0300
committerMarius <mariausol@gmail.com>2010-07-04 15:32:09 +0300
commit85b7bc695629926641c7cb752fd478adfdf374f3 (patch)
tree80293f5aaa7b95a500a78392c39688d8ee7a32fc /tex/context/base/strc-reg.mkiv
downloadcontext-85b7bc695629926641c7cb752fd478adfdf374f3.tar.gz
stable 2010-05-24 13:10
Diffstat (limited to 'tex/context/base/strc-reg.mkiv')
-rw-r--r--tex/context/base/strc-reg.mkiv1137
1 files changed, 1137 insertions, 0 deletions
diff --git a/tex/context/base/strc-reg.mkiv b/tex/context/base/strc-reg.mkiv
new file mode 100644
index 000000000..fcc37549c
--- /dev/null
+++ b/tex/context/base/strc-reg.mkiv
@@ -0,0 +1,1137 @@
+%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 / Hans Hagen]
+%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}{1.001}
+
+\unprotect
+
+\def\c!keys {keys}
+\def\c!entries{entries}
+
+% todo: tag:: becomes rendering
+% todo: language, character, linked, location
+
+%D Helper:
+
+% \def\doflushatpar{\ifvmode\expandafter\dogotopar\else\expandafter\firstofoneargument\fi}
+
+\def\doflushatpar{\ifvmode\expandafter\flushatnextpar\else\expandafter\firstofoneargument\fi}
+
+% \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
+
+% 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}
+
+%D Parameters:
+
+\let\currentregister\empty
+
+% \def\registerparameter#1{\csname\??id\currentregister#1\endcsname}
+
+\def\detokenizedregisterparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??id#1\endcsname}} % always root
+
+\def\registerparameter #1{\csname\doregisterparameter{\??id\currentregister}{#1}\endcsname}
+\def\registerparameterhash#1{\doregisterparameterhash {\??id\currentregister}#1}
+
+\def\doregisterparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doregisterparentparameter \csname#1\s!parent\endcsname{#2}\fi}
+\def\doregisterparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doregisterparentparameterhash\csname#1\s!parent\endcsname{#2}\fi}
+
+\def\doregisterparentparameter #1#2{\ifx#1\relax\s!empty\else\doregisterparameter #1{#2}\fi}
+\def\doregisterparentparameterhash#1#2{\ifx#1\relax \else\doregisterparameterhash#1{#2}\fi}
+
+\def\dosetregisterattributes#1#2% style color
+ {\edef\fontattributehash {\registerparameterhash#1}%
+ \edef\colorattributehash{\registerparameterhash#2}%
+ \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
+ \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
+
+%D Setup:
+
+\newtoks\everysetupregister
+
+\unexpanded\def\setupregisters
+ {\dotripleempty\dosetupregisters}
+
+\def\dosetupregisters[#1][#2][#3]%
+ {\ifthirdargument
+ \def\dodosetupregister##1{\getparameters[\??id##1#2][#3]}%
+ \processcommalist[#1]\dodosetupregister
+ \else\ifsecondargument
+ \def\dodosetupregister##1{\edef\currentregister{##1}\getparameters[\??id##1][#2]\the\everysetupregister}%
+ \processcommalist[#1]\dodosetupregister
+ \else
+ \getparameters[\??id][#1]%
+ \fi\fi}
+
+\let\setupregister\setupregisters
+
+\setupregisters
+ [\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=1em,
+ \c!style=\v!bold,
+ \c!pagestyle=\v!slanted,
+ \c!indicator=\v!yes,
+ \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!xmlsetup=,
+ \c!pageprefixconnector=\endash,
+ \c!pagesegments=2:2,
+ \c!file=\jobname,
+ %\c!deeptextcommand=, % undefined by default !
+ \s!language=\currentmainlanguage]%
+
+%D Definition:
+
+\unexpanded\def\defineregister
+ {\dodoubleargument\dodefineregister}
+
+\def\dodefineregister[#1][#2]% #2?
+ {\setupregister[#1][\s!parent=\??id]%
+ \ctxlua{jobregisters.define('#1')}%
+ \presetheadtext[#1=\Word{#1}]%
+ \setuvalue{#1}{\dodoubleempty\doregister[#1]}%
+ \setuvalue{\e!see#1}{\dodoubleempty\doseeregister[#1]}%
+% \setuvalue{\e!coupled#1}{\dolinkedregister{#1}}%
+ \setvalue{\e!place#1}{\placeregister[#1]}%
+ \setvalue{\e!complete#1}{\completeregister[#1]}%
+ \setvalue{\e!setup#1\e!endsetup}[##1]{\getparameters[\??id#1][##1]}}
+
+%D Registering:
+
+\newif\ifwritetoregister \writetoregistertrue
+
+% tzt variant met n entries, parameters en userdata (altnum)
+
+\getparameters
+ [\??id]
+ [\c!label=,
+ \c!entries=,
+ \c!entries:1=,\c!entries:2=,\c!entries:3=,
+ \c!keys:1=,\c!keys:2=,\c!keys:3=,
+ \c!alternative=]
+
+\def\doregisterstructurepageregister
+ {\iftrialtypesetting
+ \expandafter\gobblethreearguments
+ \else
+ \expandafter\dodoregisterstructurepageregister
+ \fi}
+
+\def\dodoregisterstructurepageregister#1#2#3% register data userdata
+ {\begingroup
+ \edef\currentregister{#1}%
+ %getparameters[\??id][\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
+ \getparameters[\??id][#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\currentregisterxmlsetup {\registerparameter\c!xmlsetup}%
+ \ifx\currentregisterentries\empty
+ \ifx\currentregisterexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}%
+ \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
+ \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
+ \xmlstopraw
+ \globallet\currentregistercoding\s!xml
+ \else
+ \ifx\currentregisterexpansion\v!yes
+ \xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}%
+ \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
+ \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
+ \else
+ \xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}%
+ \xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}%
+ \xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}%
+ \fi
+ \globallet\currentregistercoding\s!tex
+ \fi
+ \else
+ \ifx\currentregisterexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentregisterentries{\registerparameter\c!entries}%
+ \xmlstopraw
+ \globallet\currentregistercoding\s!xml
+ \else
+ \ifx\currentregisterexpansion\v!yes
+ \xdef\currentregisterentries{\registerparameter\c!entries}%
+ \else
+ \xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}%
+ \fi
+ \globallet\currentregistercoding\s!tex
+ \fi
+ \fi
+ \ifx\currentregisterkeys\empty
+ \ifx\currentregistercoding\s!xml
+ \xmlstartraw
+ \xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}%
+ \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}%
+ \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}%
+ \xmlstopraw
+ \else
+ \xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}%
+ \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}%
+ \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}%
+ \fi
+ \fi
+ \setnextinternalreference
+ % we could consider storing register entries in a list which we
+ % could then sort
+ \xdef\currentregisternumber{\ctxlua{
+ jobregisters.store { % 'own' should not be in metadata
+ metadata = {
+ kind = "entry",
+ name = "\currentregister",
+ level = structure.sections.currentlevel(),
+ coding = "\currentregistercoding",
+ catcodes = \the\catcodetable,
+ \ifx\currentregisterownnumber\v!yes
+ own = "\registerparameter\c!alternative", % can be used instead of pagenumber
+ \fi
+ xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text
+\ifx\currentregisterxmlsetup\empty \else
+ xmlsetup = "\currentregisterxmlsetup",
+\fi
+ },
+ references = {
+ internal = \nextinternalreference,
+ section = structure.sections.currentid(), % hm, why then not also lastsection the same way
+ label = "\currentregisterlabel",
+ },
+% \ifx\currentregisterentries\empty \else
+ entries = {
+ % we need a special one for xml, this is just a single one
+ \ifx\currentregisterentries\empty
+ { \!!bs\currentregisterentriesa\!!es, \!!bs\currentregisterentriesb\!!es, \!!bs\currentregisterentriesc\!!es },
+ \else
+ \!!bs\currentregisterentries\!!es,
+ \fi
+ \ifx\currentregisterkeys\empty
+ { \!!bs\currentregisterkeysa\!!es, \!!bs\currentregisterkeysb\!!es, \!!bs\currentregisterkeysc\!!es },
+ \else
+ \!!bs\currentregisterkeys\!!es,
+ \fi
+ },
+% \fi
+ userdata = structure.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
+ }
+ } }%
+ \ctxlua{jobreferences.setinternalreference(nil,nil,\nextinternalreference)}%
+ \ifx\currentregisterownnumber\v!yes
+ \glet\currentregistersynchronize\relax
+ \else
+ \xdef\currentregistersynchronize{\ctxlatelua{jobregisters.enhance("\currentregister",\currentregisternumber)}}%
+ \fi
+ \currentregistersynchronize % here?
+ \attribute\destinationattribute\lastdestinationattribute \forcecolorhack % no \strut as it will be removed during cleanup
+ \endgroup}
+
+\def\doregister[#1][#2]%
+ {\def\currentregister{#1}%
+ \doifelse{\registerparameter\c!ownnumber}\v!yes\dodoregister\donoregister{#1}{#2}}
+
+\def\donoregister #1#2#3{\doflushatpar{\doregisterstructurepageregister{#1}{\c!keys={#2},\c!entries={#3}}{}}}
+\def\dodoregister#1#2#3#4{\doflushatpar{\doregisterstructurepageregister{#1}{\c!keys={#2},\c!alternative=#3,\c!entries={#4}}{}}}
+
+\unexpanded\def\startregister{\doquadrupleempty\dostartregister}
+\unexpanded\def\stopregister {\dodoubleargument\dostopregister}
+
+% a synonym, so that we can nest with overlap without syntax check problems
+
+\let\openregisterrange \startregister
+\let\closeregisterrange\stopregister
+
+\def\dostartregister[#1][#2][#3][#4]#5%
+ {\iffourthargument
+ % #1=register #2=tag #3=own #4=sortkey #5=entry
+ \doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}%
+ \else
+ % #1=register #2=tag #3=sortkey #5=entry
+ \doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}%
+ \fi}
+
+\def\dostopregister[#1][#2]%
+ {\normalexpanded{\ctxlatelua{jobregisters.extend("#1","#2")}}}
+
+\def\setregisterentry {\dotripleempty\dosetregisterentry}
+\def\finishregisterentry{\dotripleempty\dofinishregisterentry}
+
+% not yet document, not sure if this will stay:
+
+\def\dosetregisterentry [#1][#2][#3]{\doflushatpar{\doregisterstructurepageregister{#1}{#2}{#3}}}
+\def\dofinishregisterentry[#1][#2][#3]{\dofinishregisterstructurepageregister{#1}{#2}{#3}}
+
+\def\dofinishregisterstructurepageregister#1#2#3% register data userdata
+ {\begingroup
+ \edef\currentregister{#1}%
+ \getparameters[\??id][\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
+ \edef\currentregisterlabel {\registerparameter\c!label}%
+ \edef\currentregisterexpansion{\registerparameter\c!expansion}%
+ \edef\currentregisterownnumber{\registerparameter\c!ownnumber}%
+ \xdef\currentregisterkeys {\registerparameter\c!keys}%
+ \ifx\currentregisterexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentregisterentries{\registerparameter\c!entries}%
+ \xmlstopraw
+ \globallet\currentregistercoding\s!xml
+ \else
+ \ifx\currentregisterexpansion\v!yes
+ \xdef\currentregisterentries{\registerparameter\c!entries}%
+ \else
+ \xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}%
+ \fi
+ \globallet\currentregistercoding\s!tex
+ \fi
+ \ifx\currentregisterentries\empty
+ \normalexpanded{\ctxlua{jobregisters.extend("\currentregister","\currentregisterlabel", {
+ metadata = {
+ \ifx\currentregisterownnumber\v!yes
+ own = "\registerparameter\c!alternative", % can be used instead of pagenumber
+ \fi
+ },
+ userdata = structure.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
+ })%
+ }}%
+ \else
+ \normalexpanded{\ctxlua{jobregisters.extend("\currentregister","\currentregisterlabel", {
+ metadata = {
+ catcodes = \the\catcodetable,
+ coding = "\currentregistercoding",
+ \ifx\currentregisterownnumber\v!yes
+ own = "\registerparameter\c!alternative", % can be used instead of pagenumber
+ \fi
+ },
+ entries = {
+ % we need a special one for xml, this is just a single one
+ \!!bs\currentregisterentries\!!es, \!!bs\currentregisterkeys\!!es
+ },
+ userdata = structure.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
+ })
+ }}%
+ \fi
+ \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
+
+\def\setstructurepageregister{\dotripleempty\dosetstructurepageregister}
+
+\def\dosetstructurepageregister[#1][#2][#3]% [register][settings][userdata]
+ {\doflushatpar{\doregisterstructurepageregister{#1}{#2}{#3}}}
+
+\unexpanded\def\startstructurepageregister{\doquadrupleempty\dostartstructurepageregister}
+\unexpanded\def\stopstructurepageregister {\dodoubleargument\dostopstructurepageregister}
+
+\let\openstructurepageregisterrange \startstructurepageregister
+\let\closestructurepageregisterrange\stopstructurepageregister
+
+\def\dostartstructurepageregister[#1][#2][#3][#4]% [register][tag][settings][userdata]
+ {\doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,#3}{#4}}}
+
+\def\dostopstructurepageregister[#1][#2]%
+ {\normalexpanded{\ctxlatelua{jobregisters.extend("#1","#2")}}}
+
+% So far.
+
+\def\doseeregister[#1][#2]#3#4%
+ {\doflushatpar{\doprocessseeregister{#1}{#2}{#3}{#4}}}
+
+\def\doprocessseeregister#1#2#3#4% register key entry seeword
+ {\begingroup
+ \edef\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
+ \globallet\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
+ \globallet\currentregistercoding\s!tex
+ \fi
+ \setnextinternalreference
+ % we could consider storing register entries in list
+ \edef\temp{\ctxlua{ jobregisters.store {
+ metadata = {
+ kind = "see",
+ name = "\currentregister",
+ level = structure.sections.currentlevel(),
+ catcodes = \the\catcodetable,
+ },
+ references = {
+ internal = \nextinternalreference,
+ section = structure.sections.currentid(),
+ },
+ entries = {
+ % we need a special one for xml, this is just a single one
+ "\currentregisterentries", "#2"
+ },
+ seeword = {
+ text = "\currentregisterseeword"
+ },
+ }
+ }}%
+ \endgroup}
+
+%D Rendering:
+
+\let\utilityregisterlength\!!zerocount
+
+\def\determineregistercharacteristics
+ {\dodoubleempty\dodetermineregistercharacteristics}
+
+\def\dodetermineregistercharacteristics[#1][#2]%
+ {\begingroup
+ \edef\currentregister{#1}%
+ \setupregister[\currentregister][#2]%
+ \normalexpanded{\endgroup\noexpand\xdef\noexpand\utilityregisterlength{\ctxlua{jobregisters.analyse('\currentregister',{
+ language = "\registerparameter\s!language",
+ compress = "\registerparameter\c!compress",
+ criterium = "\registerparameter\c!criterium",
+ })}}}% brrr
+ \ifcase\utilityregisterlength\relax
+ \resetsystemmode\v!register
+ \else
+ \setsystemmode \v!register
+ \fi}
+
+\newtoks\everyplaceregister
+
+\appendtoks
+ \dontcomplain
+\to \everyplaceregister
+
+\unexpanded\def\placeregister
+ {\dodoubleempty\doplaceregister}
+
+\def\doplaceregister[#1][#2]%
+ {\iffirstargument
+ \begingroup
+% \forgetall
+ \edef\currentregister{#1}%
+ \setupregister[\currentregister][#2]%
+ \the\everyplaceregister
+ \startcolumns
+ [\c!n=\registerparameter\c!n,
+ \c!balance=\registerparameter\c!balance,
+ \c!align=\registerparameter\c!align,
+ \c!tolerance=\registerparameter\c!tolerance]%
+ \startpacked[\v!blank]%
+ \ctxlua{jobregisters.process('\currentregister',{
+ language = "\registerparameter\s!language",
+ compress = "\registerparameter\c!compress",
+ criterium = "\registerparameter\c!criterium",
+ },
+ {
+% prefix = "\registerparameter\c!pageprefix",
+ separatorset = "\registerparameter\c!pageprefixseparatorset",
+ conversionset = "\registerparameter\c!pageprefixconversionset",
+ starter = \!!bs\registerparameter\c!pageprefixstarter\!!es,
+ stopper = \!!bs\registerparameter\c!pageprefixstopper\!!es,
+ set = "\registerparameter\c!pageprefixset",
+ segments = "\registerparameter\c!pageprefixsegments",
+ connector = \!!bs\registerparameter\c!pageprefixconnector\!!es,
+ },
+ {
+ prefix = "\registerparameter\c!pageprefix",
+ separatorset = "\registerparameter\c!pageseparatorset",
+ conversionset = "\registerparameter\c!pageconversionset",
+ starter = \!!bs\registerparameter\c!pagestarter\!!es,
+ stopper = \!!bs\registerparameter\c!pagestopper\!!es,
+ segments = "\registerparameter\c!pagesegments",
+ }
+ )}%
+ \stoppacked
+ \stopcolumns
+ \endgroup
+ \fi}
+
+\def\dolimitedregisterentry#1{\limitatetext{#1}\currentregistermaxwidth\unknown}%
+
+\appendtoks
+ \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}%
+ \ifx\currentregistermaxwidth\empty
+ \let\limitedregisterentry\firstofoneargument
+ \else
+ \let\limitedregisterentry\dolimitedregisterentry
+ \fi
+\to \everyplaceregister
+
+\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)
+ \normalexpanded{\systemsuppliedchapter[\currentregister]{\noexpand\headtext{\currentregister}}}%
+ \placeregister[\currentregister][#2]%
+ \page[\v!yes]%
+ \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 Character rendering (sections):
+
+\def\defaultregistercharacter#1%
+ {\doifsomething{#1}
+ {\doifnot{#1}\s!unknown
+ {\doifelse{\registerparameter\c!indicator}\v!yes
+ {\expandcheckedcsname{\??id:\c!indicator:}{\registerparameter\c!alternative}{a}{#1}}
+ {\noregistercharacter{#1}}}}}
+
+\def\noregistercharacter#1%
+ {\registerparameter\c!before
+ \goodbreak}
+
+% a = <before> <goodbreak> <character> <par> <after> <nobreak>
+
+\setvalue{\??id:\c!indicator:a}#1%
+ {\registerparameter\c!before
+ % bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight
+ \begingroup\dosetregisterattributes\c!style\c!color
+ \registerparameter\c!command{\strut#1}%
+ \endgroup
+ \registerparameter\c!after
+ \par\nobreak}
+
+
+% b = <goodbreak> <before> <character> <after> <nobreak>
+
+\setvalue{\??id:\c!indicator:b}#1%
+ {\registerparameter\c!before
+ \begingroup\dosetregisterattributes\c!style\c!color
+ \registerparameter\c!command{\strut#1}%
+ \endgroup
+ \registerparameter\c!after
+ \nobreak}
+
+\setvalue{\??id:\c!indicator:A}#1{\getvalue{\??id:\c!indicator:a}{\WORD{#1}}}
+\setvalue{\??id:\c!indicator:B}#1{\getvalue{\??id:\c!indicator:b}{\WORD{#1}}}
+
+%D The following macros are the interface to the rendering. These are
+%D generated by \LUA. This might change.
+
+%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.
+
+\unexpanded\def\startregisteroutput
+ {\endgraf
+ \begingroup
+ \forgetparindent
+ \forgetparskip}
+
+\unexpanded\def\stopregisteroutput
+ {\endgraf
+ \endgroup}
+
+\unexpanded\def\startregisterentries#1% depth
+ {\endgraf
+ \begingroup
+ \dosetregisterattributes\c!textstyle\c!textcolor
+ \advance\leftskip\numexpr#1-1\relax\dimexpr\registerparameter\c!distance\relax
+ \hangindent\registerparameter\c!distance\hangafter\plusone}
+
+\unexpanded\def\stopregisterentries
+ {\endgraf
+ \endgroup}
+
+\unexpanded\def\startregistersection#1% title
+ {\registercharacter{#1}\endgraf}
+
+\unexpanded\def\stopregistersection
+ {\endgraf}
+
+\newconditional\registerpagedone
+
+\unexpanded\def\startregisterpages
+ {\begingroup
+ \setfalse\registerpagedone
+ \dosetregisterattributes\c!pagestyle\c!pagecolor}
+
+\unexpanded\def\stopregisterpages
+ {\endgroup}
+
+\unexpanded\def\startregisterseewords
+ {\begingroup
+ \setfalse\registerpagedone
+ \dosetregisterattributes\c!pagestyle\c!pagecolor}
+
+\unexpanded\def\stopregisterseewords
+ {\endgroup}
+
+\def\registerpageseparator% todo: , configurable
+ {\ifconditional\registerpagedone
+ \registerpageseparatorsymbol
+ \else
+ \hskip\registerparameter\c!distance\relax
+ \settrue\registerpagedone
+ \fi}
+
+\def\registeronepagerangeseparator{|\endash|}
+
+\def\withregisterpagecommand#1#2#3%
+ {\def\currentregisterpageindex{#1}%
+ \iflocation
+ \goto{\registerparameter\c!pagecommand{#3}}[internal(#1)]%
+ \else
+ \registerparameter\c!pagecommand{#3}%
+ \fi}
+
+\def\registeronepage#1#2#3% content
+ {\registerpageseparator
+ \withregisterpagecommand{#1}{#2}{#3}}
+
+\def\registerpagerange#1#2#3#4#5#6% content, content todo: -- configurable
+ {\registerpageseparator
+ \withregisterpagecommand{#1}{#2}{#3}%
+ \registeronepagerangeseparator
+ \withregisterpagecommand{#4}{#5}{#6}}
+
+\def\registeroneword#1#2#3% content
+ {\registerpageseparator
+ \registerseeword{#3}}
+
+\def\defaultregisterentry #1{\registerparameter\c!textcommand{\limitedregisterentry{\registerparameter\c!deeptextcommand{#1}}}}
+\def\defaultregisterseeword#1{\labeltexts\v!see{#1}}
+
+\let\registerseeword \defaultregisterseeword
+\let\registerentry \defaultregisterentry
+\let\registercharacter\defaultregistercharacter
+
+%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
+
+\def\registerpageuserdata #1#2{\ctxlua{jobregisters.userdata(#1,"#2")}}
+\def\currentregisterpageuserdata {\registerpageuserdata\currentregisterpageindex} % {#1}
+
+% not yet ok : new internal handler names
+
+\def\registerpagebuttonsymbol{\vrule\!!width1em\!!height1ex\!!depth\zeropoint\relax}
+
+\setvalue{\??id:\c!symbol:\c!n}%
+ {\def\registerpageseparatorsymbol{, }}
+
+\setvalue{\??id:\c!symbol:\c!a}%
+ {\def\registerpageseparatorsymbol{, }} % now done via conversion
+
+\setvalue{\??id:\c!symbol:\v!none}%
+ {\let\registerpageseparatorsymbol\empty
+ \let\registeronepage \gobblethreearguments
+ \let\registerpagerange \gobblesixarguments}
+
+\setvalue{\??id:\c!symbol:1}%
+ {\let\registerpageseparatorsymbol\space
+ \def\registeronepage {\symbol[1]\gobblethreearguments}%
+ \def\registerpagerange {\symbol[1]\gobblesixarguments}}
+
+\setvalue{\??id:\c!symbol:2}%
+ {\let\registerpageseparatorsymbol\space
+ \def\registeronepage {\registerpagebuttonsymbol\gobblethreearguments}%
+ \def\registerpagerange {\registerpagebuttonsymbol\gobblesixarguments}}
+
+\def\setregisterpagerendering
+ {\edef\currentregisterpagesymbol{\registerparameter\c!symbol}%
+ \ifx\currentregisterpagesymbol\empty
+ \csname\??id:\c!symbol:\c!n\endcsname
+ \else\ifcsname\??id:\c!symbol:\currentregisterpagesymbol\endcsname
+ \csname\??id:\c!symbol:\currentregisterpagesymbol\endcsname
+ \else
+ \let\registerpageseparatorsymbol\space
+ \def\registeronepage {\registerparameter\c!symbol\gobblethreearguments}%
+ \def\registerpagerange {\registerparameter\c!symbol\gobblesixarguments}%
+ \fi\fi}
+
+\appendtoks
+ \setregisterpagerendering
+\to \everyplaceregister
+
+% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
+% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
+% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
+
+%D The following code will be reimplemented (not that hard) when it's needed
+%D again and/or when I'm bored.
+
+% \def\getalllistreferences#1#2%
+% {\gdefconvertexpanded\currentregisterentry{\getvalue{\??id#1\c!expansion}}{#2}%
+% \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?
+% {\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}%
+% % no \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\dodocommand[##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\dodocommand\expandafter[\midlistreference]%
+% \fi
+% \else
+% \expandafter\dodocommand\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\docommand##1##2%
+% {{\setbox0\hbox{\showlocation{\hbox to 1em{\hss\symbol[##2]\hss}}}%
+% \ifx##1\empty
+% % \hskip\wd0 % (optioneel maken)
+% \else
+% \expandafter\dodocommand\expandafter[##1]%
+% \fi}}%
+% \hskip\getvalue{\??id#1\c!distance}%
+% \docommand\firstlistreference\v!previous
+% \docommand\midlistreference\v!somewhere
+% \docommand\lastlistreference\v!next}%
+% % tot hier
+% \else
+% % no \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}}}
+
+% \def\dosetregister#1%
+% {\dosetpageregister{#1}}
+
+% \newcounter\internallistreference
+
+% \def\doloadregisterlinks#1%
+% {\setregisterpage{#1}%
+% \global\let\currentregisterentry\empty
+% \global\firstregisterpagetrue
+% \setvalue{#1\s!entrya}##1%
+% {\global\firstregisterpagetrue
+% \gdefconvertedargument\currentregisterentry{##1}% global 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
+% \def\currentregister{#1}%
+% \setupregister[#1][#2]%
+% \mkloadregister\currentregister\dobeforeplaceregister\doafterplaceregister
+% \endgroup
+% \ifautoregisterhack
+% \doinitializeautoregister{#1}%
+% \else
+% \doinitializelinkregister{#1}%
+% \fi
+% \fi
+% \fi}
+
+% \def\coupleregister
+% {\dodoubleempty\docoupleregister}
+
+% \def\dodocommandprolinrefAA[#1-#2]%
+% {\def\lastlistreference{#1-#2}}
+
+% \def\dodocommandprolinrefA[#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\dodocommandprolinrefA\dodocommandprolinrefAA
+% \else
+% \let\selflistreference\lastlistreference
+% \fi\fi}
+
+% \def\docommandprolinrefA#1%
+% {\dodocommandprolinrefA[#1]}
+
+% \def\dodocommandprolinrefB[#1-#2]%
+% {\gotonextinternal{\s!ind}{#1}{#2}{\box0}}
+
+% \def\docommandprolinrefB#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\dodocommandprolinrefB\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
+% \normalexpanded{\noexpand\rawprocesscommalist[\alllistreferences]}\docommandprolinrefA
+% \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
+% \docommandprolinrefB{#1}\prevlistreference\v!previous
+% \docommandprolinrefB{#1}\nextlistreference\v!next
+% \or
+% % midden
+% \docommandprolinrefB{#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
+% \docommandprolinrefB{#1}\nextlistreference\v!next
+% \or
+% % rechts
+% \docommandprolinrefB{#1}\prevlistreference\v!previous
+% \docommandprolinrefB{#1}\nextlistreference\v!next
+% \fi}}
+
+% \def\doprocesslinkedregister[#1][#2]#3% page auto link
+% {\bgroup
+% \chardef\registerpagestatus\plusone
+% \def\currentregister{#1}%
+% \iflocation % \next is not needed
+% \ifautoregisterhack
+% \def\next{\doprocessautoregister[#1][#2]}%
+% \else
+% \def\next{\doprocesslinkregister[#1][#2]}%
+% \fi
+% \else
+% \def\next{\doprocesspageregister{}{#2}{}}%
+% \fi
+% \next{#3}%
+% \egroup}
+
+% \def\dodolinkedregister[#1][#2]#3% page auto link
+% {\doflushatpar{\doprocesslinkedregister[#1][#2]{#3}}}
+
+% \def\dolinkedregister#1%
+% {\dodoubleempty\dodolinkedregister[#1]}
+
+% \def\dosetautoregister#1%
+% {\makecounter{autolink:#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
+
+% \appendtoks
+% % for now
+% \setupfield
+% [\v!register]
+% [\c!width=10em,
+% \c!height=3ex,
+% \c!align=\v!middle,
+% \c!option=\v!readonly,
+% \c!location=\v!low]
+% \to \everydump
+
+% \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
+
+%D Default index:
+
+\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