# Customizing relative page references

How can I obtain detailed information about the location of a label relative to other text and display a custom text based on this information?

• If the label comes on the immediate previous page (and this one is recto), print "on the left-hand page".
• If the label comes on the immediate previous page (and this one is verso), print "on the previous page".
• If the label comes on the immediate next page (and this one is verso), print "on the right-hand page".
• If the label comes on the immediate next page (and this one is recto), print "on the following page".

Otherwise:

• If the label comes before, on the same line, print "before, on this line."
• If the label is above on the same page, print "above, on this page".
• If the label comes after, on the same line, print "after, on this line."
• If the label is below on the same page, print "below, on this page".

Otherwise:

• If the label comes before (a previous page), print "on a previous page".
• If the label comes after (a later page), print "on a later page".

The varioref package seems to have some of these features, but this presents some problems:

• I do not which to print the page number, which vpageref tends to do.
• My document does not use English, so I need to have better control over what text appears, including control over the spaces.
-
Interesting question, but is there really ever need for "before/after, on this line"? For one, the space required by that fragment has a good chance of pushing the content it refers to off the line. Could you give an example of where you might want to reference content that's that close? –  Jake Dec 5 '11 at 3:15
You are probably right. That probably will not happen and it is probably too difficult to implement that part. –  Village Dec 5 '11 at 3:27

This is possible when using the zref package. Loading the user module (or directly via the zref-user package) you have access to a number of properties associated with a \zlabel (similar to LaTeX's \label).

\documentclass[twoside]{article}
\usepackage[margin=5mm,paperheight=2in,paperwidth=4in,bottom=15mm]{geometry}% http://ctan.org/pkg/geometry
\usepackage[user]{zref}% http://ctan.org/pkg/zref

\newcounter{refcnt}% Counter used with every reference
\makeatletter
\newcommand{\myref}[1]{%
\stepcounter{refcnt}\zlabel{#1@\therefcnt}%
\texttt{#1} is on page~\zref[page]{#1}.
This is page~\zref[page]{#1@\therefcnt}. \par
\texttt{#1} is on a~\ifodd\zref@extract{#1}{page}recto\else verso\fi~page.
This is a~\ifodd\zref@extract{#1@\therefcnt}{page}recto\else verso\fi~page. \par
\texttt{#1} is
\ifnum\zref@extract{#1@\therefcnt}{page}=\zref@extract{#1}{page} % same page
\else
\ifnum\numexpr\zref@extract{#1@\therefcnt}{page}-\zref@extract{#1}{page}\relax=1 % previous page
\ifodd\zref@extract{#1@\therefcnt}{page}
on the left-hand page.
\else
on the previous page.
\fi
\else
\ifnum\numexpr\zref@extract{#1}{page}-\zref@extract{#1@\therefcnt}{page}\relax=1 % next page
\ifodd\zref@extract{#1@\therefcnt}{page}
on the next page.
\else
on the right-hand page.
\fi
\else
\ifnum\zref@extract{#1}{page}>\zref@extract{#1@\therefcnt}{page} %
\else
\strip@pt\dimexpr\zref@extract{#1@\therefcnt}{page}pt-\zref@extract{#1}{page}pt\relax~pages before.
\fi
\fi
\fi
\fi
}
\makeatother

\begin{document}
This is~\texttt{foo}.\zlabel{foo} \par \medskip
\myref{foo}

\newpage

\myref{foo} \par \medskip
\myref{bar}

\newpage

\myref{foo} \par
This is~\texttt{bar}.\zlabel{bar}

\newpage

\myref{bar}
\end{document}


For each label <lab> that is referenced via \myref{<lab>}, a new \zlabel <lab>@<refcnt> is set where <refcnt> is an ordinary running counter. This allows for extracting properties associated with <lab>@<refcnt> to perform calculations with.

\zref@extract{<ref>}{<prop>} provides an expandable version of the property <prop> of label <ref>, allowing for calculations. In the above example, recto and verso pages are decided based on whether page is odd/even.

\myref could be expanded to include line referencing using the savepos module, which would allow for referencing "...above, on this page." or "...below, on this page." This would be achieved by using the expandable \zposy{<lab>} to extract the y-coordinate of the label <lab> on the page and comparing it to some other label.

Note that you have to compile at least twice for the references to "settle," despite possible errors that LaTeX complains about during the first run.

-