% DUE TO NEW/FUTURE FEATURES THIS MODULE IS UNDER RECONSTRUCTION ! % % uitprinten % engels maken % rommel voorlopig naar core-01d % programma, profiel etc als methode %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 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 -- 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 -- 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% {\makesectionformat \writereference{#2} {\sectionformat::\noexpand\pagenumber} {\noexpand\realfolio} {}} \def\rawtextreference#1#2#3% {\writereference{#2} {} {} {#3}} \def\rawreference#1#2#3% {\makesectionformat \writereference{#2} {\sectionformat::\noexpand\pagenumber} {\noexpand\realfolio} {#3}} %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 %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% {\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). \def\usereferences[#1]% {\bgroup \setbox0=\hbox {\doonlyonce{references:#1}{\doutilities{references}{#1}{}{}{}}}% \egroup} \def\checkreferences% {\usereferences[\jobname]% \checkrealpage \global\let\checkreferences=\relax} %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 \chardef\rt!done =1 \chardef\rt!page =2 \chardef\rt!exec =3 \chardef\rt!list =4 %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. \newcount\crossreferenceorder \def\setlocalcrossreference#1#2#3#4% {\setevalue{\r!cross\fileprefix#1}{\rt!cross{#2}{#3}{#4}{0}}} \def\setglobalcrossreference#1#2#3#4% {\global\advance\crossreferenceorder by 1 \setxvalue{\r!cross\fileprefix#1}{\rt!cross{#2}{#3}{#4}{\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}}} %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% {\setxvalue{\r!cross\fileprefix}{\rt!cross{}{}{1}{0}}% \setxvalue{\r!cross\fileprefix#1}{\rt!cross{#2}{#3}{#4}{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 %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{}{}{}{}} %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 needed those. The discrancy 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} %D When inside this tetsing 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 \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 \dodosplitofffullreference#1::::\empty\end \currentouterreference\currentreferencespecial \else\ifx#2\relax \let\currentreferencespecial=\empty \let\currentreferenceoperation=\empty \let\currentreferencearguments=\empty \dodosplitofffullreference#1::::\empty\end \currentouterreference\currentinnerreference \else \dosplitoffreferenceoperation#2#3{}\end \let\currentinnerreference=\empty \dodosplitofffullreference#1::::\empty\end \currentouterreference\currentreferencespecial \fi\fi} \def\dosplitoffreferenceoperation#1#% {\def\currentreferenceoperation{#1}% \dodosplitoffreferenceoperation} \def\dodosplitoffreferenceoperation#1#2\end {\def\currentreferencearguments{#1}} \def\dodosplitofffullreference#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\dodosplitofffullreference#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: \def\showcurrentreference% {\bgroup\tttf /ful/\convertcommand\currentfullreference \to\ascii\ascii/\par /spe/\convertcommand\currentreferencespecial \to\ascii\ascii/\par /ope/\convertcommand\currentreferenceoperation\to\ascii\ascii/\par /arg/\convertcommand\currentreferencearguments\to\ascii\ascii/\par /out/\convertcommand\currentouterreference \to\ascii\ascii/\par /inn/\convertcommand\currentinnerreference \to\ascii\ascii/\par \egroup} %D We use this visualizer to demonstrate the way references are %D split. %D %D \hbox{\splitofffullreference{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 Finaly 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.} % \def\doifreferencefoundelse#1#2#3% % {\checkreferences % \bgroup % \let\unharmedreferenceprefix=\referenceprefix % \bgroup % \splitofffullreference{#1}% % \ifx\currentreferencespecial\empty % \ifx\currentouterreference\empty % \doifdefinedelse{\r!cross\referenceprefix\currentfullreference} % {\global\referencefoundtrue} % {\let\referenceprefix=\empty % \doifdefinedelse{\r!cross\currentfullreference} % {\global\referencefoundtrue} % {\global\referencefoundfalse}}% % \else % \global\referencefoundtrue % \fi % \doifpredefinedreferenceelse{\currentfullreference} % no \referenceprefix % {\global\referencefoundfalse}{}% % \ifreferencefound % \getreferenceelements{\currentfullreference}% % \fi % \else % \let\referenceprefix=\empty % \let\unharmedreferenceprefix=\empty % \doifdefinedelse{\s!do\v!test\currentreferencespecial} % {\getvalue{\s!do\v!test\currentreferencespecial} % {\global\referencefoundtrue}{\global\referencefoundfalse}} % {\global\referencefoundtrue}% % \fi % \ifreferencefound % #2% % \egroup % \else % #3% % \egroup % \predefinereference{#1}% no \referenceprefix % \fi % \egroup} %D FILEPREFIX WEEDEN \def\doifreferencefoundelse#1#2#3% opsplitsen in inner/outer/special {\checkreferences \bgroup \let\unharmedreferenceprefix=\referenceprefix \bgroup \splitofffullreference{#1}% \ifx\currentreferencespecial\empty \ifx\currentouterreference\empty \docheckinnerreference \else \docheckouterreference \fi \ifreferencefound \getreferenceelements\currentfullreference \fi \else \docheckspecialreference \fi \ifreferencefound #2\egroup \else #3\egroup \fi \egroup} %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 \doifdefinedelse{\r!cross\referenceprefix\currentfullreference} {\global\referencefoundtrue} {\let\referenceprefix=\empty \doifdefinedelse{\r!cross\currentfullreference} {\global\referencefoundtrue} {\global\referencefoundfalse}}% \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}{}} %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\unknownreference#1% {\ifvoorlopig \doifsomething{#1} {\inlinker {\infofont \dimen0=\linkermargebreedte \advance\dimen0 by -2em \doboundtext{#1}{\dimen0}{..}->}}% \fi \doifpredefinedreferenceelse {} {\predefinereference \showmessage{\m!references}{1}{[\unharmedreferenceprefix][#1]}}} %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% {\setxvalue{\r!cross\predefinedreference}{\rt!cross{}{}{}{}}} %D Testing on existance then becomes: \def\doifpredefinedreferenceelse% {\doifelsevalue{\r!cross\predefinedreference}{\rt!cross{}{}{}{}}} %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#1}{\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}} \def\handlepagereference#1% {\gotorealpage{}{}{\currentdatareference}} \def\handlelistreference#1% {\gotodestination{}{}{\currentdatareference}{\getvalue{\currentdatareference}}} %D (in dutch, egnlish, german of whateverinterface language) %D are translated into a bit shorter reference (\type{close}) %D and passed to the special driver (using \type %D {\executecommand}). \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!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} %D Executing the command looks alike the previous goto macros. \def\executecommand#1#2% {\iflocation \dostartgoto \data {#2}% \start \dostartexecutecommand {\number\buttonwidth}{\number\buttonheight} {#1}{}% \stop \dostopexecutecommand \dostopgoto \else {#2}% \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 We can typeset a reference using \type{\in} and \type{\at} %D and goto specific locations using \type{\goto}. The last one %D does not make that much sense in a paper document. To %D complicate things, \PLAIN\ \TEX\ also implements an \type %D {\in} but fortunately that one only makes sense in math %D mode. %D --- VANAF HIER NOG VERENGELSEN --- \let\donormalin=\in \def\in% {\ifmmode \expandafter\donormalin \else \expandafter\doinatreference\expandafter\currenttextreference \fi} \def\op% {\doinatreference\currentpagereference} %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#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 \ifhmode\unskip\fi \ifx\currentreferencespecial\empty \ifx\currentouterreference\empty \ifnum0\currentrealreference=0 \ifhmode\strut$^\gonowherecharacter$\fi \else\ifnum0\currentrealreference>\realpageno \dodosymbolreference{#2}{$^\goforwardcharacter$}% \else\ifnum0\currentrealreference<\realpageno \dodosymbolreference{#2}{$^\gobackwardcharacter$}% \else \ifhmode\strut$^\gonowherecharacter$\fi \fi\fi\fi \else \gotoouterlocation{#3}{\showlocation{$^\gotosomewherecharacter$}}% \fi \else \gotospeciallocation{#3}{\showlocation{$^\gotosomewherecharacter$}}% \fi \egroup} \def\dodosymbolreference#1#2% {#1\hbox{\gotorealpage{}{}{\currentrealreference} {\dolocationattributes{\??ia}{#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]}} \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\donaarspace#1[#2]% {{\iflocation \def\processisolatedword##1% {\hbox{\gotolocation{#2}{##1\presetgoto}}}% \doattributes{\??ia} {\processisolatedwords{#1}\processisolatedword}% \else #1\relax % \relax prevents #1's next macros from gobbling \fi \fi}} \def\donaarfixed#1[#2]% {{\iflocation \hbox{\gotolocation{#2}{\doattributes{\??ia}{#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]} {\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}}% \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 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% {\doquadrupleargument\dogebruikURL} \def\dogebruikURL[#1][#2][#3][#4]% {\doifelsenothing{#4} {\dogebruikexterndocument[#1][#2][#3][#3]} {\doifsomething{#1} {\setgvalue{\v!file:::#1}{\doexternaldocument{#2}{#3}{#4}}}}} %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} \definespeciallocation\v!file {\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 % \showsetup{\y!ganaarpagina} \def\dodefinieerpagina[#1][#2]% {\setvalue{\v!pagina:::#1}{#2}} \def\definieerpagina% {\dodoubleargument\dodefinieerpagina} \definieerpagina [\v!eerste\v!pagina] [\firstpage] \definieerpagina [\v!vorige\v!pagina] [\prevpage] \definieerpagina [\v!volgende\v!pagina] [\nextpage] \definieerpagina [\v!laatste\v!pagina] [\lastpage] \definieerpagina [\v!eerste\v!sub\v!pagina] [\firstsubpage] \definieerpagina [\v!vorige\v!sub\v!pagina] [\prevsubpage] \definieerpagina [\v!volgende\v!sub\v!pagina] [\nextsubpage] \definieerpagina [\v!laatste\v!sub\v!pagina] [\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 !!!!! \ergens documenteren in handleiding !!!!! %D support, also suitable for refreences to floating bodies. \unexpanded\def\ergens#1#2[#3]% {\leaveoutervmode \doifreferencefoundelse{#3} {\ifforwardreference \doifelsenothing{#1} {\dosymbolreference{}{}[#3]} {\donaarspace{#1}[#3]}% \else \doifelsenothing{#2} {\dosymbolreference{}{}[#3]} {\donaarspace{#2}[#3]}% \fi} {\unknownreference{#3}#1/#2}% \referentieinfo{<}{#3}} \unexpanded\def\oppagina[#1]% {\leaveoutervmode \doifreferencefoundelse{#1} {\doifelse{\realfolio}{\currentrealreference} {\ifforwardreference \donaarfixed{\labeltext{\v!hier\v!boven}}[#1]% \else \donaarfixed{\labeltext{\v!hier\v!onder}}[#1]% \fi} {\donaarfixed{\labeltext{\v!op\v!pagina}~\currentpagereference}[#1]}} {\unknownreference{#1}% \v!pagina~\dummyreference}% \referentieinfo{<}{#1}} %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]% {\bgroup \resetgoto \ConvertConstantAfter\doifelse{#3}{\v!geen} {\!!doneafalse} {\!!doneatrue}% \doifreferencefoundelse{#4} {\setbox0=\if!!donea\hbox\else\hphantom\fi {\localframed[#1][#2] {\checkcontrastreference{#1}% \dolocationattributes{#1}{\ignorespaces#3}}}% \startinteractie \hbox{\gotolocation{#4}{\copy0}}% \stopinteractie} {\unknownreference{#4}% \if!!donea\hbox\else\hphantom\fi {\localframed[#1][#2] {\ignorespaces#3}}}% \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]% {\iflocation \ifsecondargument \bgroup \setbox2=\hbox {\localframed[\??ib][]{\gobackwardcharacter}}% \!!heighta=\ht2 \stelinteractiebalkin[#1,\c!strut=\v!nee]% \stelinteractiein[\c!breedte=\!!zeropoint]% \!!widtha=\@@ibbreedte\relax \!!counta=1 \processallactionsinset [#2] [ \v!pagina=>\advance\!!counta by 4, \v!sub\v!pagina=>\advance\!!counta by 4, \s!unknown=>\advance\!!counta by 1]% \divide\!!widtha by \!!counta \def\goto##1% {\setnostrut \edef\localreference{##1}% \docomplexbutton\??ib [\c!hoogte=\!!heighta,\c!breedte=\!!widtha]% {\dontleavehmode\symbol[\localreference]}% [\localreference]% \hss}% \hbox to \@@ibbreedte {\processallactionsinset [#2] [ \v!pagina=>\goto{\v!eerste\v!pagina}% \goto{\v!volgende\v!pagina}% \goto{\v!vorige\v!pagina}% \goto{\v!laatste\v!pagina}, \v!sub\v!pagina=>\goto{\v!eerste\v!sub\v!pagina}% \goto{\v!volgende\v!sub\v!pagina}% \goto{\v!vorige\v!sub\v!pagina}% \goto{\v!laatste\v!sub\v!pagina}, \s!unknown=>\goto\commalistelement]% \unskip}% \egroup \else \interactiebuttons[][#1]% \fi \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!prefix=] \protect \endinput