[latex3-commits] [latex3/latex2e] ltmarks-enhance: Generalize mark extraction code; Use it to also provide \__mark_get_marks_for_reinsertion:nNN for use in multicols (and elsewhere) eventually (010bb157)

github at latex-project.org github at latex-project.org
Mon Nov 13 19:09:37 CET 2023


Repository : https://github.com/latex3/latex2e
On branch  : ltmarks-enhance
Link       : https://github.com/latex3/latex2e/commit/010bb157d2c359ce0afcc7bd18d77bc9300a916d

>---------------------------------------------------------------

commit 010bb157d2c359ce0afcc7bd18d77bc9300a916d
Author: Frank Mittelbach <frank.mittelbach at latex-project.org>
Date:   Mon Nov 13 19:09:37 2023 +0100

    Generalize mark extraction code;
    Use it to also provide \__mark_get_marks_for_reinsertion:nNN for use in multicols (and elsewhere) eventually


>---------------------------------------------------------------

010bb157d2c359ce0afcc7bd18d77bc9300a916d
 base/ltmarks.dtx                      | 327 ++++++++++++++++++++++++++++------
 base/testfiles-ltmarks/xmarks-009.lvt |  56 +++++-
 base/testfiles-ltmarks/xmarks-009.tlg |  97 ++++++++++
 3 files changed, 421 insertions(+), 59 deletions(-)

diff --git a/base/ltmarks.dtx b/base/ltmarks.dtx
index 726fe5d4..32c0ab32 100644
--- a/base/ltmarks.dtx
+++ b/base/ltmarks.dtx
@@ -16,7 +16,7 @@
 %
 %    \begin{macrocode}
 \def\ltmarksversion{v1.0e}
-\def\ltmarksdate{2023/11/10}
+\def\ltmarksdate{2023/11/13}
 %    \end{macrocode}
 %<*driver>
 \documentclass{l3doc}
@@ -610,9 +610,9 @@
 %   marks. It too is called as part of \cs{@opcol}.
 % \end{function}
 %
-% \begin{function}{\@@_update_structure:nn}
+% \begin{function}{\@@_update_structure_from_material:nn}
 %   \begin{syntax}
-%     \cs{@@_update_structure:nn}  \Arg{region} \Arg{material with marks}
+%     \cs{@@_update_structure_from_material:nn} \Arg{region} \Arg{material with marks}
 %   \end{syntax}
 %   Helper function that inspects the marks
 %   inside the second argument and assigns new mark values based on
@@ -627,7 +627,7 @@
 %   \texttt{page} and \texttt{column} because only they have
 %   \texttt{previous-...} counterparts.
 %
-%   Another important part to keep in mind is that marks are only
+%   Another important aspect to keep in mind is that marks are only
 %   recognized if they appear on top-level, e.g., if we want to
 %   process material stored in boxes we need to put it unboxed (using
 %   \cs{unvcopy} etc.)\ into the second argument.
@@ -642,7 +642,7 @@
 %   Helper function that copies all mark values in the \meta{source}
 %   region to \meta{alias}, i.e., make the structures identical. Used
 %   to update the \texttt{previous-...} structures inside
-%   \cs{@@_update_structure:nn} and \texttt{first-column} and
+%   \cs{@@_update_structure_from_material:nn} and \texttt{first-column} and
 %   \texttt{last-column} structures inside
 %   \cs{@@_update_singlecol_structures:} or
 %   \cs{@@_update_dblcol_structures:}.
@@ -650,7 +650,6 @@
 %
 %
 %
-%
 % \begin{function}{\@@_update_structure_to_err:n}
 %   \begin{syntax}
 %     \cs{@@_update_structure_to_err:n} \Arg{region}
@@ -662,6 +661,30 @@
 % \end{function}
 %
 %
+% \begin{function}{@@_get_marks_for_reinsertion:nNN}
+%   \begin{syntax}
+%     \cs{@@_get_marks_for_reinsertion:nNN} \Arg{source}
+%           \Arg{token-list-var for collecting first marks}
+%           \Arg{token-list-var for collecting last marks}
+%   \end{syntax}
+%   Helper function for extracting marks that would otherwise get
+%    lost, for example when they are hidden inside a box. This helper
+%    does not update mark structures and can therefore be used outside
+%    the output routine as well.
+%
+%   It collect all marks inside the \meta{source} and adds suitable
+%    \cs{mark_insert:nn} in the two token lists. These token lists can
+%    then be executed at the right place to reinsert the marks, e.g.,
+%    directly after the box. This is, for example, used by
+%    \pkg{multicol} when a short balanced \env{multicols} is returned
+%    to the galley for typesetting.
+%
+%   It is quite likely that one only needs a single token list for
+%    returning the \cs{mark_insert:nn} statements. If that is the case
+%    this command may change to take only two arguments.
+% \end{function}
+%
+%
 %
 % ^^A \end{documentation}
 %
@@ -796,25 +819,26 @@
 %  \end{macro}
 %
 %
-%  \begin{macro}{\@@_update_structure:nn}
 %
-%    This function updates the mark structures. The first argument is
-%    the region to update and second argument receives the material
-%    that holds the marks. Out of this material we extract the first
-%    and last marks for all classes (if there are any) to do the
-%    assignments.
+%  \begin{macro}{\@@_extract_and_handle_marks:nnn}
 %    
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_update_structure:nn #1#2
-  {
+\cs_new_protected:Npn \@@_extract_and_handle_marks:nnn #1#2#3 {
 %    \end{macrocode}
-%    First thing we do is copying the current structure to
-%    \texttt{previous-...}; this leaves the current structure
-%    untouched so we can update it class by class (which is necessary).
-%    \begin{macrocode}
-    \@@_update_structure_alias:nn { previous-#1 } {#1}
-%    \end{macrocode}
-%    Getting the first and last marks out of the material in \verb=#2=
+%    This macro expects a region name as its third argument and
+%    vertical material (not boxed) as its fourth. It attempts to
+%    extract mark information from \verb/#4/ and if it succeeds It
+%    executes \verb/#1{#3}/ to do something with the marks, e.g., to
+%    update the mark structure for the region.
+%  
+%    If it finds infinite negative glue it generates an error message
+%    and then calls \verb/#2{#3}/ to handle anything special in that
+%    case.
+%
+%    If it finds a forced break in the material it removes it and then
+%    restarts the attempt without it.
+%
+%    Getting the first and last marks out of the material in \verb=#4=
 %    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{With normal column material cut
@@ -852,7 +876,7 @@
 %    \cs{@@_prepare_and_extract:nn}.     
 %
 %    \begin{macrocode}
-      \@@_prepare_and_extract:nn {#1}{#2}
+      \@@_prepare_and_extract:nnn {#1} {#2} {#3}
 %    \end{macrocode}
 %    Once all mark classes have been processed the data structures are
 %    updated and we can close the group which undoes our local
@@ -864,16 +888,10 @@
 %  \end{macro}
 %
 %
-%  \begin{macro}{@@_prepare_and_extract:nn}
-%    This macro expects a region name as its first argument and
-%    vertical material (not boxed) as its second. It attempts to
-%    extract mark information from \verb/#2/ and if it succeeds stores
-%    it away in the mark structure for the region. If it finds a
-%    forced break in the material it removes it and then restarts the
-%    attempt. If it finds infinite negative glue it generates an error
-%    message otherwise it finally succeeds.
+%  \begin{macro}{@@_prepare_and_extract:nnn}
+%
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_prepare_and_extract:nn #1#2 {
+\cs_new_protected:Npn \@@_prepare_and_extract:nnn #1#2#3 {
 %    \end{macrocode}
 %
 %    To handle the \cs{enlargethispage} case we do an \tn{unskip} to
@@ -896,7 +914,7 @@
 %    \begin{macrocode}
       \vbox_set_to_ht:Nnn \l_@@_box { -.5\c_max_dim }
         {
-          #2
+          #3
           \tex_unskip:D
           \box_set_to_last:N \l_@@_box
 %    \end{macrocode}
@@ -965,7 +983,7 @@
 %    that we can then use to finish the extraction:
 %    \begin{macrocode}
           \box_if_empty:NTF \l_@@_box
-              { \@@_do_extraction:n {#1} }
+              { #1 }
 %    \end{macrocode}
 %    If we have a remainder after the split then this means that there was some forced
 %    break in the material. We get rid of that be combining the
@@ -977,43 +995,71 @@
                   { Marks:~ mark~ extraction~needs~ recursion~
                     \msg_line_context: } }
 %</trace>
-                \@@_prepare_and_extract:nn {#1}
+                \@@_prepare_and_extract:nnn {#1} {#2}
                    { \vbox_unpack:N \l_@@_ii_box
                      \vbox_unpack:N \l_@@_box    }
               }
         }
 %    \end{macrocode}
 %    If the badness was zero (we actually tested for${}>0$ but it
-%    can't get negative) then we had infinite shrinkage, so we report
-%    that and set all marks to the value the last mark had before.
+%    can't get negative) then we had infinite shrinkage, so we execute
+%    the code that handles that case:
 %    \begin{macrocode}
-        {
-          \msg_error:nnn { mark } { infinite-shrinkage } {#1}
-          \seq_map_inline:Nn \g_@@_classes_seq
-            {
-              \tl_gset_eq:cc { g_@@_#1_top_  ##1_tl }
-                             { g_@@_#1_last_ ##1_tl }
-              \tl_gset_eq:cc { g_@@_#1_first_##1_tl }
-                             { g_@@_#1_last_ ##1_tl }
-            }
-        }
+        { #2 }
 }
 %    \end{macrocode}
 %  \end{macro}
 %
 %
 %
-%  \begin{macro}{}
+%  \begin{macro}{\@@_update_structure_from_material:nn}
+%
+%    This function updates the mark structures of a region. The first
+%    argument is the region to update and second argument receives the
+%    material that holds the marks. Out of this material we extract
+%    the first and last marks for all classes (if there are any) to do
+%    the assignments.
+%
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_update_structure_from_material:nn #1#2 {
+  \@@_extract_and_handle_marks:nnn
+%    \end{macrocode}
 %    
+%    If marks can be extracted we update the structure from the split
+%    marks (code in \cs{@@_update_structure_from_splitmarks:n}).
+%    Otherwise, we generate an error message and update it using the
+%    last mark from the previous region (code in
+%    \cs{@@_update_structure_when_infinite_glue:n}).
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_do_extraction:n #1 {
+     { \@@_update_structure_from_splitmarks:n {#1}    }
+     { \@@_update_structure_when_infinite_glue:n {#1} }
+     { #2 }
+}
+%    \end{macrocode}
+%  \end{macro}
+%
+%
+%
+%  \begin{macro}{\@@_update_structure_from_splitmarks:n}
+%    This macro is called when it is possible to \cs{vsplit} the
+%    material to extract the marks (or at least if we think it is
+%    possible, see notes).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_update_structure_from_splitmarks:n #1 {
+%    \end{macrocode}
+%    
+%    First thing we do is copying the current structure to
+%    \texttt{previous-...}; this leaves the current structure
+%    untouched so we can update it class by class (which is necessary).
+%    \begin{macrocode}
+  \@@_update_structure_alias:nn { previous-#1 } {#1}
 %    \end{macrocode}
 %    After this action we can get first and last marks of the various
 %    classes through \cs{tex_splitfirstmarks:D} and
 %    \cs{tex_splitbotmarks:D}. So now we loop over all classes stored in
 %    \cs{g_@@_classes_seq}.
 %    \begin{macrocode}
-          \seq_map_inline:Nn \g_@@_classes_seq
+  \seq_map_inline:Nn \g_@@_classes_seq
             {
 %    \end{macrocode}
 %    First action: get the last mark from the previous region, i.e.,
@@ -1035,7 +1081,7 @@
               \tl_gset:No \g_@@_tmp_tl
                 { \tex_splitbotmarks:D \use:c { c_@@_class_##1_mark } }
 %    \end{macrocode}
-%    If this mark doesn't exist then obviously first mark does
+%    If this mark doesn't exist then obviously the first mark does
 %    neither, so both become the last mark from the previous region. We
 %    have to be a little careful here: something like
 %    \verb=\mark_insert:nn{foo}{}= adds an \enquote{empty} mark that should
@@ -1075,6 +1121,160 @@
 }
 %    \end{macrocode}
 %  \end{macro}
+
+
+
+
+%  \begin{macro}{\@@_update_structure_when_infinite_glue:n}
+%    If a region contains infinite negative glue we report this as an
+%    error and then set all marks to the last mark from the previous
+%    region (as we can't extract any new marks).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_update_structure_when_infinite_glue:n #1 {
+  \msg_error:nnn { mark } { infinite-shrinkage-region } {#1}
+  \seq_map_inline:Nn \g_@@_classes_seq
+      {
+        \tl_gset_eq:cc { g_@@_#1_top_  ##1_tl }
+                       { g_@@_#1_last_ ##1_tl }
+        \tl_gset_eq:cc { g_@@_#1_first_##1_tl }
+                       { g_@@_#1_last_ ##1_tl }
+      }
+}
+%    \end{macrocode}
+%  \end{macro}
+%
+%
+%
+%  \begin{macro}{\@@_get_marks_for_reinsertion:nNN}
+%
+%    This function extracts the marks from the material in the first
+%    argument but it does not update any the mark structure. Instead,
+%    it collects the marks in the token lists given as the second and
+%    third argument, in a way that they can be reinserted by just
+%    executing the token lists.\footnote{It is probably enough to
+%    collect everything in a single token list as long as we put the
+%    first marks first and the last marks last). But for extra
+%    flexibility, I currently use 2 tls. This might change when it is
+%    really clear that this is never needed.}
+%
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_get_marks_for_reinsertion:nNN #1#2#3 {
+%    \end{macrocode}
+%    First we clear the tmp token lists as we haven't seen any marks yet.
+%    \begin{macrocode}
+  \tl_clear:N \g_@@_first_marks_tl
+  \tl_clear:N \g_@@_last_marks_tl
+%    \end{macrocode}
+%    The we try to extract all marks, thereby filling the token lists
+%    with suitable \cs{mark_insert:nn} calls.
+%    \begin{macrocode}
+  \@@_extract_and_handle_marks:nnn
+%    \end{macrocode}
+%    If we can extract them (i.e., if we don't detect negative infinite
+%    glue) then this is done with \cs{@@_get_from_splitmarks:} otherwise
+%    we issue warning that mark extraction was not possible.
+%    \begin{macrocode}
+     { \@@_get_from_splitmarks: }
+     { \msg_warning:nn { mark } { infinite-shrinkage-box } }
+     { #1 }
+%    \end{macrocode}
+%    finally we copy the updated (or not updated) tmp token lists to
+%    the two that have been supplied when the function was called.
+%    By convention they are local variables and
+%    \cs{@@_extract_and_handle_marks:nnn} runs in a group, which is
+%    why we have to use global variables for collecting.
+%    \begin{macrocode}
+  \tl_set_eq:NN #2 \g_@@_first_marks_tl
+  \tl_set_eq:NN #3 \g_@@_last_marks_tl
+}
+%    \end{macrocode}
+%  \end{macro}
+%
+%
+%  \begin{macro}{\@@_get_from_splitmarks:}
+%    This function is called after we have done a \cs{vsplit} to
+%    update the split marks. It loops through all mark classes to find
+%    out if there are marks for this class and if so updates the
+%    global tls used for collecting.
+%    \begin{macrocode}
+\cs_new_protected:Npn  \@@_get_from_splitmarks:  {
+  \seq_map_inline:Nn \g_@@_classes_seq
+            {
+%    \end{macrocode}
+%    First we to get the last last mark for the current class from the
+%    material supplied.
+%    \begin{macrocode}
+              \tl_gset:No \g_@@_tmp_tl
+                { \tex_splitbotmarks:D \use:c { c_@@_class_##1_mark } }
+%    \end{macrocode}
+%    
+%    If this mark doesn't exist then obviously first mark doesn't
+%    either, so we do nothing (other than issuing some debugging
+%    info). We have to be a little careful here: something like
+%    \verb=\mark_insert:nn{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 fully empty. This
+%    is why we have to make sure that \enquote{empty} from
+%    \cs{mark_insert:nn} only appears to be empty but fails the next
+%    test (see below how this is done).
+%    \begin{macrocode}
+              \tl_if_empty:NTF \g_@@_tmp_tl
+                {
+%<*trace>
+                  \@@_debug:n { \iow_term:x { Marks:~no~ marks~
+                      for~ class~ '##1'~\msg_line_context: } }
+%</trace>
+                }
+%    \end{macrocode}
+%    
+%    If it wasn't empty, i.e., if it had a real value then we use this
+%    value for our new last mark instead. This means we put an
+%    appropriate \cs{mark_insert:nn} statement into
+%    \cs{g_@@_last_marks_tl}.
+%    \begin{macrocode}
+                {
+%<*trace>
+                  \@@_debug:n { \iow_term:x { Marks:~ extract~ last~
+                       mark~ for~ class~ '##1'~ =~  \g_@@_tmp_tl } }
+%</trace>
+                  \tl_gput_right:Ne \g_@@_last_marks_tl
+                     { \mark_insert:nn {##1} { \g_@@_tmp_tl } }
+%    \end{macrocode}
+%    Because we had a last mark we also have a first mark (which might
+%    be the same, but might be not), so we pick that up and add it to
+%    the \cs{g_@@_first_marks_tl} token list. This explains why we
+%    first checked for the last mark because that makes the processing
+%    faster in case there is none.
+%    \begin{macrocode}
+%<*trace>
+                  \@@_debug:n { \iow_term:x { Marks:~ extract~ first~
+                      mark~ for~ class~ '##1'~ =~
+                      \tex_splitfirstmarks:D
+                        \use:c { c_@@_class_##1_mark }
+                  } }
+%</trace>
+                  \tl_gput_right:Ne \g_@@_first_marks_tl
+                     { \mark_insert:nn {##1}
+                       {
+                         \tex_splitfirstmarks:D
+                         \use:c { c_@@_class_##1_mark }
+                       }
+                     }
+                }
+            }
+}
+%    \end{macrocode}
+%  \end{macro}
+%
+%
+%  \begin{macro}{\g_@@_first_marks_tl,\g_@@_last_marks_tl}
+%    The two global variables used in the code above.
+%    \begin{macrocode}
+\tl_new:N  \g_@@_first_marks_tl
+\tl_new:N  \g_@@_last_marks_tl
+%    \end{macrocode}
+%  \end{macro}
+%
 %
 %  \begin{macro}{\@@_update_structure_alias:nn}
 %    This function copies the structure for one region to  another
@@ -1220,7 +1420,7 @@
 %    To retrieve the first, last or top region mark, we grab the
 %    appropriate value stored in the corresponding token list variable
 %    and pass its contents back. These functions should be used only
-%    in output routines after \cs{@@_update_structure:nn} has acted,
+%    in output routines after \cs{@@_update_structure_from_material:nn} has acted,
 %    otherwise their value will be wrong.
 %
 %    If used with an unknown class or region they generate an error
@@ -1310,17 +1510,28 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\msg_new:nnnn { mark } { infinite-shrinkage }
-  { Infinite~shrinkage~found~in~'#1'. }
+\msg_new:nnnn { mark } { infinite-shrinkage-region }
+  { Infinite~shrinkage~found~in~'#1'~region. }
   {
     \c__msg_coding_error_text_tl
     The~mark~region~'#1'~contains~some~infinite~negative~glue~
-    allowing~it~to~shrink~to~an~arbitrary~size.~
+    allowing~it~to~shrink~to~an~arbitrarily~small~size.~
     This~makes~it~impossible~to~split~the~region~apart~to~
     get~at~its~marks.~They~are~lost.
   }
 %    \end{macrocode}
 %
+%    If box content checked for marks contains some infinite negative glue 
+%    allowing it to shrink to an arbitrarily small size we can't extract any marks. 
+%    They are lost, but this should not generate an error because in
+%    certain places, e.g., in some \env{minipage}s such glue might be legitimate.
+%    \begin{macrocode}
+\msg_new:nnn { mark } { infinite-shrinkage-box }
+ { Infinite~shrinkage~found~in~box~material~--~marks~not~extracted~
+   \msg_line_context:
+ }
+%    \end{macrocode}
+%
 %
 %
 % \subsection{Debugging the mark structures}
@@ -1525,11 +1736,11 @@
 %    \begin{macrocode}
   \box_if_vertical:NTF \@outputbox
       {
-        \@@_update_structure:nn {page}
+        \@@_update_structure_from_material:nn {page}
            { \vbox_unpack:N  \@outputbox }
       }
       {
-        \@@_update_structure:nn {page}
+        \@@_update_structure_from_material:nn {page}
            { \hbox_unpack:N  \@outputbox }
       }
 %    \end{macrocode}
@@ -1569,11 +1780,11 @@
 %    \begin{macrocode}
   \box_if_vertical:NTF \@outputbox
       {
-        \@@_update_structure:nn {column}
+        \@@_update_structure_from_material:nn {column}
            { \vbox_unpack:N  \@outputbox }
       }
       {
-        \@@_update_structure:nn {column}
+        \@@_update_structure_from_material:nn {column}
            { \hbox_unpack:N  \@outputbox }
       }
 %    \end{macrocode}
diff --git a/base/testfiles-ltmarks/xmarks-009.lvt b/base/testfiles-ltmarks/xmarks-009.lvt
index da7afbf1..5e19b8c7 100644
--- a/base/testfiles-ltmarks/xmarks-009.lvt
+++ b/base/testfiles-ltmarks/xmarks-009.lvt
@@ -7,6 +7,9 @@
 
 \DebugMarksOn
 
+\NewMarkClass{unused}
+
+
 \begin{document}
 \START
 
@@ -14,7 +17,7 @@
 
 \ExplSyntaxOn
 
-\__mark_update_structure:nn{page}
+\__mark_update_structure_from_material:nn{page}
    {text\markright{A} \par
    \break
     text\markright{B} \par
@@ -27,6 +30,57 @@
 
 \ShowMarksAt{after mark extraction}
 
+\ExplSyntaxOn
+
+\__mark_update_structure_from_material:nn{page}
+   {text\markright{D} \par
+   \break
+    text\markright{E} \par
+   \vskip 0pt minus 1fil\relax
+    text\markright{F} \par
+   }
+
+\ExplSyntaxOff
+
+\ShowMarksAt{after material with infinite glue}
+
+
+\ExplSyntaxOn
+
+\tl_new:N \l_first_marks_tl
+\tl_new:N \l_last_marks_tl
+
+\__mark_get_marks_for_reinsertion:nNN
+   {
+     text\markboth{A1}{A2} \par
+   \break
+     text\markboth{B1}{B2} \par
+   \break
+     text\markright{A3} \par
+   }
+   \l_first_marks_tl
+   \l_last_marks_tl
+
+
+\tl_show:N \l_first_marks_tl
+\tl_show:N \l_last_marks_tl
+
+\__mark_get_marks_for_reinsertion:nNN
+   {
+     text\markboth{A1}{A2} \par
+   \break
+     text\markboth{B1}{B2} \par
+   \vskip 0pt minus 1fil\relax
+     text\markright{A3} \par
+   }
+   \l_first_marks_tl
+   \l_last_marks_tl
+
+
+\tl_show:N \l_first_marks_tl
+\tl_show:N \l_last_marks_tl
+
+\ExplSyntaxOff
 
 
 \newpage
diff --git a/base/testfiles-ltmarks/xmarks-009.tlg b/base/testfiles-ltmarks/xmarks-009.tlg
index 1f2414b0..2a032472 100644
--- a/base/testfiles-ltmarks/xmarks-009.tlg
+++ b/base/testfiles-ltmarks/xmarks-009.tlg
@@ -21,6 +21,13 @@ Marks: 2e-right-nonempty before mark extraction:
     column (current):||||
     column (first):||||
     column (second):||||
+Marks: unused before mark extraction:
+    page (current):||||
+    page (previous):||||
+    column (previous):||||
+    column (current):||||
+    column (first):||||
+    column (second):||||
 Marks: set 2e-right <- 'A' on line ...
 Marks: set 2e-right-nonempty <- 'A' on line ...
 Marks: set 2e-right <- 'B' on line ...
@@ -50,3 +57,93 @@ Marks: 2e-right-nonempty after mark extraction:
     column (current):||||
     column (first):||||
     column (second):||||
+Marks: unused after mark extraction:
+    page (current):||||
+    page (previous):||||
+    column (previous):||||
+    column (current):||||
+    column (first):||||
+    column (second):||||
+Marks: set 2e-right <- 'D' on line ...
+Marks: set 2e-right-nonempty <- 'D' on line ...
+Marks: set 2e-right <- 'E' on line ...
+Marks: set 2e-right-nonempty <- 'E' on line ...
+Marks: set 2e-right <- 'F' on line ...
+Marks: set 2e-right-nonempty <- 'F' on line ...
+! LaTeX mark Error: Infinite shrinkage found in 'page' region.
+For immediate help type H <return>.
+ ...                                              
+l. ...   }
+This is a coding error.
+The mark region 'page' contains some infinite negative glue allowing it to
+shrink to an arbitrarily small size. This makes it impossible to split the
+region apart to get at its marks. They are lost.
+Marks: 2e-left after material with infinite glue:
+    page (current):||||
+    page (previous):||||
+    column (previous):||||
+    column (current):||||
+    column (first):||||
+    column (second):||||
+Marks: 2e-right after material with infinite glue:
+    page (current):|C|C|C|
+    page (previous):||||
+    column (previous):||||
+    column (current):||||
+    column (first):||||
+    column (second):||||
+Marks: 2e-right-nonempty after material with infinite glue:
+    page (current):|C|C|C|
+    page (previous):||||
+    column (previous):||||
+    column (current):||||
+    column (first):||||
+    column (second):||||
+Marks: unused after material with infinite glue:
+    page (current):||||
+    page (previous):||||
+    column (previous):||||
+    column (current):||||
+    column (first):||||
+    column (second):||||
+Marks: set 2e-left <- 'A1' on line ...
+Marks: set 2e-right <- 'A2' on line ...
+Marks: set 2e-right-nonempty <- 'A2' on line ...
+Marks: set 2e-left <- 'B1' on line ...
+Marks: set 2e-right <- 'B2' on line ...
+Marks: set 2e-right-nonempty <- 'B2' on line ...
+Marks: set 2e-right <- 'A3' on line ...
+Marks: set 2e-right-nonempty <- 'A3' on line ...
+Marks: mark extraction needs recursion on line ...
+Marks: mark extraction needs recursion on line ...
+Marks: extract last mark for class '2e-left' = B1
+Marks: extract first mark for class '2e-left' = A1
+Marks: extract last mark for class '2e-right' = A3
+Marks: extract first mark for class '2e-right' = A2
+Marks: extract last mark for class '2e-right-nonempty' = A3
+Marks: extract first mark for class '2e-right-nonempty' = A2
+Marks: no marks for class 'unused' on line ...
+> \l_first_marks_tl=\mark_insert:nn {2e-left}{A1}\mark_insert:nn
+{2e-right}{A2}\mark_insert:nn {2e-right-nonempty}{A2}.
+<recently read> }
+l. ...\tl_show:N \l_first_marks_tl
+> \l_last_marks_tl=\mark_insert:nn {2e-left}{B1}\mark_insert:nn
+{2e-right}{A3}\mark_insert:nn {2e-right-nonempty}{A3}.
+<recently read> }
+l. ...\tl_show:N \l_last_marks_tl
+Marks: set 2e-left <- 'A1' on line ...
+Marks: set 2e-right <- 'A2' on line ...
+Marks: set 2e-right-nonempty <- 'A2' on line ...
+Marks: set 2e-left <- 'B1' on line ...
+Marks: set 2e-right <- 'B2' on line ...
+Marks: set 2e-right-nonempty <- 'B2' on line ...
+Marks: set 2e-right <- 'A3' on line ...
+Marks: set 2e-right-nonempty <- 'A3' on line ...
+LaTeX mark Warning: Infinite shrinkage found in box material -- marks not
+(mark)              extracted on line ...
+> \l_first_marks_tl=.
+<recently read> }
+l. ...\tl_show:N \l_first_marks_tl
+> \l_last_marks_tl=.
+<recently read> }
+l. ...\tl_show:N \l_last_marks_tl





More information about the latex3-commits mailing list.