% DUE TO NEW/FUTURE FEATURES THIS MODULE IS UNDER RECONSTRUCTION !
%
% uitprinten
% engels maken
% rommel voorlopig naar core-01d
% programma, profiel etc als methode
% \macro toevoegen

% Makes more sense to build action data first, especially now
% openaction etc are supported.
%
% \definespecial\doexecuteactionchain w h
% \definespecial\dosetgotolocation
% \definespecial\dosetexecuteJScode
% ...
%
% complication: what when direct? Two calls!

% I considered to change / simplify
%
% rt!page -> \definereference
% rt!list -> \definereference
% rt!exec -> \definereference
%
% not, because the current implementation permits to
% determine the page state and is more efficient.

%D \module
%D   [       file=core-ref,
%D        version=1998.01.15,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Cross Referencing,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. Non||commercial use is
%C granted.

\writestatus{loading}{Context Core Macros / Cross Referencing}

\unprotect

\startmessages  dutch  library: references
  title: verwijzingen
      1: onbekende verwijzing --
      2: dubbele verwijzing -- op pagina --
      3: type verwijzing -- onbekend
      4: verboden verwijzing --
     21: document -- geladen
     22: document -- is niet interactief
     23: onduidelijke verwijzing -- (prefix=--)
\stopmessages

\startmessages  english  library: references
  title: references
      1: unknown reference --
      2: duplicate reference -- on page --
      3: unknown reference type --
      4: illegal reference --
     21: document -- loaded
     22: document -- is not interactive
     23: obscure reference -- (prefix=--)
\stopmessages

\startmessages  german  library: references
  title: referenzen
      1: unbekannte Referenz --
      2: doppelte Referenz -- auf Seite --
      3: unbekannte Referenz Typ --
      4: illegale Referenz --
     21: Dokument -- geladen
     22: Dokument -- ist nicht aktiv
     23: Obskure Referenz -- (Prefix=--)
\stopmessages

%D This module deals with referencing. In \CONTEXT\ referencing
%D is one of the core features, although at a first glance
%D probably nobody will notice. This is good, because
%D referencing should be as hidden as possible.
%D
%D In paper documents, referencing comes down to cross
%D referencing, but in their interactive counterparts, is also
%D involves navigation. Many features implemented here are
%D therefore closely related to navigation.
%D
%D Many \CONTEXT\ commands can optionally be fed with a
%D reference. Such a reference, when called upon, returns the
%D number of a figure, table, chapter etc, a piece of text, or
%D a pagenumber.
%D
%D There are three ways of defining a reference:
%D
%D \starttypen
%D \pagereference[here]
%D \textreference[here]{some text}
%D \stoptypen
%D
%D the third alternative combines them in:
%D
%D \starttypen
%D \reference[here]{some text}
%D \stoptypen

\def\textreference {\dosingleargument\dotextreference}
\def\pagereference {\dosingleargument\dopagereference}
\def\reference     {\dosingleargument\doreference}

%D These are implemented in a low level form as:

\def\dotextreference[#1]#2{\rawtextreference{\s!txt}{#1}{#2}}
\def\dopagereference  [#1]{\rawpagereference{\s!pag}{#1}}
\def\doreference    [#1]#2{\rawreference    {\s!ref}{#1}{#2}}

%D Actually there is not much difference between a text and a
%D full reference, but it's the concept that counts. The low
%D level implementation is:

\def\rawpagereference#1#2%
  {\bgroup
   \the\everyreference
   \makesectionformat
   \writereference{#2}
     {\sectionformat::\noexpand\pagenumber}
     {\noexpand\realfolio}
     {}%
   \egroup}

\def\rawtextreference#1#2#3%
  {\bgroup
   \the\everyreference
   \writereference{#2}
     {}
     {\noexpand\realfolio}
     {#3}%
   \egroup}

\def\rawreference#1#2#3%
  {\bgroup
   \the\everyreference
   \makesectionformat
   \writereference{#2}
     {\sectionformat::\noexpand\pagenumber}
     {\noexpand\realfolio}
     {#3}%
   \egroup}

%D As we can see, these macros depend on three other ones,
%D \type {\makesectionformat}, that generated \type
%D {\sectionformat}, \type {\pagenumber}. The not yet used
%D argument \type{#1} is a tag that specifies the type of
%D reference.

%D \macros
%D   {everyreference}
%D
%D For rather tricky purposes, one can assign sanitizing
%D macros to \type{\everyreference}.

\newevery \everyreference \relax

%D Why do we have to write down references? \TEX, and therefore
%D \CONTEXT\ is a batch processing system. During the
%D typesetting process, pages are shipped out, which means that
%D especially forward references are not yet known when the
%D page is typeset. That's why we always need a second (and
%D sometimes even a third) pass to get the cross references
%D right. The same goes for lists and other pagenumber
%D dependant data.
%D
%D Therefore, during a pass, \CONTEXT\ writes the references to
%D a the utility file. The next macro does the job and
%D generates entries like:
%D
%D \starttypen
%D \mainreference{prefix}{reference}{page}{realpage}{text}
%D \stoptypen
%D
%D We did not yet discuss prefixing. Especially in interactive
%D documents, it's not always easy to keep track of duplicate
%D references. The prefix mechanism, which we will describe
%D later on, solves this problem. By (automatically) adding a
%D prefix one keeps references local, but the global ones in
%D view. To enable this feature, we explictly split the prefix
%D from the reference.
%D
%D A former implementation used \type{\removesubstring} to get
%D rid of the don't||use||a||prefix signal (\type{-:}), but the
%D next one proved to be more than twice as fast.

\let\referenceprefix=\empty
\let\lastreference  =\empty

%D The last reference is saved in a macro named \type
%D {\lastreference} (indeed). To keep track of the order of
%D references, later we will see for what purpose, we maintain
%D a counter.

\newcount\crossreferencenumber \crossreferencenumber=1

\def\writereference#1#2#3#4%
  {\ifreferencing
     \doifsomething{#1}
       {\def\dowritereference##1%
          {\xdef\lastreference{##1}%
           \@EA\dodowritereference\lastreference\empty\empty\end
              {#2}{#3}{#4}}%
        \processcommalist[#1]\dowritereference}%
   \fi}

\def\dodowritereference#1#2#3\end#4#5#6%
  {\bgroup
   \global\advance\crossreferencenumber by 1
   \if#1-\if#2:%
     \let\referenceprefix=\empty
     \xdef\lastreference{#3}%
   \else
     \xdef\lastreference{#1#2#3}%
   \fi\else
     \xdef\lastreference{#1#2#3}%
   \fi
   \ifx\lastreference\empty \else
     \doiffirstreferenceoccurance{\lastreference}
       {\thisisdestination{\referenceprefix\lastreference}}%
     \@EA\referentieinfo\@EA>\@EA{\lastreference}%
     \edef\dododowritereference%
       {\writeutilitycommand
          {\mainreference{\referenceprefix}{\lastreference}{#4}{#5}{#6}}}%
     \dododowritereference
   \fi
   \egroup}

%D We will implement \type {\doiffirstreferenceoccurance}
%D later on.

%D When (during a second pass over the document) references are
%D loaded, they are saved in a macro, one for each reference.
%D In practice this comes to giving \type {\mainreference} a
%D appropriate meaning and loading the utility file.

%\def\setreferences%
%  {\def\mainreference##1##2##3##4##5%
%     {\doifundefinedelse{\r!cross\fileprefix##1##2}
%        {\setglobalcrossreference{##1##2}{##3}{##4}{##5}}
%        {\showmessage{\m!references}{2}{[##1][##2],##4}}}}

\def\setreferences%
  {\the\everyreference % we're grouped anyway
   \def\mainreference##1##2##3##4##5%
     {\doifundefinedelse{\r!cross\fileprefix##1##2}
        {\setglobalcrossreference{##1##2}{##3}{##4}{##5}}
        {\ifcase0##4\else\showmessage{\m!references}{2}{[##1][##2],##4}\fi}}}

\def\resetreferences%
  {\let\mainreference=\gobblefivearguments}

\resetreferences

%D Here we see another kind of prefix surface: \type
%D {\fileprefix}. This prefix enables us to use references from
%D different files in one document. This is no really useful in
%D paper documents, but many interactive ones cannot do
%D without.

\let\fileprefix=\empty

%D Loading references is done using the normal utility file
%D handling macros. The \type{\hbox} trick prevents spaces
%D creeping in (references are set globally anyway).

\newtoks\everycheckreferences

%D This token list is expanded after the references are loaded.
%D This hook can be used to initialize mechanisms that depend
%D on the reference mechsnism. An example can be found in the
%D field module.

\def\checkreferences%
  {\bgroup
   \let\fileprefix\empty
   \global\let\checkreferences\relax
   \usereferences[\jobname]%
   \checkrealpage
   \egroup
   \the\everycheckreferences}

\def\usereferences[#1]%
  {\bgroup
   \checkreferences
   \setbox0=\hbox
     {\doonlyonce{references:#1}{\doutilities{references}{#1}{}{}{}}}%
   \egroup}

%D As mentioned we will also use the cross reference mechanism
%D for navigational purposes. The main reason for this is that
%D we want to treat both categories alike:
%D
%D \starttypen
%D \goto{go back}[PreviousJump]
%D \goto{colofon}[colofon page]
%D \stoptypen
%D
%D Here \type{PreviousJump} is handled by the viewer, while the
%D \type{colofon page} reference is, apart from hyperlinking, a
%D rather normal reference.
%D
%D We already saw that cross refences are written to and read
%D from a file. The pure navigational ones don't need to be
%D written to file, but both for fast processing and
%D transparant integration, they are saved internally as a sort
%D of reference. We can easily distinguish such system
%D references from real cross reference ones by their tag:

\chardef\rt!cross=0  % even means possible page reference
\chardef\rt!done =1
\chardef\rt!page =2  % and is used in \checkrealreferencepage
\chardef\rt!exec =3
\chardef\rt!list =4  % to determine the page state

%D We also use the odd/even characteristic to determine the
%D page state.

%D Here the \type{\rt!exec} tags a viewer specific navigational
%D reference, while for instance \type{\rt!page} gives fast
%D access to for instance the previous or next page. The
%D counter serves a purpose to be explained later. We use a
%D token register to prevent expansion of the text component,
%D which can contain all kind of \TEX\ commands.

\newcount\crossreferenceorder

\def\setlocalcrossreference#1#2#3#4%
  {\toks0={#4}%
   \setevalue{\r!cross\fileprefix#1}{\rt!cross{#2}{#3}{\the\toks0}{0}}}

\def\setglobalcrossreference#1#2#3#4%
  {\toks0={#4}%
   \global\advance\crossreferenceorder by 1
   \setxvalue{\r!cross\fileprefix#1}{\rt!cross{#2}{#3}{\the\toks0}{\the\crossreferenceorder}}}

\def\setlocalsystemreference#1#2#3%
  {\setevalue{\r!cross\fileprefix#2}{#1{#3}}}

\def\setglobalsystemreference#1#2#3%
  {\setxvalue{\r!cross\fileprefix#2}{#1{#3}}}

% Maybe I need this some day.

% \def\copycrossreference#1#2#3% file from to
%   {\bgroup
%    \def\fileprefix{#1::}%
%    \def\rt!cross##1##2##3##4%
%      {\setxvalue{\r!cross\fileprefix#3}%
%         {\noexpand\rt!cross{##1}{##2}{##3}{##4}}}%
%    \getvalue{\r!cross\fileprefix#2}%
%    \egroup}

\def\copycrossreference#1#2#3% file from to
  {\bgroup
   \doifelse{#1}{}
     {\let\fileprefix\empty}
     {\def\fileprefix{#1::}}%
   \def\rt!cross##1##2##3##4%
     {\setxvalue{\r!cross\fileprefix#3}%
        {\noexpand\rt!cross{##1}{##2}{##3}{##4}}}%
   \getvalue{\r!cross\fileprefix#2}%
   \egroup}

%D References from other files are defined globally without
%D ordering data. The first definition, the one without
%D \type{#1}, is used as a signal that references are defined.

\def\setoutercrossreference#1#2#3#4%
  {\toks0={#4}%
   \setxvalue{\r!cross\fileprefix}{\rt!cross{}{}{1}{0}}%
   \setxvalue{\r!cross\fileprefix#1}{\rt!cross{#2}{#3}{\the\toks0}{0}}}

%D In practice accessing a reference comes down to:
%D
%D \startopsomming[opelkaar]
%D \som  checking the validity
%D \som  determining the type
%D \som  filtering the content
%D \stopopsomming
%D
%D We'll deal with the last two steps first. References are
%D saved in the general format:
%D
%D \starttypen
%D {\referenceclass{realpage}{page}{text}}
%D {\referenceclass{type}{data}}
%D \stoptypen
%D
%D When we filter the content, next macros are set when we
%D meet a normal cross reference:

\let\currentrealreference=\empty
\let\currentpagereference=\empty
\let\currenttextreference=\empty
\let\currentsubtextreference=\empty
\let\currentsubsubtextreference=\empty

%D System references only have one component:

\let\currentdatareference=\empty

%D Because internally a reference comes in two disguises, one
%D with four arguments and one with only two, we need a two
%D step filter.

%\def\getreferenceelements#1%
%  {\edef\referenceelements{\getvalue{\r!cross\referenceprefix#1}}%
%   \expandafter\dogetreferenceelements\referenceelements{}{}{}{}}

\def\getreferenceelements#1% only one level expansion permitted!
  {\@EA\@EA\@EA\dogetreferenceelements\csname\r!cross\referenceprefix#1\endcsname{}{}{}{}}

%D In the following step, the \type{\ifx#1} test is needed
%D because we can access this macro directly, and therefore
%D \type{#1} can be an undefined reference (in fact, this hack
%D was needed for the line numbering mechanism).
%D
%D We already introduced a few counters. Here we see why we
%D need those. The discrepancy between the cross reference
%D definition order (determined by the utility file) and the
%D moment the reference is defined in the text, is a measure
%D for it's forward character. This enables references like
%D {\em as we will see later on}.

\chardef\currentreferencetype=0

\newif\ifforwardreference

%\def\dogetreferenceelements#1#2#3#4#5%
%  {\chardef\currentreferencetype=\ifx#1\relax0\else#1\fi\relax
%   \ifnum\currentreferencetype<2
%     \def\currentpagereference{\referencepagenumber[#2]}%
%     \edef\currentrealreference{#3}%
%     \def\currenttextreference{#4}%
%     \ifnum0#5>\crossreferencenumber
%       \forwardreferencetrue
%     \else
%       \forwardreferencefalse
%     \fi
%   \else
%     \def\currentdatareference{#2}%
%     \edef\currentrealreference{#3}%
%     \def\currenttextreference{#4}%
%     \forwardreferencefalse
%   \fi}

\newif\ifrealreferencepage

\def\docheckrealreferencepage#1%
  {\doifnumberelse{#1}
     {\ifnum#1=\realpageno
        \realreferencepagetrue
      \else
        \realreferencepagefalse
      \fi}
     {\realreferencepagefalse}}

\def\dogetreferenceelements#1#2#3#4#5%
  {\chardef\currentreferencetype=\ifx#1\relax0\else#1\fi\relax
   \ifnum\currentreferencetype<2
     \def\currentpagereference{\referencepagenumber[#2]}%
     \edef\currentrealreference{#3}%
     \settextreferences#4\end
     \ifnum0#5>\crossreferencenumber
       \forwardreferencetrue
     \else
       \forwardreferencefalse
     \fi
   \else
     \edef\currentrealreference{#3}%
     \def\currentdatareference{#2}%
     \settextreferences#4\end
     \forwardreferencefalse
   \fi
   \ifodd\currentreferencetype
     \realreferencepagefalse
   \else
     \docheckrealreferencepage\currentrealreference
     \ifrealreferencepage \else
       \docheckrealreferencepage\currentdatareference
     \fi
   \fi}

%D Text references can contain more than one entry and
%D therefore we check for
%D
%D \starttypen
%D {entry}
%D \stoptypen
%D
%D or
%D
%D \starttypen
%D {{entry}{entry}{entry}}
%D \stoptypen
%D
%D and split accordingly.

\def\settextreferences%
  {\futurelet\next\dosettextreferences}

\def\dosettextreferences%
  {\ifx\next\bgroup
     \expandafter\dotriplegroupempty\expandafter\dodosettextreferences
   \else
     \expandafter\donosettextreferences
   \fi}

\def\donosettextreferences#1\end
  {\def\currenttextreference{#1}%
   \let\currentsubtextreference\empty
   \let\currentsubsubtextreference\empty}

\def\dodosettextreferences#1#2#3#4\end%
  {\def\currenttextreference{#1}%
   \def\currentsubtextreference{#2}%
   \def\currentsubsubtextreference{#3}}

%D When inside this testing macro we can savely use:

\def\doifforwardreferenceelse#1#2%
  {\ifforwardreference#1\else#2\fi}

%D Duplicate references are reported while loading the utility
%D file. To prevent problems with document viewers cq.
%D preprocessors, one can enable a (bit time consuming) check.

\newif\ifcheckduplicatereferences

%D The next rather dirty trick is needed to preserve the
%D meaning of the original cross reference. In fact,
%D \type{\rt!cross} is toggled to \type{\rt!done}.

\def\doiffirstreferenceoccurance#1#2%
  {\ifcheckduplicatereferences
     \doifundefinedelse{\r!cross\referenceprefix#1}
       {#2}
       {\getreferenceelements{#1}%
        \ifnum\currentreferencetype=\rt!cross
          #2%
          \bgroup
          \def\rt!cross##1##2##3##4%
            {\setgvalue{\r!cross\referenceprefix#1}%
               {\rt!done{##1}{##2}{##3}{##4}}}%
          \getvalue{\r!cross\referenceprefix#1}%
          \egroup
        \fi}%
   \else
     #2%
   \fi}

%D We still have to test for the existence of a reference, but
%D before we come to that, we first look into the way a
%D reference can be accessed. It will be no surprise that
%D references can come in several forms.
%D
%D Cross references appear as numbers (figure~1.1, chapter~2)
%D or pagenumbers (page~2, page 3--2), and are called with
%D \type{\in} and \type{\at}. In interactive documents we also
%D have \type{\goto}, \type{\button} and alike. These are more
%D versatile and look like:
%D
%D \starttypen
%D \goto[reference]
%D \goto[outer reference::]
%D \goto[outer reference::inner reference]
%D \goto[operation(argument)]
%D \goto[operation(action{argument,argument})]
%D \goto[action]
%D \goto[action{argument}]
%D \stoptypen
%D
%D The first one is a normal reference, the second and third
%D are references to a file or \URL. The brace delimited
%D references for instance refer to a \JAVASCRIPT. The last
%D example shows that we can pass arguments to the actions.
%D
%D When we split off the components of such a reference, the
%D results are available in:
%D
%D \starttypen
%D \currentreferencespecial
%D \currentreferenceoperation
%D \currentreferencearguments
%D \currentinnerreference
%D \currentouterreference
%D \currentfullreference
%D \stoptypen
%D
%D Splitting a reference is done by:
%D
%D \starttypen
%D \splitofffullreference {reference}
%D \splitoffreference     {reference}
%D \stoptypen
%D
%D The second alternative can be used in a second stage
%D splitoff and only handles \type{::}.

\newif\ifreferencefound

\let\currentfullreference     =\empty
\let\currentreferencespecial  =\empty
\let\currentreferenceoperation=\empty
\let\currentreferencearguments=\empty
\let\currentouterreference    =\empty
\let\currentinnerreference    =\empty

\def\splitofffullreference#1%
  {\edef\currentfullreference{#1}%
   \@EA\dosplitofffullreference\currentfullreference\empty(\relax)\empty\end}

\def\dosplitofffullreference#1(#2#3)#4#5\end
  {\ifx#2)%
     \let\currentreferenceoperation=\empty
     \let\currentreferencearguments=\empty
     \let\currentinnerreference=\empty
     \dodosplitofffullreferenceA#1::::\empty\end
       \currentouterreference\currentreferencespecial
   \else\ifx#2\relax
     \let\currentreferencespecial=\empty
     \let\currentreferenceoperation=\empty
     \let\currentreferencearguments=\empty
     \dodosplitofffullreferenceA#1::::\empty\end
       \currentouterreference\currentinnerreference
   \else
     \dosplitoffreferenceoperation#2#3{}\end
     \let\currentinnerreference=\empty
     \dodosplitofffullreferenceB#1::::\empty\end
       \currentouterreference\currentreferencespecial
   \fi\fi}

\def\dosplitoffreferenceoperation#1#%
  {\def\currentreferenceoperation{#1}%
   \dodosplitoffreferenceoperation}

\def\dodosplitoffreferenceoperation#1#2\end
  {\def\currentreferencearguments{#1}}

\def\dodosplitofffullreferenceA#1::#2::#3#4\end#5#6%
  {\if#3:%
     \dosetfullreferenceA#5#1{}\edef#6{#2}%
   \else
     \dosetfullreferenceA#6#1{}\let#5\empty
   \fi}

\def\dosetfullreferenceA#1#2#%
  {\edef#1{#2}%
   \def\currentreferencearguments}

\def\dodosplitofffullreferenceB#1::#2::#3#4\end#5#6%
  {\if#3:%
     \edef#5{#1}\edef#6{#2}%
   \else
     \let#5\empty\edef#6{#1}%
   \fi}

\def\splitoffreference#1%
  {\expandafter\dodosplitofffullreferenceB#1::::\empty\end
     \currentouterreference\currentinnerreference}

%D Although the previous split macros have a multistep
%D character, there performance is quite reasonable.
%D
%D For debugging purposes we provide a showcase macro:

\long\def\dodoshowcurrentreference#1\from#2\with#3%
  {\convertcommand#2\to\ascii
   \edef\currentreferenceshow{\currentreferenceshow/#1/\ascii/#3/}}

\long\def\doshowcurrentreference#1%
  {\edef\currentreferenceshow{/\ifreferencefound+\else-\fi/#1}%
   \dodoshowcurrentreference ful\from\currentfullreference     \with#1%
   \dodoshowcurrentreference spe\from\currentreferencespecial  \with#1%
   \dodoshowcurrentreference ope\from\currentreferenceoperation\with#1%
   \dodoshowcurrentreference arg\from\currentreferencearguments\with#1%
   \dodoshowcurrentreference out\from\currentouterreference    \with#1%
   \dodoshowcurrentreference inn\from\currentinnerreference    \with#1}

\def\showcurrentreference%
  {\bgroup\tttf\doshowcurrentreference\par\currentreferenceshow\egroup}

%D We use this visualizer to demonstrate the way references are
%D split.
%D
%D \hbox{\splitofffullreference{rr}\showcurrentreference}
%D \hbox{\splitofffullreference{pp{rr}}\showcurrentreference}
%D \hbox{\splitofffullreference{pp(qq)}\showcurrentreference}
%D \hbox{\splitofffullreference{pp(qq{aa,bb})}\showcurrentreference}
%D \hbox{\splitofffullreference{ff::}\showcurrentreference}
%D \hbox{\splitofffullreference{ff::rr}\showcurrentreference}
%D \hbox{\splitofffullreference{ff::pp()}\showcurrentreference}
%D \hbox{\splitofffullreference{ff::pp(qq)}\showcurrentreference}
%D \hbox{\splitofffullreference{ff::pp(qq{aa})}\showcurrentreference}

%D Now we've come to the promissed testing step. As we can
%D see, this macro does bit more than testing: it also resolves
%D the reference. This means that whenever we test for the
%D existance of a reference at an outer level, we have all the
%D relevant properties of that reference avaliable inside the
%D true branche~(\type{#2}).
%D
%D The prefix has to do with localizing references. When a
%D prefix is set, looking for a reference comes to looking for
%D the prefixed one, and when not found, looking for the non
%D prefixed one. Consider for instance the prefix set to
%D \type{sidetrack}.
%D
%D \starttypen
%D \pagereference[important]
%D \pagereference[unimportant]
%D \setupreferencing[prefix=sidetrack]
%D \pagereference[important]
%D \stoptypen
%D
%D results in saving (writing) the references
%D
%D \starttypen
%D ...{}{important}
%D ...{}{unimportant}
%D ...{sidetrack}{important}...
%D \stoptypen
%D
%D Now when we call for \type{unimportant}, we will indeed get
%D the pagenumber associated to this reference. But when we
%D call for \type{important}, while the prefix is still set, we
%D will get the pagenumber bound to the prefixed one.
%D
%D {\em Some day, when processing time and memory are no longer
%D performance factors, we will introduce multi||level
%D prefixes.}
%D
%D Before we start analyzing, I introduce a general
%D definition macro. Consider:
%D
%D \starttypen
%D \goto{do}[JS(My_Script{"test",123}),titlepage]
%D \stoptypen
%D
%D This can also be achieved by:
%D
%D \starttypen
%D \definereference[startup][JS(My_Script{"test",123}),titlepage]
%D \goto{do}[REF(startup)]
%D \stoptypen
%D
%D Now is this is a handy feature or not?
%D
%D \showsetup{\y!definereference}
%D
%D We can trace references by setting the next switch to
%D true.

\newif\iftracereferences

\let\tracereferences\tracereferencestrue

\def\specialREFidentifier{REF}

\def\dodefinereference[#1][#2]%
  {\ifsecondargument
     \doifelsenothing{#2}
       {\global\letbeundefined{\specialREFidentifier#1}}
       {\setgvalue{\specialREFidentifier#1}{#2}}%
   \else\iffirstargument
     \global\letbeundefined{\specialREFidentifier#1}%
   \fi\fi}

\def\definereference%
  {\dodoubleempty\dodefinereference}

\beginTEX

\def\dodoifreferencefoundelse#1#2#3%
  {\checkreferences
   \bgroup
     \the\everyreference
     \let\unharmedreferenceprefix=\referenceprefix
     \bgroup
     \splitofffullreference{#1}%
     \ifx\currentreferencespecial\specialREFidentifier
       \@EA\ifx\csname\specialREFidentifier\currentreferenceoperation\endcsname\relax
         \global\referencefoundfalse
       \else
         \global\referencefoundtrue
         \@EA\@EA\@EA\splitofffullreference\@EA\@EA\@EA % 1 level
            {\csname\specialREFidentifier\currentreferenceoperation\endcsname}%
       \fi
     \else
       \global\referencefoundtrue
     \fi
     \ifreferencefound
       \ifx\currentreferencespecial\empty
         \ifx\currentouterreference\empty
           \docheckinnerreference
         \else
           \docheckouterreference
         \fi
         \ifreferencefound
           \ifx\currentreferencearguments\empty
             \getreferenceelements\currentfullreference
           \else
             \getreferenceelements\currentinnerreference
           \fi
         \fi
       \else
         \docheckspecialreference
       \fi
     \fi
     \ifreferencefound \else
       \let\referenceprefix=\empty
       \@EA\ifx\csname\specialREFidentifier#1\endcsname\relax\else
         \@EA\@EA\@EA\splitofffullreference\@EA\@EA\@EA % 1 level
            {\csname\specialREFidentifier#1\endcsname}%
         \ifx\currentreferencespecial\empty
           \ifx\currentouterreference\empty
             \docheckinnerreference
           \else
             \docheckouterreference
           \fi
           \ifreferencefound
             \getreferenceelements\currentfullreference
           \fi
         \else
           \docheckspecialreference
         \fi
       \fi
     \fi
%    \ifx\currentfullreference\v!geen % DOCUMENT THIS ONE!
%       \global\referencefoundfalse
%    \fi
     \iftracereferences
       \doshowcurrentreference\space
       \writestatus{\m!references}{\currentreferenceshow}%
     \fi
     \ifreferencefound#2\else#3\fi
     \egroup
   \egroup}

\endTEX

\beginETEX \ifcsname

\def\dodoifreferencefoundelse#1#2#3%
  {\checkreferences
   \bgroup
     \the\everyreference
     \let\unharmedreferenceprefix=\referenceprefix
     \bgroup
     \splitofffullreference{#1}%
     \ifx\currentreferencespecial\specialREFidentifier
       \ifcsname\specialREFidentifier\currentreferenceoperation\endcsname
         \global\referencefoundtrue
         \@EA\@EA\@EA\splitofffullreference\@EA\@EA\@EA % 1 level
            {\csname\specialREFidentifier\currentreferenceoperation\endcsname}%
       \else
         \global\referencefoundfalse
       \fi
     \else
       \global\referencefoundtrue
     \fi
     \ifreferencefound
       \ifx\currentreferencespecial\empty
         \ifx\currentouterreference\empty
           \docheckinnerreference
         \else
           \docheckouterreference
         \fi
         \ifreferencefound
           \ifx\currentreferencearguments\empty
             \getreferenceelements\currentfullreference
           \else
             \getreferenceelements\currentinnerreference
           \fi
         \fi
       \else
         \docheckspecialreference
       \fi
     \fi
     \ifreferencefound \else
       \let\referenceprefix=\empty
       \ifcsname\specialREFidentifier#1\endcsname
         \@EA\@EA\@EA\splitofffullreference\@EA\@EA\@EA % 1 level
            {\csname\specialREFidentifier#1\endcsname}%
         \ifx\currentreferencespecial\empty
           \ifx\currentouterreference\empty
             \docheckinnerreference
           \else
             \docheckouterreference
           \fi
           \ifreferencefound
             \getreferenceelements\currentfullreference
           \fi
         \else
           \docheckspecialreference
         \fi
       \fi
     \fi
%     \ifx\currentfullreference\v!geen % DOCUMENT THIS ONE!
%       \global\referencefoundfalse
%     \fi
     \iftracereferences
       \doshowcurrentreference\space
       \writestatus{\m!references}{\currentreferenceshow}%
     \fi
     \ifreferencefound#2\else#3\fi
     \egroup
   \egroup}

\endETEX

%D For most situations, we could use:
%D
%D \starttypen
%D \let\doifreferencefoundelse=\dodoifreferencefoundelse
%D \stoptypen
%D
%D But when we also want to support chained references, we need
%D some more. Such a chained reference is defined as:
%D
%D \starttypen
%D \goto{somewhere}[JS(somescript),nextpage,JS(anotherscript)]
%D \stoptypen
%D
%D Actually supporting chains is up to the special driver. Here
%D we only provide the hooks.

%D \macros
%D   {ifenablereferencechains}
%D
%D First we provide a switch to turn this mechanism off:

\newif\ifenablereferencechains \enablereferencechainstrue

%D We don't use the general commalist processing macros,
%D because we don't want to pay a speed penalty.

\newif\ifsecondaryreference
\newcount\nofsecondaryreferences

% Aanpassen: eerst alle refs scannen en componenten opslaan in
% lijst, dan de chain doorlopen. Momenteel mag alleen laatste
% laatste undefined zijn, eigenlijk moet dat overal kunnen met
% 'geen' zonder melding. Is wel trager. 

\def\doifreferencefoundelse#1#2#3%
  {\doresetgotowhereever
   \global\secondaryreferencefalse
   \xdef\primaryreference{#1}%
   \global\nofsecondaryreferences=0
   \def\dopreprocessreference##1,%
     {\if]##1\else
        \ifsecondaryreference
          \ifenablereferencechains \iflocation
           %\global\advance\nofsecondaryreferences by 1
            \dodoifreferencefoundelse{##1}
              {\global\advance\nofsecondaryreferences by 1
               #2}
              {%\global\advance\nofsecondaryreferences by -1
               \dostartnoto#3\dostopnoto}% #3}%
          \fi \fi
        \else
          \xdef\primaryreference{##1}%
          \global\secondaryreferencetrue
        \fi
        \expandafter\dopreprocessreference
     \fi}%
   \dopreprocessreference#1,],%
   \global\secondaryreferencefalse
   \@EA\dodoifreferencefoundelse\@EA{\primaryreference}{#2}{#3}%
   \doresetgotowhereever} % to prevent problems with direct goto's

%D Somewhere else we will properly define \type {\dostartgoto};
%D the noto alternative takes care of undefined references in 
%D a sequence

\ifx\dostartnoto\undefined

  \def\dostartnoto#1\dostopnoto%
    {\ifsecondaryreference\else{#1}\fi}

\fi

\ifx\dostartgoto\undefined

  \def\dostartgoto\data#1\start#2\stop#3\dostopgoto%
    {\ifsecondaryreference\else{#1}\fi}

\fi

%D As one can see, while processing the references, the first
%D one is handled last. While scanning the second and following
%D ones, we increment a counter and set a boolean to true.

%D The next fast one permits rather raw references with
%D \type{()}'s and is used in the object reference mechanism.

\def\doifrawreferencefoundelse#1#2#3%
  {\checkreferences
   \bgroup
   \edef\currentfullreference{#1}%
   \doifdefinedelse{\r!cross\currentfullreference}
     {\getreferenceelements\currentfullreference
      \global\referencefoundtrue  #2}
     {\global\referencefoundfalse #3}%
   \egroup}

%D The inner case is simple. Only two cases have to be taken
%D care of:
%D
%D \starttypen
%D \naar{some text}[reference]
%D \naar{some text}[prefix:reference]
%D \stoptypen

\def\docheckinnerreference%
  {\global\let\predefinedreference=\currentinnerreference
   \ifx\currentreferencearguments\empty
     \doifdefinedelse{\r!cross\referenceprefix\currentfullreference}
       {\global\referencefoundtrue}
       {\let\referenceprefix\empty
        \doifdefinedelse{\r!cross\currentfullreference}
          {\global\referencefoundtrue}
          {\global\referencefoundfalse}}%
   \else % [SomeThing{with,me}]
     \let\referenceprefix\empty
     \doifdefinedelse{\r!cross\currentinnerreference}
       {\global\referencefoundtrue}
       {\global\referencefoundfalse}%
   \fi
   \doifpredefinedreferenceelse{\global\referencefoundfalse}{}}

%D References to other files however are treated strict or
%D tolerant, depending on their loading and availability:
%D
%D \starttypen
%D \useexternaldocument[somefile][filename][a nice description]
%D
%D \goto{checked   reference}[somefile::reference]
%D \goto{unchecked reference}[somefile::]
%D \goto{unchecked reference}[anotherfile::reference]
%D \stoptypen
%D
%D Here we use the dummy reference \type{somefile::} set in
%D \type{\setouterreference} as a signal that indeed references
%D are defined for the outer file.

% \def\docheckouterreference%
%   {\let\referenceprefix=\empty
%    \let\unharmedreferenceprefix=\empty
%    \xdef\predefinedreference%
%      {\currentouterreference::\currentinnerreference}%
%    \ifx\innerreference\empty
%      \global\referencefoundtrue % no checking done
%    \else
%      \doifdefinedelse{\r!cross\currentouterreference::}
%        {\doifdefinedelse{\r!cross\currentfullreference}
%           {\global\referencefoundtrue}
%           {\global\referencefoundfalse}}
%        {\global\referencefoundtrue}% no checking done
%    \fi
%    \doifpredefinedreferenceelse{\global\referencefoundfalse}{}}

\newif\ifstrictouterreferences \strictouterreferencesfalse

\beginTEX

\def\dodocheckouterreference%
  {\@EA\ifx\csname\specialREFidentifier\currentfullreference\endcsname\relax
     \ifstrictouterreferences
       \global\referencefoundfalse
     \else
       % already \global\referencefoundtrue % no checking done
     \fi
   \else
     \@EA\@EA\@EA\splitofffullreference\@EA\@EA\@EA % 1 level
        {\csname\specialREFidentifier\currentfullreference\endcsname}%
     \docheckouterreference
   \fi}

\endTEX

\beginETEX \ifcsname

\def\dodocheckouterreference%
  {\ifcsname\specialREFidentifier\currentfullreference\endcsname
     \@EA\@EA\@EA\splitofffullreference\@EA\@EA\@EA % 1 level
        {\csname\specialREFidentifier\currentfullreference\endcsname}%
     \docheckouterreference
   \else\ifstrictouterreferences
     \global\referencefoundfalse
   \else
     % already \global\referencefoundtrue % no checking done
   \fi\fi}

\endETEX

\def\docheckouterreference%
  {\let\referenceprefix=\empty
   \let\unharmedreferenceprefix=\empty
   \xdef\predefinedreference%
     {\currentouterreference::\currentinnerreference}%
   \ifx\innerreference\empty
     \global\referencefoundtrue % no checking done
   \else
     \doifdefinedelse{\r!cross\currentouterreference::}
       {\doifdefinedelse{\r!cross\currentfullreference}
          {\global\referencefoundtrue}
          {\dodocheckouterreference}}
       {\ifstrictouterreferences
          \global\referencefoundfalse
        \else
          \global\referencefoundtrue % no checking done
        \fi}%
   \fi
   \doifpredefinedreferenceelse{\global\referencefoundfalse}{}}

%D Special references are only tested when some test routine is
%D defined.

\def\docheckspecialreference%
  {\let\referenceprefix=\empty
   \let\unharmedreferenceprefix=\empty
   \xdef\predefinedreference%
     {\currentreferencespecial::\currentreferenceoperation}%
   \doifdefinedelse{\s!do\v!test\currentreferencespecial}
     {\getvalue{\s!do\v!test\currentreferencespecial}
        {\global\referencefoundtrue}
        {\global\referencefoundfalse}}
     {\global\referencefoundtrue}%
   \doifpredefinedreferenceelse{\global\referencefoundfalse}{}}

%D An unknown reference is reported on the screen, in the log
%D file and, when enabled, in the left margin of the text.

\def\reportreferenceerror#1#2%
  {\ifvoorlopig\ifinpagebody\else
     \doifsomething{#2}
       {\inlinker
          {\infofont
           \dimen0=\linkermargebreedte
           \advance\dimen0 by -2em
           \doboundtext{#2}{\dimen0}{..}->}}%
   \fi\fi
   \doifpredefinedreferenceelse
     {}
     {\predefinereference
      \showmessage{\m!references}{#1}{[\unharmedreferenceprefix][#2]}}}

\def\unknownreference%
  {\reportreferenceerror1}

\def\illegalreference%
  {\reportreferenceerror4}

%D Although not actually needed, we default the unharmed
%D reference prefix to the normal one.

\def\unharmedreferenceprefix%
  {\referenceprefix}

%D When a reference is not found, we typeset a placeholder
%D (two glyphs are often enough to represent the reference
%D text).

\def\dummyreference%
  {{\tttf ??}}

%D To prevent repetitive messages concerning a reference
%D being defined, we set such an unknown reference to an empty
%D one after the first encounter.

\let\predefinedreference=\s!unknown

%\def\predefinereference%
%  {\setgvalue{\r!cross\predefinedreference}{\rt!cross{}{}{}{}}}

%\def\predefinereference%
%  {\setgvalue{\r!cross\unharmedreferenceprefix\predefinedreference}{\rt!cross{}{}{}{}}}

\def\predefinereference%
  {\setgvalue{\r!cross\predefinedreference}{\rt!cross{}{}{}{}}%
   \setgvalue{\r!cross\unharmedreferenceprefix\predefinedreference}{\rt!cross{}{}{}{}}}

%D Testing on existance then becomes:

\def\checkpredefinedreference#1#2#3#4% #3 can expand tricky
  {{#1}{#2}{#4}}

\def\doifpredefinedreferenceelse#1#2%
  {\bgroup
   \let\rt!cross\checkpredefinedreference
   \doifelse{\getvalue{\r!cross\predefinedreference}}{{}{}{}}
     {\egroup#1}{\egroup#2}}

%D Sometimes we want to temporary put a reference out of
%D order. An example can be found in the menu macros.
%D
%D \starttypen
%D \doifreferencepermitedelse{reference}{set}{true}{false}
%D \stoptypen
%D
%D The second argument can be a comma seperated list.

\def\doifreferencepermitedelse#1#2#3#4% ref set found notfound
  {\doifreferencefoundelse{#1}
     {\ifx\currentinnerreference\empty
        \ifx\currentouterreference\empty
          #3%
        \else
          \doifinstringelse{\currentouterreference::}{#2}{#4}{#3}%
        \fi
      \else\ifx\currentouterreference\empty
        \doifinstringelse{\currentinnerreference}{#2}{#4}{#3}%
      \else
        \doifinstringelse{\currentouterreference::\currentinnerreference}{#2}{#4}{#3}%
      \fi\fi}
     {#4\unknownreference{#1}}}

%D Apart from cross references supplied by the user, \CONTEXT\
%D generates cross references itself. Most of them are not
%D saved as a reference, but stored with their source, for
%D instance a list or an index entry. Such automatically
%D generated, for the user invisible, references are called
%D {\em internal references}. The user supplied ones are
%D labeled as {\em external references}.
%D
%D A second important characteristic is that when we want to
%D support different backends (viewers), we need to support
%D named destinations as well as page numbers. I invite readers
%D to take a glance at the special driver modules to understand
%D the fine points of this. As a result we will deal with {\em
%D locations} as well as {\em real page numbers}. We explictly
%D call this pagenumber a real one, because it is independant
%D of the page numbering scheme used in the document.
%D
%D One of the reasons for \CONTEXT\ being the first \TEX\ base
%D macropackage to support sophisticated interactive \PDF\
%D files, lays in the mere fact that real page numbers are
%D available in most two pass data, like references, list data
%D and index entries.
%D
%D We will speak of \type{thisis...} when we are marking a
%D location, and \type{goto...} when we point to such a
%D location. The latter one can be seen as a hyperlink to the
%D former one. In the next macros one we use constructs like:
%D
%D \starttypen
%D \dostart...
%D \dostop...
%D \stoptypen
%D
%D Such macros are used to invoke the relevant specials from
%D the special driver modules (see \type{spec-ini}). The flag
%D \type{\iflocation} signals if we're in interactive mode.

\def\thisisdestination#1% destination
  {\iflocation
     \ifusepagedestinations \else
       \dostartthisislocation{#1}%
       \dostopthisislocation
     \fi
   \fi}

\def\thisisrealpage#1% pagenumber
  {\iflocation
     \dostartthisisrealpage{#1}%
     \dostopthisisrealpage
   \fi}

%D The previous tho macros were easy ones, opposite to their
%D counterparts. A common component in these is:
%D
%D \starttypen
%D \dostartgoto
%D   \data  {..}
%D   \start {..}
%D   \stop  {..}
%D \dostopgoto
%D \stoptypen
%D
%D Here data can be whatever needs highlighting, e.g. {\em
%D figure 2.4}, and the start and stop entries handle the
%D specials. The two \DIMENSIONS\ \type{\buttonwidth} and
%D \type{\buttonheight} have to be set when handling the
%D data~(\type{#2}).

\ifx\buttonheight\undefined \newdimen\buttonheight \fi
\ifx\buttonwidth \undefined \newdimen\buttonwidth  \fi

\def\gotodestination#1#2#3#4#5% url file destination page data
  {\iflocation
     \ifusepagedestinations
       \gotorealpage{#1}{#2}{#4}{#5}%
     \else
       \dostartgoto
         \data
           {#5}%
         \start
           \dostartgotolocation
             {\number\buttonwidth}{\number\buttonheight}
             {#1}{#2}{#3}{#4}%
         \stop
           \dostopgotolocation
       \dostopgoto
     \fi
   \else
     {#5}%
   \fi}

\def\gotorealpage#1#2#3#4% url file page data
  {\iflocation
     \dostartgoto
       \data
         {#4}%
       \start
         \dostartgotorealpage
           {\number\buttonwidth}{\number\buttonheight}
           {#1}{#2}{#3}%
       \stop
         \dostopgotorealpage
     \dostopgoto
   \else
     {#4}%
   \fi}

%D Internal references can best be set using the next few
%D macros. Setting such references to unique values is
%D completely up to the macros that call them.
%D
%D \starttypen
%D \thisissomeinternal{tag}{identifier}
%D \gotosomeinternal  {tag}{identifier}{pagenumber}{text}
%D \stoptypen

\def\thisissomeinternal#1#2%  tag reference
  {\doifsomething{#2}{\thisisdestination{#1:#2}}}

\def\gotosomeinternal#1#2#3#4%
  {\gotodestination{}{}{#1:#2}{#3}{#4}}

%D An automatic mechanism is provided too:
%D
%D \starttypen
%D \thisisnextinternal{tag}
%D \gotonextinternal  {tag}{number}{pagenumber}{text}
%D \stoptypen
%D
%D The first macro increments a counter. The value of this
%D counter is available in the macro \type{\nextinternalreference}
%D and should be saved somewhere (for instance in a file) for
%D future reference. The second argument of
%D \type {\gotonextinternal} takes such a saved number. One can
%D turn on tracing these references, in which case the
%D references are a bit more verbose.

\newcount\locationcount

\newif\iftraceinternalreferences

\def\nextinternalreference%
  {\the\locationcount}

\def\thisisnextinternal#1%
  {\global\advance\locationcount by 1
   \thisisdestination{\s!aut\iftraceinternalreferences:#1\fi:\nextinternalreference}}

\def\gotonextinternal#1#2#3#4%
  {\gotodestination{}{}{\s!aut\iftraceinternalreferences:#1\fi:#2}{#3}{#4}}

%D We already went through a lot of problems to sort out what
%D kind of reference we're dealing with. Sorting out the user
%D supplied cross references (show/goto this or that) as well
%D as user supplied system references (invoke this or that) is
%D already taken care of in the test routine, but we still have
%D to direct the request to the right routine.

\def\gotolocation#1#2%
  {\ifx\currentreferencespecial\empty
     \ifx\currentouterreference\empty
       \ifnum\currentreferencetype<2
         \gotoinnerlocation{#1}{#2}%
       \else
         \gotosystemlocation{#1}{#2}%
       \fi
     \else
       \gotoouterlocation{#1}{#2}%
     \fi
   \else
     \gotospeciallocation{#1}{#2}%
   \fi}

%D An inner reference refers to some place in the document
%D itself.

\def\gotoinnerlocation#1#2%
  {\gotodestination
     {}{}
     {\referenceprefix\currentinnerreference}{\currentrealreference}
     {#2}}

%D The outer location refers to another document, specified as
%D file or \URL.

\def\gotoouterlocation#1#2% % page checken!
  {\bgroup
   \let\referenceprefix=\empty
   \setouterlocation{\currentouterreference}%
   \ifx\currentinnerreference\empty
     \gotorealpage
       {\otherURL}{\otherfile}{1}
       {#2}%
   \else
     \gotodestination
       {\otherURL}{\otherfile}{\currentinnerreference}{\currentrealreference}
       {#2}%
   \fi
   \egroup}

%D Special locations are those that are accessed by saying
%D things like:
%D
%D \starttypen
%D \goto{calculate total}[JS(summarize{10,23,56}]
%D \stoptypen
%D
%D After several intermediate steps this finally arrives at
%D the next macro and expands into (simplified):
%D
%D \starttypen
%D \gotoJSlocation{total{summarize{10,23,56}}}{calculate total}
%D \stoptypen
%D
%D The first argument is the full reference, the second one
%D is the text, in some kind of manipulated form. In practice
%D we split references, so we get:
%D
%D \starttypen
%D \gotoJSlocation{summarize{10,23,56}}{calculate}
%D \gotoJSlocation{summarize{10,23,56}}{total}
%D \stoptypen
%D
%D where \type{calculate} and \type{total} are colored, boxed
%D or whatever \type{\goto} is told to do.
%D
%D The macro \type{\gotoJSlocation} can use \type
%D {\currentreferenceoperation} (in our example
%D \type{summarize}) and \type{\currentreference} (here
%D being \type {10,23,56}) to perform its task.

\def\gotospeciallocation%
  {\executeifdefined
     {goto\currentreferencespecial location}\gobbleoneargument}

%D Such special macros can be defined by:

\def\definespeciallocation#1%
  {\setvalue{goto#1location}}

%D The associated test is to be defined by:

\def\definespecialtest#1%
  {\setvalue{\s!do\v!test#1}}

%D This \type{\def} alike macro is to be used as:
%D
%D \starttypen
%D \definespeciallocation{JS}#1#2{... #1 ... #2 ...}
%D \stoptypen
%D
%D In module \type {core-jav} one can see that \type
%D {\gotoJSlocation} looks much like the previous goto
%D definitions.

%D A system location is not always a location, but for the
%D consistency we also consider actions as such.

\def\gotosystemlocation%
  {\getvalue{\r!syst\the\currentreferencetype}}

\def\definesystemreferencehandler#1#2%
  {\setgvalue{\r!syst\the#1}{#2}}

%D In this module we define three system references: one for
%D handling navigational, viewer specific, commands, another
%D for jumping to special pages, like the first or last one,
%D and a third reference for linking tree like lists, like
%D tables of contents. The latter two adapt themselves to the
%D current state.

\definesystemreferencehandler \rt!exec \handleexecreference
\definesystemreferencehandler \rt!page \handlepagereference
\definesystemreferencehandler \rt!list \handlelistreference

\def\handleexecreference#1%
  {\executecommand{\currentdatareference}{\currentreferencearguments}}

\def\handlepagereference#1%
  {\gotorealpage{}{}{\currentdatareference}}

\def\handlelistreference#1% is deze nog echt nodig?
  {\gotodestination{}{}{\currentdatareference}{\getvalue{\currentdatareference}}}

%D Command references (in dutch, english, german of
%D whatever interface language) are translated into a bit
%D shorter reference (\type{close}) and passed to the
%D special driver (using \type{\executecommand}).

% better: [command(name)] and \definereference[name][command(name)]

\setglobalsystemreference \rt!exec \v!CloseDocument  {close}
\setglobalsystemreference \rt!exec \v!ExitViewer     {exit}
\setglobalsystemreference \rt!exec \v!FirstPage      {first}
\setglobalsystemreference \rt!exec \v!LastPage       {last}
\setglobalsystemreference \rt!exec \v!NextJump       {forward}
\setglobalsystemreference \rt!exec \v!NextPage       {next}
\setglobalsystemreference \rt!exec \v!PauseMovie     {pause}
\setglobalsystemreference \rt!exec \v!PreviousJump   {backward}
\setglobalsystemreference \rt!exec \v!PreviousPage   {previous}
\setglobalsystemreference \rt!exec \v!PrintDocument  {print}
\setglobalsystemreference \rt!exec \v!SaveForm       {export}
\setglobalsystemreference \rt!exec \v!LoadForm       {import}
\setglobalsystemreference \rt!exec \v!ResetForm      {reset}
\setglobalsystemreference \rt!exec \v!ResumeMovie    {resume}
\setglobalsystemreference \rt!exec \v!SaveDocument   {save}
\setglobalsystemreference \rt!exec \v!SearchAgain    {searchagain}
\setglobalsystemreference \rt!exec \v!SearchDocument {search}
\setglobalsystemreference \rt!exec \v!StartMovie     {start}
\setglobalsystemreference \rt!exec \v!StopMovie      {stop}
\setglobalsystemreference \rt!exec \v!SubmitForm     {submit}
\setglobalsystemreference \rt!exec \v!SwapViewer     {swap}
\setglobalsystemreference \rt!exec \v!ViewerHelp     {help}
\setglobalsystemreference \rt!exec \v!HideField      {hide}
\setglobalsystemreference \rt!exec \v!ShowField      {show}

%D Executing the command looks alike the previous goto macros.

\def\executecommand#1#2#3%
  {\iflocation
     \dostartgoto
       \data
         {#3}%
       \start
         \dostartexecutecommand
           {\number\buttonwidth}{\number\buttonheight}
           {#1}{#2}%
       \stop
         \dostopexecutecommand
     \dostopgoto
   \else
     {#3}%
   \fi}

%D We could have done without the short tags and thereby saving
%D some tokens, but the current approach leaves room for future
%D extensions.

%D It is possible to disable the writing of references to the
%D utility file by setting:

\newif\ifreferencing \referencingtrue

%D One can also activate an automatic prefix mechanism. By
%D setting the \type{\prefix} variable to \type{+}, the prefix
%D is incremented, when set to \type{-} or empty, the prefix is
%D reset. Other values become the prefix.

\newcount\prefixcounter

%D These settings are accomplished by:
%D
%D \showsetup{\y!setupreferencing}
%D
%D In interactive documents verbose references don't always
%D make sense (what is a page number in an unnumbered
%D document). By setting the \type{interaction} variable, one
%D can influences the way interactive references are set.

\def\setupreferencing%
  {\dosingleargument\dosetupreferencing}

\def\dosetupreferencing[#1]%
  {\getparameters
     [\??rf]
     [\c!prefix=\s!unknown,#1]%
   \processaction
     [\@@rfstatus]
     [  \v!stop=>\referencingfalse,
       \v!start=>\referencingtrue]%
   \processaction
     [\@@rfinteractie]
     [  \v!alles=>\let\dowantedreference=\docompletereference,
        \v!label=>\let\dowantedreference=\dolabelonlyreference,
        \v!tekst=>\let\dowantedreference=\dotextonlyreference,
      \v!symbool=>\let\dowantedreference=\dosymbolreference]%
   \ifx\@@rfprefix\s!unknown
     % retain the current value
   \else\ifx\@@rfprefix\empty
     \let\referenceprefix=\empty
   \else\ifx\@@rfprefix\incrementreferenceprefix
     \advance\prefixcounter by 1
     \edef\referenceprefix{\the\prefixcounter:}%
   \else\ifx\@@rfprefix\decrementreferenceprefix
     \let\referenceprefix=\empty
   \else
     \edef\referenceprefix{\@@rfprefix:}%
   \fi\fi\fi\fi}

\def\incrementreferenceprefix{+}
\def\decrementreferenceprefix{-}

%D \macros
%D   {handlereferenceactions,
%D    collectreferenceactions}
%D
%D Sometimes we need to pass the actions connected to
%D references to variables instead of rectangular areas on
%D which one can click. The next macro collects the actions
%D and passes them to a handle. This is a rather dreadfull
%D hack!
%D
%D \starttypen
%D \handlereferenceactions{references}\handle
%D \stoptypen
%D
%D So, \type {\handle} does the final job, which in for
%D instance the \PDF\ drivers comes down to doing something
%D with \type {\lastPDFaction}.

\newif\ifcollectreferenceactions

\def\handlereferenceactions#1#2%
  {\doifsomething{#1}
     {\bgroup
      \collectreferenceactionstrue
      \@EA\doifreferencefoundelse\@EA{#1}
        {\gotolocation{#1}{}\ifsecondaryreference\else#2\fi}
        {\unknownreference{#1}}%
      \egroup}}

%D The most straightforward way of retrieving references is
%D using \type{\ref}. Consider the reference:
%D
%D \startbuffer
%D \reference[my ref]{{Look}{Here}{I am}}
%D \stopbuffer
%D
%D \typebuffer
%D
%D \haalbuffer
%D
%D We can ask for upto five reference components:
%D
%D \startbuffer
%D user page reference:  \ref[p][my ref]
%D text reference:       \ref[t][my ref]
%D real page reference:  \ref[r][my ref]
%D sub text reference:   \ref[s][my ref]
%D extra text reference: \ref[e][my ref]
%D \stopbuffer
%D
%D \typebuffer
%D
%D And get back:
%D
%D \startregels
%D \haalbuffer
%D \stopregels

\def\ref%
  {\dodoubleargument\doref}

\def\reftypep{\currentpagereference}
\def\reftypet{\currenttextreference}
\def\reftyper{\currentrealreference}
\def\reftypes{\currentsubtextreference}
\def\reftypee{\currentsubsubtextreference}

\def\doref[#1][#2]%
  {\ifsecondargument
     \doifreferencefoundelse{#2}
       {\doifundefinedelse{reftype#1}{\reftypep}{\getvalue{reftype#1}}}
       {\unknownreference{#2}\dummyreference}%
   \else
     \dummyreference
   \fi}

%D We can typeset a reference using \type{\in}, \type{\at} and
%D \type{\about} and goto specific locations using
%D \type{\goto}. The last one does not make that much sense in
%D a paper document. To complicate things, \PLAIN\ \TEX\ also
%D implements an \type {\in} but fortunately that one only
%D makes sense in math mode.

%D --- VANAF HIER NOG VERENGELSEN ---

\let\donormalin  =\in
\let\donormalover=\over % about/oppassen beter nederlands dan engels!

\def\in%
  {\ifmmode
     \expandafter\donormalin
   \else
     \expandafter\doinatreference\expandafter\currenttextreference
   \fi}

\def\op%
  {\doinatreference\currentpagereference}

\def\over%
  {\ifmmode
     \expandafter\donormalover
   \else
     \expandafter\dospecialover
   \fi}

\unexpanded\def\dospecialover[#1]%
  {\bgroup
   \def\thecurrentsubtextreference%
     {\limitatetext{\currentsubtextreference}{\@@rfbreedte}{...}}%
   \leaveoutervmode
   \@@rflinks
   \doifreferencefoundelse{#1}
     {\let\crlf\space
      \let\\\space
      \let\donaarfixed\donaarspace
      \donaarspace{\thecurrentsubtextreference}[#1]}
     {\unknownreference{#1}\dummyreference}%
   \@@rfrechts
   \referentieinfo{<}{#1}%
   \egroup}

%D Typesetting the reference is a bit more complicated than one
%D would at first sight expect. This is due to the fact that we
%D distinguish three (five) alternative calls:
%D
%D \plaatsfiguur
%D   [hier][three calls]
%D   {Three alternatives reference calls.}
%D   \startcombinatie[1*3]
%D     {\framed{\type{ \in }}} {a}
%D     {\framed{\type{ \at }}} {b}
%D     {\framed{\type{\goto}}} {c}
%D  \stopcombinatie
%D
%D \startbuffer
%D \in figure[fig:three calls]
%D \in{figure}[fig:three calls]
%D \in figure a[fig:three calls]
%D \in{figure}{a}[fig:three calls]
%D figure~\in[fig:three calls]
%D \stopbuffer
%D
%D \typebuffer
%D
%D This turns up as:
%D
%D \startregels
%D \haalbuffer
%D \stopregels
%D
%D The dual \type{{}} results in a split reference. In a
%D document meant for paper, one is tempted to use the last
%D (most straightforward) alternative. When a document is also
%D meant voor electronic distribution, the former alternatives
%D have preference, because everything between the \type{\in}
%D and~\type{[} becomes active (and when asked for, typeset
%D in a different color and typeface).

\def\doinatreference#1%
  {\doifnextcharelse{[}
     {\dodoinatreference{#1}{}}
     {\dodoinatreference{#1}}}

\def\dodoinatreference#1%
  {\def\dododoinatreference{\dodododoinatreference{#1}}%
   \futurelet\next\dododoinatreference}

\def\dodododoinatreference#1#2#3[#4]%
  {\ifx\next\bgroup
     \dododododoinatreference{#1\ignorespaces#3}{#2}[#4]%
   \else
     \dododododoinatreference{#1}{#2#3}[#4]%
   \fi}

%D We arrived at the last step. Before we do the typesetting,
%D we forget all previous (paragraph bound) settings and make
%D sure that we remain in horizontal mode. Next we choose
%D among the several representations.

\def\dododododoinatreference#1#2[#3]%
  {\bgroup
   \forgetall
   \leaveoutervmode
   \doifreferencefoundelse{#3}
     {\doifelsenothing{#1}
        {\dosymbolreference{#1}{#2}[#3]}
        {\dowantedreference{#1}{#2}[#3]}}
     {\dounknownreference{#1}{#2}[#3]}%
   \referentieinfo{<}{#3}%
   \egroup}

%D The previously discussed setup macro lets us specify the
%D representation of references. A symbol reference does not
%D show the specific data, like the number of a figure, but
%D shows one of: \hbox {$^\goforwardcharacter$
%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending
%D on the direction to go.

\def\dosymbolreference#1#2[#3]%
  {\bgroup
   \setupsymbolset[\@@iasymboolset]%
   \ifhmode\unskip\fi
   \ifx\currentreferencespecial\empty
     \ifx\currentouterreference\empty
       \ifnum0\currentrealreference=0
         \ifhmode\strut$^{\symbol[\v!nergens]}$\fi
       \else\ifnum0\currentrealreference>\realpageno
         \dodosymbolreference{#2}{$^{\symbol[\v!volgende]}$}%
       \else\ifnum0\currentrealreference<\realpageno
         \dodosymbolreference{#2}{$^{\symbol[\v!vorige]}$}%
       \else
         \ifhmode\strut$^{\symbol[\v!nergens]}$\fi
       \fi\fi\fi
     \else
       \gotoouterlocation{#3}{\showlocation{$^{\symbol[\v!ergens]}$}}%
     \fi
   \else
     \gotospeciallocation{#3}{\showlocation{$^{\symbol[\v!ergens]}$}}%
   \fi
   \egroup}

\def\dodosymbolreference#1#2%
  {#1\hbox{\gotorealpage{}{}{\currentrealreference}
    {\dolocationattributes\??ia\c!letter\c!kleur{#2}}}}

%D The other alternatives just conform their names: only the
%D label, only the text, or the label and the text.

\def\dounknownreference#1#2[#3]%
  {\unknownreference{#3}\dotextprefix{#2}\dummyreference}%

\def\docompletereference#1#2[#3]%
  {\doifsomespaceelse{#2}
     {\doifsomething{#2}{\donaarspace{#2}[#3]~}\donaarfixed{#1}[#3]}
     {\donaarfixed{\dotextprefix{#2}#1}[#3]}}

% VEEL BETER:

\def\docompletereference#1#2[#3]%
  {\doifsomespaceelse{#2}
     {\donaarspace{\dotextprefix{#2}#1}[#3]}
     {\donaarfixed{\dotextprefix{#2}#1}[#3]}}

\def\dolabelonlyreference#1#2[#3]%
  {\doifsomespaceelse{#2}
     {\doifsomething{#2}{\donaarspace{#2}[#3]}}
     {\donaarfixed{\dotextprefix{#2}}[#3]}}

\def\dotextonlyreference#1#2[#3]%
  {\dotextprefix{#2}\donaarfixed{#1}[#3]}

\let\dowantedreference=\docompletereference

%D --- OF MEER, OF ANDERS: ---

\def\dotextprefix#1%
  {\ConvertToConstant\doifnot{#1}{}{#1~}}

%D In interactive documents going to a specific location is not
%D bound to cross references. The \type{\goto} commands can be
%D used to let users access another part of the document. In
%D this respect, interactive tables of contents and registers
%D can be considered goto's. Because in fact a \type{\goto} is
%D just a reference without reference specific data, the
%D previous macros are implemented using the goto
%D functionality.
%D
%D \showsetup{\y!naar}
%D
%D One important chaacteristic is that the first argument of
%D \type{\goto} (and therefore \type{\at} and \type{\in} is
%D split at spaces. This means that, although hyphenation is
%D prevented, long references can cross line endings.

%\unexpanded\def\naar#1[#2]%
%  {\leaveoutervmode
%   \doifreferencefoundelse{#2}
%     {\doifelsenothing{#1}
%        {\dosymbolreference{}{}[#2]}
%        {\donaarspace{#1}[#2]}}
%     {\unknownreference{#2}#1}%
%   \referentieinfo{<}{#2}}

\def\donaar#1[#2]%
  {\leaveoutervmode
   \doifreferencefoundelse{#2}
     {\doifelsenothing{#1}
        {\dosymbolreference{}{}[#2]}
        {\donaarspace{#1}[#2]}}
     {\unknownreference{#2}#1}%
   \referentieinfo{<}{#2}}

\unexpanded\def\naar#1#2%
  {\donaar{#1}#2}

\newif\ifsharesimilarreferences \sharesimilarreferencestrue
\newcount\similarreference % 0=noppes 1=create/refer 2,3,..=refer

\def\donaarspace#1[#2]%
  {\ifsecondaryreference\setbox0=\hbox\fi % due to space insertion
   {\let\donaarspace=\donaarfixed
    \iflocation
      \def\processisolatedword##1%
        {\ifisolatedwords\ifsharesimilarreferences
           \global\advance\similarreference by 1
         \fi\fi
         \hbox{\gotolocation{#2}{##1\presetgoto}}}%
      \doattributes\??ia\c!letter\c!kleur
        {\processisolatedwords{#1}\processisolatedword}%
      \global\similarreference=0
    \else
      #1\relax % \relax prevents #1's next macros from gobbling \fi
    \fi}}

\def\donaarfixed#1[#2]%
  {{\iflocation
      \hbox{\gotolocation{#2}{\doattributes\??ia\c!letter\c!kleur
        {#1\presetgoto}}}%
    \else
      #1%
    \fi}}

%D In case the auto split feature is not needed or even not
%D even wanted, \type{\gotobox} can be used.

%D --- NOG IN HANDLEIDING ---

\unexpanded\def\naarbox#1[#2]%
  {\bgroup
   \locationstrutfalse
   \leaveoutervmode
   \doifreferencefoundelse{#2}
     {\donaarfixed{#1}[#2]}
     {\hbox{\unknownreference{#2}#1}}%
   \referentieinfo{<}{#2}%
   \egroup}

%D An reference to another document can be specified as a file
%D or as an \URL. Both are handled by the same mechanism and
%D can be issued by saying something like:
%D
%D \starttypen
%D \goto[dictionary::the letter a]
%D \stoptypen
%D
%D The macros that are responsible for handling these
%D references, use the next six variables:

\let\otherlabel   = \empty
\let\fileprefix   = \empty
\def\otherfile      {\jobname}
\let\otherURL     = \empty
\let\otherprefix  = \empty
\let\dowithdocdes = \empty

%D One can imagine that many references to such a dictionary
%D are made, so in most cases such a document reference in an
%D indirect one.
%D
%D \showsetup{\y!gebruikexterndocument}
%D
%D For example:
%D
%D \starttypen
%D \useexternaldocument
%D   [dictionary][engldict]
%D   [The Famous English Dictionary]
%D \stoptypen
%D
%D The next macro implements these relations, and also take
%D care of loading the document specific references.

\def\gebruikexterndocument%
  {\dotripleargument\dogebruikexterndocument}

\def\dogebruikexterndocument[#1][#2][#3]%
  {\bgroup
   \doifelsenothing{#1}
     {\dogebruikexterndocument[#2][#2][#3]}
     {\doifelsenothing{#3}
        {\dogebruikexterndocument[#1][#2][#2]}
        {\doifsomething{#2}
           {\setgvalue{\v!file:::#1}{\doexternaldocument[][#2][#3]}% just \do
            \doifparentfileelse{#2}
              {\showmessage{\m!references}{21}{#2}}
              {\bgroup  % prevents wrong loading of \jobname
                 \def\fileprefix{#1::}%
                 \let\setglobalcrossreference=\setoutercrossreference
                 \usereferences[#2]%
               \egroup  % when called nested
               \showmessage{\m!references}{21}{#2}}}}}%
   \egroup}

%D The \URL\ alternative takes four arguments:
%D
%D \showsetup{\y!gebruikURL}
%D
%D like:
%D
%D \starttypen
%D \useURL
%D   [dictionary][http://www.publisher.com/public][engldict]
%D   [The Famous English Dictionary]
%D \stoptypen
%D
%D Several specifications are possible:
%D
%D \starttypen
%D \useURL [id] [url] [file] [description]
%D \useURL [id] [url] [file]
%D \useURL [id] [url]
%D \stoptypen
%D
%D This time we don't load the references when no file is
%D specified. This is logical when one keeps in mind that a
%D valid \URL\ can also be a mail address.

\def\gebruikURL%
  {\bgroup
   \catcode`\#=12\catcode`\%=12
   \catcode`\_=12\catcode`\~=12
   \dodoubleempty\dogebruikURL}

\def\dogebruikURL[#1][#2]%
  {\egroup\doquadrupleempty\dodogebruikURL[#1][#2]}

\def\dodogebruikURL[#1][#2][#3][#4]%
  {\iffirstargument
     \iffourthargument
       \setgvalue{\v!file:::#1}{\doexternaldocument[#2][#3][#4]}%
     \else\ifthirdargument
       \setgvalue{\v!file:::#1}{\doexternaldocument[#2][#3][{\url[#1]}]}%
     \else\ifsecondargument
       \setgvalue{\v!file:::#1}{\doexternaldocument[#2][][{\url[#1]}]}%
     \fi\fi\fi
   \fi}

\let\gebruikurl=\gebruikURL

%D \macros
%D   {url,setupurl}
%D
%D We also have: \type{\url} for directly calling the
%D description. So we can say:
%D
%D \starttypen
%D \useURL [one] [http://www.test.nl]
%D \useURL [two] [http://www.test.nl] [] [Some Site]
%D
%D \url[one] or \from[two] or \goto{Whatever Site}[URL(two)]
%D \stoptypen
%D
%D An \URL\ can be set up with
%D
%D \showsetup{\y!setupurl}

\def\setupurl%
  {\dodoubleargument\getparameters[\??ur]}

\unexpanded\def\url[#1]%
  {\bgroup
   \processaction
%     [\@@rfurlvariant]
     [\@@urvariant]
     [ \v!geen=>\chardef\urlsplitmode=0,
      \v!beide=>\chardef\urlsplitmode=1,
         \v!na=>\chardef\urlsplitmode=2,
       \v!voor=>\chardef\urlsplitmode=3]%
%   \doifelse{\@@rfurlspatie}{\v!ja}
   \doifelse{\@@urspatie}{\v!ja}
     {\setbetweenisolatedwords%
        {\scratchskip\currentspaceskip
         \hskip\!!zeropoint\!!plus.2\scratchskip}}
     {\setbetweenisolatedwords\allowbreak}%
   \def\doexternaldocument[##1][##2][##3]{\hyphenatedurl{##1}}%
   \dostartattributes\??ur\c!letter\c!kleur{}%
   \getvalue{\v!file:::#1}%
   \dostopattributes
   \egroup}

%D This macro is hooked into a support macro, and thereby
%D \URL's break ok, according to the setting of a switch,
%D
%D \startbuffer
%D \gebruikURL
%D   [test]
%D   [sentence_sentence%sentence#sentence~sentence/sentence//sentence:sentence.sentence]
%D \stopbuffer
%D
%D \typebuffer
%D
%D Such an \URL\ is, depending on the settings, hyphenated as:
%D
%D \haalbuffer
%D
%D \startregelcorrectie
%D \hbox to \hsize
%D   {\hss\en
%D    \stelrefererenin[urlvariant=beide]%
%D    \vbox{\hsize.25cm\hbox{\bf both}\prewordbreak\url[test]}%
%D    \hss
%D    \stelrefererenin[urlvariant=voor]%
%D    \vbox{\hsize.25cm\hbox{\bf before}\prewordbreak\url[test]}%
%D    \hss
%D    \stelrefererenin[urlvariant=na]%
%D    \vbox{\hsize.25cm\hbox{\bf after}\prewordbreak\url[test]}%
%D    \hss}
%D \stopregelcorrectie
%D
%D By setting \type{urlspace=yes} one can get slightly better
%D spacing when using very long \URL's.

%D Many macro definitions ago we called for the auxiliary macro
%D \type{\setouterlocation} and now is the time to define this
%D one.

\def\setouterlocation#1%
  {\doifdefinedelse{\v!file:::#1}
     {\def\doexternaldocument[##1][##2][##3]%
        {\edef\otherURL{##1}%
         \edef\otherfile{##2}}%
      \getvalue{\v!file:::#1}}
     {\let\otherURL=\empty
      \edef\otherfile{#1}}%
   \doifparentfileelse{\otherfile}
     {\let\otherURL=\empty
      \let\otherfile=\empty
      \global\let\otherlabel=\empty
      \let\otherprefix=\empty}
     {\xdef\otherlabel{#1}%
      \edef\otherprefix{#1::}}}

%D When defining the external source of information, one can
%D also specify a suitable name (the last argument). This name
%D can be called upon with:
%D
%D \showsetup{\y!uit}
%D
%D As can be expected, this macro used \type{\goto} to
%D perform its task.

\definecomplexorsimple\uit

\def\simpleuit%
  {\bgroup
   \doifdefinedelse{\v!file:::\otherlabel}
     {\def\doexternaldocument[##1][##2][##3]{##3}%
      \getvalue{\v!file:::\otherlabel}}
     {\tttf[\otherlabel]}%
   \egroup}

\def\complexuit[#1]%
  {\doifinstringelse{::}{#1}
     {\docomplexuit[#1]}
     {\docomplexuit[#1::]}}

\def\docomplexuit[#1::#2]%
  {\bgroup
   \doifdefinedelse{\v!file:::#1}
     {\def\doexternaldocument[##1][##2][##3]%
        {\naar{##3}[#1::#2]}%
      \getvalue{\v!file:::#1}}
     {\tttf[#1]}%
   \egroup}

%D We also support:
%D
%D \starttypen
%D \goto{some text}[file(identifier{location}]
%D \stoptypen
%D
%D which is completely equivalent with
%D
%D \starttypen
%D \goto{some text}[identifier::location]
%D \stoptypen
%D
%D The fastest implementation would be:

\definespecialtest\v!file     {\handlespecialFILEandURL}
\definespecialtest\v!URL      {\handlespecialFILEandURL}
\definespecialtest\v!url      {\handlespecialFILEandURL}

\definespeciallocation\v!file {\handlespecialallocationFILEandURL}
\definespeciallocation\v!URL  {\handlespecialallocationFILEandURL}
\definespeciallocation\v!url  {\handlespecialallocationFILEandURL}

\def\handlespecialFILEandURL%
  {\doifreferencefoundelse
     {\currentreferenceoperation::\currentreferencearguments}}

\def\handlespecialallocationFILEandURL%
  {\let\currentouterreference=\currentreferenceoperation
   \let\currentinnerreference=\currentreferencearguments
   \let\currentreferenceoperation=\empty
   \let\currentreferencearguments=\empty
   \gotoouterlocation}

%D Now we have file references as special ones, it's rather
%D logical to have the viewer specific ones available in a dual
%D way too. At first glance we could do with:
%D
%D \starttypen
%D \definespeciallocation\v!actie
%D   {\getreferenceelements\currentreferenceoperation
%D    \handleexecreference}
%D \stoptypen
%D
%D An better alternative, slower but error aware, is

\definespecialtest\v!actie%
  {\doifreferencefoundelse\currentreferenceoperation}

\definespeciallocation\v!actie
  {\handleexecreference}

%D So now we can say:
%D
%D \starttypen
%D \goto{some action}[PreviousJump]
%D \stoptypen
%D
%D as well as:
%D
%D \starttypen
%D \goto{some text}[action(PreviousJump]
%D \stoptypen

%D A special case of references are those to programs. These,
%D very system dependant references are implemented by abusing
%D some of the previous macros.
%D
%D \showsetup{\y!stelprogrammasin}
%D \showsetup{\y!definieerprogramma}
%D \showsetup{\y!programma}
%D
%D The latter gives access to the description of the program,
%D being the last argument to the definition command.

\def\stelprogrammasin%
  {\dodoubleargument\getparameters[\??pr]}

\def\dodefinieerprogramma[#1][#2][#3]%
  {\setgvalue{\v!programma:::#1}{\doprogramma{#2}{#3}}}

\def\definieerprogramma%
  {\dotripleargument\dodefinieerprogramma}

\def\programma#1[#2]%
  {\bgroup
   \doifdefinedelse{\v!programma:::#2}
     {\def\doprogramma##1##2%
        {\doifelsenothing{#1}
           {\naar{##2}[\v!programma(#2)]}
           {\naar{#1}[\v!programma(#2)]}}%
      \getvalue{\v!programma:::#2}}
     {\tttf[#2]}%
   \egroup}

\definespeciallocation\v!programma#1#2%
  {\bgroup
   \iflocation
     \doifdefinedelse{\v!programma:::\currentreferenceoperation}
       {\def\doprogramma##1##2{\def\@@programfile{##1}}%
        \getvalue{\v!programma:::\currentreferenceoperation}}
       {\let\@@programfile=\currentreferenceoperation}%
     \convertcommand\@@programfile\to\ascii
     \dostartgoto
       \data
         {#2}%
       \start
         \dostartrunprogram
           {\number\buttonwidth}{\number\buttonheight}
           {\@@prgebied\ascii\space\currentreferencearguments}%
       \stop
         \dostoprunprogram
     \dostopgoto
   \else
     {#2}%
   \fi
   \egroup}

%D As we can see, we directly use the special reference
%D mechanism, which means that
%D
%D \starttypen
%D \goto{some text}[program(name{args})]
%D \stoptypen
%D
%D is valid.

%D The next macro provides access to the actual pagenumbers.
%D When documenting and sanitizing the original reference
%D macros, I decided to keep the present meaning as well as to
%D make this meaning available as a special reference method.
%D So now one can use:
%D
%D \starttypen
%D \gotopage{some text}[location]
%D \gotopage{some text}[number]
%D \gotopage{some text}[file::number]
%D \stoptypen
%D
%D as well as:
%D
%D \starttypen
%D \goto{some text}[page(location)]
%D \goto{some text}[page(number)]
%D \goto{some text}[file::page(number)]
%D \stoptypen
%D
%D Here location is a keyword like \type{nextpage}.
%D
%D \showsetup{\y!ganaarpagina}

\def\dodefinieerpagina[#1][#2]%
  {\setvalue{\v!pagina:::#1}{#2}}

\def\definieerpagina%
  {\dodoubleargument\dodefinieerpagina}

\definieerpagina [\v!eerstepagina]      [\firstpage]
\definieerpagina [\v!vorigepagina]      [\prevpage]
\definieerpagina [\v!volgendepagina]    [\nextpage]
\definieerpagina [\v!laatstepagina]     [\lastpage]
\definieerpagina [\v!eerstesubpagina]   [\firstsubpage]
\definieerpagina [\v!vorigesubpagina]   [\prevsubpage]
\definieerpagina [\v!volgendesubpagina] [\nextsubpage]
\definieerpagina [\v!laatstesubpagina]  [\lastsubpage]
\definieerpagina [\v!eerste]            [\firstpage]
\definieerpagina [\v!vorige]            [\prevpage]
\definieerpagina [\v!volgende]          [\nextpage]
\definieerpagina [\v!laatste]           [\lastpage]
\definieerpagina [\v!eerste\v!sub]      [\firstsubpage]
\definieerpagina [\v!vorige\v!sub]      [\prevsubpage]
\definieerpagina [\v!volgende\v!sub]    [\nextsubpage]
\definieerpagina [\v!laatste\v!sub]     [\lastsubpage]

%D Because we combine both methods, we have to take care of
%D the \type{file::page(n)} as well as \type{page(file::n)}.

\definespeciallocation\v!pagina#1#2%
  {\iflocation
     \ifx\currentouterreference\empty
       \splitoffreference\currentreferenceoperation
     \else
       \let\currentinnerreference=\currentreferenceoperation
     \fi
     \ifx\currentouterreference\empty
       \doifnonzeropositiveelse{\currentinnerreference}
         {}
         {\edef\currentinnerreference{1}}%
       \gotorealpage{}{}{\currentinnerreference}{#2}%
     \else
       \setouterlocation\currentouterreference
       \doifnonzeropositiveelse{\currentinnerreference}
         {}
         {\doifdefinedelse{\v!pagina:::\currentinnerreference}
            {\edef\currentinnerreference{\getvalue{\v!pagina:::\currentinnerreference}}}
            {\edef\currentinnerreference{1}}}%
       \gotorealpage{\otherURL}{\otherfile}{\currentinnerreference}{#2}%
     \fi
   \else
     {#2}%
   \fi}

\def\naarpagina#1[#2]%
  {\naar{#1}[\v!pagina(#2)]}

\let\ganaarpagina=\naarpagina

%D A still very rudimentary|/|experimental forward|/|backward
%D reference mechanism is provided by the macro \type{\atpage}:
%D
%D \starttypen
%D ... \somewhere{backward text}{forward text}[someref] ...
%D ... \oppagina[someref] ...
%D \stoptypen
%D
%D In future versions there will be more sophisticated

%D support, also suitable for references to floating bodies.

\unexpanded\def\dosomewhere#1#2#3[#4]% #3 gobbles space around #2
  {\leaveoutervmode
   \doifreferencefoundelse{#4}
     {\ifforwardreference
        \doifelsenothing{#1}
          {\dosymbolreference{}{}[#4]}
          {\donaarspace{#1}[#4]}%
      \else
        \doifelsenothing{#2}
          {\dosymbolreference{}{}[#4]}
          {\donaarspace{#2}[#4]}%
      \fi}
     {\unknownreference{#4}#1/#2}%
   \referentieinfo{<}{#4}}

\unexpanded\def\atpage[#1]%
  {\leaveoutervmode
   \doifreferencefoundelse{#1}
     {\ifrealreferencepage
        \ifforwardreference
          \donaarfixed{\labeltext{\v!hierboven}}[#1]%
        \else
          \donaarfixed{\labeltext{\v!hieronder}}[#1]%
        \fi
      \else
        \donaarfixed{\labeltext{\v!oppagina}~\currentpagereference}[#1]%
      \fi}
     {\unknownreference{#1}%
      \v!pagina~\dummyreference}%
   \referentieinfo{<}{#1}}

%D We can cross link documents by using:
%D
%D \showsetup{\y!coupledocument}
%D
%D like:
%D
%D \starttypen
%D \coupledocument[print][somefile][chapter,section]
%D \stoptypen
%D
%D After which when applicable, we have available the
%D references:
%D
%D \starttypen
%D \goto{print version}[print::chapter]
%D \stoptypen
%D
%D and alike. The title placement definition macros have a
%D key \type{file}, which is interpreted as the file to jump
%D to, that is, when one clicks on the title.

\let\crossdocumentreferences\empty
\let\crossdocumentelements\empty

\newif\ifautocrossdocument

\def\docoupledocument[#1][#2][#3][#4]%
  {\ifthirdargument
     \begingroup
     \def\dolijstelement##1##2##3##4##5##6%
       {\global\utilitydonetrue %{Watch the braces here below!}
       %\setglobalcrossreference{{##1::\strippedlistentry[##5]}}{}{}{##6}}%
        \setglobalcrossreference{{##1::\strippedlistentry[##5]}}{}{##6}{}}%
     \def\usereferences[##1]%
       {\setbox0=\vbox{\doutilities{#3}{##1}{#3}{}{}}}%
     \dogebruikexterndocument[#1][#2][#4]%
     \doglobal\addtocommalist{#1}\crossdocumentreferences
     \def\docommando##1%
       {\doglobal\addtocommalist{##1}\crossdocumentelements}%
     \processcommalist[#3]\docommando
     \ifutilitydone
       \global\autocrossdocumenttrue
     \fi
     \endgroup
   \fi}

\def\coupledocument%
  {\doquadrupleempty\docoupledocument}

%D --- STRANGE HERE, BETTER IN CORE-NAV ---

\def\checkcontrastreference#1%
  {\ifnum\currentreferencetype=\rt!page\ifnum\currentdatareference=\realpageno
     \doifdefined{#1\c!contrastkleur}
       {\setevalue{#1\c!kleur}{\getvalue{#1\c!contrastkleur}}}%
   \fi\fi}

%D Buttons are just what their names says: things that can be
%D clicked (pushed) on. They are similar to \type{\goto},
%D except that the text argument is not interpreted.
%D Furthermore one can apply anything to them that can be done
%D with \type{\framed}.
%D
%D \startbuffer
%D \button[width=3cm,height=1.5cm]{Exit}[ExitViewer]
%D \stopbuffer
%D
%D \typebuffer
%D
%D gives
%D
%D \haalbuffer
%D
%D This command is formally specified as:
%D
%D \showsetup{\y!button}
%D
%D The characteristics can be set with:
%D
%D \showsetup{\y!stelbuttonsin}

\def\dostelbuttonsin[#1]%
  {\getparameters[\??bt][#1]%
   \dododostelinteractiemenuin{\??bt\c!onbekendeverwijzing}%
   \dododostelinteractiemenuin{\??bt\c!zelfdepagina}}

\def\stelbuttonsin%
  {\dosingleargument\dostelbuttonsin}

\definecomplexorsimpleempty\button

\def\complexbutton%
  {\docomplexbutton\??bt}

\presetlocalframed[\??bt]

\def\docomplexbutton#1[#2]#3#4% get rid of possible space before [#4]
  {\dodocomplexbutton#1[#2]{#3}#4} % #4 == [

\def\dodocomplexbutton#1[#2]#3[#4]%
  {\bgroup
   \doifvalue{#1\c!status}{\v!stop}{\locationfalse}%
   \iflocation
     \resetgoto
     \ConvertConstantAfter\doifelse{#3}{\v!geen}
       {\!!doneafalse}
       {\!!doneatrue}%
     \doifelsenothing{#4} % in handleiding, is soort dummy
       {\if!!donea\hbox\else\hphantom\fi
          {\localframed[#1][#2]{#3}}}%
       {\doifreferencefoundelse{#4}
          {\setbox0=\if!!donea\hbox\else\hphantom\fi
             {\localframed[#1][#2]
                {\checkcontrastreference{#1}%
                 \dolocationattributes{#1}\c!letter\c!kleur{\ignorespaces#3}}}%
           \startinteractie
           \hbox{\gotolocation{#4}{\copy0}}%
           \stopinteractie}
          {\unknownreference{#4}%
           \if!!donea\hbox\else\hphantom\fi
             {\localframed[#1][#2]
                {\ignorespaces#3}}}}%
   \fi
   \egroup}

%D Interaction buttons, in fact a row of tiny buttons, are
%D typically only used for navigational purposed. The next
%D macro builds such a row based on a specification list.
%D
%D \startbuffer
%D \interactiebuttons
%D   [breedte=\hsize][pagina,VorigeSprong,VerlaatViewer]
%D \stopbuffer
%D
%D \typebuffer
%D
%D gives
%D
%D \haalbuffer
%D
%D Apart from individual entries, one can use \type{page} and
%D \type {subpage} as shortcuts to their four associated buttons.
%D The symbols are derived from the symbols linked to the
%D entries.

\def\interactiebuttons%
  {\dodoubleempty\dointeractiebuttons}

\def\dointeractiebuttons[#1][#2]% er is een verdeel macro \fractie
  {\iflocation
     \bgroup
     \doif{\@@ibstatus}{\v!stop}{\locationfalse}%
     \iflocation
       \ifsecondargument
         \checkinteractiebalk\v!ruim\!!zeropoint % brrrrr
         \setbox2=\hbox
           {\setupsymbolset[\@@iasymboolset]%
            \localframed[\??ib][]{\symbol[\v!vorigepagina]}}%
         \!!heighta=\ht2
         \stelinteractiebalkin[#1,\c!strut=\v!nee]%
         \stelinteractiein[\c!breedte=\!!zeropoint]%
        %\!!counta=1
         \!!counta=0                          % new
         \processallactionsinset
           [#2]
           [       \v!pagina=>\advance\!!counta by 4,
             \v!sub\v!pagina=>\advance\!!counta by 4,
                  \s!unknown=>\advance\!!counta by 1]%
         \ifdim\@@ibbreedte=\!!zeropoint
           \!!widtha=2em
           \advance\!!widtha by \@@ibafstand  % new
           \!!widthb=\!!counta\!!widtha
           \advance\!!widthb by -\@@ibafstand % new
         \else
           \!!widtha=\@@ibbreedte
           \!!widthb=\@@ibafstand             % new
           \multiply\!!widthb by \!!counta    % new
           \advance\!!widthb by -\@@ibafstand % new
           \advance\!!widtha by -\!!widthb    % new
           \divide\!!widtha by \!!counta
           \!!widthb=\@@ibbreedte
         \fi
         \def\goto##1%
           {\setnostrut
            \setupsymbolset[\@@iasymboolset]%
            \edef\localreference{##1}%
            \dodocomplexbutton\??ib
              [\c!hoogte=\!!heighta,\c!breedte=\!!widtha]%
              {\dontleavehmode\symbol[\localreference]}%
              [\localreference]%
            \hss}%
         \hbox to \!!widthb
           {\processallactionsinset
              [#2]
              [    \v!pagina=>\goto\v!eerstepagina
                              \goto\v!volgendepagina
                              \goto\v!vorigepagina
                              \goto\v!laatstepagina,
             \v!sub\v!pagina=>\goto\v!eerstesubpagina
                              \goto\v!volgendesubpagina
                              \goto\v!vorigesubpagina
                              \goto\v!laatstesubpagina,
                  \s!unknown=>\goto\commalistelement]%
            \unskip}%
       \else
         \interactiebuttons[][#1]%
       \fi
     \fi
     \egroup
   \fi}

%D In the next settings we see some variables that were not
%D used here and that concern the way the pagenumbers refered
%D to are typeset.

\setupreferencing
  [\c!status=\v!start,
   \v!deel\c!nummer=\v!ja,
   \v!hoofdstuk\c!nummer=\v!nee,
   \c!interactie=\v!alles,
%   \c!urlvariant=\v!beide,
%   \c!urlspatie=\v!nee,
%   \c!urlletter=,
%   \c!urlkleur=,
   \c!prefix=,
   \c!breedte=.75\zetbreedte,
   \c!links=\citaat\bgroup,
   \c!rechts=\egroup]

\setupurl
  [\c!variant=\v!beide,
   \c!spatie=\v!nee,
   \c!letter=\v!type,
   \c!kleur=]

%D We also set up buttons (not yet, this one calls a menu macro):

% \stelbuttonsin
%   [\c!status=\v!start,
%    \c!breedte=\v!passend,
%    \c!hoogte=\v!ruim,
%    \c!offset=0.25em,
%    \c!kader=\v!aan,
%    \c!achtergrond=,
%    \c!achtergrondraster=\@@rsraster,
%    \c!achtergrondkleur=,
%    \c!letter=\@@ialetter,
%    \c!kleur=\@@iakleur,
%    \c!zelfdepagina=\v!ja,
%    \c!onbekendeverwijzing=\v!leeg]

\protect

\endinput
