From edefb18d2847b269a094f2a7d3db4a35e598a7c9 Mon Sep 17 00:00:00 2001 From: Frank Mittelbach Date: Mon, 17 Feb 2020 16:13:43 +0100 Subject: [PATCH] back to xmarks as package name more documentation --- l3trial/xmarks/build.lua | 5 +- l3trial/xmarks/testfiles/xmarks-000.lvt | 2 +- l3trial/xmarks/testfiles/xmarks-000.tlg | 4 +- l3trial/xmarks/testfiles/xmarks-001.lvt | 2 +- l3trial/xmarks/testfiles/xmarks-002.lvt | 2 +- l3trial/xmarks/testfiles/xmarks-003.lvt | 2 +- l3trial/xmarks/testfiles/xmarks-004.lvt | 2 +- l3trial/xmarks/testfiles/xmarks-005.lvt | 2 +- l3trial/xmarks/testfiles/xmarks-006.lvt | 2 +- .../{xmarks2-code.tex => xmarks-code.tex} | 2 +- .../{xmarks2-doc.tex => xmarks-doc.tex} | 2 +- l3trial/xmarks/xmarks.dtx | 1378 ++++++++++------- l3trial/xmarks/xmarks.ins | 2 - l3trial/xmarks/xmarks2.dtx | 1064 ------------- 14 files changed, 829 insertions(+), 1642 deletions(-) rename l3trial/xmarks/{xmarks2-code.tex => xmarks-code.tex} (80%) rename l3trial/xmarks/{xmarks2-doc.tex => xmarks-doc.tex} (82%) delete mode 100644 l3trial/xmarks/xmarks2.dtx diff --git a/l3trial/xmarks/build.lua b/l3trial/xmarks/build.lua index 1e9814d9e0..75f5b9389d 100644 --- a/l3trial/xmarks/build.lua +++ b/l3trial/xmarks/build.lua @@ -11,7 +11,7 @@ module = "xmarks" maindir = "../.." -- Non-standard settings -checkdeps = {maindir .. "/l3packages/xparse"} +-- checkdeps = {maindir .. "/l3packages/xparse"} -- not doing uptex as it generates spurious font warnings ... @@ -27,8 +27,6 @@ typesetfiles = {"*.tex"} checkruns = 2 - - checksuppfiles = { "CaseFolding.txt", @@ -44,7 +42,6 @@ checksuppfiles = "size10.clo", } - -- Load the common build code dofile(maindir .. "/build-config.lua") diff --git a/l3trial/xmarks/testfiles/xmarks-000.lvt b/l3trial/xmarks/testfiles/xmarks-000.lvt index 645bc0081a..1644860e4a 100644 --- a/l3trial/xmarks/testfiles/xmarks-000.lvt +++ b/l3trial/xmarks/testfiles/xmarks-000.lvt @@ -9,6 +9,6 @@ \START -\usepackage{xmarks2} +\usepackage{xmarks} \END diff --git a/l3trial/xmarks/testfiles/xmarks-000.tlg b/l3trial/xmarks/testfiles/xmarks-000.tlg index 2d7fea2e5e..7489405caa 100644 --- a/l3trial/xmarks/testfiles/xmarks-000.tlg +++ b/l3trial/xmarks/testfiles/xmarks-000.tlg @@ -1,13 +1,13 @@ This is a generated file for the LaTeX (2e + expl3) validation system. Don't change this file in any respect. -(xmarks2.sty (xparse.sty +(xmarks.sty (xparse.sty Package: xparse ....-..-.. L3 Experimental document command parser \l__xparse_current_arg_int=\count... \g__xparse_grabber_int=\count... \l__xparse_m_args_int=\count... \l__xparse_v_nesting_int=\count... ) -Package: xmarks2 ....-..-.. L3 Experimental marks +Package: xmarks ....-..-.. L3 Experimental marks \g__marks_class_int=\count... \__marks_box=\box... \tracingmarks=\count... diff --git a/l3trial/xmarks/testfiles/xmarks-001.lvt b/l3trial/xmarks/testfiles/xmarks-001.lvt index 1d346bd484..65f1609e6d 100644 --- a/l3trial/xmarks/testfiles/xmarks-001.lvt +++ b/l3trial/xmarks/testfiles/xmarks-001.lvt @@ -8,7 +8,7 @@ \input{regression-test} -\usepackage{xmarks2} +\usepackage{xmarks} \tracingmarks=2 diff --git a/l3trial/xmarks/testfiles/xmarks-002.lvt b/l3trial/xmarks/testfiles/xmarks-002.lvt index 33d5aaba5d..55416812d7 100644 --- a/l3trial/xmarks/testfiles/xmarks-002.lvt +++ b/l3trial/xmarks/testfiles/xmarks-002.lvt @@ -8,7 +8,7 @@ \input{regression-test} -\usepackage{xmarks2} +\usepackage{xmarks} \tracingmarks=2 diff --git a/l3trial/xmarks/testfiles/xmarks-003.lvt b/l3trial/xmarks/testfiles/xmarks-003.lvt index e38d3c73b8..bec0ac720c 100644 --- a/l3trial/xmarks/testfiles/xmarks-003.lvt +++ b/l3trial/xmarks/testfiles/xmarks-003.lvt @@ -8,7 +8,7 @@ \input{regression-test} -\usepackage{xmarks2} +\usepackage{xmarks} \tracingmarks=2 diff --git a/l3trial/xmarks/testfiles/xmarks-004.lvt b/l3trial/xmarks/testfiles/xmarks-004.lvt index ec4ca9adaf..23ecc7b6bf 100644 --- a/l3trial/xmarks/testfiles/xmarks-004.lvt +++ b/l3trial/xmarks/testfiles/xmarks-004.lvt @@ -8,7 +8,7 @@ \input{regression-test} -\usepackage{xmarks2} +\usepackage{xmarks} \tracingmarks=2 diff --git a/l3trial/xmarks/testfiles/xmarks-005.lvt b/l3trial/xmarks/testfiles/xmarks-005.lvt index c0f9c84052..eaeee53935 100644 --- a/l3trial/xmarks/testfiles/xmarks-005.lvt +++ b/l3trial/xmarks/testfiles/xmarks-005.lvt @@ -8,7 +8,7 @@ \input{regression-test} -\usepackage{xmarks2} +\usepackage{xmarks} \tracingmarks=2 diff --git a/l3trial/xmarks/testfiles/xmarks-006.lvt b/l3trial/xmarks/testfiles/xmarks-006.lvt index 8e6bba923e..1bb7602e05 100644 --- a/l3trial/xmarks/testfiles/xmarks-006.lvt +++ b/l3trial/xmarks/testfiles/xmarks-006.lvt @@ -11,7 +11,7 @@ \input{regression-test} -%\usepackage{xmarks2} +%\usepackage{xmarks} %\tracingmarks=0 diff --git a/l3trial/xmarks/xmarks2-code.tex b/l3trial/xmarks/xmarks-code.tex similarity index 80% rename from l3trial/xmarks/xmarks2-code.tex rename to l3trial/xmarks/xmarks-code.tex index e497e261be..a5fb504bc4 100644 --- a/l3trial/xmarks/xmarks2-code.tex +++ b/l3trial/xmarks/xmarks-code.tex @@ -1,5 +1,5 @@ % this will typeset documentation + code \AtBeginDocument{\AlsoImplementation} -\input{xmarks2.dtx} +\input{xmarks.dtx} diff --git a/l3trial/xmarks/xmarks2-doc.tex b/l3trial/xmarks/xmarks-doc.tex similarity index 82% rename from l3trial/xmarks/xmarks2-doc.tex rename to l3trial/xmarks/xmarks-doc.tex index 45976cae5e..7258d93921 100644 --- a/l3trial/xmarks/xmarks2-doc.tex +++ b/l3trial/xmarks/xmarks-doc.tex @@ -1,4 +1,4 @@ % this will typeset only documentation but not the code \AtBeginDocument{\OnlyDescription} -\input{xmarks2.dtx} +\input{xmarks.dtx} diff --git a/l3trial/xmarks/xmarks.dtx b/l3trial/xmarks/xmarks.dtx index 0f37d675dc..4ad8c460b8 100644 --- a/l3trial/xmarks/xmarks.dtx +++ b/l3trial/xmarks/xmarks.dtx @@ -1,7 +1,6 @@ % \iffalse meta-comment % -%% File: xmarks.dtx Copyright (C) 1999,2001,2004-2009 Frank Mittelbach, The LaTeX3 Project -%% (C) 2010-2012,2014,2018 The LaTeX3 Project +%% File: xmarks.dtx Copyright (C) 2018-2020 Frank Mittelbach, The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -27,7 +26,7 @@ %<*driver> \documentclass[full]{l3doc} \begin{document} - \DocInput{\jobname.dtx} + \DocInput{xmarks.dtx} \end{document} % % \fi @@ -37,27 +36,77 @@ % } % % \author{^^A -% The \LaTeX3 Project\thanks +% Frank Mittelbach, \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } -% -% \date{Released 2018-08-24} + +% \date{Released --- not yet} % % \maketitle % -% \begin{documentation} +% \begin{abstract} +% Marks are used to communicate information about the content of a +% page to the output routine. For example, in order to construct +% running headers, the output routine needs information about which +% section names are present on a page, and this information is +% passed to it through the mark system. However, marks may also be +% used for other purposes. This module provides a generalised +% mechanism for marks of independent types. +% \end{abstract} % -% Marks are used to communicate information about the content of a page -% to the output routine. Perhaps the clearest form of mark is that needed -% for sections. In order to construct running headers, the output routine -% needs information about which section names are present on a page, and this -% information is passed by the mark system. However, marks may also be used -% for other purposes. This module provides a generalised mechanism for marks -% of independent types. +% \tableofcontents +% +% \begin{documentation} + +% \section{Introduction} +% +% The \TeX{} engines offer a low-level mark mechanism to +% communicate information about the content of the current page to +% the asynchronous operating output routine. It works by placing +% \cs{mark} commands into the source document. When the material +% for the current page is assembled in box 255, \TeX{} scans for +% such marks and sets the commands \cs{topmark}, \cs{firstmark} and +% \cs{botmark}. The \cs{firstmark} receives the content of the +% first \cs{mark} seen in box 255 and \cs{botmark} the content of +% the last mark seen. The \cs{topmark} holds the content of the +% last mark seen on the previous page or more exactly the value of +% \cs{botmark} from the previous page. If there are no marks on +% the current page then all three are made equal to \cs{botmark} of +% the previous page. +% +% This mechanism works well for simple formats (such as plain \TeX) +% whose output routines are only called to generate pages. It +% fails, however, in \LaTeX{} (and other more complex formats), +% because here the output routine is sometimes called without +% producing a page, e.g., when encountering a float and placing it +% into one of the float regions. In that case the output routine is +% called, determines where to place the float, alters the goal for +% assembling text material (if the float was added to the top or +% bottom region) and then it resumes collecting textual material. +% +% As a result the \cs{botmark} gets updated and so \cs{topmark} no +% longer reflects situation at the top of the next page when that +% page is finally boxed. +% +% Another problem for \LaTeX{} was that it wanted to use several +% \enquote{independent} marks and in the early implementations of +% \TeX{} there was only a single \cs{mark} command available. +% For that reason \LaTeX{} implemented its own mark +% mechansim where the marks always contained two parts with their +% own interfaces: \cs{markboth} and \cs{markright} to set marks and +% \cs{leftmark} and \cs{rightmark} to retrieve them. +% +% However, this extended mechanism (while supporting scenarios such +% as chapter/section marks) was far from general. The mark +% situation at the top of a page (i.e., \cs{topmark}) remained +% unusable and the two marks offered were not really independent of +% each other because \cs{markboth} (as the name indicates) was +% always setting both. + % % \section{Design-level interface} % @@ -79,17 +128,42 @@ % % \begin{function}[EXP]{\PreviousMark, \FirstMark, \LastMark} % \begin{syntax} -% \cs{PreviousMark} \Arg{type} -% \cs{FirstMark} \Arg{type} -% \cs{LastMark} \Arg{type} +% \cs{PreviousMark} \oarg{region} \Arg{type} +% \cs{FirstMark} \oarg{region} \Arg{type} +% \cs{LastMark} \oarg{region} \Arg{type} % \end{syntax} % These functions expand to the appropriate mark \meta{entry} for -% the given \meta{type} on the current page. The \enquote{first} and -% \enquote{last} marks are those seen first and last on the current page, -% respectively. The \enquote{previous} mark is the last mark of the -% \meta{type} seen on the previous page. +% the given \meta{type} in the specified \meta{region} by default +% \texttt{page}. The \enquote{first} and \enquote{last} marks are +% those seen first and last in the current region/page, respectively. The +% \enquote{previous} mark is the last mark of the \meta{type} seen +% in an earlier region, i.e.what would be \enquote{current} at the +% very top of the region. +% % \end{function} % +% ^^A footnotes not supported in function! +% +% Supported regions beside \texttt{page} are \texttt{verso} and +% \texttt{recto} if you are producing a \enquote{two-sided} +% document. If you are on a recto (odd) page you can then use the +% \texttt{verso} region to refer to the marks on the opposite +% page. Note, that right now this doesn't work in the opposite +% direction: you can't refer to the following recto page if you are +% on a verso page (you will see the marks only from already handled +% regions\footnote{This restriction might get lifted when this code +% is closer integrated with the \LaTeX{} kernel.}). +% The \texttt{page} region always refers to the current page, i.e., it is +% either the same as using \texttt{recto} or \texttt{verso} +% depending on where you are. If your document is one-sided then all +% three regions return the same data.\footnote{Or verso returns the +% empty string --- to be decided.} +% +% A similar concept exists for two column documents: \texttt{1col} +% and \texttt{2col} refers to the left and right column region +% respectively. +% +% % \section{Code-level interface} % % \begin{function}{\marks_new:n} @@ -100,59 +174,196 @@ % must be declared before it is used. % \end{function} % -% \begin{function}{\marks_put:nn, \marks_put:VV} +% \begin{function}{\marks_put:nn} % \begin{syntax} % \cs{marks_put:nn} \Arg{type} \Arg{entry} % \end{syntax} % Adds a mark to the current page for the \meta{type}, containing the -% \meta{entry} text. +% \meta{entry} text. The \meta{entry} is expanded at the time of use. % \end{function} % +% +% +% % \begin{function}[EXP] -% {\marks_get_previous:n, \marks_get_first:n, \marks_get_last:n} +% {\marks_use_previous:nn, \marks_use_first:nn, \marks_use_last:nn} % \begin{syntax} -% \cs{marks_get_previous:n} \Arg{type} -% \cs{FirstMark} \Arg{type} -% \cs{LastMark} \Arg{type} +% \cs{marks_use_previous:nn} \Arg{region} \Arg{type} +% \cs{marks_use_first:nn} \Arg{region} \Arg{type} +% \cs{marks_use_last:nn} \Arg{region} \Arg{type} % \end{syntax} % These functions expand to the appropriate mark \meta{entry} for -% the given \meta{type} on the current page. The \enquote{first} and -% \enquote{last} marks are those seen first and last on the current page, +% the given \meta{type} in the specified \meta{region}. The \enquote{first} and +% \enquote{last} marks are those seen first and last in the region, % respectively. The \enquote{previous} mark is the last mark of the -% \meta{type} seen on the previous page. +% \meta{type} seen on earlier regions. These functions should be used only in +% output routines after \cs{marks_update_structure:nnn} has acted, otherwise their +% values will be wrong. % \end{function} % +% +% \section{Legacy \LaTeXe{} interface} +% +% \subsection{Legacy design-level and document-level interfaces} +% +% \begin{function}{\markboth, \markright} +% \begin{syntax} +% \cs{markboth} \Arg{left} \Arg{right} +% \cs{markright} \Arg{right} +% \end{syntax} +% \LaTeXe{} uses two marks which aren't fully independent. A +% \enquote{left} mark generated by the first argument of \cs{markboth} +% and a \enquote{right} mark generated by the second argument of +% \cs{markboth} or by the only argument of \cs{markright}. The +% command \cs{markboth} and \cs{markright} are in turn called from +% heading commands such as \cs{chaptermark} or \cs{sectionmark} and +% their behavior is controlled by the document class. +% +% For example, in the \cls{article} class with \texttt{twoside} in +% force the \cs{sectionmark} will issue \cs{markboth} with an empty +% second argument and \cs{subsectionmark} will issue +% \cs{markright}. As a result the left mark will contain chapter +% titles and the right mark subsection titles. +% +% Note, however, that in one-sided documents the standard behavior is +% that only \cs{markright} is used, i.e., there will only be +% right-marks but no left marks! +% \end{function} +% +% \begin{function}[EXP]{\leftmark, \rightmark} +% \begin{syntax} +% \cs{leftmark} +% \cs{rightmark} +% \end{syntax} +% These functions return the appropriate mark value from the current page +% and work as before, that is \cs{leftmark} will get the first (!) +% left mark from the page and \cs{rightmark} the last (!) right +% mark. +% +% In other words they work well if you want to show the section +% title that is current when the page begins (and there is not +% further section on that page) or the first section that started on +% this page (if there is one) and also show the subsection title +% that is current when the page ends. Other combination can't be +% shown using this interface. +% \end{function} +% +% +% \subsection{Legacy interface extensions} +% +% The \pkg{xmarks} package adds three mark types \texttt{ltxleft}, +% \texttt{ltxright} and \texttt{ltxrightnonempty} and patches +% \cs{markboth} and \cs{markright} slightly so that they in addition +% to the above interface also update these mark types. +% +% The difference between \texttt{ltxright} and +% \texttt{ltxrightnonempty} is that the latter will only be updated +% if the material for the mark is not empty. +% +% As a result you can use \verb=\FirstMark{ltxleft}= and +% \verb=\LastMark{{ltxright}= instead of \cs{leftmark} and +% \cs{rightmark}. But more important you can use any of the other +% retrival commands to get a different status value from those +% marks, e.g., \verb=\FirstMark{ltxright}= would return the first +% subsection on the page (instead of the last) that would be +% returned by \cs{rightmark}. +% +% The difference between \texttt{ltxright} and +% \texttt{ltxrightnonempty} is that the latter will only be updated +% if the material for the mark is not empty. Thus +% \verb=\markboth{title}{}= as issued by, say \cs{sectionmark}, +% will set a \texttt{ltxleft} mark with \texttt{title} and a +% \texttt{ltxright} mark with the empty string but will not add a +% \texttt{ltxrightnonempty} mark. +% +% Thus, if you have a section at the start of a page and you would +% ask for \verb=\FirstMark{ltxright}= you would get an empty string +% even if there are subsections on that page. But +% \texttt{ltxrightnonempty} would then give you the first subsection +% on that page. Of course, nothing is simple. If there are no +% subsection it would tell you the last subsection from an earlier +% page. We therefore need comparison tools, e.g., if previous and +% first are identical you know that the value is +% bogus.\footnote{Those tools need still doing!} +% +% % \subsection{Output routine functions} % -% These functions are tied to the output routine: they are likely to change -% or disappear as integration into other ideas takes place. +% These functions are tied to the output routine and used in the +% interface to \LaTeXe{} and perhaps at some later time within an OR +% for \LaTeX3. Not meant for general use, so made internal here. +% Internal to this package means that \verb|@@| automatically gets +% replaced in the code (and in the documentation). +% \begin{macrocode} +%<@@=marks> +% \end{macrocode} % -% \begin{function}{\marks_update_structure:} +% \begin{function}{\@@_update_structure:nnn} % \begin{syntax} -% \cs{marks_update_structure:} +% \cs{@@_update_structure:nnN} \Arg{last} \Arg{current} \Arg{material with marks} % \end{syntax} +% \meta{last} is the region from which to take the last marks to +% make them new top marks. \meta{current} is the region to update +% and \meta{material} holds material that contain new marks. Thus if this +% material consists of boxes we need to do the unpacking with the +% argument so that the marks can be seen. % \end{function} % -% \begin{function}{\marks_save_state:} +% +% +% \begin{function}{\@@_update_structure_alias:nn} % \begin{syntax} -% \cs{marks_save_state:} +% \cs{@@_update_structure_alias:nn} \Arg{alias} \Arg{source} % \end{syntax} +% Assigns all marks for the \meta{source} region also to +% \meta{alias}, e.g., if we finished a \texttt{verso} page we +% could make the generic \texttt{page} region hold the same +% marks. In most cases this is automatically done already by +% \cs{@@_update_structure:nnN} so this is only needed in a few +% cases. % \end{function} % -% \begin{function}{\marks_OR_restore_state:nn} +% +% \begin{function}{\@@_update_singlecol_structure:n} % \begin{syntax} -% \cs{marks_OR_restore_state:nn} \Arg{OR_1} \Arg{OR_2} +% \cs{@@_update_singlecol_structure:n} \Arg{material with marks} % \end{syntax} +% \LaTeXe{} integration function receiving the content of the output box +% (box~$255$, though may vary in \LuaTeX{}) for +% mark processing when we are doing single column documents. % \end{function} % +% +% \begin{function}{\@@_update_dblcol_structure:nn} +% \begin{syntax} +% \cs{@@_update_singlecol_structure:n} \Arg{current column material} +% \Arg{whole page material} +% \end{syntax} +% \LaTeXe{} integration function mark processing when we are doing +% double column documents. The first argument handles the column marks +% and the second the marks for the complete page and is only +% relevant if we are doing the second column. +% \end{function} +% +% +% % \end{documentation} % +% +% +% +% +% +% % \begin{implementation} % % \section{\pkg{xmarks} Implementation} % % \subsection{Notes on the mechanism} % +% \textbf{This is just a leftover docu from the original version an no +% longer correct at all} +% % \eTeX{} extends the \TeX{} mark system to allow multiple independent % marks. However, it does not solve a problem which means that \LaTeX{} needs % to manage marks almost independently of \TeX{}. The reason for this is that @@ -160,538 +371,411 @@ % structures) means that \tn{topmark(s)} are not reliable. Each time the % output routine is fired up, \TeX{} moves \tn{botmark} to \tn{topmark}, and % while \eTeX{} extends this the fundamental concept remains the same. That -% means that instead the state of marks needs to be tracked by \LaTeX{}, -% using \TeX{}'s \tn{botmark} only to ensure the correct interaction with -% the output routine. There is no gain in using the \eTeX{} mechanism here, -% and so \LaTeX3 ignores this extension. -% +% means that instead the state of marks needs to be tracked by +% \LaTeX{} itself. An early implementation of this package used +% \TeX{}'s \tn{botmark} only to ensure the correct interaction with +% the output routine (this was before the \eTeX{} mechanism was even +% available). However, other than in a prototype implementation for +% \LaTeX3 this package was never made public. +% +% The new implementation now does use \eTeX{}'s marks as they have +% some advantages as with them we can leave the mark text within the +% galley and only extract the marks during the output routine when +% we are finally shipping out a page or storing away a column for +% use in the next page. That means we do not have to maintain a +% global data structure that we have to keep in sync with +% informational marks in the galley but can rely on everything being +% in one place and thus manipulations (e.g.~reordering of material) +% will take the marks with them without a need for updating a +% fragile linkage. + % To allow for completely independent marks we use the following % procedure: % \begin{itemize} % \item -% For every mark of type \meta{type} we have a queue that holds every mark -% info found in memory. Every info is associated with a unique number, -% i.e., we simply count them. The queue always holds at least one item -% which is the previous mark info, i.e., the last mark for that type on -% the previous page. -% -% \item -% We use \TeX{}'s internal mark mechanism only to record the associated -% numbers for marks for every type on the current page. -% -% \item -% For every \meta{type} we record the info-number that belongs to the last -% mark of the previous page. -% -% \item -% By looking at \TeX{}'s internal \tn{botmark} we can determine the -% info-number of the last mark for every \meta{type} that is on the current -% page. +% For every mark of type \meta{type} we allocate a mark class so +% that in the output routine \TeX{} can calculate for each type top, +% first and bottom mark independently. +% +% \item As already mentioned firing up an output routine without +% shipping out a page means that \TeX's top marks get wrong so it is +% impossible to rely on \TeX's approach directly. What we do instead +% is to keep track of the real marks (from last page or +% more generally last region) in some global variables. +% +% \item These variables are updated in the output routine at defined +% places, i.e., when we do real output processing but not if we use +% special output routines to do internal housekeeping. +% +% \item The trick we use to get correctly updated variables is the +% following: the material that contains new marks (for example the +% page to be shipped out) is stored in a box. We then use \TeX{} +% primitive box splitting functions by splitting off the largest +% amount possible (which should be the whole box if nothing goes +% really wrong). While that seems a rather pointless thing to do, it +% has one important side effect: \TeX{} sets up first and bottom +% marks for each mark class from the material it has split off. This +% way we get the first and last marks (if there have been any) from +% the material in the box. +% +% \item The top marks are simply the last marks from the previous +% page or region. And if there hasn't been a first or bottom mark in +% the box then the new top mark also becomes new first and last mark +% for that class. +% \end{itemize} +% That's about it in a nutshell. Of course, there are some details to +% be taken care off and those are discussed further below. % -% \item -% The difference between this number and the info-number from the last -% page gives us the number of marks for every \meta{type} on the current -% page. % -% \item -% That way we are able to decide how to extract items from the queue so -% that first, last, and previous mark for every type can be accessed. -% \begin{itemize} -% \item -% If the difference is zero, no new marks have been added on the -% current page, therefore the only item on the corresponding mark type -% queue holds the info that should be previous, first, and last mark of -% this type for the current page. -% -% \item -% If the difference is one, then the first item in the queue represents -% the info that should become the previous mark (it will be popped off) -% and the second item (which will be kept, since it will become the -% previous mark for the next page) should become first and last mark -% for the current page. -% -% \item -% Otherwise we had at least two marks for this type on the current -% page. Therefore, the first item in the queue will become previous -% mark (popped off), the second will become first mark (popped off), -% then we pop off all but the last item in the queue, which will -% become last mark, by only looking at it. -% \end{itemize} -% In other words every queue should hold only one item after this part of -% the algorithm has acted. -% After this is done we save the info-numbers given by \tn{botmark} -% as the info-numbers of the last page, so that they are available next -% time. -% -% \item -% Putting a mark into the galley therefore means to put its info to the -% right of the corresponding queue, increment the current info-number for -% \meta{type} by one and putting a \TeX{} mark into the galley holding the -% current info-numbers for all \meta{types}. -% \end{itemize} % % \subsection{Lead-off code} % % \begin{macrocode} -%<*initex|package> +%<*package> % \end{macrocode} % -% \begin{macrocode} -%<@@=marks> -% \end{macrocode} % % \begin{macrocode} %<*package> -\ProvidesExplPackage{xmarks}{2018-08-24}{} +\ProvidesExplPackage{xmarks}{2020-02-06}{} {L3 Experimental marks} % % \end{macrocode} % -% \begin{variable}{\l_@@_tmp_int} -% \begin{variable}{\l_@@_tmp_prop} -% \begin{variable}{\l_@@_tmp_tl} -% Scratch space. +% +% \begin{variable}{\g_@@_types_seq} +% A list of all of the mark types in use. % \begin{macrocode} -\int_new:N \l_@@_tmp_int -\prop_new:N \l_@@_tmp_prop -\tl_new:N \l_@@_tmp_tl +\seq_new:N \g_@@_types_seq % \end{macrocode} % \end{variable} -% \end{variable} -% \end{variable} % -% \subsection{Creating mark types} % -% \begin{variable}{\g_@@_current_prop, \g_@@_last_prop} -% The two property lists used to hold the mark information. +% \begin{macro}{\g_@@_class_int} +% We assume that nobody is using extended marks!!! The alternative +% is to use \cs{newmarks} from \LaTeXe{} or provide an interface in +% expl3. One or the other should be dne! % \begin{macrocode} -\prop_new:N \g_@@_current_prop -\prop_new:N \g_@@_last_prop +\int_new:N \g_@@_class_int % \end{macrocode} -% \end{variable} +% \end{macro} % -% \begin{variable}{\g_@@_types_seq} -% A list of all of the mark types in use. -% \begin{macrocode} -\seq_new:N \g_@@_types_seq -% \end{macrocode} -% \end{variable} % +% % \begin{macro}{\marks_new:n} % \begin{macro}{\@@_new:n} -% A mark type is created by initialising a number of data structures. -% First, the mark information itself (a token list variable) is set up -% with empty entries: this allows for the case where information retrieval -% is attempted before \cs{marks_update_structure:} has been used. A sequence -% is then set up, which will hold each mark entry for the type being created. -% A copy of this sequence is also created so that the save code will not -% attempt to use a non-existent variable. +% A mark type is created by initialising a number of data +% structures. First, we get a number to refer to the mark class. +% The new mark type is then added to a sequence to be able to +% easily loop over all types. finally a number of top-level global +% token lists are generated that hold various versions of the mark +% for access. % \begin{macrocode} \cs_new_protected:Npn \marks_new:n #1 - { - \seq_if_in:NnTF \g_@@_types_seq {#1} +{ + \seq_if_in:NnTF \g_@@_types_seq {#1} { \__kernel_msg_error:nnn { marks } { type-already-defined } {#1} } { \@@_new:n {#1} } - } +} +% \end{macrocode} +% +% \begin{macrocode} \cs_new_protected:Npn \@@_new:n #1 - { +{ %<*trace> - \trace_marks:n { new~mark:~ #1 } + \@@_trace:n { new~mark:~ #1 } % - \seq_gput_right:Nn \g_@@_types_seq {#1} - \tl_new:c { g_@@_ #1 _tl } - \tl_gset:cn { g_@@_ #1 _tl } { { } { } { } } - \seq_new:c { g_@@_ #1 _seq } - \seq_new:c { g_@@_saved_ #1 _seq } -% \end{macrocode} -% An entry for the type is now added to each of the two property lists -% which track mark data. The set up must have the current mark set one -% less than the last mark, for the mechanism to work correctly. -% \begin{macrocode} - \prop_gput:Nnn \g_@@_last_prop {#1} { 1 } - \prop_gput:Nnn\g_@@_current_prop {#1} { 0 } -% \end{macrocode} -% We now put the very first mark of this type in. This mark will be -% empty. This will initialize the queue (now holding the empty previous -% mark) increment the current info number, so that last and current are -% now equal and also puts a \TeX{} mark into the galley with the -% additional type present. -% \begin{macrocode} - \marks_put:nn {#1} { } - } + \int_gincr:N \g_@@_class_int + \int_const:cn {c_@@_class_ #1 _int}{ \g_@@_class_int } + \seq_gput_right:Nn \g_@@_types_seq {#1} + \tl_new:c { g_@@_page_top_ #1 _tl } + \tl_new:c { g_@@_page_first_ #1 _tl } + \tl_new:c { g_@@_page_last_ #1 _tl } + \tl_new:c { g_@@_verso_top_ #1 _tl } + \tl_new:c { g_@@_verso_first_ #1 _tl } + \tl_new:c { g_@@_verso_last_ #1 _tl } + \tl_new:c { g_@@_recto_top_ #1 _tl } + \tl_new:c { g_@@_recto_first_ #1 _tl } + \tl_new:c { g_@@_recto_last_ #1 _tl } % \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{Adding and recovering mark information} -% -% \begin{macro}{\@@_store:N} -% \begin{macro}[EXP]{\@@_store_aux:nn} -% \begin{macro}{\@@_read:N} -% \begin{macro}{\@@_read_aux:nN} -% \begin{macro}{\@@_read_aux:Nnnn} -% The aim here is to provide a method for placing the property list -% information into the \TeX{} mark system and to recover it. This should not -% rely on the implementation of property lists (which has changed over the -% years), and so is set up to convert into a format which is both readable -% and reasonably efficient for the job in hand. The idea is to set up the -% mark such that when reading back loop termination can be achieved by -% a correctly-placed \cs{use_none:nn} rather than a slower test for an end -% marker. This does assume that there is at least one piece of information -% in the mark list. -% \begin{macrocode} -\cs_new_protected:Npn \@@_store:N #1 - { \tex_mark:D { \prop_map_function:NN #1 \@@_store_aux:nn } } -\cs_new:Npn \@@_store_aux:nn #1#2 { \exp_not:n { { } {#1} {#2} } } -\cs_new_protected:Npn \@@_read:N - { \exp_after:wN \@@_read_aux:nN \exp_after:wN { \tex_botmark:D } } -\cs_new_protected:Npn \@@_read_aux:nN #1#2 - { - \prop_gclear:N #2 - \exp_after:wN \@@_read_aux:Nnnn - \exp_after:wN #2 \use_none:n #1 \use_none:nn - } -\cs_new_protected:Npn \@@_read_aux:Nnnn #1#2#3#4 - { - \prop_gput:Nnn #1 {#2} {#3} - #4 \@@_read_aux:Nnnn #1 - } +% ``col'' is really useless and should get dropped or rethought +% \begin{macrocode} + \tl_new:c { g_@@_col_top_ #1 _tl } + \tl_new:c { g_@@_col_first_ #1 _tl } + \tl_new:c { g_@@_col_last_ #1 _tl } +% \end{macrocode} +% +% \begin{macrocode} + \tl_new:c { g_@@_1col_top_ #1 _tl } + \tl_new:c { g_@@_1col_first_ #1 _tl } + \tl_new:c { g_@@_1col_last_ #1 _tl } + \tl_new:c { g_@@_2col_top_ #1 _tl } + \tl_new:c { g_@@_2col_first_ #1 _tl } + \tl_new:c { g_@@_2col_last_ #1 _tl } +} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\marks_put:nn, \marks_put:VV} -% To put a mark into the current horizontal or vertical \TeX{} list -% we first update \cs{g_@@_current_prop} and then put the reference number -% onto the main vertical list. The reference number is simply stepped by one -% to do this. The mark information itself is also added to the appropriate -% sequence. +% +% +% +% % \begin{macrocode} -\cs_new_protected:Npn \marks_put:nn #1#2 - { -%<*trace> - \trace_marks:n { set~#1~<-~ \tl_to_str:n {#2} } -% - \prop_get:NnNF \g_@@_current_prop {#1} \l_@@_tmp_tl - { - \__kernel_msg_error:nnx { marks } { unknown-type } - { \tl_to_str:n {#1} } - } - \prop_gput:Nnx \g_@@_current_prop {#1} - { \int_eval:n { \l_@@_tmp_tl + 1 } } -%<*trace> - \trace_marks_internal:n - { Setting~mark~ \@@_trace_store:N \g_@@_current_prop } -% - \@@_store:N \g_@@_current_prop - \seq_gput_right:cn { g_@@_ #1 _seq } {#2} - } -\cs_generate_variant:Nn \marks_put:nn { VV } + + \box_new:N \@@_box + + \tl_new:N \g_@@_tmp_tl + \tl_new:N \g_@@_new_top_tl + % \end{macrocode} -% \end{macro} -% -% \begin{macro}{\marks_update_structure:} -% \begin{macro} -% { -% \@@_update_structure_aux:nn , -% \@@_update_structure_no_change:nn, -% \@@_update_structure_one_mark:nn , -% \@@_update_structure_marks:nn -% } -% This function is for use in output routines to initialize the marks -% at the beginning. It is only useful after \TeX{} internally has -% updated \tn{botmark}. We map a function over all keys in -% \cs{g_@@_last_prop}, in other words over all types of marks. This -% routine will set the marks for all types. Finally we set -% \cs{g_@@_last_prop} to the data that was stored in \tn{botmark}, -% \emph{i.e.}, to the info-numbers from this page. -% \begin{macrocode} -\cs_new_protected:Npn \marks_update_structure: - { - \prop_map_function:NN \g_@@_last_prop \@@_update_structure_aux:nn - \@@_read:N \g_@@_last_prop - } +% + +% \begin{macro}{\@@_update_structure:nnn} + +% This function updates the mark structure. The first argument is +% the region from which we pick up the last mark to make it the new +% top mark. The second argument is the region for which we produce +% mark value and the third argument is the material that holds the +% marks. Out of this material we extract the first and last mark +% (if there are any) to do the assignments. +% +% The second argument is always a specific region, e.g., +% \texttt{verso} while the first is always the generic name, e.g., +% \texttt{page}. Since when updating a specific region the +% corresponding generic one will receive the same values, this +% allows us to do both assignments at the same time (without the +% need for \cs{@@_update_structure_alias:nn}) which save a bit of +% processing time as we don't have to construct csnames unnecessarily. +% \begin{macrocode} +\cs_new:Npn \@@_update_structure:nnn #1#2#3 +{ + \group_begin: % \end{macrocode} -% The loop over mark types does a comparison between the reference number -% in the \TeX{} mark structure and the one in the stored property list. -% There are then three cases: the two numbers are the same, the numbers -% differ by exactly one and the numbers differ by more than one. +% Getting the first and last marks out of the material in \verb=#3= +% is done by putting the material in a box and then doing a +% split operation to the maximum size possible (which hopefully +% means all of the content.\footnote{We could verify this, maybe we +% should.} As this is a temporary thing we don't want any underfull +% box warnings so we turn those off. % \begin{macrocode} -\cs_new_protected:Npn \@@_update_structure_aux:nn #1#2 - { -%<*trace> - \cs_set:Npn \trace_seq:n ##1 - { " \tl_to_str:n {##1} ",~ } - \trace_marks_internal:n - { - queue~for~#1~before:~ - \seq_map_function:cN { g_@@_ #1 _seq } \trace_seq:n - } -% - \@@_read:N \l_@@_tmp_prop -%<*trace> - \trace_marks_internal:n - { picking~up~from~output~ \@@_trace_store:N \l_@@_tmp_prop } -% - \prop_get:NnNF \l_@@_tmp_prop {#1} \l_@@_tmp_tl - { - \__kernel_msg_error:nnx { marks } { unknown-type } - { \tl_to_str:n {#1} } - \tl_set:Nn \l_@@_tmp_tl {#2} - } -%<*trace> - \trace_marks_internal:n - { - found~ \int_eval:n { \l_@@_tmp_tl - ( #2 ) } ~entries~for~#1~ - (new~ \l_@@_tmp_tl ;~old~#2) - } -% + \dim_set:Nn \tex_splitmaxdepth:D \c_max_dim + \int_set:Nn \tex_vbadness:D \c_max_int + \vbox_set:Nn \@@_box {#3} + \vbox_set_split_to_ht:NNn \@@_box \@@_box \c_max_dim % \end{macrocode} -% The three cases: $0$, $1$ and $>1$. This is done using the low-level -% \cs{if_case:w} rather than \cs{int_case:nnF} as the primitive approach -% is faster and for this short fixed number of cases that is worth the -% slightly more complex code. -% \begin{macrocode} - \if_case:w \int_eval:n { \l_@@_tmp_tl - ( #2 ) } \scan_stop: - \exp_after:wN \@@_update_structure_no_change:nn - \or: - \exp_after:wN \@@_update_structure_one_mark:nn - \else: - \exp_after:wN \@@_update_structure_marks:nn - \fi: - {#1} {#2} -%<*trace> - \trace_marks:n { in~output:~#1~->~ \tl_to_str:c { g_@@_ #1 _tl } } - \cs_set:Npn \trace_seq:n ##1 - { " \tl_to_str:n {##1} ",~ } - \trace_marks_internal:n +% After this action we can get first and last marks of the various +% types through \cs{tex_splitfirstmarks:D} and +% \cs{tex_splitbotmarks:D}. So now we loop over all types stored in +% \cs{g_@@_types_seq}. +% \begin{macrocode} + \seq_map_inline:Nn \g_@@_types_seq { - queue~for~#1~after:~ - \seq_map_function:cN { g_@@_ #1 _seq } \trace_seq:n +% \end{macrocode} +% First action: get the last mark from the previous region. As we +% need this value in various assignments we store it away which +% avoids uncessary csname generations. +% \begin{macrocode} + \tl_gset_eq:Nc \g_@@_new_top_tl { g_@@_ #1 _last_ ##1 _tl } +% \end{macrocode} +% This will first of all become the new top mark. +% \begin{macrocode} + \tl_gset_eq:cN { g_@@_ #1 _top_ ##1 _tl } \g_@@_new_top_tl + \tl_gset_eq:cN { g_@@_ #2 _top_ ##1 _tl } \g_@@_new_top_tl +% \end{macrocode} +% Next action is to get ourselves the new last mark from the +% material supplied. +% \begin{macrocode} + \tl_gset:No \g_@@_tmp_tl + { \tex_splitbotmarks:D \use:c{c_@@_class_ ##1 _int} } +% \end{macrocode} +% If this mark doesn't exist then obviously first mark neither, so both +% become the last mark from previous region. We have to be a little +% careful here: something like \verb=\marks_put{foo}{}= adds an +% \enquote{empty} mark that should not be confused with no mark at +% all. But no mark in our material will result in \cs{g_@@_tmp_tl} +% being empty. This is why we have to make sure that the empty from +% \cs{marks_put:nn} only appears to be empty but fails the next test: +% \begin{macrocode} + \tl_if_empty:NTF \g_@@_tmp_tl + { + \tl_gset_eq:cN { g_@@_ #1 _last_ ##1 _tl } \g_@@_new_top_tl + \tl_gset_eq:cN { g_@@_ #2 _last_ ##1 _tl } \g_@@_new_top_tl + \tl_gset_eq:cN { g_@@_ #1 _first_ ##1 _tl } \g_@@_new_top_tl + \tl_gset_eq:cN { g_@@_ #2 _first_ ##1 _tl } \g_@@_new_top_tl + } +% \end{macrocode} +% If it wasn't empty, ie had a real value then we use this value +% for our new last mark. +% \begin{macrocode} + { + \tl_gset_eq:cN { g_@@_ #1 _last_ ##1 _tl } \g_@@_tmp_tl + \tl_gset_eq:cN { g_@@_ #2 _last_ ##1 _tl } \g_@@_tmp_tl +% \end{macrocode} +% Since we had a bottom mark we will also have a first mark (which +% might be the same, but might be not), so we pick that up and +% assign it to the appropriate token lists. +% \begin{macrocode} + \tl_gset:No \g_@@_tmp_tl + { \splitfirstmarks \use:c{c_@@_class_ ##1 _int} } + \tl_gset_eq:cN { g_@@_ #1 _first_ ##1 _tl } \g_@@_tmp_tl + \tl_gset_eq:cN { g_@@_ #2 _first_ ##1 _tl } \g_@@_tmp_tl + } } -% - } + \group_end: +} % \end{macrocode} -% No change to the marks: recover the top one and reuse it for all three -% entries. +% \end{macro} +% +% + +% \begin{macro}{\@@_update_structure_alias:nn} +% % \begin{macrocode} -\cs_new_protected:Npn \@@_update_structure_no_change:nn #1#2 - { - \seq_get_left:cN { g_@@_ #1 _seq } \l_@@_tmp_tl - \tl_gset:cx { g_@@_ #1 _tl } +\cs_new:Npn \@@_update_structure_alias:nn #1#2 +{ + \seq_map_inline:Nn \g_@@_types_seq { - { \exp_not:o \l_@@_tmp_tl } - { \exp_not:o \l_@@_tmp_tl } - { \exp_not:o \l_@@_tmp_tl } + \tl_gset_eq:cc { g_@@_ #1 _top_ ##1 _tl } + { g_@@_ #2 _top_ ##1 _tl } + \tl_gset_eq:cc { g_@@_ #1 _first_ ##1 _tl } + { g_@@_ #2 _first_ ##1 _tl } + \tl_gset_eq:cc { g_@@_ #1 _last_ ##1 _tl } + { g_@@_ #2 _last_ ##1 _tl } } - } +} % \end{macrocode} -% A difference of exactly one means that the last mark we had is now the -% one on the previous page, while the two on this page are the same. +% \end{macro} +% +% +% \begin{macro}{\marks_put:nn} +% % \begin{macrocode} -\cs_new_protected:Npn \@@_update_structure_one_mark:nn #1#2 - { - \seq_gpop:cN { g_@@_ #1 _seq } \l_@@_tmp_tl - \tl_gset:cx { g_@@_ #1 _tl } { { \exp_not:o \l_@@_tmp_tl } } - \seq_get_left:cN { g_@@_ #1 _seq } \l_@@_tmp_tl - \tl_gput_right:cx { g_@@_ #1 _tl } +\cs_new_protected:Npn \marks_put:nn #1#2 +{ + \seq_if_in:NnTF \g_@@_types_seq {#1} { - { \exp_not:o \l_@@_tmp_tl } - { \exp_not:o \l_@@_tmp_tl } - } - } % \end{macrocode} -% The most complex case is where two or more new marks have been seen. -% First, the previous mark is popped off the sequence. The left-most entry -% is then the first mark on the page, while finding the last mark requires -% a loop to remove the intermediate values (which are thrown away). +% We need to pass the evaluated string into the mark (and we don't +% have \cs{expanded} yet) so we use the \cs{protect} approach of +% \LaTeXe{} here including disabling \cs{label} and the +% like.\footnote{Straight copy from \texttt{latex.ltx} but is this +% even correct? At least a label in a running header makes little +% sense if it get set several times! Maybe that needs looking at in +% the 2e kernel.} % \begin{macrocode} -\cs_new_protected:Npn \@@_update_structure_marks:nn #1#2 - { - \int_set:Nn \l_@@_tmp_int { \l_@@_tmp_tl - ( #2 ) } - \seq_gpop:cN { g_@@_ #1 _seq } \l_@@_tmp_tl - \tl_gset:cx { g_@@_ #1 _tl } { { \exp_not:o \l_@@_tmp_tl } } - \seq_get_left:cN { g_@@_ #1 _seq } \l_@@_tmp_tl - \tl_gput_right:cx { g_@@_ #1 _tl } { { \exp_not:o \l_@@_tmp_tl } } - \int_while_do:nNnn \l_@@_tmp_int > 1 + \group_begin: + \cs_set_eq:NN \label \scan_stop: + \cs_set_eq:NN \index \scan_stop: + \cs_set_eq:NN \glossary \scan_stop: + \unrestored@protected@xdef \g_@@_tmp_tl {#2} +%<*trace> + \@@_trace:n { set~#1~<-~ '\tl_to_str:V \g_@@_tmp_tl' } +% + \tex_marks:D \use:c{c_@@_class_ #1 _int} + { + \exp_not:n{ \prg_do_nothing: } + \g_@@_tmp_tl + } + \group_end: + } { - \int_decr:N \l_@@_tmp_int - \seq_gpop:cN { g_@@_ #1 _seq } \l_@@_tmp_tl + \__kernel_msg_error:nnx { marks } { unknown-type } + { \tl_to_str:n {#1} } } - \seq_get_left:cN { g_@@_ #1 _seq } \l_@@_tmp_tl - \tl_gput_right:cx { g_@@_ #1 _tl } { { \exp_not:o \l_@@_tmp_tl } } - } +} % \end{macrocode} -% \end{macro} -% \end{macro} +% \end{macro} % +% +% % \begin{macro}[EXP] -% {\marks_get_first:n, \marks_get_last:n, \marks_get_previous:n} -% To retrieve the first, last or previous page mark, we grab the appropriate -% value stored in the tl var. The marks are stored in the tl var.~in the -% order previous, first, last mark. These functions should be used only in -% output routines after \cs{marks_retrieve:} has acted, otherwise their +% {\marks_get_first:nn, \marks_get_last:nn, \marks_get_previous:nn} +% To retrieve the first, last or previous region mark, we grab the appropriate +% value stored in some tl var. These functions should be used only in +% output routines after \cs{@@_update_structure:nnn} has acted, otherwise their % value will be wrong. % \begin{macrocode} -\cs_new:Npn \marks_get_first:n #1 - { - \exp_after:wN \exp_after:wN \exp_after:wN - \use_ii:nnn \cs:w g_@@_ #1 _tl \cs_end: - } -\cs_new:Npn \marks_get_last:n #1 - { - \exp_after:wN \exp_after:wN \exp_after:wN - \use_iii:nnn \cs:w g_@@_ #1 _tl \cs_end: - } -\cs_new:Npn \marks_get_previous:n #1 - { - \exp_after:wN \exp_after:wN \exp_after:wN - \use_i:nnn \cs:w g_@@_ #1 _tl \cs_end: - } +\cs_new:Npn \marks_use_first:nn #1#2 + { \use:c { g_@@_ #1 _first_ #2 _tl } } +\cs_new:Npn \marks_use_last:nn #1#2 + { \use:c { g_@@_ #1 _last_ #2 _tl } } +\cs_new:Npn \marks_use_previous:nn #1#2 + { \use:c { g_@@_ #1 _top_ #2 _tl } } % \end{macrocode} % \end{macro} % -% \subsection{Saving and restoring marks} % -% \begin{variable}{\g_@@_saved_current_prop, \g_@@_saved_last_prop} -% Storage for the saved versions of the two property lists: notice that -% there is only a single save level available. +% +% \begin{macro}{\marks_status:n} +% \begin{macro}{\marks_status:nn} +% Some simple tracing, should be changed \ldots % \begin{macrocode} -\prop_new:N \g_@@_saved_current_prop -\prop_new:N \g_@@_saved_last_prop +\cs_new:Npn \marks_status:n #1 + { + \seq_map_inline:Nn \g_@@_types_seq { \marks_status:nn {#1} {##1} } + } % \end{macrocode} -% \end{variable} -% -% \begin{macro}{\marks_save_state:} -% Saving the state of the marks is easy, as it only involves copying -% data structures that \LaTeX{} controls directly. The two permanent -% structures are easy, and the various mark types are handled with a -% simple loop, done inline for speed. +% % \begin{macrocode} -\cs_new_protected:Npn \marks_save_state: - { -%<*trace> - \trace_marks:n { saving~state } -% - \prop_gset_eq:NN \g_@@_saved_current_prop \g_@@_current_prop - \prop_gset_eq:NN \g_@@_saved_last_prop \g_@@_last_prop - \seq_map_inline:Nn \g_@@_types_seq - { \seq_gset_eq:cc { g_@@_saved_ ##1 _seq } { g_@@_ ##1 _seq } } - } +\cs_new:Npn \marks_status:nn #1#2 + { + \int_compare:nNnT \tracingmarks > 1 + { + \typeout{#1~ #2:} + \typeout{\@spaces page~ (current): + | \tl_use:c { g_@@_page_top_ #2 _tl } + | \tl_use:c { g_@@_page_first_ #2 _tl } + | \tl_use:c { g_@@_page_last_ #2 _tl } |} + \typeout{\@spaces page~ (verso): + | \tl_use:c { g_@@_verso_top_ #2 _tl } + | \tl_use:c { g_@@_verso_first_ #2 _tl } + | \tl_use:c { g_@@_verso_last_ #2 _tl } |} + \typeout{\@spaces page~ (recto): + | \tl_use:c { g_@@_recto_top_ #2 _tl } + | \tl_use:c { g_@@_recto_first_ #2 _tl } + | \tl_use:c { g_@@_recto_last_ #2 _tl } |} + % + \typeout{\@spaces column~ (current): + | \tl_use:c { g_@@_col_top_ #2 _tl } + | \tl_use:c { g_@@_col_first_ #2 _tl } + | \tl_use:c { g_@@_col_last_ #2 _tl } |} + \typeout{\@spaces column~ (first): + | \tl_use:c { g_@@_1col_top_ #2 _tl } + | \tl_use:c { g_@@_1col_first_ #2 _tl } + | \tl_use:c { g_@@_1col_last_ #2 _tl } |} + \typeout{\@spaces column~ (second): + | \tl_use:c { g_@@_2col_top_ #2 _tl } + | \tl_use:c { g_@@_2col_first_ #2 _tl } + | \tl_use:c { g_@@_2col_last_ #2 _tl } |} + } +} % \end{macrocode} -% \end{macro} +% \end{macro} +% \end{macro} +% +% +% % -% \begin{macro}{\@@_restore_state:} -% The reverse of \cs{marks_save_state:} is marked for internal use only -% as this can only be used correctly as part of a broader restore chain -% involving the output routine. % \begin{macrocode} -\cs_new_protected:Npn \@@_restore_state: - { -%<*trace> - \trace_marks:n { restoring~state } -% - \prop_gset_eq:NN \g_@@_current_prop \g_@@_saved_current_prop - \prop_gset_eq:NN \g_@@_last_prop \g_@@_saved_last_prop - \seq_map_inline:Nn \g_@@_types_seq - { \seq_gset_eq:cc { g_@@_ ##1 _seq } { g_@@_saved_ ##1 _seq } } - } % \end{macrocode} -% \end{macro} % -% \begin{variable}{\c_@@_penaltyi_int, \c_@@_penaltyii_int} -% Two marker penalties for detected that the restore system is used -% correctly. +% +% +% +% % \begin{macrocode} -\int_const:Nn \c_@@_penaltyi_int { -20203 } -\int_const:Nn \c_@@_penaltyii_int { -20204 } % \end{macrocode} -% \end{variable} % -% \begin{variable}{\c_@@_output_int} -% The output box. +% +% +% % \begin{macrocode} -\int_const:Nn \c_@@_output_int { 255 } % \end{macrocode} -% \end{variable} % -% \begin{macro}{\marks_OR_restore_state:nn} -% Restoring the mark state is more complex than saving it as we need to -% interact with the output routine to get \tn{botmark} to be correct. To -% do that, a two-state system is used, with two customised output routines. -% Why? Because the first one could reinsert material that has been previously -% picked up from the MVL and the second call could do then some processing -% including adding additional material such as insertions. With only a single -% pass that would result in the material appearing in the wrong order on the -% MVL (as the insertions would have to come \emph{before} material for -% reprocessing). By ending an output routine and immediately starting a -% second one the material from the first routine is pushed to -% \enquote{recent contributions}. -% \begin{macrocode} -\cs_new_protected:Npn \marks_OR_restore_state:nn #1#2 - { -%<*trace> - \trace_push:n { marks_OR_restore_state:nn } -% -% \end{macrocode} -% We first restore the external data structures by calling -% \cs{@@_restore_state:}. Then we have to ensure that \TeX{}'s -% idea of what the current \tn{botmark} is, corresponds to what it -% was when we saved the state. Back then it was the contents of -% \cs{g_@@_last_prop} so we are now adding an empty box and then -% mark with is contents -% onto the MVL followed by a penalty that ensures we trigger the -% output routine and then specify a tiny little output routine -% whose sole purpose is to get that mark processed. -% \begin{macrocode} - \@@_restore_state: - \hbox:n { } -%<*trace> - \trace_marks_internal:n - { restoring~botmark~ \@@_trace_store:N \g_@@_last_prop } -% - \@@_store:N \g_@@_last_prop - \tex_penalty:D \c_@@_penaltyi_int - \tex_global:D \tex_output:D - { -%<*trace> - \trace_push:n { marks_restore_state~(inline~code~arg1) } -% - \int_compare:nNnF \c_@@_penaltyi_int = \tex_outputpenalty:D - { \__kernel_msg_error:nn { marks } { bad-restore } } - \box_gclear:N \c_@@_output_int - \hbox:n { } - \tex_penalty:D \c_@@_penaltyii_int - #1 - \tex_global:D \tex_output:D - { -%<*trace> - \trace_push:n { marks_restore_state~(inline~code~arg2) } -% - \int_compare:nNnF \c_@@_penaltyii_int = \tex_outputpenalty:D - { \__kernel_msg_error:nn { marks } { bad-restore } } - \box_gclear:N \c_@@_output_int - #2 -%<*trace> - \trace_pop:n { marks_restore_state~(inline~code~arg2) } -% - } -%<*trace> - \trace_pop:n { marks_restore_state~(inline~code~arg1) } -% - } -%<*trace> - \trace_pop:n { marks_OR_restore_state:nn } -% - } -% \end{macrocode} -% \end{macro} % % \subsection{Trace support} % @@ -702,47 +786,29 @@ % \end{macrocode} % \end{variable} % -% \begin{macro}{\trace_marks:n, \trace_marks_internal:n} +% \begin{macro}{\@@_trace:n, \@@_trace_internal:n} % Two trace functions, one more verbose than the other. % \begin{macrocode} %<*trace> -\cs_new_protected:Npn \trace_marks:n #1 +\cs_new_protected:Npn \@@_trace:n #1 { \int_compare:nNnT \tracingmarks > 0 - { \iow_log:x { Marks:~#1~ \msg_line_context: } } + { \iow_term:x { Marks:~#1~ \msg_line_context: } } } -\cs_new_protected:Npn \trace_marks_internal:n #1 +\cs_new_protected:Npn \@@_trace_internal:n #1 { \int_compare:nNnT \tracingmarks > 1 - { \iow_log:x { Marks:~#1 } } + { \iow_term:x { Marks:~#1 } } } % % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\@@_trace_store:N} -% \begin{macro}[EXP]{\@@_trace_store_aux:nn} -% For pretty-printing marks when tracing. -% \begin{macrocode} -%<*trace> -\cs_new:Npn \@@_trace_store:N #1 - { \prop_map_function:NN #1 \@@_trace_store_aux:nn } -\cs_new:Npn \@@_trace_store_aux:nn #1#2 { \exp_not:n { { #1 = #2 } } } -% -% \end{macrocode} -% \end{macro} -% \end{macro} +% % % \subsection{Messages} % % \begin{macrocode} -\__kernel_msg_new:nnnn { marks } { bad-restore } - { Incorrect~use~of~restore~marks~function. } - { - \c__msg_coding_error_text_tl - LaTeX~was~asked~to~run~part~of~the~mark-restoring~system~in~a~location~ - where~this~should~not~happen. - } \__kernel_msg_new:nnnn { marks } { type-already-defined } { Mark~type~'#1'~already~defined } { @@ -759,101 +825,291 @@ does~not~exist. } % \end{macrocode} + +% % -% \subsection{Design-level interface} +% \subsection{Designer-level interfaces} % +% % \begin{macro}{\DeclareMarkType} % \begin{macro}{\PutMark} % \begin{macro}[EXP]{\PreviousMark, \FirstMark, \LastMark} -% Simple copies: may change. +% Largely simple copies: may change. +% \begin{macrocode} % \begin{macrocode} \cs_new_eq:NN \DeclareMarkType \marks_new:n \cs_new_eq:NN \PutMark \marks_put:nn -\cs_new_eq:NN \PreviousMark \marks_get_previous:n -\cs_new_eq:NN \FirstMark \marks_get_first:n -\cs_new_eq:NN \LastMark \marks_get_last:n +% \end{macrocode} +% The following commands take an optional argument that defaults to +% page. There is no checking that the region is actually valid. If +% not there is simply an empty return. +% \begin{macrocode} +\NewExpandableDocumentCommand \FirstMark { O{page} m } + { \marks_use_first:nn {#1}{#2} } + +\NewExpandableDocumentCommand \LastMark { O{page} m } + { \marks_use_last:nn {#1}{#2} } + +\NewExpandableDocumentCommand \PreviousMark { O{page} m } +{ \marks_use_previous:nn {#1}{#2} } + % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \subsection{Support for \LaTeXe{} internals} % +% +% \section{\LaTeXe{} integration} +% +% \begin{macro}[TF, int]{\legacy_switch_if:n} +% To evaluate \LaTeXe{} boolean switches in a nice way, we need a +% conditional. Eventually this will probably make it into the \pkg{expl3} +% code in this or a similar form, but right now it is missing. % \begin{macrocode} -%<*package> +\prg_new_conditional:Npnn \legacy_switch_if:n #1 {p, T , F , TF } + { \exp_args:Nc\if_meaning:w { if#1 } \iftrue \prg_return_true: + \else: \prg_return_false: \fi: } % \end{macrocode} +% \end{macro} +% % -% \begin{macro}{leftmark (mark), rightmark (mark)} -% We declare two marks to hold heading information % \begin{macrocode} -\DeclareMarkType { leftmark } -\DeclareMarkType { rightmark } +\RequirePackage{etoolbox} +% \end{macrocode} +% +% +% \begin{macrocode} +\marks_new:n {ltxleft} +\marks_new:n {ltxright} +\marks_new:n {ltxrightnonempty} % \end{macrocode} -% \end{macro} % +% % \begin{macro}{\markboth} % \begin{macro}{\markright} -% The \LaTeX2e{} commands for generating heading marks need a new -% definition (this one right now is just a one-to-one translation). +% In addition to generating the legacy mark we output the +% individual ones as well at the very same point. +% +% These days both macros are robust so patching needs to be done on +% the internal ones which is arkward. But then this is only +% temporary \dots +% \begin{macrocode} +\expandafter\patchcmd\csname markboth\space \endcsname + {\mark} + { + \marks_put:nn{ltxleft}{#1} + \marks_put:nn{ltxright}{#2} + \tl_if_empty:nF{#2}{ \marks_put:nn{ltxrightnonempty}{#2} } + \mark + } + {\typeout{\noexpand\markboth patch~ successful}} + {\typeout{\noexpand\markboth patch~ failed}} +% \end{macrocode} +% Same game with \cs{markright} more or less \ldots +% \begin{macrocode} +\expandafter\patchcmd\csname markright\space \endcsname + {\mark} + { + \marks_put:nn{ltxright}{#1} + \tl_if_empty:nF{#1}{ \marks_put:nn{ltxrightnonempty}{#1} } +% \end{macrocode} +% Not sure this is a good idea --- needs some further thoughts +% probably: We add here another ltxleft mark using the value it had +% before. This mimics the way \LaTeX{} currently handles its marks, +% i.e. if a sub-mark (ie right mark) is set the corresponding main +% mark also is getting a mark. +% \begin{macrocode} + \marks_put:nn{ltxleft}{\exp_after:wN \use_i:nn \@themark } + \mark + } + {\typeout{\noexpand\markright patch~ successful}} + {\typeout{\noexpand\markright patch~ failed}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% +% +% \begin{macro}{\@opcol} +% \cs{@opcol} handles outputting single or two-column pages. So we +% need to patch it in each branch to get our mark data structure +% updated. % \begin{macrocode} -\RenewDocumentCommand \markboth { m m } +\patchcmd\@opcol + {\@outputpage} { - \group_begin: - \cs_set_eq:NN \label \scan_stop: - \cs_set_eq:NN \index \scan_stop: - \cs_set_eq:NN \glossary \scan_stop: - \protected@edef \l_@@_tmp_tl {#1} - \exp_args:NV \@markleft \l_@@_tmp_tl - \protected@edef \l_@@_tmp_tl {#2} - \exp_args:NV \@markright \l_@@_tmp_tl - \group_end: - \if@nobreak - \mode_if_vertical:T { \nobreak } - \fi + \@@_update_singlecol_structure:n + { \unvcopy\@outputbox\unskip } + \@outputpage } -\RenewDocumentCommand \markright { m } + {\typeout{\noexpand\@opcol patch~ 1~ successful}} + {\typeout{\noexpand\@opcol patch~ 1~ failed}} +% \end{macrocode} +% +% \begin{macrocode} +\patchcmd\@opcol + {\@outputdblcol} { - \group_begin: - \cs_set_eq:NN \label \scan_stop: - \cs_set_eq:NN \index \scan_stop: - \cs_set_eq:NN \glossary \scan_stop: - \protected@edef \l_@@_tmp_tl {#1} - \exp_args:NV \@markright \l_@@_tmp_tl - \group_end: - \if@nobreak - \mode_if_vertical:T { \nobreak } - \fi + \@@_update_dblcol_structure:nn + { \unvcopy\@outputbox\unskip } + { \unvcopy\@leftcolumn\unskip + \unvcopy\@outputbox\unskip } + \@outputdblcol } + {\typeout{\noexpand\@opcol patch~ 2~ successful}} + {\typeout{\noexpand\@opcol patch~ 2~ failed}} % \end{macrocode} % \end{macro} -% \end{macro} % -% \begin{macro}{\@markleft, \@markright} -% Internal, but used by others and so still need to work. +% +% \begin{macro}{\@@_update_singlecol_structure:n} +% % \begin{macrocode} -\cs_set_protected:Npn \@markleft #1 { \PutMark { leftmark } {#1} } -\cs_set_protected:Npn \@markright #1 { \PutMark { rightmark } {#1} } +\cs_new:Npn \@@_update_singlecol_structure:n #1 + { + \legacy_switch_if:nTF {@twoside} + { + \int_if_odd:nTF \c@page + { \@@_update_structure:nnn {page}{recto}{#1} } + { \@@_update_structure:nnn {page}{verso}{#1} } + } + { + \@@_update_structure:nnn {page}{recto}{#1} + \@@_update_structure_alias:nn {verso}{page} + } + \@@_update_structure_alias:nn {col}{page} + \@@_update_structure_alias:nn {1col}{page} + \@@_update_structure_alias:nn {2col}{page} +%<*trace> + \marks_status:n + { OR:~( + \legacy_switch_if:nTF {@twoside} + { twoside- + \int_if_odd:nTF \c@page + { odd }{ even } + } + { oneside } + ) + } +% + } % \end{macrocode} -% \end{macro} -% -% \begin{macro}{\leftmark, \rightmark} -% Again, document level and so use \pkg{xparse}: not really token list -% variables as a single expansion will not yield what is actually required -% here. +% \end{macro} +% +% \begin{macro}{\@@_update_dblcol_structure:nn} +% % \begin{macrocode} -\DeclareExpandableDocumentCommand \leftmark { } { \LastMark { leftmark } } -\DeclareExpandableDocumentCommand \rightmark { } { \LastMark { rightmark } } +\cs_new:Npn \@@_update_dblcol_structure:nn #1#2 + { + \legacy_switch_if:nTF {@firstcolumn} + { \@@_update_structure:nnn {col}{1col}{#1} } + { + \@@_update_structure:nnn {col}{2col}{#1} + \legacy_switch_if:nTF {@twoside} + { + \int_if_odd:nTF \c@page + { \@@_update_structure:nnn {page}{recto}{#2} } + { \@@_update_structure:nnn {page}{verso}{#2} } + } + { \@@_update_structure:nnn {page}{recto}{#2} } + } +%<*trace> + \marks_status:n + { OR:~( + \legacy_switch_if:nTF {@twoside} + { twoside- + \int_if_odd:nTF \c@page + { odd }{ even } + } + { oneside } + \space + \legacy_switch_if:nTF {@firstcolumn} + { first~ }{ second~ } + column ) + } +% + } % \end{macrocode} -% \end{macro} +% \end{macro} +% +% % % \begin{macrocode} % % \end{macrocode} % +% \section{Supporting marks in floats} +% +% At the moment, marks that are placed into floats do not migrate out +% and thus are never seen. Below are some ideas how the scheme could +% be extended to support use cases that involve marks inside +% floats. +% +% The basic idea is that when the floats are combined to be placed +% into their areas we make a copy of that in an additional box (but +% using \cs{unvcopy} so that the fload body is at top-level in that +% box. Later when getting the marks in the OR via \cs{vsplit} we can +% then use this content so that any marks inside will be seen too. +% +% \cs{@combinefloats} is not the only place that would need patching +% in that case, the same needs to be done for spanning floats and also +% to the code that adds inline floats. So this is just an outline really. +% \begin{macrocode} +%<*floats> +% \end{macrocode} +% +% \begin{macrocode} +\box_new:N \@@_floats_box +\box_new:N \@@_tfloats_box +\box_new:N \@@_bfloats_box +% \end{macrocode} +% +% \begin{macrocode} +\def \@combinefloats {% + \setbox\@@_floats_box\vbox{}% + \ifx \@toplist\@empty \else + \@cflt + \setbox\@@_tfloats_box\vbox{\unvbox\@@_floats_box} + \setbox\@@_floats_box\vbox{}% + \fi + \ifx \@botlist\@empty \else \@cflb \fi + \setbox\@@_bfloats_box\vbox{\unvbox\@@_floats_box} +} +% \end{macrocode} +% +% \begin{macrocode} +\def\@comflelt#1{% + \setbox\@@_floats_box\vbox{% + \unvbox\@@_floats_box \unvcopy #1}% % may need to check that it + % is a vbox! + \setbox\@tempboxa + \vbox{\unvbox\@tempboxa\box #1\vskip\floatsep}} +% \end{macrocode} +% +% When getting the marks we then have to look not only at the +% galley but also at the content of \cs{@@_tfloats_box} etc. In +% reality that gets even more complex for two columns as we have +% more float areas then. +% \begin{macrocode} + \@@_update_structure:nnn + {#1}{#2} + { \unvcopy\@@_tfloats_box + \unvcopy #3 \unskip + \unvcopy\@@_bfloats_box } +% \end{macrocode} +% % \begin{macrocode} -% +% % \end{macrocode} +% % % \end{implementation} % % \PrintIndex + + + + diff --git a/l3trial/xmarks/xmarks.ins b/l3trial/xmarks/xmarks.ins index a9924405d8..bbc25b49b9 100644 --- a/l3trial/xmarks/xmarks.ins +++ b/l3trial/xmarks/xmarks.ins @@ -53,6 +53,4 @@ and all files in that bundle must be distributed together. \generate{\file{xmarks.sty}{\from{xmarks.dtx}{package,trace}}} -\generate{\file{xmarks2.sty}{\from{xmarks2.dtx}{package,trace}}} - \endbatchfile diff --git a/l3trial/xmarks/xmarks2.dtx b/l3trial/xmarks/xmarks2.dtx deleted file mode 100644 index 4e6bc0da39..0000000000 --- a/l3trial/xmarks/xmarks2.dtx +++ /dev/null @@ -1,1064 +0,0 @@ -% \iffalse meta-comment -% -%% File: xmarks.dtx Copyright (C) 2018-2020 Frank Mittelbach, The LaTeX3 Project -% -% It may be distributed and/or modified under the conditions of the -% LaTeX Project Public License (LPPL), either version 1.3c of this -% license or (at your option) any later version. The latest version -% of this license is in the file -% -% https://www.latex-project.org/lppl.txt -% -% This file is part of the "l3trial bundle" (The Work in LPPL) -% and all files in that bundle must be distributed together. -% -% ----------------------------------------------------------------------- -% -% The development version of the bundle can be found at -% -% https://github.com/latex3/latex3 -% -% for those people who are interested. -% -%<*driver|package> -\RequirePackage{xparse} -% -%<*driver> -\documentclass[full]{l3doc} -\begin{document} - \DocInput{xmarks2.dtx} -\end{document} -% -% \fi -% -% \title{^^A -% The \textsf{xmarks2} package\\Marks^^A -% } -% -% \author{^^A -% Frank Mittelbach, \LaTeX3 Project\thanks -% {^^A -% E-mail: -% \href{mailto:latex-team@latex-project.org} -% {latex-team@latex-project.org}^^A -% }^^A -% } - -% \date{Released --- not yet} -% -% \maketitle -% -% \begin{documentation} -% -% Marks are used to communicate information about the content of a page -% to the output routine. Perhaps the clearest form of mark is that needed -% for sections. In order to construct running headers, the output routine -% needs information about which section names are present on a page, and this -% information is passed by the mark system. However, marks may also be used -% for other purposes. This module provides a generalised mechanism for marks -% of independent types. -% -% \section{Design-level interface} -% -% \begin{function}{\DeclareMarkType} -% \begin{syntax} -% \cs{DeclareMarkType} \Arg{type} -% \end{syntax} -% Declares a \meta{type} of mark to be tracked by \LaTeX{}. Each \meta{type} -% must be declared before it is used. -% \end{function} -% -% \begin{function}{\PutMark} -% \begin{syntax} -% \cs{PutMark} \Arg{type} \Arg{entry} -% \end{syntax} -% Adds a mark to the current page for the \meta{type}, containing the -% \meta{entry} text. -% \end{function} -% -% \begin{function}[EXP]{\PreviousMark, \FirstMark, \LastMark} -% \begin{syntax} -% \cs{PreviousMark} \oarg{region} \Arg{type} -% \cs{FirstMark} \oarg{region} \Arg{type} -% \cs{LastMark} \oarg{region} \Arg{type} -% \end{syntax} -% These functions expand to the appropriate mark \meta{entry} for -% the given \meta{type} in the specified \meta{region} by default -% \texttt{page}. The \enquote{first} and \enquote{last} marks are -% those seen first and last in the current region/page, respectively. The -% \enquote{previous} mark is the last mark of the \meta{type} seen -% in an earlier region, i.e.what would be \enquote{current} at the -% very top of the region. -% -% \end{function} -% -% ^^A footnotes not supported in function! -% -% Supported regions beside \texttt{page} are \texttt{verso} and -% \texttt{recto} if you are producing a \enquote{two-sided} -% document. If you are on a recto (odd) page you can then use the -% \texttt{verso} region to refer to the marks on the opposite -% page. Note, that right now this doesn't work in the opposite -% direction: you can't refer to the following recto page if you are -% on a verso page (you will see the marks only from already handled -% regions\footnote{This restriction might get lifted eventually.}). -% The \texttt{page} region always refers to the current page, i.e., it is -% either the same as using \texttt{recto} or \texttt{verso} -% depending on where you are. If your document is one-sided then all -% three regions return the same data.\footnote{Or verso returns the -% empty string --- to be decided.} -% -% A similar concept exists for two column documents: \texttt{1col} -% and \texttt{2col} refers to the left and right column region -% respectively. -% -% -% \section{Code-level interface} -% -% \begin{function}{\marks_new:n} -% \begin{syntax} -% \cs{marks_new:n} \Arg{type} -% \end{syntax} -% Declares a \meta{type} of mark to be tracked by \LaTeX{}. Each \meta{type} -% must be declared before it is used. -% \end{function} -% -% \begin{function}{\marks_put:nn} -% \begin{syntax} -% \cs{marks_put:nn} \Arg{type} \Arg{entry} -% \end{syntax} -% Adds a mark to the current page for the \meta{type}, containing the -% \meta{entry} text. The \meta{entry} is expanded at the time of use. -% \end{function} -% -% -% -% -% \begin{function}[EXP] -% {\marks_use_previous:nn, \marks_use_first:nn, \marks_use_last:nn} -% \begin{syntax} -% \cs{marks_use_previous:nn} \Arg{region} \Arg{type} -% \cs{marks_use_first:nn} \Arg{region} \Arg{type} -% \cs{marks_use_last:nn} \Arg{region} \Arg{type} -% \end{syntax} -% These functions expand to the appropriate mark \meta{entry} for -% the given \meta{type} in the specified \meta{region}. The \enquote{first} and -% \enquote{last} marks are those seen first and last in the region, -% respectively. The \enquote{previous} mark is the last mark of the -% \meta{type} seen on earlier regions. These functions should be used only in -% output routines after \cs{marks_update_structure:nnn} has acted, otherwise their -% values will be wrong. -% \end{function} -% -% -% \section{Legacy \LaTeXe{} interface} -% -% \subsection{Legacy design-level and document-level interfaces} -% -% \begin{function}{\markboth, \markright} -% \begin{syntax} -% \cs{markboth} \Arg{left} \Arg{right} -% \cs{markright} \Arg{right} -% \end{syntax} -% \LaTeXe{} uses two marks which aren't fully independent. A -% \enquote{left} mark generated by the first argument of \cs{markboth} -% and a \enquote{right} mark generated by the second argument of -% \cs{markboth} or by the only argument of \cs{markright}. The -% command \cs{markboth} and \cs{markright} are in turn called from -% heading commands such as \cs{chaptermark} or \cs{sectionmark} and -% their behavior is controlled by the document class. -% -% For example, in the \cls{article} class with \texttt{twoside} in -% force the \cs{sectionmark} will issue \cs{markboth} with an empty -% second argument and \cs{subsectionmark} will issue -% \cs{markright}. As a result the left mark will contain chapter -% titles and the right mark subsection titles. -% -% Note, however, that in one-sided documents the standard behavior is -% that only \cs{markright} is used, i.e., there will only be -% right-marks but no left marks! -% \end{function} -% -% \begin{function}[EXP]{\leftmark, \rightmark} -% \begin{syntax} -% \cs{leftmark} -% \cs{rightmark} -% \end{syntax} -% These functions return the appropriate mark value from the current page -% and work as before, that is \cs{leftmark} will get the first (!) -% left mark from the page and \cs{rightmark} the last (!) right -% mark. -% -% In other words they work well if you want to show the section -% title that is current when the page begins (and there is not -% further section on that page) or the first section that started on -% this page (if there is one) and also show the subsection title -% that is current when the page ends. Other combination can't be -% shown using this interface. -% \end{function} -% -% -% \subsection{Legacy interface extensions} -% -% The \pkg{xmarks2} package adds three mark types \texttt{ltxleft}, -% \texttt{ltxright} and \texttt{ltxrightnonempty} and patches -% \cs{markboth} and \cs{markright} slightly so that they in addition -% to the above interface also update these mark types. -% -% The difference between \texttt{ltxright} and -% \texttt{ltxrightnonempty} is that the latter will only be updated -% if the material for the mark is not empty. -% -% As a result you can use \verb=\FirstMark{ltxleft}= and -% \verb=\LastMark{{ltxright}= instead of \cs{leftmark} and -% \cs{rightmark}. But more important you can use any of the other -% retrival commands to get a different status value from those -% marks, e.g., \verb=\FirstMark{ltxright}= would return the first -% subsection on the page (instead of the last) that would be -% returned by \cs{rightmark}. -% -% The difference between \texttt{ltxright} and -% \texttt{ltxrightnonempty} is that the latter will only be updated -% if the material for the mark is not empty. Thus -% \verb=\markboth{title}{}= as issued by, say \cs{sectionmark}, -% will set a \texttt{ltxleft} mark with \texttt{title} and a -% \texttt{ltxright} mark with the empty string but will not add a -% \texttt{ltxrightnonempty} mark. -% -% Thus, if you have a section at the start of a page and you would -% ask for \verb=\FirstMark{ltxright}= you would get an empty string -% even if there are subsections on that page. But -% \texttt{ltxrightnonempty} would then give you the first subsection -% on that page. Of course, nothing is simple. If there are no -% subsection it would tell you the last subsection from an earlier -% page. We therefore need comparison tools, e.g., if previous and -% first are identical you know that the value is -% bogus.\footnote{Those tools need still doing!} -% -% -% \subsection{Output routine functions} -% -% These functions are tied to the output routine and used in the -% interface to \LaTeXe{} and perhaps at some later time within an OR -% for \LaTeX3. Not meant for general use, so made internal here. -% Internal to this package means that \verb|@@| automatically gets -% replaced in the code (and in the documentation). -% \begin{macrocode} -%<@@=marks> -% \end{macrocode} -% -% \begin{function}{\@@_update_structure:nnn} -% \begin{syntax} -% \cs{@@_update_structure:nnN} \Arg{last} \Arg{current} \Arg{material with marks} -% \end{syntax} -% \meta{last} is the region from which to take the last marks to -% make them new top marks. \meta{current} is the region to update -% and \meta{material} holds material that contain new marks. Thus if this -% material consists of boxes we need to do the unpacking with the -% argument so that the marks can be seen. -% \end{function} -% -% -% -% \begin{function}{\@@_update_structure_alias:nn} -% \begin{syntax} -% \cs{@@_update_structure_alias:nn} \Arg{alias} \Arg{source} -% \end{syntax} -% Assigns all marks for the \meta{source} region also to -% \meta{alias}, e.g., if we finished a \texttt{verso} page we -% could make the generic \texttt{page} region hold the same -% marks. In most cases this is automatically done already by -% \cs{@@_update_structure:nnN} so this is only needed in a few -% cases. -% \end{function} -% -% -% \begin{function}{\@@_update_singlecol_structure:n} -% \begin{syntax} -% \cs{@@_update_singlecol_structure:n} \Arg{material with marks} -% \end{syntax} -% \LaTeXe{} integration function receiving the content of the output box -% (box~$255$, though may vary in \LuaTeX{}) for -% mark processing when we are doing single column documents. -% \end{function} -% -% -% \begin{function}{\@@_update_dblcol_structure:nn} -% \begin{syntax} -% \cs{@@_update_singlecol_structure:n} \Arg{current column material} -% \Arg{whole page material} -% \end{syntax} -% \LaTeXe{} integration function mark processing when we are doing -% double column documents. The first argument handles the column marks -% and the second the marks for the complete page and is only -% relevant if we are doing the second column. -% \end{function} -% -% -% -% \end{documentation} -% -% -% -% -% -% -% -% \begin{implementation} -% -% \section{\pkg{xmarks2} Implementation} -% -% \subsection{Notes on the mechanism} -% -% \textbf{This is just a leftover docu from the original version an no -% longer correct at all} -% -% \eTeX{} extends the \TeX{} mark system to allow multiple independent -% marks. However, it does not solve a problem which means that \LaTeX{} needs -% to manage marks almost independently of \TeX{}. The reason for this is that -% the complex output routine used by \LaTeX{} to handle floats (and related -% structures) means that \tn{topmark(s)} are not reliable. Each time the -% output routine is fired up, \TeX{} moves \tn{botmark} to \tn{topmark}, and -% while \eTeX{} extends this the fundamental concept remains the same. That -% means that instead the state of marks needs to be tracked by -% \LaTeX{} itself. An early implementation of this package used -% \TeX{}'s \tn{botmark} only to ensure the correct interaction with -% the output routine (this was before the \eTeX{} mechanism was even -% available). However, other than in a prototype implementation for -% \LaTeX3 this package was never made public. -% -% The new implementation now does use \eTeX{}'s marks as they have -% some advantages as with them we can leave the mark text within the -% galley and only extract the marks during the output routine when -% we are finally shipping out a page or storing away a column for -% use in the next page. That means we do not have to maintain a -% global data structure that we have to keep in sync with -% informational marks in the galley but can rely on everything being -% in one place and thus manipulations (e.g.~reordering of material) -% will take the marks with them without a need for updating a -% fragile linkage. - -% To allow for completely independent marks we use the following -% procedure: -% \begin{itemize} -% \item -% For every mark of type \meta{type} we allocate a mark class so -% that in the output routine \TeX{} can calculate for each type top, -% first and bottom mark independently. -% -% \item As already mentioned firing up an output routine without -% shipping out a page means that \TeX's top marks get wrong so it is -% impossible to rely on \TeX's approach directly. What we do instead -% is to keep track of the real marks (from last page or -% more generally last region) in some global variables. -% -% \item These variables are updated in the output routine at defined -% places, i.e., when we do real output processing but not if we use -% special output routines to do internal housekeeping. -% -% \item The trick we use to get correctly updated variables is the -% following: the material that contains new marks (for example the -% page to be shipped out) is stored in a box. We then use \TeX{} -% primitive box splitting functions by splitting off the largest -% amount possible (which should be the whole box if nothing goes -% really wrong). While that seems a rather pointless thing to do, it -% has one important side effect: \TeX{} sets up first and bottom -% marks for each mark class from the material it has split off. This -% way we get the first and last marks (if there have been any) from -% the material in the box. -% -% \item The top marks are simply the last marks from the previous -% page or region. And if there hasn't been a first or bottom mark in -% the box then the new top mark also becomes new first and last mark -% for that class. -% \end{itemize} -% That's about it in a nutshell. Of course, there are some details to -% be taken care off and those are discussed further below. -% -% -% -% \subsection{Lead-off code} -% -% \begin{macrocode} -%<*package> -% \end{macrocode} -% -% -% \begin{macrocode} -%<*package> -\ProvidesExplPackage{xmarks2}{2020-02-06}{} - {L3 Experimental marks} -% -% \end{macrocode} -% -% -% \begin{variable}{\g_@@_types_seq} -% A list of all of the mark types in use. -% \begin{macrocode} -\seq_new:N \g_@@_types_seq -% \end{macrocode} -% \end{variable} -% -% -% \begin{macro}{\g_@@_class_int} -% We assume that nobody is using extended marks!!! The alternative -% is to use \cs{newmarks} from \LaTeXe{} or provide an interface in -% expl3. One or the other should be dne! -% \begin{macrocode} -\int_new:N \g_@@_class_int -% \end{macrocode} -% \end{macro} -% -% -% -% \begin{macro}{\marks_new:n} -% \begin{macro}{\@@_new:n} -% A mark type is created by initialising a number of data -% structures. First, we get a number to refer to the mark class. -% The new mark type is then added to a sequence to be able to -% easily loop over all types. finally a number of top-level global -% token lists are generated that hold various versions of the mark -% for access. -% \begin{macrocode} -\cs_new_protected:Npn \marks_new:n #1 -{ - \seq_if_in:NnTF \g_@@_types_seq {#1} - { - \__kernel_msg_error:nnn { marks } { type-already-defined } - {#1} - } - { \@@_new:n {#1} } -} -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_new:n #1 -{ -%<*trace> - \@@_trace:n { new~mark:~ #1 } -% - \int_gincr:N \g_@@_class_int - \int_const:cn {c_@@_class_ #1 _int}{ \g_@@_class_int } - \seq_gput_right:Nn \g_@@_types_seq {#1} - \tl_new:c { g_@@_page_top_ #1 _tl } - \tl_new:c { g_@@_page_first_ #1 _tl } - \tl_new:c { g_@@_page_last_ #1 _tl } - \tl_new:c { g_@@_verso_top_ #1 _tl } - \tl_new:c { g_@@_verso_first_ #1 _tl } - \tl_new:c { g_@@_verso_last_ #1 _tl } - \tl_new:c { g_@@_recto_top_ #1 _tl } - \tl_new:c { g_@@_recto_first_ #1 _tl } - \tl_new:c { g_@@_recto_last_ #1 _tl } -% \end{macrocode} -% ``col'' is really useless and should get dropped or rethought -% \begin{macrocode} - \tl_new:c { g_@@_col_top_ #1 _tl } - \tl_new:c { g_@@_col_first_ #1 _tl } - \tl_new:c { g_@@_col_last_ #1 _tl } -% \end{macrocode} -% -% \begin{macrocode} - \tl_new:c { g_@@_1col_top_ #1 _tl } - \tl_new:c { g_@@_1col_first_ #1 _tl } - \tl_new:c { g_@@_1col_last_ #1 _tl } - \tl_new:c { g_@@_2col_top_ #1 _tl } - \tl_new:c { g_@@_2col_first_ #1 _tl } - \tl_new:c { g_@@_2col_last_ #1 _tl } -} -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% -% -% -% -% \begin{macrocode} - - \box_new:N \@@_box - - \tl_new:N \g_@@_tmp_tl - \tl_new:N \g_@@_new_top_tl - -% \end{macrocode} -% - -% \begin{macro}{\@@_update_structure:nnn} - -% This function updates the mark structure. The first argument is -% the region from which we pick up the last mark to make it the new -% top mark. The second argument is the region for which we produce -% mark value and the third argument is the material that holds the -% marks. Out of this material we extract the first and last mark -% (if there are any) to do the assignments. -% -% The second argument is always a specific region, e.g., -% \texttt{verso} while the first is always the generic name, e.g., -% \texttt{page}. Since when updating a specific region the -% corresponding generic one will receive the same values, this -% allows us to do both assignments at the same time (without the -% need for \cs{@@_update_structure_alias:nn}) which save a bit of -% processing time as we don't have to construct csnames unnecessarily. -% \begin{macrocode} -\cs_new:Npn \@@_update_structure:nnn #1#2#3 -{ - \group_begin: -% \end{macrocode} -% Getting the first and last marks out of the material in \verb=#3= -% is done by putting the material in a box and then doing a -% split operation to the maximum size possible (which hopefully -% means all of the content.\footnote{We could verify this, maybe we -% should.} As this is a temporary thing we don't want any underfull -% box warnings so we turn those off. -% \begin{macrocode} - \dim_set:Nn \tex_splitmaxdepth:D \c_max_dim - \int_set:Nn \tex_vbadness:D \c_max_int - \vbox_set:Nn \@@_box {#3} - \vbox_set_split_to_ht:NNn \@@_box \@@_box \c_max_dim -% \end{macrocode} -% After this action we can get first and last marks of the various -% types through \cs{tex_splitfirstmarks:D} and -% \cs{tex_splitbotmarks:D}. So now we loop over all types stored in -% \cs{g_@@_types_seq}. -% \begin{macrocode} - \seq_map_inline:Nn \g_@@_types_seq - { -% \end{macrocode} -% First action: get the last mark from the previous region. As we -% need this value in various assignments we store it away which -% avoids uncessary csname generations. -% \begin{macrocode} - \tl_gset_eq:Nc \g_@@_new_top_tl { g_@@_ #1 _last_ ##1 _tl } -% \end{macrocode} -% This will first of all become the new top mark. -% \begin{macrocode} - \tl_gset_eq:cN { g_@@_ #1 _top_ ##1 _tl } \g_@@_new_top_tl - \tl_gset_eq:cN { g_@@_ #2 _top_ ##1 _tl } \g_@@_new_top_tl -% \end{macrocode} -% Next action is to get ourselves the new last mark from the -% material supplied. -% \begin{macrocode} - \tl_gset:No \g_@@_tmp_tl - { \tex_splitbotmarks:D \use:c{c_@@_class_ ##1 _int} } -% \end{macrocode} -% If this mark doesn't exist then obviously first mark neither, so both -% become the last mark from previous region. We have to be a little -% careful here: something like \verb=\marks_put{foo}{}= adds an -% \enquote{empty} mark that should not be confused with no mark at -% all. But no mark in our material will result in \cs{g_@@_tmp_tl} -% being empty. This is why we have to make sure that the empty from -% \cs{marks_put:nn} only appears to be empty but fails the next test: -% \begin{macrocode} - \tl_if_empty:NTF \g_@@_tmp_tl - { - \tl_gset_eq:cN { g_@@_ #1 _last_ ##1 _tl } \g_@@_new_top_tl - \tl_gset_eq:cN { g_@@_ #2 _last_ ##1 _tl } \g_@@_new_top_tl - \tl_gset_eq:cN { g_@@_ #1 _first_ ##1 _tl } \g_@@_new_top_tl - \tl_gset_eq:cN { g_@@_ #2 _first_ ##1 _tl } \g_@@_new_top_tl - } -% \end{macrocode} -% If it wasn't empty, ie had a real value then we use this value -% for our new last mark. -% \begin{macrocode} - { - \tl_gset_eq:cN { g_@@_ #1 _last_ ##1 _tl } \g_@@_tmp_tl - \tl_gset_eq:cN { g_@@_ #2 _last_ ##1 _tl } \g_@@_tmp_tl -% \end{macrocode} -% Since we had a bottom mark we will also have a first mark (which -% might be the same, but might be not), so we pick that up and -% assign it to the appropriate token lists. -% \begin{macrocode} - \tl_gset:No \g_@@_tmp_tl - { \splitfirstmarks \use:c{c_@@_class_ ##1 _int} } - \tl_gset_eq:cN { g_@@_ #1 _first_ ##1 _tl } \g_@@_tmp_tl - \tl_gset_eq:cN { g_@@_ #2 _first_ ##1 _tl } \g_@@_tmp_tl - } - } - \group_end: -} -% \end{macrocode} -% \end{macro} -% -% - -% \begin{macro}{\@@_update_structure_alias:nn} -% -% \begin{macrocode} -\cs_new:Npn \@@_update_structure_alias:nn #1#2 -{ - \seq_map_inline:Nn \g_@@_types_seq - { - \tl_gset_eq:cc { g_@@_ #1 _top_ ##1 _tl } - { g_@@_ #2 _top_ ##1 _tl } - \tl_gset_eq:cc { g_@@_ #1 _first_ ##1 _tl } - { g_@@_ #2 _first_ ##1 _tl } - \tl_gset_eq:cc { g_@@_ #1 _last_ ##1 _tl } - { g_@@_ #2 _last_ ##1 _tl } - } -} -% \end{macrocode} -% \end{macro} -% -% -% \begin{macro}{\marks_put:nn} -% -% \begin{macrocode} -\cs_new_protected:Npn \marks_put:nn #1#2 -{ - \seq_if_in:NnTF \g_@@_types_seq {#1} - { -% \end{macrocode} -% We need to pass the evaluated string into the mark (and we don't -% have \cs{expanded} yet) so we use the \cs{protect} approach of -% \LaTeXe{} here including disabling \cs{label} and the -% like.\footnote{Straight copy from \texttt{latex.ltx} but is this -% even correct? At least a label in a running header makes little -% sense if it get set several times! Maybe that needs looking at in -% the 2e kernel.} -% \begin{macrocode} - \group_begin: - \cs_set_eq:NN \label \scan_stop: - \cs_set_eq:NN \index \scan_stop: - \cs_set_eq:NN \glossary \scan_stop: - \unrestored@protected@xdef \g_@@_tmp_tl {#2} -%<*trace> - \@@_trace:n { set~#1~<-~ '\tl_to_str:V \g_@@_tmp_tl' } -% - \tex_marks:D \use:c{c_@@_class_ #1 _int} - { - \exp_not:n{ \prg_do_nothing: } - \g_@@_tmp_tl - } - \group_end: - } - { - \__kernel_msg_error:nnx { marks } { unknown-type } - { \tl_to_str:n {#1} } - } -} -% \end{macrocode} -% \end{macro} -% -% -% -% \begin{macro}[EXP] -% {\marks_get_first:nn, \marks_get_last:nn, \marks_get_previous:nn} -% To retrieve the first, last or previous region mark, we grab the appropriate -% value stored in some tl var. These functions should be used only in -% output routines after \cs{@@_update_structure:nnn} has acted, otherwise their -% value will be wrong. -% \begin{macrocode} -\cs_new:Npn \marks_use_first:nn #1#2 - { \use:c { g_@@_ #1 _first_ #2 _tl } } -\cs_new:Npn \marks_use_last:nn #1#2 - { \use:c { g_@@_ #1 _last_ #2 _tl } } -\cs_new:Npn \marks_use_previous:nn #1#2 - { \use:c { g_@@_ #1 _top_ #2 _tl } } -% \end{macrocode} -% \end{macro} -% -% -% -% \begin{macro}{\marks_status:n} -% \begin{macro}{\marks_status:nn} -% Some simple tracing, should be changed \ldots -% \begin{macrocode} -\cs_new:Npn \marks_status:n #1 - { - \seq_map_inline:Nn \g_@@_types_seq { \marks_status:nn {#1} {##1} } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new:Npn \marks_status:nn #1#2 - { - \int_compare:nNnT \tracingmarks > 1 - { - \typeout{#1~ #2:} - \typeout{\@spaces page~ (current): - | \tl_use:c { g_@@_page_top_ #2 _tl } - | \tl_use:c { g_@@_page_first_ #2 _tl } - | \tl_use:c { g_@@_page_last_ #2 _tl } |} - \typeout{\@spaces page~ (verso): - | \tl_use:c { g_@@_verso_top_ #2 _tl } - | \tl_use:c { g_@@_verso_first_ #2 _tl } - | \tl_use:c { g_@@_verso_last_ #2 _tl } |} - \typeout{\@spaces page~ (recto): - | \tl_use:c { g_@@_recto_top_ #2 _tl } - | \tl_use:c { g_@@_recto_first_ #2 _tl } - | \tl_use:c { g_@@_recto_last_ #2 _tl } |} - % - \typeout{\@spaces column~ (current): - | \tl_use:c { g_@@_col_top_ #2 _tl } - | \tl_use:c { g_@@_col_first_ #2 _tl } - | \tl_use:c { g_@@_col_last_ #2 _tl } |} - \typeout{\@spaces column~ (first): - | \tl_use:c { g_@@_1col_top_ #2 _tl } - | \tl_use:c { g_@@_1col_first_ #2 _tl } - | \tl_use:c { g_@@_1col_last_ #2 _tl } |} - \typeout{\@spaces column~ (second): - | \tl_use:c { g_@@_2col_top_ #2 _tl } - | \tl_use:c { g_@@_2col_first_ #2 _tl } - | \tl_use:c { g_@@_2col_last_ #2 _tl } |} - } -} -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% -% -% -% \begin{macrocode} -% \end{macrocode} -% -% -% -% -% -% \begin{macrocode} -% \end{macrocode} -% -% -% -% -% \begin{macrocode} -% \end{macrocode} -% -% -% \subsection{Trace support} -% -% \begin{variable}{\tracingmarks} -% Used to control the amount of trace material placed in the log. -% \begin{macrocode} -\int_new:N \tracingmarks -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\@@_trace:n, \@@_trace_internal:n} -% Two trace functions, one more verbose than the other. -% \begin{macrocode} -%<*trace> -\cs_new_protected:Npn \@@_trace:n #1 - { - \int_compare:nNnT \tracingmarks > 0 - { \iow_term:x { Marks:~#1~ \msg_line_context: } } - } -\cs_new_protected:Npn \@@_trace_internal:n #1 - { - \int_compare:nNnT \tracingmarks > 1 - { \iow_term:x { Marks:~#1 } } - } -% -% \end{macrocode} -% \end{macro} -% -% -% -% \subsection{Messages} -% -% \begin{macrocode} -\__kernel_msg_new:nnnn { marks } { type-already-defined } - { Mark~type~'#1'~already~defined } - { - \c__msg_coding_error_text_tl - LaTeX~was~asked~to~define~a~new~mark~type~called~'#1':~ - this~mark~type~already~exists. - \c__msg_return_text_tl - } -\__kernel_msg_new:nnnn { marks } { unknown-type } - { Unknown~mark~type~'#1'. } - { - \c__msg_coding_error_text_tl - LaTeX~was~asked~to~manipulate~a~mark~of~type~'#1',~but~this~type~of~mark~ - does~not~exist. - } -% \end{macrocode} - -% -% -% \subsection{Designer-level interfaces} -% -% -% \begin{macro}{\DeclareMarkType} -% \begin{macro}{\PutMark} -% \begin{macro}[EXP]{\PreviousMark, \FirstMark, \LastMark} -% Largely simple copies: may change. -% \begin{macrocode} -% \begin{macrocode} -\cs_new_eq:NN \DeclareMarkType \marks_new:n -\cs_new_eq:NN \PutMark \marks_put:nn -% \end{macrocode} -% The following commands take an optional argument that defaults to -% page. There is no checking that the region is actually valid. If -% not there is simply an empty return. -% \begin{macrocode} -\NewExpandableDocumentCommand \FirstMark { O{page} m } - { \marks_use_first:nn {#1}{#2} } - -\NewExpandableDocumentCommand \LastMark { O{page} m } - { \marks_use_last:nn {#1}{#2} } - -\NewExpandableDocumentCommand \PreviousMark { O{page} m } -{ \marks_use_previous:nn {#1}{#2} } - -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% -% -% \section{\LaTeXe{} integration} -% -% \begin{macro}[TF, int]{\legacy_switch_if:n} -% To evaluate \LaTeXe{} boolean switches in a nice way, we need a -% conditional. Eventually this will probably make it into the \pkg{expl3} -% code in this or a similar form, but right now it is missing. -% \begin{macrocode} -\prg_new_conditional:Npnn \legacy_switch_if:n #1 {p, T , F , TF } - { \exp_args:Nc\if_meaning:w { if#1 } \iftrue \prg_return_true: - \else: \prg_return_false: \fi: } -% \end{macrocode} -% \end{macro} -% -% -% \begin{macrocode} -\RequirePackage{etoolbox} -% \end{macrocode} -% -% -% \begin{macrocode} -\marks_new:n {ltxleft} -\marks_new:n {ltxright} -\marks_new:n {ltxrightnonempty} -% \end{macrocode} -% -% -% \begin{macro}{\markboth} -% \begin{macro}{\markright} -% In addition to generating the legacy mark we output the -% individual ones as well at the very same point. -% -% These days both macros are robust so patching needs to be done on -% the internal ones which is arkward. But then this is only -% temporary \dots -% \begin{macrocode} -\expandafter\patchcmd\csname markboth\space \endcsname - {\mark} - { - \marks_put:nn{ltxleft}{#1} - \marks_put:nn{ltxright}{#2} - \tl_if_empty:nF{#2}{ \marks_put:nn{ltxrightnonempty}{#2} } - \mark - } - {\typeout{\noexpand\markboth patch~ successful}} - {\typeout{\noexpand\markboth patch~ failed}} -% \end{macrocode} -% Same game with \cs{markright} more or less \ldots -% \begin{macrocode} -\expandafter\patchcmd\csname markright\space \endcsname - {\mark} - { - \marks_put:nn{ltxright}{#1} - \tl_if_empty:nF{#1}{ \marks_put:nn{ltxrightnonempty}{#1} } -% \end{macrocode} -% Not sure this is a good idea --- needs some further thoughts -% probably: We add here another ltxleft mark using the value it had -% before. This mimics the way \LaTeX{} currently handles its marks, -% i.e. if a sub-mark (ie right mark) is set the corresponding main -% mark also is getting a mark. -% \begin{macrocode} - \marks_put:nn{ltxleft}{\exp_after:wN \use_i:nn \@themark } - \mark - } - {\typeout{\noexpand\markright patch~ successful}} - {\typeout{\noexpand\markright patch~ failed}} -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% -% -% -% -% \begin{macro}{\@opcol} -% \cs{@opcol} handles outputting single or two-column pages. So we -% need to patch it in each branch to get our mark data structure -% updated. -% \begin{macrocode} -\patchcmd\@opcol - {\@outputpage} - { - \@@_update_singlecol_structure:n - { \unvcopy\@outputbox\unskip } - \@outputpage - } - {\typeout{\noexpand\@opcol patch~ 1~ successful}} - {\typeout{\noexpand\@opcol patch~ 1~ failed}} -% \end{macrocode} -% -% \begin{macrocode} -\patchcmd\@opcol - {\@outputdblcol} - { - \@@_update_dblcol_structure:nn - { \unvcopy\@outputbox\unskip } - { \unvcopy\@leftcolumn\unskip - \unvcopy\@outputbox\unskip } - \@outputdblcol - } - {\typeout{\noexpand\@opcol patch~ 2~ successful}} - {\typeout{\noexpand\@opcol patch~ 2~ failed}} -% \end{macrocode} -% \end{macro} -% -% -% \begin{macro}{\@@_update_singlecol_structure:n} -% -% \begin{macrocode} -\cs_new:Npn \@@_update_singlecol_structure:n #1 - { - \legacy_switch_if:nTF {@twoside} - { - \int_if_odd:nTF \c@page - { \@@_update_structure:nnn {page}{recto}{#1} } - { \@@_update_structure:nnn {page}{verso}{#1} } - } - { - \@@_update_structure:nnn {page}{recto}{#1} - \@@_update_structure_alias:nn {verso}{page} - } - \@@_update_structure_alias:nn {col}{page} - \@@_update_structure_alias:nn {1col}{page} - \@@_update_structure_alias:nn {2col}{page} -%<*trace> - \marks_status:n - { OR:~( - \legacy_switch_if:nTF {@twoside} - { twoside- - \int_if_odd:nTF \c@page - { odd }{ even } - } - { oneside } - ) - } -% - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_update_dblcol_structure:nn} -% -% \begin{macrocode} -\cs_new:Npn \@@_update_dblcol_structure:nn #1#2 - { - \legacy_switch_if:nTF {@firstcolumn} - { \@@_update_structure:nnn {col}{1col}{#1} } - { - \@@_update_structure:nnn {col}{2col}{#1} - \legacy_switch_if:nTF {@twoside} - { - \int_if_odd:nTF \c@page - { \@@_update_structure:nnn {page}{recto}{#2} } - { \@@_update_structure:nnn {page}{verso}{#2} } - } - { \@@_update_structure:nnn {page}{recto}{#2} } - } -%<*trace> - \marks_status:n - { OR:~( - \legacy_switch_if:nTF {@twoside} - { twoside- - \int_if_odd:nTF \c@page - { odd }{ even } - } - { oneside } - \space - \legacy_switch_if:nTF {@firstcolumn} - { first~ }{ second~ } - column ) - } -% - } -% \end{macrocode} -% \end{macro} -% -% -% -% \begin{macrocode} -% -% \end{macrocode} -% -% \section{Supporting marks in floats} -% -% At the moment, marks that are placed into floats do not migrate out -% and thus are never seen. Below are some ideas how the scheme could -% be extended to support use cases that involve marks inside -% floats. -% -% The basic idea is that when the floats are combined to be placed -% into their areas we make a copy of that in an additional box (but -% using \cs{unvcopy} so that the fload body is at top-level in that -% box. Later when getting the marks in the OR via \cs{vsplit} we can -% then use this content so that any marks inside will be seen too. -% -% \cs{@combinefloats} is not the only place that would need patching -% in that case, the same needs to be done for spanning floats and also -% to the code that adds inline floats. So this is just an outline really. -% \begin{macrocode} -%<*floats> -% \end{macrocode} -% -% \begin{macrocode} -\box_new:N \@@_floats_box -\box_new:N \@@_tfloats_box -\box_new:N \@@_bfloats_box -% \end{macrocode} -% -% \begin{macrocode} -\def \@combinefloats {% - \setbox\@@_floats_box\vbox{}% - \ifx \@toplist\@empty \else - \@cflt - \setbox\@@_tfloats_box\vbox{\unvbox\@@_floats_box} - \setbox\@@_floats_box\vbox{}% - \fi - \ifx \@botlist\@empty \else \@cflb \fi - \setbox\@@_bfloats_box\vbox{\unvbox\@@_floats_box} -} -% \end{macrocode} -% -% \begin{macrocode} -\def\@comflelt#1{% - \setbox\@@_floats_box\vbox{% - \unvbox\@@_floats_box \unvcopy #1}% % may need to check that it - % is a vbox! - \setbox\@tempboxa - \vbox{\unvbox\@tempboxa\box #1\vskip\floatsep}} -% \end{macrocode} -% -% When getting the marks we then have to look not only at the -% galley but also at the content of \cs{@@_tfloats_box} etc. In -% reality that gets even more complex for two columns as we have -% more float areas then. -% \begin{macrocode} - \@@_update_structure:nnn - {#1}{#2} - { \unvcopy\@@_tfloats_box - \unvcopy #3 \unskip - \unvcopy\@@_bfloats_box } -% \end{macrocode} -% -% \begin{macrocode} -% -% \end{macrocode} -% -% -% \end{implementation} -% -% \PrintIndex - - - -