% multicoltab.sty -- breakable table rows for multicols and ordinary pages % Copyright (C) 2026 Andres Zanzani % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3c of this license or (at % your option) any later version. The latest version of this license is at % https://www.latex-project.org/lppl.txt and version 1.3c or later is part of % all distributions of LaTeX version 2008 or later. % % This work has the LPPL maintenance status "maintained". % The Current Maintainer of this work is Andres Zanzani . \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{multicoltab}[2026/09/04 v0.8 Breakable table rows] \RequirePackage{xparse} \RequirePackage{array} \RequirePackage{tabularx} \RequirePackage{keyval} \makeatletter % Each source row becomes its own tabularx. multicols can consequently break % between rows without replacing its own page and column output routine. \newif\ifmulticoltab@active \newif\ifmulticoltab@hashead \newif\ifmulticoltab@measure \newif\ifmulticoltab@naturalglobal \def\multicoltab@preamble{} \def\multicoltab@begin{} \def\multicoltab@typesetrow{} \def\multicoltab@typesetrule{} \def\multicoltab@headbefore{} \def\multicoltab@headafter{} \def\multicoltab@headcells{} \def\multicoltab@headextra{} \newlength\multicoltab@width \newlength\multicoltab@rowsep \newcount\multicoltab@breakpenalty \ExplSyntaxOn \seq_new:N \l_multicoltab_column_kinds_seq \seq_new:N \l_multicoltab_column_widths_seq \seq_new:N \l_multicoltab_cells_seq \tl_new:N \l_multicoltab_preamble_tl \tl_new:N \l_multicoltab_output_preamble_tl \tl_new:N \l_multicoltab_measured_width_tl \int_new:N \l_multicoltab_column_int \int_new:N \l_multicoltab_cell_int \int_new:N \l_multicoltab_preamble_args_int \box_new:N \l_multicoltab_measure_box \dim_new:N \l_multicoltab_cell_width_dim \bool_new:N \l_multicoltab_preamble_safe_bool \bool_new:N \l_multicoltab_has_natural_bool \bool_new:N \l_multicoltab_has_x_bool \cs_generate_variant:Nn \seq_set_item:Nnn {NnV} \cs_new_protected:Npn \multicoltab_scan_preamble: { \seq_clear:N \l_multicoltab_column_kinds_seq \int_zero:N \l_multicoltab_column_int \bool_set_true:N \l_multicoltab_preamble_safe_bool \bool_set_false:N \l_multicoltab_has_natural_bool \bool_set_false:N \l_multicoltab_has_x_bool \int_zero:N \l_multicoltab_preamble_args_int \exp_args:NNo \tl_set:Nn \l_multicoltab_preamble_tl \multicoltab@preamble \tl_map_inline:Nn \l_multicoltab_preamble_tl { \multicoltab_scan_preamble_item:n {##1} } \seq_clear:N \l_multicoltab_column_widths_seq \int_step_inline:nn { \l_multicoltab_column_int } { \seq_put_right:Nn \l_multicoltab_column_widths_seq {0pt} } } \cs_new_protected:Npn \multicoltab_scan_preamble_item:n #1 { \int_compare:nNnTF { \l_multicoltab_preamble_args_int } > {0} { \int_decr:N \l_multicoltab_preamble_args_int } { \tl_if_single_token:nTF {#1} { \multicoltab_scan_preamble_token:N #1 } { \bool_set_false:N \l_multicoltab_preamble_safe_bool \bool_set_true:N \l_multicoltab_has_x_bool } } } \cs_new_protected:Npn \multicoltab_scan_preamble_token:N #1 { \token_if_space:NTF #1 { } { \token_if_eq_charcode:NNTF #1 l { \multicoltab_add_natural_column_kind:n {l} } { \token_if_eq_charcode:NNTF #1 c { \multicoltab_add_natural_column_kind:n {c} } { \token_if_eq_charcode:NNTF #1 r { \multicoltab_add_natural_column_kind:n {r} } { \token_if_eq_charcode:NNTF #1 X { \multicoltab_add_column_kind:n {X} \bool_set_true:N \l_multicoltab_has_x_bool } { \token_if_eq_charcode:NNTF #1 p { \multicoltab_add_fixed_kind:n {1} } { \token_if_eq_charcode:NNTF #1 m { \multicoltab_add_fixed_kind:n {1} } { \token_if_eq_charcode:NNTF #1 b { \multicoltab_add_fixed_kind:n {1} } { \token_if_eq_charcode:NNTF #1 w { \multicoltab_add_fixed_kind:n {2} } { \token_if_eq_charcode:NNTF #1 W { \multicoltab_add_fixed_kind:n {2} } { \token_if_eq_charcode:NNTF #1 | { } { \token_if_eq_charcode:NNTF #1 @ { \int_set:Nn \l_multicoltab_preamble_args_int {1} } { \token_if_eq_charcode:NNTF #1 ! { \int_set:Nn \l_multicoltab_preamble_args_int {1} } { \token_if_eq_charcode:NNTF #1 > { \bool_set_false:N \l_multicoltab_preamble_safe_bool \int_set:Nn \l_multicoltab_preamble_args_int {1} } { \token_if_eq_charcode:NNTF #1 < { \bool_set_false:N \l_multicoltab_preamble_safe_bool \int_set:Nn \l_multicoltab_preamble_args_int {1} } { \bool_set_false:N \l_multicoltab_preamble_safe_bool % An alias may expand to X, so retain tabularx. \bool_set_true:N \l_multicoltab_has_x_bool } } } } } } } } } } } } } } } } \cs_new_protected:Npn \multicoltab_add_fixed_kind:n #1 { \multicoltab_add_column_kind:n {F} \int_set:Nn \l_multicoltab_preamble_args_int {#1} } \cs_new_protected:Npn \multicoltab_add_column_kind:n #1 { \int_incr:N \l_multicoltab_column_int \seq_put_right:Nn \l_multicoltab_column_kinds_seq {#1} } \cs_new_protected:Npn \multicoltab_add_natural_column_kind:n #1 { \bool_set_true:N \l_multicoltab_has_natural_bool \multicoltab_add_column_kind:n {#1} } \cs_new_protected:Npn \multicoltab_measure_cells:n #1 { \cs_set:Npn \newline { \space } \cs_set:Npn \multicoltab_discard_rowcolor: { \peek_charcode:NTF [ { \multicoltab_discard_rowcolor_optional:w } { \multicoltab_discard_rowcolor_mandatory:w } } \cs_set:Npn \multicoltab_discard_rowcolor_optional:w [##1]##2 {} \cs_set:Npn \multicoltab_discard_rowcolor_mandatory:w ##1 {} \cs_set_eq:NN \rowcolor \multicoltab_discard_rowcolor: \seq_set_split:Nnn \l_multicoltab_cells_seq { & } {#1} \int_set:Nn \l_multicoltab_cell_int {1} \seq_map_inline:Nn \l_multicoltab_cells_seq { \tl_set:Nn \l_multicoltab_row_tl {##1} \tl_trim_spaces:N \l_multicoltab_row_tl \exp_args:NV \multicoltab_measure_one_cell:n \l_multicoltab_row_tl } } \cs_new_protected:Npn \multicoltab_measure_one_cell:n #1 { \tl_if_empty:nTF {#1} { \int_incr:N \l_multicoltab_cell_int } { \tl_if_head_is_group:nTF {#1} { \multicoltab_measure_normal_cell:n {#1} } { \multicoltab_measure_one_cell_aux:w #1 \q_stop } } } \cs_new_protected:Npn \multicoltab_measure_one_cell_aux:w #1#2\q_stop { \token_if_eq_meaning:NNTF #1 \multicoltab@savedmulticolumn { \multicoltab_measure_multicolumn:w #1#2 \q_stop } { \token_if_eq_meaning:NNTF #1 \rowcolor { \tl_if_in:nnTF {#2} {\multicolumn} { % Preserve the source preamble rather than parsing every % rowcolor form that could precede a multicolumn. \bool_set_false:N \l_multicoltab_preamble_safe_bool \int_incr:N \l_multicoltab_cell_int } { \multicoltab_measure_normal_cell:n {#1#2} } } { \multicoltab_measure_normal_cell:n {#1#2} } } } \cs_new_protected:Npn \multicoltab_measure_normal_cell:n #1 { \int_compare:nNnT { \l_multicoltab_cell_int } < { \int_eval:n { \l_multicoltab_column_int + 1 } } { \ifmulticoltab@naturalglobal \bool_if:NT \l_multicoltab_preamble_safe_bool { \exp_args:Ne \multicoltab_measure_for_kind:nn { \seq_item:Nn \l_multicoltab_column_kinds_seq {\l_multicoltab_cell_int} } {#1} } \fi } \int_incr:N \l_multicoltab_cell_int } \cs_new_protected:Npn \multicoltab_measure_multicolumn:w \multicolumn #1#2#3#4\q_stop { \int_add:Nn \l_multicoltab_cell_int {#1} } \cs_new_protected:Npn \multicoltab_measure_for_kind:nn #1#2 { \str_case:nn {#1} { {l}{ \multicoltab_measure_natural_cell:n {#2} } {c}{ \multicoltab_measure_natural_cell:n {#2} } {r}{ \multicoltab_measure_natural_cell:n {#2} } } } \cs_new_protected:Npn \multicoltab_measure_natural_cell:n #1 { \hbox_set:Nn \l_multicoltab_measure_box {\strut #1} \dim_set:Nn \l_multicoltab_cell_width_dim { \seq_item:Nn \l_multicoltab_column_widths_seq {\l_multicoltab_cell_int} } \dim_compare:nNnT { \box_wd:N \l_multicoltab_measure_box } > { \l_multicoltab_cell_width_dim } { % Leave a small allowance for the paragraph-box setup used by p. \tl_set:Nx \l_multicoltab_measured_width_tl {\dim_eval:n {\box_wd:N \l_multicoltab_measure_box + 1pt}} \seq_set_item:NnV \l_multicoltab_column_widths_seq {\l_multicoltab_cell_int} \l_multicoltab_measured_width_tl } } \cs_new_protected:Npn \multicoltab_build_output_preamble: { \tl_clear:N \l_multicoltab_output_preamble_tl \int_zero:N \l_multicoltab_column_int \int_zero:N \l_multicoltab_preamble_args_int \tl_map_inline:Nn \l_multicoltab_preamble_tl { \multicoltab_build_preamble_item:n {##1} } } \cs_new_protected:Npn \multicoltab_build_preamble_item:n #1 { \int_compare:nNnTF { \l_multicoltab_preamble_args_int } > {0} { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {{#1}} \int_decr:N \l_multicoltab_preamble_args_int } { \tl_if_single_token:nTF {#1} { \multicoltab_build_preamble_token:N #1 } { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {{#1}} } } } \cs_new_protected:Npn \multicoltab_build_preamble_token:N #1 { \token_if_eq_charcode:NNTF #1 l { \multicoltab_add_output_column:n {l} } { \token_if_eq_charcode:NNTF #1 c { \multicoltab_add_output_column:n {c} } { \token_if_eq_charcode:NNTF #1 r { \multicoltab_add_output_column:n {r} } { \token_if_eq_charcode:NNTF #1 X { \multicoltab_add_output_column:n {X} } { \token_if_eq_charcode:NNTF #1 p { \multicoltab_add_fixed_output_column:nn {p}{1} } { \token_if_eq_charcode:NNTF #1 m { \multicoltab_add_fixed_output_column:nn {m}{1} } { \token_if_eq_charcode:NNTF #1 b { \multicoltab_add_fixed_output_column:nn {b}{1} } { \token_if_eq_charcode:NNTF #1 w { \multicoltab_add_fixed_output_column:nn {w}{2} } { \token_if_eq_charcode:NNTF #1 W { \multicoltab_add_fixed_output_column:nn {W}{2} } { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {#1} \token_if_eq_charcode:NNT #1 @ { \int_set:Nn \l_multicoltab_preamble_args_int {1} } \token_if_eq_charcode:NNT #1 ! { \int_set:Nn \l_multicoltab_preamble_args_int {1} } \token_if_eq_charcode:NNT #1 > { \int_set:Nn \l_multicoltab_preamble_args_int {1} } \token_if_eq_charcode:NNT #1 < { \int_set:Nn \l_multicoltab_preamble_args_int {1} } } } } } } } } } } } \cs_new_protected:Npn \multicoltab_add_fixed_output_column:nn #1#2 { \multicoltab_add_fixed_source_column:n {#1} \int_set:Nn \l_multicoltab_preamble_args_int {#2} } \cs_new_protected:Npn \multicoltab_add_fixed_source_column:n #1 { \int_incr:N \l_multicoltab_column_int \tl_put_right:Nn \l_multicoltab_output_preamble_tl {#1} } \cs_new_protected:Npn \multicoltab_add_output_column:n #1 { \int_incr:N \l_multicoltab_column_int \str_case:nnF {#1} { {X} { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {X} } {l} { \multicoltab_add_natural_output_column:n {l} } {c} { \multicoltab_add_natural_output_column:n {c} } {r} { \multicoltab_add_natural_output_column:n {r} } } { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {#1} } } \cs_new_protected:Npn \multicoltab_add_natural_output_column:n #1 { \ifmulticoltab@naturalglobal \bool_if:NTF \l_multicoltab_preamble_safe_bool { \multicoltab_add_fixed_column:n {#1} } { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {#1} } \else \tl_put_right:Nn \l_multicoltab_output_preamble_tl {#1} \fi } \cs_new_protected:Npn \multicoltab_add_fixed_column:n #1 { \tl_if_eq:nnTF {#1} {c} { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {>{\centering\arraybackslash}p} } { \tl_if_eq:nnTF {#1} {r} { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {>{\raggedleft\arraybackslash}p} } { \tl_put_right:Nn \l_multicoltab_output_preamble_tl {p} } } \tl_put_right:Nx \l_multicoltab_output_preamble_tl { {\seq_item:Nn \l_multicoltab_column_widths_seq {\int_use:N \l_multicoltab_column_int}} } } \cs_new_protected:Npn \multicoltab_prepare:n #1 { \multicoltab_scan_preamble: \let\multicoltab@savedmulticolumn\multicolumn \let\multicoltab@savednewline\newline \let\multicoltab@savedrowcolor\rowcolor \multicoltab@measuretrue \multicoltab@hasheadfalse \multicoltab@parser #1\\\multicoltab@stop \let\multicolumn\multicoltab@savedmulticolumn \let\newline\multicoltab@savednewline \let\rowcolor\multicoltab@savedrowcolor \multicoltab@measurefalse \multicoltab@hasheadfalse \ifmulticoltab@naturalglobal \bool_if:NT \l_multicoltab_has_natural_bool { \bool_if:NF \l_multicoltab_preamble_safe_bool { \PackageWarning{multicoltab} {Natural-column~widths~cannot~be~synchronized~for~this~preamble} } } \fi \multicoltab_build_output_preamble: \bool_if:NTF \l_multicoltab_has_x_bool { \edef\multicoltab@begin{ \noexpand\begin{tabularx}{\the\multicoltab@width} {\exp_not:V \l_multicoltab_output_preamble_tl}} \let\multicoltab@typesetrow\multicoltab@typesetrow@x \let\multicoltab@typesetrule\multicoltab@typesetrule@x } { \edef\multicoltab@begin{ \noexpand\begin{tabular} {\exp_not:V \l_multicoltab_output_preamble_tl}} \let\multicoltab@typesetrow\multicoltab@typesetrow@fixed \let\multicoltab@typesetrule\multicoltab@typesetrule@fixed } } \cs_new_eq:NN \multicoltab@measurecells \multicoltab_measure_cells:n \cs_new_eq:NN \multicoltab@prepare \multicoltab_prepare:n \ExplSyntaxOff \define@key{multicoltab}{width}{\setlength\multicoltab@width{#1}} \define@key{multicoltab}{row-sep}{\setlength\multicoltab@rowsep{#1}} \define@key{multicoltab}{break-penalty}{% \multicoltab@breakpenalty=#1\relax } \def\multicoltab@natural@global{\multicoltab@naturalglobaltrue} \def\multicoltab@natural@local{\multicoltab@naturalglobalfalse} \define@key{multicoltab}{natural-widths}{% \@ifundefined{multicoltab@natural@#1}{% \PackageError{multicoltab}{Invalid natural-widths value `#1'}% {Use natural-widths=global or natural-widths=local.}% }{% \csname multicoltab@natural@#1\endcsname }% } \newcommand{\multicoltab@start}[2]{% \par \begingroup \multicoltab@activetrue \multicoltab@hasheadfalse \setkeys{multicoltab}{% width=\linewidth,row-sep=0pt,break-penalty=0, natural-widths=global,#1}% \def\multicoltab@preamble{#2}% \setlength{\parindent}{0pt}% \setlength{\parskip}{0pt}% } \newcommand{\multicoltab@end}{% \par \multicoltab@activefalse \endgroup } \newcommand{\multicoltab@check}{% \ifmulticoltab@active\else \PackageError{multicoltab}{Table command used outside multicoltab}% {Put the command between \string\begin{multicoltab} and \string\end{multicoltab}.}% \fi } \def\multicoltab@star{*} \newcommand{\multicoltab@finishrow}[1]{% \par \nointerlineskip \edef\multicoltab@tempa{#1}% \ifx\multicoltab@tempa\multicoltab@star \penalty10000 \else \penalty\multicoltab@breakpenalty \fi \vskip\multicoltab@rowsep } \newcommand{\multicoltab@emitrow}[5]{% \ifmulticoltab@measure \multicoltab@measurecells{#5}% \else \multicoltab@typesetrow{#2}{#5}{#3}{#4}% \multicoltab@finishrow{#1}% \fi } \newcommand{\multicoltab@typesetrow@x}[4]{% \noindent \multicoltab@begin #1#2\expandafter\\#3#4% \end{tabularx}% } \newcommand{\multicoltab@typesetrow@fixed}[4]{% \noindent \multicoltab@begin #1#2\expandafter\\#3#4% \end{tabular}% } % A booktabs rule is a noalign command and must not be followed by the row % terminator used for ordinary source rows. Emit it in an empty alignment. \newcommand{\multicoltab@typesetrule@x}[2]{% \noindent \begingroup \hbadness=10000 \multicoltab@begin #1#2% \end{tabularx}% \endgroup } \newcommand{\multicoltab@typesetrule@fixed}[2]{% \noindent \begingroup \hbadness=10000 \multicoltab@begin #1#2% \end{tabular}% \endgroup } \newcommand{\multicoltab@emitrule}[2]{% \ifmulticoltab@measure\else \multicoltab@typesetrule{#1}{#2}% \multicoltab@finishrow{*}% \fi } \newcommand{\multicoltab@sethead}[3]{% \ifmulticoltab@measure \multicoltab@measurecells{#3}% \else \def\multicoltab@headbefore{#1}% \def\multicoltab@headafter{#2}% \def\multicoltab@headcells{#3}% \let\multicoltab@headextra\multicoltab@rowextra \multicoltab@hasheadtrue \multicoltab@repeathead \fi } \newcommand{\multicoltab@repeathead}{% \ifmulticoltab@hashead \multicoltab@emitrow{*}{\multicoltab@headbefore}% {\multicoltab@headextra}{\multicoltab@headafter}% {\multicoltab@headcells}% \else \PackageError{multicoltab}{Heading repeated before it was declared}% {Declare a heading with \string\mchead first.}% \fi } % The body parser recognizes ordinary rows, headings, and explicit breaks. % TeX ignores delimiters inside braces, so a nested table or grouped line break % does not split the outer row. \ExplSyntaxOn \tl_new:N \l_multicoltab_row_tl \cs_new_protected:Npn \multicoltab@processrow #1#2#3 { \tl_set:Nn \l_multicoltab_row_tl {#1} \tl_replace_all:Nnn \l_multicoltab_row_tl { \par } { } \tl_trim_spaces:N \l_multicoltab_row_tl \tl_if_blank:VF \l_multicoltab_row_tl { \cs_set:Npn \multicoltab@rowstar {#2} \cs_set:Npn \multicoltab@rowextra {#3} \exp_args:NV \multicoltab@dispatch \l_multicoltab_row_tl } } \cs_new_protected:Npn \multicoltab@dispatchremainder #1 { \tl_set:Nn \l_multicoltab_row_tl {#1} \tl_trim_spaces:N \l_multicoltab_row_tl \tl_if_blank:VF \l_multicoltab_row_tl { \exp_args:NV \multicoltab@dispatch \l_multicoltab_row_tl } } \ExplSyntaxOff \long\def\multicoltab@parser#1\\{% \def\multicoltab@rawrow{#1}% \@ifnextchar*{\multicoltab@parser@star}{% \@ifnextchar[{\multicoltab@parser@extra}{\multicoltab@parser@plain}}% } \def\multicoltab@parser@star*{% \@ifnextchar[{\multicoltab@parser@star@extra}% {\multicoltab@parser@complete{*}{}}} \def\multicoltab@parser@star@extra[#1]{% \multicoltab@parser@complete{*}{[#1]}} \def\multicoltab@parser@extra[#1]{% \multicoltab@parser@complete{}{[#1]}} \def\multicoltab@parser@plain{\multicoltab@parser@complete{}{}} \def\multicoltab@parser@complete#1#2{% \expandafter\multicoltab@processrow\expandafter {\multicoltab@rawrow}{#1}{#2}% \@ifnextchar\multicoltab@stop {\multicoltab@parser@end}{\multicoltab@parser}% } \def\multicoltab@parser@end\multicoltab@stop{} \newcommand{\multicoltab@dispatch}[1]{% \def\multicoltab@rowcontents{#1}% \expandafter\multicoltab@dispatch@next\multicoltab@rowcontents \multicoltab@row@stop } \def\multicoltab@dispatch@next{% \@ifnextchar\mchead{\multicoltab@parse@shorthead}{\multicoltab@dispatch@break}} \def\multicoltab@dispatch@break{% \@ifnextchar\multicoltabbreak{\multicoltab@parse@columnbreak}{\multicoltab@dispatch@page}} \def\multicoltab@dispatch@page{% \@ifnextchar\multicoltabpagebreak{\multicoltab@parse@pagebreak}{\multicoltab@dispatch@repeat}} \def\multicoltab@dispatch@repeat{% \@ifnextchar\mcheadrepeat{\multicoltab@parse@repeathead}{\multicoltab@dispatch@toprule}} \def\multicoltab@dispatch@toprule{% \@ifnextchar\toprule{\multicoltab@parse@toprule}{\multicoltab@dispatch@midrule}} \def\multicoltab@dispatch@midrule{% \@ifnextchar\midrule{\multicoltab@parse@midrule}{\multicoltab@dispatch@bottomrule}} \def\multicoltab@dispatch@bottomrule{% \@ifnextchar\bottomrule{\multicoltab@parse@bottomrule}{\multicoltab@parse@normal}} \def\multicoltab@parse@toprule\toprule{\multicoltab@parse@rule{\toprule}} \def\multicoltab@parse@midrule\midrule{\multicoltab@parse@rule{\midrule}} \def\multicoltab@parse@bottomrule\bottomrule{\multicoltab@parse@rule{\bottomrule}} \long\def\multicoltab@parse@rule#1{% \@ifnextchar[{\multicoltab@parse@rule@optional{#1}}% {\multicoltab@parse@rule@plain{#1}}% } \long\def\multicoltab@parse@rule@optional#1[#2]#3\multicoltab@row@stop{% \multicoltab@emitrule{#1}{[#2]}% \multicoltab@dispatchremainder{#3}% } \long\def\multicoltab@parse@rule@plain#1#2\multicoltab@row@stop{% \multicoltab@emitrule{#1}{}% \multicoltab@dispatchremainder{#2}% } \def\multicoltab@parse@shorthead\mchead{\multicoltab@parse@head} \def\multicoltab@parse@head{% \@ifnextchar[{\multicoltab@parse@head@one}{\multicoltab@parse@head@zero}} \def\multicoltab@parse@head@zero{\multicoltab@parse@head@emit[][]} \def\multicoltab@parse@head@one[#1]{% \@ifnextchar[{\multicoltab@parse@head@two{#1}}% {\multicoltab@parse@head@emit[#1][]}} \def\multicoltab@parse@head@two#1[#2]{% \multicoltab@parse@head@emit[#1][#2]} \long\def\multicoltab@parse@head@emit[#1][#2]#3#4\multicoltab@row@stop{% \multicoltab@sethead{#1}{#2}{#3}} \long\def\multicoltab@parse@columnbreak\multicoltabbreak#1\multicoltab@row@stop{% \ifmulticoltab@measure\else \columnbreak[4]\multicoltab@repeathead \fi} \long\def\multicoltab@parse@pagebreak\multicoltabpagebreak#1\multicoltab@row@stop{% \ifmulticoltab@measure\else \newpage\multicoltab@repeathead \fi} \long\def\multicoltab@parse@repeathead\mcheadrepeat#1\multicoltab@row@stop{% \ifmulticoltab@measure\else\multicoltab@repeathead\fi} \long\def\multicoltab@parse@normal#1\multicoltab@row@stop{% \multicoltab@emitrow{\multicoltab@rowstar}{}% {\multicoltab@rowextra}{}{#1}} % Public markers interpreted by the parser. They intentionally fail outside a % multicoltab body, where a row delimiter is unavailable. \newcommand{\multicoltab@outsideerror}[1]{% \PackageError{multicoltab}{#1 used outside multicoltab}% {Use this command as a complete row inside multicoltab.}} \newcommand{\mchead}{\multicoltab@outsideerror{\string\mchead}} \newcommand{\mcheadrepeat}{% \multicoltab@outsideerror{\string\mcheadrepeat}} \newcommand{\multicoltabbreak}{\multicoltab@outsideerror{\string\multicoltabbreak}} \newcommand{\multicoltabpagebreak}{% \multicoltab@outsideerror{\string\multicoltabpagebreak}} \NewDocumentEnvironment{multicoltab}{O{} m +b}{% \multicoltab@start{#1}{#2}% \multicoltab@prepare{#3}% \multicoltab@parser #3\\\multicoltab@stop \multicoltab@end }{} \makeatother \endinput