The varioref package^{∗}

Frank Mittelbach

1995/10/19

Abstract

This package defines the commands \vref and \vpageref for L^{A}TEX 2ε. \vref is similar to \ref but adds an additional page reference, like ‘on the facing page’ or ‘on page 27’ whenever the corresponding \label is not on the same page. The command \vpageref is a variation to \pageref with a similar functionality. Generated strings are customizable so that these commands are usable with other languages.

1 Introduction

In many cases it is helpful when refering to a figure or table to put both a \ref and a \pageref command into the document especially when there are one or more pages between the reference and the object. Therefore some people use a command like

  \newcommand{\fullref}[1]{\ref{#1} on page~\pageref{#1}}

which reduces the number of key strokes, necessary to make such a complete reference. But since one never knows where the referenced object finally falls, using such a device may result in a page reference to the current page which is disturbing and therefore should be avoided.

2 The user interface

\vref The implementation of \vref below produces only a \ref when reference and \label are on the same page. It will additionally produce one of the strings ‘on the facing page’, ‘on the preceding page’, or ‘on the following page’, if label and reference differ by one and it will produce both \ref and \pageref when the difference is larger. The word ‘facing’ is used when label and reference both fall onto a double spread. However, if a special page numbering scheme is used instead of the usual arabic numbering (e.g., \pagenumbering{roman}) then there will be no distinction between one or many pages off.

\vpageref Sometimes one wants to refer only to page number and again such a reference should normally be suppressed if we are refering to the current page. For this purpose the package defines the \vpageref command. It will produce the same strings as \vref except that it doesn’t start with the \ref and except that it will produce the string that is saved in \reftextcurrent if label and reference fall onto the same page. By defining \reftextcurrent to produce “on this page” or something similar, we can avoid that

∗This file has version number v1.1b, last revised 1995/10/19.

   ... see the example \vpageref{ex:foo} which shows ...

comes out as “… see the example which shows … ”, which could be misleading.

You can put a space in front of \vpageref it will be ignored if the command doesn’t produce any text at all.

But in fact \vpageref allows even more control. If has two optional arguments. With the first one, one can specify the text that should be used if label and reference fall on the same page. This is very helpful if both are near to each other, so that they may or may not be separated by a page break. In such a case we usually know (!) whether the reference is before or after the label so that we can say something like

   ... see the example \vpageref[above]{ex:foo} which shows ...

which will then come out as “… see the example above which shows … ” if we are still on the same page, but as “… see the example on the page before which shows … ” (or something similar depending on the settings of the \reftext..before commands) when there was a page break in the meantime. One warning however, if you use \vpageref with the optional argument to refer to a figure or table, keep in mind that depending on the float placement parameters the float may show up on top of the current page and therefore before the reference even if it came after it in the source file.

But maybe you prefer to say “… see the above example” if example and reference fall onto the same page, i.e., reverse the word order. In fact, in some languages the word order automatically changes in that case. To allow for this variation the second optional argument can be used. It specifies the text preceding the generated reference if object and reference do not fall onto the same page. Thus one would write

   ... see the \vpageref[above example][example]{ex:foo}
       which shows ...

to achieve the desired effect.

3 Customization

The package supports all options defined by the babel package to translate the fixed strings into other languages than English. (Some languages need updating, however.) It also supports languages currently not in babel; check the section on options later on. You can also modify some or all of the strings by redefining

\reftextbefore the following commands. Backward references use \reftextbefore if the label

\reftextfacebefore
\reftextafter
\reftextfaceafter

is on the preceding page but invisible and \reftextfacebefore if it is one the facing page (i.e., if the current page number is odd). Similarily \reftextafter is used when the label comes on the next page but one has to turn the page and \reftextfaceafter if it is on the following but facing page.

In fact, \reftextface... is used only if the user or the document class specified two-sided printing.

\reftextfaraway Finally we have \reftextfaraway which is used whenever label and reference differ by more than one or when they aren’t numeric. This macro is a bit different because it takes one argument, the symbolic reference string so that one cane make use of \pageref in its replacement text.

\vreftextvario To allow a bit random variation in the generated strings one can use the command \reftextvario inside the string macros. It takes two arguments and selects one or the other for printing depending on the number of already seens \vref or \vpageref commands. As an example see the definitions of \reftextbefore etc. on page 5.

4 A few warnings

Defining commands like the ones described above poses some interesting problems. Suppose, for example, that a generated text like ‘on the next page’ gets broken across pages. If this happens it is very difficult to find an acceptable solution and in fact can even result in a document that will always change from one state to another (i.e., inserting one string, finding that this is wrong, inserting another string on the next run which makes the first string correct again, inserting …). The current implementation of varioref therefore issues an error message whenever the generated text is broken across page boundaries, e.g.,

table 5 on the current ⟨page break⟩ page

would would result in an error, which needs to be resolved by the user by replacing the \vref command with an ordinary \ref just before the final run. This is not

\vrefwarning completely satisfactory but in such case no solution really is. During document preparation, while one is still changing the text, such error messages can be turned into warnings by placing a \vrefwarning command in the preamble.

At the end final a warning: every use of \vref will internally generate two macro names to keep track of the string positions within the document. As a result you may run out of name space or main memory if you make havy use of

\fullref this macro on a small TEX installation. For this reason the primitive command \fullref is also provided. This command can be used whenever you know for sure that label and reference can’t fall onto nearby pages.

5 The documentation driver file

The next bit of code contains the documentation driver file for TEX, i.e., the file that will produce the documentation you are currently reading. It will be extracted from this file by the docstrip program.

1 ⟨∗driver⟩

 2 \documentclass{ltxdoc}
 3 \usepackage{varioref}
 4 \GetFileInfo{varioref.sty}
 5 \setlength\hfuzz{1pt}    % ignore slight overfulls
 6 \EnableCrossrefs
 7 %\DisableCrossrefs   % Say \DisableCrossrefs if index is ready

8

 9 \RecordChanges       % Gather update information
10 %\OnlyDescription    % comment out for implementation details
11 \begin{document}

12 \DocInput{varioref.dtx}
13 \end{document}

14 ⟨/driver⟩

6 The implementation

The main implementation idea is to generate an internal label command for every \vpageref and compare the page reference of this label with the page reference of the user-requested label. Since this means one additional macro name for each use of \vpageref or vref (which is implemented in terms of \vpageref) the memory requirements of this package may be high in terms of main and macro name memory. Since the information held in the internal labels is used only once one could envision a different scheme if suitable primitives for this kind of “one place information” would be provided by L^{A}TEX. This type of data structure is planned for L^{A}TEX3 but for the moment we have to live with the memory restrictions.

We start by checking if this file was already loaded. If not we identify the current version. This is actually done at the top of the file, so we comment it out here

15 ⟨∗package⟩

16 %\NeedsTeXFormat{LaTeX2e}[1994/06/01]
17 %\ProvidesPackage{varioref}[\filedate\space\fileversion\space
18 %                     LaTeX2e package for extended references (FMi)]

\vref@addto To support the use of babel we want to add the additional strings to the \extras⟨language⟩ commands. Since \addto in the current implementation of babel has a bug that does not allow to use arguments containing hashmarks we do this by hand.

19 \def\vref@addto#1#2{%
20 #2%
21 \@temptokena{#2}%
22 \ifx#1\undefined
23  \edef#1{\the\@temptokena}%
24 \else
25  \toks@\expandafter{#1}%
26  \edef#1{\the\toks@\the\@temptokena}%
27 \fi
28 \@temptokena{}\toks@\@temptokena

29 }

30 \@onlypreamble\vref@addto

6.1 Options

\vref@excuse Excuse that we don’t know the strings for a certain language.

31 \def\vref@excuse#1{%
32 \PackageWarningNoLine{varioref}{Sorry, language `#1'
33  not supported%
34  \MessageBreak
35  by in this version.
36  English strings used by default.
37  \MessageBreak
38  Please Modify \protect\reftext... commands manually.%

39  \MessageBreak\MessageBreak
40  If you can suggest translations for
41  this language,%
42  \MessageBreak
43  please mail your them
44  to the author of this package}}
45 \@onlypreamble\vref@excuse
\reftextfaceafter \reftextfacebefore \reftextafter \reftextbefore \reftextcurrent The options do set the the macros that generate the textual strings. Note, that

they do not start with a space, the space is already added in the main macro below.

46 \DeclareOption{american}
47 {\vref@addto\extrasamerican{%%
48  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
49  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
50  page}%
51  \def\reftextafter     {on the \reftextvario{following}{next} page}%
52  \def\reftextbefore    {on the \reftextvario{preceding page}{page
53  before}}%
54  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
55  \def\reftextfaraway#1{on page~\pageref{#1}}%
56 }}
57 \DeclareOption{austrian}
58 {\vref@excuse{austrian}%
59 \vref@addto\extrasaustrian{%
60  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
61  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
62  page}%
63  \def\reftextafter     {on the \reftextvario{following}{next} page}%
64  \def\reftextbefore    {on the \reftextvario{preceding page}{page
65  before}}%
66  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
67  \def\reftextfaraway#1{on page~\pageref{#1}}%
68 }}

Text for brazil defaults was contributed by Alcino Dall Igna Junior

(adij@di.ufpe.br).
69 \DeclareOption{brazil}
70 {\vref@addto\extrabrazil{%
71  \def\reftextfaceafter {na \reftextvario{p\'agina oposta}{pr\'oxima
72  p\'agina}}%
73  \def\reftextfacebefore{na p\'agina \reftextvario{oposta}{anterior}}%
74  \def\reftextafter     {na \reftextvario{p\'agina seguinte}{pr\'oxima
75  p\'agina}}%
76  \def\reftextbefore{na p\'agina \reftextvario{anterior}{precedente}}%
77  \def\reftextcurrent   {\reftextvario{nesta p\'agina}{na p\'agina
78  corrente}}%
79  \def\reftextfaraway#1{na p\'agina~\pageref{#1}}%
80 }}

Text for Breton defaults was contributed by Christian ROLLAND (Christian.Rolland@univ-brest.fr).

81 \DeclareOption{breton}
82 {\vref@excuse{breton}%

 83 \vref@addto\extrasbreton{%
 84  \def\reftextfaceafter {war ar bajenn \reftextvario{a-dal}{da heul}}%
 85  \def\reftextfacebefore{war ar bajenn \reftextvario{a-dal}{a-raok}}%
 86  \def\reftextafter     {war ar bajenn da heul}%
 87  \def\reftextbefore    {war ar bajenn a-raok}%
 88  \def\reftextcurrent   {war ar \reftextvario{bajenn-ma\~n}%
 89  {bajenn war-wel}}%
 90  \def\reftextfaraway#1{war ar bajenn~\pageref{#1}}%
 91 }}
 92 \DeclareOption{catalan}
 93 {\vref@excuse{catalan}%
 94 \vref@addto\extrascatalan{%
 95  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
 96  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
 97  page}%
 98  \def\reftextafter     {on the \reftextvario{following}{next} page}%
 99  \def\reftextbefore    {on the \reftextvario{preceding page}{page
100  before}}%
101  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
102  \def\reftextfaraway#1{on page~\pageref{#1}}%

103 }}

104 \DeclareOption{croatian}
105 {\vref@excuse{croatian}%
106 \vref@addto\extrascroatian{%
107  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
108  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
109  page}%
110  \def\reftextafter     {on the \reftextvario{following}{next} page}%
111  \def\reftextbefore    {on the \reftextvario{preceding page}{page
112  before}}%
113  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
114  \def\reftextfaraway#1{on page~\pageref{#1}}%

115 }}

116 \DeclareOption{czech}
117 {\vref@excuse{czech}%
118 \vref@addto\extrasczech{%
119  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
120  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
121  page}%
122  \def\reftextafter     {on the \reftextvario{following}{next} page}%
123  \def\reftextbefore    {on the \reftextvario{preceding page}{page
124  before}}%
125  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
126  \def\reftextfaraway#1{on page~\pageref{#1}}%

127 }}

Defaults for Danish provided by Torsten Martinsen (tmar91@kom.auc.dk).

128 \DeclareOption{danish}
129 {\vref@addto\extrasdanish{%
130  \def\reftextfaceafter {p\aa{} \reftextvario{modst\aa ende}%
131  {n\ae ste} side}%
132  \def\reftextfacebefore{p\aa{} \reftextvario{modst\aa ende}%
133  {forrige} side}%
134  \def\reftextafter     {p\aa{} \reftextvario{den f\o lgende}%
135  {n\ae ste} side}%

136  \def\reftextbefore    {p\aa{} \reftextvario{forrige side}
137  {foreg\aa ende side}}%
138  \def\reftextcurrent   {p\aa{} denne side}%
139  \def\reftextfaraway#1{p\aa{} side~\pageref{#1}}%

140 }}

Default string for dutch have been contributed by Frank Poppe. this option currently supports one additional string macro \refpagename so that you can easily change to bladzijde instead of pagina if you prefer this word for “page”. However, I will not guarantee that this will survive future versions of this package, so use it on your own risk (you can always update the full strings to be on the safe side).

141 \DeclareOption{dutch}
142 {\vref@addto\extrasdutch{%
143  \def\refpagename{pagina}%
144  \def\reftextfaceafter {op de \reftextvario{rechter \refpagename}%
145  {\refpagename\ hiernaast}}%
146  \def\reftextfacebefore{op de \reftextvario{linker \refpagename}%
147  {\refpagename\ hiernaast}}%
148  \def\reftextafter     {op de \reftextvario{volgende \refpagename}%
149  {\refpagename\ hierna}}%
150  \def\reftextbefore    {op de \reftextvario{vorige \refpagename}%
151  {\refpagename\ hiervoor}}%
152  \def\reftextcurrent   {op deze \refpagename}%
153  \def\reftextfaraway#1{op \refpagename~\pageref{#1}}%

154 }}

155 \DeclareOption{english}
156 {\vref@addto\extrasenglish{%
157  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
158  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
159  page}%
160  \def\reftextafter     {on the \reftextvario{following}{next} page}%
161  \def\reftextbefore    {on the \reftextvario{preceding page}{page
162  before}}%
163  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
164  \def\reftextfaraway#1{on page~\pageref{#1}}%

165 }}

166 \DeclareOption{esperanto}
167 {\vref@excuse{esperanto}%
168 \vref@addto\extrasesperanto{%
169  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
170  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
171  page}%
172  \def\reftextafter     {on the \reftextvario{following}{next} page}%
173  \def\reftextbefore    {on the \reftextvario{preceding page}{page
174  before}}%
175  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
176  \def\reftextfaraway#1{on page~\pageref{#1}}%

177 }}

The finnish strings were suggested by Matti Rintala (bitti@cs.tut.fi).

178 \DeclareOption{finnish}
179 {\vref@addto\extrasfinnish{%
180  \def\reftextfaceafter {\reftextvario{viereisell\"a}%
181  {seuraavalla} sivulla}%

182  \def\reftextfacebefore{\reftextvario{viereisell\"a}%
183  {edellisell\"a} sivulla}%
184  \def\reftextafter     {seuraavalla sivulla}%
185  \def\reftextbefore    {edellisell\"a sivulla}%
186  \def\reftextcurrent   {t\"all\"a sivulla}%
187  \def\reftextfaraway#1{sivulla~\pageref{#1}}%

188 }}

French defaults are provided by Daniel Flippo.

189 \DeclareOption{french}
190 {\vref@addto\extrasfrench{%
191  \def\reftextfaceafter {page \reftextvario{ci-contre}{suivante}}%
192  \def\reftextfacebefore{page \reftextvario{ci-contre}%
193  {pr\'ec\'edente}}%
194  \def\reftextafter     {page suivante}%
195  \def\reftextbefore    {page pr\'ec\'edente}%
196  \def\reftextcurrent   {de la pr\'esente page}%
197  \def\reftextfaraway#1{page~\pageref{#1}}%

198 }}

199 \DeclareOption{galician}
200 {\vref@excuse{galician}%
201 \vref@addto\extrasgalician{%
202  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
203  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
204  page}%
205  \def\reftextafter     {on the \reftextvario{following}{next} page}%
206  \def\reftextbefore    {on the \reftextvario{preceding page}{page
207  before}}%
208  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
209  \def\reftextfaraway#1{on page~\pageref{#1}}%

210 }}

There are no good variants for German (I think and still think but this is a matter of taste :-). The following definitions were recently suggested to me but since the original are in for a long time i don’t want to change them now since that could make a lot of documents change their formatting. If you fancy them, add a redefinition of the corresponding macro(s) to the preamble of your document.

     \def\reftextfaceafter {auf der \reftextvario
           {gegen\"uberliegenden}{anderen} Seite}%
     \def\reftextfacebefore {auf der \reftextvario
           {gegen\"uberliegenden}{anderen} Seite}%
     \def\reftextafter     {auf der \reftextvario
           {n\"achsten}{folgenden} Seite}%
     \def\reftextbefore    {auf der \reftextvario
           {vorigen}{vorhergehenden} Seite}%
     \def\reftextcurrent   {\reftextvario
           {auf dieser}{diese} Seite}%
211 \DeclareOption{german}
212 {\vref@addto\extrasgerman{%
213  \def\reftextfaceafter {auf der n\"achsten Seite}%
214  \def\reftextfacebefore{auf der vorherigen Seite}%
215  \let\reftextafter     \reftextfaceafter
216  \let\reftextbefore    \reftextfacebefore
217  \def\reftextcurrent   {auf dieser Seite}%

218  \def\reftextfaraway#1{auf Seite~\pageref{#1}}%

219 }}

Defaults for Italian suggested by Giovanni Pensa (pensa@dsi.unimi.it) with iTEXnici.

220 \DeclareOption{italian}
221 {\vref@excuse{italian}%
222 \vref@addto\extrasitalian{%
223  \def\reftextfaceafter {\reftextvario{a fronte}%
224  {nella pagina successiva}}%
225  \def\reftextfacebefore{\reftextvario{a fronte}%
226  {nella pagina precedente}}%
227  \def\reftextafter     {nella pagina \reftextvario{seguente}%
228  {successiva}}%
229  \def\reftextbefore    {nella pagina precedente}%
230  \def\reftextcurrent   {in questa pagina}%
231  \def\reftextfaraway#1{a pagina~\pageref{#1}}%

232 }}

233 \DeclareOption{magyar}
234 {\vref@excuse{magyar}%
235 \vref@addto\extrasmagyar{%
236  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
237  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
238  page}%
239  \def\reftextafter     {on the \reftextvario{following}{next} page}%
240  \def\reftextbefore    {on the \reftextvario{preceding page}{page
241  before}}%
242  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
243  \def\reftextfaraway#1{on page~\pageref{#1}}%

244 }}

The Norwegian and ‘nynorsk translations have been provided by Dag F Langmyhr

 <dag@ifi.uio.no>.
245 \DeclareOption{norsk}
246 {\vref@addto\extrasnorsk{%
247  \def\reftextfaceafter {p\aa{} \reftextvario{motst\aa{}ende}{neste}
248  side}%
249  \def\reftextfacebefore{p\aa{} \reftextvario{motst\aa{}ende}{forrige}
250  side}%
251  \def\reftextafter     {p\aa{} \reftextvario{siden etter}%
252  {neste side}}%
253  \def\reftextbefore    {p\aa{} \reftextvario{siden foran}%
254  {forrige side}}%
255  \def\reftextcurrent   {p\aa{} denne siden}%
256  \def\reftextfaraway#1{p\aa{} side~\pageref{#1}}%

257 }}

258 \DeclareOption{nynorsk}
259 {\vref@addto\extrasnynorsk{%
260  \def\reftextfaceafter {p\aa{} den \reftextvario{motst\aa{}ande}%
261  {neste} sida}%
262  \def\reftextfacebefore{p\aa{} den \reftextvario{motst\aa{}ande}%
263  {f\o{}rre} sida}%
264  \def\reftextafter     {p\aa{} \reftextvario{sida etter}%
265  {den neste sida}}%
266  \def\reftextbefore    {p\aa{} \reftextvario{sida f\o{}r}%

267  {den f\o{}rre sida}}%
268  \def\reftextcurrent   {p\aa{} denne sida}%
269  \def\reftextfaraway#1{p\aa{} side~\pageref{#1}}%

270 }}

271 \DeclareOption{polish}
272 {\vref@excuse{polish}%
273 \vref@addto\extraspolish{%
274  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
275  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
276  page}%
277  \def\reftextafter     {on the \reftextvario{following}{next} page}%
278  \def\reftextbefore    {on the \reftextvario{preceding page}{page
279  before}}%
280  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
281  \def\reftextfaraway#1{on page~\pageref{#1}}%

282 }}

283 \DeclareOption{portuges}
284 {\vref@excuse{portuges}%
285 \vref@addto\extrasportuges{%
286  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
287  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
288  page}%
289  \def\reftextafter     {on the \reftextvario{following}{next} page}%
290  \def\reftextbefore    {on the \reftextvario{preceding page}{page
291  before}}%
292  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
293  \def\reftextfaraway#1{on page~\pageref{#1}}%

294 }}

295 \DeclareOption{romanian}
296 {\vref@excuse{romanian}%
297 \vref@addto\extrasromanian{%
298  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
299  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
300  page}%
301  \def\reftextafter     {on the \reftextvario{following}{next} page}%
302  \def\reftextbefore    {on the \reftextvario{preceding page}{page
303  before}}%
304  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
305  \def\reftextfaraway#1{on page~\pageref{#1}}%

306 }}

307 \DeclareOption{russian}
308 {\vref@excuse{russian}%
309 \vref@addto\extrasrussian{%
310  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
311  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
312  page}%
313  \def\reftextafter     {on the \reftextvario{following}{next} page}%
314  \def\reftextbefore    {on the \reftextvario{preceding page}{page
315  before}}%
316  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
317  \def\reftextfaraway#1{on page~\pageref{#1}}%

318 }}

319 \DeclareOption{slovak}
320 {\vref@excuse{slovak}%

321 \vref@addto\extrasslovak{%
322  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
323  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
324  page}%
325  \def\reftextafter     {on the \reftextvario{following}{next} page}%
326  \def\reftextbefore    {on the \reftextvario{preceding page}{page
327  before}}%
328  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
329  \def\reftextfaraway#1{on page~\pageref{#1}}%

330 }}

331 \DeclareOption{slovene}
332 {\vref@excuse{slovene}%
333 \vref@addto\extrasslovene{%
334  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
335  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
336  page}%
337  \def\reftextafter     {on the \reftextvario{following}{next} page}%
338  \def\reftextbefore    {on the \reftextvario{preceding page}{page
339  before}}%
340  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
341  \def\reftextfaraway#1{on page~\pageref{#1}}%

342 }}

Text for spanish defaults was contributed by Julio Sanchez (jsanchez@gmv.es).

343 \DeclareOption{spanish}
344 {\vref@addto\extrasspanish{%
345  \def\reftextfaceafter {en la p\'agina siguiente}%
346  \def\reftextfacebefore{en la p\'agina anterior}%
347  \let\reftextafter     \reftextfaceafter
348  \let\reftextbefore    \reftextfacebefore
349  \def\reftextcurrent   {en esta p\'agina}%
350  \def\reftextfaraway#1{en la p\'agina~\pageref{#1}}%

351 }}

The text for swedish was contributed by Mats Dahlgren (matsd@physchem.kth.se).

352 \DeclareOption{swedish}
353 {\vref@addto\extrasswedish{%
354  \def\reftextfaceafter {p\aa\ \reftextvario{motst\aa ende}%
355  {n\"{a}sta} sida}%
356  \def\reftextfacebefore{p\aa\ \reftextvario{motst\aa ende}%
357  {f\"{o}reg\aa ende} sida}%
358  \def\reftextafter     {p\aa\ \reftextvario{f\"{o}ljande}%
359  {n\"{a}sta} sida}%
360  \def\reftextbefore    {p\aa\ f\"{o}reg\aa ende sida}%
361  \def\reftextcurrent   {p\aa\ denna sida}%
362  \def\reftextfaraway#1{p\aa\ sidan~\pageref{#1}}%

363 }}

364 \DeclareOption{turkish}
365 {\vref@excuse{turkish}%
366 \vref@addto\extrasturkish{%
367  \def\reftextfaceafter {on the \reftextvario{facing}{next} page}%
368  \def\reftextfacebefore{on the \reftextvario{facing}{preceding}
369  page}%
370  \def\reftextafter     {on the \reftextvario{following}{next} page}%

371  \def\reftextbefore    {on the \reftextvario{preceding page}{page
372  before}}%
373  \def\reftextcurrent   {on \reftextvario{this}{the current} page}%
374  \def\reftextfaraway#1{on page~\pageref{#1}}%

375 }}

We support francais as an alternative to french since people might be used to it, but we discurrage it.

376 \DeclareOption{francais}{%
377 \typeout{Please use `french' instead of `francais'}%
378 \ExecuteOptions{french}}
379 \DeclareOption{germanb}{%
380 \typeout{Please use `german' instead of `germanb'}%
381 \ExecuteOptions{german}}

After all options are declared we execute the default option english to set up the defaults and then call \ProcessOptions* to handle any option passed to the package. The star form is used since we want to execute the options in the order they are given (in case this isn’t used together with the babel package).

382 \ExecuteOptions{english}
383 \ProcessOptions*

6.2 Defining the main macros

\vr@cnt To generate new labels we use a counter and construct the internal label names by prefixing the current counter value with the string vr@. We need a L^{A}TEX counter to get \includes handled correctly.

384 \newcounter{vrcnt}

\vpageref \@vpageref The command \vpageref generates the appropriate string by first parsing the optional arguments (if any) and then compares the internal and the user label. This command should be robust since the user might put it anywhere.

385 \DeclareRobustCommand\vpageref{\@ifnextchar[%

The default for the first optional argument is the string hidden in the macro

\reftextcurrent.
386 \@vpageref{\@vpageref[\reftextcurrent]}%

387 }

388 \def\@vpageref[#1]{\@ifnextchar[%

The default for the second optional argument is a space which is prefixed by \unskip to get rid of any leading space inserted already.

389 {\@@vpageref{#1}}{\@@vpageref{#1}[\unskip\space]}}

\@@vpageref The \@@vpageref macro finally generates the references by comparing the value of an internal label with the value of the user label.

390 \def\@@vpageref#1[#2]#3{%

First it switches to horizontal mode if necessary and also removes any leading space.

391 \leavevmode\unskip

Then it advances the counter \c@vrcnt by one which is used to generate internal label names.

392 \global\advance\c@vrcnt\@ne

Then it checks if for the current value of \c@vrcnt a label command was issued in the last run. If not it pretends that there was one with the value {??}{??}. Thereafter it stores the the pageref value for this label in the macro \@tempa.

393 \@ifundefined{r@\the\c@vrcnt @vr}%
394  {\@namedef{r@\the\c@vrcnt @vr}{{??}{??}}}{}%
395 \edef\@tempa{\expandafter\expandafter\expandafter
396  \@cdr\csname r@\the\c@vrcnt @vr\endcsname
397  \@nil}%

Here we check that the generated text is not going across a page boundary.

398 \@ifundefined{r@\the\c@vrcnt @xvr}%
399  {\@namedef{r@\the\c@vrcnt @xvr}{{??}{??}}}{}%
400 \edef\@tempb{\expandafter\expandafter\expandafter
401  \@cdr\csname r@\the\c@vrcnt @xvr\endcsname
402  \@nil}%
403 {\let\@currentlabel\@empty

In version 1.0l the label string has been turned around so that the number comes first. This was done to allow easy explicit expansion of the number before it is passed to the \label command. In the babel system the argument of label was not expanded with the result that wrong label strings have been generated. This is a general problem that might need a completely different solution in babel but for now the change below (and in some other places in the code) should solve the problem for this special combination of packages.

404 \expandafter\label\expandafter{\the\c@vrcnt @xvr}}%
405 \ifx\@tempa\@tempb\else

If both points do not fall onto the same page with either issue an error or a warning message.

406 \vref@err{\noexpand\vref at page boundary
407  \@tempb-\@tempa\space (may loop)%

408 }%

409 \fi

Same game for the user requested label; this time the page reference is saved in

\@tempb.
410 \@ifundefined{r@#3}{\@namedef{r@#3}{{??}{??}}}{}%
411 \edef\@tempb{\expandafter\expandafter\expandafter
412  \@cdr\csname r@#3\endcsname
413  \@nil}%

Now after the internal label has served its purpose if would be nice to free the memory it occupies by using something like

 \global\expandafter\let
        \csname r@\the\c@vrcnt @vr\endcsname\@empty

But this is not possible because it would result in getting ‘Labels may have changed… ’ warnings for every run. Now we are ready to produce the textual strings. Since we have removed any leading space we now insert a space and then compare the two page references.

414 \space
415 \ifx\@tempa\@tempb

If they are the same we insert the first argument into the input stream. Otherwise we insert the second argument. Recall that those are the two optional arguments

of ....
416  #1%
417 \else
418  #2%

Now we check if the page number of the referenced object (stored in \@tempb is a single positive number.

419  \is@pos@number\@tempb

420 {%

If so, we check if the current position (stored in \@tempa) is a positive number. If this is the case we assign this number to the counter register \@tempcnta and add one to it.

421  \is@pos@number\@tempa
422  {\@tempcnta\@tempa
423  \advance\@tempcnta\@ne

424 }%

If it is not a positive number we assign the largest possible number to \@tempcnta and thereby pretending that label and reference are miles away from each other.

425  {\@tempcnta\maxdimen}%

Now we are ready to check if reference and object are on nearby pages. \@tempb will expand to the page number of the object (and we know that this is a number) and \@tempcnta is either one higher than the reference page or completely out of bounds. So if both represend the same value then the object lies one page after its reference.

426  \ifnum \@tempb =\@tempcnta

Thus if the object falls onto an odd page then the reference is on the facing even page (and so we insert \reftextfaceafter), otherwise the object can not be seen from the reference (and we in insert \reftextafter). Don’t be surprised if we are not using \@tempb in the check. Since \@tempcnta has the same value it is faster to use the register instead of parsing the macro contents anew.

427  \ifodd\@tempcnta

In fact we are going to use \reftextfaceafter only if we are doing two-sided printing, otherwise \reftextafter is always used. Since the value of \if@twoside is evaluated before reading in packages we could do better (saving some tokens) by defining the current macro in dependence of this boolean.

428  \if@twoside
429  \reftextfaceafter
430  \else
431  \reftextafter
432  \fi
433  \else
434  \reftextafter
435  \fi

If the object is not on the page following the reference we check if it is on the page before the reference. In L^{A}TEX this situation is not too common, for example with floats it normally does not occur, but of course it isn’t impossible if you more than one reference to the same object, or if you have back references to sections, theorems, etc. To test this we now substract two from the current value of \@tempcnta (which was set to one higher as the reference page number). Note, that substraction is also possible if the value was \maxdimen — we still get something that is much larger than any sensible page number.

436  \else
437  \advance\@tempcnta-2

If now \@tempb and \@tempcnta have the same value then the object lies one page before the reference.

438  \ifnum \@tempb =\@tempcnta

Again we have to check for odd or even pages to distinguish between the facing and the non-facing situation.

439  \ifodd\@tempcnta
440  \reftextbefore
441  \else

Again the \reftextfacebefore only if @twoside evaluates to true.

442  \if@twoside
443  \reftextfacebefore
444  \else
445  \reftextbefore
446  \fi
447  \fi

If the above test also returns false then we have object and references on pages which are far away or don’t contain simple page numbers. Therefore we generate the \reftextfaraway string. Recall that this is a macro which has the user label as an argument.

448  \else
449  \reftextfaraway{#3}%
450  \fi
451  \fi

452 }%

We do the same if our first test (that the page with the object has a positive page number) turns out to be false.

453  {\reftextfaraway{#3}}%
454 \fi

Finally we generate the internal label so that it can be check on the next run. This means that we compare the position after the string with the position of the referenced object. There is one thing to note: to conserve space we locally make \@currentlabel empty since we are only interested in the page number value of this internal label.

455 {\let\@currentlabel\@empty
456 \expandafter\label\expandafter{\the\c@vrcnt @vr}}%

457 }

\vrefwarning \vref@err When the \vref command detects a possible crossing over a page boundary it will call \vref@err to generate an error message. During document preparation one can turn such errors into warnings by issuing a \vrefwarning declaration.

458 \def\vrefwarning{\def\vref@err{\PackageWarning{varioref}}}
459 \def\vref@err#1{\PackageError{varioref}{#1}%
460  {Please check the pages in question. You might need to replace

461  the \string\vref\MessageBreak
462  or \noexpand\vpageref by a normal \noexpand\(page)ref to
463  stop LaTeX running forever.}}
\vref Undoc
464 \DeclareRobustCommand\vref[1]{%
465 \unskip~\ref{#1}%
466 \@vpageref[\unskip]{#1}%

467 }

\is@pos@number The utility macro \is@pos@number takes three arguments: a string that is tested for being a valid integer and the actions to be taken in case the test comes out true or false.

We start by passing the string to the macro \is@pos@num after prefixing it with a 0 and adding a space after it. To have a well defined ending point we also add \@nil at the end.

468 \def\is@pos@number#1{\is@pos@num0#1\space\@nil}

Now we parse the enlarged string into a counter register. To get control back after everything that is regarded by TEX as a number is put into that register we assign \is@pos@num@ to the \afterassignment token. Since the string started with 0, we can be sure that the register assignment will be carried out without an error message. In case of counter assignments leading zeros are discarded.

469 \def\is@pos@num{\afterassignment\is@pos@num@ \count@}

Now we have to check whether or not the whole string was parsed into that register or some remainder was left over. Since we have added a \@nil token at the very end we can use that to delimit the argument of \is@pos@num@. Note, that the added space in \is@pos@number above gets parsed away by the counter assignment. If it would be missing, and the full string would consist of a number, TEXwould try to replace \@nil by its definition to see if it would contain additional digits and thus we would be in trouble at this point.

470 \def\is@pos@num@#1\@nil{%

Now we have to check if the argument is empty. We can do this with an \if test (i.e., in an expandable way) since we know for sure that it can not start with a digit

471 \if0#10%

Depending on the result we execute the second or third argument of the command \is@pos@number using a technique that removes the \else or \fi from the input stream first, so that in principle input stream parsing could be done from within the arguments.

472  \expandafter\@firstoftwo \else
473  \expandafter\@secondoftwo  \fi}

\reftextvario This macro gives a little bit of random variation in the text because the outcome depends on the number of \vref commands seen before.

474 \def\reftextvario#1#2{\ifodd\c@vrcnt #1\else#2\fi}

\fullref And here is the primitive command that always produces a \ref and a \pageref.

475 \def\fullref#1{\ref{#1} \reftextfaraway{#1}}

476 ⟨/package⟩

Change History

1.0f

\reftextcurrent: Inserted missing

hash mark . . . . . . . . . . . . . . 11 1.0j

\reftextcurrent: Added french

defaults . . . . . . . . . . . . . . . . . 8 1.0k

\reftextcurrent: Corrected mis-

spelled cmd ‘extrasspanish … 11 1.0l

\@@vpageref: Explicitly expand ‘la-

bel argument for babel . . 13, 15

\reftextcurrent: Added dutch de-

faults . . . . . . . . . . . . . . . . . . . 7 1.0n

\reftextcurrent: Added Danish

defaults . . . . . . . . . . . . . . . . . 6 1.0p

\reftextcurrent: Added swedish

strings . . . . . . . . . . . . . . . . . 11

v0.1e

\vr@cnt: use LaTeX counter … 12 v0.1f

\@@vpageref: Add another label to

catch cross-overs . . . . . . . . . . 13 v0.1g

\vref@err: Macro added . . . . . . 15 \vrefwarning: Macro added …. 15

v0.1h

General: Small documentation

changes . . . . . . . . . . . . . . . . . 4 v1.0a

General: Upgrade to LaTeX2e … 1 v1.0b

\reftextcurrent: Replace in incorrect ‘def by ‘let . . . . . . . . . . . . 8 \vref@addto: Avoid using babel

‘addto . . . . . . . . . . . . . . . . . . 4 The babel commands are starting with extras . . . . . . . . . . . . . . . 4

v1.0g

\@@vpageref: Looping pages shown

in wrong order . . . . . . . . . . . 13

                                       General: Use \DeclareRobustCommand

. . . . . . . . . . . . . . . . . . . . . . . . 1

                                       \reftextcurrent: Brazil defaults

added. . . . . . . . . . . . . . . . . . . 5 \vref@err: Macro added . . . . . . 15

v1.0h

\@@vpageref: Change internal in-

terface . . . . . . . . . . . . . . . . . 12 \@vpageref: Pass first argument in

both cases . . . . . . . . . . . . . . 12 v1.0i

\@vpageref: Do it correctly …. 12 v1.0m

                                       \reftextcurrent: Added finnish

strings . . . . . . . . . . . . . . . . . . 7 v1.0o

                                       \reftextcurrent: Added defaults

for breton . . . . . . . . . . . . . . . . 5 v1.0q

                                       \reftextcurrent: Added defaults

for norsk . . . . . . . . . . . . . . . . 9 Added defaults for nynorsk …. 9

\vref@excuse: Use ‘PackageWarn-

ing . . . . . . . . . . . . . . . . . . . . . 4 v1.1b

                                       \reftextcurrent: Added defaults

for Italian . . . . . . . . . . . . . . . . 9