Where on the page was the index entry created?

At yesterday’s TeX meetup in Ladenburg—curiously enough, the Heidelberg TeX meetup has been taking place in my neighboring town for several years now—I was shown a beautiful, old Latin grammar book. What was particularly nice about it was the index. Next to the page numbers were small superscript numbers indicating whether the corresponding index entry was located in the first, second, third, or fourth quarter of the page. This actually makes it easier to search the page. When you consider that 100 years ago the entire index was still compiled by hand, you can imagine what a labor-intensive task that was.

The question that followed was obvious: Can you do this with TeX as well? My immediate answer: Sure. About a quarter of an hour later, I had a solution to offer:

\documentclass[english]{scrartcl}
\usepackage{makeidx}
\usepackage{babel}
\usepackage{blindtext}
\makeindex

\makeatletter
% Definition copied from latex.ltx and modified:
\def\@wrindex#1{%
  \pdfsavepos
   \protected@write\@indexfile{}%
      {\string\indexentry{#1|pmark{\noexpand\the\pdflastypos}}{\thepage}}%
 \endgroup
 \@esphack}
% Additions:
\newcommand*{\pmark}[2]{%
  #2\ifnum #1>\value{Delineation}\textsuperscript{1}\else\textsuperscript{2}\fi}
\newcounter{Delineation}
\setlength{\@tempdima}{.5\paperheight}
\setcounter{Delineation}{\@tempdima}
\makeatother

\usepackage{eso-pic}

\begin{document}
\AddToShipoutPicture{%
  \AtPageLowerLeft{%
    \setlength{\unitlength}{1sp}%
    \put(0,\value{Delineation}){\line(1,0){\LenToUnit{\paperwidth}}}%
  }%
}
\textbf{A}\marginpar{A}\index{TestA}\blindtext
\textbf{B}\marginpar{B}\index{testB}\blindtext
\textbf{C}\marginpar{C}\index{TestC}\blindtext
\textbf{D}\marginpar{D}\index{testD}\blindtext
\textbf{E}\marginpar{E}\index{TestE}\blindtext
\textbf{F}\marginpar{F}\index{testF}\blindtext
\textbf{G}\marginpar{G}\index{TestG}\blindtext
\textbf{H}\marginpar{H}\index{testH}\blindtext
\textbf{A}\marginpar{A}\index{TestA}\blindtext
\printindex
\end{document}

Unlike the original problem, this quick solution distinguishes only between the upper and lower halves of the page (not the type area). Compared to last night’s solution, the boundary is no longer specified explicitly but is instead calculated—albeit in a very primitive way—and visualized using eso-pic so that you can assess whether the entries are correctly positioned.

To view the result, you need to run pdflatex (whether in DVI, PDF, or draft mode), run MakeIndex, and then run pdflatex again. As you can see from the last entry, this also works when multiple entries are created for a single term. However, a drawback of this solution is that it relies on page number formatting to write information about the vertical position to the idx file. This means that entries like \index{foo|textbf} no longer work. The same applies to hyperpage formatting via hyperref. To re-enable these features, the solution above would need to be extended in a similar way to how it is done in newer versions of hyperref. This is solvable.

Of course, I could also have used the following redefinition:

\def\@wrindex#1{%
  \pdfsavepos
   \protected@write\@indexfile{}%
      {\string\indexentry{#1}{\thepage\string\pmark{\noexpand\the\pdflastypos}}}%
 \endgroup
 \@esphack}
\newcommand*{\pmark}[1]{%
  \ifnum #1>\value{Delineation}\textsuperscript{1}\else\textsuperscript{2}\fi}

In that case, the information about the vertical position would be appended directly to the page number. Unfortunately, MakeIndex cannot handle this additional information in the page numbers at all. However, this might be a possibility for use with Xindy. I’ll leave it to the Xindy experts to come up with a suitable Xindy solution.

Since my package luaindex does not sort page numbers but assumes that the page numbers are written to the index in the correct order (in which case, of course, you cannot use QuickSort), an extension to handle this should also be fairly simple.

Of course, the question immediately arose last night as to whether, instead of a purely vertical division of the page, one could overlay a proper grid. If you extend the solution above with \pdflastxpos and further refine the case distinction within \pmark, you can achieve this without any major problems.

As you can see, at first glance this was once again a somewhat unusual question. Nevertheless, it’s one of those curiosities that can be solved using TeX tools.