Ok, so I did the research myself. The answer to my question is SO simple that I am wondering if I didn't pose it well enough. It suddenly struck me like lightning: if \firstmark works in LaTeX and \topmark doesn't, then one just has to keep a list of all marks, enter it at \firstmark and then move back one item. Or, which is equivalent, keep the predecessor of each mark in the mark itself and use that when accessing the mark with \topmark.
I have now read ttlps.def and that is exactly what it is doing. I wasn't able to fix the two problems in titleps that I mentioned above, so I just rewrote and minimized it the way I need it:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% extra marks %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ExplSyntaxOn
\cs_generate_variant:Nn \tl_if_eq:nnTF { xxTF }
\def\ifsamemark#1#2{
\let\protect\@unexpandable@protect
\tl_if_eq:xxTF { #1#2 } { \firstshortmark#2 }
{ \expandafter\use_i:nn }
{ \expandafter\use_ii:nn }
}
% ttl@mkc@\a = the (macro)name for the e-tex counter for markset \a
% ttl@mks@\a = contents of a markset \a
% ttl@premks@\a = contents of the previous item of markset \a
% arg: macro, containing the current section etc.
\newcommand\newshortmark[1]{
\newmarkset{\string#1}
\newextramark{\string#1}#1
\extramark{\string#1} % initialize empty mark
}
% arg: macro or name to identify the markset
%
% \newmarkset
% defines the ttl@mkc@#1 counter with \newmarks
% defines \ttl@mks@#1 (to be empty)
% defines ttl@premks@#1 to be \ttl@mks@#1
%
\newcommand\newmarkset[1]{
% define a counter for a new markset called ttl@mkc@#1
\expandafter\newmarks\csname ttl@mkc@#1\endcsname
% \def \ttl@mks@#1 {}
\@namedef{ttl@mks@#1}{}
\@namedef{ttl@premks@#1}{\@nameuse{ttl@mks@#1}}
}
\newcommand\newextramark{\ttl@newmk@i}
% #1: markset name (macro as string: \string\macro)
% #2: \macro
\def\ttl@newmk@i#1#2{
% def \ttl@a to be the macro name (without the \)
\edef\ttl@a{\expandafter\@gobble\string#2}
% call \ttl@newmk@ii {\ttl@a} {#1}
\expandafter\ttl@newmk@ii\expandafter{\ttl@a}{#1}
}
% #1: markset name (macro as string without \)
% #2: macro as string
\def\ttl@newmk@ii#1#2{
\expandafter\def\expandafter\ttl@a\expandafter{\@nameuse{#1}}
\expandafter\let\csname ttl@mks@#2\endcsname\ttl@a
}
% #1: markset name
\newcommand\extramark[1]{%
\begingroup
\let\protect\@unexpandable@protect
% the usual \mark
\marks\csname ttl@mkc@#1\endcsname{
{\@nameuse{ttl@mks@#1}}
{\@nameuse{ttl@mks@#1}}
}
\expandafter\xdef\csname ttl@premks@#1\endcsname {\@nameuse{ttl@mks@#1}}
\endgroup
\if@nobreak\ifvmode\nobreak\fi\fi
}
\newcommand\preextramark[1]{%
\begingroup
\let\protect\@unexpandable@protect
\marks\csname ttl@mkc@#1\endcsname{%
{\csname ttl@mks@#1\endcsname}%
{\csname ttl@premks@#1\endcsname}}%
\endgroup
\if@nobreak\ifvmode\nobreak\fi\fi
}
\newcommand\shortmark[1]{\extramark{\string#1}}
\newcommand\preshortmark[1]{\preextramark{\string#1}}
\newcommand\topshortmark[1]{\topextramarks{\string#1}}
\newcommand\firstshortmark[1]{\firstextramarks{\string#1}}
% #1: the markset name (or macro)
\newcommand\topextramarks[1]{
\expandafter\use_ii:nn\firstmarks\csname ttl@mkc@#1\endcsname
}
\newcommand\firstextramarks[1]{
\expandafter\use_i:nn\firstmarks\csname ttl@mkc@#1\endcsname
}
I wanted to do it completely in LaTeX3 (I love the syntax! So much easier!) but just didn't have time yet. The code can now be used like this:
\topshortmark\indexitem
\ifsamemark\topshortmark\indexitem{}{(continued)}
which will add a (continued) to the header if a list of subitems or of page numbers is broken onto a new page. I would have loved to add another mainitem to the index but really, that output routine is beyond me...
And regarding the literal contents, I can now write:
\AddEverypageHook{
\tl_if_empty:xTF { \topshortmark\indexthumb }
{}
{
\fancytab{ \topshortmark\indexthumb }{ \int_from_alph:n { \topshortmark\indexthumb } }
}
}
\topextramarks \int_from_alph:n { \indexthumb }(untested). (2) It seems a bug - I'll have a look at it. – Javier Bezos Mar 13 '12 at 14:38\topextramarks{indexmark} \int_from_alph:n {\indexthumb}but that is interpreted as two separate commands and gives me the current \indexthumb, not the topmark one. – MiB Mar 14 '12 at 19:11