1

I am defining a computation environment which defines a bunch of equations. Each equation has a number and I want to print that number. To generate automatically the correct number, I use the label/reference mechanism of LaTeX. Here is my code:

\documentclass{article}
\usepackage{hyperref}

\newcounter{cp}
\newcommand{\rcp}[1]{\refstepcounter{cp}\label{\ctmp:#1}}
\newcommand{\cref}[1]{\ref{\ctmp:#1}}
\newenvironment{computation}[1]{
  \def\ctmp{#1}
  \begin{tabular}{lc|lc}
}
    {
  \end{tabular}
  \setcounter{cp}{0}
}


\newcommand{\addeq}[4]{
  \rcp{#1}\((\thecp{})\) & #2 & #3 & #4\\
}

\begin{document}

\begin{computation}{first}
   \addeq{cp:1}{foo}{justification of foo}{}
    \hline
    \addeq{cp:2}{bla}{justification of bla (using foo)}{\cref{cp:1}}
\end{computation}

\clearpage

\begin{computation}{second}
   \addeq{cp:1}{foo}{justification of foo}{}
    \hline
    \addeq{cp:2}{bla}{justification of bla (using foo)}{\cref{cp:1}} % here the reference is bad.
\end{computation}

\end{document}

The problem I have, is that each time I reference an equation, the correct number is printed, but on the PDF, the link send me back to the equation where the macro computation was used the first time, and not in the current computation environment.

I suppose it is related to the evaluation mechanism of LaTeX, but I don't see my mistake.

  • 2
    As always on this site, please provide a full minimal example instead of sniplets like this. Then it is a lot easier for others to copy and play with. – daleif Jun 26 at 13:39
  • My bad, I use the article class so that the command clearpage does not fail. – Saroupille Jun 26 at 15:19
  • 1
    Slightly off-topic: the widely-used cleveref cross-referencing package defines a macro called \cref. You may therefore want to give your user macro a different name. – Mico Jun 26 at 15:25
  • 1
    \label and \ref, while useful, are not the only game in town. You can store information in global macros and use \hypertarget and \hyperlink to link things. – John Kormylo Jun 26 at 15:26
2

You also get on the terminal and in the .log-file some error-messages of the pattern:

pdfTeX warning (ext4): destination with the same identifier (name{cp.1}) has been already used, duplicate ignored

The reason is within the ending-part of your computaion-environment the line \setcounter{cp}{0} :

When \rcp is carried out, \refstepcounter{cp} is carried out also. When using hyperref, then \refstepcounter{cp} in turn also creates a destination for hyperlinks. That destination has a name. That name by default is derived both from the name and from the value of the counter cp. The value of the counter cp is obtained by expanding the macro \theHcp. Thus if the value of cp is reset to 0 at some point, uniqueness of names of destinations for hyperlinks is not ensured any more.

You need to ensure uniqueness of names of destinations for hyperlinks. You can do so by redefining \theHcp in a way so that resetting the cp-counter doesn't matter regarding uniqueness of names of destinations for hyperlinks.

One possibility is counting the instances of the computation-environment as well and adding the number of the corresponding computation-environment to the expansion of \theHcp as well. In the example below this is done by means of a macro \ThisCpmputationinstance which with each instance of the computation-environment gets defined only within the scope formed by that instance. It is done this way because \stepcounter and \refstepcounter work globally which means that using \arabic{computationinstance} directly might turn things weird in case of nesting instances of the computation-environment.

Besides this you may also wish to do something about the vertical placement of the destinations for hyperlinks that get created due to \refstepcounter:

Actually a destination would vertically be placed on the baseline of the box wherein it occurs.
Thus clicking a hyperlink would (vertically) scroll the baseline of the corresponding box to the top of the window wherein the .pdf-file is viewed. Thus you would not see those parts of glyphs/letters etc that are above the baseline.
Therefore with the hyperref-package additional work was done for ensuring that destinations are vertically shifted upwards by the amount of \baselineskip (which is the distance between the baselines of two consecutive lines of text) if LaTeX is not in vertical mode.
Usually this is nice. But not within tabular-environments because within these environments \baselineskip is 0 which means shifting upwards by 0 which means navigating to the corresponding destination by clicking the link ends up at scrolling the baseline of the corresponding box to the top of the window wherein the .pdf-file is viewed. Which means not seeing those parts of the glyphs in that box that are above the baseline.
I suggest using the dimensions of \strutbox inside these environments rather than using \baselineskip.

In the examples below I added some % here and there in order to prevent the coming into being of unneeded/unwanted space tokens.

\documentclass{article}
\usepackage{hyperref}

\newcounter{cp}
\newcounter{computationinstance}
\newcommand{\ThisCpmputationinstance}{}%
\edef\ThisCpmputationinstance{\arabic{computationinstance}}
\renewcommand{\theHcp}{\ThisCpmputationinstance.\arabic{cp}}
\newcommand\savedHyperRaiseLinkHook{}
\newcommand{\rcp}[1]{%
   %\ifvmode\leavevmode\fi
   \let\savedHyperRaiseLinkHook\HyperRaiseLinkHook
   \def\HyperRaiseLinkHook{%
     % Usually \HyperRaiseLinkLength equals \baselineskip but
     % \baselineskip is 0 inside tabulars, thus let's use
     % the dimensions of the strutbox instead:
     \setlength\HyperRaiseLinkLength{\ht\strutbox}%
     \addtolength\HyperRaiseLinkLength{\dp\strutbox}%
   }%
   \refstepcounter{cp}%
   \let\HyperRaiseLinkHook\savedHyperRaiseLinkHook
   \label{\ctmp:#1}}%

\newcommand{\MYcref}[1]{\ref{\ctmp:#1}}
\newcommand{\ctmp}{}%
\newenvironment{computation}[1]{%
  \stepcounter{computationinstance}% 
  \edef\ThisCpmputationinstance{\arabic{computationinstance}}%
  \def\ctmp{#1}%
  \begin{tabular}{lc|lc}%
}{%
  \end{tabular}%
  \setcounter{cp}{0}%
}


\newcommand{\addeq}[4]{%
  \rcp{#1}\((\thecp{})\)&#2&#3&#4\\%
}%

\begin{document}

\begin{computation}{first}%
   \addeq{cp:1}{foo}{justification of foo}{}%
   \hline
   \addeq{cp:2}{bla}{justification of bla (using foo)}{\MYcref{cp:1}}%
\end{computation}

\clearpage

\begin{computation}{second}%
   \addeq{cp:1}{foo}{justification of foo}{}%
   \hline
   \addeq{cp:2}{bla}{justification of bla (using foo)}{\MYcref{cp:1}}% here the reference is okay now.
\end{computation}

\end{document}

As long as it is ensured that both no two instances of the computation-environment have the same name, and no environment-instance-name contains dangerous (non-character-)tokens, you can probably ensure uniqueness of names of destinations for hyperlinks by just adding \ctmp to the expansion of \theHcp:

\documentclass{article}
\usepackage{hyperref}

\newcounter{cp}
\renewcommand{\theHcp}{\ctmp.\arabic{cp}}
\newcommand\savedHyperRaiseLinkHook{}

\newcommand{\rcp}[1]{%
   %\ifvmode\leavevmode\fi
   \let\savedHyperRaiseLinkHook\HyperRaiseLinkHook
   \def\HyperRaiseLinkHook{%
     % Usually \HyperRaiseLinkLength equals \baselineskip but
     % \baselineskip is 0 inside tabulars, thus let's use
     % the dimensions of the strutbox instead:
     \setlength\HyperRaiseLinkLength{\ht\strutbox}%
     \addtolength\HyperRaiseLinkLength{\dp\strutbox}%
   }%
   \refstepcounter{cp}%
   \let\HyperRaiseLinkHook\savedHyperRaiseLinkHook
   \label{\ctmp:#1}}%

\newcommand{\MYcref}[1]{\ref{\ctmp:#1}}
\newcommand{\ctmp}{}%
\def\ctmp.{}%
\newenvironment{computation}[1]{%
  \def\ctmp{#1}%
  \begin{tabular}{lc|lc}%
}{%
  \end{tabular}%
  \setcounter{cp}{0}%
}

\newcommand{\addeq}[4]{%
  \rcp{#1}\((\thecp{})\)&#2&#3&#4\\%
}%

\begin{document}

\begin{computation}{first}%
   \addeq{cp:1}{foo}{justification of foo}{}%
   \hline
   \addeq{cp:2}{bla}{justification of bla (using foo)}{\MYcref{cp:1}}%
\end{computation}

\clearpage

\begin{computation}{second}%
   \addeq{cp:1}{foo}{justification of foo}{}%
   \hline
   \addeq{cp:2}{bla}{justification of bla (using foo)}{\MYcref{cp:1}}% here the reference is okay now.
\end{computation}

\end{document}
  • It works perfecly well, thank you! – Saroupille Jul 3 at 11:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.