strc-ref.mkvi /size: 75 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=strc-ref,
3%D        version=2008.10.20,
4%D          title=\CONTEXT\ Structure Macros,
5%D       subtitle=Cross Referencing,
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% todo: (1) configure references, (2) rendering => with presets
15%
16% \defineconversionset[default][Character,number,Romannumerals,Character][number]
17% \defineseparatorset [default][.,.,--][.]
18% \setuphead[subsection][sectionstopper=),sectionsegments=4:4]
19% \setupreferencestructureprefix[default][prefixsegments=2:4]
20% \setupreferencestructureprefix[figure][default][prefixsegments=3:4]
21% \chapter {One}
22% \section {One}
23% \subsection[sec:test]{Two}
24% See \in[sec:test] and \in[fig:xx] and \in[fig:yy]
25% \placefigure[here][fig:xx]{}{}
26% \placefigure[here][fig:yy]{}{}
27
28\writestatus{loading}{ConTeXt Structure Macros / Cross Referencing}
29
30\registerctxluafile{strc-rsc}{}
31\registerctxluafile{strc-ref}{}
32\registerctxluafile{node-ref}{optimize}
33
34\unprotect
35
36% todo : unknown/illegal reference no arg
37% todo : +n pages check on 'samepage' (contrastcolor)
38% todo : multiple text in reference
39
40% Makes more sense to build action data first, especially now
41% openaction etc are supported.
42%
43% \definespecial\doexecuteactionchain w h
44% \definespecial\dosetgotolocation
45% \definespecial\dosetexecuteJScode
46% ...
47
48%D This module deals with referencing. In \CONTEXT\ referencing is one of the core
49%D features, although at a first glance probably nobody will notice. This is good,
50%D because referencing should be as hidden as possible.
51%D
52%D Before we start implementing functionality we provide a way to set up this
53%D mechanism.
54%D
55%D \showsetup{setupreferencing}
56%D
57%D In interactive documents verbose references don't always make sense (what is a
58%D page number in an unnumbered document). By setting the \type{interaction}
59%D variable, one can influences the way interactive references are set.
60
61\let\referenceprefix\empty
62
63\installcorenamespace{referencing}
64
65\installdirectcommandhandler \??referencing {referencing} % \??referencing
66
67\newif\ifreferencing \referencingtrue
68
69\appendtoks
70    \edef\p_state{\referencingparameter\c!state}%
71    \ifx\p_state\v!start
72      \referencingtrue
73    \else
74      \referencingfalse
75    \fi
76\to \everysetupreferencing
77
78%D In paper documents, referencing comes down to cross referencing, but in
79%D their interactive counterparts, is also involves navigation. Many features
80%D implemented here are therefore closely related to navigation.
81%D
82%D Many \CONTEXT\ commands can optionally be fed with a reference. Such a
83%D reference, when called upon, returns the number of a figure, table, chapter
84%D etc, a piece of text, or a pagenumber.
85%D
86%D There are three ways of defining a reference:
87%D
88%D \starttyping
89%D \pagereference[here]
90%D \textreference[here]{some text}
91%D \stoptyping
92%D
93%D the third alternative combines them in:
94%D
95%D \starttyping
96%D \reference[here]{some text}
97%D \stoptyping
98
99\unexpanded\def\textreference {\dosingleargument\strc_references_text_reference} % no need for \dosingle
100\unexpanded\def\pagereference {\dosingleargument\strc_references_page_reference} % as they're mandate and
101\unexpanded\def\reference     {\dosingleargument\strc_references_full_reference} % never forgotten
102\unexpanded\def\setreference  {\dodoubleargument\strc_references_set_reference } %
103
104% maybe: \let\reference\textreference
105
106\unexpanded\def\showreferences
107  {\enabletrackers[nodes.references.show,nodes.destinations.show]}
108
109%D These are implemented in a low level form as:
110
111\unexpanded\def\strc_references_text_reference          [#labels]{\strc_references_set_named_reference\s!text{#labels}{}}
112\unexpanded\def\strc_references_page_reference          [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}}
113\unexpanded\def\strc_references_full_reference          [#labels]{\strc_references_set_named_reference\s!full{#labels}{}}
114\unexpanded\def\strc_references_set_reference[#labels][#settings]{\strc_references_set_named_reference\s!user{#labels}{#settings}{}}
115
116\unexpanded\def\dosetdirectpagereference#1{\strc_references_set_named_reference\s!page{#1}{}{}} % low level, maybe use _
117
118\unexpanded\def\usereferenceparameter#1% faster local variant
119  {\edef\m_strc_references_asked{#1\c!reference}%
120   \ifx\m_strc_references_asked\empty\else
121     \dosetdirectpagereference\m_strc_references_asked
122   \fi}
123
124%D Actually there is not much difference between a text and a full reference, but
125%D it's the concept that counts. The low level implementation is:
126
127\newcount\lastreferenceattribute
128\newcount\lastdestinationattribute
129
130\def\strc_references_finish#prefix#reference#internal%
131  {\normalexpanded{\clf_deferredenhancereference{#prefix}{#reference}}}
132
133\let\dofinishreference\strc_references_finish % used at lua end
134
135%D This is somewhat tricky: we want to keep the reference with the following word but
136%D that word should also hyphenate. We need to find a better way.
137
138% 0 = nothing
139% 1 = bind to following word
140
141\setnewconstant\c_strc_references_bind_state\plusone
142
143\def\strc_references_inject_before
144  {}
145
146\def\strc_references_inject_after
147  {\ifcase\c_strc_references_bind_state
148     % nothing
149   \or
150     \prewordbreak % to be tested: \removeunwantedspaces\permithyphenation
151   \fi}
152
153
154\unexpanded\def\strc_references_set_named_reference
155  {\ifreferencing
156      \expandafter\strc_references_set_named_reference_indeed
157   \else
158      \expandafter\gobblefourarguments
159   \fi}
160
161\newbox\b_strc_destination_nodes
162
163\unexpanded\def\strc_references_flush_destination_nodes
164  {\ifvoid\b_strc_destination_nodes \else
165     \unhbox\b_strc_destination_nodes
166   \fi}
167
168\def\strc_references_placeholder
169  {\ifx\dotaggedplaceholder\empty\else
170     \c_attr_destination\lastdestinationattribute
171     \dotaggedplaceholder
172   \fi}
173
174\unexpanded\def\strc_references_destination_point_yes
175  {\strc_references_inject_before % new
176   \dostarttagged\t!reference\empty
177   \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
178     \strc_references_flush_destination_nodes
179     \strc_references_placeholder
180     \egroup
181   \dostoptagged
182   \strc_references_inject_after}
183
184\unexpanded\def\strc_references_destination_point_nop
185  {\strc_references_inject_before % new
186   \dostarttagged\t!reference\empty
187   \dontleavehmode\hbox \bgroup
188     \strc_references_flush_destination_nodes
189     \strc_references_placeholder
190   \egroup
191   \dostoptagged
192   \strc_references_inject_after}
193
194\unexpanded\def\strc_references_start_destination_nodes % messy but we need the delay
195  {\setbox\b_strc_destination_nodes\hbox\bgroup}        % also sets lastdestinationattribute
196
197\unexpanded\def\strc_references_stop_destination_nodes
198  {\normalexpanded{\egroup\lastdestinationattribute\the\lastdestinationattribute\relax}}
199
200\unexpanded\def\strc_references_set_named_reference_indeed#kind#labels#userdata#text% labels userdata text -> todo: userdata
201  {\ifreferencing
202     % we could have a more efficient one for page references but for the moment
203     % we don't care too much
204     \edef\currentreferencekind     {#kind}%
205     \edef\currentreferencelabels   {#labels}%
206     \edef\currentreferenceuserdata {#userdata}%
207     \edef\currentreferenceexpansion{\referencingparameter\c!expansion}% {\referenceparameter\c!expansion}
208     \ifx\currentreferencelabels\empty
209       \lastdestinationattribute\attributeunsetvalue
210     \else
211       \ifx\currentreferenceexpansion\s!xml
212         \xmlstartraw
213           \xdef\currentreferencedata{#text}% data, no text else conflict
214         \xmlstopraw
215         \glet\currentreferencecoding\s!xml
216       \else
217         \ifx\currentreferenceexpansion\v!yes
218           \xdef\currentreferencedata{#text}%
219         \else
220           \xdef\currentreferencedata{\detokenize{#text}}%
221         \fi
222         \glet\currentreferencecoding\s!tex
223       \fi
224       % beware, the structures.references.set writes a
225       \setnextinternalreference
226       \strc_references_start_destination_nodes
227       \clf_setdestinationattribute
228            {%
229                references {%
230                    internal  \locationcount
231                  % block     {\currentsectionblock}%
232                    view      {\interactionparameter\c!focus}%
233                \ifx\referenceprefix\empty\else
234                    prefix    {\referenceprefix}%
235                \fi
236                    reference {\currentreferencelabels}%
237                }%
238                metadata {%
239                    kind     {\currentreferencekind}%
240            \ifx\currentreferencekind\s!page\else
241                \ifx\currentreferencecoding\s!xml
242                    xmlroot  {\xmldocument}%
243                \fi
244                    catcodes \catcodetable
245            \fi
246                }%
247            \ifx\currentreferencedata\empty\else
248                entries {%
249                    text {\currentreferencedata}%
250                }%
251            \fi
252            \ifx\currentreferenceuserdata\empty\else
253                userdata {\detokenize{#userdata}}%
254            \fi
255            }%
256       \relax
257       \strc_references_stop_destination_nodes
258     \fi
259   \else
260     \setbox\b_strc_destination_nodes\emptyhbox
261     \lastdestinationattribute\attributeunsetvalue
262   \fi
263   % will become obsolete:
264   \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
265   % will become an option:
266   \ifnum\lastdestinationattribute>\zerocount
267     \strc_references_destination_point_yes
268   \else\ifvoid\b_strc_destination_nodes\else
269     \strc_references_destination_point_nop
270   \fi\fi}
271
272\def\strc_references_set_page_only_destination_attribute#labels% could in fact be fully expandable
273  {\ifreferencing
274     \edef\currentreferencelabels{#labels}%
275     \ifx\currentreferencelabels\empty
276       \setbox\b_strc_destination_nodes\emptyhbox
277       \lastdestinationattribute\attributeunsetvalue
278     \else
279       \strc_references_start_destination_nodes
280       \setnextinternalreference
281       \clf_setdestinationattribute
282            {%
283                references {%
284                    internal  \locationcount
285                 %  block     {\currentsectionblock}%
286                    view      {\interactionparameter\c!focus}%
287                \ifx\referenceprefix\empty\else
288                    prefix    {\referenceprefix}%
289                \fi
290                    reference {\currentreferencelabels}%
291                }%
292                metadata {%
293                    kind {page}%
294                }%
295            }%
296       \relax
297       \strc_references_stop_destination_nodes
298     \fi
299   \else
300     \setbox\b_strc_destination_nodes\emptyhbox
301     \lastdestinationattribute\attributeunsetvalue
302   \fi}
303
304\unexpanded\def\strc_references_direct_full_user#user#labels#text%
305  {\ifreferencing
306     \strc_references_start_destination_nodes
307     \setnextinternalreference
308     \edef\m_strc_references_user{#user}%
309     \edef\m_strc_references_text{#text}%
310     \clf_setdestinationattribute
311        {%
312            references {%
313                internal  \locationcount
314              % block     {\currentsectionblock}%
315                view      {\interactionparameter\c!focus}%
316            \ifx\referenceprefix\empty\else
317                prefix    {\referenceprefix}%
318            \fi
319                reference {#labels}%
320            }%
321            metadata {%
322                kind {\s!full}%
323            }%
324        \ifx\m_strc_references_text\empty \else
325            entries {%
326                text {\m_strc_references_text}%
327            }%
328        \fi
329        \ifx\m_strc_references_user\empty \else
330            userdata {\m_strc_references_user}% \detokenize\expandafter{\normalexpanded{...}}
331        \fi
332        }%
333     \relax
334     \strc_references_stop_destination_nodes
335   \else
336     \setbox\b_strc_destination_nodes\emptyhbox
337     \lastdestinationattribute\attributeunsetvalue
338   \fi
339   % will become obsolete:
340   \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
341   % will become an option:
342   \ifnum\lastdestinationattribute>\zerocount
343     \strc_references_destination_point_yes
344   \else\ifvoid\b_strc_destination_nodes\else
345     \strc_references_destination_point_nop
346   \fi\fi}
347
348\unexpanded\def\strc_references_direct_full
349  {\strc_references_direct_full_user\empty}
350
351\let\dodirectfullreference\strc_references_direct_full % for at lua end (no longer)
352
353\def\strc_references_set_page_only_destination_box_attribute#cs#labels%
354  {\strc_references_set_page_only_destination_attribute{#labels}%
355   \ifnum\lastdestinationattribute>\zerocount
356     \edef#cs{attr \destinationattribute\number\lastdestinationattribute}%
357   \else
358     \let#cs\empty
359   \fi}
360
361%D It's about time to clean up references .. stable enough now.
362
363\unexpanded\def\boxreference[#1]%
364  {\begingroup
365   \dowithnextbox
366    {\strc_references_set_page_only_destination_attribute{#1}%
367     \hpack % \hbox
368       \ifnum\lastdestinationattribute=\attributeunsetvalue\else attr \destinationattribute \lastdestinationattribute \fi
369       {\box\b_strc_destination_nodes\box\nextbox}%
370     \endgroup}}
371
372\unexpanded\def\hboxreference[#1]{\boxreference[#1]\hbox}
373\unexpanded\def\vboxreference[#1]{\boxreference[#1]\vbox}
374
375% \ifx\currentdestinationattribute\empty
376%   \begingroup\c_attr_destination\currentdestinationattribute\emptyhbox\endgroup % todo
377% \fi
378
379\def\defaultreferencepage#text{[[[#text]]]}
380\def\defaultreferencetext#text{[[[#text]]]}
381
382%D For internal usage:
383
384\def\strc_references_set_simple_reference#label%
385  {\iflocation
386     \strc_references_start_destination_nodes
387     \setnextinternalreference
388     \clf_setdestinationattribute
389        {%
390            references {%
391                view      {\interactionparameter\c!focus}%
392            \ifx\referenceprefix\empty\else
393                prefix    {\referenceprefix}%
394            \fi
395                reference {#label}%
396                internal  \locationcount
397            }%
398            metadata {%
399                kind {\s!page}%
400            }%
401        }%
402     \relax
403     \strc_references_stop_destination_nodes
404     \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
405   \else
406     \setbox\b_strc_destination_nodes\emptyhbox
407     \xdef\currentdestinationattribute{\number\attributeunsetvalue}%
408   \fi}
409
410\def\strc_references_set_simple_internal_reference#label% no prefix
411  {\iflocation
412     \strc_references_start_destination_nodes
413     \setnextinternalreference
414     \clf_setdestinationattribute
415        {%
416            references {%
417                view      {\interactionparameter\c!focus}%
418                reference {#label}%
419                internal  \locationcount
420            }%
421            metadata {%
422                kind {\s!page}%
423            }%
424        }%
425     \relax
426     \strc_references_stop_destination_nodes
427     \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
428   \else
429     \setbox\b_strc_destination_nodes\emptyhbox
430     \xdef\currentdestinationattribute{\number\attributeunsetvalue}%
431   \fi}
432
433\def\strc_references_get_simple_reference#label%
434  {\iflocation
435     \clf_injectreference
436        {\referenceprefix}%
437        {#label}%
438        {%
439            height \ht\strutbox
440            depth  \dp\strutbox
441            \extrareferencearguments
442        }%
443     \relax
444     \xdef\currentreferenceattribute{\number\lastreferenceattribute}%
445   \else
446     \xdef\currentreferenceattribute{\number\attributeunsetvalue}%
447   \fi}
448
449%D \macros
450%D   {contentreference}
451%D
452%D \starttyping
453%D \setupinteraction
454%D   [state=start,
455%D    focus=standard]
456%D
457%D \setupheader
458%D   [state=stop]
459%D
460%D  See page \goto{page 2}[page2] \page
461%D
462%D  \contentreference
463%D    [page2]
464%D    [offset=1cm,toffset=2cm,frame=on]
465%D    {\externalfigure[cow.pdf][factor=fit]}
466%D
467%D \stoptyping
468
469\unexpanded\def\contentreference
470  {\hbox\bgroup
471   \dodoubleempty\strc_references_content_pickup}
472
473\def\strc_references_content_pickup
474  {\ifsecondargument
475     \expandafter\strc_references_content_pickup_yes
476   \else
477     \expandafter\strc_references_content_pickup_nop
478   \fi}
479
480\def\strc_references_content_pickup_yes[#1][#2]%
481 {\dowithnextbox{\strc_references_content_yes_finish{#1}{#2}}\hbox}
482
483\def\strc_references_content_pickup_nop[#1][#2]%
484 {\dowithnextbox{\strc_references_content_nop_finish{#1}{#2}}\hbox}
485
486\def\strc_references_content_yes_finish#1#2%
487  {\scratchwidth \wd\nextbox
488   \scratchheight\ht\nextbox
489   \scratchdepth \dp\nextbox
490   \setbox\nextbox\hpack
491     {\framed[\c!frame=\v!off,#2]{\box\nextbox}}%
492   \strc_references_set_simple_reference{#1}%
493   \setbox\nextbox\hpack attr \destinationattribute \currentdestinationattribute % \hpack ?
494     {\strc_references_flush_destination_nodes
495      \box\nextbox}%
496   \setbox\nextbox\hpack{\box\nextbox}%
497   \wd\nextbox\scratchwidth
498   \ht\nextbox\scratchheight
499   \dp\nextbox\scratchdepth
500   \box\nextbox
501   \egroup}
502
503\def\strc_references_content_nop_finish#1#2%
504  {\strc_references_set_simple_reference{#1}%
505   \hpack attr \destinationattribute \currentdestinationattribute % \hpack ?
506     {\strc_references_flush_destination_nodes
507      \box\nextbox}%
508   \egroup}
509
510%D \macros
511%D   {everyreference}
512%D
513%D For rather tricky purposes, one can assign sanitizing macros to \type
514%D {\everyreference} (no longer that relevant).
515
516\newevery \everyreference \relax
517
518%D This is really needed, since for instance Polish has a different alphabet and
519%D needs accented entries in registers.
520
521\appendtoks
522    \cleanupfeatures
523\to \everyreference
524
525%D We did not yet discuss prefixing. Especially in interactive documents, it's not
526%D always easy to keep track of duplicate references. The prefix mechanism, which we
527%D will describe later on, solves this problem. By (automatically) adding a prefix
528%D one keeps references local, but the global ones in view. To enable this feature,
529%D we explictly split the prefix from the reference.
530
531\let\referenceprefix\empty
532
533%D For a long time the only way to access an external file was to use the file
534%D prefix (\type {somefile::}. However, when you split up a document, redefining the
535%D references may be such a pain, that another approach is feasible. By setting the
536%D \type {autofile} variable to \type {yes} or \type {page}, you can access the
537%D reference directly.
538%D
539%D \starttabulate[||||]
540%D \NC filename::tag \NC page(filename::pnum) \NC tag     \NC\NR
541%D \NC   $\star$     \NC                      \NC         \NC\NR
542%D \NC   $\star$     \NC $\star$              \NC $\star$ \NC\NR
543%D \NC               \NC $\star$              \NC         \NC\NR
544%D \stoptabulate
545
546\unexpanded\def\usereferences[#filename]{} % obsolete
547
548%D As mentioned we will also use the cross reference mechanism for navigational
549%D purposes. The main reason for this is that we want to treat both categories
550%D alike:
551%D
552%D \starttyping
553%D \goto{go back}[PreviousJump]
554%D \goto{colofon}[colofon page]
555%D \stoptyping
556%D
557%D Here \type{PreviousJump} is handled by the viewer, while the
558%D \type{colofon page} reference is, apart from hyperlinking, a
559%D rather normal reference.
560%D
561%D We already saw that cross refences are written to and read from a file. The pure
562%D navigational ones don't need to be written to file, but both for fast processing
563%D and transparant integration, they are saved internally as a sort of reference. We
564%D can easily distinguish such system references from real cross reference ones by
565%D their tag.
566%D
567%D We also use the odd/even characteristic to determine the page state.
568
569\let\currentrealreference      \empty
570\let\currentpagereference      \empty
571\let\currenttextreference      \empty
572\let\currentreferenceorder     \empty
573\let\currentsubtextreference   \empty
574\let\currentsubsubtextreference\empty
575
576\newcount\referencehastexstate % set in backend
577
578% referencepagestate:
579%
580% 0 = no page ref, 1=same page, 2=before, 3=after
581
582%D Cross references appear as numbers (figure~1.1, chapter~2) or pagenumbers
583%D (page~2, page 3--2), and are called with \type {\in} and \type {\at}. In
584%D interactive documents we also have \type {\goto}, \type {\button} and alike.
585%D These are more versatile and look like:
586%D
587%D \starttyping
588%D \goto[reference]
589%D \goto[outer reference::]
590%D \goto[outer reference::inner reference]
591%D \goto[operation(argument)]
592%D \goto[operation(action{argument,argument})]
593%D \goto[action]
594%D \goto[action{argument}]
595%D \stoptyping
596%D
597%D The first one is a normal reference, the second and third are references to a
598%D file or \URL. The brace delimited references for instance refer to a \JAVASCRIPT.
599%D The last example shows that we can pass arguments to the actions.
600%D
601%D Now we've come to the testing step. As we can see below, this macro does bit more
602%D than testing: it also resolves the reference. This means that whenever we test
603%D for the existance of a reference at an outer level, we have all the relevant
604%D properties of that reference avaliable inside the true branche~(\type {#2}).
605%D
606%D The prefix has to do with localizing references. When a prefix is set, looking
607%D for a reference comes to looking for the prefixed one, and when not found,
608%D looking for the non prefixed one. Consider for instance the prefix set to \type
609%D {sidetrack}.
610%D
611%D \starttyping
612%D \pagereference[important]
613%D \pagereference[unimportant]
614%D \setupreferencing[prefix=sidetrack]
615%D \pagereference[important]
616%D \stoptyping
617%D
618%D results in saving (writing) the references
619%D
620%D \starttyping
621%D ...{}{important}
622%D ...{}{unimportant}
623%D ...{sidetrack}{important}...
624%D \stoptyping
625%D
626%D Now when we call for \type{unimportant}, we will indeed get the pagenumber
627%D associated to this reference. But when we call for \type{important}, while the
628%D prefix is still set, we will get the pagenumber bound to the prefixed one.
629%D
630%D {\em Some day, when processing time and memory are no longer
631%D performance factors, we will introduce multi||level
632%D prefixes.}
633%D
634%D Before we start analyzing, I introduce a general definition macro. Consider:
635%D
636%D \starttyping
637%D \goto{do}[JS(My_Script{"test",123}),titlepage]
638%D \stoptyping
639%D
640%D This can also be achieved by:
641%D
642%D \starttyping
643%D \definereference[startup][JS(My_Script{"test",123}),titlepage]
644%D \goto{do}[startup]
645%D \stoptyping
646%D
647%D Now is this is a handy feature or not?
648%D
649%D \showsetup{definereference}
650%D
651%D We can trace references by setting the next switch to true.
652
653\unexpanded\def\definereference
654  {\dodoubleempty\strc_references_define_reference}
655
656\def\strc_references_define_reference[#name][#specification]%
657  {\clf_definereference{\referenceprefix}{#name}{\detokenize{#specification}}}
658
659\unexpanded\def\resetreference[#name]%
660  {\clf_resetreference{\referenceprefix}{#name}}
661
662\def\setpagereference#name#specification% hm,. low level ?
663  {\clf_definereference{}{#name}{\v!page(\detokenize{#specification}}} % is detokenize needed here?
664
665%D Chained references are defined as:
666%D
667%D \starttyping
668%D \goto{somewhere}[JS(somescript),nextpage,JS(anotherscript)]
669%D \stoptyping
670%D
671%D Actually supporting chains is up to the special driver. Here we only provide the
672%D hooks.
673
674%D \macros
675%D   {highlighthyperlinks}
676%D
677%D The next switch can be used to make user hyperlinks are not highlighted when
678%D clicked on.
679
680\newconditional\highlighthyperlinks \settrue\highlighthyperlinks
681
682%D \macros
683%D   {gotonewwindow}
684%D
685%D To make the {\em goto previous jump} feature more convenient when using more than
686%D one file, it makes sense to force the viewer to open a new window for each file
687%D opened.
688
689\newconditional\gotonewwindow \setfalse\gotonewwindow
690
691\def\expandtexincurrentreference % will happen in lua some time
692  {\ifcase\referencehastexstate\else\clf_expandcurrentreference\fi}
693
694\def\expandreferenceoperation#tag#content{\clf_setreferenceoperation#tag{#content}}
695\def\expandreferencearguments#tag#content{\clf_setreferencearguments#tag{#content}}
696
697\def\doifelsereferencefound#label#yes#nop%
698  {\clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
699     {\expandtexincurrentreference
700      #yes}%
701     {#nop}}
702
703\let\doifreferencefoundelse \doifelsereferencefound
704
705%D The tester only splits the reference in components but does not look into them.
706%D The following macro does a preroll and determines for instance the current real
707%D reference pagenumber. The \type {\currentrealreference} macro does the same so
708%D unless one wants to use the pagestate the next macro seldom needs to be called.
709%D
710%D The inner case is simple. Only two cases have to be taken
711%D care of:
712%D
713%D \starttyping
714%D \goto{some text}[reference]
715%D \goto{some text}[prefix:reference]
716%D \stoptyping
717%D
718%D References to other files however are treated strict or tolerant, depending on
719%D their loading and availability:
720%D
721%D \starttyping
722%D \useexternaldocument[somefile][filename][a nice description]
723%D
724%D \goto{checked   reference}[somefile::reference]
725%D \goto{unchecked reference}[somefile::]
726%D \goto{unchecked reference}[anotherfile::reference]
727%D \stoptyping
728%D
729%D An unknown reference is reported on the screen, in the log file and, when
730%D enabled, in the left margin of the text.
731
732\let\unknownreference\gobbleoneargument
733
734%D When a reference is not found, we typeset a placeholder (two glyphs are often
735%D enough to represent the reference text).
736
737\def\dummyreference{{\tttf ??}}
738\def\emptyreference{{\tttf !!}}
739
740\installtextracker
741  {structures.referencing.show}
742  {\let\strc_references_dummy\strc_references_dummy_yes}
743  {\let\strc_references_dummy\strc_references_dummy_nop}
744
745\def\strc_references_dummy_nop
746  {\dummyreference}
747
748\def\strc_references_dummy_yes
749  {\dummyreference
750   \margindata
751     [\referencingparameter\c!labelalternative]% alternative?
752     [\c!style=\referencingparameter\c!labelstyle,
753      \c!color=\referencingparameter\c!labelcolor]
754     {\askedreference}}
755
756\let\strc_references_dummy\strc_references_dummy_nop
757
758\setupreferencing
759  [\c!labelalternative=\v!inleft,
760         \c!labelcolor=darkred,
761         \c!labelstyle=\smallinfofont]
762
763%D To prevent repetitive messages concerning a reference being defined, we set such
764%D an unknown reference to an empty one after the first encounter.
765%D
766%D Apart from cross references supplied by the user, \CONTEXT\ generates cross
767%D references itself. Most of them are not saved as a reference, but stored with
768%D their source, for instance a list or an index entry. Such automatically
769%D generated, for the user invisible, references are called {\em internal
770%D references}. The user supplied ones are labeled as {\em external references}.
771%D
772%D A second important characteristic is that when we want to support different
773%D backends (viewers), we need to support named destinations as well as page
774%D numbers. I invite readers to take a glance at the special driver modules to
775%D understand the fine points of this. As a result we will deal with {\em locations}
776%D as well as {\em real page numbers}. We explictly call this pagenumber a real one,
777%D because it is independant of the page numbering scheme used in the document.
778%D
779%D One of the reasons for \CONTEXT\ being the first \TEX\ base macropackage to
780%D support sophisticated interactive \PDF\ files, lays in the mere fact that real
781%D page numbers are available in most two pass data, like references, list data and
782%D index entries.
783%D
784%D We will speak of \type {thisis...} when we are marking a location, and
785%D \type {goto...} when we point to such a location. The latter one can be seen as a
786%D hyperlink to the former one. In the next macros one we use constructs like:
787%D
788%D \starttyping
789%D \dostart...
790%D \dostop...
791%D \stoptyping
792%D
793%D The flag \type {\iflocation} signals if we're in interactive mode.
794
795\ifdefined\buttonheight \else \newdimen\buttonheight \fi
796\ifdefined\buttonwidth  \else \newdimen\buttonwidth  \fi
797
798%D Internal references can best be set using the next few macros. Setting such
799%D references to unique values is completely up to the macros that call them.
800%D
801%D \starttyping
802%D \thisissomeinternal{tag}{identifier}
803%D \gotosomeinternal  {tag}{identifier}{pagenumber}{text}
804%D \stoptyping
805%D
806%D We could do this in \LUA\ \unknown
807
808\newif   \iflocation
809\newcount\locationcount
810\newcount\locationorder
811\newbox  \locationbox
812
813\def\nextinternalreference     {\the\locationcount}
814\def\nextinternalorderreference{\the\locationorder}
815
816\def\setnextinternalreference
817  {\global\advance\locationcount\plusone}
818
819\def\setnextinternalreferences#kind#name% plural
820  {\clf_setnextinternalreference{#kind}{#name}}
821
822\def\getinternalorderreference#kind#name%
823  {\clf_currentreferenceorder{#kind}{#name}}
824
825\def\thisissomeinternal#kind#name% only for old time sake, will go away
826  {\begingroup
827   \clf_setinternalreference
828     reference {#kind:#name}% no view
829   \relax
830   \hpack attr \destinationattribute\lastdestinationattribute{}%
831   \endgroup}
832
833\installcorenamespace{savedinternalreference}
834
835\letvalue{\??savedinternalreference\s!default}\!!zerocount
836
837\unexpanded\def\storeinternalreference#1#2%
838  {\setxvalue{\??savedinternalreference\currentstructurename}{\number#2}}
839
840\newconditional\preferpagereferences
841
842\def\gotosomeinternal#kind#name#target#text%
843  {\ifconditional\preferpagereferences
844     \directgoto{#text}[page(#target)]%
845   \else
846     \directgoto{#text}[#kind:#name]%
847   \fi}
848
849\def\gotonextinternal#text#target%
850  {\directgoto{#text}[internal(#target)]}
851
852%D In this module we define three system references: one for handling navigational,
853%D viewer specific, commands, another for jumping to special pages, like the first
854%D or last one, and a third reference for linking tree like lists, like tables of
855%D contents. The latter two adapt themselves to the current state.
856%D
857%D An example of an action is:
858%D
859%D \starttyping
860%D \goto{some action}[PreviousJump]
861%D \stoptyping
862%D
863%D as well as:
864%D
865%D \starttyping
866%D \goto{some text}[\v!action(PreviousJump]
867%D \stoptyping
868%D
869%D One can also activate an automatic prefix mechanism. By setting the
870%D \type {\prefix} variable to \type {+}, the prefix is incremented, when set to
871%D \type {-} or empty, the prefix is reset. Other values become the prefix.
872
873\newcount\prefixcounter
874
875\newconditional\autocrossfilereferences
876
877\appendtoks
878    \edef\p_autofile{\referencingparameter\c!autofile}%
879    \ifx\p_autofile\v!yes
880      \settrue \autocrossfilereferences
881    \else
882      \setfalse\autocrossfilereferences
883    \fi
884\to \everysetupreferencing
885
886\appendtoks
887    \edef\p_export{\referencingparameter\c!export}%
888    \ifx\p_export\v!yes
889      \clf_exportreferences
890    \fi
891\to \everygoodbye
892
893\unexpanded\def\setupglobalreferenceprefix[#prefix]%
894  {\xdef\referenceprefix{#prefix}}
895
896\unexpanded\def\globalpushreferenceprefix#prefix%
897  {\xdef\referenceprefix{\clf_pushreferenceprefix{#prefix}}}
898
899\unexpanded\def\globalpopreferenceprefix
900  {\xdef\referenceprefix{\clf_popreferenceprefix}}
901
902\unexpanded\def\pushreferenceprefix#prefix%
903  {\edef\referenceprefix{\clf_pushreferenceprefix{#prefix}}}
904
905\unexpanded\def\popreferenceprefix
906  {\edef\referenceprefix{\clf_popreferenceprefix}}
907
908\def\m_strc_references_prefix_yes{+}
909\def\m_strc_references_prefix_nop{-}
910
911\unexpanded\def\setupreferenceprefix[#prefix]%
912  {\edef\p_prefix{#prefix}%
913   \ifx\p_prefix\empty
914     \let\referenceprefix\empty
915   \else\ifx\p_prefix\m_strc_references_prefix_yes
916     \letreferencingparameter\c!prefix\s!unknown
917     \global\advance\prefixcounter\plusone
918     \edef\referenceprefix{\the\prefixcounter}%
919   \else\ifx\p_prefix\m_strc_references_prefix_nop
920     \letreferencingparameter\c!prefix\s!unknown
921     \let\referenceprefix\empty
922   \else\ifx\p_prefix\s!unknown
923     % forget about it
924   \else
925     \let\referenceprefix\p_prefix
926   \fi\fi\fi\fi}
927
928\appendtoks
929    \setupreferenceprefix[\referencingparameter\c!prefix]
930\to \everysetupreferencing
931
932%D We can typeset a reference using \type {\in}, \type {\at} and \type {\about} and
933%D goto specific locations using \type {\goto}. The last one does not make that much
934%D sense in a paper document. To complicate things, \PLAIN\ \TEX\ also implements an
935%D \type {\in} but fortunately that one only makes sense in math mode.
936%D
937%D Typesetting the reference is a bit more complicated than one would at first sight
938%D expect. This is due to the fact that we distinguish three (five) alternative
939%D calls:
940%D
941%D \placefigure
942%D   [here][three calls]
943%D   {Three alternatives reference calls.}
944%D   {\startcombination[1*3]
945%D      {\framed{\type{ \in }}} {a}
946%D      {\framed{\type{ \at }}} {b}
947%D      {\framed{\type{\goto}}} {c}
948%D    \stopcombination}
949%D
950%D \startbuffer
951%D \in figure[fig:three calls]
952%D \in{figure}[fig:three calls]
953%D \in figure a[fig:three calls]
954%D \in{figure}{a}[fig:three calls]
955%D figure~\in[fig:three calls]
956%D \stopbuffer
957%D
958%D \typebuffer
959%D
960%D This turns up as:
961%D
962%D \startlines
963%D \getbuffer
964%D \stoplines
965%D
966%D The dual \type {{}} results in a split reference. In a document meant for paper,
967%D one is tempted to use the last (most straightforward) alternative. When a
968%D document is also meant voor electronic distribution, the former alternatives have
969%D preference, because everything between the \type {\in} and~\type {[} becomes
970%D active (and when asked for, typeset in a different color and typeface).
971
972\appendtoks
973    \ifdefined\in    \let\normalmathin   \in    \unexpanded\def\in   {\mathortext\normalmathin   \strc_references_in   } \else \let\in   \strc_references_in    \fi
974    \ifdefined\at    \let\normalmathat   \at    \unexpanded\def\at   {\mathortext\normalmathat   \strc_references_at   } \else \let\at   \strc_references_at    \fi
975    \ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\strc_references_about} \else \let\about\strc_references_about \fi
976    \ifdefined\from  \let\normalmathfrom \from  \unexpanded\def\from {\mathortext\normalmathfrom \strc_references_from } \else \let\from \strc_references_from  \fi
977    \ifdefined\over  \let\normalmathover \over  \unexpanded\def\over {\mathortext\normalmathover \strc_references_about} \else \let\over \strc_references_about \fi
978\to \everydump
979
980           \def\filterreference  #key{\clf_filterreference{#key}} % no checking, expanded
981\unexpanded\def\getreferenceentry#key{\clf_filterreference{#key}} % no checking, unexpanded
982
983\def\currentreferencenumber  {\clf_filterreference{number}}
984\def\currentreferencepage    {\clf_filterreference{page}}
985\def\currentreferencetitle   {\clf_filterreference{title}}
986\def\currentreferencetext    {\clf_filterreference{text}}
987\def\currentreferencedefault {\clf_filterreference{default}}
988\def\currentreferencerealpage{\clf_filterreference{realpage}}
989
990%D The most straightforward way of retrieving references is using \type {\ref}.
991
992\unexpanded\def\getreference % checking, unexpanded
993  {\dodoubleargument\strc_references_get_reference}
994
995\def\strc_references_get_reference[#key][#label]% #key = number page title text default realpage ...
996  {\ifsecondargument
997     \doifelsereferencefound{#label}{\clf_filterreference{#key}}\strc_references_dummy
998   \else
999     \strc_references_dummy
1000   \fi}
1001
1002\let\ref\getreference
1003
1004%D Special cases:
1005
1006\unexpanded\def\strc_references_about[#label]%
1007  {\dontleavehmode
1008   \begingroup
1009   \enforced\let\crlf\space
1010   \enforced\let\\\space
1011   \postponenotes % might go
1012   \referencingparameter\c!left
1013   \doifelsereferencefound{#label}
1014     {\goto{\limitatetext\currentreferencetitle{\referencingparameter\c!width}\unknown}[#label]}% not so efficient (dup lookup)
1015     {}% todo
1016   \flushnotes % might go
1017   \referencingparameter\c!right
1018   \endgroup}
1019
1020%D The previously discussed setup macro lets us specify the representation of
1021%D references. A symbol reference does not show the specific data, like the number
1022%D of a figure, but shows one of: \hbox {$^\goforwardcharacter$
1023%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending on the direction to
1024%D go.
1025%D
1026%D \starttyping
1027%D ... \somewhere{backward text}{forward text}[someref] ...
1028%D ... \atpage[someref] ...
1029%D \stoptyping
1030
1031% standard      detail
1032%
1033% 0 = unknown   unknown
1034% 1 = same      on same page
1035% 2 = before    preceding page
1036% 3 = after     following page
1037%
1038% 4 = above     above on same page
1039% 5 = below     below on same page
1040
1041% todo: optimize for use in pagebody
1042% todo: maybe make it optional
1043
1044% \setuppagenumbering[alternative=doublesided]
1045% \setupreferencing  [doublesided=no] % yes is default
1046%
1047% \somewhere{backward}{foreward}[label]
1048% \someplace{preceding}{backward}{current}{foreward}{following}[label]
1049% \atpage[#label]
1050% \doifcheckedpagestate{label}{preceding}{backward}{current}{foreward}{following}{otherwise}
1051%
1052% \dorecurse {20} {
1053%     \placefigure[here][fig:#1]{}{\externalfigure[dummy]}
1054%     \dorecurse {20} {
1055%         ##1: \atpage[fig:##1] /
1056%         \doifcheckedpagestate
1057%             {fig:##1}
1058%             {preceding}{backward}{current}{foreward}{following}
1059%             {otherwise}
1060%     }
1061% }
1062
1063\newcount      \nofreferencestates
1064\newconditional\pagestatespread
1065
1066\appendtoks
1067    \doifelse{\referencingparameter\c!doublesided}\v!yes\settrue\setfalse\pagestatespread
1068\to \everysetupreferencing
1069
1070\setupreferencing
1071  [\c!doublesided=\v!yes]
1072
1073\def\referencepagestate
1074  {\numexpr\clf_referencepagestate
1075     {rst::\number\nofreferencestates}%
1076   \relax}
1077
1078\def\referencepagedetail
1079   {\numexpr\clf_referencepagedetail
1080      {rst::\number\nofreferencestates}%
1081      true %
1082      \ifconditional\pagestatespread false\ifdoublesided true\else false\fi\fi
1083    \relax}
1084
1085\def\referencerealpage
1086  {\clf_referencerealpage}
1087
1088\def\referencecolumnnumber
1089  {\clf_referencecolumn}
1090
1091% So we need : instead of \ but that's only lmtx:
1092%
1093% \def\referencecolumnnumber
1094%   {\numexpr\dimexpr\clf_referenceposx-\cutspace\relax:\dimexpr\makeupwidth/\nofcolumns\relax+\plusone\relax}
1095%
1096% Tacos patch of the older one, kept here as illustration
1097%
1098% \def\referencecolumnnumber
1099%   {\numexpr
1100%       \dimexpr\clf_referenceposx-\cutspace-\makeupwidth/(2*\nofcolumns)\relax
1101%      /\dimexpr                             \makeupwidth/   \nofcolumns \relax
1102%      +\plusone
1103%    \relax}
1104
1105
1106\unexpanded\def\tracedpagestate
1107  {{\blue\tttf(\ifcase\referencepagedetail unknown\or same\or previous\or next\or above\or below\else unknown\fi)}}
1108
1109\unexpanded\def\markreferencepage
1110  {\dontleavehmode\begingroup
1111   \iftrialtypesetting
1112     % issue warning that not stable
1113   \else
1114     % needs checking ... but probably never in trialmode
1115     \global\advance\nofreferencestates\plusone
1116     \xypos{rst::\number\nofreferencestates}%
1117     % \tracedpagestate
1118   \fi
1119   \endgroup}
1120
1121\unexpanded\def\doifcheckedpagestate#label% #preceding#backward#current#foreward#following#otherwise%
1122  {\doifelsereferencefound{#label}\strc_references_handle_page_state_yes\strc_references_handle_page_state_nop}
1123
1124\let\strc_references_handle_page_state_nop\sixthofsixarguments
1125
1126\def\strc_references_handle_page_state_yes
1127  {\markreferencepage
1128   \ifcase\referencepagedetail\relax
1129     \expandafter\sixthofsixarguments \or
1130     \expandafter\thirdofsixarguments \or
1131     \expandafter\firstofsixarguments \or
1132     \expandafter\fifthofsixarguments \or
1133     \expandafter\secondofsixarguments\or
1134     \expandafter\fourthofsixarguments\else
1135     \expandafter\sixthofsixarguments \fi}
1136
1137\unexpanded\def\referencesymbol
1138  {\hpack\bgroup
1139     \strut
1140     \markreferencepage
1141     \high
1142       {\setupsymbolset[\interactionparameter\c!symbolset]%
1143        \symbol[\ifcase\referencepagedetail\v!somewhere\or\v!nowhere\or\v!previous\or\v!next\or\v!previous\or\v!next\else\v!somewhere\fi]}%
1144   \egroup}
1145
1146%D Hereafter the \type {\ignorespaces} binds the state node to next character (more likely
1147%D than a preceding one) and one can always add an explicit space.
1148
1149\unexpanded\def\somewhere#backward#foreward#dummy[#label]% #dummy gobbles space around #foreward
1150  {\doifcheckedpagestate{#label}%
1151     {\goto{#backward}[#label]}%
1152     {\goto{#backward}[#label]}%
1153     {\ignorespaces}%
1154     {\goto{#foreward}[#label]}%
1155     {\goto{#foreward}[#label]}%
1156     {#label}}%
1157
1158\unexpanded\def\someplace#preceding#backward#current#foreward#following#dummy[#label]% #dummy gobbles space around #foreward
1159  {\doifcheckedpagestate{#label}%
1160     {\doifelsenothing{#preceding}{\goto{#preceding}[#label]}\ignorespaces}%
1161     {\doifelsenothing {#backward}{\goto {#backward}[#label]}\ignorespaces}%
1162     {\doifelsenothing  {#current}{\goto  {#current}[#label]}\ignorespaces}%
1163     {\doifelsenothing {#foreward}{\goto {#foreward}[#label]}\ignorespaces}%
1164     {\doifelsenothing{#following}{\goto{#following}[#label]}\ignorespaces}%
1165     {#label}}
1166
1167\unexpanded\def\atpage[#label]% todo
1168  {\doifcheckedpagestate{#label}%
1169     {\goto{\labeltext\v!precedingpage}[#label]}%
1170     {\goto{\labeltext\v!hencefore}[#label]}%
1171     {\ignorespaces}%
1172     {\goto{\labeltext\v!hereafter}[#label]}%
1173     {\goto{\labeltext\v!followingpage}[#label]}%
1174     {\goto{\labeltexts\v!page\strc_references_dummy}[#label]}}
1175
1176% Someone requested this but in retrospect didn't need it so we keep it as example.
1177% Beware: a node is injected which is why we add ignorespaces!
1178%
1179% \unexpanded\def\strc_references_conditional#action#text[#condition]#dummy[#label]%
1180%   {\doifcheckedpagestate{#label}%
1181%      {\doifelse{#condition}\v!precedingpage{#action{#text}[#label]}\ignorespaces}%
1182%      {\doifelse{#condition}\v!hencefore    {#action{#text}[#label]}\ignorespaces}%
1183%      {\doifelse{#condition}\v!current      {#action{#text}[#label]}\ignorespaces}%
1184%      {\doifelse{#condition}\v!hereafter    {#action{#text}[#label]}\ignorespaces}%
1185%      {\doifelse{#condition}\v!followingpage{#action{#text}[#label]}\ignorespaces}%
1186%      {#label}}
1187%
1188% \unexpanded\def\conditionalat   {\strc_references_conditional\at}
1189% \unexpanded\def\conditionalin   {\strc_references_conditional\in}
1190% \unexpanded\def\conditionalabout{\strc_references_conditional\about}
1191
1192%D The other alternatives just conform their names: only the label, only the text, or the
1193%D label and the text.
1194
1195% \dounknownreference -> \dummyreference
1196
1197\def\symbolreference[#label]% for old times sake
1198  {\goto{\referencesymbol}[#label]}
1199
1200% \referencecontentmode 0=all 1=label 2=text 3=symbol
1201
1202\newtoks\leftreferencetoks
1203\newtoks\rightreferencetoks
1204\newtoks\defaultleftreferencetoks
1205\newtoks\defaultrightreferencetoks
1206
1207%def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this
1208\let\rightofreferencecontent \empty
1209\let\leftofreference         \empty
1210\let\rightofreference        \empty
1211
1212\unexpanded\def\leftofreferencecontent
1213  {\removeunwantedspaces
1214   \nonbreakablespace
1215   \ignorespaces}
1216
1217\installcorenamespace{referencinginteraction}
1218
1219\def\strc_references_interaction_all
1220  {\the\leftreferencetoks
1221   \doifelsesometoks\leftreferencetoks \leftofreferencecontent \donothing
1222   \leftofreference
1223   \doifelsesometoks\leftreferencetoks\onlynonbreakablespace\relax % new, replace space by nonbreakable if present
1224   \currentreferencecontent
1225   \rightofreference
1226   \doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing
1227   \the\rightreferencetoks}
1228
1229\letvalue{\??referencinginteraction\v!all}\strc_references_interaction_all
1230
1231\setvalue{\??referencinginteraction\v!label}%
1232  {\leftofreference
1233   \the\leftreferencetoks
1234   \the\rightreferencetoks
1235   \rightofreference}
1236
1237\setvalue{\??referencinginteraction\v!text}%
1238  {\leftofreference
1239   \currentreferencecontent
1240   \rightofreference}
1241
1242\setvalue{\??referencinginteraction\v!symbol}%
1243  {\referencesymbol}
1244
1245\def\referencesequence
1246  {\ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
1247     \expandafter\lastnamedcs
1248   \else
1249     \expandafter\strc_references_interaction_all
1250   \fi}
1251
1252\newtoks\everyresetinatreference
1253
1254\appendtoks
1255    \glet\leftofreference \relax
1256    \glet\rightofreference\relax
1257\to \everyresetinatreference
1258
1259\def\strc_references_start_goto
1260  {\dontleavehmode
1261   \begingroup}
1262
1263\def\strc_references_stop_goto
1264  {\the\everyresetinatreference
1265   \endgroup}
1266
1267\def\strc_references_pickup_goto
1268  {\dodoublegroupempty\strc_references_pickup_goto_indeed}
1269
1270\def\strc_references_pickup_goto_indeed#left#right#dummy[#label]% #dummy gobbles spaces (really needed)
1271  {\leftreferencetoks
1272     \iffirstargument
1273       {#left}%
1274     \else
1275       \defaultleftreferencetoks
1276       \let\leftofreferencecontent\empty
1277     \fi
1278   \rightreferencetoks
1279     \ifsecondargument
1280       {#right}%
1281     \else
1282       \defaultrightreferencetoks
1283       \let\rightofreferencecontent\empty
1284     \fi
1285   % inefficient: double resolve
1286   \doifelsereferencefound{#label} % we need to resolve the text
1287     {\goto{\referencesequence}[#label]}
1288     {\let\currentreferencecontent\strc_references_dummy
1289      \goto{\referencesequence}[#label]}%
1290   \strc_references_stop_goto}
1291
1292\unexpanded\def\strc_references_in
1293  {\strc_references_start_goto
1294   \let\currentreferencecontent\currentreferencedefault
1295   \strc_references_pickup_goto}
1296
1297\unexpanded\def\strc_references_at
1298  {\strc_references_start_goto
1299   \let\currentreferencecontent\currentreferencepage
1300   \strc_references_pickup_goto}
1301
1302%D \macros
1303%D   {definereferenceformat}
1304%D
1305%D The next few macros were made for for David Arnold and Taco Hoekwater. They can
1306%D be used for predefining reference texts, and thereby stimulate efficiency.
1307%D
1308%D \starttyping
1309%D \definereferenceformat[informula]  [left=(,right=),text=formula]
1310%D \definereferenceformat[informulas] [left=(,right=),text=formulas]
1311%D \definereferenceformat[andformula] [left=(,right=),text=and]
1312%D \definereferenceformat[andformulas][left=(,right=),text=and]
1313%D
1314%D \informula [b] and \informula [for:c]
1315%D the \informula {formulas}[b] \informula {and} [for:c]
1316%D the \informulas {formulas}[b] \informula {and} [for:c]
1317%D the \informulas [b] \informula {en} [for:c]
1318%D the \informulas [b] \andformula [for:c]
1319%D \stoptyping
1320%D
1321%D Instead of a text, one can specify a label, which should be defined with \type
1322%D {\setuplabeltext}.
1323%D
1324%D Watch out: the second argument is somewhat special and mostly meant for a suffix
1325%D to a number:
1326%D
1327%D \startbuffer
1328%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~]
1329%D \definereferenceformat [intestb] [left=(,right=),label=figure]
1330%D
1331%D \placeformula[x]\startformula a \stopformula
1332%D
1333%D \starttabulate[|||||]
1334%D \NC \in     [x] \NC \in     {left}[x] \NC \in     {}{right}[x] \NC \in     {left}{right}[x] \NC \NR
1335%D \NC \intesta[x] \NC \intesta{left}[x] \NC \intesta{}{right}[x] \NC \intesta{left}{right}[x] \NC \NR
1336%D \NC \intestb[x] \NC \intestb{left}[x] \NC \intestb{}{right}[x] \NC \intestb{left}{right}[x] \NC \NR
1337%D \stoptabulate
1338%D \stopbuffer
1339%D
1340%D \typebuffer \getbuffer
1341
1342% to be done: interfaced
1343
1344\installcorenamespace{referenceformat}
1345
1346\installcommandhandler \??referenceformat {referenceformat} \??referenceformat
1347
1348\appendtoks
1349    \setuevalue\currentreferenceformat{\strc_references_apply_format{\currentreferenceformat}}%
1350\to \everydefinereferenceformat
1351
1352\setupreferenceformat
1353  [\c!left=,
1354   \c!right=,
1355   \c!text=,
1356   \c!label=,
1357   \c!autocase=\v!no,
1358   \c!style=,
1359   \c!type=default, % to be done: interfaced
1360   \c!setups=,
1361   \c!color=]
1362
1363\unexpanded\def\strc_references_apply_format#name%
1364  {\strc_references_start_goto
1365   \edef\currentreferenceformat{#name}%
1366   \gdef\leftofreference               {\referenceformatparameter\c!left    }%
1367   \gdef\rightofreference              {\referenceformatparameter\c!right   }%
1368   \edef\currentreferenceformatlabel   {\referenceformatparameter\c!label   }%
1369   \edef\currentreferenceformattype    {\referenceformatparameter\c!type    }%
1370   \edef\currentreferenceformatsetups  {\referenceformatparameter\c!setups  }%
1371   \edef\currentreferenceformatautocase{\referenceformatparameter\c!autocase}%
1372   \usereferenceformatstyleandcolor\c!style\c!color
1373   \ifx\currentstyleparameter\empty \else
1374     \resetinteractionparameter\c!style
1375   \fi
1376   \ifx\currentcolorparameter\empty \else
1377     \resetinteractionparameter\c!contrastcolor
1378     \resetinteractionparameter\c!color
1379   \fi
1380   \ifx\currentreferenceformatlabel\autoreferencelabeltextflag
1381      \edef\currentreferenceformatlabel{\autoreferencelabeltext}%
1382   \fi
1383   \ifx\currentreferenceformatautocase\v!yes
1384     \setcharactercleaning[1]%
1385   \fi
1386   \ifx\currentreferenceformatlabel\empty
1387     \defaultleftreferencetoks {\referenceformatparameter\c!text}%
1388     \defaultrightreferencetoks\emptytoks
1389   \else
1390     \defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}%
1391     \defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}%
1392   \fi
1393   \ifx\currentreferenceformattype\empty
1394     \def\currentreferenceformattype{default}%
1395   \fi
1396   %
1397   \ifx\currentreferenceformatsetups\empty
1398     \def\currentreferencecontent{\filterreference\currentreferenceformattype}%
1399   \else
1400     \def\currentreferencecontent{\directsetup\currentreferenceformatsetups}%
1401   \fi
1402   %
1403   \let\leftofreferencecontent \empty
1404   \let\rightofreferencecontent\empty
1405   \strc_references_pickup_goto}
1406
1407\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key
1408
1409\unexpanded\def\autoreferencelabeltext
1410  {\clf_getcurrentreferencemetadata{name}}
1411
1412% \starttext
1413%     \definereferenceformat[inxx]  [left=(,right=),text=txt]
1414%     \setupinteraction[state=start]
1415%     \chapter[one]{xx}
1416%     [\goto{state}[file(mk-last-state)]]
1417%     [\goto{state} [file(mk-last-state)]]
1418%     [\at{page} [one]]
1419%     [\at{page}[one]]
1420%     [\at{page}{okay}[one]]
1421%     [\inxx{a}{b}[one]]
1422% \stoptext
1423
1424% \startsetups referenceformat:numberplustext
1425%     \filterreference{number}, \filterreference{title}
1426% \stopsetups
1427%
1428% \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext]
1429
1430%D In interactive documents going to a specific location is not bound to cross
1431%D references. The \type {\goto} commands can be used to let users access another
1432%D part of the document. In this respect, interactive tables of contents and
1433%D registers can be considered goto's. Because in fact a \type {\goto} is just a
1434%D reference without reference specific data, the previous macros are implemented
1435%D using the goto functionality.
1436%D
1437%D \showsetup{goto}
1438%D
1439%D One important characteristic is that the first argument of \type {\goto} (and
1440%D therefore \type {\at} and \type {\in} is split at spaces. This means that,
1441%D although hyphenation is prevented, long references can cross line endings.
1442
1443% \starttext
1444%     \setupinteraction[state=start]
1445%     [\goto{state}[file(mk-last-state)]]
1446%     [\goto{state} [file(mk-last-state)]]
1447% \stoptext
1448
1449\newconditional\uselocationstrut \settrue\uselocationstrut
1450
1451\def\extrareferencearguments
1452  {highlight \luaconditional\highlighthyperlinks\space
1453   newwindow \luaconditional\gotonewwindow\space
1454   layer     {\currentviewerlayer}}
1455
1456\unexpanded\def\directgoto
1457  {\ifconditional\uselocationstrut
1458     \expandafter\strc_references_direct_goto
1459   \else
1460     \expandafter\strc_references_direct_goto_htdp
1461   \fi}
1462
1463\unexpanded\def\goto
1464  {\ifconditional\uselocationstrut
1465     \expandafter\strc_references_goto
1466   \else
1467     \expandafter\strc_references_goto_htdp
1468   \fi}
1469
1470% The unbox trick is needed in order to permit \par inside a reference. Otherwise
1471% the reference attribute migrates to the outer boxes.
1472
1473\newcount\lastsavedreferenceattribute
1474
1475\newbox\referencebox
1476
1477\def\revivesavedreferenceattribute % sometimes handy as no test etc needed
1478  {\c_attr_reference\lastsavedreferenceattribute}
1479
1480\def\strc_references_direct_goto#content[#label]% no test for valid references
1481  {\dontleavehmode
1482   \begingroup
1483   \c_attr_reference\attributeunsetvalue
1484   \global\lastsavedreferenceattribute\attributeunsetvalue
1485   \iflocation
1486     \clf_injectreference
1487        {\referenceprefix}%
1488        {#label}%
1489        {%
1490            height \ht\strutbox
1491            depth  \dp\strutbox
1492            \extrareferencearguments
1493        }%
1494     \relax
1495     \setlocationattributes
1496     \setstrut % can be option
1497     \global\lastsavedreferenceattribute\lastreferenceattribute
1498     \c_attr_reference\lastreferenceattribute
1499     \dostarttagged\t!link\empty % not here
1500     #content%
1501     \dostoptagged
1502   \else
1503     #content%
1504   \fi
1505   \endgroup}
1506
1507\def\strc_references_direct_goto_htdp#content[#label]% no test for valid references
1508  {\dontleavehmode
1509   \begingroup
1510   \global\lastsavedreferenceattribute\attributeunsetvalue
1511   \c_attr_reference\attributeunsetvalue
1512   \iflocation
1513     \clf_injectreference
1514        {\referenceprefix}%
1515        {#label}%
1516        {%
1517            height \dimexpr\interactionparameter\c!height\relax
1518            depth  \dimexpr\interactionparameter\c!depth \relax
1519            \extrareferencearguments
1520        }%
1521     \relax
1522     \setlocationattributes
1523     \c_attr_reference\lastreferenceattribute
1524     \global\lastsavedreferenceattribute\lastreferenceattribute
1525     \dostarttagged\t!link\empty
1526     #content%
1527     \dostoptagged
1528   \else
1529     #content%
1530   \fi
1531   \endgroup}
1532
1533\def\strc_references_goto#content#dummy[#label]% #dummy gobbles spaces
1534  {\dontleavehmode
1535   \begingroup
1536  %\setbox\referencebox\hbox\bgroup % experiment, might change again to non \par support
1537   \global\lastsavedreferenceattribute\attributeunsetvalue
1538   \c_attr_reference\attributeunsetvalue
1539   \iflocation
1540     \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
1541       {\expandtexincurrentreference
1542        \clf_injectcurrentreferencehtdp
1543          \ht\strutbox
1544          \dp\strutbox
1545        \relax
1546        \setlocationattributes
1547        \setstrut % can be option
1548        \global\lastsavedreferenceattribute\lastreferenceattribute
1549        \c_attr_reference\lastreferenceattribute
1550        \dostarttagged\t!link\empty
1551        #content%
1552        \dostoptagged}%
1553       {#content}%
1554   \else
1555     #content%
1556   \fi
1557  %\egroup\unhbox\referencebox}
1558   \endgroup}
1559
1560\def\strc_references_goto_internal#content#dummy[#internal]% #dummy gobbles spaces
1561  {\dontleavehmode
1562   \begingroup
1563   \global\lastsavedreferenceattribute\attributeunsetvalue
1564   \c_attr_reference\attributeunsetvalue
1565   \iflocation
1566     \setstrut % can be option
1567     \strc_references_get_simple_reference{#internal}%
1568     \global\lastsavedreferenceattribute\currentreferenceattribute
1569     \c_attr_reference\currentreferenceattribute
1570     \setlocationattributes
1571     \dostarttagged\t!link\empty
1572     #content%
1573     \dostoptagged
1574   \else
1575     #content%
1576   \fi
1577   \endgroup}
1578
1579\unexpanded\def\startgoto[#label]%
1580  {\dontleavehmode
1581   \begingroup
1582   \iflocation
1583     \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
1584       {\expandafter\strc_references_start_goto_yes}%
1585       {\expandafter\strc_references_start_goto_nop}%
1586   \else
1587     \expandafter\strc_references_start_goto_nop
1588   \fi}
1589
1590\unexpanded\def\strc_references_start_goto_nop
1591  {\let\stopgoto\strc_references_stop_goto_nop}
1592
1593\unexpanded\def\strc_references_stop_goto_nop
1594  {\endgroup}
1595
1596\unexpanded\def\strc_references_start_goto_yes
1597  {\expandtexincurrentreference
1598   \clf_injectcurrentreferencehtdp
1599     \ht\strutbox
1600     \dp\strutbox
1601   \relax
1602   \setlocationattributes
1603   \setstrut % can be option
1604   \global\lastsavedreferenceattribute\lastreferenceattribute
1605   \c_attr_reference\lastreferenceattribute
1606   \dostarttagged\t!link\empty
1607   \let\stopgoto\strc_references_stop_goto_yes}
1608
1609\unexpanded\def\strc_references_stop_goto_yes
1610  {\dostoptagged
1611   \endgroup}
1612
1613\def\strc_references_goto_htdp#content#dummy[#label]% dummy gobbles spaces
1614  {\dontleavehmode
1615   \begingroup
1616   \global\lastsavedreferenceattribute\attributeunsetvalue
1617   \c_attr_reference\attributeunsetvalue
1618   \iflocation
1619     \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
1620       {\expandtexincurrentreference
1621        \clf_injectcurrentreferencehtdp
1622          \dimexpr\interactionparameter\c!height\relax
1623          \dimexpr\interactionparameter\c!depth \relax
1624        \relax
1625        \setlocationattributes
1626        \global\lastsavedreferenceattribute\lastreferenceattribute
1627        \c_attr_reference\lastreferenceattribute
1628        \dostarttagged\t!link\empty
1629        #content%
1630        \dostoptagged}%
1631       {#content}%
1632   \else
1633     #content%
1634   \fi
1635   \endgroup}
1636
1637\unexpanded\def\directgotobox#content[#label]% no test for valid references
1638  {\dontleavehmode
1639   \begingroup
1640   \global\lastsavedreferenceattribute\attributeunsetvalue
1641   \c_attr_reference\attributeunsetvalue
1642   \iflocation
1643     \clf_injectreference
1644       {\referenceprefix}%
1645       {#label}%
1646       {\extrareferencearguments}%
1647     \relax
1648     \setlocationattributes
1649     \global\lastsavedreferenceattribute\lastreferenceattribute
1650     \dostarttagged\t!link\empty
1651     \hbox attr \referenceattribute \lastreferenceattribute {#content}%
1652     \dostoptagged
1653   \else
1654     #content%
1655   \fi
1656   \endgroup}
1657
1658\unexpanded\def\directgotospecbox#resolver#content[#label]% no test for valid references
1659  {\dontleavehmode
1660   \begingroup
1661   \global\lastsavedreferenceattribute\attributeunsetvalue
1662   \c_attr_reference\attributeunsetvalue
1663   \iflocation
1664     \clf_injectreference
1665       {\referenceprefix}%
1666       {#label}%
1667       {\extrareferencearguments}%
1668     \relax
1669     \setlocationcolorspec{#resolver}% no consequence for strut
1670     \global\lastsavedreferenceattribute\lastreferenceattribute
1671     \dostarttagged\t!link\empty
1672     \hbox attr \referenceattribute \lastreferenceattribute {#content}%
1673     \dostoptagged
1674   \else
1675     #content%
1676   \fi
1677   \endgroup}
1678
1679\unexpanded\def\directgotodumbbox#content[#label]% no test for valid references
1680  {\dontleavehmode
1681   \begingroup
1682   \global\lastsavedreferenceattribute\attributeunsetvalue
1683   \c_attr_reference\attributeunsetvalue
1684   \iflocation
1685     \clf_injectreference
1686       {\referenceprefix}%
1687       {#label}%
1688       {\extrareferencearguments}%
1689     \relax
1690     \global\lastsavedreferenceattribute\lastreferenceattribute
1691     \dostarttagged\t!link\empty
1692     \hbox attr \referenceattribute \lastreferenceattribute {#content}%
1693     \dostoptagged
1694   \else
1695     #content%
1696   \fi
1697   \endgroup}
1698
1699\unexpanded\def\gotobox#content[#label]%
1700  {\dontleavehmode
1701   \begingroup
1702   \global\lastsavedreferenceattribute\attributeunsetvalue
1703   \c_attr_reference\attributeunsetvalue
1704   \iflocation
1705     \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
1706       {\expandtexincurrentreference
1707        \clf_injectcurrentreference
1708        \setlocationattributes
1709        \global\lastsavedreferenceattribute\lastreferenceattribute
1710        \dostarttagged\t!link\empty
1711        \hbox attr \referenceattribute \lastreferenceattribute {#content}%
1712        \dostoptagged}%
1713       {#content}%
1714   \else
1715     #content%
1716   \fi
1717   \endgroup}
1718
1719\unexpanded\def\gotowdhtbox#width#height[#label]% fast variant for overlays
1720  {\dontleavehmode
1721   \begingroup
1722   \setbox\scratchbox\emptyhbox
1723   \wd\scratchbox#width%
1724   \ht\scratchbox#height%
1725   \global\lastsavedreferenceattribute\attributeunsetvalue
1726   \c_attr_reference\attributeunsetvalue
1727   \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
1728     {\clf_injectcurrentreference
1729      \global\lastsavedreferenceattribute\lastreferenceattribute
1730      \hpack attr \referenceattribute \lastreferenceattribute {\box\scratchbox}}
1731     {\box\scratchbox}%
1732   \endgroup}
1733
1734%D An reference to another document can be specified as a file or as an \URL. Both
1735%D are handled by the same mechanism and can be issued by saying something like:
1736%D
1737%D \starttyping
1738%D \goto[dictionary::the letter a]
1739%D \stoptyping
1740%D
1741%D One can imagine that many references to such a dictionary are made, so in most
1742%D cases such a document reference in an indirect one.
1743%D
1744%D \showsetup{useexternaldocument}
1745%D
1746%D For example:
1747%D
1748%D \starttyping
1749%D \useexternaldocument
1750%D   [dictionary][engldict]
1751%D   [The Famous English Dictionary]
1752%D \stoptyping
1753%D
1754%D The next macro implements these relations, and also take care of loading the
1755%D document specific references.
1756%D
1757%D The \URL\ alternative takes four arguments:
1758%D
1759%D \showsetup{useURL}
1760%D
1761%D like:
1762%D
1763%D \starttyping
1764%D \useURL
1765%D   [dictionary][http://www.publisher.com/public][engldict]
1766%D   [The Famous English Dictionary]
1767%D \stoptyping
1768%D
1769%D Several specifications are possible:
1770%D
1771%D \starttyping
1772%D \useURL [id] [url] [file] [description]
1773%D \useURL [id] [url] [file]
1774%D \useURL [id] [url]
1775%D \stoptyping
1776%D
1777%D This time we don't load the references when no file is specified. This is logical
1778%D when one keeps in mind that a valid \URL\ can also be a mail address.
1779
1780\unexpanded\def\useurl {\doquadrupleempty\strc_references_use_url }  % so that they can be used in expanded arguments
1781\unexpanded\def\usefile{\dotripleargument\strc_references_use_file}  % so that they can be used in expanded arguments
1782
1783\let\useURL             \useurl
1784\let\useexternaldocument\usefile
1785
1786\def\strc_references_use_url[#label][#url][#file][#description]%
1787  {\clf_useurl{#label}{\detokenize{#url}}{\detokenize{#file}}{\detokenize{#description}}}
1788
1789\def\strc_references_use_file[#label][#file][#description]%
1790  {\clf_usefile{#label}{\detokenize{#file}}{\detokenize{#description}}}
1791
1792\def\doifelseurldefined #label{\clf_doifelseurldefined {#label}}
1793\def\doifelsefiledefined#label{\clf_doifelsefiledefined{#label}}
1794
1795\let\doifurldefinedelse \doifelseurldefined
1796\let\doiffiledefinedelse\doifelsefiledefined
1797
1798%D \macros
1799%D   {url,setupurl}
1800%D
1801%D We also have: \type {\url} for directly calling the description. So we can say:
1802%D
1803%D \starttyping
1804%D \useURL [one] [http://www.test.nl]
1805%D \useURL [two] [http://www.test.nl] [] [Some Site]
1806%D
1807%D \url[one] or \from[two] or \goto{Whatever Site}[URL(two)]
1808%D \stoptyping
1809%D
1810%D An \URL\ can be set up with
1811%D
1812%D \showsetup{setupurl}
1813
1814\installcorenamespace{url}
1815
1816\installdirectcommandhandler \??url {url}
1817
1818\setupurl
1819  [\c!style=\v!type,
1820   \c!color=]
1821
1822\unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua)
1823  {\dontleavehmode
1824   \begingroup
1825   \useurlstyleandcolor\c!style\c!color
1826   \hyphenatedurl{\clf_geturl{#label}}%
1827   \endgroup}
1828
1829%D This macro is hooked into a support macro, and thereby \URL's break ok, according
1830%D to the setting of a switch,
1831%D
1832%D \startbuffer
1833%D \useURL
1834%D   [test]
1835%D   [sentence_sentence~sentence//sentence:sentence.sentence]
1836%D \stopbuffer
1837%D
1838%D \typebuffer
1839%D
1840%D Such an \URL\ is, depending on the settings, hyphenated as:
1841%D
1842%D \getbuffer
1843
1844%D When defining the external source of information, one can also specify a suitable
1845%D name (the last argument). This name can be called upon with:
1846%D
1847%D \showsetup{from}
1848%D
1849%D We keep this for compatibility reasons, hence the hackery.
1850
1851\unexpanded\def\strc_references_from
1852  {\dosingleempty\strc_references_do_special_from}
1853
1854\def\strc_references_do_special_from[#label]%
1855  {\dontleavehmode
1856   \goto{\clf_from{#label}}[fileorurl(#label)]}
1857
1858\def\dofromurldescription#content% called at the lua end
1859  {#content}
1860
1861\def\dofromurlliteral#content% called at the lua end
1862  {\useurlstyleandcolor\c!style\c!color
1863   \hyphenatedurl{#content}}
1864
1865\let\dofromfiledescription\dofromurldescription
1866\let\dofromfileliteral    \dofromurlliteral     % maybe some day setupfile that inherits from url
1867
1868%D We also support:
1869%D
1870%D \starttyping
1871%D \goto{some text}[file(identifier{location}]
1872%D \stoptyping
1873%D
1874%D which is completely equivalent with
1875%D
1876%D \starttyping
1877%D \goto{some text}[identifier::location]
1878%D \stoptyping
1879
1880%D A special case of references are those to programs. These, very system dependant
1881%D references are implemented by abusing some of the previous macros.
1882%D
1883%D \showsetup{setupprograms}
1884%D \showsetup{defineprogram}
1885%D \showsetup{program} % changed functionality !
1886%D
1887%D The latter gives access to the description of the program,
1888%D being the last argument to the definition command.
1889
1890% also lua, like urls and files
1891
1892\installcorenamespace{programs}
1893
1894\installdirectcommandhandler \??programs {programs}
1895
1896\unexpanded\def\defineprogram
1897  {\dotripleargument\strc_references_define_program}
1898
1899\def\strc_references_define_program[#name][#program][#description]%
1900  {\clf_defineprogram{#name}{#program}{#description}}
1901
1902\unexpanded\def\program[#name]% incompatible, more consistent, hardy used anyway
1903  {\dontleavehmode
1904   \begingroup
1905   \useprogramsstyleandcolor\c!style\c!color
1906   \clf_getprogram{#name}%
1907   \endgroup}
1908
1909%D As we can see, we directly use the special reference mechanism, which means that
1910%D
1911%D \starttyping
1912%D \goto{some text}[program(name{args})]
1913%D \stoptyping
1914%D
1915%D is valid.
1916
1917%D The next macro provides access to the actual pagenumbers. When documenting and
1918%D sanitizing the original reference macros, I decided to keep the present meaning
1919%D as well as to make this meaning available as a special reference method. So now
1920%D one can use:
1921%D
1922%D \starttyping
1923%D \gotopage{some text}[location]
1924%D \gotopage{some text}[number]
1925%D \gotopage{some text}[file::number]
1926%D \stoptyping
1927%D
1928%D as well as:
1929%D
1930%D \starttyping
1931%D \goto{some text}[page(location)]
1932%D \goto{some text}[page(number)]
1933%D \goto{some text}[file::page(number)]
1934%D \stoptyping
1935%D
1936%D Here location is a keyword like \type{nextpage}.
1937%D
1938%D \showsetup{gotopage}
1939
1940\unexpanded\def\definepage
1941  {\dodoubleargument\strc_references_define_page}
1942
1943\def\strc_references_define_page[#name][#target]%
1944  {\definereference[#name][page(#target)]}
1945
1946\def\gotopage#text[#target]%
1947  {\goto{#text}[\v!page(#target)]}
1948
1949%D The previous definitions are somewhat obsolete so we don't use it here.
1950
1951%D We can cross link documents by using:
1952%D
1953%D \showsetup{coupledocument}
1954%D
1955%D like:
1956%D
1957%D \starttyping
1958%D \coupledocument[print][somefile][chapter,section]
1959%D \stoptyping
1960%D
1961%D After which when applicable, we have available the references:
1962%D
1963%D \starttyping
1964%D \goto{print version}[print::chapter]
1965%D \stoptyping
1966%D
1967%D and alike. The title placement definition macros have a key \type {file}, which
1968%D is interpreted as the file to jump to, that is, when one clicks on the title.
1969
1970\def\coupledocument
1971  {\doquadrupleempty\strc_references_couple_document}
1972
1973\def\strc_references_couple_document[#name][#file][#sections][#description]%
1974  {\ifthirdargument
1975     % this will be done differently (when it's needed)
1976   \fi}
1977
1978%D \macros
1979%D   {dotextprefix}
1980%D
1981%D In previous macros we used \type {\dotextprefix} to generate a space between
1982%D a label and a number.
1983%D
1984%D \starttyping
1985%D \dotextprefix{text}
1986%D \stoptyping
1987%D
1988%D Only when \type {text} is not empty, a space is inserted.
1989
1990\unexpanded\def\dotextprefix#text%
1991  {\begingroup
1992   \setbox\scratchbox\hbox{#text}% to be solved some day
1993   \ifdim\wd\scratchbox>\zeropoint
1994     \unhbox\scratchbox
1995     \edef\p_separator{\referencingparameter\c!separator}%
1996     \ifx\p_separator\empty \else
1997        \removeunwantedspaces % remove is new
1998        \p_separator
1999     \fi
2000   \else
2001     \unhbox\scratchbox
2002   \fi
2003   \endgroup}
2004
2005%D In the next settings we see some variables that were not used here and that
2006%D concern the way the pagenumbers refered to are typeset.
2007
2008\setupreferencing
2009  [\c!state=\v!start,
2010   \c!autofile=\v!no,
2011   \v!part\c!number=\v!yes,
2012   \v!chapter\c!number=\v!no,
2013   \c!interaction=\v!all,
2014   \c!convertfile=\v!no,
2015  %\c!strut=\v!no, % some day an option
2016   \c!prefix=,
2017   \c!width=.75\makeupwidth,
2018   \c!left=\quotation\bgroup,
2019   \c!right=\egroup,
2020   \c!global=\v!no,
2021   \c!expansion=\v!no,
2022   \c!separator=\nonbreakablespace,
2023   \c!export=\v!no]
2024
2025\setupprograms
2026  [\c!directory=,
2027   \c!style=\v!type,
2028   \c!color=]
2029
2030\definereference [\v!CloseDocument    ] [action(close)]
2031\definereference [\v!ExitViewer       ] [action(exit)]
2032\definereference [\v!FirstPage        ] [action(first)]
2033\definereference [\v!LastPage         ] [action(last)]
2034\definereference [\v!NextJump         ] [action(forward)]
2035\definereference [\v!NextPage         ] [action(next)]
2036\definereference [\v!PauseMovie       ] [action(pausemovie)]
2037\definereference [\v!PauseSound       ] [action(pausesound)]
2038\definereference [\v!PauseRendering   ] [action(pauserendering)]
2039\definereference [\v!PreviousJump     ] [action(backward)]
2040\definereference [\v!PreviousPage     ] [action(previous)]
2041\definereference [\v!PrintDocument    ] [action(print)]
2042\definereference [\v!SaveForm         ] [action(exportform)]
2043\definereference [\v!LoadForm         ] [action(importform)]
2044\definereference [\v!ResetForm        ] [action(resetform)]
2045\definereference [\v!ResumeMovie      ] [action(resumemovie)]
2046\definereference [\v!ResumeSound      ] [action(resumesound)]
2047\definereference [\v!ResumeRendering  ] [action(resumerendering)]
2048\definereference [\v!SaveDocument     ] [action(save)]
2049\definereference [\v!SaveNamedDocument] [action(savenamed)]
2050\definereference [\v!OpenNamedDocument] [action(opennamed)]
2051\definereference [\v!SearchDocument   ] [action(search)]
2052\definereference [\v!SearchAgain      ] [action(searchagain)]
2053\definereference [\v!StartMovie       ] [action(startmovie)]
2054\definereference [\v!StartSound       ] [action(startsound)]
2055\definereference [\v!StartRendering   ] [action(startrendering)]
2056\definereference [\v!StopMovie        ] [action(stopmovie)]
2057\definereference [\v!StopSound        ] [action(stopsound)]
2058\definereference [\v!StopRendering    ] [action(stoprendering)]
2059\definereference [\v!SubmitForm       ] [action(submitform)]
2060\definereference [\v!ToggleViewer     ] [action(toggle)]
2061\definereference [\v!ViewerHelp       ] [action(help)]
2062\definereference [\v!HideField        ] [action(hide)]
2063\definereference [\v!ShowField        ] [action(show)]
2064\definereference [\v!GotoPage         ] [action(gotopage)]
2065\definereference [\v!Query            ] [action(query)]
2066\definereference [\v!QueryAgain       ] [action(queryagain)]
2067\definereference [\v!FitWidth         ] [action(fitwidth)]
2068\definereference [\v!FitHeight        ] [action(fitheight)]
2069\definereference [\v!ShowThumbs       ] [action(thumbnails)]
2070\definereference [\v!ShowBookmarks    ] [action(bookmarks)]
2071
2072\definereference [\v!HideLayer        ] [action(hidelayer)]
2073\definereference [\v!VideLayer        ] [action(videlayer)]
2074\definereference [\v!ToggleLayer      ] [action(togglelayer)]
2075
2076\definereference [\v!firstpage]       [page(firstpage)]
2077\definereference [\v!previouspage]    [page(previouspage)]
2078\definereference [\v!nextpage]        [page(nextpage)]
2079\definereference [\v!lastpage]        [page(lastpage)]
2080\definereference [\v!forward]         [page(forward)]
2081\definereference [\v!backward]        [page(backward)]
2082\definereference [\v!firstsubpage]    [page(firstsubpage)]
2083\definereference [\v!previoussubpage] [page(previoussubpage)]
2084\definereference [\v!nextsubpage]     [page(nextsubpage)]
2085\definereference [\v!lastsubpage]     [page(lastsubpage)]
2086
2087% we can do this but only when later in resolve (else problems with \chapter[first]{...}
2088%
2089% \definereference [\v!first]           [page(firstpage)]
2090% \definereference [\v!previous]        [page(prevpage)]
2091% \definereference [\v!next]            [page(nextpage)]
2092% \definereference [\v!last]            [page(lastpage)]
2093% \definereference [\v!first\v!sub]     [page(firstsubpage)]
2094% \definereference [\v!previous\v!sub]  [page(prevsubpage)]
2095% \definereference [\v!next\v!sub]      [page(nextsubpage)]
2096% \definereference [\v!last\v!sub]      [page(lastsubpage)]
2097
2098%D We cannot set up buttons (not yet, this one calls a menu macro):
2099
2100%D New (and experimental):
2101
2102% \starttext
2103%     \chapter{test}
2104%     \placefigure[here][xx:1]{}{\framed{one}} \placefigure[here][xx:2]{}{\framed{three}}
2105%     \placetable [here][xx:3]{}{\framed{two}} \placetable [here][xx:4]{}{\framed{four}}
2106%     \start
2107%         \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
2108%     \stop \blank \start
2109%         \setupreferencestructureprefix[default][prefix=no]
2110%         \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
2111%     \stop \blank \start
2112%         \setupreferencestructureprefix[float][default][prefix=no]
2113%         \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
2114%     \stop \blank \start
2115%         \setupreferencestructureprefix[figure][default][prefix=no]
2116%         \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4]
2117%     \stop \blank
2118% \stoptext
2119
2120% todo: parameterhandler
2121
2122\installcorenamespace{referencingprefix}
2123
2124\def\getreferencestructureprefix#kind#name#category% name will change
2125  {{%
2126        prefix        {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefix}%
2127        separatorset  {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixseparatorset}%
2128        conversion    {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversion}%
2129        conversionset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversionset}%
2130        starter       {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixstarter}%
2131        stopper       {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixstopper}%
2132        set           {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixset}%
2133        segments      {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixsegments}%
2134        connector     {\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconnector}%
2135  }%
2136  {%
2137        separatorset  {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberseparatorset}%
2138        conversion    {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberconversion}%
2139        conversionset {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberconversionset}%
2140        starter       {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberstarter}%
2141        stopper       {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numberstopper}%
2142        segments      {\referencestructureprefixparameter{#kind}{#name}{#category}\c!numbersegments}%
2143  }}
2144
2145\unexpanded\def\setupreferencestructureprefix
2146  {\dotripleempty\strc_references_setup_reference_structure_prefix}
2147
2148\def\strc_references_setup_reference_structure_prefix[#kind][#category][#settings]%
2149  {\ifthirdargument
2150     \getparameters[\??referencingprefix#kind:#category][#settings]%
2151   \else\ifsecondargument
2152     \getparameters[\??referencingprefix:#kind][#category]%
2153   \fi\fi}
2154
2155\def\referencestructureprefixparameter#kind#name#category#parameter%
2156  {\ifcsname\??referencingprefix#name:#category#parameter\endcsname
2157     \lastnamedcs
2158   \else\ifcsname\??referencingprefix#kind:#category#parameter\endcsname
2159     \lastnamedcs
2160   \else\ifcsname\??referencingprefix:#category#parameter\endcsname
2161     \lastnamedcs
2162   \fi\fi\fi}
2163
2164\def\currentreferencedefault % for some reason we need to explicitly expand
2165  {\normalexpanded{\noexpand\clf_filterdefaultreference
2166     {\s!default}%
2167     \noexpand\getreferencestructureprefix\clf_getcurrentprefixspec{\s!default}% returns #kind#name#category
2168   \relax}}
2169
2170%D Not all support is visible by looking at the \TEX\ code; here is one of those:^
2171%D
2172%D \starttyping
2173%D \startinteractionmenu[right]
2174%D   \startbut [section(first   {chapter})]    first chapter \stopbut
2175%D   \startbut [section(previous{chapter})] previous chapter \stopbut
2176%D   \startbut [section(next    {chapter})]     next chapter \stopbut
2177%D   \startbut [section(last    {chapter})]     last chapter \stopbut
2178%D   \blank[2*big]
2179%D   \startbut [section(first   {section})]    first section \stopbut
2180%D   \startbut [section(previous{section})] previous section \stopbut
2181%D   \startbut [section(next    {section})]     next section \stopbut
2182%D   \startbut [section(last    {section})]     last section \stopbut
2183%D \stopinteractionmenu
2184%D \stoptyping
2185
2186%D Relatively new:
2187%D
2188%D \starttyping
2189%D \chapter{The never ending story}
2190%D
2191%D \section{An ending story}
2192%D
2193%D \in{chapter}[match(complex bibliographies)]
2194%D \in{chapter}[match(never ending)]
2195%D \in{chapter}[match(ending)]
2196%D \in{chapter}[match(chapter:never ending)]
2197%D \in{chapter}[match(chapter:ending)]
2198%D \in{section}[match(section:ending)]
2199%D \in{figure}[match(float:mess)]
2200%D \in{figure}[match(figure:mess)]
2201%D \in{figure (not found)}[match(section:mess)]
2202%D \in{figure (not found)}[match(section:xxxx)]
2203%D \in{figure}[match(mess)]
2204%D
2205%D \placefigure{What a mess}{}
2206%D
2207%D \chapter{About complex bibliographies}
2208%D
2209%D \in{chapter}[match(complex bibliographies)]
2210%D \in{chapter}[match(never ending)]
2211%D \in{figure}[match(mess)]
2212%D \stoptyping
2213
2214\protect \endinput
2215
2216% tricky:
2217%
2218% \enabletrackers[nodes.references]
2219% \setupinteraction[state=start]
2220% \def\KnuthTest{\input knuth }
2221% \def\KnuthTest{\input tufte }
2222% \def\TufteTest{\input tufte }
2223% \defineoverlay[xxx][\overlaybutton{page(3)}]
2224% \setupbackgrounds[text][background=xxx]
2225% \starttext
2226% test {\red \KnuthTest} test \par
2227% \button{test}[page(1)] \par
2228% \goto{page 2 \TeX}[page(2)] \goto{page 2 \TeX}[page(2)] \goto{\TufteTest}[page(2)] test \page
2229% test \goto{page 3}[page(3)] \goto{\TufteTest\space\par\TufteTest}[page(4)] test \page
2230% \goto{page 1}[page(1)] \goto{\TufteTest\space test}[page(1)] \page
2231% \goto{page 1}[page(1)] \goto{\KnuthTest\space test}[page(1)] \page
2232% test \goto{page 1}[page(1)] {\goto{\KnuthTest\space test}[page(1)]} test
2233% \goto{page 1}[page(1)] \goto{\TufteTest}[page(1)] test \page
2234% \stoptext
2235