4

I am trying to understand a bit better what atbegshi and lineno do (or accomplish). In the following example, I add the current linenumber to the shipout and am struggling to fully understand what's going on.

\documentclass{article}
\usepackage{lipsum}
\usepackage{atbegshi}
\usepackage[pagewise]{lineno}
\usepackage{tikz} % only for illustration
\begin{document}
\linenumbers
\AtBeginShipout{\AtBeginShipoutAddToBox{\fbox{\arabic{linenumber}}
\tikz[overlay,remember picture]{\draw[thick,blue,latex-](lastline)--++(-2cm,0);}}}
\renewcommand\thelinenumber{\arabic{linenumber}%
\tikz[overlay,remember picture]{\node(lastline){\strut};}}
\begin{itemize}
\item \lipsum*[1]
\item \lipsum*[2]
\item \lipsum*[3]
\item \lipsum*[4]
\item \lipsum*[5]
\item \lipsum*[6]
\item \lipsum*[7]
\item \lipsum*[8]
\item \lipsum*[9]
\item \lipsum*[10]
\item \lipsum*[11]
\item \lipsum*[12]
\item \lipsum*[13]
\end{itemize}
\lipsum[1-10]
\end{document}

On the first page, I get the result 44, which is too large by one, whereas on the second page I get 87, which is correct. I sort of think to understand why this is happening: in the first case, TeX decides later to move the last line to the next page, but in the second case there is no need for that. Now I am wondering if there is a way to cure this. (It is also somewhat surprising that the line number keeps growing despite the pagewise option, and if someone knows an elegant fix I'd be eager to learn as I can only think of an ugly fix at this point.)

In addition, I define nodes with TikZ. Knowing that this is bad practice, I keep on overwriting these nodes, and I wish to mark the last line (number) using \AtBeginShipout. However, I get a crazy pattern, either the last or the first line get marked. Most likely the reason is the same as above, and presumably the issue is gone once the first part of the question is solved.

What could this be good for? Among other things, one may finally answer this question, but really I wish this way to access the area filled by text.

4

You get the line number that was active, when the asynchronous output routine was called. Therefore, the value of counter linenumber is not reliable, if it is asked in the shipout routine (\AtBeginShipout).

Because of option pagewise, package lineno has to know, how many lines are on each page and column. It uses the same trick as page references do. The data are stored in the .aux file and read in the next LaTeX run.

Package lineno maintains a linked list of the data in the .aux file. Each column has an entry, the head is \LN@Pfirst. Data of the example below with two columns:

\LN@Pfirst -> \nextLN \LN@P0C1 
\LN@P0C1 -> \lastLN {44}\firstLN {0}\pageLN {0}{1}{0}\nextLN \LN@P0C2 
\LN@P0C2 -> \lastLN {88}\firstLN {45}\pageLN {0}{2}{0}\nextLN \LN@P1C1
\LN@P1C1 -> \lastLN {132}\firstLN {89}\pageLN {1}{1}{89}\nextLN \LN@P1C2
  • The macro name consists of the zero-based page number and the one-based column number (\LN@P3C2 is the macro for page 4 and column 2).
  • \lastLN is the last zero-based line number of the column.
  • \firstLN is the first zero-based line number of the column.
  • \pageLN stores three data, the zero-based page-number, the one-based column number and the zero-base line number of the first line of the page. \nextLN is the pointer to the next column.

The following example uses these data to fix the example of the question. It also supports more than one column.

\documentclass[twocolumn]{article}
\usepackage[columnsep=1cm]{geometry}
\usepackage{microtype}
\usepackage{lipsum}
\usepackage{atbegshi}
\usepackage[pagewise]{lineno}
\usepackage{tikz} % only for illustration

\makeatletter
\newcount\AbsolutePageNumber % zero-based
\AbsolutePageNumber=\z@
\newcommand*{\UnknownLineNumber}{??}
\let\FirstLineNumber\UnknownLineNumber
\let\LastLineNumber\UnknownLineNumber
\newcommand*{\GetLineNumbers}{%
  \begingroup
    \let\nextLN\relax
    \def\pageLN##1##2##3{%
      \ifnum##1=\AbsolutePageNumber
        \xdef\FirstLineNumber{\the\numexpr##3+1}%
        \global\let\LastLineNumber\@LastLineNumber
      \fi
      \ifnum##1>\AbsolutePageNumber
        \let\nextLN\relax
      \fi
    }%
    \let\firstLN\@gobble
    \def\lastLN##1{%
      \def\@LastLineNumber{\the\numexpr##1+1}%
    }%
    \LN@Pfirst
  \endgroup
}
\AtBeginShipout{%
  \GetLineNumbers
  \AtBeginShipoutAddToBox{%
    \ifx\FirstLineNumber\UnknownLineNumber
    \else
      \fbox{%
        \the\numexpr\LastLineNumber + 1 - \FirstLineNumber\relax
        ~(\FirstLineNumber--\LastLineNumber)%
      }%
    \fi
    \expandafter\ifx\csname Anchor\LastLineNumber\endcsname\relax
    \else
      \tikz[overlay,remember picture]{%
        \draw[thick,blue,latex-](ln\LastLineNumber)--++(-2cm,0);%
      }%
    \fi
  }%
  \global\advance\AbsolutePageNumber\@ne
}
\renewcommand\thelinenumber{%
  \arabic{linenumber}%
  \GetLineNumbers
  \ifx\LastLineNumber\UnknownLineNumber
  \else
    \ifnum\LastLineNumber=\numexpr\FirstLineNumber+\value{linenumber}-1\relax
      \tikz[overlay,remember picture]{%
        \node(ln\LastLineNumber){\strut};%
      }%
      \global\expandafter\let\csname Anchor\LastLineNumber\endcsname\@empty
    \fi
  \fi
}
\makeatother

\begin{document}
\linenumbers
\begin{itemize}
\item \lipsum*[3]
\item \lipsum*[4]
\item \lipsum*[5]
\item \lipsum*[6]
\item \lipsum*[7]
\item \lipsum*[8]
\item \lipsum*[9]
\item \lipsum*[10]
\item \lipsum*[11]
\item \lipsum*[12]
\item \lipsum*[13]
\item \lipsum*[14]
\end{itemize}
\lipsum[1-10]
\end{document}

The TikZ part was trickier: The label for the last line of the page can only be set, if this line number is known (second run). A global macro remembers that the node is actually put on the page to avoid that the arrow is drawn to an unknown node.

The uses internal macros of package lineno. The version used is:

Package: lineno 2005/11/02 line numbers on paragraphs v4.41

The first two pages of the generated four-page document:

Page 1: 89 (1-89) Page 2: 88 (90-177)

Your Answer

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