# Code inside an equation environment is executed 4 times (or isn't it?).

I created a small example:

\documentclass[a4paper,12pt]{article}
\usepackage{amsmath}
\usepackage[pdfstartview=FitH]{hyperref}
\usepackage{bookmark}
\begin{document}
one line
\newcounter{test}
$\text{\stepcounter{test}\bookmark[dest=whatever]{my equation}one equation}$
counter value: \arabic{test}.
\end{document}


It creates 4 bookmarks but increases the counter only by 1. How is that (even logically) possible? Either this equation environment somehow executes the code 4 times (maybe first measuring the contents or whatever), then the counter should be increased by four. Or it only executes once, then there should only be one bookmark.

How do I get it to display only one bookmark? (moving it out of the equation is not an option since this happens inside a macro which at the same time marks the equation as target.)

update:

alright, egregs \tbookmark command fixed my minimal example. turns out it was too minimal. here is another one which went back to not working:

\documentclass[a4paper,12pt]{article}
\usepackage{amsmath}
\usepackage[pdfstartview=FitH]{hyperref}
\usepackage[atend]{bookmark}
\makeatletter\newcommand{\tbookmark}[2][]{\iffirstchoice@\bookmark[#1]{#2}\fi}\makeatother
\newcounter{nops}
\newcommand{\nop}{\stepcounter{nops}\raisebox{\ht\strutbox}{\hypertarget{nop\arabic{nops}}{}}\begingroup\edef\x{\endgroup\noexpand\BookmarkAtEnd{\noexpand\tbookmark[dest=nop\arabic{nops}]{page \arabic{nops}}}}\x}
\begin{document}
one line
$\text{\nop one equation}$
counter value: \arabic{nops}.
\end{document}

-
I get only one bookmark. (I use TeX Live 2010 with latest packages) –  Leo Liu May 1 '11 at 15:14
I use miktex 2.9. I just started an update and will report back later. What additional information might be helpful to debug this? –  peter May 1 '11 at 15:18
the TeX primitive \mathchoice has four arguments corresponding to display, text, script and script-script style. When TeX encounters it it constructs all four and then inserts the appropriate one. So it could be a case of this primitive being used somewhere. –  jfbu May 1 '11 at 17:37
updated miktex, output unchanged. –  peter May 1 '11 at 20:56

\text uses internally \mathchoice (so jfbu was right), but amstext.sty redefines \stepcounter and \addtocounter in such a way that they act only once.

A cheap solution would be to define a special \bookmark command:

\makeatletter
\newcommand{\tbookmark}[2][]{%
\iffirstchoice@
\bookmark[#1]{#2}%
\fi}
\makeatother


that will be free of the problem. Probably something that Heiko should take care of.

One might try also with letltxmacro (the redefinition must go after \usepackage{bookmark}):

\usepackage{letltxmacro}
\makeatletter
\LetLtxMacro{\orig@bookmark}{\bookmark}
\renewcommand{\bookmark}[2][]{%
\iffirstchoice@\orig@bookmark[#1]{#2}\fi}
\makeatother


--- Added after Peter's edits ---

Any command to be used inside \text and which sets bookmarks or hypertargets should be defined in terms of \iffirstchoice@:

\newcommand{\nop}{%
\stepcounter{nops}%
\iffirstchoice@
\raisebox{\ht\strutbox}{\hypertarget{nop\arabic{nops}}{}}
\fi}


The AMS packages define \text using the conditional \iffirstchoice@; essentially, \text{...} is defined to become

\mathchoice{\firstchoice@true\textrm{...}}
{\firstchoice@false\textrm{...}}
{\firstchoice@false\textrm{...}}
{\firstchoice@false\textrm{...}}


One has to remember that \mathchoice typesets all four forms and TeX chooses one depending on the needed math style; with \iffirstchoice@<tokens>\fi we are sure that the <tokens> are found only once.

-
How is \LetltxMacro different from \let? –  Aditya May 1 '11 at 20:27
@Aditya: When a command is defined with an optional argument, using \let to keep its definition is not safe at all. I believe this is a good question to ask. –  egreg May 1 '11 at 21:04
@egreg: Thanks. I looked up the documentation of letltxmacro and it clearly explains why \let fails. –  Aditya May 1 '11 at 21:59
you fixed my minimal example, but my production file still exhibited the faulty behavior. so please look at the new minimal example, i updated the question. –  peter May 3 '11 at 6:58
show 1 more comment