diff options
Diffstat (limited to 'macros/latex-dev/required/latex-lab')
37 files changed, 2199 insertions, 148 deletions
diff --git a/macros/latex-dev/required/latex-lab/README.md b/macros/latex-dev/required/latex-lab/README.md index 2b86c4d5ee..046d498ab8 100644 --- a/macros/latex-dev/required/latex-lab/README.md +++ b/macros/latex-dev/required/latex-lab/README.md @@ -1,6 +1,6 @@ # LaTeX laboratory -Release 2023-11-01 pre-release 1 +Release 2024-06-01 pre-release 0 ## Overview diff --git a/macros/latex-dev/required/latex-lab/blocks-code.pdf b/macros/latex-dev/required/latex-lab/blocks-code.pdf Binary files differindex 7b3c18298f..ff13361fcc 100644 --- a/macros/latex-dev/required/latex-lab/blocks-code.pdf +++ b/macros/latex-dev/required/latex-lab/blocks-code.pdf diff --git a/macros/latex-dev/required/latex-lab/blocks-doc.pdf b/macros/latex-dev/required/latex-lab/blocks-doc.pdf Binary files differindex 4e0408b361..a0f0e5dfad 100644 --- a/macros/latex-dev/required/latex-lab/blocks-doc.pdf +++ b/macros/latex-dev/required/latex-lab/blocks-doc.pdf diff --git a/macros/latex-dev/required/latex-lab/changes.txt b/macros/latex-dev/required/latex-lab/changes.txt index e447d8130a..1a65830e8b 100644 --- a/macros/latex-dev/required/latex-lab/changes.txt +++ b/macros/latex-dev/required/latex-lab/changes.txt @@ -1,3 +1,18 @@ +2023-10-30 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * added latex-lab-table.dtx for basic table tagging. + +2023-10-21 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * latex-lab-minipage.dtx: use sockets to allow local changes + +2023-10-13 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * latex-lab-toc.dtx, latex-lab-sec.dtx, latex-lab-toc-kernel-changes: extend + \MakeLinkTarget to store the target-structure relationship too, see tagging issue #20 + +2023-10-13 Ulrike Fischer <Ulrike.Fischer@latex-project.org> + * latex-lab-graphic.dtx: fix handling of scale factor, tagging issue #16 + * latex-lab-graphic.dtx, latex-lab-footnote.dtx: switch to new property referencing code. + * latex-lab-math.dtx: fix grabbing of \(..\), tagging issue #19 + 2023-09-04 Ulrike Fischer <Ulrike.Fischer@latex-project.org> * latex-lab-math.dtx: fix below display skip, tagging issue #11 * latex-lab-math.dtx: allow to use it without tagging. diff --git a/macros/latex-dev/required/latex-lab/documentmetadata-support-code.pdf b/macros/latex-dev/required/latex-lab/documentmetadata-support-code.pdf Binary files differindex ed38483aec..e7e0823f1e 100644 --- a/macros/latex-dev/required/latex-lab/documentmetadata-support-code.pdf +++ b/macros/latex-dev/required/latex-lab/documentmetadata-support-code.pdf diff --git a/macros/latex-dev/required/latex-lab/documentmetadata-support-doc.pdf b/macros/latex-dev/required/latex-lab/documentmetadata-support-doc.pdf Binary files differindex d05aca93d9..af93980113 100644 --- a/macros/latex-dev/required/latex-lab/documentmetadata-support-doc.pdf +++ b/macros/latex-dev/required/latex-lab/documentmetadata-support-doc.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-amsmath.pdf b/macros/latex-dev/required/latex-lab/latex-lab-amsmath.pdf Binary files differindex d47e09867f..9c0073d19d 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-amsmath.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-amsmath.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-bib.pdf b/macros/latex-dev/required/latex-lab/latex-lab-bib.pdf Binary files differindex 153923a871..59569a1735 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-bib.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-bib.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-block.dtx b/macros/latex-dev/required/latex-lab/latex-lab-block.dtx index 3bd06b72c8..e0a723ca87 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-block.dtx +++ b/macros/latex-dev/required/latex-lab/latex-lab-block.dtx @@ -2314,7 +2314,7 @@ % \end{macrocode} % \end{variable} % -% \begin{macro}{\@@_make_label_box:n, \@@_label_format:x} +% \begin{macro}{\@@_make_label_box:n, \@@_label_format:e} % Make one label, wrapped in \cs{@@_label_format:n}, with an % appropriate \tn{strut} and possibly \tn{makelabel} in compatibility % mode (used for the \env{list} environment). diff --git a/macros/latex-dev/required/latex-lab/latex-lab-block.pdf b/macros/latex-dev/required/latex-lab/latex-lab-block.pdf Binary files differindex b82beb2684..7cd08195e3 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-block.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-block.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-firstaid.pdf b/macros/latex-dev/required/latex-lab/latex-lab-firstaid.pdf Binary files differindex 23b2d0d97d..578d70101e 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-firstaid.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-firstaid.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-float.pdf b/macros/latex-dev/required/latex-lab/latex-lab-float.pdf Binary files differindex 6cf52778ba..1af101107f 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-float.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-float.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-footnotes.dtx b/macros/latex-dev/required/latex-lab/latex-lab-footnotes.dtx index f62d12bfd9..2389906c5a 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-footnotes.dtx +++ b/macros/latex-dev/required/latex-lab/latex-lab-footnotes.dtx @@ -899,8 +899,6 @@ % \subsection{Variants} % % \begin{macrocode} -\cs_generate_variant:Nn \ref_value:nn { Vn } -\cs_generate_variant:Nn \prop_gput:Nnn {cxn} \cs_generate_variant:Nn \hook_gput_code:nnn{nne} \cs_generate_variant:Nn \tag_struct_use:n {e} % \end{macrocode} @@ -1711,14 +1709,14 @@ % At first we define a suitable attribute, it uses as value the structure % number of the note as stored in \cs{l__fnote_currentstruct_tl} % \begin{macrocode} -\ref_attribute_gset:nnnn {fnote/struct}{1}{now}{\l_@@_currentstruct_tl} +\property_new:nnnn {fnote/struct}{now}{1}{\l_@@_currentstruct_tl} % \end{macrocode} % % We add a hook to the label hook. By default it does nothing -% \begin{macro}{\@@_label_hook:n} +% \begin{macro}{\@@_label_hook:e} % \begin{macrocode} -\cs_new_protected:Npn \@@_label_hook:n #1 {} -\AddToHookWithArguments{label}{ \@@_label_hook:n{#1}} +\cs_new_protected:Npn \@@_label_hook:e #1 {} +\AddToHookWithArguments{label}{ \@@_label_hook:e{#1}} % \end{macrocode} % \end{macro} % Inside a footnotetext we change the hook to store the structure number too. @@ -1726,9 +1724,9 @@ % \begin{macrocode} \AddToHook{fntext/begin} { - \cs_set_protected:Npn \@@_label_hook:n #1 + \cs_set_protected:Npn \@@_label_hook:e #1 { - \ref_label:nn {#1} {fnote/struct} + \property_record:ee {@@/#1} {fnote/struct} } } % \end{macrocode} @@ -1766,7 +1764,7 @@ % \begin{macrocode} \cs_new_protected:Npn \fnote_mark_gput:nn #1 #2 % #1 the representation of the mark, #2 type { - \prop_gput:cxn { g_@@_currentmarks_ #2 _prop } + \prop_gput:cen { g_@@_currentmarks_ #2 _prop } { \tag_get:n{struct_num} } { #1 } } @@ -1839,7 +1837,7 @@ % which means the name of the prop shouldn't be fix. % \begin{macrocode} \fnote_mark_gput:oo {\@thefnmark}{\l_fnote_type_tl} - \tl_set:Nx \l_@@_linktarget_tl {footnote*.\tag_get:n{struct_num}} + \tl_set:Ne \l_@@_linktarget_tl {footnote*.\tag_get:n{struct_num}} } % \end{macrocode} % If there is no autodetecting we need some id, @@ -1854,13 +1852,13 @@ { \exp_not:N\fnote_gput_refs:ee { \tag_get:n{struct_num} } - { \ref_value:Vn\l_@@_currentlabel_tl {fnote/struct} } + { \property_ref:ee{ @@/\l_@@_currentlabel_tl } {fnote/struct} } } % \end{macrocode} % in this case we set the name of the linktarget in the note % to the structure number of the text mark. % \begin{macrocode} - \tl_set:Nx \l_@@_linktarget_tl {footnote*.\ref_value:Vn\l_@@_currentlabel_tl {fnote/struct}} + \tl_set:Ne \l_@@_linktarget_tl {footnote*.\property_ref:ee {@@/\l_@@_currentlabel_tl} {fnote/struct}} } % \end{macrocode} % And now the actual content @@ -1938,7 +1936,7 @@ % \end{macrocode} % Store the current structure number for labels. % \begin{macrocode} - \tl_set:Nx \l_@@_currentstruct_tl { \tag_get:n{struct_num} } + \tl_set:Ne \l_@@_currentstruct_tl { \tag_get:n{struct_num} } % \end{macrocode} % We want to move the label structure here. So we provide a container % It number is |\l__fnote_currentstruct_tl| plus 1. diff --git a/macros/latex-dev/required/latex-lab/latex-lab-footnotes.pdf b/macros/latex-dev/required/latex-lab/latex-lab-footnotes.pdf Binary files differindex 6736fc5132..e0b8bc5580 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-footnotes.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-footnotes.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-graphic.dtx b/macros/latex-dev/required/latex-lab/latex-lab-graphic.dtx index 1db0277425..158b0d2a9c 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-graphic.dtx +++ b/macros/latex-dev/required/latex-lab/latex-lab-graphic.dtx @@ -15,8 +15,8 @@ % https://github.com/latex3/latex2e/required/latex-lab % % for those people who are interested or want to report an issue. -\def\ltlabgraphicdate{2023-07-20} -\def\ltlabgraphicversion{0.80a} +\def\ltlabgraphicdate{2023-10-13} +\def\ltlabgraphicversion{0.80b} % %<*driver> \documentclass{l3doc} @@ -184,25 +184,16 @@ \RequirePackage{l3opacity} % \end{macrocode} % -%\subsection{Saving the position} -% We need a replacement for zref-savepos. This uses l3ref which loaded -% by the pdfmanagement/tagpdf. % -% TODO: this is perhaps needed in other places too and should be moved to -% l3ref!! -% \begin{macrocode} -\ref_attribute_gset:nnnn{xpos}{0}{shipout}{\int_use:N\tex_lastxpos:D} -\ref_attribute_gset:nnnn{ypos}{0}{shipout}{\int_use:N\tex_lastypos:D} -% \end{macrocode} - % \begin{macro}{\@@_graphic_savepos:n} -% this is the command which stores the position. It uses -% two savepos in case bidi needs it (see zref-savepos). +% this is the command which stores the position. Similar to +% zref-savepos it uses two savepos commands +% for the case that bidi changes the processing order. % \begin{macrocode} \cs_new_protected:Npn\@@_graphic_savepos:n #1 { \tex_savepos:D - \ref_label:nn{#1}{xpos,ypos,abspage} + \property_record:nn{#1}{xpos,ypos,abspage} \tex_savepos:D } \cs_generate_variant:Nn \@@_graphic_savepos:n {e} @@ -310,8 +301,7 @@ \fp_new:N\l_@@_graphic_lx_fp \fp_new:N\l_@@_graphic_uy_fp % \end{macrocode} -% this holds the scale value. Currently this only the one from -% \cs{Gin@scalex} +% this holds the scale value. Either \cs{Gin@scalex} or (if that is !) \cs{Gin@scaley} % \begin{macrocode} \fp_new:N\l_@@_graphic_scale_fp % \end{macrocode} @@ -353,8 +343,8 @@ { \tl_if_empty:NT\l_@@_graphic_alt_tl { - \msg_warning:nnx{tag}{alt-text-missing}{\l_@@_graphic_alt_dflt_tl} - \tl_set:Nx\l_@@_graphic_alt_tl {\l_@@_graphic_alt_dflt_tl} + \msg_warning:nne{tag}{alt-text-missing}{\l_@@_graphic_alt_dflt_tl} + \tl_set:Ne\l_@@_graphic_alt_tl {\l_@@_graphic_alt_dflt_tl} } \tag_struct_begin:n { @@ -470,7 +460,7 @@ % \begin{macrocode} \AddToHook{package/graphicx/after}[latex-lab] { - \define@key{Gin}{alt} {\tl_set:Nx\l_@@_graphic_alt_tl{\text_purify:n{#1}}} + \define@key{Gin}{alt} {\tl_set:Ne\l_@@_graphic_alt_tl{\text_purify:n{#1}}} \define@key{Gin}{artifact}[] { \bool_set_true:N \l_@@_graphic_artifact_bool @@ -478,7 +468,7 @@ } \define@key{Gin}{actualtext} { - \tl_set:Nx\l_@@_graphic_actual_tl{\text_purify:n{#1}} + \tl_set:Ne\l_@@_graphic_actual_tl{\text_purify:n{#1}} \bool_set_false:N \l_@@_graphic_BBox_bool } \define@key{Gin}{correct-BBox} @@ -509,7 +499,7 @@ \keys_define:nn{tag/picture} { ,alt .code:n = - {\tl_set:Nx\l_@@_graphic_alt_tl{\text_purify:n{#1}}} + {\tl_set:Ne\l_@@_graphic_alt_tl{\text_purify:n{#1}}} ,artifact .code:n = { \bool_set_true:N \l_@@_graphic_artifact_bool @@ -517,7 +507,7 @@ } ,actualtext .code:n = { - \tl_set:Nx\l_@@_graphic_actual_tl{\text_purify:n{#1}} + \tl_set:Ne\l_@@_graphic_actual_tl{\text_purify:n{#1}} \bool_set_false:N \l_@@_graphic_BBox_bool } ,correct-BBox .code:n = @@ -581,7 +571,12 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_graphic_get_scale: { - \fp_set:Nn \l_@@_graphic_scale_fp { \Gin@scalex } + \fp_set:Nn \l_@@_graphic_scale_fp + { + \str_if_eq:eeTF {\Gin@scalex} { ! } + { \Gin@scaley } + { \Gin@scalex } + } } % \end{macrocode} % \end{macro} @@ -636,7 +631,7 @@ (\l_@@_graphic_uy_fp-\l_@@_graphic_ly_fp-\l_@@_graphic_trim_ly_fp) * (-\l_@@_graphic_sin_fp) } - \tl_gset:Nx\g_@@_graphic_lx_tl + \tl_gset:Ne\g_@@_graphic_lx_tl { \fp_eval:n { @@ -651,7 +646,7 @@ +\l_@@_graphic_trim_lx_fp } } - \tl_gset:Nx\g_@@_graphic_ux_tl + \tl_gset:Ne\g_@@_graphic_ux_tl { \fp_eval:n { @@ -695,7 +690,7 @@ (\l_@@_graphic_uy_fp-\l_@@_graphic_ly_fp-\l_@@_graphic_trim_ly_fp) * \l_@@_graphic_cos_fp } - \tl_gset:Nx\g_@@_graphic_ly_tl + \tl_gset:Ne\g_@@_graphic_ly_tl { \fp_eval:n { @@ -709,7 +704,7 @@ + \l_@@_graphic_ly_fp + \l_@@_graphic_trim_ly_fp } } - \tl_gset:Nx\g_@@_graphic_uy_tl + \tl_gset:Ne\g_@@_graphic_uy_tl { \fp_eval:n { @@ -735,7 +730,7 @@ { \bool_if:NT\l_@@_graphic_bboxcorr_bool { - \tl_set:Nx #1 + \tl_set:Ne #1 { \fp_eval:n { @@ -744,7 +739,7 @@ \dim_to_decimal_in_bp:n {\seq_item:Nn \l_@@_graphic_bboxcorr_seq {1} } } } - \tl_set:Nx #2 + \tl_set:Ne #2 { \fp_eval:n { @@ -753,7 +748,7 @@ \dim_to_decimal_in_bp:n {\seq_item:Nn \l_@@_graphic_bboxcorr_seq {2} } } } - \tl_set:Nx #3 + \tl_set:Ne #3 { \fp_eval:n { @@ -762,7 +757,7 @@ \dim_to_decimal_in_bp:n {\seq_item:Nn \l_@@_graphic_bboxcorr_seq {3} } } } - \tl_set:Nx #4 + \tl_set:Ne #4 { \fp_eval:n { @@ -791,22 +786,22 @@ {\l_@@_graphic_BBox_bool} } { - \fp_set:Nn \l_@@_graphic_scale_fp { \Gin@scalex } + \__tag_graphic_get_scale: \@@_graphic_get_trim: \int_gincr:N\g_@@_graphic_int - \tl_set:Nx\l_@@_graphic_currentlabel_tl {_@@_graphic_\int_use:N \g_@@_graphic_int} + \tl_set:Ne\l_@@_graphic_currentlabel_tl {_@@_graphic_\int_use:N \g_@@_graphic_int} \@@_graphic_savepos:e { \l_@@_graphic_currentlabel_tl } - \tl_gset:Nx\g_@@_graphic_lx_tl + \tl_gset:Ne\g_@@_graphic_lx_tl { \dim_to_decimal_in_bp:n - { \@@_ref_value:enn {\l_@@_graphic_currentlabel_tl}{xpos}{0}sp } + { \property_ref:een {\l_@@_graphic_currentlabel_tl}{xpos}{0}sp } } - \tl_gset:Nx\g_@@_graphic_ly_tl + \tl_gset:Ne\g_@@_graphic_ly_tl { \dim_to_decimal_in_bp:n - { \@@_ref_value:enn {\l_@@_graphic_currentlabel_tl}{ypos}{0}sp } + { \property_ref:een {\l_@@_graphic_currentlabel_tl}{ypos}{0}sp } } - \tl_gset:Nx\g_@@_graphic_ux_tl + \tl_gset:Ne\g_@@_graphic_ux_tl { \fp_eval:n { @@ -815,7 +810,7 @@ \dim_to_decimal_in_bp:n { \Gin@req@width } } } - \tl_gset:Nx\g_@@_graphic_uy_tl + \tl_gset:Ne\g_@@_graphic_uy_tl { \fp_eval:n { @@ -829,7 +824,7 @@ % \begin{macrocode} \legacy_if:nF {Gin@clip} { - \tl_gset:Nx\g_@@_graphic_ux_tl + \tl_gset:Ne\g_@@_graphic_ux_tl { \fp_eval:n { @@ -838,7 +833,7 @@ \l_@@_graphic_trim_ux_fp } } - \tl_gset:Nx\g_@@_graphic_lx_tl + \tl_gset:Ne\g_@@_graphic_lx_tl { \fp_eval:n { @@ -847,7 +842,7 @@ \l_@@_graphic_trim_lx_fp } } - \tl_gset:Nx\g_@@_graphic_uy_tl + \tl_gset:Ne\g_@@_graphic_uy_tl { \fp_eval:n { @@ -856,7 +851,7 @@ \l_@@_graphic_trim_uy_fp } } - \tl_gset:Nx\g_@@_graphic_ly_tl + \tl_gset:Ne\g_@@_graphic_ly_tl { \fp_eval:n { @@ -934,26 +929,26 @@ } { \int_gincr:N\g_@@_graphic_int - \tl_set:Nx\l_@@_graphic_currentlabel_tl {_@@_graphic_\int_use:N \g_@@_graphic_int} + \tl_set:Ne\l_@@_graphic_currentlabel_tl {_@@_graphic_\int_use:N \g_@@_graphic_int} \@@_graphic_savepos:e { \l_@@_graphic_currentlabel_tl } - \tl_gset:Nx \g_@@_graphic_lx_tl + \tl_gset:Ne \g_@@_graphic_lx_tl { \dim_to_decimal_in_bp:n - { \@@_ref_value:enn {\l_@@_graphic_currentlabel_tl}{xpos}{0}sp } + { \property_ref:een {\l_@@_graphic_currentlabel_tl}{xpos}{0}sp } } - \tl_gset:Nx \g_@@_graphic_ly_tl + \tl_gset:Ne \g_@@_graphic_ly_tl { \dim_to_decimal_in_bp:n - { \@@_ref_value:enn {\l_@@_graphic_currentlabel_tl}{ypos}{0}sp - \dp\@picbox } + { \property_ref:een {\l_@@_graphic_currentlabel_tl}{ypos}{0}sp - \dp\@picbox } } - \tl_gset:Nx \g_@@_graphic_ux_tl + \tl_gset:Ne \g_@@_graphic_ux_tl { \dim_to_decimal_in_bp:n { \g_@@_graphic_lx_tl bp + \wd\@picbox } } - \tl_gset:Nx \g_@@_graphic_uy_tl + \tl_gset:Ne \g_@@_graphic_uy_tl { \dim_to_decimal_in_bp:n { @@ -1044,7 +1039,7 @@ \int_compare:nNnT {\g_shipout_readonly_int} = - {\@@_ref_value:enn{_@@_graphic_#6}{abspage}{0}} + {\property_ref:een{_@@_graphic_#6}{abspage}{0}} { \put (#1 bp,\dim_eval:n{-\paperheight + \dim_eval:n{#2 bp}}) diff --git a/macros/latex-dev/required/latex-lab/latex-lab-graphic.pdf b/macros/latex-dev/required/latex-lab/latex-lab-graphic.pdf Binary files differindex 03f3d0b3f5..bf57d1bd95 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-graphic.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-graphic.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-math.dtx b/macros/latex-dev/required/latex-lab/latex-lab-math.dtx index d593f93320..285471addc 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-math.dtx +++ b/macros/latex-dev/required/latex-lab/latex-lab-math.dtx @@ -164,8 +164,6 @@ % presumably)\\ % - Math environments created with \pkg{ltcmd} [commands] should not be copied, . . .\\ % - Package authors should be able to manually set up math environments with a public boolean.} -% -% \item % \end{enumerate} % % @@ -243,6 +241,8 @@ % Or do we need an extra storage tl?} % % \begin{variable}{\g_@@_grabbed_env_tl, \g_@@_grabbed_math_tl} +% \cs{g_@@_grabbed_env_tl} contains the name of the math environment (\texttt{math} in the case +% of inline math, \cs{g_@@_grabbed_math_tl} the math content. % \begin{macrocode} \tl_new:N \g_@@_grabbed_env_tl \tl_new:N \g_@@_grabbed_math_tl @@ -312,8 +312,9 @@ % fairly simple this one % \end{macrocode} % We do not want math tagging in fakemath or when measuring, -% so we imitate the test inside -% \cs{@@_process:nn} for now, see https://github.com/latex3/tagging-project/issues/5 +% so we imitate the test inside \cs{@@_process:nn} for now, +% see https://github.com/latex3/tagging-project/issues/5 +% TODO: use socket to get more control about typesetting variants (tagged, drop etc)? % \begin{macrocode} \legacy_if:nTF { measuring@ } { #1 $ } @@ -327,8 +328,7 @@ \@kernel@math@end \tagmcbegin{} % restart P-chunk (whatsits in pdftex) } - } - + } } } % \end{macrocode} @@ -715,7 +715,6 @@ { $ } } { - \bool_set_true:N \l_@@_collected_bool \@@_grab_inline:w } } % \( @@ -796,16 +795,16 @@ \tl_gset:Nx\tmpmathcontent { LaTeX~ formula~ starts~ - \exp_not:N\begin{\g__math_grabbed_env_tl} + \exp_not:N\begin{\g_@@_grabbed_env_tl} \space - \exp_not:V\g__math_grabbed_math_tl + \exp_not:V\g_@@_grabbed_math_tl \space - \exp_not:N\end{\g__math_grabbed_env_tl} + \exp_not:N\end{\g_@@_grabbed_env_tl} \space LaTeX~ formula~ ends~ } \tagstructbegin{tag=Formula, AFinline-o=\tmpmathcontent, - title-o=\g__math_grabbed_env_tl, + title-o=\g_@@_grabbed_env_tl, actualtext=\tmpmathcontent % alt=\tmpmathcontent } @@ -1220,10 +1219,10 @@ \tl_new:N \result \cs_new_protected:Npn\grabaformulapartandstart { - \@@_split_at_nl:NN \g__math_grabbed_math_tl \result + \@@_split_at_nl:NN \g_@@_grabbed_math_tl \result \typeout{====>first-result=\meaning\result} - \typeout{====>first-tmpmathcontent=\meaning\g__math_grabbed_math_tl} - \tl_if_empty:NTF \g__math_grabbed_math_tl + \typeout{====>first-tmpmathcontent=\meaning\g_@@_grabbed_math_tl} + \tl_if_empty:NTF \g_@@_grabbed_math_tl { \typeout{====>formula~ has~ no~ subparts} \global\@subformulasfalse @@ -1231,7 +1230,7 @@ { \typeout{====>formula~ has~ subparts} \global\@subformulastrue - \edef\resulttitle{\g__math_grabbed_env_tl\space (part)} + \edef\resulttitle{\g_@@_grabbed_env_tl\space (part)} \tagstructbegin{tag=Formula, % \end{macrocode} % For now we don't put anything in /alt or /ActualText on subformulas @@ -1244,16 +1243,16 @@ } \cs_new_protected:Npn\grabaformulapartandmayberestart { - \@@_split_at_nl:NN \g__math_grabbed_math_tl \result + \@@_split_at_nl:NN \g_@@_grabbed_math_tl \result \typeout{====>result=\meaning\result} - \typeout{====>tmpmathcontent=\meaning\g__math_grabbed_math_tl} -% \tl_if_empty:NTF \g__math_grabbed_math_tl + \typeout{====>tmpmathcontent=\meaning\g_@@_grabbed_math_tl} +% \tl_if_empty:NTF \g_@@_grabbed_math_tl % { % \typeout{====>tmpmathcontent=empty} % } % { % \typeout{====>tmpmathcontent=not-empty} - \edef\resulttitle{\g__math_grabbed_env_tl\space (part)} + \edef\resulttitle{\g_@@_grabbed_env_tl\space (part)} \tagstructbegin{tag=Formula, alt=\result, title-o=\resulttitle @@ -1272,7 +1271,7 @@ \if@subformulas \ifmeasuring@\else % - \tl_if_empty:NF \g__math_grabbed_math_tl + \tl_if_empty:NF \g_@@_grabbed_math_tl { \tagmcend \tagstructend diff --git a/macros/latex-dev/required/latex-lab/latex-lab-math.pdf b/macros/latex-dev/required/latex-lab/latex-lab-math.pdf Binary files differindex f68397d94a..deab5ad914 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-math.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-math.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-mathpkg.pdf b/macros/latex-dev/required/latex-lab/latex-lab-mathpkg.pdf Binary files differindex a8c65f5f9c..dbfcb0815b 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-mathpkg.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-mathpkg.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-mathtools.pdf b/macros/latex-dev/required/latex-lab/latex-lab-mathtools.pdf Binary files differindex 8dec843fe9..97026901d6 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-mathtools.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-mathtools.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-minipage.dtx b/macros/latex-dev/required/latex-lab/latex-lab-minipage.dtx index bbd40a3c52..1d3ee828aa 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-minipage.dtx +++ b/macros/latex-dev/required/latex-lab/latex-lab-minipage.dtx @@ -16,8 +16,8 @@ % % for those people who are interested or want to report an issue. % -\def\ltlabminipagedate{2023-08-20} -\def\ltlabminipageversion{0.81b} +\def\ltlabminipagedate{2023-10-30} +\def\ltlabminipageversion{0.81c} %<*driver> \documentclass{l3doc} \EnableCrossrefs @@ -49,12 +49,21 @@ % % \section{Introduction} % -% How to tag minipages and parboxes is still under discussion. +% How to best tag minipages and parboxes is still under discussion. % But as they start and contain paragraphs it is clear that -% hooks are needed to interrupt and restart the tagging. +% some sockets are needed to interrupt and restart the tagging. % -% The tagging added is currently quite simple minded. See the todo-testfiles and the -% code comments for some open points. +% The tagging added is currently quite simple-minded. See the +% todo-testfiles and the code comments for some open points. +% +% One of the main problems is how to properly embed them in the +% surrounding. When used in normal text (in a paragraph) they +% typically should close the \texttt{text} structure and reopen one +% at the end. But when used inside low-level \cs{vbox} or \cs{hbox} +% this is often wrong. The code uses now there two sockets +% \texttt{tagsupport/parbox/before} and +% \texttt{tagsupport/parbox/after} which can be set to noop, if +% necessary. % % \begin{macrocode} %<*package> @@ -82,12 +91,13 @@ \def\@kernel@init@minipage{} \def\@kernel@init@parbox{} % \end{macrocode} -% We need a few hooks. +% We use sockets for the tag support code, as there will be cases where we want +% to exchange the content or disable it. % \begin{macrocode} -\def\@kernel@before@minipage{} -\def\@kernel@after@minipage{} -\def\@kernel@before@parbox{} -\def\@kernel@after@parbox{} +\socket_new:nn {tagsupport/minipage/before}{0} +\socket_new:nn {tagsupport/minipage/after} {0} +\socket_new:nn {tagsupport/parbox/before} {0} +\socket_new:nn {tagsupport/parbox/after}{0} % \end{macrocode} % % \subsection{Patch minipage} @@ -106,16 +116,16 @@ \setlength\@tempdima{#4}% \def\@mpargs{{#1}{#2}[#3]{#4}}% % \end{macrocode} -% insert the hook +% insert the socket % \begin{macrocode} - \@kernel@before@minipage% new + \socket_use:n{tagsupport/minipage/before}% new \setbox\@tempboxa\vbox\bgroup \color@begingroup \hsize\@tempdima \textwidth\hsize \columnwidth\hsize \@parboxrestore \def\@mpfn{mpfootnote}\def\thempfn{\thempfootnote}\c@mpfootnote\z@ - \AssignSocketPlug{fntext/process}{mp}% + \socket_assign_plug:nn{fntext/process}{mp}% \let\@listdepth\@mplistdepth \@mplistdepth\z@ \@minipagerestore \@setminipage} @@ -135,13 +145,13 @@ \color@endgroup \egroup % \end{macrocode} -% as the parbox command is called, we must prevent that it adds its additional -% tagging commands: +% As the parbox command is called, we must prevent that it adds its +% additional tagging commands: % \begin{macrocode} \tag_stop:n{minipage} \expandafter\@iiiparbox\@mpargs{\unvbox\@tempboxa}% \tag_start:n{minipage} - \@kernel@after@minipage%new end ... + \socket_use:n{tagsupport/minipage/after} %new end ... } % \end{macrocode} % @@ -152,7 +162,7 @@ \leavevmode \@pboxswfalse \setlength\@tempdima{#4}% - \@kernel@before@parbox% new + \socket_use:n{tagsupport/parbox/before} \@begin@tempboxa\vbox{\hsize\@tempdima\@parboxrestore#5\@@par}% \ifx\relax#2\else \setlength\@tempdimb{#2}% @@ -167,7 +177,7 @@ \csname bm@#3\endcsname}% \if@pboxsw \m@th$\fi \@end@tempboxa% - \@kernel@after@parbox%new end + \socket_use:n{tagsupport/parbox/after} } % \end{macrocode} % @@ -176,7 +186,7 @@ % \begin{macrocode} \tl_new:N \l__ltboxes_tag_tl \tl_set:Nn \l__ltboxes_tag_tl {Div} -\cs_set_protected:Npn\@kernel@before@minipage +\socket_new_plug:nnn{tagsupport/minipage/before}{tag/dflt} { % \end{macrocode} % As there was a \cs{leavevmode} before that is a P/text open that we have to close. @@ -185,14 +195,27 @@ % \end{macrocode} % TODO: the P can be further up, we need a proper method to test and handle this. % \begin{macrocode} - \tag_struct_begin:n{tag=\l__ltboxes_tag_tl}} -\cs_set_protected:Npn\@kernel@after@minipage + \tag_struct_begin:n{tag=\l__ltboxes_tag_tl} + } +% \end{macrocode} +% similar for the other sockets: +% \begin{macrocode} +\socket_new_plug:nnn{tagsupport/minipage/after}{tag/dflt} {\tag_struct_end:\tag_struct_begin:n{tag=\l__tag_para_tag_tl}\tag_mc_begin_pop:n{}} -\cs_set_protected:Npn\@kernel@before@parbox + +\socket_new_plug:nnn{tagsupport/parbox/before}{tag/dflt} {\tag_mc_end_push:\tag_struct_end:\tag_struct_begin:n{tag=\l__ltboxes_tag_tl}} -\cs_set_protected:Npn\@kernel@after@parbox + +\socket_new_plug:nnn{tagsupport/parbox/after}{tag/dflt} {\tag_struct_end:\tag_struct_begin:n{tag=\l__tag_para_tag_tl}\tag_mc_begin_pop:n{}} % \end{macrocode} +% Activate the default tagging plug +% \begin{macrocode} +\socket_assign_plug:nn{tagsupport/minipage/before}{tag/dflt} +\socket_assign_plug:nn{tagsupport/minipage/after} {tag/dflt} +\socket_assign_plug:nn{tagsupport/parbox/before} {tag/dflt} +\socket_assign_plug:nn{tagsupport/parbox/after} {tag/dflt} +% \end{macrocode} % \begin{macrocode} %</package> % \end{macrocode} diff --git a/macros/latex-dev/required/latex-lab/latex-lab-minipage.pdf b/macros/latex-dev/required/latex-lab/latex-lab-minipage.pdf Binary files differindex ac235aef7d..c91e93f2fc 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-minipage.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-minipage.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-namespace.pdf b/macros/latex-dev/required/latex-lab/latex-lab-namespace.pdf Binary files differindex e0c02494ca..ff8e705be3 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-namespace.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-namespace.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-new-or-1.pdf b/macros/latex-dev/required/latex-lab/latex-lab-new-or-1.pdf Binary files differindex 3f68d29e3e..e670627022 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-new-or-1.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-new-or-1.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-new-or-2.pdf b/macros/latex-dev/required/latex-lab/latex-lab-new-or-2.pdf Binary files differindex 2846071100..13f4fa1265 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-new-or-2.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-new-or-2.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-sec.dtx b/macros/latex-dev/required/latex-lab/latex-lab-sec.dtx index d20c55624b..ae7a0b85c3 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-sec.dtx +++ b/macros/latex-dev/required/latex-lab/latex-lab-sec.dtx @@ -16,8 +16,8 @@ % % for those people who are interested or want to report an issue. % -\def\ltlabsecdate{2023-07-20} -\def\ltlabsecversion{0.84a} +\def\ltlabsecdate{2023-10-16} +\def\ltlabsecversion{0.84b} %<*driver> \documentclass{l3doc} \EnableCrossrefs @@ -517,12 +517,10 @@ } } { +% \end{macrocode} +% The relation target-struct is stored internally by the MakeLinkTarget commands +% \begin{macrocode} \MakeLinkTarget[chapter]{} - %todo public function for this update! - \tl_if_blank:VF \@currentHref - { - \prop_gput:Nxx \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} - } } % \end{macrocode} % The main call to the underlying commands. @@ -578,10 +576,6 @@ } { \MakeLinkTarget[part]{} - \tl_if_blank:VF \@currentHref - { - \prop_gput:Nxx \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} - } } % \end{macrocode} % The main call to the underlying commands. @@ -633,18 +627,14 @@ % probably need something slightly different based on \cs{MakeLinkTarget}. % \begin{macrocode} \cs_new_protected:Npn \@hyp@section@target@nnn #1 #2 #3 %#1 optarg #2 name/counter, #3 indent - { - \makebox[0pt][l] + { + \makebox[0pt][l] { \skip_set:Nn \@tempskipa {#3} \dim_compare:nNnF {\@tempskipa}<{0pt}{\kern-\@tempskipa} \MakeLinkTarget#1{#2} } - \tl_if_blank:VF \@currentHref - { - \prop_gput:Nxx \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} - } - } + } % \end{macrocode} % \end{macro} % diff --git a/macros/latex-dev/required/latex-lab/latex-lab-sec.pdf b/macros/latex-dev/required/latex-lab/latex-lab-sec.pdf Binary files differindex ca042a4314..4dc549e7c9 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-sec.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-sec.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-table.dtx b/macros/latex-dev/required/latex-lab/latex-lab-table.dtx new file mode 100644 index 0000000000..700d4ce6c1 --- /dev/null +++ b/macros/latex-dev/required/latex-lab/latex-lab-table.dtx @@ -0,0 +1,1975 @@ +% \iffalse meta-comment +% +%% File: latex-lab-table.dtx (C) Copyright 2023 LaTeX 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 +% +% +% The development version of the bundle can be found below +% +% https://github.com/latex3/latex2e/required/latex-lab +% +% for those people who are interested or want to report an issue. +% +\def\ltlabtbldate{2023-10-30} +\def\ltlabtblversion{0.85d} +%<*driver> +\documentclass{l3doc} +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{latex-lab-table.dtx} +\end{document} +%</driver> +% +% \fi +% +% \providecommand\hook[1]{\texttt{#1\DescribeHook[noprint]{#1}}} +% \providecommand\socket[1]{\texttt{#1\DescribeSocket[noprint]{#1}}} +% \providecommand\plug[1]{\texttt{#1\DescribePlug[noprint]{#1}}} +% +% \NewDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl} +% \NewDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl} +% \NewDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl} +% +% +% +% +% \title{The \textsf{latex-lab-table} package\\ +% Changes related to the tagging of tables} +% \author{Frank \& Ulrike, \LaTeX{} Project\thanks{Initial implementation done by Frank Mittelbach}} +% \date{v\ltlabtblversion\ \ltlabtbldate} +% +% \maketitle +% +% \newcommand{\xt}[1]{\textsl{\textsf{#1}}} +% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} +% \newcommand{\docclass}{document class \marginpar{\raggedright document class +% customizations}} +% +% +% \begin{abstract} +% The following code implements a first draft for the tagging of +% tables. It still has a large number of limitations and restrictions! +% \end{abstract} +% +% \tableofcontents +% +% \section{Documentation} +% +% In \LaTeX{} the word \texttt{table} is used as the name of the float environment that can contain +% a data table\footnote{But it does not really have to, you can put +% other material into such environments.} along with a caption and some additional text. The environments for +% actual data tables have various names like \texttt{tabular}, \texttt{tabular*}, +% \texttt{tabularx} and \texttt{longtable}---the last should not be used inside a float +% and supports its own caption command. +% +% In this documentation \enquote{table} always means such data tables and not the float +% environment. +% +% Tagging of tables is on one side doesn't look very difficult: one only has to +% surround rows and cells by TR and TH or TD structures. +% But there are difficulties: +% \begin{itemize} +% \item +% One is that over the years various packages related to tables have +% been written that all change some of the internals. Inserting the +% tagging commands and testing all the variants and various nestings +% is not trivial. +% +% \item +% The other difficulty is that most of the existing environments to +% create tables do not know the concept of headers as a semantic +% structures. +% +% \item +% Headers are only produced through visual formatting, e.g., by +% making them bold or by underlying some color. But accessible +% tables need headers (and the PDF/UA standards requires them) and +% this means that additional syntax to declare headers (when they +% can't be guessed) must be developed. This is still an area for +% research. +% \end{itemize} +% +% Right now, this module therefore does implement only some basic +% support for the tagging of tables. A list of the known limitations +% is shown below. +% +% The module is not loaded automatically (i.e., not yet integrated +% into any \texttt{phase-XX}) and by itself it doesn't activate +% tagging. For experimenting with table tagging it is therefore best +% to load it in combination +% with phase-III in \cs{DocumentMetadata}, i.e.: +% +% \begin{verbatim} +% \DocumentMetadata{testphase={phase-III,table}} +% \end{verbatim} +% +% It will then automatically tag all table environments it already supports with +% the exception of tables in the header and footer of the page (where tagging is disabled). +% Such tables can be nested. +% +% If a table should not be tagged as table, for example because it is merely used +% to produce a layout or because it is a not yet (fully) supported table structure, +% the tagging can be disabled with +% \verb|\tagpdfsetup{table-tagging=false}|. +% +% Inside cells the automatic tagging of paragraphs is disabled with the exception of +% p/m/b-type cells. +% +% Rows do not need to contain a full number of \&, missing cells are automatically +% added with an empty TD-structure. +% +% There is some basic support\footnote{This is not meant to be the +% final interface, though.} for headers. With +% \begin{quote} +% \verb|\tagpdfsetup{table-header-rows={|\meta{list of row numbers}\verb|}| +% \end{quote} +% you can +% declare which (absolute) row numbers should be tagged as header rows. +% It applies to all tables until it is changed to a different list of row numbers or undone by setting +% the key to \meta{empty}. +% A row number can be +% negative, then the counting starts from the end of the table. There is no support +% for header columns yet. In a \env{longtable} the code will currently use the \cs{endhead} or +% \cs{endfirsthead} rows as header if one of these commands has been +% used and in that case the code +% ignores a \texttt{table-header-rows} setting. +% +% You should not insert meaningful text with \verb+!{...}+ or \verb+@{...}+ or \cs{noalign} +% between the rows or columns of the table. +% With pdflatex such text will be unmarked, with lualatex it will be marked as artifact. +% Either case means that it will be currently ignored in the +% structure.\footnote{While it is theoretically possible +% to collect such text and move it into a structure it would require manual markup +% from the author to clarify where this text belongs too.} +% +% As mentioned below the \pkg{colortbl} doesn't yet work properly with the tagging, +% but once it does, then colors inside the table will probably be +% simply ignored (at least initially). If such a color +% has a semantic meaning (like \enquote{important value}) this meaning will be lost. +% +% Feedback and problems with the code can be reported at +% \url{https://github.com/latex3/tagging-project} either in form of +% explicit issues or as a \enquote{discussion topic}, whatever works best. +% +% +% \section{Limitations} +% +% \begin{itemize} +% \item The code loads the \pkg{array} package and so does not work without it (that is +% not really a limitation, but can affect existing tables). +% +% \item It supports only a restricted number of tables types. Currently +% \env{tabular}, \env{tabular*}, \env{tabularx}, and \env{longtable}. +% +% \item the \env{array} environment is assumed to be part of math and tagging as a table is disabled for +% it. +% +% \item Row spans are not yet supported (and the \pkg{multirow} package is untested). +% +% \item The \pkg{colortbl} package breaks tagging if there are nested tables. It also breaks +% the filling up of incomplete rows. +% +% \item The \pkg{tabularray} package use a completed different +% method to create tables and will not be supported by this code. +% +% \item The \pkg{nicematrix} package is currently incompatible. +% +% \item Most other packages related to tables in \LaTeX{} are not yet tested, +% that includes packages that change rules like \pkg{booktabs}, \pkg{hhline}, +% \pkg{arydshln}, \pkg{hvdashln}. +% +% \item \env{longtable} currently only works with lualatex. +% With other engines it breaks as its output +% routine clashes with the code which closes open MC-chunks at pagebreaks and +% if this is resolved there will probably be problems with the head and foot boxes +% (but this can't be tested currently). +% +% \item Not every table should be tagged as a Table structure, often they are +% only used as layout help, e.g. to align authors in a title pages. In such uses +% the tagging of the table must be deactivated with \verb|\tagpdfsetup{table-tagging=false}|. +% +% \item Only simple header rows are currently supported. Columns and complex headers with +% subheaders will be handled later as that needs some syntax changes. Tables +% with more than one header row are probably not pdf/UA as the headers array in +% the cells is missing. +% +% \item A \pkg{longtable} \cs{caption} is currently simply formatted as a multicolumn and +% not tagged as a \texttt{Caption} structure. +% +% \item The \pkg{caption} package will quite probably break the \pkg{longtable} caption. +% +% \item The setup for \pkg{longtable} requires lots of patches to internal \pkg{longtable} +% commands and so can easily break if other packages try to patch \pkg{longtable} too. +% +% \item The \env{longtable} environment supports footnotes in p-type columns, but it hasn't been +% tested yet if this works also with the tagging code. +% +% \item The code is quite noisy and fills the log with lots of +% messages.\footnote{Helpful for us at this stage.} +% \end{itemize} +% +% +% +% \section{Introduction} +% +% +% \section{Technical details and problems} +% +% The implementation has to take care of various details. +% +% \subsection{TODOs} +% +% \begin{itemize} +% \item +% Test \texttt{array-006-longtable.lvt} and +% \texttt{array-007-longtable.lvt} have errors with pdftex (para +% tagging) +% +% \item +% Instead of before/after hooks we should add sockets directly +% into the code. +% +% \item Debugging code and messages must be improved. +% +% \item Cells need an \texttt{Headers} array. +% +% \item Row spans should be supported (but perhaps need syntax support) +% +% \item Longtable captions should be properly supported. +% +% \item Handle p-cells better. para-tagging should probably be enabled, +% but Part can't be a child of TD, so this should probably be changed to Div here. +% Also there is a stray MC somewhere. +% +% \item More packages must be tested. +% \end{itemize} +% +% +% \section{Implementation} +% \begin{macrocode} +%<@@=tbl> +%<*package> +% \end{macrocode} +% \begin{macrocode} +\ProvidesExplPackage {latex-lab-testphase-table} {\ltlabtbldate} {\ltlabtblversion} + {Code related to the tagging of tables} +% \end{macrocode} +% This builds on \pkg{array} so we load it by default: +% \begin{macrocode} +\RequirePackage{array} +% \end{macrocode} +% +% +% \subsection{Variables} +% \begin{macro} +% { +% \l_@@_celltag_tl +% ,\l_@@_rowtag_tl +% ,\l_@@_cellattribute_tl +% ,\l_@@_rowattribute_tl +% ,\g_@@_missingcells_int +% ,\l_@@_tmpa_clist +% ,\l_@@_tmpa_seq +% ,\l_@@_tmpa_tl +% } +% This is for the celltag, e.g. TD or TH: +% \begin{macrocode} +\tl_new:N \l_@@_celltag_tl +\tl_set:Nn \l_@@_celltag_tl {TD} +% \end{macrocode} +% For the rowtag, probably always TR: +% \begin{macrocode} +\tl_new:N \l_@@_rowtag_tl +\tl_set:Nn \l_@@_rowtag_tl {TR} +% \end{macrocode} +% And here cell and row attributes: +% \begin{macrocode} +\tl_new:N \l_@@_cellattribute_tl +\tl_set:Nn \l_@@_cellattribute_tl {} +\tl_new:N \l_@@_rowattribute_tl +\tl_set:Nn \l_@@_rowattribute_tl {} +% \end{macrocode} +% This will contain the number of missing cells used: +% \begin{macrocode} +\int_new:N \g_@@_missing_cells_int +% \end{macrocode} +% Temp variables +% \begin{macrocode} +\clist_new:N \l_@@_tmpa_clist +\seq_new:N \l_@@_tmpa_seq +\tl_new:N \l_@@_tmpa_tl +% \end{macrocode} +% \end{macro} +% +% \subsection{Sockets} +% +% The code uses a number of sockets to inject the tagging +% commands. These can be easily set to a noop-plug in case the +% automated tagging is not wanted At first sockets for the begin and +% end of cells and rows +% +% \begin{socketdecl}{tagsupport/tblcell/begin, +% tagsupport/tblcell/end, +% tagsupport/tblrow/begin, +% tagsupport/tblrow/end, +% } +% \begin{macrocode} +\NewSocket{tagsupport/tblcell/begin}{0} +\NewSocket{tagsupport/tblcell/end}{0} +\NewSocket{tagsupport/tblrow/begin}{0} +\NewSocket{tagsupport/tblrow/end}{0} +% \end{macrocode} +% \end{socketdecl} +% +% \begin{socketdecl}{tagsupport/tbl/init} +% This socket should be at the begin of the table, inside a group. +% It is meant for settings like disabling paratagging. This socket +% can perhaps be merged later into the begin-sockets when they are +% no longer added as hooks but in the environment definitions. +% \begin{macrocode} +\NewSocket{tagsupport/tbl/init}{0} +% \end{macrocode} +% \end{socketdecl} +% +% +% \begin{socketdecl}{tagsupport/tbl/finalize} +% To fine tune the structure (change cells to header cells, remove +% unwanted structures, move a foot to the end, etc.) we also need a +% socket that is executed at the end of the table but \emph{before} +% all the variables are restored to the outer or default values. +% The code in the socket can make assignments, but probably +% shouldn't do typesetting and not write whatsits. +% \begin{macrocode} +\NewSocket{tagsupport/tbl/finalize}{0} +% \end{macrocode} +% \end{socketdecl} +% +% \begin{socketdecl}{tagsupport/tbl/finalize/longtable} +% \env{longtable} needs its own socket to fine tune the structure. +% Simply switching the plug in the previous socket interferes with +% enabling/disabling the tagging. +% \begin{macrocode} +\NewSocket{tagsupport/tbl/finalize/longtable}{0} +% \end{macrocode} +% \end{socketdecl} +% +% \begin{socketdecl}{tagsupport/tblhmode/begin, +% tagsupport/tblhmode/end, +% tagsupport/tblvmode/begin, +% tagsupport/tblvmode/end +% } +% +% These sockets are used in the begin and end code of environments, +% to allow a fast enabling and disabling of the tagging. We +% distinguish between tables that can be used inside paragraphs and +% standalone tables like longtable. +% \begin{macrocode} +\NewSocket{tagsupport/tblhmode/begin}{0} +\NewSocket{tagsupport/tblhmode/end}{0} +\NewSocket{tagsupport/tblvmode/begin}{0} +\NewSocket{tagsupport/tblvmode/end}{0} +% \end{macrocode} +% \end{socketdecl} +% +% This are the standard plugs for tagging of cells and rows. +% +% \begin{plugdecl}{TD} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblcell/begin}{TD} + { + \tag_struct_begin:n + { + tag =\l_@@_celltag_tl, + attribute-class =\l_@@_cellattribute_tl + } + \seq_gput_right:Ne \g_@@_struct_cur_seq { \tag_get:n {struct_num} } +% \end{macrocode} +% we store the cells of multicolumns as negative number. This allow to skip them +% or to use them as needed. +% \begin{macrocode} + \int_step_inline:nn { \g_@@_span_tl - 1 } + { + \seq_gput_right:Ne \g_@@_struct_cur_seq { -\tag_get:n {struct_num} } + } + \tag_mc_begin:n{} + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{TD} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblcell/end}{TD} + { + \tag_mc_end: + \tag_struct_end: + } +% \end{macrocode} +% \end{plugdecl} +% +% In p-columns we need a slightly different plug which reactivates the +% paragraph tagging. +% tagging +% \begin{plugdecl}{TD} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblcell/begin}{TDpbox} + { + \tag_struct_begin:n + { + tag =\l__tbl_celltag_tl, + attribute-class =\l__tbl_cellattribute_tl + } + \seq_gput_right:Ne \g__tbl_struct_cur_seq { \tag_get:n {struct_num} } + \int_step_inline:nn { \g__tbl_span_tl - 1 } + { + \seq_gput_right:Ne \g__tbl_struct_cur_seq { -\tag_get:n {struct_num} } + } + \tagpdfparaOn + \tl_set:Nn \l__tag_para_main_tag_tl {Div} + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{TD} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblcell/end}{TDpbox} + { + \tag_struct_end: + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{TR} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblrow/begin}{TR} + { + \seq_gclear:N \g_@@_struct_cur_seq + \tag_struct_begin:n + { + tag =\l_@@_rowtag_tl, + attribute-class=\l_@@_rowattribute_tl + } + \seq_gput_right:Ne \g_@@_struct_rows_seq { \tag_get:n {struct_num} } + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{TR} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblrow/end}{TR} + { + \__tag_tbl_add_missing_cells:n { \g_@@_missing_cells_int } + \seq_gput_right:Ne \g_@@_struct_cells_seq + { + \seq_use:Nn \g_@@_struct_cur_seq {,} + } + \int_compare:nNnTF { \g_@@_row_int } = { \seq_count:N\g_@@_struct_cells_seq } + { + \typeout + {==>~ + stucture~stored~for~row~\int_use:N\g_@@_row_int :~ + \seq_use:Nn \g_@@_struct_cur_seq {,} + } + } + { \ERROR } % should not happen ... + \tag_struct_end: + } +% \end{macrocode} +% \end{plugdecl} +% +% And the plugs for the table as whole. The code can be different for +% normal tables which can also be used inline and nested and +% \enquote{vmode} tables like longtable. +% +% \begin{plugdecl}{Table} +% Inside a table we currently only disable paratagging. We assume +% that these sockets are in an environment group, so there is no +% need to reenable paratagging. +% \begin{macrocode} +\NewSocketPlug{tagsupport/tbl/init}{Table} + { + \tag_if_active:T + { + \bool_set_false:N \l__tag_para_bool + } + } +% \end{macrocode} +% \end{plugdecl} +% +% +% \begin{plugdecl}{Table} +% This plug will fine tune the structure. +% \begin{macrocode} +\NewSocketPlug{tagsupport/tbl/finalize}{Table} + { + \@@_set_header_rows: + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{Table} +% This plug will fine tune the structure of longtable. +% \begin{macrocode} +\NewSocketPlug{tagsupport/tbl/finalize/longtable}{Table} + { +% \end{macrocode} +% If neither \cs{endhead} nor \cs{endfirsthead} has been used +% we use the standard header command: +% \begin{macrocode} + \bool_lazy_and:nnTF + { \seq_if_empty_p:N \g_@@_LT@head_rows_seq } + { \seq_if_empty_p:N \g_@@_LT@firsthead_rows_seq } + { \@@_set_header_rows: } +% \end{macrocode} +% Otherwise, if firsthead has not been used we use head. For this +% we simple retrieve the row numbers and then call the header +% command. +% \begin{macrocode} + { + \seq_if_empty:NTF \g_@@_LT@firsthead_rows_seq + { + \clist_set:Ne \l_@@_header_rows_clist + {\seq_use:Nn \g_@@_LT@head_rows_seq {,}} + \@@_set_header_rows: + } +% \end{macrocode} +% In the other case we use firsthead. +% \begin{macrocode} + { + \clist_set:Ne \l_@@_header_rows_clist + { \seq_use:Nn \g_@@_LT@firsthead_rows_seq {,} } + \@@_set_header_rows: +% \end{macrocode} +% Additionally we have to remove the head to avoid duplication. The +% one option here is to remove the rows from the kid sequence of +% the table (which will lead to orphaned structure elements), the +% other to make them artifact. For now we use the first option for +% pdf 1.7 and the second for pdf 2.0. +% \begin{macrocode} + \pdf_version_compare:NnTF < {2.0} + { + \seq_map_inline:Nn \g_@@_LT@head_rows_seq + { + \seq_gset_item:cnn + {g__tag_struct_kids_ \g_@@_struct_table_tl _seq} + { ##1 } + {} +% \end{macrocode} +% Not sure if needed, but if needed we can remove also the P tag. +% This is currently disabled as it produce warnings. TODO: This +% needs also a tagpdf command which takes care of debug code. +% \begin{macrocode} + \tl_set:Ne \l_@@_tmpa_tl + { \seq_item:Nn\g_@@_struct_rows_seq {##1} } + \prop_if_exist:cT + { g__tag_struct_ \l_@@_tmpa_tl _prop } + { + %\prop_gremove:cn {g__tag_struct_ \l_@@_tmpa_tl _prop} {P} + } + } + } + { + \seq_map_inline:Nn \g_@@_LT@head_rows_seq + { + \tl_set:Ne \l_@@_tmpa_tl + { \seq_item:Nn\g_@@_struct_rows_seq {##1} } + \prop_if_exist:cT + { g__tag_struct_ \l_@@_tmpa_tl _prop } + { + \@@_struct_prop_gput:Vnn \l_@@_tmpa_tl {S}{/Artifact} + } + } + } + } + } +% \end{macrocode} +% The foot is handled similar, the difference is +% that we have to move it to the end one of them +% is not empty, but do nothing if they aren't there. +% \begin{macrocode} + \bool_lazy_and:nnF + { \seq_if_empty_p:N \g_@@_LT@foot_rows_seq } + { \seq_if_empty_p:N \g_@@_LT@lastfoot_rows_seq } + { +% \end{macrocode} +% If lastfoot is empty move foot to the end. +% \begin{macrocode} + \seq_if_empty:NTF \g_@@_LT@lastfoot_rows_seq + { + \seq_map_inline:Nn \g_@@_LT@foot_rows_seq + { + \tl_set:Ne \l_@@_tmpa_tl + { + \seq_item:cn + {g__tag_struct_kids_ \g_@@_struct_table_tl _seq} + {##1} + } + \seq_gset_item:cnn + {g__tag_struct_kids_ \g_@@_struct_table_tl _seq} + { ##1 } + {} + \seq_gput_right:cV + {g__tag_struct_kids_ \g_@@_struct_table_tl _seq} + \l_@@_tmpa_tl + } + } +% \end{macrocode} +% If lastfoot is not empty we move that. +% \begin{macrocode} + { + \seq_map_inline:Nn \g_@@_LT@lastfoot_rows_seq + { + \tl_set:Ne \l_@@_tmpa_tl + { + \seq_item:cn + {g__tag_struct_kids_ \g_@@_struct_table_tl _seq} + {##1} + } + \seq_gset_item:cnn + {g__tag_struct_kids_ \g_@@_struct_table_tl _seq} + { ##1 } + {} + \seq_gput_right:cV + {g__tag_struct_kids_ \g_@@_struct_table_tl _seq} + \l_@@_tmpa_tl + } +% \end{macrocode} +% and we hide foot +% \begin{macrocode} + \pdf_version_compare:NnTF < {2.0} + { + \seq_map_inline:Nn \g_@@_LT@foot_rows_seq + { + \seq_gset_item:cnn + {g__tag_struct_kids_ \g_@@_struct_table_tl _seq} + { ##1 } + {} +% \end{macrocode} +% Not sure if needed, but if needed we can remove also the P tag. +% This is currently disabled as it produce warnings. +% TODO: This needs also +% a tagpdf command which takes care of debug code. +% \begin{macrocode} + \tl_set:Ne \l_@@_tmpa_tl + { \seq_item:Nn\g_@@_struct_rows_seq {##1} } + \prop_if_exist:cT + { g__tag_struct_ \l_@@_tmpa_tl _prop } + { + %\prop_gremove:cn {g__tag_struct_ \l_@@_tmpa_tl _prop} {P} + } + } + } + { + \seq_map_inline:Nn \g_@@_LT@foot_rows_seq + { + \tl_set:Ne \l_@@_tmpa_tl + { \seq_item:Nn\g_@@_struct_rows_seq {##1} } + \prop_if_exist:cT + { g__tag_struct_ \l_@@_tmpa_tl _prop } + { + \@@_struct_prop_gput:Vnn \l_@@_tmpa_tl {S}{/Artifact} + } + } + } + } + } + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{Table} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblhmode/begin}{Table} + { + \mode_leave_vertical: + \tag_mc_end_push: +% \end{macrocode} +% Close the P-chunk. This assumes that para-tagging is active. +% For nested tables that is not necessarly true, so we test for it. +% \begin{macrocode} + \bool_lazy_and:nnT + { \bool_if_exist_p:N \l__tag_para_bool } { \l__tag_para_bool } + { \tag_struct_end:n { text } } + \tag_struct_begin:n {tag=Table} + \tl_gset:Ne \g_@@_struct_table_tl { \tag_get:n {struct_num} } + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{Table} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblhmode/end}{Table} + { + \tag_struct_end: +% \end{macrocode} +% reopen the P-chunk. This assumes that para-tagging is active. +% For nested tables that is not necessarly true, so we test for it. +% \begin{macrocode} + \bool_lazy_and:nnT + { \bool_if_exist_p:N \l__tag_para_bool } { \l__tag_para_bool } + { \tag_struct_begin:n { tag=\l__tag_para_tag_tl } } + \tag_mc_begin_pop:n{} + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{Table} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblvmode/begin}{Table} + { + \tag_struct_begin:n {tag=Table} + \tl_gset:Ne \g_@@_struct_table_tl { \tag_get:n {struct_num} } + } +% \end{macrocode} +% \end{plugdecl} +% +% \begin{plugdecl}{Table} +% \begin{macrocode} +\NewSocketPlug{tagsupport/tblvmode/end}{Table} + { + \tag_struct_end: + \par + } +% \end{macrocode} +% \end{plugdecl} +% +% +% +% +% +%\subsection{Environments} +% +% Currently only tabular, tabular*, tabularx and longtable. +% We must use the \texttt{before} and \texttt{after} hooks as the \texttt{end} +% hook is executed before the end of the last row and then MC are messed up. +% This means that this sockets should only contain code that doesn't needs to be +% grouped! +% \begin{macrocode} +\AddToHook{env/tabular/before} {\UseSocket{tagsupport/tblhmode/begin}} +\AddToHook{env/tabular/after} {\UseSocket{tagsupport/tblhmode/end}} +\AddToHook{env/tabular*/before} {\UseSocket{tagsupport/tblhmode/begin}} +\AddToHook{env/tabular*/after} {\UseSocket{tagsupport/tblhmode/end}} +\AddToHook{env/tabularx/before} {\UseSocket{tagsupport/tblhmode/begin}} +\AddToHook{env/tabularx/after} {\UseSocket{tagsupport/tblhmode/end}} +\AddToHook{env/longtable/before}{\UseSocket{tagsupport/tblvmode/begin}} +\AddToHook{env/longtable/after} {\UseSocket{tagsupport/tblvmode/end}} +% \end{macrocode} +% +% The \env{array} environment is math. So we disable table tagging for now. +% \begin{macrocode} +\AddToHook{env/array/begin} {\__tag_tbl_disable:} +% \end{macrocode} +% +% +% \subsection{Interfaces to tagging} +% +% \subsubsection{Tagging helper commands} +% +% \begin{macro}{\@@_set_colspan:n} +% This commands takes a number, checks if is larger than one, +% checks if the colspan attribute exists (we can't predefine an +% arbitrary number), and updates \cs{l_@@_cellattribute_tl}. +% \begin{macrocode} +\tag_if_active:T + { \cs_generate_variant:Nn \__tag_attr_new_entry:nn {ee} } +\cs_new_protected:Npn \@@_set_colspan:n #1 + { + \tag_if_active:T + { + \int_compare:nNnT {#1}>{1} + { + \prop_get:NeNF \g__tag_attr_entries_prop + {colspan-\int_eval:n{#1}} + \l_@@_tmpa_tl + { + \__tag_attr_new_entry:ee + {colspan-\int_eval:n{#1}} + {/O /Table /ColSpan~\int_eval:n{#1}} + } + \tl_set:Ne \l_@@_cellattribute_tl + {colspan-\int_eval:n{#1}} + } + } + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Disabling/enabling} +% +% For now we have only the option true/false but this will probably be extended +% to allow different setups like first row header etc. + +% \begin{macro}{\__tag_tbl_disable:} +% +% \begin{macrocode} +\cs_new_protected:Npn \__tag_tbl_disable: + { + \AssignSocketPlug{tagsupport/tblcell/begin}{noop} + \AssignSocketPlug{tagsupport/tblcell/end}{noop} + \AssignSocketPlug{tagsupport/tblrow/begin}{noop} + \AssignSocketPlug{tagsupport/tblrow/end}{noop} + \AssignSocketPlug{tagsupport/tbl/init}{noop} + \AssignSocketPlug{tagsupport/tbl/finalize}{noop} + \AssignSocketPlug{tagsupport/tbl/finalize/longtable}{noop} + \AssignSocketPlug{tagsupport/tblhmode/begin}{noop} + \AssignSocketPlug{tagsupport/tblhmode/end}{noop} + \AssignSocketPlug{tagsupport/tblvmode/begin}{noop} + \AssignSocketPlug{tagsupport/tblvmode/end}{noop} + } +% \end{macrocode} +% \end{macro} + + +% \begin{macro}{\__tag_tbl_enable:} +% +% \begin{macrocode} +\cs_new_protected:Npn \__tag_tbl_enable: + { + \AssignSocketPlug{tagsupport/tblcell/begin}{TD} + \AssignSocketPlug{tagsupport/tblcell/end}{TD} + \AssignSocketPlug{tagsupport/tblrow/begin}{TR} + \AssignSocketPlug{tagsupport/tblrow/end}{TR} + \AssignSocketPlug{tagsupport/tbl/init}{Table} + \AssignSocketPlug{tagsupport/tbl/finalize}{Table} + \AssignSocketPlug{tagsupport/tbl/finalize/longtable}{Table} + \AssignSocketPlug{tagsupport/tblhmode/begin}{Table} + \AssignSocketPlug{tagsupport/tblhmode/end}{Table} + \AssignSocketPlug{tagsupport/tblvmode/begin}{Table} + \AssignSocketPlug{tagsupport/tblvmode/end}{Table} + } +% \end{macrocode} +% \end{macro} + +% \begin{macrocode} +% TODO decide about key name +\keys_define:nn { __tag / setup } + { + table-tagging .choices:nn = { true, on } + { \__tag_tbl_enable: }, + table-tagging .choices:nn = { false, off } + { \__tag_tbl_disable: }, + table-tagging .default:n = true, + table-tagging .initial:n = true + } +% \end{macrocode} +% +% Table tagging should be disabled in the head and foot. +% \begin{macrocode} +\AddToHook{begindocument} + { + \cs_if_exist:NT \@kernel@before@head + { + \tl_put_right:Nn \@kernel@before@head {\__tag_tbl_disable:} + \tl_put_right:Nn \@kernel@before@foot {\__tag_tbl_disable:} + } + } +% \end{macrocode} +% +% \subsubsection{Header support} +% +% Accessible table must have header cells declaring the meaning of the +% data in a row or column. To allow a data cell to find it header cell(s) +% a number of things must be done: +% \begin{itemize} +% \item every cell meant as a header should use the tag \texttt{TH}. +% +% \item header cells should have a \texttt{Scope} attribute with the +% value \texttt{Column}, \texttt{Row} or \texttt{Both}. This is not +% needed in the first row or column of a table. +% +% \item For more complex cases both \texttt{TD} and \texttt{TH} cell +% can contain a \texttt{Headers} attribute, that is an array of +% \texttt{ID}s of \texttt{TH} cell. +% \end{itemize} +% +% For now we support only header rows. +% +% At first we define attributes for the three standard cases: +% We delay to begin document +% as we can't know if tagpdf is already loaded. +% \begin{macrocode} +\AddToHook{begindocument} + { + \tag_if_active:T + { + \tagpdfsetup + { + newattribute = + {TH-col}{/O /Table /Scope /Column}, + newattribute = + {TH-row}{/O /Table /Scope /Row}, + newattribute = + {TH-both}{/O /Table /Scope /Both}, + } +% \end{macrocode} +% +% And we put all three into the class map (perhaps the next tagpdf +% should do that directly with newattribute): +% +% \begin{macrocode} + \seq_gput_left:Ne\g__tag_attr_class_used_seq + {\pdf_name_from_unicode_e:n{TH-col}} + \seq_gput_left:Ne\g__tag_attr_class_used_seq + {\pdf_name_from_unicode_e:n{TH-row}} + \seq_gput_left:Ne\g__tag_attr_class_used_seq + {\pdf_name_from_unicode_e:n{TH-both}} + } + } + +% \end{macrocode} +% +% \begin{variable}{\l_@@_header_rows_clist} +% This holds the numbers of the header rows. Negative numbers are +% possible and count from the back. +% \begin{macrocode} +\clist_new:N \l_@@_header_rows_clist +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_set_header_rows:} +% TEMP: Next tagpdf will have the right command which also updates +% the debug info. +% For now a temporary command: +% \begin{macrocode} +\cs_if_free:NTF \__tag_struct_prop_gput:nnn + { + \cs_new_protected:Npn \@@_struct_prop_gput:nnn #1#2#3 + { \prop_gput:cnn { g__tag_struct_#1_prop }{#2}{#3} } + } + { \cs_new_protected:Npn \@@_struct_prop_gput:nnn #1#2#3 + { \__tag_struct_prop_gput:nnn {#1}{#2}{#3} } + } +\cs_generate_variant:Nn \@@_struct_prop_gput:nnn {nne,Vnn} +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_header_rows: + { + \clist_map_inline:Nn \l_@@_header_rows_clist + { + \clist_set:Ne\l_@@_tmpa_clist + { + \seq_item:Nn \g_@@_struct_cells_seq {##1} + } + \clist_map_inline:Nn \l_@@_tmpa_clist + { +% \end{macrocode} +% We can have negative numbers in the list from the multicolumn. +% \begin{macrocode} + \prop_if_exist:cT { g__tag_struct_####1_prop } + { + \@@_struct_prop_gput:nnn{ ####1 }{S}{/TH} +% \end{macrocode} +% This need refinement once row headers (and perhaps other attributes) +% are used too, but for now it should be ok. +% \begin{macrocode} + \prop_get:cnNTF + { g__tag_struct_####1_prop } + { C } + \l_@@_tmpa_tl + {\@@_struct_prop_gput:nne{ ####1 }{C}{[/TH-col~\l_@@_tmpa_tl]} } + {\@@_struct_prop_gput:nnn{ ####1 }{C}{/TH-col}} + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% And some key support: +% \begin{macrocode} +% TODO decide about key name +\keys_define:nn { __tag / setup } + { + table-header-rows .clist_set:N = \l_@@_header_rows_clist + } +% \end{macrocode} +% +% \subsection{Changes to \pkg{array} commands} +% +% +% +% \begin{macro}{\@@_show_curr_cell_data:} +% Show the row/column index and span count for current table cell +% for debugging. +% \begin{macrocode} +\cs_new_protected:Npn \@@_show_curr_cell_data: { + \typeout { ==>~ current~cell~data:~ + \int_use:N \g_@@_row_int , + \int_use:N \g_@@_col_int , + \g_@@_span_tl + } +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{\insert@column} +% \cs{insert@column} is defined in \pkg{array}, here only the two +% sockets are inserted. +% \begin{macrocode} +\def\insert@column{% + \@@_show_curr_cell_data: + \UseSocket{tagsupport/tblcell/begin}% + \the@toks \the \@tempcnta + \ignorespaces \@sharp \unskip + \the@toks \the \count@ \relax + \UseSocket{tagsupport/tblcell/end}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@classz} +% \begin{macrocode} +\def\@classz{\@classx + \@tempcnta \count@ + \prepnext@tok + \@addtopreamble{\ifcase \@chnum + \hfil + \hskip1sp% + \d@llarbegin + \insert@column + \d@llarend \do@row@strut \hfil \or + \hskip1sp\d@llarbegin \insert@column \d@llarend \do@row@strut \hfil \or + \hfil\hskip1sp\d@llarbegin \insert@column \d@llarend \do@row@strut \or + \setbox\ar@mcellbox\vbox + \@startpbox{\@nextchar} + \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox} + \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox} + \insert@column \@endpbox + \ar@align@mcell + \do@row@strut \or + \vtop \@startpbox{\@nextchar} + \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox} + \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox} + \insert@column \@endpbox\do@row@strut \or + \vbox \@startpbox{\@nextchar} + \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox} + \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox} + \insert@column \@endpbox\do@row@strut + \fi}\prepnext@tok} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@array,\@@@@array} +% We modificate the \cs{@array} from \pkg{array}. +% \begin{macrocode} +\def\@array[#1]#2{% + \@tempdima \ht \strutbox + \advance \@tempdima by\extrarowheight + \setbox \@arstrutbox \hbox{\vrule + \@height \arraystretch \@tempdima + \@depth \arraystretch \dp \strutbox + \@width \z@}% +% \end{macrocode} +% The total number of table columns of the current table is +% determined in \cs{@@_determine_table_cols:} but this is called in +% a group, so local settings do not survive. Thus, to save away the +% outer value of \cs{g_@@_table_cols_tl} we do it before the group. +% \begin{macrocode} + \tl_set_eq:NN \l_@@_saved_table_cols_tl \g_@@_table_cols_tl +% \end{macrocode} +% +% \begin{macrocode} + \begingroup + \@mkpream{#2} +% \end{macrocode} +% Next call has to happen immediately after \cs{@mkpream} because +% it uses implementation details from that. +% \begin{macrocode} + \@@_determine_table_cols: +% \end{macrocode} +% +% \begin{macrocode} + \xdef\@preamble{% + \noexpand +% \end{macrocode} +% \cs{ialign} in the original definition is replaced by +% \cs{ar@ialign} defined below. +% \begin{macrocode} + \ar@ialign + \@halignto + \bgroup \@arstrut +% \end{macrocode} +% A socket is inserted +% \begin{macrocode} + \UseSocket{tagsupport/tblrow/begin}% +% \end{macrocode} +% At the start of the preamble for the first column we set +% \cs{g_@@_col_int} to \texttt{1} as we are no longer "at" but "in" +% the first column. This is done in \cs{@@_init_cell_data:}. In +% later columns this data is updated via \cs{@@_update_cell_data:}. +% \begin{macrocode} + \@@_init_cell_data: + \@preamble + \tabskip \z@ \cr}% + \endgroup + \@arrayleft +% \end{macrocode} +% Another socket for tagging. TODO: what about \cs{arrayleft}? +% \begin{macrocode} + \UseSocket{tagsupport/tbl/init} + \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi \fi + \bgroup + \let \@sharp ##\let \protect \relax + \lineskip \z@ + \baselineskip \z@ + \m@th + \let\\\@arraycr \let\tabularnewline\\\let\par\@empty +%\show\@preamble + \@preamble} +% \end{macrocode} +% Finally, also set \cs{@@@@array} to the new definition: +% \begin{macrocode} +\let\@@@@array\@array +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_init_cell_data:} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_init_cell_data: { + \int_gset:Nn \g_@@_col_int {1} + \tl_gset:Nn \g_@@_span_tl {1} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_update_cell_data:} +% Updating cell data in columns after the first means we have to +% increment the \cs{g_@@_col_int} by the span count of the previous +% cell (in case it was a \cs{multicolumn} and then reset the +% \cs{g_@@_span_tl} to one (as the default). +% \begin{macrocode} +\cs_new_protected:Npn \@@_update_cell_data: { + \int_gadd:Nn \g_@@_col_int { \g_@@_span_tl } + \tl_gset:Nn \g_@@_span_tl {1} +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_determine_table_cols:} +% Current implementation of \cs{@mkpream} uses the scratch counter +% \cs{count@} to keep track of the number of toks registers it needs +% (2 per column), but this can't be used as it counts also +% insertings made with \verb+!{}+ and \verb+@{}+. +% So similar as does longtable for \cs{LT@cols} we count the +% numbers of ambersands instead. +% \begin{macrocode} +\cs_new:Npn \@@_determine_table_cols: { + \seq_set_split:NnV\l_@@_tmpa_seq {&}\@preamble + \tl_gset:Ne \g_@@_table_cols_tl { \seq_count:N \l_@@_tmpa_seq } + \typeout{ ==>~ Table~ has~ \g_@@_table_cols_tl \space columns } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@arraycr} +% Add code that figures out if the current table row is incomplete +% (not enough \verb=&=s). It can then do extra actions, such as +% inserting missing cell tags. +% \begin{macrocode} +\protected\def\@arraycr{ + \relax + \@@_store_missing_cells:n{@arraycr} + % + \iffalse{\fi\ifnum 0=`}\fi + \@ifstar \@xarraycr \@xarraycr} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_store_missing_cells:n, +% \__tag_tbl_add_missing_cells:n} +% The storing and use of the number of missing cells +% must happen at different places as the testing happens at +% the end of the last cell of a row, but +% still inside that cell, so we use two commands. The second is used in +% the endrow socket. +% \begin{macrocode} +\cs_new:Npn \@@_store_missing_cells:n #1 { + \int_compare:nNnT \g_@@_col_int > 0 + { + \int_gset:Nn \g_@@_missing_cells_int + { + \g_@@_table_cols_tl + - \g_@@_col_int + - \g_@@_span_tl + + 1 + } + \int_compare:nNnT \g_@@_missing_cells_int < 0 \ERROR % should not happen + \typeout{==>~ + (#1)~ + This~ row~ needs~ + \int_use:N \g_@@_missing_cells_int \space + additional~ cell(s) + } + } +} +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Npn \__tag_tbl_add_missing_cells:n #1 + { +% \end{macrocode} +% The TD-socket messages are issued after the message about the end-row socket, +% but the structure is ok, so better issue a message for now to avoid confusion: +% \begin{macrocode} + \int_compare:nNnT {#1}>{0} + { + \typeout{==>~ + ~Inserting~\int_eval:n{#1}~additional~cell(s)~into~previous~row:} + } + \int_step_inline:nn { #1 } + { + \UseSocket{tagsupport/tblcell/begin} + \UseSocket{tagsupport/tblcell/end} + } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\endarray} +% If tables are nested into another then it is necessary to +% restore information about the cell the inner table started +% in. Otherwise, \cs{g_@@_row_int}, \cs{g_@@_col_int}, and +% \cs{g_@@_span_tl} reflect the status in the outer table as they +% are globally manipulated. We restore in all cases even if we are +% not in a nesting situation as that makes the code simpler (and +% probably faster). +% +% \cs{endtabular} and \cs{endtabular*} inherit from \cs{endarray} +% so we only need to change that. \texttt{tabularx} is handled +% below. +% \begin{macrocode} +\def\endarray{ + \@@_store_missing_cells:n{endarray} + \crcr \egroup + \UseSocket{tagsupport/tbl/finalize} + \int_gset:Nn \g_@@_col_int { \l_@@_saved_col_tl } + \int_gset:Nn \g_@@_row_int { \l_@@_saved_row_tl } + \tl_gset_eq:NN \g_@@_span_tl \l_@@_saved_span_tl + \tl_gset_eq:NN \g_@@_table_cols_tl \l_@@_saved_table_cols_tl + \tl_gset_eq:NN \g_@@_struct_table_tl \l_@@_saved_struct_table_tl + \seq_gset_eq:NN \g_@@_struct_rows_seq \l_@@_saved_struct_rows_seq + \seq_gset_eq:NN \g_@@_struct_cells_seq\l_@@_saved_struct_cells_seq + \seq_gset_eq:NN \g_@@_struct_cur_seq \l_@@_saved_struct_cur_seq + \typeout{==>~ restored~cell~data:~ + \int_use:N \g_@@_row_int, + \int_use:N \g_@@_col_int, + \l_@@_saved_span_tl \space + ( + \int_compare:nNnTF \g_@@_table_cols_tl = 0 + { outer~ level } + { max:~ \g_@@_table_cols_tl } + ) + } + \egroup + \@arrayright \gdef\@preamble{}% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@addamp} +% If we are after the first column we have to insert a \verb=&= and +% also update the cell data. +% \begin{macrocode} +\def\@addamp { + \if@firstamp + \@firstampfalse + \else + \edef\@preamble{\@preamble & + \@@_update_cell_data: + } + \fi +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{ +% \g_@@_col_int, +% \g_@@_row_int, +% \g_@@_span_tl, +% \g_@@_table_cols_tl} +% \cs{g_@@_row_int} holds the current row number in the table. The value +% \texttt{0} means we haven't yet processed the table preamble. It +% is incremented by every \cs{cr} including the one ending the +% table preamble. +% +% \cs{g_@@_col_int} holds the current column number. The value +% \texttt{0} means we have not yet started the table or just finished a table row +% (with \verb=\\= typically); any other positive value means we +% are currently typesetting a cell in that column in some row +% (denoted by the \cs{g_@@_row_int}. +% +% In a \cs{multicolumn} it holds the column number of the first +% spanned column and \cs{g_@@_span_tl} the info how many cells are +% spanned. +% +% \cs{g_@@_span_tl} is normally \texttt{1} except in a +% \cs{multicolumn} cell. +% \begin{macrocode} +\int_new:N \g_@@_col_int +\int_new:N \g_@@_row_int +\tl_new:N \g_@@_span_tl +\tl_new:N \g_@@_table_cols_tl + +\tl_gset:Nn \g_@@_span_tl {1} +\tl_gset:Nn \g_@@_table_cols_tl {0} % indicates outer level +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\l_@@_saved_col_tl,\l_@@_saved_row_tl, +% \l_@@_saved_span_tl,\l_@@_saved_table_cols_tl} +% +% Saving the outer values if we are nesting tables is necessary (as +% the above variables are globally altered. For this we use always +% token lists because they don't change and we do not need to blow +% additional integer registers. +% \begin{macrocode} +\tl_new:N \l_@@_saved_col_tl +\tl_new:N \l_@@_saved_row_tl +\tl_new:N \l_@@_saved_span_tl +\tl_new:N \l_@@_saved_table_cols_tl + +\tl_set:Nn \l_@@_saved_col_tl{0} +\tl_set:Nn \l_@@_saved_row_tl{0} +\tl_set:Nn \l_@@_saved_span_tl{1} +\tl_set:Nn \l_@@_saved_table_cols_tl{0} % indicates outer level +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \g_@@_struct_table_tl, \l_@@_saved_struct_table_tl, +% \g_@@_struct_rows_seq,\l_@@_saved_struct_rows_seq, +% \g_@@_struct_cells_seq,\l_@@_saved_struct_cells_seq, +% \g_@@_struct_cur_seq,\l_@@_saved_struct_cur_seq +% } +% We need to store the structure numbers for the fine tuning in the +% finalize socket. For now we use a rather simple system: A +% sequence that hold the numbers for the row structures, and one +% that holds comma lists for the cells. +% +% \cs{g_@@_struct_table_tl} will hold the structure number of the +% table, \cs{g_@@_struct_rows_seq} will hold at index i the +% structure number of row i, \cs{g_@@_struct_cells_seq} will hold +% at index i a comma list of the cell structure numbers of row i. +% \cs{g_@@_struct_cur_seq} is used as a temporary store for the +% cell structures of the current row. We need also local version +% to store and restore the values. +% +% \begin{macrocode} +\tl_new:N \g_@@_struct_table_tl +\tl_new:N \l_@@_saved_struct_table_tl +\seq_new:N \g_@@_struct_rows_seq +\seq_new:N \l_@@_saved_struct_rows_seq +\seq_new:N \g_@@_struct_cells_seq +\seq_new:N \l_@@_saved_struct_cells_seq +\seq_new:N \g_@@_struct_cur_seq +\seq_new:N \l_@@_saved_struct_cur_seq +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ar@ialign} +% A new command that replaces \cs{ialign} above. \cs{everycr} is +% also applied to the \cs{cr} ending the preamble so we have to +% program around that. +% \begin{macrocode} +\def\ar@ialign{% +% \end{macrocode} +% Before starting a table we locally stored the information related +% to the current cell (if any) so that we can restore it once the +% table is finished. +% \begin{macrocode} + \tl_set:No \l_@@_saved_col_tl {\int_use:N \g_@@_col_int } + \tl_set:No \l_@@_saved_row_tl {\int_use:N \g_@@_row_int } + \tl_set_eq:NN \l_@@_saved_span_tl \g_@@_span_tl + \tl_set_eq:NN \l_@@_saved_struct_table_tl \g_@@_struct_table_tl + \seq_set_eq:NN \l_@@_saved_struct_rows_seq \g_@@_struct_rows_seq + \seq_set_eq:NN \l_@@_saved_struct_cells_seq \g_@@_struct_cells_seq + \seq_set_eq:NN \l_@@_saved_struct_cur_seq \g_@@_struct_cur_seq +% + \typeout{==>~ saved~cell~data:~ + \l_@@_saved_row_tl, + \l_@@_saved_col_tl, + \l_@@_saved_span_tl \space + ( + \int_compare:nNnTF \l_@@_saved_table_cols_tl = 0 + { outer~ level } + { max:~ \l_@@_saved_table_cols_tl } + ) + } +% \end{macrocode} +% These are the initial values when starting a table: +% \begin{macrocode} + \int_gzero:N \g_@@_row_int + \int_gzero:N \g_@@_col_int + \tl_gset:Nn \g_@@_span_tl {1} + \seq_gclear:N\g_@@_struct_rows_seq + \seq_gclear:N\g_@@_struct_cells_seq + \seq_gclear:N\g_@@_struct_cur_seq +% \end{macrocode} +% +% \begin{macrocode} + \everycr{% + \noalign{% +% \end{macrocode} +% We use \cs{g_@@_col_int} equal zero to indicate that we are just +% after a TR (or at the very beginning of the table). Using the row +% count is not so good as longtable may split the table in chunks. +% \begin{macrocode} + \int_compare:nNnT \g_@@_col_int > 0 + { \UseSocket{tagsupport/tblrow/end} } + \int_gincr:N \g_@@_row_int % this row about to start + \int_gzero:N \g_@@_col_int % we are before first col + }% + }% + \tabskip\z@skip\halign} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\multicolumn} +% +% \cs{multicolumn} is also defined in \pkg{array}. The redefinition +% has to solve two problems: it must handle the row begin if it is +% used there, and it must save the numbers of cells it spans so +% that we can add a suitable ColSpan attribute.\footnote{FMi: This can +% now perhaps cleaned up somewhat} +% \begin{macrocode} +\long\def\multicolumn#1#2#3{% + % alternative: determine first col with vmode test ... + % \ifvmode + % \multispan{#1}\typeout{A==> vmode}% + % \else + % \multispan{#1}\typeout{A==> not vmode} + % \fi + % but this makes the \crcr handling really complicated which would + % then need to become something like + % \ifvmode \expandafter \@gobble + % \else \expandafter \@iden \fi {\cr\noalign{do something}}% + % so not used. + % Instead: + \multispan{#1}\begingroup +% \end{macrocode} +% Insert rowbegin socket only if this multicolumn +% replaces the preamble of the first column. In that case we have +% to set \cs{g_@@_col_int} to 1 since this is no longer done in the +% preamble for the cell. +% \begin{macrocode} + \int_compare:nNnTF \g_@@_col_int = 0 + { + \UseSocket{tagsupport/tblrow/begin} + \int_gset:Nn \g_@@_col_int {1} + } +% \end{macrocode} +% If we are in a later column we use \cs{g_@@_span_tl} from the +% previous column to update. +% \begin{macrocode} + { + \int_gadd:Nn \g_@@_col_int { \g_@@_span_tl } + } +% \end{macrocode} +% Then we set the span value so that it can be use in the next column. +% \begin{macrocode} + \tl_gset:Nn \g_@@_span_tl {#1} +% \end{macrocode} +% +% \begin{macrocode} + \def\@addamp{\if@firstamp\@firstampfalse \else + \@preamerr 5\fi}% + \@mkpream{#2}\@addtopreamble\@empty + \endgroup +% \end{macrocode} +% Now we update the colspan attribute. This needs setting after +% the group as it is hidden inside the plug in \cs{insert@column}. +% \begin{macrocode} + \@@_set_colspan:n {#1} +% \end{macrocode} +% \begin{macrocode} + \def\@sharp{#3}% + \@arstrut \@preamble + \null + \ignorespaces} +% \end{macrocode} +% \end{macro} +% +% \subsection{longtable} +% +% Longtable is complicated. When at the begin the \cs{endhead}, +% \cs{endfirsthead}, \cs{endfoot} and \cs{endlastfoot} are used to +% setup head and foot they create each a structure subtree with one or +% more rows. From this structures we want to keep at most two (head +% and foot) and move the foot to the end of the table. When the head +% and foot boxes are (re)inserted on following pages we want to mark +% them up as artifact with the exception of the head at the begin and +% the foot box at the end. +% +% TODO: When a line is killed the structure subtree is there already +% too and must be removed. +% +% Hyperref patches longtable. This must be disabled and replace with +% genuine code +% \begin{macrocode} +\let\@kernel@refstepcounter\refstepcounter +\def\hyper@nopatch@longtable{} +% \end{macrocode} +% \begin{macrocode} +\def\@@_patch_LT@array[#1]#2{% +% \end{macrocode} +% \cs{LT@array} is executed in a group, so we can disable para-tagging here. +% \begin{macrocode} + \UseSocket{tagsupport/tbl/init}% + \@kernel@refstepcounter{table}\stepcounter{LT@tables}% +% \end{macrocode} +% The target is created rather late and a \cs{label} can come earlier, +% so we have to define \cs{@currentHref} explicitly. We can't currently +% assume that \cs{theHtable} is defined always. +% \begin{macrocode} + \tl_gset:Ne \@currentHref {table.\cs_if_exist_use:N\theHtable} + \int_gzero:N \g_@@_row_int + \seq_gclear:N\g_@@_struct_rows_seq + \seq_gclear:N\g_@@_struct_cells_seq + \seq_gclear:N\g_@@_struct_cur_seq + \seq_gclear:N\g_@@_LT@firsthead_rows_seq + \seq_gclear:N\g_@@_LT@head_rows_seq + \seq_gclear:N\g_@@_LT@lastfoot_rows_seq + \seq_gclear:N\g_@@_LT@foot_rows_seq + \if l#1% + \LTleft\z@ \LTright\fill + \else\if r#1% + \LTleft\fill \LTright\z@ + \else\if c#1% + \LTleft\fill \LTright\fill + \fi\fi\fi + \let\LT@mcol\multicolumn + \let\LT@@@@tabarray\@tabarray + \let\LT@@@@hl\hline + \def\@tabarray{% + \let\hline\LT@@@@hl + \LT@@@@tabarray}% + \let\\\LT@tabularcr + \let\tabularnewline\\% + \def\newpage{\noalign{\break}}% + \def\pagebreak{\noalign{\ifnum`}=0\fi\@testopt{\LT@no@pgbk-}4}% + \def\nopagebreak{\noalign{\ifnum`}=0\fi\@testopt\LT@no@pgbk4}% + \let\hline\LT@hline \let\kill\LT@kill\let\caption\LT@caption + \@tempdima\ht\strutbox + \let\@endpbox\LT@endpbox + \ifx\extrarowheight\@undefined + \let\@acol\@tabacol + \let\@classz\@tabclassz \let\@classiv\@tabclassiv + \def\@startpbox{\vtop\LT@startpbox}% + \let\@@@@startpbox\@startpbox + \let\@@@@endpbox\@endpbox + \let\LT@LL@FM@cr\@tabularcr + \else + \advance\@tempdima\extrarowheight + \col@sep\tabcolsep + \let\@startpbox\LT@startpbox\let\LT@LL@FM@cr\@arraycr + \fi + \setbox\@arstrutbox\hbox{\vrule + \@height \arraystretch \@tempdima + \@depth \arraystretch \dp \strutbox + \@width \z@}% + \let\@sharp##\let\protect\relax + \begingroup + \@mkpream{#2}% + \@@_determine_table_cols: + \xdef\LT@bchunk{% +% \end{macrocode} +% At the start of a chunk we set \cs{g_@@_col_int} to zero to make +% sure that we aren't generating /TR with the \cs{cr} ending the +% chunk preamble. +% \begin{macrocode} + \int_gzero:N \g_@@_col_int + \global\advance\c@LT@chunks\@ne + \global\LT@rows\z@\setbox\z@\vbox\bgroup + \LT@setprevdepth + \tabskip\LTleft \noexpand\halign to\hsize\bgroup + \tabskip\z@ \@arstrut +% \end{macrocode} +% Insert the socket and the setting of the conditional +% \begin{macrocode} + \UseSocket{tagsupport/tblrow/begin}% + \@@_init_cell_data: +% \end{macrocode} +% \begin{macrocode} + \@preamble \tabskip\LTright \cr}% + \endgroup + \expandafter\LT@nofcols\LT@bchunk&\LT@nofcols + \LT@make@row + \m@th\let\par\@empty +% \end{macrocode} +% Socket and conditional +% \begin{macrocode} + \everycr{% + \noalign{% +% \end{macrocode} +% In \pkg{longtable} we have a bunch of extra \cs{cr}s that are +% executed whenever a chunk ends. In that case they should not +% increment the main row counter, sigh. +% \begin{macrocode} + \typeout{--longtable-->~chunk~row:~ \the\LT@rows \space + row:~ \the\g_@@_row_int \space + column:~ \the\g_@@_col_int + } + \int_compare:nNnT \g_@@_col_int > 0 + { + \UseSocket{tagsupport/tblrow/end} + } +% \end{macrocode} +% This prevents any of the additional \cs{cr}s at the end of the +% chunk to add another /TR. Then once we really start a new chunk +% it gets incremented so\ldots +% \begin{macrocode} + \int_gzero:N \g_@@_col_int % before first col +% \end{macrocode} +% And for the same reason such \cs{cr}s should not increment the +% main row counter (but it has to be incremented after the preamble +% of a chunk), so here we test against \cs{LT@rows} which is +% \cs{LTchunksize} at the end of a chunk. +% \begin{macrocode} + \int_compare:nNnT \LT@rows < \LTchunksize + { \int_gincr:N \g_@@_row_int } % this row about to start + }% + }% +% \end{macrocode} +% \begin{macrocode} + \lineskip\z@\baselineskip\z@ + \LT@bchunk} +% \end{macrocode} +% The end code most stop to insert the endrow too. +% \begin{macrocode} +\def\@@_patch_endlongtable{% + \@@_store_missing_cells:n{endlongtable} + \crcr + \noalign{% + \UseSocket{tagsupport/tbl/finalize/longtable} + \int_gzero:N \g_@@_row_int % this prevents considering the next + % \crcr as another row end. + \let\LT@entry\LT@entry@chop + \xdef\LT@save@row{\LT@save@row}}% + \LT@echunk + \LT@start + \unvbox\z@ + \LT@get@widths + \if@filesw + {\let\LT@entry\LT@entry@write\immediate\write\@auxout{% + \gdef\expandafter\noexpand + \csname LT@\romannumeral\c@LT@tables\endcsname + {\LT@save@row}}}% + \fi + \ifx\LT@save@row\LT@@@@save@row + \else + \LT@warn{Column~\@width s~have~changed\MessageBreak + in~table~\thetable}% + \LT@final@warn + \fi + \endgraf\penalty -\LT@end@pen + \ifvoid\LT@foot\else + \global\advance\vsize\ht\LT@foot + \global\advance\@colroom\ht\LT@foot + \dimen@\pagegoal\advance\dimen@\ht\LT@foot\pagegoal\dimen@ + \fi + \endgroup + \global\@mparbottom\z@ + \endgraf\penalty\z@\addvspace\LTpost + \ifvoid\footins\else\insert\footins{}\fi} +% \end{macrocode} +% +% +% +% \begin{macro}{\@@_patch_LT@t@bularcr} +% +% \begin{macrocode} +\def\@@_patch_LT@t@bularcr{% + \global\advance\LT@rows\@ne + \ifnum\LT@rows=\LTchunksize +% \end{macrocode} +% At the end of the chunk \verb=\\= is doing something special and +% so we loose \cs{@@_store_missing_cells:n}. Below is about the +% right place to add it do this code branch. +% \begin{macrocode} + \@@_store_missing_cells:n{echunk} + \gdef\LT@setprevdepth{% + \prevdepth\z@ + \global\let\LT@setprevdepth\relax}% + \expandafter\LT@xtabularcr + \else + \ifnum0=`{}\fi + \expandafter\LT@LL@FM@cr + \fi} + +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_patch_LT@end@hd@ft} +% This command is used to store the head and foot boxes. +% We need to retrieve and store the row so that we can clean +% up the structure in the finalize code. +% \begin{macrocode} +\def\@@_patch_LT@end@hd@ft#1{% +% \end{macrocode} +% To handle missing columns in the header we need this: +% \begin{macrocode} + \__tbl_store_missing_cells:n{head/foot} + \int_step_inline:nn + { \LT@rows + 1 } + { + \seq_gput_left:ce + {g_@@_\cs_to_str:N #1 _rows_seq } + { \int_eval:n {\g_@@_row_int + 1 - ##1 } } + } +% \end{macrocode} +% We also have to set the chunk rows to its max value before +% calling \cs{LTechunk} so that we don't get extra increments of +% the main row counter due to \cs{everycr}. +% \begin{macrocode} + \int_gset:Nn \LT@rows { \LTchunksize } + \LT@echunk + \ifx\LT@start\endgraf + \LT@err + {Longtable head or foot not at start of table}% + {Increase LTchunksize}% + \fi + \setbox#1\box\z@ + \LT@get@widths + \LT@bchunk} +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\@@_patch_LT@start} +% \begin{macrocode} +\def\@@_patch_LT@start{% + \let\LT@start\endgraf + \endgraf\penalty\z@\vskip\LTpre\endgraf + \ifdim \pagetotal<\pagegoal \else + \dimen@=\pageshrink + \advance \dimen@ 1sp % + \kern\dimen@\penalty 9999\endgraf \kern-\dimen@ + \fi + \dimen@\pagetotal + \advance\dimen@ \ht\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi + \advance\dimen@ \dp\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi + \advance\dimen@ \ht\LT@foot + \edef\LT@reset@vfuzz{\vfuzz\the\vfuzz\vbadness\the\vbadness\relax}% + \vfuzz\maxdimen + \vbadness\@M + \setbox\tw@\copy\z@ + \setbox\tw@\vsplit\tw@ to \ht\@arstrutbox + \setbox\tw@\vbox{\unvbox\tw@}% + \LT@reset@vfuzz + \advance\dimen@ \ht + \ifdim\ht\@arstrutbox>\ht\tw@\@arstrutbox\else\tw@\fi + \advance\dimen@\dp + \ifdim\dp\@arstrutbox>\dp\tw@\@arstrutbox\else\tw@\fi + \advance\dimen@ -\pagegoal + \ifdim \dimen@>\z@ + \vfil\break + \else + \ifdim\pageshrink>\z@\pageshrink\z@\fi + \fi + \global\@colroom\@colht + \ifvoid\LT@foot\else + \global\advance\vsize-\ht\LT@foot + \global\advance\@colroom-\ht\LT@foot + \dimen@\pagegoal\advance\dimen@-\ht\LT@foot\pagegoal\dimen@ + \maxdepth\z@ + \fi + \MakeLinkTarget{table} + \ifvoid\LT@firsthead\copy\LT@head\else\box\LT@firsthead\fi\nobreak +% \end{macrocode} +% Avoid that following uses of the box add content: +% \begin{macrocode} + \tagmcbegin{artifact} + \tag_mc_reset_box:N\LT@head + \tagmcend + \output{\LT@output}} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_patch_LT@output} +% We must also avoid that the reuse of the foot box leads to +% duplicated content: +% \begin{macrocode} +\def\@@_patch_LT@output{% + \ifnum\outputpenalty <-\@Mi + \ifnum\outputpenalty > -\LT@end@pen + \LT@err{floats and marginpars not allowed in a longtable}\@ehc + \else + \setbox\z@\vbox{\unvbox\@cclv}% + \ifdim \ht\LT@lastfoot>\ht\LT@foot + \dimen@\pagegoal + \advance\dimen@\ht\LT@foot + \advance\dimen@-\ht\LT@lastfoot + \ifdim\dimen@<\ht\z@ + \setbox\@cclv\vbox{\unvbox\z@\copy\LT@foot\vss}% + \@makecol + \@outputpage + \global\vsize\@colroom + \setbox\z@\vbox{\box\LT@head}% + \fi + \fi + \unvbox\z@\box\ifvoid\LT@lastfoot\LT@foot\else\LT@lastfoot\fi +% \end{macrocode} +% Reset attribute of foot box: +% \begin{macrocode} + \tagmcbegin{artifact} + \tag_mc_reset_box:N \LT@foot + \tagmcend + \fi + \else + \setbox\@cclv\vbox{\unvbox\@cclv\copy\LT@foot\vss}% +% \end{macrocode} +% Reset attribute of foot box: +% \begin{macrocode} + \tagmcbegin{artifact} + \tag_mc_reset_box:N \LT@foot + \tagmcend + \@makecol + \@outputpage + \global\vsize\@colroom + \copy\LT@head\nobreak + \fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_patch_\LT@makecaption} +% This patch is quite similar to the one for LaTeX's \cs{@makecaption} +% we also have to change the parbox sockets. +% \begin{macrocode} +\def\@@_patch_LT@makecaption#1#2#3{% + \LT@mcol\LT@cols c{% + % test can go after merge + \str_if_exist:cT { l__socket_tagsupport/parbox/before_plug_str } + { + \AssignSocketPlug{tagsupport/parbox/before}{noop} + \AssignSocketPlug{tagsupport/parbox/after}{noop} + } + \hbox to\z@{\hss\parbox[t]\LTcapwidth{% + \reset@font + \tag_stop:n{caption} + \sbox\@tempboxa{#1{#2:~}#3}% + \tag_start:n{caption} + \ifdim\wd\@tempboxa>\hsize + #1{#2:~}#3% + \else + \hbox to\hsize{\hfil#1{#2:~}#3\hfil}% + \fi + \endgraf\vskip\baselineskip}% + \hss}}} +% \end{macrocode} +% \end{macro} +% +% +% +% Overwrite the longtable definition. That will probably break somewhere as +% they are various package which patch too. +% \begin{macrocode} +\AddToHook{package/longtable/after} + { + \seq_new:N \g_@@_LT@firsthead_rows_seq + \seq_new:N \g_@@_LT@head_rows_seq + \seq_new:N \g_@@_LT@lastfoot_rows_seq + \seq_new:N \g_@@_LT@foot_rows_seq + \cs_set_eq:NN \LT@array\@@_patch_LT@array + \cs_set_eq:NN \endlongtable\@@_patch_endlongtable + \cs_set_eq:NN \LT@start\@@_patch_LT@start + \cs_set_eq:NN \LT@output\@@_patch_LT@output + \cs_set_eq:NN \LT@t@bularcr\@@_patch_LT@t@bularcr + \cs_set_eq:NN \LT@end@hd@ft\@@_patch_LT@end@hd@ft + \cs_set_eq:NN \LT@makecaption\@@_patch_LT@makecaption + } +% \end{macrocode} + + + + + +% \subsection{tabularx} +% +% In tabularx we mainly need to ensure that no tagging is done during +% the trial. +% +% \begin{macrocode} +\def\@@_patch_TX@endtabularx{% + \expandafter\expandafter\expandafter + \TX@find@endtabularxa\csname end\TX@\endcsname + \endtabularx\TX@\endtabularx\TX@find@endtabularxa + \expandafter\TX@newcol\expandafter{\tabularxcolumn{\TX@col@width}}% + \let\verb\TX@verb + \def\@elt##1{\global\value{##1}\the\value{##1}\relax}% + \edef\TX@ckpt{\cl@@@@ckpt}% + \let\@elt\relax + \TX@old@table\maxdimen + \TX@col@width\TX@target + \global\TX@cols\@ne + \TX@typeout@ + {\@spaces Table Width\@spaces Column Width\@spaces X Columns}% +% \end{macrocode} +% Here we stop tagging: +% \begin{macrocode} + \tag_stop:n{tabularx} + \TX@trial{\def\NC@rewrite@X{% + \global\advance\TX@cols\@ne\NC@find p{\TX@col@width}}}% + \loop + \TX@arith + \ifTX@ + \TX@trial{}% + \repeat +% \end{macrocode} +% And now we restart it again. +% \begin{macrocode} + \tag_start:n{tabularx} + {\let\@footnotetext\TX@ftntext\let\@xfootnotenext\TX@xftntext + \csname tabular*\expandafter\endcsname\expandafter\TX@target + \the\toks@ + \csname endtabular*\endcsname}% + \global\TX@ftn\expandafter{\expandafter}\the\TX@ftn + \ifnum0=`{\fi}% + \expandafter\expandafter\expandafter + \TX@find@endtabularxbb + \expandafter\end\expandafter{\TX@}% + \endtabularx\TX@\endtabularx\TX@find@endtabularxb +} + +\AddToHook{package/tabularx/after} + {\cs_set_eq:NN \TX@endtabularx\@@_patch_TX@endtabularx } +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% +% \begin{macrocode} +%<*latex-lab> +\ProvidesFile{table-latex-lab-testphase.ltx} + [\ltlabtbldate\space v\ltlabtblversion\space latex-lab wrapper table] +\RequirePackage{latex-lab-testphase-table} +%</latex-lab> +% \end{macrocode} diff --git a/macros/latex-dev/required/latex-lab/latex-lab-table.pdf b/macros/latex-dev/required/latex-lab/latex-lab-table.pdf Binary files differnew file mode 100644 index 0000000000..997db2d1a7 --- /dev/null +++ b/macros/latex-dev/required/latex-lab/latex-lab-table.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-testphase.pdf b/macros/latex-dev/required/latex-lab/latex-lab-testphase.pdf Binary files differindex 0fd13aba89..c65847a04f 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-testphase.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-testphase.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-text.pdf b/macros/latex-dev/required/latex-lab/latex-lab-text.pdf Binary files differindex 4940583de0..a4e26db75f 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-text.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-text.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-toc-hyperref-changes.pdf b/macros/latex-dev/required/latex-lab/latex-lab-toc-hyperref-changes.pdf Binary files differindex e00a26b141..161e96f338 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-toc-hyperref-changes.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-toc-hyperref-changes.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.dtx b/macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.dtx index 632315a731..81c9edfe4d 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.dtx +++ b/macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.dtx @@ -17,8 +17,8 @@ % for those people who are interested or want to report an issue. % % dates for latex-lab-kernel-changes.sty (pulled from various sources, see ins) -\def\ltlabkerneldate{2023-07-20} -\def\ltlabkernelversion{0.85a} +\def\ltlabkerneldate{2023-10-16} +\def\ltlabkernelversion{0.85b} %<*driver> \documentclass{l3doc} \EnableCrossrefs @@ -66,6 +66,7 @@ [\ltlabkerneldate\space v\ltlabkernelversion\space General kernel and class changes] % \end{macrocode} +% % \subsection{Providing the counter representation \cs{theHxx} generally} % [kernel?] % @@ -151,8 +152,32 @@ \def\toclevel@subparagraph{5} \def\toclevel@figure{1} \def\toclevel@table{1} +% \end{macrocode} +% +%\subsection{Storing the relation between target names and structure numbers} +% To be able to add a /Ref key to structures the tagging makes use of target names +% and stores the relationship in a property. We add a hook to \cs{MakeLinkTarget} to +% catch as much as possible, see also tagging issue \#20. This should work also +% without hyperref. The property is defined in tagpdf-base, so the code would +% work also without tagging but we add a test anyway, this is probably faster. +% \begin{macrocode} +\ExplSyntaxOn +\AddToHookWithArguments{cmd/MakeLinkTarget/after} + { + \tag_if_active:T + { + \tl_if_blank:VF \@currentHref + { + \prop_gput:Nee \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} + } + } + } +\ExplSyntaxOff +% \end{macrocode} +% \begin{macrocode} %</kernelchange> % \end{macrocode} +% % \subsection{load kernel changes} % \begin{macrocode} %<*package> diff --git a/macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.pdf b/macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.pdf Binary files differindex 22016e835d..0a78ca15d9 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab-toc.dtx b/macros/latex-dev/required/latex-lab/latex-lab-toc.dtx index 81f6676a80..6def505e11 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-toc.dtx +++ b/macros/latex-dev/required/latex-lab/latex-lab-toc.dtx @@ -16,8 +16,8 @@ % % for those people who are interested or want to report an issue. % -\def\ltlabtocdate{2023-07-20} -\def\ltlabtocversion{0.85a} +\def\ltlabtocdate{2023-10-16} +\def\ltlabtocversion{0.85b} %<*driver> \documentclass{l3doc} \EnableCrossrefs @@ -54,12 +54,42 @@ { Code related to the tagging of toc-like lists} %</header> % \end{macrocode} -% +% \begin{documentation} % \section{Introduction} % % The followings contains various functions related to the tagging of the -% table of contents and similar list. The functions will at some time -% be moved inside the tagpdf code. +% table of contents and similar list. +% +% The structure of tocs consist of nested TOC and TOCI structures. +% The code uses the first argument of the \cs{contentsline} command to detect the +% level and to decided if a structure should be closed. The structure that +% should be used in \texttt{/Ref} key to link to the heading is detected from the +% target name in the fourth argument -- because of this with this code such a target +% name is created and stored also if hyperref is not loaded. +% +% \subsection{Manual toc additions} +% As the \texttt{/Ref} key relies on the target name, +% manual \cs{addcontentsline} commands must ensure that they reference the right +% structure. If an unnumbered heading command is used before this is normally the case, +% so the following should work fine: +% +% \begin{verbatim} +% \chapter*{Unnumbered} +% \addcontentsline{toc}{chapter}{Unnumbered} +% \end{verbatim} +% +% If there is no heading command a target name must be created manually \emph{inside the +% right structure} with \cs{MakeLinkTarget}: +% +% \begin{verbatim} +% \noindent % start e.g. P-structure +% \MakeLinkTarget*{unnumbered}% target inside the P-structure +% Unnumbered +% \addcontentsline{toc}{chapter}{Unnumbered} +% \end{verbatim} +% +% \end{documentation} +% \begin{implementation} % \begin{macrocode} %<*package> %<@@=tag> @@ -78,33 +108,28 @@ % This variable records for (some or all, not clear yet) % destination names the related structure number to allow % to reference them in a Ref. The key is the destination. -% Moved into tagpdf! +% Defined by tagpdf. % \end{variable} % -% We use \cs{refstepcounter} to store the relation between +% \cs{refstepcounter} doesn't use \cs{MakeLinkTarget} (yet) so +% we have to patch it too to store the relation between % destination names/\cs{@currentHref} and structure numbers % -% TODO: the functions should be moved into tagpdf so that one -% doesn't has to test if the prop exists or not. +% The property is set up in tagpdf-test so that one +% doesn't has to check if the prop exists or not. % \begin{macrocode} \AddToHook{cmd/refstepcounter/after} { \tl_if_blank:VF \@currentHref { - \prop_if_exist:NT \g_@@_struct_dest_num_prop - { - \prop_gput:Nxx \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} - } + \prop_gput:Nee \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} } } \AddToHook{cmd/H@refstepcounter/after} { \tl_if_blank:VF \@currentHref { - \prop_if_exist:NT \g_@@_struct_dest_num_prop - { - \prop_gput:Nxx \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} - } + \prop_gput:Nee \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}} } } % \end{macrocode} @@ -375,3 +400,4 @@ %</latex-lab> % \end{macrocode} +% \end{implementation} diff --git a/macros/latex-dev/required/latex-lab/latex-lab-toc.pdf b/macros/latex-dev/required/latex-lab/latex-lab-toc.pdf Binary files differindex 64853b0e8b..eafeeec42e 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab-toc.pdf +++ b/macros/latex-dev/required/latex-lab/latex-lab-toc.pdf diff --git a/macros/latex-dev/required/latex-lab/latex-lab.ins b/macros/latex-dev/required/latex-lab/latex-lab.ins index a4aeb7289d..548f18a6fa 100644 --- a/macros/latex-dev/required/latex-lab/latex-lab.ins +++ b/macros/latex-dev/required/latex-lab/latex-lab.ins @@ -152,6 +152,11 @@ where one can also log issues in case there are any. \generate{\file{firstaid-latex-lab-testphase.ltx}{\from{latex-lab-firstaid.dtx}{latex-lab}}} \generate{\file{latex-lab-testphase-firstaid.sty}{\from{latex-lab-firstaid.dtx}{package}}} +%table +\generate{\file{table-latex-lab-testphase.ltx}{\from{latex-lab-table.dtx}{latex-lab}}} +\generate{\file{latex-lab-testphase-table.sty}{\from{latex-lab-table.dtx}{package}}} + + % stop docstrip adding \endinput \preamble \endpreamble |