strc-reg.mkxl /size: 56 Kb    last modification: 2023-12-21 09:44
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 left \currentregistermaxwidth sentinel {\unknown} text {#1} freeze true\relax}
728
729\aliased\let\limitedregisterentry\firstofoneargument
730
731\appendtoks
732    \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}%
733    \ifempty\currentregistermaxwidth
734      \enforced\let\limitedregisterentry\firstofoneargument
735    \else
736      \enforced\let\limitedregisterentry\strc_registers_limited_entry
737    \fi
738\to \everyplaceregister
739
740\permanent\tolerant\protected\def\completeregister[#1]#*[#S#2]%
741  {\ifarguments\or
742     \begingroup
743     \cdef\currentregister{\firstinset{#1}}%
744     \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}%
745     \placeregister[#1][#2]%
746     \page[\v!yes]%
747     \stopnamedsection
748     \endgroup
749   \fi}
750
751% test case for collapsing (experimental, for Steffen Wolfrum)
752%
753% \starttext
754% \placeregister[index][compress=no]  \blank[2*big]
755% \placeregister[index][compress=yes] \blank[2*big]
756% \placeregister[index][compress=all] \page
757% \dorecurse{10}{test 1:!\index{test} test \page}
758% \dorecurse{5} {test 2:\recurselevel      \page}
759% \dorecurse{10}{test 3:!\index{test} test \page}
760% \dorecurse{5} {test 4:\recurselevel      \page}
761% \dorecurse{1} {test 5:!\index{test} test \page}
762% \dorecurse{5} {test 6:\recurselevel      \page}
763% \dorecurse{10}{test 7:!\index{test} test \page}
764% \dorecurse{5} {test 8:\recurselevel      \page}
765% oeps \index{oeps}
766% xxxx \index{xxxx}
767% todo \index{todo}
768% \stoptext
769
770%D Kind of new:
771
772% % index-1.tex:
773%
774% \setupinteraction[state=start]
775% \starttext
776%     test \index{entry    WB.1} \page empty \page
777%     test \index{another  WB.1} \page empty \page
778%     test \index{onemore  WB.1} \page empty \page
779%     test \index{whatever WB.1} \page empty \page
780%     test \index{common}        \page empty \page
781%     \placeregister[index]
782% \stoptext
783%
784% % index-2.tex:
785%
786% \setupinteraction[state=start]
787% \defineregister[xedni]
788% \useregister[workbook][index-1][index][WB ]
789% \starttext
790%     test \index{onemore TB.1} \page
791%     test \index{another TB.1} \page
792%     test \index{entry   TB.1} \page
793%     test \index{common}       \page
794%     test \xedni{onemore TB.2} \page
795%     test \xedni{another TB.2} \page
796%     test \xedni{entry   TB.2} \page
797%     test \xedni{common}       \page
798%     \placeregister[index,xedni,workbook]
799% \stoptext
800
801\permanent\protected\tolerant\def\useregister[#1]#*[#2]#*[#3]#*[#4]%  tag file class prefix
802  {\doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
803   \clf_useregister{#1}{#2}{#3}{#4}}
804
805% \permanent\protected\tolerant\def\useregister[#1]#*[#2]#*[#3]#*[#4]%  tag file class prefix
806%   {\begingroup
807%    \doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
808%    \ifhastok={#4}%
809%      \getdummyparameters[\c!prefix=#1,\c!label=#1,#4]%
810%    \else
811%      \getdummyparameters[\c!prefix=#4,\c!label=#4]%
812%    \fi
813%    \clf_useregister
814%      {#1}
815%      {
816%         filename {#2}
817%         class    {#3}
818%         prefix   {\dummyparameter\c!prefix}
819%         label    {\dummyparameter\c!label}
820%      }
821%    \relax
822%    \endgroup}
823
824%D Character rendering (sections):
825
826\installcorenamespace{registerindicator}
827
828\permanent\def\defaultregistercharacter#1%
829  {\edef\currentregistercharacter{#1}%
830   \ifempty\currentregistercharacter
831     % skip
832   \orelse\ifx\currentregistercharacter\s!unknown
833     % skip
834   \orelse\ifcstok{\registerparameter\c!indicator}\v!yes
835     \strc_registers_place_character_yes
836   \else
837     \strc_registers_place_character_nop
838   \fi}
839
840\def\strc_registers_place_character_yes
841  {\expandnamespaceparameter\??registerindicator\registerparameter\c!alternative\v!a{\currentregistercharacter}}
842
843\def\strc_registers_place_character_nop
844  {\registerparameter\c!before
845   \goodbreak}
846
847% a = <before> <goodbreak> <character> <par> <after> <nobreak>
848
849\def\strc_registers_indicator_a#1#2%
850  {\registerparameter\c!before
851   % bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight
852   \typo_injectors_check_register
853   \begingroup
854   \useregisterstyleandcolor\c!style\c!color
855   \dontleavehmode
856   \typo_injectors_mark_register
857   \strut
858   \iflocation
859     \dosetdirectpagereference{\currentregister:\v!section:#1}%
860   \fi
861   \registerparameter\c!command{#2}%
862   \endgroup
863   \blank[\v!samepage]%
864   \registerparameter\c!after
865   \endgraf
866   \nobreak}
867
868% b = <goodbreak> <before> <character> <after> <nobreak>
869
870\def\strc_registers_indicator_b#1#2%
871  {\registerparameter\c!before
872   \typo_injectors_check_register
873   \begingroup
874   \useregisterstyleandcolor\c!style\c!color
875   \dontleavehmode
876   \typo_injectors_mark_register
877   \strut
878   \iflocation
879     \dosetdirectpagereference{\currentregister:\v!section:#1}%
880   \fi
881   \registerparameter\c!command{#2}%
882   \endgroup
883   \registerparameter\c!after
884   \nobreak}
885
886\defcsname\??registerindicator a\endcsname#1{\strc_registers_indicator_a{#1}{#1}}
887\defcsname\??registerindicator A\endcsname#1{\strc_registers_indicator_a{#1}{\WORD{#1}}}
888\defcsname\??registerindicator b\endcsname#1{\strc_registers_indicator_b{#1}{#1}}
889\defcsname\??registerindicator B\endcsname#1{\strc_registers_indicator_b{#1}{\WORD{#1}}}
890
891%D The following macros are the interface to the rendering. These are
892%D generated by \LUA. This might change.
893
894% \showinjector
895% \setinjector[register][2][\column]
896%
897% \starttext
898%     first  \index{first}
899%     second \index{second}
900%     third  \index{third}
901%     fourth \index{fourth}
902%     \placeregister[index]
903% \stoptext
904
905\doinstallinjector\s!register
906
907%D Beware, we get funny side effects when a dangling \index precedes an
908%D placeindex as then flushing takes place inside the index. Took me hours
909%D to notice that.
910
911\newconstant \c_strc_registers_page_state % 0=nothing  1=page  2=see
912\newdimension\d_strc_registers_distance
913\newinteger  \c_strc_register_level
914
915\def\strc_registers_update_text_properties
916  {\ifx\m_current_register\currentregister\else
917     \useregisterstyleandcolor\c!textstyle\c!textcolor
918   \fi}
919
920\def\strc_registers_update_page_properties
921  {\ifx\m_current_register\currentregister\else
922     \useregisterstyleandcolor\c!pagestyle\c!pagecolor
923   \fi}
924
925\permanent\protected\def\startregisteroutput
926  {\endgraf
927   \begingroup
928   \d_strc_registers_distance\registerparameter\c!distance\relax
929   \dostarttaggedchained\t!register\currentregister\??register
930   \forgeteverypar
931   \forgetparindent
932   \forgetparskip}
933
934\permanent\protected\def\stopregisteroutput
935  {\endgraf
936   \dostoptagged
937   \endgroup}
938
939\newdimension\d_strc_registers_hangindent
940\newinteger  \c_strc_registers_hangafter
941
942% \permanent\protected\def\usenestedregisterstyleandcolor#1#2% will change
943%   {\useregisterstyleandcolor#1#2%
944%    % how about style
945%    \ifconditional\c_strc_registers_text_interaction
946%      \ifempty\currentcolorparameter \else
947%        \resetinteractionparameter\c!color
948%        \resetinteractionparameter\c!contrastcolor
949%      \fi
950%    \fi}
951%
952% \permanent\protected\def\startregisterentries#1% depth
953%   {\endgraf
954%    \begingroup
955%    \c_strc_register_level\ifnum#1>\c_strc_registers_maxlevel\c_strc_registers_maxlevel\else#1\fi\relax
956%    \dostarttagged\t!registerentries\empty
957%  % \let\savedcurrentregister\currentregister
958%    \pushmacro\currentregister
959%    \cdef\currentregister{\currentregister:\the\c_strc_register_level}%
960%    \usenestedregisterstyleandcolor\c!textstyle\c!textcolor
961%    \ifnum\c_strc_register_level>\plusone
962%      \advanceby\leftskip\d_strc_registers_distance\relax
963%    \fi
964%    \d_strc_registers_hangindent\registerparameter\c!distance\relax
965%    \c_strc_registers_hangafter \plusone
966%    \blank[\v!samepage]%
967%  % \let\currentregister\savedcurrentregister}
968%    \popmacro\currentregister}
969%
970% \permanent\protected\def\stopregisterentries
971%   {\endgraf
972%    \dostoptagged
973%    \endgroup}
974
975%D See test suite \type {registers/horizontal-001.tex} for a more extensive example
976%D of horizontal:
977%D
978%D \stoptyping
979%D \defineregister
980%D   [demo]
981%D   [n=1,
982%D    pagenumber=no,
983%D    textalternative=horizontal,
984%D    distance=0pt]
985%D
986%D \setupregister [demo] [2] [textstyle=bold,left={, }]
987%D \setupregister [demo] [3] [textstyle=italic,left={, }]
988%D
989%D \setregisterentry [demo] [entries:1={alpha}, entries:2={one}, entries:3={first}]
990%D \setregisterentry [demo] [entries:1={beta},  entries:2={two}, entries:3={last}]
991%D
992%D \starttext
993%D     \starttitle[title=Demo]
994%D         \placeregister[demo]
995%D     \stoptitle
996%D \stoptext
997%D \stoptyping
998
999\appendtoks
1000    \ifcstok{\registerparameter\c!textalternative}\v!horizontal
1001      \c_strc_registers_vertical\conditionalfalse
1002    \else
1003      \c_strc_registers_vertical\conditionaltrue
1004    \fi
1005\to \everysetupregister
1006
1007\mutable\lettonothing\currentnestedregister
1008
1009\permanent\protected\def\usenestedregisterstyleandcolor#1#2% will change
1010  {\useregisterstyleandcolor#1#2%
1011   % how about style
1012   \ifconditional\c_strc_registers_text_interaction
1013     \ifempty\currentcolorparameter \else
1014       \resetinteractionparameter\c!color
1015       \resetinteractionparameter\c!contrastcolor
1016     \fi
1017   \fi}
1018
1019\permanent\protected\def\startregisterentries#1% depth
1020  {\ifconditional\c_strc_registers_vertical
1021     \endgraf
1022   \fi
1023   \begingroup
1024   \c_strc_register_level\ifnum#1>\c_strc_registers_maxlevel\c_strc_registers_maxlevel\else#1\fi\relax
1025   \dostarttagged\t!registerentries\empty
1026   \pushmacro\currentregister % bah
1027   \cdef\currentregister{\currentregister:\the\c_strc_register_level}%
1028   \let\currentnestedregister\currentregister
1029   \usenestedregisterstyleandcolor\c!textstyle\c!textcolor
1030   \ifnum\c_strc_register_level>\plusone
1031     \advanceby\leftskip\d_strc_registers_distance\relax
1032   \fi
1033   \d_strc_registers_hangindent\registerparameter\c!distance\relax
1034   \c_strc_registers_hangafter \plusone
1035   \ifconditional\c_strc_registers_vertical
1036     \blank[\v!samepage]%
1037   \fi
1038   \popmacro\currentregister}
1039
1040\permanent\protected\def\stopregisterentries
1041  {\endgraf
1042   \dostoptagged
1043   \endgroup}
1044
1045\permanent\protected\def\startregisterentry#1% todo: level
1046  {\typo_injectors_check_register
1047   \begingroup
1048   \dostarttagged\t!registerentry\empty
1049   \global\setconstant\c_strc_registers_page_state\zerocount
1050   \ifconditional\c_strc_registers_vertical
1051     \hangindent\d_strc_registers_hangindent
1052     \hangafter \c_strc_registers_hangafter
1053   \else
1054     \namedregisterparameter\currentnestedregister\c!left\relax
1055   \fi
1056   \typo_injectors_mark_register}
1057
1058\permanent\protected\def\stopregisterentry
1059  {\ifconditional\c_strc_registers_vertical
1060     \endgraf
1061   \else
1062     \namedregisterparameter\currentnestedregister\c!right\relax
1063   \fi
1064   \global\setconstant\c_strc_registers_page_state\zerocount
1065   \dostoptagged
1066   \endgroup}
1067
1068\permanent\protected\def\startregistersection#1% title
1069  {\dostarttagged\t!registersection\empty
1070   \dostarttagged\t!registertag\empty
1071   \registercharacter{#1}\endgraf
1072   \dostoptagged}
1073
1074\permanent\protected\def\stopregistersection
1075  {\dostoptagged
1076   \endgraf}
1077
1078\permanent\protected\def\startregisterpages
1079  {\begingroup
1080   \dostarttagged\t!registerpages\empty
1081   \useregisterstyleandcolor\c!pagestyle\c!pagecolor
1082   \registerparameter\c!pageleft}
1083
1084\permanent\protected\def\stopregisterpages
1085  {\registerparameter\c!pageright
1086   \dostoptagged
1087   \endgroup}
1088
1089\permanent\protected\def\startregisterseewords
1090  {\begingroup
1091   \dostarttagged\t!registerpage\empty
1092   \useregisterstyleandcolor\c!pagestyle\c!pagecolor}
1093
1094\permanent\protected\def\stopregisterseewords
1095  {\dostoptagged
1096   \endgroup}
1097
1098\permanent\protected\def\registerpageseparator % todo: , configurable
1099  {\ifcase\c_strc_registers_page_state
1100     \hskip\d_strc_registers_distance\relax
1101   \or
1102     \dostarttagged\t!registerseparator\empty
1103     \registerpageseparatorsymbol % page
1104     \dostoptagged
1105   \or
1106     \dostarttagged\t!registerseparator\empty
1107     \registerpageseparatorsymbol % see
1108     \dostoptagged
1109   \fi}
1110
1111\permanent\protected\def\registeronepagerangeseparator
1112  {|\endash|} % todo use \prewordbreak
1113
1114\let\currentregisterrealpage\!!zerocount % todo: more general accessor
1115
1116% keep as reference
1117%
1118% \permanent\protected\def\withregisterpagecommand#1#2#3#4%
1119%   {\ifcase#3\relax
1120%      {\tt [entry\space not\space flushed]}%
1121%    \else
1122%      \def\currentregisterpageindex{#2}%
1123%      \def\currentregisterrealpage{#3}%
1124%      \iflocation
1125%        \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
1126%      \else
1127%        \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
1128%      \fi
1129%    \fi}
1130%
1131% todo: adapt \strc_references_goto_internal to take an extra argument, the ref
1132
1133\permanent\protected\def\withregisterpagecommand#1#2#3#4% #1:processor #2:internal #3:realpage #4:page
1134  {\begingroup
1135   \ifcase#3\relax
1136     \tt [entry\space not\space flushed]%
1137   \else
1138     \def\currentregisterpageindex{#2}%
1139     \def\currentregisterrealpage{#3}%
1140     \ifchknum\currentregisterpageindex\or
1141       \lettonothing\currentregisterpageprefix
1142     \else
1143       \def\currentregisterpageprefix{\clf_registerlabel{\currentregisterpageindex}}%
1144     \fi
1145     \iflocation
1146       \ifempty\currentregisterpageprefix
1147         \strc_references_get_simple_reference{internal(\currentregisterpageindex)}%
1148       \else
1149         \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}%
1150       \fi
1151       \global\lastsavedreferenceattribute\currentreferenceattribute
1152       \c_attr_reference\currentreferenceattribute
1153       \setlocationattributes
1154     \fi
1155     \applyprocessor{#1}{\currentregisterpageprefix\registerparameter\c!pagecommand{#4}}%
1156   \fi
1157   \endgroup}
1158
1159\lettonothing\m_current_register
1160
1161\permanent\protected\def\pushcurrentregister#1%
1162  {\let\m_current_register\currentregister
1163   \cdef\currentregister{#1}}
1164
1165\permanent\protected\def\popcurrentregister
1166  {\let\currentregister\m_current_register}
1167
1168\permanent\protected\def\registeronepage#1#2#3#4#5% #1:class #2:processor content
1169  {\pushcurrentregister{#1}%
1170   \strc_registers_update_page_properties
1171   \ifcstok{\registerparameter\c!pagenumber}\v!no\else
1172     \registerpageseparator
1173     \global\setconstant\c_strc_registers_page_state\plusone
1174     \dostarttagged\t!registerpage\empty
1175     \withregisterpagecommand{#2}{#3}{#4}{#5}%
1176     \dostoptagged
1177   \fi
1178   \popcurrentregister}
1179
1180\newconditional\c_strc_registers_following
1181
1182\appendtoks
1183    \edef\p_compress{\registerparameter\c!compress}%
1184    \ifx\p_compress\v!text
1185      \c_strc_registers_following\conditionaltrue
1186      \letregisterparameter\c!compress\v!yes
1187    \else
1188      \c_strc_registers_following\conditionalfalse
1189    \fi
1190\to \everyplaceregister
1191
1192\permanent\protected\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor  content, content todo: -- configurable
1193  {\pushcurrentregister{#1}%
1194   \strc_registers_update_page_properties
1195   \ifcstok{\registerparameter\c!pagenumber}\v!no\else
1196     \registerpageseparator
1197     \global\setconstant\c_strc_registers_page_state\plusone
1198     \dostarttagged\t!registerpagerange\empty
1199     \dostarttagged\t!registerfrompage\empty
1200     \withregisterpagecommand{#2}{#3}{#4}{#5}%
1201     \dostoptagged
1202     \ifconditional\c_strc_registers_following
1203       \ifnum#3=\numexpr#6-1\relax
1204         \labeltext{following:\s!singular}%
1205       \else
1206         \labeltext{following:\s!plural}%
1207       \fi
1208     \else
1209       \registeronepagerangeseparator
1210       \dostarttagged\t!registertopage\empty
1211       \withregisterpagecommand{#2}{#6}{#7}{#8}%
1212     \fi
1213     \dostoptagged
1214     \dostoptagged
1215   \fi
1216   \popcurrentregister}
1217
1218\permanent\protected\def\defaultregisterentry#1#2#3#4#5% #1:class #2:processor #3:internal #4:seeindex #5:word
1219  {\pushcurrentregister{#1}%
1220   \strc_registers_update_text_properties
1221   \def\currentregisterpageindex{#3}%
1222   \iflocation
1223     \def\currentregisterseeindex{#4}%
1224     \ifconditional\c_strc_registers_text_interaction
1225       \ifchknum\currentregisterpageindex\or
1226         \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]%
1227       \fi
1228     \else
1229       \doapplyregisterentrycommand{#2}{#5}%
1230     \fi
1231   \else
1232     \lettonothing\currentregisterseeindex
1233     \doapplyregisterentrycommand{#2}{#5}%
1234   \fi
1235   \popcurrentregister}
1236
1237\permanent\protected\def\doapplyregisterentrycommand#1#2% processor text
1238  {\dostarttagged\t!registercontent\empty
1239   \ifempty\currentregisterseeindex \else
1240     \dontleavehmode
1241     \dosetdirectpagereference{seeindex:\currentregisterseeindex}% maybe some day we will support an area
1242   \fi
1243   \applyprocessor{#1}{\registerparameter\c!textcommand{\limitedregisterentry{\registerparameter\c!deeptextcommand{#2}}}}%
1244   \dostoptagged}
1245
1246\permanent\protected\def\doapplyregisterseecommand#1#2%
1247  {\ifempty\currentregisterseeindex
1248     \applyprocessor{#1}{#2}%
1249   \orelse\iflocation
1250     \strc_references_goto_internal{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]%
1251   \else
1252     \applyprocessor{#1}{#2}%
1253   \fi}
1254
1255\permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word
1256  {\pushcurrentregister{#1}%
1257   \ifnum#2=\plusone
1258     \registerpageseparator
1259   \fi
1260   \global\setconstant\c_strc_registers_page_state\plustwo
1261   \def\currentregisterpageindex{#5}%
1262   \def\currentregisterseeindex{#6}%
1263   \dostarttagged\t!registersee\empty
1264   \c_strc_registers_page_done\conditionaltrue
1265   \ifchknum\currentregisterseeindex\or
1266     \lettonothing\currentregisterpageprefix
1267   \else
1268     \def\currentregisterpageprefix{\clf_registerlabel{\currentregisterseeindex}}%
1269   \fi
1270   \iflocation
1271     \ifempty\currentregisterpageprefix
1272       \strc_references_get_simple_reference{internal(\currentregisterseeindex)}%
1273     \else
1274       \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}%
1275     \fi
1276     \global\lastsavedreferenceattribute\currentreferenceattribute
1277     \c_attr_reference\currentreferenceattribute
1278     \setlocationattributes
1279   \fi
1280   \ifnum#2=\plusone
1281     \labeltexts\v!see{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}%
1282   \orelse\ifnum#2=#3\relax
1283     \labeltexts\v!and{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}%
1284   \else
1285     ,\space\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}%
1286   \fi
1287   \dostoptagged
1288   \popcurrentregister}
1289
1290\permanent\protected\def\doapplyregistersectioncommand#1#2%
1291  {\ifempty\currentregistersectionindex
1292     \applyprocessor{#1}{#2}%
1293   \orelse\iflocation
1294     \strc_references_goto_internal{\applyprocessor{#1}{#2}}[sectionindex:\currentregistersectionindex]%
1295   \else
1296     \applyprocessor{#1}{#2}%
1297   \fi}
1298
1299\permanent\protected\def\defaultregistersection#1#2#3#4#5#6#7% class i n #4:processor #5:internal #6:sectionindex #7:word
1300  {\pushcurrentregister{#1}%
1301   \ifnum#2=\plusone
1302     \registerpageseparator
1303   \fi
1304   \global\setconstant\c_strc_registers_page_state\plustwo
1305   \def\currentregisterpageindex{#5}%
1306   \dostarttagged\t!registersection\empty
1307   \c_strc_registers_page_done\conditionaltrue
1308   \iflocation
1309     \def\currentregistersectionindex{#6}%
1310   \else
1311     \lettonothing\currentregistersectionindex
1312   \fi
1313   \ifnum#2=\plusone\else
1314      ,\space
1315   \fi
1316   \doapplyregistersectioncommand{#4}{#7}%
1317   \dostoptagged
1318   \popcurrentregister}
1319
1320\aliased\let\registersection  \defaultregistersection
1321\aliased\let\registerseeword  \defaultregisterseeword
1322\aliased\let\registerentry    \defaultregisterentry
1323\aliased\let\registercharacter\defaultregistercharacter
1324
1325%D Experimental:
1326%D
1327%D \starttyping
1328%D \setupregister
1329%D   [index]
1330%D   [pagesegments=1:4,
1331%D    pagemethod=section]
1332%D
1333%D \starttext
1334%D
1335%D     \chapter {one} \section {alpha}
1336%D
1337%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
1338%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
1339%D
1340%D     \chapter {one} \section {alpha}
1341%D
1342%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
1343%D     x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page
1344%D
1345%D     \placeindex[n=1]
1346%D
1347%D \stoptext
1348%D \stoptyping
1349
1350%D A few specific rendering variants:
1351
1352% \def\doregisterpagelocation#1#2%
1353%   {\nextregisterpage
1354%    \hbox to 1em{\hss\doregisterpagehowto{#1}{#2}\hss}}
1355
1356% todo: \installregisterpagehandler
1357
1358% \def\MyRegisterPageCommand#1%
1359%   {#1\currentregisterpageuserdata{whatever}}
1360%
1361% \starttext
1362%     \setregisterentry[index][entries=aaa][whatever=f.] test \index{bbb} test
1363%     \placeregister[index][n=1,pagecommand=\MyRegisterPageCommand]
1364% \stoptext
1365
1366\permanent\def\registerpageuserdata       #1#2{\clf_registeruserdata#1{#2}}
1367\permanent\def\currentregisterpageuserdata    {\registerpageuserdata\currentregisterpageindex} % {#1}
1368
1369% not yet ok : new internal handler names
1370
1371\lettonothing\registerpageseparatorsymbol
1372
1373\permanent\protected\def\registerpagebuttonsymbol
1374  {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax}
1375
1376\installcorenamespace{registersymbol}
1377
1378\defcsname\??registersymbol n\endcsname
1379  {\enforced\frozen\def\registerpageseparatorsymbol{,\space}}
1380
1381\defcsname\??registersymbol a\endcsname
1382  {\enforced\frozen\def\registerpageseparatorsymbol{,\space}} % now done via conversion
1383
1384\defcsname\??registersymbol\v!none\endcsname
1385  {\enforced\frozen\lettonothing\registerpageseparatorsymbol
1386   \enforced\frozen\let\registeronepage\gobblefivearguments
1387   \enforced\frozen\let\registerpagerange\gobbleeightarguments}
1388
1389\defcsname\??registersymbol 1\endcsname
1390  {\enforced\frozen\let\registerpageseparatorsymbol\space
1391   \enforced\frozen\def\registeronepage{\symbol[1]\gobblefivearguments}%
1392   \enforced\frozen\def\registerpagerange{\symbol[1]\gobbleeightarguments}}
1393
1394\defcsname\??registersymbol 2\endcsname
1395  {\enforced\frozen\let\registerpageseparatorsymbol\space
1396   \enforced\frozen\def\registeronepage{\registerpagebuttonsymbol\gobblefivearguments}%
1397   \enforced\frozen\def\registerpagerange{\registerpagebuttonsymbol\gobbleeightarguments}}
1398
1399\protected\def\strc_registers_set_page_rendering
1400  {\ifcstok{\registerparameter\c!pagenumber}\v!no
1401     \enforced\frozen\let\currentregisterpagesymbol\v!none
1402   \else
1403     \enforced\frozen\edef\currentregisterpagesymbol{\registerparameter\c!symbol}%
1404   \fi
1405   \ifempty\currentregisterpagesymbol
1406     \csname\??registersymbol n\endcsname
1407   \orelse\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname
1408     \csname\??registersymbol\currentregisterpagesymbol\endcsname
1409   \else
1410     \enforced\frozen\let\registerpageseparatorsymbol\space
1411     \enforced\frozen\def\registeronepage{\registerparameter\c!symbol\gobblefivearguments}%
1412     \enforced\frozen\def\registerpagerange{\registerparameter\c!symbol\gobbleeightarguments}%
1413   \fi}
1414
1415\appendtoks
1416     \strc_registers_set_page_rendering
1417\to \everyplaceregister
1418
1419%D The linked register code will be reimplemented (not that hard) when it's needed
1420%D again and/or when I'm bored.
1421
1422\permanent          \def\findregisterinternal#1#2#3{\clf_findregisterinternal{#1}{#2}#3\relax}
1423\permanent\protected\def\pageofinternal          #1{\clf_pageofinternal#1\relax}
1424
1425\permanent\protected\def\linkedregisterentrylink#1#2#3#4% tag where before after
1426  {\iflocation
1427     \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax
1428     \ifcase\scratchcounter\else
1429       #3\relax
1430       \goto{\symbol[#2]}[internal(\the\scratchcounter)]%
1431       #4\relax
1432     \fi
1433   \else
1434   % \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax
1435   % \ifcase\scratchcounter\else
1436   %   #3\relax
1437   %   \pageofinternal\scratchcounter
1438   %   #4\relax
1439   % \fi
1440   \fi}
1441
1442\permanent\protected\def\linkedregisterentry#1%
1443  {\dontleavehmode
1444   \begingroup
1445   \setbox\scratchbox\hbox{#1}%
1446   \linkedregisterentrylink\currentregistername\v!previous\relax\nobreakspace
1447   \unhbox\scratchbox
1448   \linkedregisterentrylink\currentregistername\v!next\nobreakspace\relax
1449   \endgroup}
1450
1451\permanent\protected\def\registerpacked#1#2%
1452  {\iflocation
1453     \hskip\d_strc_registers_distance\relax
1454     \nobreak
1455     \ifnum#1=#2\relax
1456       \goto{\symbol[\v!somewhere]}[internal(#1)]%
1457     \else
1458       \goto{\symbol[\v!first]}[internal(#1)]%
1459       \nobreakspace
1460       \goto{\symbol[\v!last]}[internal(#2)]%
1461     \fi
1462   \fi}
1463
1464%D Default index:
1465
1466\defineregister
1467  [\v!index]
1468%  [\v!indices]
1469
1470\stopcontextdefinitioncode
1471
1472\protect \endinput
1473
1474% % maybe also more levels with [entries|keys|processors]:n
1475% %
1476% % \setregisterentry
1477% %   [index]
1478% %   [entries:1=one,
1479% %    entries:2=two,
1480% %    entries:3=three,
1481% %    entries:4=four]
1482% %
1483% % test \blank \placeregister[index][balance=no]
1484%
1485% \def\expanddetokenizedregistervalues#1#2%
1486%   {\edef\expandedregistervalue{\detokenizedregisterparameter{#1:#2}}%
1487%    \ifempty\expandedregistervalue\else
1488%       \letregisterparameter{#1:#2}\expandedregistervalue
1489%       \expandafter\expanddetokenizedregistervalues
1490%       \expandafter#1%
1491%       \expandafter{\the\numexpr#2+1}%
1492%    \fi}%
1493%
1494% \def\expandregistervalues#1#2%
1495%   {\edef\expandedregistervalue{\registerparameter{#1:#2}}%
1496%    \ifempty\expandedregistervalue\else
1497%       \letregisterparameter{#1:#2}\expandedregistervalue
1498%       \expandafter\expandregistervalues
1499%       \expandafter#1%
1500%       \expandafter{\the\numexpr#2+1}%
1501%    \fi}%
1502%
1503% % \def\injectregistervalues#1#2%
1504% %   {\beginlocalcontrol
1505% %    \edef\expandedregistervalue{\registerparameter{#1:\the\numexpr#2}}%
1506% %    \endlocalcontrol
1507% %    \ifempty\expandedregistervalue\else
1508% %       {\expandedregistervalue}%
1509% %       \injectregistervalues#1{#2+1}%
1510% %     \fi}%
1511%
1512% \def\injectregistervalues#1#2%
1513%   {\ifempty{\registerparameter{#1:\the\numexpr#2}}\else
1514%       \expandafter{\lastnamedcs}%
1515%       \injectregistervalues#1{#2+1}%
1516%     \fi}%
1517%
1518% \def\strc_registers_register_page_expand_xml_entries
1519%   {\xmlstartraw
1520%      \beginlocalcontrol
1521%      \expandregistervalues\c!entries1%
1522%      \endlocalcontrol
1523%    \xmlstopraw
1524%    \glet\currentregistercoding\s!xml}
1525%
1526% \def\strc_registers_register_page_expand_yes_entries
1527%   {\beginlocalcontrol
1528%    \expandregistervalues\c!entries1%
1529%    \endlocalcontrol
1530%    \glet\currentregistercoding\s!tex}
1531%
1532% \def\strc_registers_register_page_expand_nop_entries
1533%   {\beginlocalcontrol
1534%    \expanddetokenizesregistervalues\c!entries1%
1535%    \endlocalcontrol
1536%    \glet\currentregistercoding\s!tex}
1537%
1538% \def\strc_registers_register_page_expand_nop_entries
1539%   {\beginlocalcontrol
1540%    \expandregistervalues\c!entries1%
1541%    \endlocalcontrol
1542%    \glet\currentregistercoding\s!tex}
1543%
1544% \def\strc_registers_register_page_expand_xml_keys
1545%   {\xmlstartraw
1546%      \beginlocalcontrol
1547%      \expandregistervalues\c!keys1%
1548%      \endlocalcontrol
1549%    \xmlstopraw}
1550%
1551% \def\strc_registers_register_page_expand_yes_keys
1552%   {\beginlocalcontrol
1553%    \expandregistervalues\c!keys1%
1554%    \endlocalcontrol}
1555%
1556% \def\strc_registers_register_page_expand_processors
1557%   {\beginlocalcontrol
1558%    \expandregistervalues\c!processors1%
1559%    \endlocalcontrol}
1560%
1561% \def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata
1562%   {\begingroup
1563%    \cdef\currentregister{#1}%
1564%    %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
1565%    \setupcurrentregister[#2]%
1566%    \edef\currentregisterlabel     {\registerparameter\c!label}%
1567%    \edef\currentregisterexpansion {\registerparameter\c!expansion}%
1568%    \edef\currentregisterownnumber {\registerparameter\c!ownnumber}%
1569%    \xdef\currentregisterkeys      {\registerparameter\c!keys}%
1570%    \xdef\currentregisterentries   {\registerparameter\c!entries}%
1571%    \xdef\currentregisterprocessors{\registerparameter\c!processors}%
1572%    \xdef\currentregisterxmlsetup  {\registerparameter\c!xmlsetup}%
1573%    \ifempty\currentregisterentries
1574%      \ifx\currentregisterexpansion\s!xml
1575%        \strc_registers_register_page_expand_xml_entries
1576%      \orelse\ifx\currentregisterexpansion\v!yes
1577%        \strc_registers_register_page_expand_yes_entries
1578%      \else
1579%        \strc_registers_register_page_expand_nop_entries
1580%      \fi
1581%    \else
1582%      \ifx\currentregisterexpansion\s!xml
1583%        \strc_registers_register_page_expand_xml
1584%      \orelse\ifx\currentregisterexpansion\v!yes
1585%        \strc_registers_register_page_expand_yes
1586%      \else
1587%        \strc_registers_register_page_expand_nop
1588%      \fi
1589%    \fi
1590%    \ifempty\currentregisterkeys
1591%      \ifx\currentregistercoding\s!xml
1592%        \strc_registers_register_page_expand_xml_keys
1593%      \else
1594%        \strc_registers_register_page_expand_yes_keys
1595%      \fi
1596%    \fi
1597%    \strc_registers_register_page_expand_processors
1598%    \setnextinternalreference
1599%    % we could consider storing register entries in a list which we
1600%    % could then sort
1601%    \glet\currentregistername\currentregister
1602%    \xdef\currentregisternumber{\clf_storeregister % 'own' should not be in metadata
1603%         metadata {%
1604%             name     {\currentregister}%
1605%             coding   {\currentregistercoding}%
1606%         \ifx\currentregisterownnumber\v!yes
1607%             own      {\registerparameter\c!alternative}% can be used instead of pagenumber
1608%         \fi
1609%         \ifx\currentreferencecoding\s!xml
1610%             xmlroot  {\xmldocument} % only useful when text
1611%         \fi
1612%         \ifempty\currentregisterxmlsetup \else
1613%             xmlsetup {\currentregisterxmlsetup}%
1614%         \fi
1615%         }%
1616%         references {%
1617%         \ifempty\currentregisterlabel \else
1618%             label    {\currentregisterlabel}%
1619%         \fi
1620%          %  view     {\interactionparameter\c!focus}%
1621%         }%
1622%         entries {%
1623%             % we need a special one for xml, this is just a single one
1624%             \ifempty\currentregisterentries
1625%                 entries {\injectregistervalues\c!entries1}%
1626%             \else
1627%                 entry {\currentregisterentries}%
1628%             \fi
1629%             \ifempty\currentregisterkeys
1630%                 keys {\injectregistervalues\c!keys1}%
1631%             \else
1632%                 key {\currentregisterkeys}%
1633%             \fi
1634%             \ifempty\currentregisterprocessors
1635%                 processors {\injectregistervalues\c!processors1}%
1636%             \else
1637%                 processor {\currentregisterprocessors}%
1638%             \fi
1639%         }%
1640%         userdata {\detokenize\expandafter{\normalexpanded{#3}}}
1641%    }%
1642%    \clf_setinternalreference
1643%       internal \locationcount
1644%       view     {\interactionparameter\c!focus}%
1645%    \relax % this will change
1646%    \ifx\currentregisterownnumber\v!yes
1647%      \glet\currentregistersynchronize\relax
1648%    \else
1649%      \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
1650%    \fi
1651%    \currentregistersynchronize % here?
1652%    % needs thinking ... bla\index{bla}. will break before the . but adding a
1653%    % penalty is also no solution
1654%    \dostarttagged\t!registerlocation\currentregister
1655%    \c_attr_destination\lastdestinationattribute
1656%    \signalcharacter % no \strut as it will be removed during cleanup
1657%    \dotagregisterlocation
1658%    \dostoptagged
1659%    \endgroup}
1660