strc-reg.mkxl /size: 56 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=strc-reg,
3%D        version=2008.10.20,
4%D          title=\CONTEXT\ Structure Macros,
5%D       subtitle=Registers,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Structure Macros / Registers}
15
16\registerctxluafile{strc-reg}{autosuffix}
17
18\unprotect
19
20\startcontextdefinitioncode
21
22% todo: tag:: becomes rendering
23% todo: language, character, linked, location
24% todo: fonts etc at sublevels (already defined)
25
26% \starttext
27% \placeregister[index]
28% \chapter{a} \index{93} \index{456} \index{***} \index{*} \index{@}
29% test \index{aa} test \startregister[index][x]{bb} test \page test \page test \page test \stopregister[index][x]
30% test \index{aa} test \setregisterentry[index][label=x,entries=bb] test \page test \page test \page test \finishregisterentry[index][label=x]
31% test \index{aa} test \setregisterentry[index][label=y] test \page test \page test \page test \finishregisterentry[index][label=y,entries=yy]
32% \stoptext
33
34%  \index                {entry}
35%  \index[key]           {entry}
36%  \index[pageclass::]   {entry}
37%  \index[pageclass::key]{entry}
38%  \index                {textclass::entry}
39%  \index[key]           {textclass::entry}
40%  \index[pageclass::]   {textclass::entry}
41%  \index[pageclass::key]{textclass::entry}
42
43% nice example:
44%
45% \setupregister[index]
46%     [n=1,
47%      pageleft=\hfilll,
48%      pageright=\frozen\parfillleftskip 0pt plus 1fill\frozen\parfillrightskip 0pt\par]
49%
50% \starttext
51%
52% {\showmakeup \placeindex \page}
53%
54% % \dorecurse{10}{\dontleavehmode \index{AAA}\page}
55% \dorecurse{100}{\dontleavehmode\index{AAA}\page}
56
57% tzt variant with n entries, parameters and userdata (altnum)
58
59\installcorenamespace{register}
60
61\installcommandhandler\??register {register} \??register
62
63\aliased\let\strc_registers_setup_saved\setupregister
64
65% maybe we should drop the plural form
66
67\let\strc_registers_setup_step\relax
68
69\permanent\tolerant\protected\overloaded\def\setupregister[#S#1]#*[#S#2]#*[#S#3]%
70  {\ifarguments\or
71     \strc_registers_setup_saved[#1]%
72   \or
73     \strc_registers_setup_saved[#1][#2]%
74   \or
75     \def\strc_registers_setup_step##1{\strc_registers_setup_saved[#1:##1][#3]}%
76     \processcommalist[#2]\strc_registers_setup_step
77   \fi}
78
79\permanent\tolerant\protected\def\setupregisters[#S#1]%
80  {\strc_registers_setup_saved[#1]\relax}
81
82\setupregister
83  [\c!n=2,
84   \c!balance=\v!yes,  % \v!no komt niet zo vaak voor
85   \c!align=\v!flushleft,
86   \c!tolerance=\v!stretch,
87   \c!before=\blank,
88  %\c!after=,
89  %\c!symbol=,
90   \c!compress=\v!no,
91   \c!interaction=\v!pagenumber,
92   \c!alternative=\v!a,
93   \c!distance=\emwidth,
94   \c!style=\v!bold,
95   \c!pagestyle=\v!slanted,
96   \c!indicator=\v!yes,
97   \c!criterium=\v!all,
98   \c!check=\v!yes, % check for weird see usage
99  %\c!command=,
100   \c!referencing=\v!on,
101   \c!location=\v!middle,
102  %\c!maxwidth=,
103   \c!number=\v!no,
104   \c!unknownreference=\v!empty,
105   \c!prefix=\v!both,
106  %\c!expansion=,
107  %\c!xmlsetup=,
108   \c!pagenumber=\v!yes,
109   \c!pageprefixconnector=\endash,
110   \c!pagesegments=2:2,
111   \c!file=\jobname,
112  %\c!deeptextcommand=, % undefined by default !
113   \c!method=, % no default as we have them in the module, maybe some day in lang-*
114   \c!numberorder=\v!numbers, % \v!characters
115   \s!language=\currentmainlanguage]%
116
117% yes or no shared ?
118
119\setupregister
120  [\c!label=,
121   \c!entries=,
122   \c!alternative=]
123
124\definemixedcolumns
125  [\v!register]
126  [\c!define=\v!no,
127   \c!n=\registerparameter\c!n,
128   \c!balance=\registerparameter\c!balance,
129   \c!align=\registerparameter\c!align,
130   \c!tolerance=\registerparameter\c!tolerance]
131
132%D \starttyping
133%D \setupregister[index][1][textcolor=darkred]
134%D \setupregister[index][2][textcolor=darkgreen,textstyle=bold]
135%D
136%D \placeregister[index][n=1] \blank[3*big]
137%D
138%D test \index{test+one} test \index{test+two} more \index{more}
139%D \stoptyping
140
141\mutable\lettonothing\currentregistercharacter
142\mutable\lettonothing\currentregistercoding
143\mutable\lettonothing\currentregisterentries
144\mutable\lettonothing\currentregisterentriesa
145\mutable\lettonothing\currentregisterentriesb
146\mutable\lettonothing\currentregisterentriesc
147\mutable\lettonothing\currentregisterexpansion
148\mutable\lettonothing\currentregisterkeys
149\mutable\lettonothing\currentregisterkeysa
150\mutable\lettonothing\currentregisterkeysb
151\mutable\lettonothing\currentregisterkeysc
152\mutable\lettonothing\currentregisterlabel
153\mutable\lettonothing\currentregistermaxwidth
154\mutable\lettonothing\currentregistername
155\mutable\lettonothing\currentregisternumber
156\mutable\lettonothing\currentregisterownnumber
157\mutable\lettonothing\currentregisterpageindex
158\mutable\lettonothing\currentregisterpageprefix
159\mutable\lettonothing\currentregisterpagesymbol
160\mutable\lettonothing\currentregisterprocessors
161\mutable\lettonothing\currentregisterprocessorsa
162\mutable\lettonothing\currentregisterprocessorsb
163\mutable\lettonothing\currentregisterprocessorsc
164\mutable\lettonothing\currentregistersectionindex
165\mutable\lettonothing\currentregisterseeindex
166\mutable\lettonothing\currentregisterseeword
167\mutable\lettonothing\currentregistersynchronize
168\mutable\lettonothing\currentregisterxmlsetup
169
170\newconditional\c_strc_registers_defining
171\setnewconstant\c_strc_registers_maxlevel \plusfive
172\newconditional\c_strc_registers_vertical \c_strc_registers_vertical\conditionaltrue
173
174\ifdefined\Word \else \protected\def\Word#1{#1} \fi
175
176\appendtoks
177    \ifconditional\c_strc_registers_defining \else % todo: dosingle ...
178      \c_strc_registers_defining\conditionaltrue
179      \definemixedcolumns[\currentregister][\v!register]% first as otherwise it overloads start/stop
180      \clf_defineregister{\currentregister}{\registerparameter\c!referencemethod}%
181      \normalexpanded{\presetheadtext[\currentregister=\Word{\currentregister}]}%
182      \frozen\instance\protected\edefcsname\currentregister\endcsname{\strc_registers_insert_entry[\currentregister]}%
183      \frozen\instance\protected\edefcsname\e!see\currentregister\endcsname{\strc_registers_insert_see[\currentregister]}%
184      %frozen\instance\protected\edefcsname\e!coupled\currentregister\endcsname{\dolinkedregister{\currentregister}}%
185      % historic ballast
186      \frozen\instance\protected\edefcsname\e!place\currentregister\endcsname{\placeregister[\currentregister]}%
187      \frozen\instance\protected\edefcsname\e!complete\currentregister\endcsname{\completeregister[\currentregister]}%
188      \frozen\instance\protected\edefcsname\e!setup\currentregister\e!endsetup\endcsname{\setupregister[\currentregister]}%
189      \dorecurse\c_strc_registers_maxlevel{% weird, expanded should not be needed
190        \normalexpanded{\defineregister[\currentregister:\recurselevel][\currentregister]}%
191       %\defineregister[\currentregister:\recurselevel][\currentregister]%
192        \resetregisterparameter{\c!entries:\recurselevel}% needed as we use detokenize (ok, we can
193        \resetregisterparameter{\c!keys   :\recurselevel}% avoid it, but it's faster too)
194      }%
195      %
196      \c_strc_registers_defining\conditionalfalse
197    \fi
198\to \everydefineregister
199
200\appendtoks
201    \clf_setregistermethod{\currentregister}{\registerparameter\c!referencemethod}%
202\to \everysetupregister
203
204%D Registering:
205
206\glettonothing\currentregistername
207\glet         \currentregisternumber\!!zerocount
208
209\def\strc_registers_register_page_entry
210  {\iftrialtypesetting
211     \expandafter\gobblethreearguments
212   \orelse\ifconditional\prerollrun
213     \expandafter\gobblethreearguments
214   \else
215     \expandafter\strc_registers_register_page_entry_indeed
216   \fi}
217
218\def\strc_registers_register_page_expand_xml_entries
219  {\xmlstartraw
220     \xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}%
221     \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
222     \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
223   \xmlstopraw
224   \glet\currentregistercoding\s!xml}
225
226\def\strc_registers_register_page_expand_yes_entries
227  {\xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}%
228   \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
229   \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
230   \glet\currentregistercoding\s!tex}
231
232\def\strc_registers_register_page_expand_nop_entries
233  {\xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}%
234   \xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}%
235   \xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}%
236   \glet\currentregistercoding\s!tex}
237
238\def\strc_registers_register_page_expand_xml
239  {\xmlstartraw
240     \xdef\currentregisterentries{\registerparameter\c!entries}%
241   \xmlstopraw
242   \glet\currentregistercoding\s!xml}
243
244\def\strc_registers_register_page_expand_yes
245  {\xdef\currentregisterentries{\registerparameter\c!entries}%
246   \glet\currentregistercoding\s!tex}
247
248\def\strc_registers_register_page_expand_nop
249  {\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}%
250   \glet\currentregistercoding\s!tex}
251
252\def\strc_registers_register_page_expand_xml_keys
253  {\xmlstartraw
254     \xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}%
255     \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}%
256     \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}%
257   \xmlstopraw}
258
259\def\strc_registers_register_page_expand_yes_keys
260  {\xdef\currentregisterkeysa{\registerparameter{\c!keys:1}}%
261   \xdef\currentregisterkeysb{\registerparameter{\c!keys:2}}%
262   \xdef\currentregisterkeysc{\registerparameter{\c!keys:3}}}
263
264\def\strc_registers_register_page_expand_processors
265  {\xdef\currentregisterprocessorsa{\registerparameter{\c!processors:1}}%
266   \xdef\currentregisterprocessorsb{\registerparameter{\c!processors:2}}%
267   \xdef\currentregisterprocessorsc{\registerparameter{\c!processors:3}}}
268
269\def\strc_registers_register_prepare_entry#1#2%
270  {\cdef\currentregister{#1}%
271   %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
272   \setupcurrentregister[#2]%
273   \edef\currentregisterlabel     {\registerparameter\c!label}%
274   \edef\currentregisterexpansion {\registerparameter\c!expansion}%
275   \edef\currentregisterownnumber {\registerparameter\c!ownnumber}%
276   \xdef\currentregisterkeys      {\registerparameter\c!keys}%
277   \xdef\currentregisterentries   {\registerparameter\c!entries}%
278   \xdef\currentregisterprocessors{\registerparameter\c!processors}%
279   \xdef\currentregisterxmlsetup  {\registerparameter\c!xmlsetup}%
280   \ifempty\currentregisterentries
281     \ifx\currentregisterexpansion\s!xml
282       \strc_registers_register_page_expand_xml_entries
283     \orelse\ifx\currentregisterexpansion\v!yes
284       \strc_registers_register_page_expand_yes_entries
285     \else
286       \strc_registers_register_page_expand_nop_entries
287     \fi
288   \else
289     \ifx\currentregisterexpansion\s!xml
290       \strc_registers_register_page_expand_xml
291     \orelse\ifx\currentregisterexpansion\v!yes
292       \strc_registers_register_page_expand_yes
293     \else
294       \strc_registers_register_page_expand_nop
295     \fi
296   \fi
297   \ifempty\currentregisterkeys
298     \ifx\currentregistercoding\s!xml
299       \strc_registers_register_page_expand_xml_keys
300     \else
301       \strc_registers_register_page_expand_yes_keys
302     \fi
303   \fi
304   \strc_registers_register_page_expand_processors}
305
306\def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata
307  {\begingroup
308   \strc_registers_register_prepare_entry{#1}{#2}%
309   \setnextinternalreference
310   % we could consider storing register entries in a list which we
311   % could then sort
312   \glet\currentregistername\currentregister
313   \xdef\currentregisternumber{\clf_storeregister % 'own' should not be in metadata
314        metadata {%
315            name     {\currentregister}%
316            coding   {\currentregistercoding}%
317        \ifx\currentregisterownnumber\v!yes
318            own      {\registerparameter\c!alternative}% can be used instead of pagenumber
319        \fi
320        \ifx\currentreferencecoding\s!xml
321            xmlroot  {\xmldocument} % only useful when text
322        \fi
323        \ifempty\currentregisterxmlsetup \else
324            xmlsetup {\currentregisterxmlsetup}%
325        \fi
326        }%
327        references {%
328        \ifempty\currentregisterlabel \else
329            label    {\currentregisterlabel}%
330        \fi
331          % view     {\interactionparameter\c!focus}%
332        }%
333        entries {%
334            % we need a special one for xml, this is just a single one
335            \ifempty\currentregisterentries
336                entries {
337                    {\currentregisterentriesa}%
338                    {\currentregisterentriesb}%
339                    {\currentregisterentriesc}%
340                }
341            \else
342                entry {\currentregisterentries}%
343            \fi
344            \ifempty\currentregisterkeys
345                keys {
346                    {\currentregisterkeysa}%
347                    {\currentregisterkeysb}%
348                    {\currentregisterkeysc}%
349                }
350            \else
351                key {\currentregisterkeys}%
352            \fi
353            \ifempty\currentregisterprocessors
354                processors {
355                    {\currentregisterprocessorsa}%
356                    {\currentregisterprocessorsb}%
357                    {\currentregisterprocessorsc}%
358                }
359            \else
360                processor {\currentregisterprocessors}%
361            \fi
362        }%
363        userdata {\detokenize\expandafter{\normalexpanded{#3}}}
364   }%
365   \clf_setinternalreference
366      internal \locationcount
367      view     {\interactionparameter\c!focus}%
368   \relax % this will change
369   \ifx\currentregisterownnumber\v!yes
370     \glet\currentregistersynchronize\relax
371   \else
372     \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
373   \fi
374   \currentregistersynchronize % here?
375   % needs thinking ... bla\index{bla}. will break before the . but adding a
376   % penalty is also no solution
377   \dostarttagged\t!registerlocation\currentregister
378   \c_attr_destination\lastdestinationattribute
379   \signalcharacter % no \strut as it will be removed during cleanup
380   \dotagregisterlocation
381   \dostoptagged
382   \endgroup}
383
384\permanent\protected\def\dosetfastregisterentry#1#2#3#4#5% register entry key processor processor
385  {\begingroup
386   \cdef\currentregister{#1}%
387   \setnextinternalreference
388   \glet\currentregistername\currentregister
389   \xdef\currentregisternumber{\clf_storeregister
390     {%
391        metadata {%
392          name {\currentregister}%
393        }
394        entries {%
395          entry {#2}%
396          key   {#3}%
397        }%
398        processors {%
399          entry {#4}%
400          page  {#5}%
401        }%
402     }%
403   }%
404   % overlap with the above
405 % \clf_setinternalreference
406 %    internal \locationcount
407 %    view     {\interactionparameter\c!focus}%
408   \relax % this will change
409   \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
410   \currentregistersynchronize % here?
411   \dostarttagged\t!registerlocation\currentregister
412   \c_attr_destination\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
413   \dotagregisterlocation
414   \dostoptagged
415   \endgroup}
416
417\aliased\let\dotagregisterlocation\relax % experiment
418
419\tolerant\protected\def\strc_registers_insert_entry[#1]#*[#S#2]%
420  {\cdef\currentregister{#1}%
421   \ifcstok{\registerparameter\c!ownnumber}\v!yes
422     \expandafter\strc_registers_insert_entry_yes
423   \else
424     \expandafter\strc_registers_insert_entry_nop
425   \fi{#2}}
426
427% \def\strc_registers_insert_entry_nop#1#2%
428%   {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}}
429%
430% \def\strc_registers_insert_entry_yes#1#2#3%
431%   {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}}
432%
433% less tokens passed (nicer for tracing) .. could become installable
434
435\def\strc_registers_insert_entry_nop
436  {\ifvmode
437     \expandafter\strc_registers_insert_entry_nop_par
438   \else
439     \expandafter\strc_registers_insert_entry_nop_txt
440   \fi}
441
442\def\strc_registers_insert_entry_yes
443  {\ifvmode
444     \expandafter\strc_registers_insert_entry_yes_par
445   \else
446     \expandafter\strc_registers_insert_entry_yes_txt
447   \fi}
448
449\def\strc_registers_insert_entry_nop_par#1#2%
450  {\ifprerolling\else\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}\fi}
451
452\def\strc_registers_insert_entry_yes_par#1#2#3%
453  {\ifprerolling\else\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}\fi}
454
455\def\strc_registers_insert_entry_nop_txt#1#2%
456  {\ifprerolling\else\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}\fi}
457
458\def\strc_registers_insert_entry_yes_txt#1#2#3%
459  {\ifprerolling\else\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}\fi}
460
461%D This is one of the few commands where a stop has arguments.
462
463\permanent\tolerant\protected\def\startregister[#1]#*[#2]#*[#3]#*[#4]#*#:#5%
464  {\ifparameter#4\or
465     % #1=register #2=tag #3=own #4=sortkey #5=entry
466     \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}%
467   \else
468     % #1=register #2=tag #3=sortkey #5=entry
469     \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}%
470   \fi}
471
472\permanent\tolerant\protected\def\stopregister[#1]#*[#2]%
473% {\normalexpanded{\ctxlatecommand{extendregister("#1","#2")}}}
474  {\clf_extendregisterlate{#1}{#2}}
475
476% a synonym, so that we can nest with overlap without syntax check problems
477
478\aliased\let\openregisterrange \startregister
479\aliased\let\closeregisterrange\stopregister
480
481% not yet document, not sure if this will stay:
482
483\permanent\tolerant\protected\def\setregisterentry[#1]#*[#2]#*[#3]%
484  {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}}
485
486\permanent\tolerant\protected\def\finishregisterentry[#1]#*[#2]#*[#3]%
487  {\strc_registers_finish_entry_indeed{#1}{#2}{#3}}
488
489\protected\def\strc_registers_finish_entry_indeed#1#2#3% register data userdata
490  {\begingroup
491   % I hate this kind of mess ... but it's a user request.
492   \strc_registers_register_prepare_entry{#1}{#2}%
493   \glet\currentregistername\currentregister
494   \clf_extendregister { % 'own' should not be in metadata
495        metadata {%
496            name     {\currentregister}%
497            coding   {\currentregistercoding}%
498        \ifx\currentregisterownnumber\v!yes
499            own      {\registerparameter\c!alternative}% can be used instead of pagenumber
500        \fi
501        \ifx\currentreferencecoding\s!xml
502            xmlroot  {\xmldocument} % only useful when text
503        \fi
504        \ifempty\currentregisterxmlsetup \else
505            xmlsetup {\currentregisterxmlsetup}%
506        \fi
507        }%
508        references {%
509        \ifempty\currentregisterlabel \else
510            label    {\currentregisterlabel}%
511        \fi
512          % view     {\interactionparameter\c!focus}%
513        }%
514        entries {%
515            % we need a special one for xml, this is just a single one
516            \ifempty\currentregisterentries
517                entries {
518                    {\currentregisterentriesa}%
519                    {\currentregisterentriesb}%
520                    {\currentregisterentriesc}%
521                }
522            \else
523                entry {\currentregisterentries}%
524            \fi
525            \ifempty\currentregisterkeys
526                keys {
527                    {\currentregisterkeysa}%
528                    {\currentregisterkeysb}%
529                    {\currentregisterkeysc}%
530                }
531            \else
532                key {\currentregisterkeys}%
533            \fi
534            \ifempty\currentregisterprocessors
535                processors {
536                    {\currentregisterprocessorsa}%
537                    {\currentregisterprocessorsb}%
538                    {\currentregisterprocessorsc}%
539                }
540            \else
541                processor {\currentregisterprocessors}%
542            \fi
543        }%
544        userdata {\detokenize\expandafter{\normalexpanded{#3}}}
545    }%
546   \relax
547   \endgroup}
548
549% The following variants are meant for (for instance xml). There is some
550% overlap with previously defined macros.
551%
552% \starttext
553%     \setstructurepageregister[index][entries=alpha]a
554%     \setstructurepageregister[index][entries=gamma]g
555%     \setstructurepageregister[index][entries=beta]b
556%     \setstructurepageregister[index][entries:1=alpha,keys:1=z]a
557%     \setstructurepageregister[index][entries:1=gamma,keys:1=x]g
558%     \setstructurepageregister[index][entries:1=beta, keys:1=y]b
559%     \index{alpha}a
560%     \index{gamma}g
561%     \index{beta}b
562%     \placeregister[index][n=1]
563% \stoptext
564
565% some overlap with previous
566
567\permanent\tolerant\protected\def\setstructurepageregister[#1]#*[#2]#*[#S#3]% [register][settings][userdata]
568  {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}}
569
570\permanent\tolerant\protected\def\startstructurepageregister[#1]#*[#2]#*[#S#3]#*[#S#4]% [register][tag][settings][userdata]
571  {\doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,#3}{#4}}}
572
573\permanent\tolerant\protected\def\stopstructurepageregister[#1]#*[#2]%
574  {\normalexpanded{\ctxlatecommand{structures.registers.extend("#1","#2")}}}
575
576\aliased\let\openstructurepageregisterrange \startstructurepageregister
577\aliased\let\closestructurepageregisterrange\stopstructurepageregister
578
579% So far.
580
581\tolerant\protected\def\strc_registers_insert_see[#1]#*[#2]#*#:#3#4%
582  {\doflushatpar{\strc_registers_insert_see_indeed{#1}{#2}{#3}{#4}}}
583
584\def\strc_registers_insert_see_indeed#1#2#3#4% register key entry seeword
585  {\begingroup
586   \cdef\currentregister{#1}%
587   \edef\currentregisterexpansion{\registerparameter\c!expansion}%
588   \ifx\currentregisterexpansion\s!xml
589     \xmlstartraw
590       \xdef\currentregisterentries{\detokenize{#3}}% not ok yet
591       \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet
592     \xmlstopraw
593     \glet\currentregistercoding\s!xml
594   \else
595     \ifx\currentregisterexpansion\v!yes
596       \xdef\currentregisterentries{#3}% not ok yet
597       \xdef\currentregisterseeword{#4}% not ok yet
598     \else
599       \xdef\currentregisterentries{\detokenize{#3}}% not ok yet
600       \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet
601     \fi
602     \glet\currentregistercoding\s!tex
603   \fi
604   \setnextinternalreference
605   % we could consider storing register entries in list
606   \edef\temp{\clf_storeregister{% \temp grabs the nofentries
607     metadata {%
608         kind {see}%
609         name {\currentregister}%
610     }%
611     references {%
612%         view  {\interactionparameter\c!focus}%
613     }%
614     entries {%
615         % we need a special one for xml, this is just a single one
616         entry {\currentregisterentries}%
617         key   {#2}%
618     }%
619     seeword {%
620         text  {\currentregisterseeword}%
621     }%
622   }}%
623   \clf_setinternalreference
624      internal \locationcount
625      view     {\interactionparameter\c!focus}%
626   \relax % this will change
627   \dostarttagged\t!registerlocation\currentregister
628   \c_attr_destination\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
629   \dotagregisterlocation
630   \dostoptagged
631   \endgroup}
632
633%D Rendering:
634
635% todo: c!language ipv s!language
636
637\permanent\def\utilityregisterlength{\listlength} % also in strc-lst (downward compatible name)
638
639% \mutable\let\listlength\!!zerocount             % also in strc-lst
640
641\permanent\tolerant\protected\def\determineregistercharacteristics[#1]#*[#S#2]%
642  {\begingroup
643   \setupregister[#1][#2]%
644   \cdef\currentregister{\firstinset{#1}}%
645   \normalexpanded{\endgroup\noexpand\xdef\noexpand\listlength{\clf_analyzeregister
646     {\currentregister}%
647     {%
648        language    {\registerparameter\s!language}%
649        method      {\registerparameter\c!method}%
650        numberorder {\registerparameter\c!numberorder}%
651        compress    {\registerparameter\c!compress}%
652        criterium   {\registerparameter\c!criterium}%
653        pagenumber  \ifempty\registerpageseparatorsymbol false\else true\fi
654     }%
655   }}%
656   \ifcase\utilityregisterlength\relax
657     \resetsystemmode\v!register
658   \else
659     \setsystemmode  \v!register
660   \fi}
661
662\newtoks\everyplaceregister
663
664\appendtoks
665    \dontcomplain
666\to \everyplaceregister
667
668\newconditional\c_strc_registers_text_interaction
669\newconditional\c_strc_registers_page_done
670
671\permanent\tolerant\protected\def\placeregister[#1]#*[#S#2]%
672  {\ifarguments\else
673     \begingroup
674    %\forgetall
675     \setupregister[#1][#2]% can be a list
676     \cdef\currentregister{\firstinset{#1}}%
677     \expand\everyplaceregister
678     \ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone
679       \startmixedcolumns[\currentregister]%
680         \strc_registers_place_indeed{#1}%
681       \stopmixedcolumns
682     \else
683       \strc_registers_place_indeed{#1}%
684     \fi
685     \endgroup
686   \fi}
687
688\def\strc_registers_place_indeed#1%
689  {\ifcstok{\registerparameter\c!interaction}\v!text
690     \c_strc_registers_text_interaction\conditionaltrue
691   \else
692     \c_strc_registers_text_interaction\conditionalfalse
693   \fi
694   \clf_processregister
695     {#1}%
696     {%
697        language      {\registerparameter\s!language}%
698        method        {\registerparameter\c!method}%
699        numberorder   {\registerparameter\c!numberorder}%
700        check         {\registerparameter\c!check}%
701        compress      {\registerparameter\c!compress}%
702        criterium     {\registerparameter\c!criterium}%
703        pagemethod    {\registerparameter\c!pagemethod}%
704        pagenumber    \ifempty\registerpageseparatorsymbol false\else true\fi
705     }{%
706        separatorset  {\registerparameter\c!pageprefixseparatorset}%
707        conversionset {\registerparameter\c!pageprefixconversionset}%
708        starter       {\registerparameter\c!pageprefixstarter}%
709        stopper       {\registerparameter\c!pageprefixstopper}%
710        set           {\registerparameter\c!pageprefixset}%
711        segments      {\registerparameter\c!pageprefixsegments}%
712        connector     {\registerparameter\c!pageprefixconnector}%
713     }{%
714        prefix        {\registerparameter\c!pageprefix}%
715        separatorset  {\registerparameter\c!pageseparatorset}%
716        conversionset {\registerparameter\c!pageconversionset}%
717        starter       {\registerparameter\c!pagestarter}%
718        stopper       {\registerparameter\c!pagestopper}%
719        segments      {\registerparameter\c!pagesegments}%
720     }%
721   \relax}
722
723% \def\strc_registers_limited_entry#1%
724%   {\limitatetext{#1}\currentregistermaxwidth\unknown}%
725
726\def\strc_registers_limited_entry#1%
727  {\limitated
728     left     {\currentregistermaxwidth}%
729     sentinel {\unknown}%
730     text     {#1}%
731     freeze   true
732   \relax}
733
734\aliased\let\limitedregisterentry\firstofoneargument
735
736\appendtoks
737    \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}%
738    \ifempty\currentregistermaxwidth
739      \enforced\let\limitedregisterentry\firstofoneargument
740    \else
741      \enforced\let\limitedregisterentry\strc_registers_limited_entry
742    \fi
743\to \everyplaceregister
744
745\permanent\tolerant\protected\def\completeregister[#1]#*[#S#2]%
746  {\ifarguments\or
747     \begingroup
748     \cdef\currentregister{\firstinset{#1}}%
749     \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}%
750     \placeregister[#1][#2]%
751     \page[\v!yes]%
752     \stopnamedsection
753     \endgroup
754   \fi}
755
756% test case for collapsing (experimental, for Steffen Wolfrum)
757%
758% \starttext
759% \placeregister[index][compress=no]  \blank[2*big]
760% \placeregister[index][compress=yes] \blank[2*big]
761% \placeregister[index][compress=all] \page
762% \dorecurse{10}{test 1:!\index{test} test \page}
763% \dorecurse{5} {test 2:\recurselevel      \page}
764% \dorecurse{10}{test 3:!\index{test} test \page}
765% \dorecurse{5} {test 4:\recurselevel      \page}
766% \dorecurse{1} {test 5:!\index{test} test \page}
767% \dorecurse{5} {test 6:\recurselevel      \page}
768% \dorecurse{10}{test 7:!\index{test} test \page}
769% \dorecurse{5} {test 8:\recurselevel      \page}
770% oeps \index{oeps}
771% xxxx \index{xxxx}
772% todo \index{todo}
773% \stoptext
774
775%D Kind of new:
776
777% % index-1.tex:
778%
779% \setupinteraction[state=start]
780% \starttext
781%     test \index{entry    WB.1} \page empty \page
782%     test \index{another  WB.1} \page empty \page
783%     test \index{onemore  WB.1} \page empty \page
784%     test \index{whatever WB.1} \page empty \page
785%     test \index{common}        \page empty \page
786%     \placeregister[index]
787% \stoptext
788%
789% % index-2.tex:
790%
791% \setupinteraction[state=start]
792% \defineregister[xedni]
793% \useregister[workbook][index-1][index][WB ]
794% \starttext
795%     test \index{onemore TB.1} \page
796%     test \index{another TB.1} \page
797%     test \index{entry   TB.1} \page
798%     test \index{common}       \page
799%     test \xedni{onemore TB.2} \page
800%     test \xedni{another TB.2} \page
801%     test \xedni{entry   TB.2} \page
802%     test \xedni{common}       \page
803%     \placeregister[index,xedni,workbook]
804% \stoptext
805
806\permanent\protected\tolerant\def\useregister[#1]#*[#2]#*[#3]#*[#4]%  tag file class prefix
807  {\doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
808   \clf_useregister{#1}{#2}{#3}{#4}}
809
810% \permanent\protected\tolerant\def\useregister[#1]#*[#2]#*[#3]#*[#4]%  tag file class prefix
811%   {\begingroup
812%    \doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
813%    \ifhastok={#4}%
814%      \getdummyparameters[\c!prefix=#1,\c!label=#1,#4]%
815%    \else
816%      \getdummyparameters[\c!prefix=#4,\c!label=#4]%
817%    \fi
818%    \clf_useregister
819%      {#1}
820%      {
821%         filename {#2}
822%         class    {#3}
823%         prefix   {\dummyparameter\c!prefix}
824%         label    {\dummyparameter\c!label}
825%      }
826%    \relax
827%    \endgroup}
828
829%D Character rendering (sections):
830
831\installcorenamespace{registerindicator}
832
833\permanent\def\defaultregistercharacter#1%
834  {\edef\currentregistercharacter{#1}%
835   \ifempty\currentregistercharacter
836     % skip
837   \orelse\ifx\currentregistercharacter\s!unknown
838     % skip
839   \orelse\ifcstok{\registerparameter\c!indicator}\v!yes
840     \strc_registers_place_character_yes
841   \else
842     \strc_registers_place_character_nop
843   \fi}
844
845\def\strc_registers_place_character_yes
846  {\expandnamespaceparameter\??registerindicator\registerparameter\c!alternative\v!a{\currentregistercharacter}}
847
848\def\strc_registers_place_character_nop
849  {\registerparameter\c!before
850   \goodbreak}
851
852% a = <before> <goodbreak> <character> <par> <after> <nobreak>
853
854\def\strc_registers_indicator_a#1#2%
855  {\registerparameter\c!before
856   % bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight
857   \typo_injectors_check_register
858   \begingroup
859   \useregisterstyleandcolor\c!style\c!color
860   \dontleavehmode
861   \typo_injectors_mark_register
862   \strut
863   \iflocation
864     \dosetdirectpagereference{\currentregister:\v!section:#1}%
865   \fi
866   \registerparameter\c!command{#2}%
867   \endgroup
868   \blank[\v!samepage]%
869   \registerparameter\c!after
870   \endgraf
871   \nobreak}
872
873% b = <goodbreak> <before> <character> <after> <nobreak>
874
875\def\strc_registers_indicator_b#1#2%
876  {\registerparameter\c!before
877   \typo_injectors_check_register
878   \begingroup
879   \useregisterstyleandcolor\c!style\c!color
880   \dontleavehmode
881   \typo_injectors_mark_register
882   \strut
883   \iflocation
884     \dosetdirectpagereference{\currentregister:\v!section:#1}%
885   \fi
886   \registerparameter\c!command{#2}%
887   \endgroup
888   \registerparameter\c!after
889   \nobreak}
890
891\defcsname\??registerindicator a\endcsname#1{\strc_registers_indicator_a{#1}{#1}}
892\defcsname\??registerindicator A\endcsname#1{\strc_registers_indicator_a{#1}{\WORD{#1}}}
893\defcsname\??registerindicator b\endcsname#1{\strc_registers_indicator_b{#1}{#1}}
894\defcsname\??registerindicator B\endcsname#1{\strc_registers_indicator_b{#1}{\WORD{#1}}}
895
896%D The following macros are the interface to the rendering. These are
897%D generated by \LUA. This might change.
898
899% \showinjector
900% \setinjector[register][2][\column]
901%
902% \starttext
903%     first  \index{first}
904%     second \index{second}
905%     third  \index{third}
906%     fourth \index{fourth}
907%     \placeregister[index]
908% \stoptext
909
910\doinstallinjector\s!register
911
912%D Beware, we get funny side effects when a dangling \index precedes an
913%D placeindex as then flushing takes place inside the index. Took me hours
914%D to notice that.
915
916\newconstant \c_strc_registers_page_state % 0=nothing  1=page  2=see
917\newdimension\d_strc_registers_distance
918\newinteger  \c_strc_register_level
919
920\def\strc_registers_update_text_properties
921  {\ifx\m_current_register\currentregister\else
922     \useregisterstyleandcolor\c!textstyle\c!textcolor
923   \fi}
924
925\def\strc_registers_update_page_properties
926  {\ifx\m_current_register\currentregister\else
927     \useregisterstyleandcolor\c!pagestyle\c!pagecolor
928   \fi}
929
930\permanent\protected\def\startregisteroutput
931  {\endgraf
932   \begingroup
933   \d_strc_registers_distance{\registerparameter\c!distance}%
934   \dostarttaggedchained\t!register\currentregister\currentregister\??register
935   \forgeteverypar
936   \forgetparindent
937   \forgetparskip}
938
939\permanent\protected\def\stopregisteroutput
940  {\endgraf
941   \dostoptagged
942   \endgroup}
943
944\newdimension\d_strc_registers_hangindent
945\newinteger  \c_strc_registers_hangafter
946
947% \permanent\protected\def\usenestedregisterstyleandcolor#1#2% will change
948%   {\useregisterstyleandcolor#1#2%
949%    % how about style
950%    \ifconditional\c_strc_registers_text_interaction
951%      \ifempty\currentcolorparameter \else
952%        \resetinteractioncolor
953%      \fi
954%    \fi}
955%
956% \permanent\protected\def\startregisterentries#1% depth
957%   {\endgraf
958%    \begingroup
959%    \c_strc_register_level\ifnum#1>\c_strc_registers_maxlevel\c_strc_registers_maxlevel\else#1\fi\relax
960%    \dostarttaggednodetail\t!registerentries
961%  % \let\savedcurrentregister\currentregister
962%    \pushmacro\currentregister
963%    \cdef\currentregister{\currentregister:\the\c_strc_register_level}%
964%    \usenestedregisterstyleandcolor\c!textstyle\c!textcolor
965%    \ifnum\c_strc_register_level>\plusone
966%      \advanceby\leftskip\d_strc_registers_distance\relax
967%    \fi
968%    \d_strc_registers_hangindent\registerparameter\c!distance\relax
969%    \c_strc_registers_hangafter \plusone
970%    \blank[\v!samepage]%
971%  % \let\currentregister\savedcurrentregister}
972%    \popmacro\currentregister}
973%
974% \permanent\protected\def\stopregisterentries
975%   {\endgraf
976%    \dostoptagged
977%    \endgroup}
978
979%D See test suite \type {registers/horizontal-001.tex} for a more extensive example
980%D of horizontal:
981%D
982%D \stoptyping
983%D \defineregister
984%D   [demo]
985%D   [n=1,
986%D    pagenumber=no,
987%D    textalternative=horizontal,
988%D    distance=0pt]
989%D
990%D \setupregister [demo] [2] [textstyle=bold,left={, }]
991%D \setupregister [demo] [3] [textstyle=italic,left={, }]
992%D
993%D \setregisterentry [demo] [entries:1={alpha}, entries:2={one}, entries:3={first}]
994%D \setregisterentry [demo] [entries:1={beta},  entries:2={two}, entries:3={last}]
995%D
996%D \starttext
997%D     \starttitle[title=Demo]
998%D         \placeregister[demo]
999%D     \stoptitle
1000%D \stoptext
1001%D \stoptyping
1002
1003\appendtoks
1004    \ifcstok{\registerparameter\c!textalternative}\v!horizontal
1005      \c_strc_registers_vertical\conditionalfalse
1006    \else
1007      \c_strc_registers_vertical\conditionaltrue
1008    \fi
1009\to \everysetupregister
1010
1011\mutable\lettonothing\currentnestedregister
1012
1013\permanent\protected\def\usenestedregisterstyleandcolor#1#2% will change
1014  {\useregisterstyleandcolor#1#2%
1015   % how about style
1016   \ifconditional\c_strc_registers_text_interaction
1017     \ifempty\currentcolorparameter \else
1018       \resetinteractioncolor
1019     \fi
1020   \fi}
1021
1022\permanent\protected\def\startregisterentries#1% depth
1023  {\ifconditional\c_strc_registers_vertical
1024     \endgraf
1025   \fi
1026   \begingroup
1027   \c_strc_register_level\ifnum#1>\c_strc_registers_maxlevel\c_strc_registers_maxlevel\else#1\fi\relax
1028   \dostarttaggednodetail\t!registerentries
1029   \pushmacro\currentregister % bah
1030   \cdef\currentregister{\currentregister:\the\c_strc_register_level}%
1031   \let\currentnestedregister\currentregister
1032   \usenestedregisterstyleandcolor\c!textstyle\c!textcolor
1033   \ifnum\c_strc_register_level>\plusone
1034     \advanceby\leftskip\d_strc_registers_distance\relax
1035   \fi
1036   \d_strc_registers_hangindent{\registerparameter\c!distance}%
1037   \c_strc_registers_hangafter \plusone
1038   \ifconditional\c_strc_registers_vertical
1039     \blank[\v!samepage]%
1040   \fi
1041   \popmacro\currentregister}
1042
1043\permanent\protected\def\stopregisterentries
1044  {\endgraf
1045   \dostoptagged
1046   \endgroup}
1047
1048\permanent\protected\def\startregisterentry#1% todo: level
1049  {\typo_injectors_check_register
1050   \begingroup
1051   \dostarttaggednodetail\t!registerentry
1052   \global\setconstant\c_strc_registers_page_state\zerocount
1053   \ifconditional\c_strc_registers_vertical
1054     \hangindent\d_strc_registers_hangindent
1055     \hangafter \c_strc_registers_hangafter
1056   \else
1057     \namedregisterparameter\currentnestedregister\c!left\relax
1058   \fi
1059   \typo_injectors_mark_register}
1060
1061\permanent\protected\def\stopregisterentry
1062  {\ifconditional\c_strc_registers_vertical
1063     \endgraf
1064   \else
1065     \namedregisterparameter\currentnestedregister\c!right\relax
1066   \fi
1067   \global\setconstant\c_strc_registers_page_state\zerocount
1068   \dostoptagged
1069   \endgroup}
1070
1071\permanent\protected\def\startregistersection#1% title
1072  {\dostarttaggednodetail\t!registersection
1073   \dostarttaggednodetail\t!registertag
1074   \registercharacter{#1}\endgraf
1075   \dostoptagged}
1076
1077\permanent\protected\def\stopregistersection
1078  {\dostoptagged
1079   \endgraf}
1080
1081\permanent\protected\def\startregisterpages
1082  {\begingroup
1083   \dostarttaggednodetail\t!registerpages
1084   \useregisterstyleandcolor\c!pagestyle\c!pagecolor
1085   \registerparameter\c!pageleft}
1086
1087\permanent\protected\def\stopregisterpages
1088  {\registerparameter\c!pageright
1089   \dostoptagged
1090   \endgroup}
1091
1092\permanent\protected\def\startregisterseewords
1093  {\begingroup
1094   \dostarttaggednodetail\t!registerpage
1095   \useregisterstyleandcolor\c!pagestyle\c!pagecolor}
1096
1097\permanent\protected\def\stopregisterseewords
1098  {\dostoptagged
1099   \endgroup}
1100
1101\permanent\protected\def\registerpageseparator % todo: , configurable
1102  {\ifcase\c_strc_registers_page_state
1103     \hskip\d_strc_registers_distance\relax
1104   \or
1105     \dostarttaggednodetail\t!registerseparator
1106     \registerpageseparatorsymbol % page
1107     \dostoptagged
1108   \or
1109     \dostarttaggednodetail\t!registerseparator
1110     \registerpageseparatorsymbol % see
1111     \dostoptagged
1112   \fi}
1113
1114\permanent\protected\def\registeronepagerangeseparator
1115  {|\endash|} % todo use \prewordbreak
1116
1117\let\currentregisterrealpage\!!zerocount % todo: more general accessor
1118
1119% keep as reference
1120%
1121% \permanent\protected\def\withregisterpagecommand#1#2#3#4%
1122%   {\ifcase#3\relax
1123%      {\tt [entry\space not\space flushed]}%
1124%    \else
1125%      \def\currentregisterpageindex{#2}%
1126%      \def\currentregisterrealpage{#3}%
1127%      \iflocation
1128%        \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
1129%      \else
1130%        \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
1131%      \fi
1132%    \fi}
1133%
1134% todo: adapt \strc_references_goto_internal to take an extra argument, the ref
1135
1136\permanent\protected\def\withregisterpagecommand#1#2#3#4% #1:processor #2:internal #3:realpage #4:page
1137  {\begingroup
1138   \ifcase#3\relax
1139     \tt [entry\space not\space flushed]%
1140   \else
1141     \def\currentregisterpageindex{#2}%
1142     \def\currentregisterrealpage{#3}%
1143     \ifchknum\currentregisterpageindex\or
1144       \lettonothing\currentregisterpageprefix
1145     \else
1146       \def\currentregisterpageprefix{\clf_registerlabel{\currentregisterpageindex}}%
1147     \fi
1148     \iflocation
1149       \ifempty\currentregisterpageprefix
1150         \strc_references_get_simple_reference{internal(\currentregisterpageindex)}%
1151       \else
1152         \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}%
1153       \fi
1154       \global\lastsavedreferenceattribute\currentreferenceattribute
1155       \c_attr_reference\currentreferenceattribute
1156       \setlocationattributes
1157     \fi
1158     \applyprocessor{#1}{\currentregisterpageprefix\registerparameter\c!pagecommand{#4}}%
1159   \fi
1160   \endgroup}
1161
1162\lettonothing\m_current_register
1163
1164\permanent\protected\def\pushcurrentregister#1%
1165  {\let\m_current_register\currentregister
1166   \cdef\currentregister{#1}}
1167
1168\permanent\protected\def\popcurrentregister
1169  {\let\currentregister\m_current_register}
1170
1171\permanent\protected\def\registeronepage#1#2#3#4#5% #1:class #2:processor content
1172  {\pushcurrentregister{#1}%
1173   \strc_registers_update_page_properties
1174   \ifcstok{\registerparameter\c!pagenumber}\v!no\else
1175     \registerpageseparator
1176     \global\setconstant\c_strc_registers_page_state\plusone
1177     \dostarttaggednodetail\t!registerpage
1178     \withregisterpagecommand{#2}{#3}{#4}{#5}%
1179     \dostoptagged
1180   \fi
1181   \popcurrentregister}
1182
1183\newconditional\c_strc_registers_following
1184
1185\appendtoks
1186    \edef\p_compress{\registerparameter\c!compress}%
1187    \ifx\p_compress\v!text
1188      \c_strc_registers_following\conditionaltrue
1189      \letregisterparameter\c!compress\v!yes
1190    \else
1191      \c_strc_registers_following\conditionalfalse
1192    \fi
1193\to \everyplaceregister
1194
1195\permanent\protected\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor  content, content todo: -- configurable
1196  {\pushcurrentregister{#1}%
1197   \strc_registers_update_page_properties
1198   \ifcstok{\registerparameter\c!pagenumber}\v!no\else
1199     \registerpageseparator
1200     \global\setconstant\c_strc_registers_page_state\plusone
1201     \dostarttaggednodetail\t!registerpagerange
1202     \dostarttaggednodetail\t!registerfrompage
1203     \withregisterpagecommand{#2}{#3}{#4}{#5}%
1204     \dostoptagged
1205     \ifconditional\c_strc_registers_following
1206       \ifnum#3={#6-1}%
1207         \labeltext{following:\s!singular}%
1208       \else
1209         \labeltext{following:\s!plural}%
1210       \fi
1211     \else
1212       \registeronepagerangeseparator
1213       \dostarttaggednodetail\t!registertopage
1214       \withregisterpagecommand{#2}{#6}{#7}{#8}%
1215     \fi
1216     \dostoptagged
1217     \dostoptagged
1218   \fi
1219   \popcurrentregister}
1220
1221\permanent\protected\def\defaultregisterentry#1#2#3#4#5% #1:class #2:processor #3:internal #4:seeindex #5:word
1222  {\pushcurrentregister{#1}%
1223   \strc_registers_update_text_properties
1224   \def\currentregisterpageindex{#3}%
1225   \iflocation
1226     \def\currentregisterseeindex{#4}%
1227     \ifconditional\c_strc_registers_text_interaction
1228       \ifchknum\currentregisterpageindex\or
1229         \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]%
1230       \fi
1231     \else
1232       \doapplyregisterentrycommand{#2}{#5}%
1233     \fi
1234   \else
1235     \lettonothing\currentregisterseeindex
1236     \doapplyregisterentrycommand{#2}{#5}%
1237   \fi
1238   \popcurrentregister}
1239
1240\permanent\protected\def\doapplyregisterentrycommand#1#2% processor text
1241  {\dostarttaggednodetail\t!registercontent
1242   \ifempty\currentregisterseeindex \else
1243     \dontleavehmode
1244     \dosetdirectpagereference{seeindex:\currentregisterseeindex}% maybe some day we will support an area
1245   \fi
1246   \applyprocessor{#1}{\registerparameter\c!textcommand{\limitedregisterentry{\registerparameter\c!deeptextcommand{#2}}}}%
1247   \dostoptagged}
1248
1249\permanent\protected\def\doapplyregisterseecommand#1#2%
1250  {\ifempty\currentregisterseeindex
1251     \applyprocessor{#1}{#2}%
1252   \orelse\iflocation
1253     \strc_references_goto_internal{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]%
1254   \else
1255     \applyprocessor{#1}{#2}%
1256   \fi}
1257
1258\permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word
1259  {\pushcurrentregister{#1}%
1260   \ifnum#2=\plusone
1261     \registerpageseparator
1262   \fi
1263   \global\setconstant\c_strc_registers_page_state\plustwo
1264   \def\currentregisterpageindex{#5}%
1265   \def\currentregisterseeindex{#6}%
1266   \dostarttaggednodetail\t!registersee
1267   \c_strc_registers_page_done\conditionaltrue
1268   \ifchknum\currentregisterseeindex\or
1269     \lettonothing\currentregisterpageprefix
1270   \else
1271     \def\currentregisterpageprefix{\clf_registerlabel{\currentregisterseeindex}}%
1272   \fi
1273   \iflocation
1274     \ifempty\currentregisterpageprefix
1275       \strc_references_get_simple_reference{internal(\currentregisterseeindex)}%
1276     \else
1277       \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}%
1278     \fi
1279     \global\lastsavedreferenceattribute\currentreferenceattribute
1280     \c_attr_reference\currentreferenceattribute
1281     \setlocationattributes
1282   \fi
1283   \ifnum#2=\plusone
1284     \labeltexts\v!see{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}%
1285   \orelse\ifnum#2=#3\relax
1286     \labeltexts\v!and{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}%
1287   \else
1288     ,\space\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}%
1289   \fi
1290   \dostoptagged
1291   \popcurrentregister}
1292
1293\permanent\protected\def\doapplyregistersectioncommand#1#2%
1294  {\ifempty\currentregistersectionindex
1295     \applyprocessor{#1}{#2}%
1296   \orelse\iflocation
1297     \strc_references_goto_internal{\applyprocessor{#1}{#2}}[sectionindex:\currentregistersectionindex]%
1298   \else
1299     \applyprocessor{#1}{#2}%
1300   \fi}
1301
1302\permanent\protected\def\defaultregistersection#1#2#3#4#5#6#7% class i n #4:processor #5:internal #6:sectionindex #7:word
1303  {\pushcurrentregister{#1}%
1304   \ifnum#2=\plusone
1305     \registerpageseparator
1306   \fi
1307   \global\setconstant\c_strc_registers_page_state\plustwo
1308   \def\currentregisterpageindex{#5}%
1309   \dostarttaggednodetail\t!registersection
1310   \c_strc_registers_page_done\conditionaltrue
1311   \iflocation
1312     \def\currentregistersectionindex{#6}%
1313   \else
1314     \lettonothing\currentregistersectionindex
1315   \fi
1316   \ifnum#2=\plusone\else
1317      ,\space
1318   \fi
1319   \doapplyregistersectioncommand{#4}{#7}%
1320   \dostoptagged
1321   \popcurrentregister}
1322
1323\aliased\let\registersection  \defaultregistersection
1324\aliased\let\registerseeword  \defaultregisterseeword
1325\aliased\let\registerentry    \defaultregisterentry
1326\aliased\let\registercharacter\defaultregistercharacter
1327
1328%D Experimental:
1329%D
1330%D \starttyping
1331%D \setupregister
1332%D   [index]
1333%D   [pagesegments=1:4,
1334%D    pagemethod=section]
1335%D
1336%D \starttext
1337%D
1338%D     \chapter {one} \section {alpha}
1339%D
1340%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
1341%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
1342%D
1343%D     \chapter {one} \section {alpha}
1344%D
1345%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
1346%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
1347%D
1348%D     \placeindex[n=1]
1349%D
1350%D \stoptext
1351%D \stoptyping
1352
1353%D A few specific rendering variants:
1354
1355% \def\doregisterpagelocation#1#2%
1356%   {\nextregisterpage
1357%    \hbox to 1em{\hss\doregisterpagehowto{#1}{#2}\hss}}
1358
1359% todo: \installregisterpagehandler
1360
1361% \def\MyRegisterPageCommand#1%
1362%   {#1\currentregisterpageuserdata{whatever}}
1363%
1364% \starttext
1365%     \setregisterentry[index][entries=aaa][whatever=f.] test \index{bbb} test
1366%     \placeregister[index][n=1,pagecommand=\MyRegisterPageCommand]
1367% \stoptext
1368
1369\permanent\def\registerpageuserdata       #1#2{\clf_registeruserdata#1{#2}}
1370\permanent\def\currentregisterpageuserdata    {\registerpageuserdata\currentregisterpageindex} % {#1}
1371
1372% not yet ok : new internal handler names
1373
1374\lettonothing\registerpageseparatorsymbol
1375
1376\permanent\protected\def\registerpagebuttonsymbol
1377  {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax}
1378
1379\installcorenamespace{registersymbol}
1380
1381\defcsname\??registersymbol n\endcsname
1382  {\enforced\frozen\def\registerpageseparatorsymbol{,\space}}
1383
1384\defcsname\??registersymbol a\endcsname
1385  {\enforced\frozen\def\registerpageseparatorsymbol{,\space}} % now done via conversion
1386
1387\defcsname\??registersymbol\v!none\endcsname
1388  {\enforced\frozen\lettonothing\registerpageseparatorsymbol
1389   \enforced\frozen\let\registeronepage\gobblefivearguments
1390   \enforced\frozen\let\registerpagerange\gobbleeightarguments}
1391
1392\defcsname\??registersymbol 1\endcsname
1393  {\enforced\frozen\let\registerpageseparatorsymbol\space
1394   \enforced\frozen\def\registeronepage{\symbol[1]\gobblefivearguments}%
1395   \enforced\frozen\def\registerpagerange{\symbol[1]\gobbleeightarguments}}
1396
1397\defcsname\??registersymbol 2\endcsname
1398  {\enforced\frozen\let\registerpageseparatorsymbol\space
1399   \enforced\frozen\def\registeronepage{\registerpagebuttonsymbol\gobblefivearguments}%
1400   \enforced\frozen\def\registerpagerange{\registerpagebuttonsymbol\gobbleeightarguments}}
1401
1402\protected\def\strc_registers_set_page_rendering
1403  {\ifcstok{\registerparameter\c!pagenumber}\v!no
1404     \enforced\frozen\let\currentregisterpagesymbol\v!none
1405   \else
1406     \enforced\frozen\edef\currentregisterpagesymbol{\registerparameter\c!symbol}%
1407   \fi
1408   \ifempty\currentregisterpagesymbol
1409     \csname\??registersymbol n\endcsname
1410   \orelse\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname
1411     \csname\??registersymbol\currentregisterpagesymbol\endcsname
1412   \else
1413     \enforced\frozen\let\registerpageseparatorsymbol\space
1414     \enforced\frozen\def\registeronepage{\registerparameter\c!symbol\gobblefivearguments}%
1415     \enforced\frozen\def\registerpagerange{\registerparameter\c!symbol\gobbleeightarguments}%
1416   \fi}
1417
1418\appendtoks
1419     \strc_registers_set_page_rendering
1420\to \everyplaceregister
1421
1422%D The linked register code will be reimplemented (not that hard) when it's needed
1423%D again and/or when I'm bored.
1424
1425\permanent          \def\findregisterinternal#1#2#3{\clf_findregisterinternal{#1}{#2}#3\relax}
1426\permanent\protected\def\pageofinternal          #1{\clf_pageofinternal#1\relax}
1427
1428\permanent\protected\def\linkedregisterentrylink#1#2#3#4% tag where before after
1429  {\iflocation
1430     \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax
1431     \ifcase\scratchcounter\else
1432       #3\relax
1433       \goto{\symbol[#2]}[internal(\the\scratchcounter)]%
1434       #4\relax
1435     \fi
1436   \else
1437   % \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax
1438   % \ifcase\scratchcounter\else
1439   %   #3\relax
1440   %   \pageofinternal\scratchcounter
1441   %   #4\relax
1442   % \fi
1443   \fi}
1444
1445\permanent\protected\def\linkedregisterentry#1%
1446  {\dontleavehmode
1447   \begingroup
1448   \setbox\scratchbox\hbox{#1}%
1449   \linkedregisterentrylink\currentregistername\v!previous\relax\nobreakspace
1450   \unhbox\scratchbox
1451   \linkedregisterentrylink\currentregistername\v!next\nobreakspace\relax
1452   \endgroup}
1453
1454\permanent\protected\def\registerpacked#1#2%
1455  {\iflocation
1456     \hskip\d_strc_registers_distance\relax
1457     \nobreak
1458     \ifnum#1=#2\relax
1459       \goto{\symbol[\v!somewhere]}[internal(#1)]%
1460     \else
1461       \goto{\symbol[\v!first]}[internal(#1)]%
1462       \nobreakspace
1463       \goto{\symbol[\v!last]}[internal(#2)]%
1464     \fi
1465   \fi}
1466
1467%D Default index:
1468
1469\defineregister
1470  [\v!index]
1471%  [\v!indices]
1472
1473\stopcontextdefinitioncode
1474
1475\protect \endinput
1476
1477% % maybe also more levels with [entries|keys|processors]:n
1478% %
1479% % \setregisterentry
1480% %   [index]
1481% %   [entries:1=one,
1482% %    entries:2=two,
1483% %    entries:3=three,
1484% %    entries:4=four]
1485% %
1486% % test \blank \placeregister[index][balance=no]
1487%
1488% \def\expanddetokenizedregistervalues#1#2%
1489%   {\edef\expandedregistervalue{\detokenizedregisterparameter{#1:#2}}%
1490%    \ifempty\expandedregistervalue\else
1491%       \letregisterparameter{#1:#2}\expandedregistervalue
1492%       \expandafter\expanddetokenizedregistervalues
1493%       \expandafter#1%
1494%       \expandafter{\the\numexpr#2+1}%
1495%    \fi}%
1496%
1497% \def\expandregistervalues#1#2%
1498%   {\edef\expandedregistervalue{\registerparameter{#1:#2}}%
1499%    \ifempty\expandedregistervalue\else
1500%       \letregisterparameter{#1:#2}\expandedregistervalue
1501%       \expandafter\expandregistervalues
1502%       \expandafter#1%
1503%       \expandafter{\the\numexpr#2+1}%
1504%    \fi}%
1505%
1506% % \def\injectregistervalues#1#2%
1507% %   {\beginlocalcontrol
1508% %    \edef\expandedregistervalue{\registerparameter{#1:\the\numexpr#2}}%
1509% %    \endlocalcontrol
1510% %    \ifempty\expandedregistervalue\else
1511% %       {\expandedregistervalue}%
1512% %       \injectregistervalues#1{#2+1}%
1513% %     \fi}%
1514%
1515% \def\injectregistervalues#1#2%
1516%   {\ifempty{\registerparameter{#1:\the\numexpr#2}}\else
1517%       \expandafter{\lastnamedcs}%
1518%       \injectregistervalues#1{#2+1}%
1519%     \fi}%
1520%
1521% \def\strc_registers_register_page_expand_xml_entries
1522%   {\xmlstartraw
1523%      \beginlocalcontrol
1524%      \expandregistervalues\c!entries1%
1525%      \endlocalcontrol
1526%    \xmlstopraw
1527%    \glet\currentregistercoding\s!xml}
1528%
1529% \def\strc_registers_register_page_expand_yes_entries
1530%   {\beginlocalcontrol
1531%    \expandregistervalues\c!entries1%
1532%    \endlocalcontrol
1533%    \glet\currentregistercoding\s!tex}
1534%
1535% \def\strc_registers_register_page_expand_nop_entries
1536%   {\beginlocalcontrol
1537%    \expanddetokenizesregistervalues\c!entries1%
1538%    \endlocalcontrol
1539%    \glet\currentregistercoding\s!tex}
1540%
1541% \def\strc_registers_register_page_expand_nop_entries
1542%   {\beginlocalcontrol
1543%    \expandregistervalues\c!entries1%
1544%    \endlocalcontrol
1545%    \glet\currentregistercoding\s!tex}
1546%
1547% \def\strc_registers_register_page_expand_xml_keys
1548%   {\xmlstartraw
1549%      \beginlocalcontrol
1550%      \expandregistervalues\c!keys1%
1551%      \endlocalcontrol
1552%    \xmlstopraw}
1553%
1554% \def\strc_registers_register_page_expand_yes_keys
1555%   {\beginlocalcontrol
1556%    \expandregistervalues\c!keys1%
1557%    \endlocalcontrol}
1558%
1559% \def\strc_registers_register_page_expand_processors
1560%   {\beginlocalcontrol
1561%    \expandregistervalues\c!processors1%
1562%    \endlocalcontrol}
1563%
1564% \def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata
1565%   {\begingroup
1566%    \cdef\currentregister{#1}%
1567%    %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
1568%    \setupcurrentregister[#2]%
1569%    \edef\currentregisterlabel     {\registerparameter\c!label}%
1570%    \edef\currentregisterexpansion {\registerparameter\c!expansion}%
1571%    \edef\currentregisterownnumber {\registerparameter\c!ownnumber}%
1572%    \xdef\currentregisterkeys      {\registerparameter\c!keys}%
1573%    \xdef\currentregisterentries   {\registerparameter\c!entries}%
1574%    \xdef\currentregisterprocessors{\registerparameter\c!processors}%
1575%    \xdef\currentregisterxmlsetup  {\registerparameter\c!xmlsetup}%
1576%    \ifempty\currentregisterentries
1577%      \ifx\currentregisterexpansion\s!xml
1578%        \strc_registers_register_page_expand_xml_entries
1579%      \orelse\ifx\currentregisterexpansion\v!yes
1580%        \strc_registers_register_page_expand_yes_entries
1581%      \else
1582%        \strc_registers_register_page_expand_nop_entries
1583%      \fi
1584%    \else
1585%      \ifx\currentregisterexpansion\s!xml
1586%        \strc_registers_register_page_expand_xml
1587%      \orelse\ifx\currentregisterexpansion\v!yes
1588%        \strc_registers_register_page_expand_yes
1589%      \else
1590%        \strc_registers_register_page_expand_nop
1591%      \fi
1592%    \fi
1593%    \ifempty\currentregisterkeys
1594%      \ifx\currentregistercoding\s!xml
1595%        \strc_registers_register_page_expand_xml_keys
1596%      \else
1597%        \strc_registers_register_page_expand_yes_keys
1598%      \fi
1599%    \fi
1600%    \strc_registers_register_page_expand_processors
1601%    \setnextinternalreference
1602%    % we could consider storing register entries in a list which we
1603%    % could then sort
1604%    \glet\currentregistername\currentregister
1605%    \xdef\currentregisternumber{\clf_storeregister % 'own' should not be in metadata
1606%         metadata {%
1607%             name     {\currentregister}%
1608%             coding   {\currentregistercoding}%
1609%         \ifx\currentregisterownnumber\v!yes
1610%             own      {\registerparameter\c!alternative}% can be used instead of pagenumber
1611%         \fi
1612%         \ifx\currentreferencecoding\s!xml
1613%             xmlroot  {\xmldocument} % only useful when text
1614%         \fi
1615%         \ifempty\currentregisterxmlsetup \else
1616%             xmlsetup {\currentregisterxmlsetup}%
1617%         \fi
1618%         }%
1619%         references {%
1620%         \ifempty\currentregisterlabel \else
1621%             label    {\currentregisterlabel}%
1622%         \fi
1623%          %  view     {\interactionparameter\c!focus}%
1624%         }%
1625%         entries {%
1626%             % we need a special one for xml, this is just a single one
1627%             \ifempty\currentregisterentries
1628%                 entries {\injectregistervalues\c!entries1}%
1629%             \else
1630%                 entry {\currentregisterentries}%
1631%             \fi
1632%             \ifempty\currentregisterkeys
1633%                 keys {\injectregistervalues\c!keys1}%
1634%             \else
1635%                 key {\currentregisterkeys}%
1636%             \fi
1637%             \ifempty\currentregisterprocessors
1638%                 processors {\injectregistervalues\c!processors1}%
1639%             \else
1640%                 processor {\currentregisterprocessors}%
1641%             \fi
1642%         }%
1643%         userdata {\detokenize\expandafter{\normalexpanded{#3}}}
1644%    }%
1645%    \clf_setinternalreference
1646%       internal \locationcount
1647%       view     {\interactionparameter\c!focus}%
1648%    \relax % this will change
1649%    \ifx\currentregisterownnumber\v!yes
1650%      \glet\currentregistersynchronize\relax
1651%    \else
1652%      \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
1653%    \fi
1654%    \currentregistersynchronize % here?
1655%    % needs thinking ... bla\index{bla}. will break before the . but adding a
1656%    % penalty is also no solution
1657%    \dostarttagged\t!registerlocation\currentregister
1658%    \c_attr_destination\lastdestinationattribute
1659%    \signalcharacter % no \strut as it will be removed during cleanup
1660%    \dotagregisterlocation
1661%    \dostoptagged
1662%    \endgroup}
1663