1

This is a follow-up question to Making marginnote to appear either side of twocolumn, twoside document, taking into account Marginnote right after \section: how to prevent page break? (the main difference being the use of \strut instead of \needspace).

In this MWE, the note appears on the wrong column:

\documentclass[twocolumn,twoside]{article}

\usepackage{lipsum}
\usepackage{marginnote}

\makeatletter
\let\oldmarginnote\marginnote
\renewcommand*{\marginnote}[1]{%
    \strut%
    \begingroup%
        \ifodd\value{page}
            \if@firstcolumn\reversemarginpar\fi
        \else
            \if@firstcolumn\else\reversemarginpar\fi
        \fi
        \oldmarginnote{#1}%
    \endgroup%
}
\makeatother


\begin{document}
    \lipsum[4-6]
    \lipsum[6]
    \marginnote{Note on wrong column}
    Text with note
\end{document}

This seems to be an issue with \if@firstcolumn. How can this be fixed?

2 Answers 2

1

Your code won't work and the answer you linked to is wrong. The problem can be seen with this example:

\documentclass[twocolumn,twoside]{article}

\usepackage{lipsum}
\usepackage{marginnote}
\makeatletter
\let\oldmarginnote\marginnote
\renewcommand*{\marginnote}[1]{%
 \begingroup\strut
     \if@firstcolumn
      \reversemarginpar
      \oldmarginnote{first #1}%
     \else
      \normalmarginpar
      \oldmarginnote{second #1}%
     \fi
 \endgroup%
}
\makeatother


\begin{document}
    blalla\marginnote{text 1}
    \lipsum[4-6]
    \lipsum[6]

    \marginnote{text 2}%
    Text with note

    \marginnote{text 3}%
    Text with note
\end{document}

Because of the asynchronous page building of tex the marginnote "test 2" thinks it is on column 1.

Detecting correctly the current column isn't easy (see e.g. Detecting current column in multicol).

In your case you could use the zref-savepos (I found the value 19000000 by looking in the aux the position of "stop" and "start2". This could be improved):

\documentclass[twocolumn,twoside]{article}

\usepackage{lipsum}
\usepackage{marginnote,zref-savepos}
\newcounter{labelnote}
\makeatletter
\let\oldmarginnote\marginnote
\renewcommand*{\marginnote}[1]{%
 \begingroup\strut
  \stepcounter{labelnote}\zsaveposx {marginnote-\thelabelnote}
     \ifnum 0\zposx{marginnote-\thelabelnote}<19000000
      \reversemarginpar
      \oldmarginnote{first #1}%
     \else
      \normalmarginpar
      \oldmarginnote{second #1}%
     \fi
 \endgroup%
}
\makeatother


\begin{document}
    %\noindent\zsaveposx{start}x\hfill y\zsaveposx{stop}

    blalla\marginnote{text 1}
    \lipsum[4-6]
    \lipsum[6]

    \marginnote{text 2}%
    Text with note

    \marginnote{text 3}%
    Text with note

    %\noindent\zsaveposx{start2}x\hfill y\zsaveposx{stop2}
\end{document}
4
  • Thanks! Could you be a little more specific with respect to which "answer [I] linked to" is "wrong"? I linked to two different answers. My second question is about your first MWE: I may be missing its point, what does it show that my original MWE does not? I will try your replacement of \if@firstcolumn.
    – bers
    May 28, 2015 at 15:22
  • The answer you linked to is wrong because the tests it uses (if the page is odd, if in first column) will fail in edge case, e.g. when a marginnote is just at the top of the second column like in my example: "text 3" is correctly on the right, but "text 2" is not (text 2 is printed on top of text 1). TeX always looks a bit ahead and so executes the code in the second marginnote when still building the first column. May 28, 2015 at 15:49
  • I know all that, this is why I asked my original question. Although I would not dare to call someone else's answer "wrong" just because it fails in edge cases. If that was the case, the whole flushend package would be wrong, and so many more. And by the way, that edge case you mention IS already shown in my original MWE, so I wonder why you took the time to reproduce it.
    – bers
    May 28, 2015 at 17:06
  • From your code it wasn't obvious that the wrong placement was due to the asynchronous page building (and that you knew this is the source). And code that doesn't take the asynchronous page building into account is wrong and I dare to say it. May 28, 2015 at 18:56
2

Tikz[remember picture,overlay] provides accurate location information by writing the origin and page number to the aux file each time. Consequently it takes two runs to get it to work.

\documentclass[twocolumn,twoside]{article}
\usepackage{lipsum}
\usepackage{marginnote}
\usepackage{tikzpagenodes}

\newlength{\tempdima}
\newcount{\tikzpage}

\makeatletter
\let\oldmarginnote\marginnote
\renewcommand*{\marginnote}[1]{%
  \begin{tikzpicture}[remember picture, overlay]%
    \pgfextractx{\tempdima}{\pgfpointanchor{current page text area}{center}}%
    \global\tempdima=\tempdima
    \global\tikzpage=\oddpage@page
  \end{tikzpicture}%
  \begingroup
    \ifodd\tikzpage\relax
      \ifdim\tempdima>0pt \reversemarginpar\fi
    \else
      \ifdim\tempdima<0pt \reversemarginpar\fi
    \fi
  \oldmarginnote{#1}%
  \endgroup% resets \reversemarginpar
}
\makeatother

\begin{document}
    \marginnote{left}
    \lipsum[4-6]
    \lipsum[6]
    \marginnote{right}
    Text with note
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .