7295 lines
244 KiB
TeX
7295 lines
244 KiB
TeX
%%% % -*- coding: utf-8 -*-
|
|
%%% ----------------------------------------------------------------------------
|
|
%%% Tabularray: Typeset tabulars and arrays with LaTeX3
|
|
%%% Copyright : 2021-2023 (c) Jianrui Lyu <tolvjr@163.com>
|
|
%%% Repository: https://github.com/lvjr/tabularray
|
|
%%% License : The LaTeX Project Public License 1.3c
|
|
%%% ----------------------------------------------------------------------------
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Scratch Variables and Function Variants}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% \DeclareRelease and \DeclareCurrentRelease are added in LaTeX 2018-04-01
|
|
\NeedsTeXFormat{LaTeX2e}[2018-04-01]
|
|
\providecommand\DeclareRelease[3]{}
|
|
\providecommand\DeclareCurrentRelease[2]{}
|
|
\DeclareRelease{v2021}{2021-01-01}{tabularray-2021.sty}
|
|
\DeclareCurrentRelease{}{2022-01-01}
|
|
|
|
\RequirePackage{expl3}
|
|
\ProvidesExplPackage{tabularray}{2023-03-01}{2023A}
|
|
{Typeset tabulars and arrays with LaTeX3}
|
|
|
|
%% \IfFormatAtLeastTF, xparse and lthooks are added in LaTeX 2020-10-01
|
|
%% Note that \@ifl@t@r or \@ifpackagelater means 'this date or later'
|
|
\msg_new:nnn { tabularray } { latex-too-old }
|
|
{
|
|
Your ~ LaTeX ~ release ~ is ~ too ~ old. \\
|
|
Please ~ update ~ it ~ to ~ 2020-10-01 ~ first.
|
|
}
|
|
\@ifl@t@r\fmtversion{2020-10-01}{}{
|
|
%% Support TeX Live 2020 on Overleaf
|
|
\msg_warning:nn { tabularray } { latex-too-old }
|
|
\usepackage{xparse}
|
|
}
|
|
|
|
\AtBeginDocument{
|
|
\@ifpackageloaded{xcolor}{\RequirePackage{ninecolors}}{}
|
|
\@ifpackageloaded{hyperref}{
|
|
\newenvironment{tblrNoHyper}{\NoHyper}{\endNoHyper}
|
|
}{
|
|
\newenvironment{tblrNoHyper}{}{}
|
|
}
|
|
}
|
|
|
|
\NewDocumentCommand \TblrParboxRestore { } { \@parboxrestore }
|
|
|
|
\NewDocumentCommand \TblrAlignBoth { }
|
|
{
|
|
\let \\ = \@normalcr
|
|
\leftskip = \z@skip
|
|
\@rightskip = \z@skip
|
|
\rightskip = \@rightskip
|
|
\parfillskip = \@flushglue
|
|
}
|
|
|
|
\NewDocumentCommand \TblrAlignLeft { } { \raggedright }
|
|
|
|
\NewDocumentCommand \TblrAlignCenter { } { \centering }
|
|
|
|
\NewDocumentCommand \TblrAlignRight { } { \raggedleft }
|
|
|
|
\cs_set_eq:NN \TblrNewPage \newpage
|
|
|
|
%% Note that \cs_if_exist:NTF doesn't treat \relax as an existing command.
|
|
%% Therefore we define our \__tblr_cs_if_defined:NTF here.
|
|
\prg_set_conditional:Npnn \__tblr_cs_if_defined:N #1 { p, T, F, TF }
|
|
{
|
|
%% \if_cs_exist:N = \ifdefined in eTeX
|
|
\if_cs_exist:N #1
|
|
\prg_return_true:
|
|
\else:
|
|
\prg_return_false:
|
|
\fi:
|
|
}
|
|
\prg_set_conditional:Npnn \__tblr_cs_if_defined:c #1 { p, T, F, TF }
|
|
{
|
|
%% \if_cs_exist:w = \ifcsname in eTeX
|
|
\if_cs_exist:w #1 \cs_end:
|
|
\prg_return_true:
|
|
\else:
|
|
\prg_return_false:
|
|
\fi:
|
|
}
|
|
|
|
\cs_generate_variant:Nn \msg_error:nnnn { nnVn }
|
|
\cs_generate_variant:Nn \prop_item:Nn { Ne, NV }
|
|
\cs_generate_variant:Nn \prop_put:Nnn { Nxn, Nxx, NxV }
|
|
\cs_generate_variant:Nn \regex_replace_all:NnN { NVN }
|
|
\cs_generate_variant:Nn \seq_map_indexed_inline:Nn { cn }
|
|
\cs_generate_variant:Nn \tl_const:Nn { ce }
|
|
\cs_generate_variant:Nn \tl_log:n { x }
|
|
\cs_generate_variant:Nn \tl_gput_right:Nn { Nf }
|
|
\cs_generate_variant:Nn \tl_put_left:Nn { Nv }
|
|
\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { Nx } { TF }
|
|
\prg_generate_conditional_variant:Nnn \prop_if_in:Nn { c } { T }
|
|
\prg_generate_conditional_variant:Nnn \regex_match:Nn { NV } { TF }
|
|
\prg_generate_conditional_variant:Nnn \str_if_eq:nn { xn } { TF }
|
|
\prg_generate_conditional_variant:Nnn \tl_if_eq:nn { en } { T, TF }
|
|
\prg_generate_conditional_variant:Nnn \tl_if_head_eq_catcode:nN { VN } { TF }
|
|
\prg_generate_conditional_variant:Nnn \tl_if_head_eq_meaning:nN { VN } { T, TF }
|
|
|
|
\tl_new:N \l__tblr_a_tl
|
|
\tl_new:N \l__tblr_b_tl
|
|
\tl_new:N \l__tblr_c_tl
|
|
\tl_new:N \l__tblr_d_tl
|
|
\tl_new:N \l__tblr_e_tl
|
|
\tl_new:N \l__tblr_f_tl
|
|
\tl_new:N \l__tblr_h_tl
|
|
\tl_new:N \l__tblr_i_tl % for row index
|
|
\tl_new:N \l__tblr_j_tl % for column index
|
|
\tl_new:N \l__tblr_k_tl
|
|
\tl_new:N \l__tblr_n_tl
|
|
\tl_new:N \l__tblr_o_tl
|
|
\tl_new:N \l__tblr_r_tl
|
|
\tl_new:N \l__tblr_s_tl
|
|
\tl_new:N \l__tblr_t_tl
|
|
\tl_new:N \l__tblr_u_tl
|
|
\tl_new:N \l__tblr_v_tl
|
|
\tl_new:N \l__tblr_w_tl
|
|
\tl_new:N \l__tblr_x_tl
|
|
\tl_new:N \l__tblr_y_tl
|
|
\int_new:N \l__tblr_a_int
|
|
\int_new:N \l__tblr_c_int % for column number
|
|
\int_new:N \l__tblr_r_int % for row number
|
|
\dim_new:N \l__tblr_d_dim % for depth
|
|
\dim_new:N \l__tblr_h_dim % for height
|
|
\dim_new:N \l__tblr_o_dim
|
|
\dim_new:N \l__tblr_p_dim
|
|
\dim_new:N \l__tblr_q_dim
|
|
\dim_new:N \l__tblr_r_dim
|
|
\dim_new:N \l__tblr_s_dim
|
|
\dim_new:N \l__tblr_t_dim
|
|
\dim_new:N \l__tblr_v_dim
|
|
\dim_new:N \l__tblr_w_dim % for width
|
|
\box_new:N \l__tblr_a_box
|
|
\box_new:N \l__tblr_b_box
|
|
\box_new:N \l__tblr_c_box % for cell box
|
|
\box_new:N \l__tblr_d_box
|
|
|
|
%% Total number of tblr tables
|
|
\int_new:N \g__tblr_table_count_int
|
|
|
|
%% Some commands for horizontal alignment
|
|
\cs_new_eq:NN \__tblr_halign_command_j: \TblrAlignBoth
|
|
\cs_new_eq:NN \__tblr_halign_command_l: \TblrAlignLeft
|
|
\cs_new_eq:NN \__tblr_halign_command_c: \TblrAlignCenter
|
|
\cs_new_eq:NN \__tblr_halign_command_r: \TblrAlignRight
|
|
|
|
%% Some counters for row and column numbering.
|
|
%% We may need to restore all LaTeX counters in measuring and building cells,
|
|
%% so we must not define these counters with \newcounter command.
|
|
\int_zero_new:N \c@rownum
|
|
\int_zero_new:N \c@colnum
|
|
\int_zero_new:N \c@rowcount
|
|
\int_zero_new:N \c@colcount
|
|
|
|
%% Add missing \therownum, \thecolnum, \therowcount, \thecolcount (issue #129)
|
|
\ProvideExpandableDocumentCommand \therownum {} { \@arabic \c@rownum }
|
|
\ProvideExpandableDocumentCommand \thecolnum {} { \@arabic \c@colnum }
|
|
\ProvideExpandableDocumentCommand \therowcount {} { \@arabic \c@rowcount }
|
|
\ProvideExpandableDocumentCommand \thecolcount {} { \@arabic \c@colcount }
|
|
|
|
%% Some dimensions for row and column spacing
|
|
\dim_new:N \abovesep
|
|
\dim_new:N \belowsep
|
|
\dim_new:N \leftsep
|
|
\dim_new:N \rightsep
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Data Structures Based on Property Lists}
|
|
%%% --------------------------------------------------------
|
|
|
|
\int_new:N \g_tblr_level_int % store table nesting level
|
|
|
|
\cs_new_protected:Npn \__tblr_clear_prop_lists:
|
|
{
|
|
\prop_gclear_new:c { g__tblr_text_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_command_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_inner_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_note_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_remark_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_more_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_row_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_column_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_cell_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_hline_ \int_use:N \g_tblr_level_int _prop }
|
|
\prop_gclear_new:c { g__tblr_vline_ \int_use:N \g_tblr_level_int _prop }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_prop_gput:nnn #1 #2 #3
|
|
{
|
|
\prop_gput:cnn
|
|
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_prop_gput:nnn { nnx, nnV, nxn, nxx, nxV }
|
|
|
|
\cs_new:Npn \__tblr_prop_item:nn #1 #2
|
|
{
|
|
\prop_item:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_prop_item:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_prop_if_in:nnT #1
|
|
{
|
|
\prop_if_in:cnT { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop }
|
|
}
|
|
\cs_new_protected:Npn \__tblr_prop_if_in:nnF #1
|
|
{
|
|
\prop_if_in:cnF { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop }
|
|
}
|
|
\cs_new_protected:Npn \__tblr_prop_if_in:nnTF #1
|
|
{
|
|
\prop_if_in:cnTF { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop }
|
|
}
|
|
\prg_generate_conditional_variant:Nnn \__tblr_prop_if_in:nn { nx } { T, F, TF }
|
|
|
|
\cs_new_protected:Npn \__tblr_prop_log:n #1
|
|
{
|
|
\prop_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_prop_map_inline:nn #1 #2
|
|
{
|
|
\prop_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } {#2}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_prop_gput_if_larger:nnn #1 #2 #3
|
|
{
|
|
\__tblr_gput_if_larger:cnn
|
|
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_prop_gput_if_larger:nnn { nnx, nnV, nxn, nxx, nxV }
|
|
|
|
\cs_new_protected:Npn \__tblr_prop_gadd_dimen_value:nnn #1 #2 #3
|
|
{
|
|
\__tblr_gadd_dimen_value:cnn
|
|
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_prop_gadd_dimen_value:nnn { nnx, nnV, nxn, nxx }
|
|
|
|
%% Put the dimension to the prop list only if it's larger than the old one
|
|
|
|
\tl_new:N \l__tblr_put_if_larger_tl
|
|
|
|
\cs_new_protected:Npn \__tblr_put_if_larger:Nnn #1 #2 #3
|
|
{
|
|
\tl_set:Nx \l__tblr_put_if_larger_tl { \prop_item:Nn #1 { #2 } }
|
|
\bool_lazy_or:nnT
|
|
{ \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
|
|
{ \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } }
|
|
{ \prop_put:Nnn #1 { #2 } { #3 } }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_put_if_larger:Nnn { Nnx, Nxn, Nxx, NnV }
|
|
|
|
\cs_new_protected:Npn \__tblr_gput_if_larger:Nnn #1 #2 #3
|
|
{
|
|
\tl_set:Nx \l__tblr_put_if_larger_tl { \prop_item:Nn #1 { #2 } }
|
|
\bool_lazy_or:nnT
|
|
{ \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
|
|
{ \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } }
|
|
{ \prop_gput:Nnn #1 { #2 } { #3 } }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_gput_if_larger:Nnn { Nnx, Nxn, Nxx, cnn }
|
|
|
|
%% Add the dimension to some key value of the prop list
|
|
%% #1: the prop list, #2: the key, #3: the dimen to add
|
|
|
|
\cs_new_protected:Npn \__tblr_add_dimen_value:Nnn #1 #2 #3
|
|
{
|
|
\prop_put:Nnx #1 { #2 } { \dim_eval:n { \prop_item:Nn #1 { #2 } + #3 } }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_add_dimen_value:Nnn { cnn }
|
|
|
|
\cs_new_protected:Npn \__tblr_gadd_dimen_value:Nnn #1 #2 #3
|
|
{
|
|
\prop_gput:Nnx #1 { #2 } { \dim_eval:n { \prop_item:Nn #1 { #2 } + #3 } }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_gadd_dimen_value:Nnn { cnn }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Data Structures Based on Token Lists}
|
|
%%% --------------------------------------------------------
|
|
|
|
\cs_new_protected:Npn \__tblr_clear_spec_lists:
|
|
{
|
|
%\__tblr_clear_one_spec_lists:n { row }
|
|
%\__tblr_clear_one_spec_lists:n { column }
|
|
%\__tblr_clear_one_spec_lists:n { cell }
|
|
\__tblr_clear_one_spec_lists:n { text }
|
|
\__tblr_clear_one_spec_lists:n { hline }
|
|
\__tblr_clear_one_spec_lists:n { vline }
|
|
\__tblr_clear_one_spec_lists:n { outer }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_clear_one_spec_lists:n #1
|
|
{
|
|
\clist_if_exist:cTF { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
|
|
{
|
|
\clist_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
|
|
{
|
|
\tl_gclear:c { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_##1_tl }
|
|
}
|
|
}
|
|
{ \clist_new:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_spec_gput:nnn #1 #2 #3
|
|
{
|
|
\tl_gset:cn
|
|
{ g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl } {#3}
|
|
\clist_gput_right:cx { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_spec_gput:nnn { nne, nnV, nen, nee, neV }
|
|
|
|
\cs_new:Npn \__tblr_spec_item:nn #1 #2
|
|
{
|
|
\tl_if_exist:cT { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl }
|
|
{
|
|
\exp_args:Nv \exp_not:n
|
|
{ g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl }
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_spec_item:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_spec_gput_if_larger:nnn #1 #2 #3
|
|
{
|
|
\tl_set:Nx \l__tblr_put_if_larger_tl { \__tblr_spec_item:nn {#1} {#2} }
|
|
\bool_lazy_or:nnT
|
|
{ \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
|
|
{ \dim_compare_p:nNn {#3} > { \l__tblr_put_if_larger_tl } }
|
|
{ \__tblr_spec_gput:nnn {#1} {#2} {#3} }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_spec_gput_if_larger:nnn { nne, nnV, nen, nee, neV }
|
|
|
|
\cs_new_protected:Npn \__tblr_spec_gadd_dimen_value:nnn #1 #2 #3
|
|
{
|
|
\__tblr_spec_gput:nne {#1} {#2}
|
|
{ \dim_eval:n { \__tblr_spec_item:ne {#1} {#2} + #3 } }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_spec_gadd_dimen_value:nnn { nne, nnV, nen, nee }
|
|
|
|
\cs_new_protected:Npn \__tblr_spec_log:n #1
|
|
{
|
|
\clist_gremove_duplicates:c
|
|
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
|
|
\tl_log:x
|
|
{
|
|
The ~ spec ~ list ~ #1 _ \int_use:N \g_tblr_level_int
|
|
\space contains ~ the ~ pairs:
|
|
}
|
|
\clist_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
|
|
{
|
|
\tl_log:x
|
|
{
|
|
\space { ##1 } ~\space=>~\space { \__tblr_spec_item:nn {#1} {##1} }
|
|
}
|
|
}
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Data Structures Based on Integer Arrays}
|
|
%%% --------------------------------------------------------
|
|
|
|
\msg_new:nnn { tabularray } { intarray-beyond-bound }
|
|
{ Position ~ #2 ~ is ~ beyond ~ the ~ bound ~ of ~ intarray ~ #1.}
|
|
|
|
\cs_new_protected:Npn \__tblr_intarray_gset:Nnn #1 #2 #3
|
|
{
|
|
\bool_lazy_or:nnTF
|
|
{ \int_compare_p:nNn {#2} < {0} }
|
|
{ \int_compare_p:nNn {#2} > {\intarray_count:N #1} }
|
|
{
|
|
\bool_if:NT \g__tblr_tracing_intarray_bool
|
|
{ \msg_warning:nnnn { tabularray } { intarray-beyond-bound } {#1} {#2} }
|
|
}
|
|
{ \intarray_gset:Nnn #1 {#2} {#3} }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_intarray_gset:Nnn { cnn }
|
|
|
|
%% #1: data name; #2: key name; #3: value type
|
|
\cs_new_protected:Npn \__tblr_data_new_key:nnn #1 #2 #3
|
|
{
|
|
\int_gincr:c { g__tblr_data_#1_key_count_int }
|
|
\tl_const:ce
|
|
{
|
|
c__tblr_data_#1_key_name_
|
|
\int_use:c { g__tblr_data_#1_key_count_int } _tl
|
|
}
|
|
{ #2 }
|
|
\tl_const:ce { c__tblr_data_#1_key_number_#2_tl }
|
|
{ \int_use:c { g__tblr_data_#1_key_count_int } }
|
|
\tl_const:cn { c__tblr_data_#1_key_type_#2_tl } {#3}
|
|
}
|
|
|
|
\int_new:N \g__tblr_data_row_key_count_int
|
|
\__tblr_data_new_key:nnn { row } { height } { dim }
|
|
\__tblr_data_new_key:nnn { row } { coefficient } { dec }
|
|
\__tblr_data_new_key:nnn { row } { abovesep } { dim }
|
|
\__tblr_data_new_key:nnn { row } { belowsep } { dim }
|
|
\__tblr_data_new_key:nnn { row } { @row-height } { dim }
|
|
\__tblr_data_new_key:nnn { row } { @row-head } { dim }
|
|
\__tblr_data_new_key:nnn { row } { @row-foot } { dim }
|
|
\__tblr_data_new_key:nnn { row } { @row-upper } { dim }
|
|
\__tblr_data_new_key:nnn { row } { @row-lower } { dim }
|
|
|
|
\int_new:N \g__tblr_data_column_key_count_int
|
|
\__tblr_data_new_key:nnn { column } { width } { dim }
|
|
\__tblr_data_new_key:nnn { column } { coefficient } { dec }
|
|
\__tblr_data_new_key:nnn { column } { leftsep } { dim }
|
|
\__tblr_data_new_key:nnn { column } { rightsep } { dim }
|
|
\__tblr_data_new_key:nnn { column } { @col-width } { dim }
|
|
|
|
\int_new:N \g__tblr_data_cell_key_count_int
|
|
\__tblr_data_new_key:nnn { cell } { width } { dim }
|
|
\__tblr_data_new_key:nnn { cell } { rowspan } { int }
|
|
\__tblr_data_new_key:nnn { cell } { colspan } { int }
|
|
\__tblr_data_new_key:nnn { cell } { halign } { str }
|
|
\__tblr_data_new_key:nnn { cell } { valign } { str }
|
|
\__tblr_data_new_key:nnn { cell } { background } { str }
|
|
\__tblr_data_new_key:nnn { cell } { foreground } { str }
|
|
\__tblr_data_new_key:nnn { cell } { font } { str }
|
|
\__tblr_data_new_key:nnn { cell } { mode } { str }
|
|
\__tblr_data_new_key:nnn { cell } { cmd } { str }
|
|
\__tblr_data_new_key:nnn { cell } { omit } { int }
|
|
\__tblr_data_new_key:nnn { cell } { @cell-width } { dim }
|
|
\__tblr_data_new_key:nnn { cell } { @cell-height } { dim }
|
|
\__tblr_data_new_key:nnn { cell } { @cell-depth } { dim }
|
|
|
|
\clist_const:Nn \c__tblr_data_clist { row, column, cell }
|
|
\tl_const:Nn \c__tblr_data_row_count_tl { \c@rowcount }
|
|
\tl_const:Nn \c__tblr_data_column_count_tl { \c@colcount }
|
|
\tl_const:Nn \c__tblr_data_cell_count_tl { \c@rowcount * \c@colcount }
|
|
\tl_const:Nn \c__tblr_data_row_index_number_tl {1}
|
|
\tl_const:Nn \c__tblr_data_column_index_number_tl {1}
|
|
\tl_const:Nn \c__tblr_data_cell_index_number_tl {2}
|
|
\int_new:N \g__tblr_array_int
|
|
|
|
\cs_new_protected:Npn \__tblr_init_table_data:
|
|
{
|
|
\clist_map_function:NN \c__tblr_data_clist \__tblr_init_one_data:n
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_init_one_data:n #1
|
|
{
|
|
\int_gincr:N \g__tblr_array_int
|
|
\intarray_new:cn { g__tblr_#1_ \int_use:N \g__tblr_array_int _intarray }
|
|
{
|
|
\int_use:c { g__tblr_data_#1_key_count_int }
|
|
* \tl_use:c { c__tblr_data_#1_count_tl }
|
|
}
|
|
\cs_set_eq:cc { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
{ g__tblr_#1_ \int_use:N \g__tblr_array_int _intarray }
|
|
%\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
}
|
|
|
|
%% #1: data name; #2: data index; #3: key name
|
|
\cs_new:Npn \__tblr_data_key_to_int:nnn #1 #2 #3
|
|
{
|
|
( #2 - 1 ) * \int_use:c { g__tblr_data_#1_key_count_int }
|
|
+ \tl_use:c { c__tblr_data_#1_key_number_#3_tl }
|
|
}
|
|
|
|
%% #1: data name; #2: data index 1; #3: data index 2; #4: key name
|
|
\cs_new:Npn \__tblr_data_key_to_int:nnnn #1 #2 #3 #4
|
|
{
|
|
( #2 - 1 ) * \c@colcount * \int_use:c { g__tblr_data_#1_key_count_int }
|
|
+ ( #3 - 1 ) * \int_use:c { g__tblr_data_#1_key_count_int }
|
|
+ \tl_use:c { c__tblr_data_#1_key_number_#4_tl }
|
|
}
|
|
|
|
\int_new:N \l__tblr_key_count_int
|
|
\int_new:N \l__tblr_key_quotient_int
|
|
\int_new:N \l__tblr_key_quotient_two_int
|
|
\int_new:N \l__tblr_key_remainder_int
|
|
|
|
%% #1: data name; #2: array position;
|
|
%% #3: returning tl with index; #4: returning tl with key name
|
|
\cs_new:Npn \__tblr_data_int_to_key:nnNN #1 #2 #3 #4
|
|
{
|
|
\int_set_eq:Nc \l__tblr_key_count_int { g__tblr_data_#1_key_count_int }
|
|
\int_set:Nn \l__tblr_key_quotient_int
|
|
{
|
|
\int_div_truncate:nn
|
|
{ #2 + \l__tblr_key_count_int - 1 } { \l__tblr_key_count_int }
|
|
}
|
|
\int_set:Nn \l__tblr_key_remainder_int
|
|
{
|
|
#2 + \l__tblr_key_count_int
|
|
- \l__tblr_key_quotient_int * \l__tblr_key_count_int
|
|
}
|
|
\int_compare:nNnT { \l__tblr_key_remainder_int } = { 0 }
|
|
{ \int_set_eq:NN \l__tblr_key_remainder_int \l__tblr_key_count_int }
|
|
\tl_set:Nx #3 { \int_use:N \l__tblr_key_quotient_int }
|
|
\tl_set_eq:Nc #4
|
|
{ c__tblr_data_#1_key_name_ \int_use:N \l__tblr_key_remainder_int _tl }
|
|
}
|
|
|
|
%% #1: data name; #2: array position;
|
|
%% #3: returning tl with index 1; #4: returning tl with index 2;
|
|
%% #5: returning tl with key name
|
|
\cs_new:Npn \__tblr_data_int_to_key:nnNNN #1 #2 #3 #4 #5
|
|
{
|
|
\int_set_eq:Nc \l__tblr_key_count_int { g__tblr_data_#1_key_count_int }
|
|
\int_set:Nn \l__tblr_key_quotient_int
|
|
{
|
|
\int_div_truncate:nn
|
|
{ #2 + \l__tblr_key_count_int - 1 } { \l__tblr_key_count_int }
|
|
}
|
|
\int_set:Nn \l__tblr_key_remainder_int
|
|
{
|
|
#2 + \l__tblr_key_count_int
|
|
- \l__tblr_key_quotient_int * \l__tblr_key_count_int
|
|
}
|
|
\int_compare:nNnT { \l__tblr_key_remainder_int } = { 0 }
|
|
{ \int_set_eq:NN \l__tblr_key_remainder_int \l__tblr_key_count_int }
|
|
\tl_set_eq:Nc #5
|
|
{ c__tblr_data_#1_key_name_ \int_use:N \l__tblr_key_remainder_int _tl }
|
|
\int_set:Nn \l__tblr_key_quotient_two_int
|
|
{
|
|
\int_div_truncate:nn
|
|
{ \l__tblr_key_quotient_int + \c@colcount - 1 } { \c@colcount }
|
|
}
|
|
\int_set:Nn \l__tblr_key_remainder_int
|
|
{
|
|
\l__tblr_key_quotient_int + \c@colcount
|
|
- \l__tblr_key_quotient_two_int * \c@colcount
|
|
}
|
|
\int_compare:nNnT { \l__tblr_key_remainder_int } = { 0 }
|
|
{ \int_set_eq:NN \l__tblr_key_remainder_int \c@colcount }
|
|
\tl_set:Nx #4 { \int_use:N \l__tblr_key_remainder_int }
|
|
\tl_set:Nx #3 { \int_use:N \l__tblr_key_quotient_two_int }
|
|
}
|
|
|
|
\tl_new:N \g__tblr_data_int_from_value_tl
|
|
|
|
%% #1: data name; #2: key name; #3: value
|
|
%% The result will be stored in \g__tblr_data_int_from_value_tl
|
|
\cs_new_protected:Npn \__tblr_data_int_from_value:nnn #1 #2 #3
|
|
{
|
|
\cs:w
|
|
__tblr_data_int_from_ \tl_use:c { c__tblr_data_#1_key_type_#2_tl } :n
|
|
\cs_end:
|
|
{#3}
|
|
}
|
|
|
|
%% #1: data name; #2: key name; #3: int
|
|
\cs_new:Npn \__tblr_data_int_to_value:nnn #1 #2 #3
|
|
{
|
|
\cs:w
|
|
__tblr_data_int_to_ \tl_use:c { c__tblr_data_#1_key_type_#2_tl } :n
|
|
\cs_end:
|
|
{#3}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_data_int_to_value:nnn { nne, nVe }
|
|
|
|
\cs_new_protected:Npn \__tblr_data_int_from_int:n #1
|
|
{
|
|
\tl_gset:Nn \g__tblr_data_int_from_value_tl {#1}
|
|
}
|
|
|
|
\cs_new:Npn \__tblr_data_int_to_int:n #1
|
|
{
|
|
#1
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_data_int_from_dim:n #1
|
|
{
|
|
\tl_gset:Nx \g__tblr_data_int_from_value_tl { \dim_to_decimal_in_sp:n {#1} }
|
|
}
|
|
|
|
%% Return a dimension in pt so that it's easier to understand in tracing messages
|
|
\cs_new:Npn \__tblr_data_int_to_dim:n #1
|
|
{
|
|
%#1 sp
|
|
%\dim_eval:n { #1 sp }
|
|
\dim_to_decimal:n { #1 sp } pt
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_data_int_from_dec:n #1
|
|
{
|
|
\tl_gset:Nx \g__tblr_data_int_from_value_tl
|
|
{ \dim_to_decimal_in_sp:n {#1 pt} }
|
|
}
|
|
|
|
\cs_new:Npn \__tblr_data_int_to_dec:n #1
|
|
{
|
|
\dim_to_decimal:n {#1 sp}
|
|
}
|
|
|
|
\int_new:N \g__tblr_data_str_value_count_int
|
|
\tl_gclear_new:c { g__tblr_data_0_to_str_tl }
|
|
|
|
\cs_new_protected:Npn \__tblr_data_int_from_str:n #1
|
|
{
|
|
\tl_if_exist:cTF { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
|
|
{
|
|
\tl_gset_eq:Nc \g__tblr_data_int_from_value_tl
|
|
{ g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
|
|
}
|
|
{
|
|
\int_gincr:N \g__tblr_data_str_value_count_int
|
|
\tl_gset:cx { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
|
|
{ \int_use:N \g__tblr_data_str_value_count_int }
|
|
\tl_gset:cn
|
|
{ g__tblr_data_ \int_use:N \g__tblr_data_str_value_count_int _to_str_tl }
|
|
{ \exp_not:n {#1} }
|
|
\tl_gset:Nx \g__tblr_data_int_from_value_tl
|
|
{ \int_use:N \g__tblr_data_str_value_count_int }
|
|
}
|
|
}
|
|
|
|
\cs_new:Npn \__tblr_data_int_to_str:n #1
|
|
{
|
|
\tl_use:c { g__tblr_data_#1_to_str_tl }
|
|
}
|
|
|
|
%% #1: data name; #2: data index; #3: key; #4: value
|
|
\cs_new_protected:Npn \__tblr_data_gput:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_data_int_from_value:nnn {#1} {#3} {#4}
|
|
\__tblr_intarray_gset:cnn
|
|
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
{ \__tblr_data_key_to_int:nnn {#1} {#2} {#3} }
|
|
{ \g__tblr_data_int_from_value_tl }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_data_gput:nnnn
|
|
{ nnne, nnnV, nenn, nene, nenV, nVnn }
|
|
|
|
%% #1: data name; #2: data index 1; #3: data index 2; #4: key; #5: value
|
|
\cs_new_protected:Npn \__tblr_data_gput:nnnnn #1 #2 #3 #4 #5
|
|
{
|
|
\__tblr_data_int_from_value:nnn {#1} {#4} {#5}
|
|
\__tblr_intarray_gset:cnn
|
|
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
{ \__tblr_data_key_to_int:nnnn {#1} {#2} {#3} {#4} }
|
|
{ \g__tblr_data_int_from_value_tl }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_data_gput:nnnnn
|
|
{ nnnne, nnnnV, neenn, neene, neenV, neeen, nVVnn }
|
|
|
|
%% #1: data name; #2: data index; #3: key
|
|
\cs_new:Npn \__tblr_data_item:nnn #1 #2 #3
|
|
{
|
|
\__tblr_data_int_to_value:nne {#1} {#3}
|
|
{
|
|
\intarray_item:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
{ \__tblr_data_key_to_int:nnn {#1} {#2} {#3} }
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_data_item:nnn { nen }
|
|
|
|
%% #1: data name; #2: data index 1; #3: data index 2; #4: key
|
|
\cs_new:Npn \__tblr_data_item:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_data_int_to_value:nne {#1} {#4}
|
|
{
|
|
\intarray_item:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
{ \__tblr_data_key_to_int:nnnn {#1} {#2} {#3} {#4} }
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_data_item:nnnn { neen }
|
|
|
|
\tl_new:N \l__tblr_data_key_tl
|
|
\tl_new:N \l__tblr_data_index_tl
|
|
\tl_new:N \l__tblr_data_index_two_tl
|
|
|
|
\cs_new_protected:Npn \__tblr_data_log:n #1
|
|
{
|
|
\use:c { __tblr_data_log_ \use:c { c__tblr_data_#1_index_number_tl } :n } {#1}
|
|
\__tblr_prop_log:n {#1}
|
|
}
|
|
|
|
\cs_new_protected:cpn { __tblr_data_log_1:n } #1
|
|
{
|
|
%\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
\tl_set:Nx \l_tmpa_tl { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
\tl_log:n { ----------~----------~----------~----------~---------- }
|
|
\int_step_inline:nn
|
|
{ \intarray_count:c { \l_tmpa_tl } }
|
|
{
|
|
\__tblr_data_int_to_key:nnNN {#1} {##1}
|
|
\l__tblr_data_index_tl \l__tblr_data_key_tl
|
|
\tl_log:x
|
|
{
|
|
\space
|
|
{ #1 [\l__tblr_data_index_tl] / \l__tblr_data_key_tl }
|
|
~\space => ~\space
|
|
{
|
|
\__tblr_data_int_to_value:nVe {#1} \l__tblr_data_key_tl
|
|
{ \intarray_item:cn { \l_tmpa_tl } {##1} }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:cpn { __tblr_data_log_2:n } #1
|
|
{
|
|
%\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
\tl_set:Nx \l_tmpa_tl { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
\tl_log:n { ----------~----------~----------~----------~---------- }
|
|
\int_step_inline:nn
|
|
{ \intarray_count:c { \l_tmpa_tl } }
|
|
{
|
|
\__tblr_data_int_to_key:nnNNN {#1} {##1}
|
|
\l__tblr_data_index_tl \l__tblr_data_index_two_tl \l__tblr_data_key_tl
|
|
\tl_log:x
|
|
{
|
|
\space
|
|
{
|
|
#1 [\l__tblr_data_index_tl][\l__tblr_data_index_two_tl]
|
|
/ \l__tblr_data_key_tl
|
|
}
|
|
~\space => ~\space
|
|
{
|
|
\__tblr_data_int_to_value:nVe {#1} \l__tblr_data_key_tl
|
|
{ \intarray_item:cn { \l_tmpa_tl } {##1} }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
%% #1: data name; #2: row index; #3: key; #4: value
|
|
\cs_new_protected:Npn \__tblr_data_gput_if_larger:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_data_int_from_value:nnn {#1} {#3} {#4}
|
|
\__tblr_array_gput_if_larger:cnn
|
|
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
{ \__tblr_data_key_to_int:nnn {#1} {#2} {#3} }
|
|
{ \g__tblr_data_int_from_value_tl }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_data_gput_if_larger:nnnn { nnne, nnnV, nene, nenV }
|
|
|
|
\cs_new_protected:Npn \__tblr_array_gput_if_larger:Nnn #1 #2 #3
|
|
{
|
|
\int_compare:nNnT {#3} > { \intarray_item:Nn #1 {#2} }
|
|
{ \__tblr_intarray_gset:Nnn #1 {#2} {#3} }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_array_gput_if_larger:Nnn { cnn }
|
|
|
|
%% #1: data name; #2: data index; #3: key; #4: value
|
|
\cs_new_protected:Npn \__tblr_data_gadd_dimen_value:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_data_int_from_value:nnn {#1} {#3} {#4}
|
|
\__tblr_array_gadd_value:cnn
|
|
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
|
|
{ \__tblr_data_key_to_int:nnn {#1} {#2} {#3} }
|
|
{ \g__tblr_data_int_from_value_tl }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_data_gadd_dimen_value:nnnn
|
|
{ nnne, nnnV, nenn, nene }
|
|
|
|
\cs_new_protected:Npn \__tblr_array_gadd_value:Nnn #1 #2 #3
|
|
{
|
|
\__tblr_intarray_gset:Nnn #1 {#2} { \intarray_item:Nn #1 {#2} + #3 }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_array_gadd_value:Nnn { cnn }
|
|
|
|
\bool_new:N \g__tblr_use_intarray_bool
|
|
\bool_gset_true:N \g__tblr_use_intarray_bool
|
|
|
|
\AtBeginDocument
|
|
{
|
|
\bool_if:NF \g__tblr_use_intarray_bool
|
|
{
|
|
\cs_set_protected:Npn \__tblr_data_gput:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_spec_gput:nnn {#1} { [#2] / #3 } {#4}
|
|
}
|
|
\cs_set_protected:Npn \__tblr_data_gput:nnnnn #1 #2 #3 #4 #5
|
|
{
|
|
\__tblr_spec_gput:nnn {#1} { [#2][#3] / #4 } {#5}
|
|
}
|
|
\cs_set:Npn \__tblr_data_item:nnn #1 #2 #3
|
|
{
|
|
\__tblr_spec_item:nn {#1} { [#2] / #3 }
|
|
}
|
|
\cs_set:Npn \__tblr_data_item:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_spec_item:nn {#1} { [#2][#3] / #4 }
|
|
}
|
|
\cs_set_protected:Npn \__tblr_data_log:n #1
|
|
{
|
|
\__tblr_spec_log:n {#1}
|
|
}
|
|
\cs_set_protected:Npn \__tblr_data_gput_if_larger:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_spec_gput_if_larger:nnn {#1} { [#2] / #3 } {#4}
|
|
}
|
|
\cs_set_protected:Npn \__tblr_data_gput_if_larger:nnnnn #1 #2 #3 #4 #5
|
|
{
|
|
\__tblr_spec_gput_if_larger:nnn {#1} { [#2][#3] / #4 } {#5}
|
|
}
|
|
\cs_set_protected:Npn \__tblr_data_gadd_dimen_value:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_spec_gadd_dimen_value:nnn {#1} { [#2] / #3 } {#4}
|
|
}
|
|
\cs_set_protected:Npn \__tblr_data_gadd_dimen_value:nnnnn #1 #2 #3 #4 #5
|
|
{
|
|
\__tblr_spec_gadd_dimen_value:nnn {#1} { [#2][#3] / #4 } {#5}
|
|
}
|
|
}
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Child Selectors}
|
|
%%% --------------------------------------------------------
|
|
|
|
\clist_new:N \g_tblr_used_child_selectors_clist
|
|
|
|
\tl_new:N \l__tblr_childs_arg_spec_tl
|
|
|
|
\msg_new:nnn { tabularray } { used-child-selector }
|
|
{ Child ~ selector ~ name ~ "#1" ~ has ~ been ~ used! }
|
|
|
|
\NewDocumentCommand \NewChildSelector { m O{0} o m }
|
|
{
|
|
\__tblr_new_child_selector_aux:xnnn { \tl_trim_spaces:n {#1} } {#2} {#3} {#4}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_new_child_selector_aux:nnnn #1 #2 #3 #4
|
|
{
|
|
\clist_if_in:NnTF \g_tblr_used_child_selectors_clist { #1 }
|
|
{
|
|
\msg_error:nnn { tabularray } { used-child-selector } { #1 }
|
|
\clist_log:N \g_tblr_used_child_selectors_clist
|
|
}
|
|
{
|
|
\__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_childs_arg_spec_tl
|
|
\exp_args:NcV \NewDocumentCommand
|
|
{ __tblr_child_selector_ #1 :w } \l__tblr_childs_arg_spec_tl { #4 }
|
|
\clist_gput_right:Nn \g_tblr_used_child_selectors_clist { #1 }
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_new_child_selector_aux:nnnn { xnnn }
|
|
|
|
%% #1: argument number, #2: optional argument default, #3: result tl
|
|
\cs_new_protected:Npn \__tblr_make_xparse_arg_spec:nnN #1 #2 #3
|
|
{
|
|
\tl_clear:N #3
|
|
\int_compare:nNnT { #1 } > { 0 }
|
|
{
|
|
\IfValueTF { #2 }
|
|
{ \tl_set:Nn #3 { O{#2} } }
|
|
{ \tl_set:Nn #3 { m } }
|
|
\tl_put_right:Nx #3 { \prg_replicate:nn { #1 - 1 } { m } }
|
|
}
|
|
}
|
|
|
|
\clist_new:N \l_tblr_childs_clist
|
|
\tl_new:N \l_tblr_childs_total_tl
|
|
|
|
\NewChildSelector { odd } [1] []
|
|
{
|
|
\tl_if_blank:nTF {#1}
|
|
{
|
|
\int_step_inline:nnnn {1} {2} { \l_tblr_childs_total_tl }
|
|
{ \clist_put_right:Nn \l_tblr_childs_clist {##1} }
|
|
}
|
|
{ \__tblr_child_selector_odd_or_even:nn { odd } {#1} }
|
|
}
|
|
|
|
\NewChildSelector { even } [1] []
|
|
{
|
|
\tl_if_blank:nTF {#1}
|
|
{
|
|
\int_step_inline:nnnn {2} {2} { \l_tblr_childs_total_tl }
|
|
{ \clist_put_right:Nn \l_tblr_childs_clist {##1} }
|
|
}
|
|
{ \__tblr_child_selector_odd_or_even:nn { even } {#1} }
|
|
}
|
|
|
|
\tl_new:N \l__tblr_child_from_tl
|
|
\tl_new:N \l__tblr_child_to_tl
|
|
|
|
%% #1: odd or even; #2: selector option
|
|
\cs_new_protected:Npn \__tblr_child_selector_odd_or_even:nn #1 #2
|
|
{
|
|
\seq_set_split:Nnn \l_tmpa_seq {-} { #2 - Z }
|
|
\tl_set:Nx \l__tblr_child_from_tl { \seq_item:Nn \l_tmpa_seq {1} }
|
|
\tl_set:Nx \l__tblr_child_to_tl { \seq_item:Nn \l_tmpa_seq {2} }
|
|
\tl_use:c { int_if_ #1 :nF } { \l__tblr_child_from_tl }
|
|
{
|
|
\tl_set:Nx \l__tblr_child_from_tl
|
|
{ \int_eval:n { \l__tblr_child_from_tl + 1 } }
|
|
}
|
|
\__tblr_child_name_to_index:VN \l__tblr_child_to_tl \l__tblr_child_to_tl
|
|
\int_step_inline:nnnn { \l__tblr_child_from_tl } {2} { \l__tblr_child_to_tl }
|
|
{ \clist_put_right:Nn \l_tblr_childs_clist {##1} }
|
|
}
|
|
|
|
\regex_const:Nn \c__tblr_split_selector_name_regex { ^ ( [A-Za-z] {2,} ) ( . * ) }
|
|
\seq_new:N \l__tblr_childs_split_seq
|
|
\seq_new:N \l__tblr_childs_regex_seq
|
|
\tl_new:N \l__tblr_childs_selector_tl
|
|
|
|
%% #1, child specifications; #2, total number.
|
|
%% The result will be put into \l_tblr_childs_clist
|
|
\cs_new_protected:Npn \__tblr_get_childs:nn #1 #2
|
|
{
|
|
\clist_clear:N \l_tblr_childs_clist
|
|
\tl_set:Nx \l_tblr_childs_total_tl {#2}
|
|
\regex_extract_once:NnNTF \c__tblr_split_selector_name_regex {#1}
|
|
\l__tblr_childs_regex_seq
|
|
{
|
|
\tl_set:No \l__tblr_childs_selector_tl
|
|
{
|
|
\cs:w
|
|
__tblr_child_selector_ \seq_item:Nn \l__tblr_childs_regex_seq {2} :w
|
|
\cs_end:
|
|
}
|
|
\exp_last_unbraced:Nx \l__tblr_childs_selector_tl
|
|
{ \seq_item:Nn \l__tblr_childs_regex_seq{3} }
|
|
}
|
|
{
|
|
\tl_if_eq:nnTF {#1} {-}
|
|
{ \__tblr_get_childs_normal:nn {1-#2} {#2} }
|
|
{ \__tblr_get_childs_normal:nn {#1} {#2} }
|
|
}
|
|
%\clist_log:N \l_tblr_childs_clist
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_get_childs:nn { nx }
|
|
|
|
\cs_new_protected:Npn \__tblr_get_childs_normal:nn #1 #2
|
|
{
|
|
\seq_set_split:Nnn \l__tblr_childs_split_seq {,} {#1}
|
|
\seq_map_inline:Nn \l__tblr_childs_split_seq
|
|
{
|
|
\tl_if_in:nnTF {##1} {-}
|
|
{ \__tblr_get_childs_normal_aux:w ##1 \scan_stop }
|
|
{ \__tblr_get_childs_normal_aux:w ##1 - ##1 \scan_stop }
|
|
}
|
|
}
|
|
|
|
\cs_new_protected_nopar:Npn \__tblr_get_childs_normal_aux:w #1 - #2 \scan_stop
|
|
{
|
|
\__tblr_child_name_to_index:nN {#1} \l__tblr_child_from_tl
|
|
\__tblr_child_name_to_index:nN {#2} \l__tblr_child_to_tl
|
|
\int_step_inline:nnn { \l__tblr_child_from_tl } { \l__tblr_child_to_tl }
|
|
{ \clist_put_right:Nn \l_tblr_childs_clist {##1} }
|
|
}
|
|
|
|
\regex_const:Nn \c__tblr_child_name_regex { ^ [U-Z] $ }
|
|
|
|
%% Convert U, V, W, X, Y, Z to the indexes of the last six childs, respectively
|
|
\cs_new_protected_nopar:Npn \__tblr_child_name_to_index:nN #1 #2
|
|
{
|
|
\regex_match:NnTF \c__tblr_child_name_regex {#1}
|
|
{
|
|
\tl_set:Nx #2
|
|
{ \int_eval:n { \l_tblr_childs_total_tl + \int_from_alph:n {#1} - 26 } }
|
|
}
|
|
{ \tl_set:Nx #2 { #1 } }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_child_name_to_index:nN { VN }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{New Table Commands}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% We need some commands to modify table/row/column/cell specifications.
|
|
%% These commands must be defined with \NewTableCommand command,
|
|
%% so that we could extract them, execute them once, then disable them.
|
|
|
|
\clist_new:N \g__tblr_table_commands_clist
|
|
|
|
\msg_new:nnn { tabularray } { defined-table-command }
|
|
{ Table ~ command ~ #1 already ~ defined! }
|
|
|
|
\NewDocumentCommand \NewTableCommand { m O{0} o m }
|
|
{
|
|
\clist_if_in:NnTF \g__tblr_table_commands_clist { #1 }
|
|
{
|
|
\msg_error:nnn { tabularray } { defined-table-command } { #1 }
|
|
\clist_log:N \g__tblr_table_commands_clist
|
|
}
|
|
{
|
|
\__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_a_tl
|
|
\exp_args:NcV \NewDocumentCommand
|
|
{ __tblr_table_command_ \cs_to_str:N #1 :w } \l__tblr_a_tl { #4 }
|
|
%% we can not use \cs_if_exist:NTF here (see issue #328)
|
|
\__tblr_cs_if_defined:NTF #1
|
|
{
|
|
\cs_set_eq:cN { __tblr_table_command_ \cs_to_str:N #1 _saved:w } #1
|
|
}
|
|
{
|
|
\exp_args:NcV \NewDocumentCommand
|
|
{ __tblr_table_command_ \cs_to_str:N #1 _saved:w } \l__tblr_a_tl { }
|
|
}
|
|
\IfValueTF { #3 }
|
|
{
|
|
\tl_gset:cn { g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl } {-#2}
|
|
}
|
|
{
|
|
\tl_gset:cn { g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl } {#2}
|
|
}
|
|
\clist_gput_right:Nn \g__tblr_table_commands_clist { #1 }
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_enable_table_commands:
|
|
{
|
|
\clist_map_inline:Nn \g__tblr_table_commands_clist
|
|
{ \cs_set_eq:Nc ##1 { __tblr_table_command_ \cs_to_str:N ##1 :w } }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_disable_table_commands:
|
|
{
|
|
\clist_map_inline:Nn \g__tblr_table_commands_clist
|
|
{ \cs_set_eq:Nc ##1 { __tblr_table_command_ \cs_to_str:N ##1 _saved:w } }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_execute_table_commands:
|
|
{
|
|
\__tblr_prop_map_inline:nn { command }
|
|
{
|
|
\__tblr_set_row_col_from_key_name:w ##1
|
|
##2
|
|
}
|
|
\LogTblrTracing { cell }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_set_row_col_from_key_name:w [#1][#2]
|
|
{
|
|
\int_set:Nn \c@rownum {#1}
|
|
\int_set:Nn \c@colnum {#2}
|
|
}
|
|
|
|
%% Add \empty as a table command so that users can write \\\empty\hline (see #328)
|
|
\NewTableCommand\empty{}
|
|
|
|
%% Table commands are defined only inside tblr environments,
|
|
%% but some packages such as csvsimple need to use them outside tblr environments,
|
|
%% therefore we define some of them first here.
|
|
\ProvideDocumentCommand \SetHlines { o m m } {}
|
|
\ProvideDocumentCommand \SetHline { o m m } {}
|
|
\ProvideDocumentCommand \SetVlines { o m m } {}
|
|
\ProvideDocumentCommand \SetVline { o m m } {}
|
|
\ProvideDocumentCommand \SetCells { o m } {}
|
|
\ProvideDocumentCommand \SetCell { o m } {}
|
|
\ProvideDocumentCommand \SetRows { o m } {}
|
|
\ProvideDocumentCommand \SetRow { o m } {}
|
|
\ProvideDocumentCommand \SetColumns { o m } {}
|
|
\ProvideDocumentCommand \SetColumn { o m } {}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{New Content Commands}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% We need to emulate or fix some commands such as \diagbox in other packages
|
|
%% These commands must be defined with \NewContentCommand command
|
|
%% We only enable them inside tblr environment to avoid potential conflict
|
|
|
|
\clist_new:N \g__tblr_content_commands_clist
|
|
|
|
\msg_new:nnn { tabularray } { defined-content-command }
|
|
{ Content ~ command ~ #1 already ~ defined! }
|
|
|
|
\NewDocumentCommand \NewContentCommand { m O{0} o m }
|
|
{
|
|
\clist_if_in:NnTF \g__tblr_content_commands_clist { #1 }
|
|
{
|
|
\msg_error:nnn { tabularray } { defined-content-command } { #1 }
|
|
\clist_log:N \g__tblr_content_commands_clist
|
|
}
|
|
{
|
|
\__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_a_tl
|
|
\exp_args:NcV \NewDocumentCommand
|
|
{ __tblr_content_command_ \cs_to_str:N #1 :w } \l__tblr_a_tl { #4 }
|
|
\clist_gput_right:Nn \g__tblr_content_commands_clist { #1 }
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_enable_content_commands:
|
|
{
|
|
\clist_map_inline:Nn \g__tblr_content_commands_clist
|
|
{ \cs_set_eq:Nc ##1 { __tblr_content_command_ \cs_to_str:N ##1 :w } }
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{New Dash Styles}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% \NewDashStyle commands
|
|
|
|
\dim_zero_new:N \rulewidth
|
|
\dim_set:Nn \rulewidth {0.4pt}
|
|
|
|
\prop_gset_from_keyval:Nn \g__tblr_defined_hdash_styles_prop
|
|
{ solid = \hrule height \rulewidth }
|
|
\prop_gset_from_keyval:Nn \g__tblr_defined_vdash_styles_prop
|
|
{ solid = \vrule width \rulewidth }
|
|
|
|
\NewDocumentCommand \NewDashStyle { m m }
|
|
{
|
|
\seq_set_split:Nnn \l_tmpa_seq { ~ } {#2}
|
|
\tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {1} }
|
|
\tl_set:Nx \l__tblr_b_tl { \seq_item:Nn \l_tmpa_seq {2} }
|
|
\tl_set:Nx \l__tblr_c_tl { \seq_item:Nn \l_tmpa_seq {3} }
|
|
\tl_set:Nx \l__tblr_d_tl { \seq_item:Nn \l_tmpa_seq {4} }
|
|
\tl_if_eq:NnT \l__tblr_a_tl { on }
|
|
{
|
|
\tl_if_eq:NnT \l__tblr_c_tl { off }
|
|
{
|
|
\__tblr_dash_style_make_boxes:nxx {#1}
|
|
{ \dim_eval:n {\l__tblr_b_tl} } { \dim_eval:n {\l__tblr_d_tl} }
|
|
}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_dash_style_make_boxes:nnn #1 #2 #3
|
|
{
|
|
\dim_set:Nn \l_tmpa_dim { #2 + #3 }
|
|
\tl_set:Nn \l__tblr_h_tl { \hbox_to_wd:nn }
|
|
\tl_put_right:Nx \l__tblr_h_tl { { \dim_use:N \l_tmpa_dim } }
|
|
\tl_put_right:Nn \l__tblr_h_tl
|
|
{
|
|
{ \hss \vbox:n { \hbox_to_wd:nn {#2} {} \hrule height \rulewidth } \hss }
|
|
}
|
|
\prop_gput:NnV \g__tblr_defined_hdash_styles_prop {#1} \l__tblr_h_tl
|
|
%\prop_log:N \g__tblr_defined_hdash_styles_prop
|
|
\tl_set:Nn \l__tblr_v_tl { \vbox_to_ht:nn }
|
|
\tl_put_right:Nx \l__tblr_v_tl { { \dim_use:N \l_tmpa_dim } }
|
|
\tl_put_right:Nn \l__tblr_v_tl
|
|
{
|
|
{ \vss \hbox:n { \vbox_to_ht:nn {#2} {} \vrule width \rulewidth } \vss }
|
|
}
|
|
\prop_gput:NnV \g__tblr_defined_vdash_styles_prop {#1} \l__tblr_v_tl
|
|
%\prop_log:N \g__tblr_defined_vdash_styles_prop
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_dash_style_make_boxes:nnn { nxx }
|
|
|
|
\cs_new_protected:Npn \__tblr_get_hline_dash_style:N #1
|
|
{
|
|
\tl_set:Nx \l_tmpa_tl
|
|
{ \prop_item:NV \g__tblr_defined_hdash_styles_prop #1 }
|
|
\tl_if_empty:NF \l_tmpa_tl { \tl_set_eq:NN #1 \l_tmpa_tl }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_get_vline_dash_style:N #1
|
|
{
|
|
\tl_set:Nx \l_tmpa_tl
|
|
{ \prop_item:NV \g__tblr_defined_vdash_styles_prop #1 }
|
|
\tl_if_empty:NF \l_tmpa_tl { \tl_set_eq:NN #1 \l_tmpa_tl }
|
|
}
|
|
|
|
\NewDashStyle {dashed} {on ~ 2pt ~ off ~ 2pt}
|
|
\NewDashStyle {dotted} {on ~ 0.4pt ~ off ~ 1pt}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Set Hlines and Vlines}
|
|
%%% --------------------------------------------------------
|
|
|
|
\tl_const:Nn \@tblr@dash { dash }
|
|
\tl_const:Nn \@tblr@text { text }
|
|
|
|
\regex_const:Nn \c__tblr_is_color_key_regex { ^[A-Za-z] }
|
|
|
|
%% \SetHlines command for setting every hline in the table
|
|
\NewTableCommand \SetHlines [3] [+]
|
|
{
|
|
\tblr_set_every_hline:nnn {#1} {#2} {#3}
|
|
}
|
|
|
|
%% We put all code inside a group to avoid affecting other table commands
|
|
\cs_new_protected:Npn \tblr_set_every_hline:nnn #1 #2 #3
|
|
{
|
|
\group_begin:
|
|
\int_step_inline:nn { \int_eval:n { \c@rowcount + 1 } }
|
|
{
|
|
\int_set:Nn \c@rownum {##1}
|
|
\tblr_set_hline:nnn {#1} {#2} {#3}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_every_hline in different ways
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_every_hline_aux:n #1
|
|
{
|
|
\tl_if_head_is_group:nTF {#1}
|
|
{
|
|
\int_compare:nNnTF { \tl_count:n {#1} } = {3}
|
|
{ \tblr_set_every_hline:nnn #1 }
|
|
{ \tblr_set_every_hline:nnn {1} #1 }
|
|
}
|
|
{ \tblr_set_every_hline:nnn {1} {-} {#1} }
|
|
}
|
|
|
|
%% Add \SetHline, \hline and \cline commands
|
|
|
|
\tl_new:N \l__tblr_hline_count_tl % the count of all hlines
|
|
\tl_new:N \l__tblr_hline_num_tl % the index of the hline
|
|
\tl_new:N \l__tblr_hline_cols_tl % the columns of the hline
|
|
\tl_new:N \l__tblr_hline_dash_tl % dash style
|
|
\tl_new:N \l__tblr_hline_fg_tl % dash foreground
|
|
\tl_new:N \l__tblr_hline_wd_tl % dash width
|
|
\tl_new:N \l__tblr_hline_leftpos_tl % left position
|
|
\tl_new:N \l__tblr_hline_rightpos_tl % right position
|
|
\bool_new:N \l__tblr_hline_endpos_bool % whether set positions only for both ends
|
|
|
|
\NewTableCommand \cline [2] [] { \SetHline [=] {#2} {#1} }
|
|
|
|
\NewTableCommand \hline [1] [] { \SetHline [+] {-} {#1} }
|
|
|
|
%% #1: the index of the hline (may be + or =)
|
|
%% #2: which columns of the hline, separate by commas
|
|
%% #3: key=value pairs
|
|
\NewTableCommand \SetHline [3] [+]
|
|
{
|
|
\tblr_set_hline:nnn {#1} {#2} {#3}
|
|
}
|
|
|
|
%% We need to check "text" key first
|
|
%% If it does exist and has empty value, then do nothing
|
|
\cs_new_protected:Npn \tblr_set_hline:nnn #1 #2 #3
|
|
{
|
|
\group_begin:
|
|
\keys_set_groups:nnn { tblr-hline } { text } {#3}
|
|
\tl_if_eq:NnF \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text }
|
|
{
|
|
\__tblr_set_hline_num:n {#1}
|
|
\tl_clear:N \l__tblr_hline_dash_tl
|
|
\keys_set:nn { tblr-hline } { dash = solid, #3 }
|
|
\__tblr_set_hline_cmd:n {#2}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
\cs_new_protected:Npn \tblr_set_hline:nnnn #1 #2 #3 #4
|
|
{
|
|
\group_begin:
|
|
\__tblr_get_childs:nx {#1} { \int_eval:n { \c@rowcount + 1 } }
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\int_set:Nn \c@rownum {##1}
|
|
\tblr_set_hline:nnn {#2} {#3} {#4}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_hline in different ways
|
|
%% Note that #1 always includes an outer pair of braces
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_hline_aux:nn #1 #2
|
|
{
|
|
\tl_if_head_is_group:nTF {#2}
|
|
{
|
|
\int_compare:nNnTF { \tl_count:n {#2} } = {3}
|
|
{ \tblr_set_hline:nnnn #1 #2 }
|
|
{ \tblr_set_hline:nnnn #1 {1} #2 }
|
|
}
|
|
{ \tblr_set_hline:nnnn #1 {1} {-} {#2} }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_hline_aux:nn { Vn }
|
|
|
|
%% #1: the index of hline to set (may be + or =)
|
|
\cs_new_protected:Npn \__tblr_set_hline_num:n #1
|
|
{
|
|
\tl_clear:N \l__tblr_hline_num_tl
|
|
\tl_set:Nx \l__tblr_hline_count_tl
|
|
{ \__tblr_spec_item:ne { hline } { [\int_use:N \c@rownum] / @hline-count } }
|
|
%% \l__tblr_hline_count_tl may be empty when rowspec has extra |'s
|
|
\int_compare:nNnTF { \l__tblr_hline_count_tl + 0 } = {0}
|
|
{
|
|
\tl_set:Nx \l__tblr_hline_num_tl { 1 }
|
|
\__tblr_spec_gput:nen { hline }
|
|
{ [\int_use:N \c@rownum] / @hline-count } { 1 }
|
|
}
|
|
{
|
|
\tl_if_eq:nnTF {#1} {+}
|
|
{ \__tblr_set_hline_num_incr: }
|
|
{
|
|
\tl_if_eq:nnTF {#1} {=}
|
|
{ \tl_set_eq:NN \l__tblr_hline_num_tl \l__tblr_hline_count_tl }
|
|
{
|
|
\int_compare:nNnTF {#1} > { \l__tblr_hline_count_tl }
|
|
{ \__tblr_set_hline_num_incr: }
|
|
{ \tl_set:Nn \l__tblr_hline_num_tl {#1} }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_set_hline_num_incr:
|
|
{
|
|
\tl_set:Nx \l__tblr_hline_count_tl
|
|
{ \int_eval:n { \l__tblr_hline_count_tl + 1 } }
|
|
\__tblr_spec_gput:nee { hline }
|
|
{ [\int_use:N \c@rownum] / @hline-count } { \l__tblr_hline_count_tl }
|
|
\tl_set_eq:NN \l__tblr_hline_num_tl \l__tblr_hline_count_tl
|
|
}
|
|
|
|
\keys_define:nn { tblr-hline }
|
|
{
|
|
dash .code:n = \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@dash #1 },
|
|
text .code:n = \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text #1 },
|
|
text .groups:n = { text },
|
|
wd .code:n = \tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {#1} },
|
|
fg .code:n = \tl_set:Nn \l__tblr_hline_fg_tl {#1},
|
|
leftpos .code:n = \tl_set:Nx \l__tblr_hline_leftpos_tl {#1},
|
|
rightpos .code:n = \tl_set:Nx \l__tblr_hline_rightpos_tl {#1},
|
|
l .meta:n = { leftpos = #1 },
|
|
l .default:n = { -0.8 },
|
|
r .meta:n = { rightpos = #1 },
|
|
r .default:n = { -0.8 },
|
|
lr .meta:n = { leftpos = #1, rightpos = #1 },
|
|
lr .default:n = { -0.8 },
|
|
endpos .bool_set:N = \l__tblr_hline_endpos_bool,
|
|
unknown .code:n = \__tblr_hline_unknown_key:V \l_keys_key_str,
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_hline_unknown_key:n #1
|
|
{
|
|
\prop_if_in:NnTF \g__tblr_defined_hdash_styles_prop {#1}
|
|
{ \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@dash #1 } }
|
|
{
|
|
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
|
|
{ \tl_set:Nn \l__tblr_hline_fg_tl {#1} }
|
|
{
|
|
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
|
|
\tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {\l__tblr_v_tl} }
|
|
}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_hline_unknown_key:n { V }
|
|
|
|
\cs_new_protected_nopar:Npn \__tblr_set_hline_cmd:n #1
|
|
{
|
|
\__tblr_get_childs:nx {#1} { \int_use:N \c@colcount }
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\__tblr_set_hline_option:nnn { ##1 } { @dash } { \l__tblr_hline_dash_tl }
|
|
\tl_if_empty:NF \l__tblr_hline_wd_tl
|
|
{
|
|
\__tblr_set_hline_option:nnn { ##1 } { wd } { \l__tblr_hline_wd_tl }
|
|
}
|
|
\tl_if_empty:NF \l__tblr_hline_fg_tl
|
|
{
|
|
\__tblr_set_hline_option:nnn { ##1 } { fg } { \l__tblr_hline_fg_tl }
|
|
}
|
|
}
|
|
\tl_if_empty:NF \l__tblr_hline_leftpos_tl
|
|
{
|
|
\bool_if:NTF \l__tblr_hline_endpos_bool
|
|
{
|
|
\__tblr_set_hline_option:nnn
|
|
{ \clist_item:Nn \l_tblr_childs_clist {1} }
|
|
{ leftpos }
|
|
{ \l__tblr_hline_leftpos_tl }
|
|
}
|
|
{
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\__tblr_set_hline_option:nnn
|
|
{ ##1 } { leftpos } { \l__tblr_hline_leftpos_tl }
|
|
}
|
|
}
|
|
}
|
|
\tl_if_empty:NF \l__tblr_hline_rightpos_tl
|
|
{
|
|
\bool_if:NTF \l__tblr_hline_endpos_bool
|
|
{
|
|
\__tblr_set_hline_option:nnn
|
|
{ \clist_item:Nn \l_tblr_childs_clist {-1} }
|
|
{ rightpos }
|
|
{ \l__tblr_hline_rightpos_tl }
|
|
}
|
|
{
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\__tblr_set_hline_option:nnn
|
|
{ ##1 } { rightpos } { \l__tblr_hline_rightpos_tl }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
%% #1: column; #2: key; #3: value
|
|
\cs_new_protected_nopar:Npn \__tblr_set_hline_option:nnn #1 #2 #3
|
|
{
|
|
\__tblr_spec_gput:nee { hline }
|
|
{ [\int_use:N \c@rownum][#1](\l__tblr_hline_num_tl) / #2 } { #3 }
|
|
}
|
|
|
|
\msg_new:nnn { tabularray } { obsolete-firsthline }
|
|
{ \firsthline ~ is ~ obsolete; ~ use ~ 'baseline=T' ~ instead. }
|
|
|
|
\msg_new:nnn { tabularray } { obsolete-lasthline }
|
|
{ \lasthline ~ is ~ obsolete; ~ use ~ 'baseline=B' ~ instead. }
|
|
|
|
\NewTableCommand \firsthline [1] []
|
|
{
|
|
\msg_error:nn { tabularray } { obsolete-firsthline }
|
|
}
|
|
|
|
\NewTableCommand \lasthline [1] []
|
|
{
|
|
\msg_error:nn { tabularray } { obsolete-lasthline }
|
|
}
|
|
|
|
%% \SetVlines command for setting every vline in the table
|
|
\NewTableCommand \SetVlines [3] [+]
|
|
{
|
|
\tblr_set_every_vline:nnn {#1} {#2} {#3}
|
|
}
|
|
|
|
%% We put all code inside a group to avoid affecting other table commands
|
|
\cs_new_protected:Npn \tblr_set_every_vline:nnn #1 #2 #3
|
|
{
|
|
\group_begin:
|
|
\int_step_inline:nn { \int_eval:n { \c@colcount + 1 } }
|
|
{
|
|
\int_set:Nn \c@colnum {##1}
|
|
\tblr_set_vline:nnn {#1} {#2} {#3}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_every_vline in different ways
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_every_vline_aux:n #1
|
|
{
|
|
\tl_if_head_is_group:nTF {#1}
|
|
{
|
|
\int_compare:nNnTF { \tl_count:n {#1} } = {3}
|
|
{ \tblr_set_every_vline:nnn #1 }
|
|
{ \tblr_set_every_vline:nnn {1} #1 }
|
|
}
|
|
{ \tblr_set_every_vline:nnn {1} {-} {#1} }
|
|
}
|
|
|
|
%% Add \SetVline, \vline and \rline commands
|
|
|
|
\tl_new:N \l__tblr_vline_count_tl % the count of all vlines
|
|
\tl_new:N \l__tblr_vline_num_tl % the index of the vline
|
|
\tl_new:N \l__tblr_vline_rows_tl % the rows of the vline
|
|
\tl_new:N \l__tblr_vline_dash_tl % dash style
|
|
\tl_new:N \l__tblr_vline_fg_tl % dash foreground
|
|
\tl_new:N \l__tblr_vline_wd_tl % dash width
|
|
\tl_new:N \l__tblr_vline_abovepos_tl % above position
|
|
\tl_new:N \l__tblr_vline_belowpos_tl % below position
|
|
|
|
\NewTableCommand \rline [2] [] { \SetVline [=] {#2} {#1} }
|
|
|
|
\NewTableCommand \vline [1] [] { \SetVline [+] {-} {#1} }
|
|
|
|
%% #1: the index of the vline (may be + or =)
|
|
%% #2: which rows of the vline, separate by commas
|
|
%% #3: key=value pairs
|
|
\NewTableCommand \SetVline [3] [+]
|
|
{
|
|
\tblr_set_vline:nnn {#1} {#2} {#3}
|
|
}
|
|
|
|
%% We need to check "text" key first
|
|
%% If it does exist and has empty value, then do nothing
|
|
\cs_new_protected:Npn \tblr_set_vline:nnn #1 #2 #3
|
|
{
|
|
\group_begin:
|
|
\keys_set_groups:nnn { tblr-vline } { text } {#3}
|
|
\tl_if_eq:NnF \l__tblr_vline_dash_tl { \exp_not:N \@tblr@text }
|
|
{
|
|
\__tblr_set_vline_num:n {#1}
|
|
\tl_clear:N \l__tblr_vline_dash_tl
|
|
\keys_set:nn { tblr-vline } { dash = solid, #3 }
|
|
\__tblr_set_vline_cmd:n {#2}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
\cs_new_protected:Npn \tblr_set_vline:nnnn #1 #2 #3 #4
|
|
{
|
|
\group_begin:
|
|
\__tblr_get_childs:nx {#1} { \int_eval:n { \c@colcount + 1} }
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\int_set:Nn \c@colnum {##1}
|
|
\tblr_set_vline:nnn {#2} {#3} {#4}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_vline in different ways
|
|
%% Note that #1 always includes an outer pair of braces
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_vline_aux:nn #1 #2
|
|
{
|
|
\tl_if_head_is_group:nTF {#2}
|
|
{
|
|
\int_compare:nNnTF { \tl_count:n {#2} } = {3}
|
|
{ \tblr_set_vline:nnnn #1 #2 }
|
|
{ \tblr_set_vline:nnnn #1 {1} #2 }
|
|
}
|
|
{ \tblr_set_vline:nnnn #1 {1} {-} {#2} }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_vline_aux:nn { Vn }
|
|
|
|
%% #1: the index of vline to set (may be + or =)
|
|
\cs_new_protected:Npn \__tblr_set_vline_num:n #1
|
|
{
|
|
\tl_clear:N \l__tblr_vline_num_tl
|
|
\tl_set:Nx \l__tblr_vline_count_tl
|
|
{ \__tblr_spec_item:ne { vline } { [\int_use:N \c@colnum] / @vline-count } }
|
|
%% \l__tblr_vline_count_tl may be empty when colspec has extra |'s
|
|
\int_compare:nNnTF { \l__tblr_vline_count_tl + 0 } = {0}
|
|
{
|
|
\tl_set:Nx \l__tblr_vline_num_tl { 1 }
|
|
\__tblr_spec_gput:nen { vline }
|
|
{ [\int_use:N \c@colnum] / @vline-count } { 1 }
|
|
}
|
|
{
|
|
\tl_if_eq:nnTF {#1} {+}
|
|
{ \__tblr_set_vline_num_incr: }
|
|
{
|
|
\tl_if_eq:nnTF {#1} {=}
|
|
{ \tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl }
|
|
{
|
|
\int_compare:nNnTF {#1} > { \l__tblr_vline_count_tl }
|
|
{ \__tblr_set_vline_num_incr: }
|
|
{ \tl_set:Nn \l__tblr_vline_num_tl {#1} }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_set_vline_num_incr:
|
|
{
|
|
\tl_set:Nx \l__tblr_vline_count_tl
|
|
{ \int_eval:n { \l__tblr_vline_count_tl + 1 } }
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [\int_use:N \c@colnum] / @vline-count } { \l__tblr_vline_count_tl }
|
|
\tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl
|
|
}
|
|
|
|
\keys_define:nn { tblr-vline }
|
|
{
|
|
dash .code:n = \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@dash #1 },
|
|
text .code:n = \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@text #1 },
|
|
text .groups:n = { text },
|
|
wd .code:n = \tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {#1} },
|
|
fg .code:n = \tl_set:Nn \l__tblr_vline_fg_tl {#1},
|
|
abovepos .code:n = \tl_set:Nx \l__tblr_vline_abovepos_tl {#1},
|
|
belowpos .code:n = \tl_set:Nx \l__tblr_vline_belowpos_tl {#1},
|
|
unknown .code:n = \__tblr_vline_unknown_key:V \l_keys_key_str,
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_vline_unknown_key:n #1
|
|
{
|
|
\prop_if_in:NnTF \g__tblr_defined_vdash_styles_prop {#1}
|
|
{ \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@dash #1 } }
|
|
{
|
|
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
|
|
{ \tl_set:Nn \l__tblr_vline_fg_tl {#1} }
|
|
{
|
|
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
|
|
\tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {\l__tblr_v_tl} }
|
|
}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_vline_unknown_key:n { V }
|
|
|
|
\cs_new_protected_nopar:Npn \__tblr_set_vline_cmd:n #1
|
|
{
|
|
\__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / @dash }
|
|
{ \l__tblr_vline_dash_tl }
|
|
\tl_if_empty:NF \l__tblr_vline_wd_tl
|
|
{
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / wd }
|
|
{ \l__tblr_vline_wd_tl }
|
|
}
|
|
\tl_if_empty:NF \l__tblr_vline_fg_tl
|
|
{
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / fg }
|
|
{ \l__tblr_vline_fg_tl }
|
|
}
|
|
\tl_if_empty:NF \l__tblr_vline_abovepos_tl
|
|
{
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / abovepos }
|
|
{ \l__tblr_vline_abovepos_tl }
|
|
}
|
|
\tl_if_empty:NF \l__tblr_vline_belowpos_tl
|
|
{
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / belowpos }
|
|
{ \l__tblr_vline_belowpos_tl }
|
|
}
|
|
}
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Set Hborders and Vborders}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% Hborder holds keys not related to a specified hline
|
|
\NewTableCommand \hborder [1] { \tblr_set_hborder:n {#1} }
|
|
|
|
\cs_new_protected:Npn \tblr_set_hborder:n #1
|
|
{
|
|
\keys_set:nn { tblr-hborder } {#1}
|
|
}
|
|
|
|
\cs_new_protected:Npn \tblr_set_hborder:nn #1 #2
|
|
{
|
|
\group_begin:
|
|
\__tblr_get_childs:nx {#1} { \int_eval:n { \c@rowcount + 1 } }
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\int_set:Nn \c@rownum {##1}
|
|
\tblr_set_hborder:n {#2}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% This function is called when parsing table specifications
|
|
%% Note that #1 always includes an outer pair of braces
|
|
\cs_new_protected:Npn \__tblr_set_hborder_aux:nn #1 #2
|
|
{
|
|
\tblr_set_hborder:nn #1 {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_hborder_aux:nn { Vn }
|
|
|
|
\keys_define:nn { tblr-hborder }
|
|
{
|
|
abovespace .code:n = \__tblr_row_gput_above:ne
|
|
{ belowsep } { \dim_eval:n {#1} },
|
|
belowspace .code:n = \__tblr_row_gput:ne { abovesep } { \dim_eval:n {#1} },
|
|
abovespace+ .code:n = \__tblr_row_gadd_dimen_above:ne
|
|
{ belowsep } { \dim_eval:n {#1} },
|
|
belowspace+ .code:n = \__tblr_row_gadd_dimen:ne
|
|
{ abovesep } { \dim_eval:n {#1} },
|
|
pagebreak .code:n = \__tblr_hborder_gput_pagebreak:n {#1},
|
|
pagebreak .default:n = yes,
|
|
baseline .code:n = \__tblr_outer_gput_spec:ne
|
|
{ baseline } { - \int_use:N \c@rownum },
|
|
}
|
|
|
|
\tl_const:Nn \c__tblr_pagebreak_yes_tl { 1 }
|
|
\tl_const:Nn \c__tblr_pagebreak_auto_tl { 0 }
|
|
\tl_const:Nn \c__tblr_pagebreak_no_tl { -1 }
|
|
|
|
\cs_new_protected:Npn \__tblr_hborder_gput_pagebreak:n #1
|
|
{
|
|
\tl_if_exist:cT { c__tblr_pagebreak_ #1 _tl }
|
|
{
|
|
\__tblr_spec_gput:nee { hline }
|
|
{ [\int_use:N \c@rownum] / @pagebreak }
|
|
{ \tl_use:c { c__tblr_pagebreak_ #1 _tl } }
|
|
}
|
|
}
|
|
|
|
%% Vborder holds keys not related to a specified vline
|
|
\NewTableCommand \vborder [1] { \tblr_set_vborder:n {#1} }
|
|
|
|
\cs_new_protected:Npn \tblr_set_vborder:n #1
|
|
{
|
|
\keys_set:nn { tblr-vborder } {#1}
|
|
}
|
|
|
|
\cs_new_protected:Npn \tblr_set_vborder:nn #1 #2
|
|
{
|
|
\group_begin:
|
|
\__tblr_get_childs:nx {#1} { \int_eval:n { \c@colcount + 1 } }
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\int_set:Nn \c@colnum {##1}
|
|
\tblr_set_vborder:n {#2}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% This function is called when parsing table specifications
|
|
%% Note that #1 always includes an outer pair of braces
|
|
\cs_new_protected:Npn \__tblr_set_vborder_aux:nn #1 #2
|
|
{
|
|
\tblr_set_vborder:nn #1 {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_vborder_aux:nn { Vn }
|
|
|
|
\keys_define:nn { tblr-vborder }
|
|
{
|
|
leftspace .code:n = \__tblr_column_gput_left:ne
|
|
{ rightsep } { \dim_eval:n {#1} },
|
|
rightspace .code:n = \__tblr_column_gput:ne { leftsep } { \dim_eval:n {#1} },
|
|
leftspace+ .code:n = \__tblr_column_gadd_dimen_left:ne
|
|
{ rightsep } { \dim_eval:n {#1} },
|
|
rightspace+ .code:n = \__tblr_column_gadd_dimen:ne
|
|
{ leftsep } { \dim_eval:n {#1} },
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Set Cells}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% \SetCells command for setting every cell in the table
|
|
\NewTableCommand \SetCells [2] []
|
|
{
|
|
\tblr_set_every_cell:nn {#1} {#2}
|
|
}
|
|
|
|
%% We put all code inside a group to avoid affecting other table commands
|
|
\cs_new_protected:Npn \tblr_set_every_cell:nn #1 #2
|
|
{
|
|
\group_begin:
|
|
\int_step_inline:nn { \c@rowcount }
|
|
{
|
|
\int_set:Nn \c@rownum {##1}
|
|
\int_step_inline:nn { \c@colcount }
|
|
{
|
|
\int_set:Nn \c@colnum {####1}
|
|
\tblr_set_cell:nn {#1} {#2}
|
|
}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_every_cell in different ways
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_every_cell_aux:n #1
|
|
{
|
|
\tl_if_head_is_group:nTF {#1}
|
|
{ \tblr_set_every_cell:nn #1 }
|
|
{ \tblr_set_every_cell:nn {} {#1} }
|
|
}
|
|
|
|
%% \SetCell command for multirow and/or multicolumn cells
|
|
|
|
\NewTableCommand \SetCell [2] []
|
|
{
|
|
\tblr_set_cell:nn { #1 } { #2 }
|
|
}
|
|
|
|
\tl_new:N \l__tblr_row_span_num_tl
|
|
\tl_new:N \l__tblr_col_span_num_tl
|
|
|
|
\cs_new_protected:Npn \tblr_set_cell:nn #1 #2
|
|
{
|
|
\tl_set:Nn \l__tblr_row_span_num_tl { 1 }
|
|
\tl_set:Nn \l__tblr_col_span_num_tl { 1 }
|
|
\keys_set:nn { tblr-cell-span } { #1 }
|
|
\keys_set:nn { tblr-cell-spec } { #2 }
|
|
\__tblr_set_span_spec:VV \l__tblr_row_span_num_tl \l__tblr_col_span_num_tl
|
|
}
|
|
\cs_generate_variant:Nn \tblr_set_cell:nn { nV }
|
|
|
|
\cs_new_protected:Npn \tblr_set_cell:nnnn #1 #2 #3 #4
|
|
{
|
|
\group_begin:
|
|
\__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
|
|
\clist_set_eq:NN \l_tmpa_clist \l_tblr_childs_clist
|
|
\__tblr_get_childs:nx {#2} { \int_use:N \c@colcount }
|
|
\clist_set_eq:NN \l_tmpb_clist \l_tblr_childs_clist
|
|
\clist_map_inline:Nn \l_tmpa_clist
|
|
{
|
|
\int_set:Nn \c@rownum {##1}
|
|
\clist_map_inline:Nn \l_tmpb_clist
|
|
{
|
|
\int_set:Nn \c@colnum {####1}
|
|
\tblr_set_cell:nn {#3} {#4}
|
|
}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_cell in different ways
|
|
%% Note that #1 is always of the type {<i>}{<j>}
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_cell_aux:nn #1 #2
|
|
{
|
|
\tl_if_head_is_group:nTF {#2}
|
|
{ \tblr_set_cell:nnnn #1 #2 }
|
|
{ \tblr_set_cell:nnnn #1 {} {#2} }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_cell_aux:nn { Vn }
|
|
|
|
\keys_define:nn { tblr-cell-span }
|
|
{
|
|
r .tl_set:N = \l__tblr_row_span_num_tl,
|
|
c .tl_set:N = \l__tblr_col_span_num_tl,
|
|
}
|
|
|
|
\keys_define:nn { tblr-cell-spec }
|
|
{
|
|
halign .code:n = \__tblr_cell_gput:nn { halign } {#1},
|
|
valign .code:n = \__tblr_cell_gput:nn { valign } {#1},
|
|
j .meta:n = { halign = j },
|
|
l .meta:n = { halign = l },
|
|
c .meta:n = { halign = c },
|
|
r .meta:n = { halign = r },
|
|
t .meta:n = { valign = t },
|
|
p .meta:n = { valign = t },
|
|
m .meta:n = { valign = m },
|
|
b .meta:n = { valign = b },
|
|
h .meta:n = { valign = h },
|
|
f .meta:n = { valign = f },
|
|
wd .code:n = \__tblr_cell_gput:ne { width } {#1},
|
|
bg .code:n = \__tblr_cell_gput:ne { background } {#1},
|
|
fg .code:n = \__tblr_cell_gput:ne { foreground } {#1},
|
|
font .code:n = \__tblr_cell_gput:nn { font } { #1 \selectfont },
|
|
mode .code:n = \__tblr_cell_gput:nn { mode } {#1},
|
|
$ .meta:n = { mode = math },
|
|
$$ .meta:n = { mode = dmath },
|
|
cmd .code:n = \__tblr_cell_gput:nn { cmd } {#1},
|
|
preto .code:n = \__tblr_cell_preto_text:n {#1},
|
|
appto .code:n = \__tblr_cell_appto_text:n {#1},
|
|
unknown .code:n = \__tblr_cell_unknown_key:V \l_keys_key_str,
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_cell_gput:nn #1 #2
|
|
{
|
|
\__tblr_data_gput:neenn { cell }
|
|
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_cell_gput:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_cell_gput:nnnn #1 #2 #3 #4
|
|
{
|
|
\__tblr_data_gput:nnnnn { cell } {#1} {#2} {#3} {#4}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_cell_gput:nnnn
|
|
{ nenn, ennn, eenn, nene, enne, eene }
|
|
|
|
\tl_new:N \l__tblr_cell_text_tl
|
|
|
|
\cs_new_protected:Npn \__tblr_cell_preto_text:n #1
|
|
{
|
|
\__tblr_cell_preto_text:een
|
|
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_cell_preto_text:nnn #1 #2 #3
|
|
{
|
|
\tl_set:Nx \l__tblr_cell_text_tl { \__tblr_spec_item:nn { text } { [#1][#2] } }
|
|
\tl_put_left:Nn \l__tblr_cell_text_tl {#3}
|
|
\__tblr_spec_gput:nnV { text } { [#1][#2] } \l__tblr_cell_text_tl
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_cell_preto_text:nnn { nen, enn, een }
|
|
|
|
\cs_new_protected:Npn \__tblr_cell_appto_text:n #1
|
|
{
|
|
\__tblr_cell_appto_text:een
|
|
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_cell_appto_text:nnn #1 #2 #3
|
|
{
|
|
\tl_set:Nx \l__tblr_cell_text_tl { \__tblr_spec_item:ne { text } { [#1][#2] } }
|
|
\tl_put_right:Nn \l__tblr_cell_text_tl {#3}
|
|
\__tblr_spec_gput:neV { text } { [#1][#2] } \l__tblr_cell_text_tl
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_cell_appto_text:nnn { nen, enn, een }
|
|
|
|
\cs_new_protected:Npn \__tblr_cell_unknown_key:n #1
|
|
{
|
|
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
|
|
{
|
|
\__tblr_data_gput:neene { cell }
|
|
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { background } {#1}
|
|
}
|
|
{
|
|
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
|
|
\__tblr_data_gput:neene { cell }
|
|
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { width }
|
|
{ \dim_eval:n { \l__tblr_v_tl } }
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_cell_unknown_key:n { V }
|
|
|
|
\cs_new_protected:Npn \__tblr_set_span_spec:nn #1 #2
|
|
{
|
|
\int_compare:nNnT { #1 } > { 1 }
|
|
{
|
|
\__tblr_prop_gput:nnn { inner } { rowspan } { true }
|
|
\__tblr_data_gput:neenn { cell }
|
|
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { rowspan } {#1}
|
|
}
|
|
\int_compare:nNnT { #2 } > { 1 }
|
|
{
|
|
\__tblr_prop_gput:nnn { inner } { colspan } { true }
|
|
\__tblr_data_gput:neenn { cell }
|
|
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { colspan } {#2}
|
|
}
|
|
\int_step_variable:nnNn
|
|
{ \int_use:N \c@rownum } { \int_eval:n { \c@rownum + #1 - 1 } } \l__tblr_i_tl
|
|
{
|
|
\int_step_variable:nnNn
|
|
{ \int_use:N \c@colnum } { \int_eval:n { \c@colnum + #2 - 1 } }
|
|
\l__tblr_j_tl
|
|
{
|
|
\bool_lazy_and:nnF
|
|
{ \int_compare_p:nNn { \l__tblr_i_tl } = { \c@rownum } }
|
|
{ \int_compare_p:nNn { \l__tblr_j_tl } = { \c@colnum } }
|
|
{
|
|
\__tblr_data_gput:neenn { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { omit } {1}
|
|
}
|
|
\int_compare:nNnF { \l__tblr_i_tl } = { \c@rownum }
|
|
{
|
|
\__tblr_spec_gput:nen { hline }
|
|
{ [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
|
|
}
|
|
\int_compare:nNnF { \l__tblr_j_tl } = { \c@colnum }
|
|
{
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
|
|
}
|
|
}
|
|
}
|
|
%% Make continuous borders for multirow cells
|
|
\tl_set:Nx \l__tblr_n_tl
|
|
{
|
|
\int_max:nn
|
|
{
|
|
\__tblr_spec_item:ne { vline } { [\int_use:N \c@colnum] / @vline-count }
|
|
}
|
|
{ 1 }
|
|
}
|
|
\int_step_variable:nnNn
|
|
{ \c@rownum } { \int_eval:n { \c@rownum + #1 - 2 } } \l__tblr_i_tl
|
|
{
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [\l__tblr_i_tl][\int_use:N \c@colnum](\l__tblr_n_tl) / belowpos } {1}
|
|
\__tblr_spec_gput:nee { vline }
|
|
{ [\l__tblr_i_tl][\int_eval:n {\c@colnum + #2}](1) / belowpos } {1}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_span_spec:nn { VV }
|
|
|
|
%% Obsolete \multicolumn and \multirow commands
|
|
|
|
\msg_new:nnn { tabularray } { obsolete-multicolumn }
|
|
{ \multicolumn ~ is ~ obsolete; ~ use ~ \SetCell ~ instead. }
|
|
|
|
\msg_new:nnn { tabularray } { obsolete-multirow }
|
|
{ \multirow ~ is ~ obsolete; ~ use ~ \SetCell ~ instead. }
|
|
|
|
\NewTableCommand \multicolumn [2]
|
|
{
|
|
\msg_error:nn { tabularray } { obsolete-multicolumn }
|
|
}
|
|
|
|
\NewTableCommand \multirow [3] [m]
|
|
{
|
|
\msg_error:nn { tabularray } { obsolete-multirow }
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Set Columns and Rows}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% \SetColumns command for setting every column in the table
|
|
\NewTableCommand \SetColumns [2] []
|
|
{
|
|
\tblr_set_every_column:nn {#1} {#2}
|
|
}
|
|
|
|
%% We put all code inside a group to avoid affecting other table commands
|
|
\cs_new_protected:Npn \tblr_set_every_column:nn #1 #2
|
|
{
|
|
\group_begin:
|
|
\int_step_inline:nn { \c@colcount }
|
|
{
|
|
\int_set:Nn \c@colnum {##1}
|
|
\tblr_set_column:nn {#1} {#2}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_every_column in different ways
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_every_column_aux:n #1
|
|
{
|
|
\tl_if_head_is_group:nTF {#1}
|
|
{ \tblr_set_every_column:nn #1 }
|
|
{ \tblr_set_every_column:nn {} {#1} }
|
|
}
|
|
|
|
%% \SetColumn command for current column or each cells in the column
|
|
|
|
\NewTableCommand \SetColumn [2] []
|
|
{
|
|
\tblr_set_column:nn {#1} {#2}
|
|
}
|
|
|
|
\cs_new_protected:Npn \tblr_set_column:nn #1 #2
|
|
{
|
|
\keys_set:nn { tblr-column } {#2}
|
|
}
|
|
|
|
\cs_new_protected:Npn \tblr_set_column:nnn #1 #2 #3
|
|
{
|
|
\group_begin:
|
|
\__tblr_get_childs:nx {#1} { \int_use:N \c@colcount }
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\int_set:Nn \c@colnum {##1}
|
|
\tblr_set_column:nn {#2} {#3}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_column in different ways
|
|
%% Note that #1 always includes an outer pair of braces
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_column_aux:nn #1 #2
|
|
{
|
|
\tl_if_head_is_group:nTF {#2}
|
|
{ \tblr_set_column:nnn #1 #2 }
|
|
{ \tblr_set_column:nnn #1 {} {#2} }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_column_aux:nn { Vn }
|
|
|
|
\keys_define:nn { tblr-column }
|
|
{
|
|
halign .code:n = \__tblr_column_gput_cell:nn { halign } {#1},
|
|
valign .code:n = \__tblr_column_gput_cell:nn { valign } {#1},
|
|
j .meta:n = { halign = j },
|
|
l .meta:n = { halign = l },
|
|
c .meta:n = { halign = c },
|
|
r .meta:n = { halign = r },
|
|
t .meta:n = { valign = t },
|
|
p .meta:n = { valign = t },
|
|
m .meta:n = { valign = m },
|
|
b .meta:n = { valign = b },
|
|
h .meta:n = { valign = h },
|
|
f .meta:n = { valign = f },
|
|
bg .code:n = \__tblr_column_gput_cell:nn { background } {#1},
|
|
fg .code:n = \__tblr_column_gput_cell:nn { foreground } {#1},
|
|
font .code:n = \__tblr_column_gput_cell:nn { font } { #1 \selectfont },
|
|
mode .code:n = \__tblr_column_gput_cell:nn { mode } {#1},
|
|
$ .meta:n = { mode = math },
|
|
$$ .meta:n = { mode = dmath },
|
|
cmd .code:n = \__tblr_column_gput_cell:nn { cmd } {#1},
|
|
wd .code:n = \__tblr_column_gput:ne { width } { \dim_eval:n {#1} },
|
|
co .code:n = \__tblr_column_gput:ne { coefficient } {#1},
|
|
preto .code:n = \__tblr_preto_text_for_every_column_cell:n {#1},
|
|
appto .code:n = \__tblr_appto_text_for_every_column_cell:n {#1},
|
|
leftsep .code:n = \__tblr_column_gput:ne { leftsep } { \dim_eval:n {#1} },
|
|
rightsep .code:n = \__tblr_column_gput:ne { rightsep } { \dim_eval:n {#1} },
|
|
colsep .meta:n = { leftsep = #1, rightsep = #1},
|
|
leftsep+ .code:n = \__tblr_column_gadd_dimen:ne
|
|
{ leftsep } { \dim_eval:n {#1} },
|
|
rightsep+ .code:n = \__tblr_column_gadd_dimen:ne
|
|
{ rightsep } { \dim_eval:n {#1} },
|
|
colsep+ .meta:n = { leftsep+ = #1, rightsep+ = #1},
|
|
unknown .code:n = \__tblr_column_unknown_key:V \l_keys_key_str,
|
|
}
|
|
|
|
%% #1: key; #2: value
|
|
\cs_new_protected:Npn \__tblr_column_gput:nn #1 #2
|
|
{
|
|
\__tblr_data_gput:nenn { column } { \int_use:N \c@colnum } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_column_gput:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_column_gput_left:nn #1 #2
|
|
{
|
|
\__tblr_data_gput:nenn { column } { \int_eval:n { \c@colnum - 1 } } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_column_gput_left:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_column_gadd_dimen:nn #1 #2
|
|
{
|
|
\__tblr_data_gadd_dimen_value:nenn { column }
|
|
{ \int_use:N \c@colnum } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_column_gadd_dimen:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_column_gadd_dimen_left:nn #1 #2
|
|
{
|
|
\__tblr_data_gadd_dimen_value:nenn { column }
|
|
{ \int_eval:n { \c@colnum - 1 } } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_column_gadd_dimen_left:nn { ne }
|
|
|
|
%% #1: key; #2: value
|
|
\cs_new_protected:Npn \__tblr_column_gput_cell:nn #1 #2
|
|
{
|
|
\int_step_inline:nn { \c@rowcount }
|
|
{
|
|
\__tblr_cell_gput:nenn {##1} { \int_use:N \c@colnum } {#1} {#2}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_column_gput_cell:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_preto_text_for_every_column_cell:n #1
|
|
{
|
|
\int_step_inline:nn { \c@rowcount }
|
|
{
|
|
\__tblr_cell_preto_text:nen {##1} { \int_use:N \c@colnum } {#1}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_appto_text_for_every_column_cell:n #1
|
|
{
|
|
\int_step_inline:nn { \c@rowcount }
|
|
{
|
|
\__tblr_cell_appto_text:nen {##1} { \int_use:N \c@colnum } {#1}
|
|
}
|
|
}
|
|
|
|
\regex_const:Nn \c__tblr_is_number_key_regex { ^[\+\-]? (\d+|\d*\.\d+)$ }
|
|
|
|
\cs_new_protected:Npn \__tblr_column_unknown_key:n #1
|
|
{
|
|
\regex_match:NnTF \c__tblr_is_number_key_regex {#1}
|
|
{ \__tblr_column_gput:ne { coefficient } {#1} }
|
|
{
|
|
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
|
|
{ \__tblr_column_gput_cell:nn { background } {#1} }
|
|
{
|
|
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
|
|
\__tblr_column_gput:ne { width } { \dim_eval:n { \l__tblr_v_tl } }
|
|
}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_column_unknown_key:n { V }
|
|
|
|
%% \SetRows command for setting every row in the table
|
|
\NewTableCommand \SetRows [2] []
|
|
{
|
|
\tblr_set_every_row:nn {#1} {#2}
|
|
}
|
|
|
|
%% We put all code inside a group to avoid affecting other table commands
|
|
\cs_new_protected:Npn \tblr_set_every_row:nn #1 #2
|
|
{
|
|
\group_begin:
|
|
\int_step_inline:nn { \c@rowcount }
|
|
{
|
|
\int_set:Nn \c@rownum {##1}
|
|
\tblr_set_row:nn {#1} {#2}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_every_row in different ways
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_every_row_aux:n #1
|
|
{
|
|
\tl_if_head_is_group:nTF {#1}
|
|
{ \tblr_set_every_row:nn #1 }
|
|
{ \tblr_set_every_row:nn {} {#1} }
|
|
}
|
|
|
|
%% \SetRow command for current row or each cells in the row
|
|
|
|
\NewTableCommand \SetRow [2] []
|
|
{
|
|
\tblr_set_row:nn {#1} {#2}
|
|
}
|
|
|
|
\cs_new_protected:Npn \tblr_set_row:nn #1 #2
|
|
{
|
|
\keys_set:nn { tblr-row } {#2}
|
|
}
|
|
|
|
\cs_new_protected:Npn \tblr_set_row:nnn #1 #2 #3
|
|
{
|
|
\group_begin:
|
|
\__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
|
|
\clist_map_inline:Nn \l_tblr_childs_clist
|
|
{
|
|
\int_set:Nn \c@rownum {##1}
|
|
\tblr_set_row:nn {#2} {#3}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% Check the number of arguments and call \tblr_set_row in different ways
|
|
%% Note that #1 always includes an outer pair of braces
|
|
%% This function is called when parsing table specifications
|
|
\cs_new_protected:Npn \__tblr_set_row_aux:nn #1 #2
|
|
{
|
|
\tl_if_head_is_group:nTF {#2}
|
|
{ \tblr_set_row:nnn #1 #2 }
|
|
{ \tblr_set_row:nnn #1 {} {#2} }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_row_aux:nn { Vn }
|
|
|
|
\keys_define:nn { tblr-row }
|
|
{
|
|
halign .code:n = \__tblr_row_gput_cell:nn { halign } {#1},
|
|
valign .code:n = \__tblr_row_gput_cell:nn { valign } {#1},
|
|
j .meta:n = { halign = j },
|
|
l .meta:n = { halign = l },
|
|
c .meta:n = { halign = c },
|
|
r .meta:n = { halign = r },
|
|
t .meta:n = { valign = t },
|
|
p .meta:n = { valign = t },
|
|
m .meta:n = { valign = m },
|
|
b .meta:n = { valign = b },
|
|
h .meta:n = { valign = h },
|
|
f .meta:n = { valign = f },
|
|
bg .code:n = \__tblr_row_gput_cell:nn { background } {#1},
|
|
fg .code:n = \__tblr_row_gput_cell:nn { foreground } {#1},
|
|
font .code:n = \__tblr_row_gput_cell:nn { font } { #1 \selectfont },
|
|
mode .code:n = \__tblr_row_gput_cell:nn { mode } {#1},
|
|
$ .meta:n = { mode = math },
|
|
$$ .meta:n = { mode = dmath },
|
|
cmd .code:n = \__tblr_row_gput_cell:nn { cmd } {#1},
|
|
ht .code:n = \__tblr_row_gput:ne { height } { \dim_eval:n {#1} },
|
|
co .code:n = \__tblr_row_gput:ne { coefficient } {#1},
|
|
preto .code:n = \__tblr_preto_text_for_every_row_cell:n {#1},
|
|
appto .code:n = \__tblr_appto_text_for_every_row_cell:n {#1},
|
|
abovesep .code:n = \__tblr_row_gput:ne { abovesep } { \dim_eval:n {#1} },
|
|
belowsep .code:n = \__tblr_row_gput:ne { belowsep } { \dim_eval:n {#1} },
|
|
rowsep .meta:n = { abovesep = #1, belowsep = #1},
|
|
abovesep+ .code:n = \__tblr_row_gadd_dimen:ne { abovesep } { \dim_eval:n {#1} },
|
|
belowsep+ .code:n = \__tblr_row_gadd_dimen:ne { belowsep } { \dim_eval:n {#1} },
|
|
rowsep+ .meta:n = { abovesep+ = #1, belowsep+ = #1},
|
|
baseline .code:n = \__tblr_outer_gput_spec:ne
|
|
{ baseline } { \int_use:N \c@rownum },
|
|
unknown .code:n = \__tblr_row_unknown_key:V \l_keys_key_str,
|
|
}
|
|
|
|
%% #1: key; #2: value
|
|
\cs_new_protected:Npn \__tblr_row_gput:nn #1 #2
|
|
{
|
|
\__tblr_data_gput:nenn { row } { \int_use:N \c@rownum } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_row_gput:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_row_gput_above:nn #1 #2
|
|
{
|
|
\__tblr_data_gput:nenn { row } { \int_eval:n { \c@rownum - 1 } } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_row_gput_above:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_row_gadd_dimen:nn #1 #2
|
|
{
|
|
\__tblr_data_gadd_dimen_value:nenn { row } { \int_use:N \c@rownum } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_row_gadd_dimen:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_row_gadd_dimen_above:nn #1 #2
|
|
{
|
|
\__tblr_data_gadd_dimen_value:nenn { row }
|
|
{ \int_eval:n { \c@rownum - 1 } } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_row_gadd_dimen_above:nn { ne }
|
|
|
|
%% #1: key; #2: value
|
|
\cs_new_protected:Npn \__tblr_row_gput_cell:nn #1 #2
|
|
{
|
|
\int_step_inline:nn { \c@colcount }
|
|
{
|
|
\__tblr_cell_gput:ennn { \int_use:N \c@rownum } {##1} {#1} {#2}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_row_gput_cell:nn { ne }
|
|
|
|
\cs_new_protected:Npn \__tblr_preto_text_for_every_row_cell:n #1
|
|
{
|
|
\int_step_inline:nn { \c@colcount }
|
|
{
|
|
\__tblr_cell_preto_text:enn { \int_use:N \c@rownum } {##1} {#1}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_appto_text_for_every_row_cell:n #1
|
|
{
|
|
\int_step_inline:nn { \c@colcount }
|
|
{
|
|
\__tblr_cell_appto_text:enn { \int_use:N \c@rownum } {##1} {#1}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_row_unknown_key:n #1
|
|
{
|
|
\regex_match:NnTF \c__tblr_is_number_key_regex {#1}
|
|
{
|
|
\__tblr_data_gput:nene { row } { \int_use:N \c@rownum }
|
|
{ coefficient } {#1}
|
|
}
|
|
{
|
|
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
|
|
{ \__tblr_row_gput_cell:nn { background } {#1} }
|
|
{
|
|
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
|
|
\__tblr_row_gput:ne { height } { \dim_eval:n { \l__tblr_v_tl } }
|
|
}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_row_unknown_key:n { V }
|
|
|
|
\NewTableCommand \pagebreak [1] [4]
|
|
{
|
|
\hborder { pagebreak = yes }
|
|
}
|
|
|
|
\NewTableCommand \nopagebreak [1] [4]
|
|
{
|
|
\hborder { pagebreak = no }
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Column Types and Row Types}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% Some primitive column/row types
|
|
|
|
\str_const:Nn \c_tblr_primitive_colrow_types_str { Q | < > }
|
|
\tl_new:N \g__tblr_expanded_colrow_spec_tl
|
|
|
|
\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ Q } { O{} }
|
|
{
|
|
\keys_set:nn { tblr-column } { #1 }
|
|
\int_incr:N \c@colnum
|
|
\__tblr_execute_colrow_spec_next:N
|
|
}
|
|
\exp_args:Nc \NewDocumentCommand { tblr_column_type_ Q } { O{} }
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { Q[#1] }
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
|
|
\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ Q } { O{} }
|
|
{
|
|
\keys_set:nn { tblr-row } { #1 }
|
|
\int_incr:N \c@rownum
|
|
\__tblr_execute_colrow_spec_next:N
|
|
}
|
|
\exp_args:Nc \NewDocumentCommand { tblr_row_type_ Q } { O{} }
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { Q[#1] }
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
|
|
\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ | } { O{} }
|
|
{
|
|
\vline [#1]
|
|
\__tblr_execute_colrow_spec_next:N
|
|
}
|
|
\exp_args:Nc \NewDocumentCommand { tblr_column_type_ | } { O{} }
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { |[#1] }
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
|
|
\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ | } { O{} }
|
|
{
|
|
\hline [#1]
|
|
\__tblr_execute_colrow_spec_next:N
|
|
}
|
|
\exp_args:Nc \NewDocumentCommand { tblr_row_type_ | } { O{} }
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { |[#1] }
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
|
|
\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ > } { O{} m }
|
|
{
|
|
\tl_if_blank:nF {#1}
|
|
{
|
|
\__tblr_data_gput:nene
|
|
{ column }
|
|
{ \int_use:N \c@colnum } { leftsep }
|
|
{ \dim_eval:n {#1} }
|
|
}
|
|
\tl_if_blank:nF {#2}
|
|
{
|
|
\__tblr_preto_text_for_every_column_cell:n {#2}
|
|
}
|
|
\__tblr_execute_colrow_spec_next:N
|
|
}
|
|
\exp_args:Nc \NewDocumentCommand { tblr_column_type_ > } { O{} m }
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { >[#1]{#2} }
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
|
|
\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ > } { O{} m }
|
|
{
|
|
\tl_if_blank:nF {#1}
|
|
{
|
|
\__tblr_data_gput:nene { row } { \int_use:N \c@rownum }
|
|
{ abovesep } { \dim_eval:n { #1 } }
|
|
}
|
|
\tl_if_blank:nF {#2}
|
|
{
|
|
\__tblr_preto_text_for_every_row_cell:n {#2}
|
|
}
|
|
\__tblr_execute_colrow_spec_next:N
|
|
}
|
|
\exp_args:Nc \NewDocumentCommand { tblr_row_type_ > } { O{} m }
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { >[#1]{#2} }
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
|
|
\exp_args:Nc \NewDocumentCommand { tblr_primitive_column_type_ < } { O{} m }
|
|
{
|
|
\tl_if_blank:nF {#1}
|
|
{
|
|
\__tblr_data_gput:nene { column }
|
|
{ \int_eval:n {\c@colnum - 1} } { rightsep } { \dim_eval:n {#1} }
|
|
}
|
|
\tl_if_blank:nF {#2}
|
|
{
|
|
\group_begin:
|
|
\int_decr:N \c@colnum
|
|
\__tblr_appto_text_for_every_column_cell:n {#2}
|
|
\group_end:
|
|
}
|
|
\__tblr_execute_colrow_spec_next:N
|
|
}
|
|
\exp_args:Nc \NewDocumentCommand { tblr_column_type_ < } { O{} m }
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { <[#1]{#2} }
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
|
|
\exp_args:Nc \NewDocumentCommand { tblr_primitive_row_type_ < } { O{} m }
|
|
{
|
|
\tl_if_blank:nF {#1}
|
|
{
|
|
\__tblr_data_gput:nene { row } { \int_eval:n {\c@rownum - 1} }
|
|
{ belowsep } { \dim_eval:n {#1} }
|
|
}
|
|
\tl_if_blank:nF {#2}
|
|
{
|
|
\group_begin:
|
|
\int_decr:N \c@rownum
|
|
\__tblr_appto_text_for_every_row_cell:n {#2}
|
|
\group_end:
|
|
}
|
|
\__tblr_execute_colrow_spec_next:N
|
|
}
|
|
\exp_args:Nc \NewDocumentCommand { tblr_row_type_ < } { O{} m }
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_expanded_colrow_spec_tl { <[#1]{#2} }
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
|
|
%% \NewColumnType/\NewRowType command and predefined column/row types
|
|
|
|
\str_new:N \g_tblr_used_column_types_str
|
|
\str_gset_eq:NN \g_tblr_used_column_types_str \c_tblr_primitive_colrow_types_str
|
|
|
|
\str_new:N \g_tblr_used_row_types_str
|
|
\str_gset_eq:NN \g_tblr_used_row_types_str \c_tblr_primitive_colrow_types_str
|
|
|
|
\bool_new:N \g__tblr_colrow_spec_expand_stop_bool
|
|
\tl_new:N \g__tblr_column_or_row_tl
|
|
|
|
\msg_new:nnn { tabularray } { used-colrow-type }
|
|
{ #1 ~ type ~ name ~ #2 ~ has ~ been ~ used! }
|
|
|
|
\NewDocumentCommand \NewColumnType { m O{0} o m }
|
|
{
|
|
\tl_set:Nn \g__tblr_column_or_row_tl { column }
|
|
\__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4}
|
|
}
|
|
|
|
\NewDocumentCommand \NewRowType { m O{0} o m }
|
|
{
|
|
\tl_set:Nn \g__tblr_column_or_row_tl { row }
|
|
\__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4}
|
|
}
|
|
|
|
\NewDocumentCommand \NewColumnRowType { m O{0} o m }
|
|
{
|
|
\tl_set:Nn \g__tblr_column_or_row_tl { column }
|
|
\__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4}
|
|
\tl_set:Nn \g__tblr_column_or_row_tl { row }
|
|
\__tblr_new_column_or_row_type:nnnn {#1} {#2} {#3} {#4}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_new_column_or_row_type:nnnn #1 #2 #3 #4
|
|
{
|
|
\str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
|
|
{
|
|
\tl_if_eq:NnTF \g__tblr_column_or_row_tl { row }
|
|
{ \msg_error:nnnn { tabularray } { used-colrow-type } { Row } {#1} }
|
|
{ \msg_error:nnnn { tabularray } { used-colrow-type } { Column } {#1} }
|
|
\str_log:c { g_tblr_used_ \g__tblr_column_or_row_tl _types_str }
|
|
}
|
|
{
|
|
\__tblr_make_xparse_arg_spec:nnN {#2} {#3} \l__tblr_a_tl
|
|
\exp_args:NcV \NewDocumentCommand
|
|
{ tblr_ \g__tblr_column_or_row_tl _type_ #1 } \l__tblr_a_tl
|
|
{
|
|
\bool_gset_false:N \g__tblr_colrow_spec_expand_stop_bool
|
|
\tl_gput_right:Nf \g__tblr_expanded_colrow_spec_tl {#4}
|
|
\__tblr_expand_colrow_spec_next:N
|
|
}
|
|
\str_gput_right:cn
|
|
{ g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
|
|
}
|
|
}
|
|
|
|
\NewColumnRowType { l } { Q[l] }
|
|
\NewColumnRowType { c } { Q[c] }
|
|
\NewColumnRowType { r } { Q[r] }
|
|
\NewColumnRowType { j } { Q[j] }
|
|
|
|
\NewColumnType { t } [1] { Q[t,wd=#1] }
|
|
\NewColumnType { p } [1] { Q[p,wd=#1] }
|
|
\NewColumnType { m } [1] { Q[m,wd=#1] }
|
|
\NewColumnType { b } [1] { Q[b,wd=#1] }
|
|
\NewColumnType { h } [1] { Q[h,wd=#1] }
|
|
\NewColumnType { f } [1] { Q[f,wd=#1] }
|
|
|
|
\NewRowType { t } [1] { Q[t,ht=#1] }
|
|
\NewRowType { p } [1] { Q[p,ht=#1] }
|
|
\NewRowType { m } [1] { Q[m,ht=#1] }
|
|
\NewRowType { b } [1] { Q[b,ht=#1] }
|
|
\NewRowType { h } [1] { Q[h,ht=#1] }
|
|
\NewRowType { f } [1] { Q[f,ht=#1] }
|
|
|
|
\NewColumnRowType { X } [1][] { Q[co=1,#1] }
|
|
|
|
\NewColumnRowType { ! } [1] { |[text={#1}] }
|
|
\NewColumnRowType { @ } [1] { <[0pt]{} |[text={#1}] >[0pt]{} }
|
|
\NewColumnRowType { * } [2] { \prg_replicate:nn {#1} {#2} }
|
|
|
|
\cs_new_protected:Npn \__tblr_parse_colrow_spec:nn #1 #2
|
|
{
|
|
\tl_gset:Nn \g__tblr_column_or_row_tl {#1}
|
|
\tl_gset:Nn \g__tblr_expanded_colrow_spec_tl {#2}
|
|
\__tblr_expand_colrow_spec:N \g__tblr_expanded_colrow_spec_tl
|
|
\__tblr_execute_colrow_spec:N \g__tblr_expanded_colrow_spec_tl
|
|
}
|
|
|
|
%% Expand defined column/row types
|
|
|
|
\cs_new_protected:Npn \__tblr_expand_colrow_spec:N #1
|
|
{
|
|
\bool_do_until:Nn \g__tblr_colrow_spec_expand_stop_bool
|
|
{
|
|
\LogTblrTracing { colspec, rowspec }
|
|
\bool_gset_true:N \g__tblr_colrow_spec_expand_stop_bool
|
|
\tl_set_eq:NN \l_tmpa_tl #1
|
|
\tl_gclear:N #1
|
|
\exp_last_unbraced:NV
|
|
\__tblr_expand_colrow_spec_next:N \l_tmpa_tl \scan_stop:
|
|
}
|
|
}
|
|
|
|
\msg_new:nnn { tabularray } { unexpandable-colrow-type }
|
|
{ Unexpandable ~ command ~ #2 inside ~ #1 ~ type! }
|
|
|
|
\msg_new:nnn { tabularray } { unknown-colrow-type }
|
|
{ Unknown ~ #1 ~ type ~ #2! }
|
|
|
|
\cs_new_protected:Npn \__tblr_expand_colrow_spec_next:N #1
|
|
{
|
|
\token_if_eq_catcode:NNTF #1 \scan_stop:
|
|
{
|
|
\token_if_eq_meaning:NNF #1 \scan_stop:
|
|
{
|
|
\msg_error:nnVn { tabularray } { unexpandable-colrow-type }
|
|
\g__tblr_column_or_row_tl {#1}
|
|
}
|
|
}
|
|
{
|
|
\str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
|
|
{
|
|
%% Note that #1 may be an active character (see issue #58)
|
|
\cs:w tblr_ \g__tblr_column_or_row_tl _type_ \token_to_str:N #1 \cs_end:
|
|
}
|
|
{
|
|
\msg_error:nnVn { tabularray } { unknown-colrow-type }
|
|
\g__tblr_column_or_row_tl {#1}
|
|
\str_log:c { g_tblr_used_ \g__tblr_column_or_row_tl _types_str }
|
|
}
|
|
}
|
|
}
|
|
|
|
%% Execute primitive column/row types
|
|
|
|
\cs_new_protected:Npn \__tblr_execute_colrow_spec:N #1
|
|
{
|
|
\tl_if_eq:NnTF \g__tblr_column_or_row_tl { row }
|
|
{ \int_set:Nn \c@rownum {1} }
|
|
{ \int_set:Nn \c@colnum {1} }
|
|
\exp_last_unbraced:NV \__tblr_execute_colrow_spec_next:N #1 \scan_stop:
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_execute_colrow_spec_next:N #1
|
|
{
|
|
\token_if_eq_meaning:NNF #1 \scan_stop:
|
|
{ \cs:w tblr_primitive_ \g__tblr_column_or_row_tl _type_ #1 \cs_end: }
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Set Environments and New Environments}
|
|
%%% --------------------------------------------------------
|
|
|
|
\tl_new:N \l__tblr_initial_tblr_outer_tl
|
|
\tl_set:Nn \l__tblr_initial_tblr_outer_tl
|
|
{
|
|
halign = c, baseline = m, headsep = 6pt, footsep = 6pt,
|
|
presep = 1.5\bigskipamount, postsep = 1.5\bigskipamount,
|
|
}
|
|
|
|
%% #1: env name; #2: specifications
|
|
\NewDocumentCommand \SetTblrInner { O{tblr} m }
|
|
{
|
|
\clist_map_inline:nn {#1}
|
|
{ \tl_put_right:cn { l__tblr_default_ ##1 _inner_tl } { , #2 } }
|
|
\ignorespaces
|
|
}
|
|
\cs_new_eq:NN \SetTblrDefault \SetTblrInner
|
|
|
|
%% #1: env name; #2: specifications
|
|
\NewDocumentCommand \SetTblrOuter { O{tblr} m }
|
|
{
|
|
\clist_map_inline:nn {#1}
|
|
{ \tl_put_right:cn { l__tblr_default_ ##1 _outer_tl } { , #2 } }
|
|
\ignorespaces
|
|
}
|
|
|
|
%% #1: env name
|
|
\NewDocumentCommand \NewTblrEnviron { m }
|
|
{
|
|
\NewDocumentEnvironment {#1} { O{c} m +b }
|
|
{
|
|
\__tblr_environ_code:nnnn {#1} {##1} {##2} {##3}
|
|
} { }
|
|
\tl_new:c { l__tblr_default_ #1 _inner_tl }
|
|
\tl_new:c { l__tblr_default_ #1 _outer_tl }
|
|
\tl_set_eq:cN { l__tblr_default_ #1 _outer_tl } \l__tblr_initial_tblr_outer_tl
|
|
}
|
|
|
|
%% Create tblr and longtblr environments
|
|
\NewTblrEnviron { tblr }
|
|
\NewTblrEnviron { longtblr }
|
|
\SetTblrOuter [ longtblr ] { long }
|
|
\NewTblrEnviron { talltblr }
|
|
\SetTblrOuter [ talltblr ] { tall }
|
|
|
|
\tl_new:N \l__tblr_env_name_tl
|
|
\bool_new:N \l__tblr_math_mode_bool
|
|
|
|
%% Main environment code
|
|
%% We need to add \group_align_safe_begin: and \group_align_safe_end:
|
|
%% to make tabularray correctly nest in align environment (see issue #143)
|
|
\cs_new_protected:Npn \__tblr_environ_code:nnnn #1 #2 #3 #4
|
|
{
|
|
\group_align_safe_begin:
|
|
\int_gincr:N \g__tblr_table_count_int
|
|
\tl_set:Nn \l__tblr_env_name_tl {#1}
|
|
\mode_if_math:TF
|
|
{ \bool_set_true:N \l__tblr_math_mode_bool }
|
|
{ \bool_set_false:N \l__tblr_math_mode_bool }
|
|
\__tblr_builder:nnn {#2} {#3} {#4}
|
|
\group_align_safe_end:
|
|
}
|
|
|
|
\bool_new:N \lTblrMeasuringBool
|
|
|
|
%% Read, split and build the table
|
|
\cs_new_protected:Npn \__tblr_builder:nnn #1 #2 #3
|
|
{
|
|
\int_gincr:N \g_tblr_level_int
|
|
\bool_set_true:N \lTblrMeasuringBool
|
|
\__tblr_clear_prop_lists:
|
|
\__tblr_clear_spec_lists:
|
|
\LogTblrTracing { step = init ~ table ~ outer ~ spec}
|
|
\__tblr_init_table_outer_spec:
|
|
\LogTblrTracing { step = parse ~ table ~ options }
|
|
\__tblr_parse_table_option:n {#1}
|
|
\LogTblrTracing { outer }
|
|
\LogTblrTracing { option }
|
|
\__tblr_enable_table_commands:
|
|
\LogTblrTracing { step = split ~ table}
|
|
\__tblr_split_table:n {#3}
|
|
\LogTblrTracing { command }
|
|
\bool_if:NT \g__tblr_use_intarray_bool { \__tblr_init_table_data: }
|
|
\LogTblrTracing { step = init ~ table ~ inner ~ spec}
|
|
\__tblr_init_table_inner_spec:
|
|
\LogTblrTracing { inner }
|
|
\LogTblrTracing { step = parse ~ table ~ inner ~ spec}
|
|
\__tblr_parse_table_spec:n {#2}
|
|
\LogTblrTracing { step = execute ~ table ~ commands}
|
|
\__tblr_execute_table_commands:
|
|
\__tblr_disable_table_commands:
|
|
\__tblr_functional_calculation:
|
|
\LogTblrTracing { step = calculate ~ cell ~ and ~ line ~ sizes}
|
|
\__tblr_enable_content_commands:
|
|
\__tblr_calc_cell_and_line_sizes:
|
|
\bool_set_false:N \lTblrMeasuringBool
|
|
\LogTblrTracing { step = build ~ the ~ whole ~ table}
|
|
\__tblr_build_whole:
|
|
\int_gdecr:N \g_tblr_level_int
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Split Table Contents}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% Insert and remove braces for nesting environments inside cells
|
|
%% These make line split and cell split workable
|
|
%% We need to replace N times for N level nestings
|
|
\regex_const:Nn \c__tblr_insert_braces_regex
|
|
{
|
|
\c{begin} \cB\{ (\c[^BE].*) \cE\} (.*?) \c{end} \cB\{ (\c[^BE].*) \cE\}
|
|
}
|
|
\tl_const:Nn \c__tblr_insert_braces_tl
|
|
{
|
|
\c{begin} \cB\{ \cB\{ \1 \cE\} \2 \c{end} \cE\} \cB\{ \3 \cE\}
|
|
}
|
|
\regex_const:Nn \c__tblr_remove_braces_regex
|
|
{
|
|
\c{begin} \cB\{ \cB\{ (.*?) \c{end} \cE\}
|
|
}
|
|
\tl_const:Nn \c__tblr_remove_braces_tl
|
|
{
|
|
\c{begin} \cB\{ \1 \c{end}
|
|
}
|
|
\cs_new_protected:Npn \__tblr_insert_braces:N #1
|
|
{
|
|
\regex_replace_all:NVN \c__tblr_insert_braces_regex \c__tblr_insert_braces_tl #1
|
|
\regex_replace_all:NVN \c__tblr_insert_braces_regex \c__tblr_insert_braces_tl #1
|
|
}
|
|
\cs_new_protected:Npn \__tblr_remove_braces:N #1
|
|
{
|
|
\regex_replace_all:NVN \c__tblr_remove_braces_regex \c__tblr_remove_braces_tl #1
|
|
\regex_replace_all:NVN \c__tblr_remove_braces_regex \c__tblr_remove_braces_tl #1
|
|
}
|
|
|
|
\tl_new:N \l__tblr_body_tl
|
|
\seq_new:N \l__tblr_lines_seq
|
|
|
|
%% Split table content to cells and store them
|
|
%% #1: table content
|
|
\cs_new_protected:Npn \__tblr_split_table:n #1
|
|
{
|
|
\tl_set:Nn \l__tblr_body_tl {#1}
|
|
\tblr_modify_table_body:
|
|
\int_zero:N \c@rowcount
|
|
\int_zero:N \c@colcount
|
|
\__tblr_split_table_to_lines:NN \l__tblr_body_tl \l__tblr_lines_seq
|
|
\__tblr_split_lines_to_cells:N \l__tblr_lines_seq
|
|
}
|
|
|
|
\tl_new:N \l__tblr_expand_tl
|
|
|
|
\cs_set_eq:NN \__tblr_hook_split_before: \prg_do_nothing:
|
|
|
|
\cs_new_protected:Npn \tblr_modify_table_body:
|
|
{
|
|
\__tblr_hook_split_before:
|
|
\tl_set:Nx \l__tblr_expand_tl { \__tblr_spec_item:nn { outer } { expand } }
|
|
\tl_set:Nx \l__tblr_expand_tl { \tl_head:N \l__tblr_expand_tl }
|
|
\tl_if_empty:NF \l__tblr_expand_tl
|
|
{
|
|
\exp_last_unbraced:NNV
|
|
\__tblr_expand_table_body:NN \l__tblr_body_tl \l__tblr_expand_tl
|
|
}
|
|
}
|
|
|
|
%% Expand every occurrence of the specified macro once
|
|
%% #1: tl with table content; #2: macro to be expanded
|
|
\cs_new_protected:Npn \__tblr_expand_table_body:NN #1 #2
|
|
{
|
|
\tl_set_eq:NN \l_tmpa_tl #1
|
|
\tl_clear:N #1
|
|
\cs_set_protected:Npn \__tblr_expand_table_body_aux:w ##1 #2
|
|
{
|
|
\tl_put_right:Nn #1 {##1}
|
|
\peek_meaning:NTF \q_stop
|
|
{ \use_none:n }
|
|
{ \exp_last_unbraced:NV \__tblr_expand_table_body_aux:w #2 }
|
|
}
|
|
\exp_last_unbraced:NV \__tblr_expand_table_body_aux:w \l_tmpa_tl #2 \q_stop
|
|
}
|
|
|
|
%% Split table content to a sequence of lines
|
|
%% #1: tl with table contents, #2: resulting sequence of lines
|
|
\cs_new_protected:Npn \__tblr_split_table_to_lines:NN #1 #2
|
|
{
|
|
\__tblr_insert_braces:N #1
|
|
\seq_set_split:NnV \l_tmpa_seq { \\ } #1
|
|
\seq_clear:N #2
|
|
\seq_map_inline:Nn \l_tmpa_seq
|
|
{
|
|
\tl_if_head_eq_meaning:nNTF {##1} *
|
|
{
|
|
\tl_set:Nn \l__tblr_b_tl { \hborder { pagebreak = no } }
|
|
\tl_set:Nx \l__tblr_c_tl { \tl_tail:n {##1} }
|
|
\tl_trim_spaces:N \l__tblr_c_tl %% Ignore spaces between * and [dimen]
|
|
\tl_if_head_eq_meaning:VNT \l__tblr_c_tl [
|
|
{
|
|
\tl_put_right:Nn \l__tblr_b_tl { \RowBefore@AddBelowSep }
|
|
}
|
|
\tl_put_right:NV \l__tblr_b_tl \l__tblr_c_tl
|
|
\seq_put_right:NV #2 \l__tblr_b_tl
|
|
}
|
|
{
|
|
\tl_if_head_eq_meaning:nNTF { ##1 } [
|
|
{ \seq_put_right:Nn #2 { \RowBefore@AddBelowSep ##1 } }
|
|
{ \seq_put_right:Nn #2 { ##1 } }
|
|
}
|
|
}
|
|
\int_set:Nn \c@rowcount { \seq_count:N #2 }
|
|
}
|
|
|
|
%% Treat \\[dimen] command
|
|
\NewTableCommand \RowBefore@AddBelowSep [1] []
|
|
{
|
|
\IfValueT { #1 }
|
|
{
|
|
\__tblr_data_gadd_dimen_value:nene { row }
|
|
{ \int_eval:n {\c@rownum - 1} } { belowsep } {#1}
|
|
}
|
|
}
|
|
|
|
%% Split table lines to cells and store them
|
|
%% #1: sequence of lines
|
|
\cs_new_protected:Npn \__tblr_split_lines_to_cells:N #1
|
|
{
|
|
\seq_map_indexed_function:NN #1 \__tblr_split_one_line:nn
|
|
\LogTblrTracing { text }
|
|
}
|
|
|
|
%% Split one line into cells and store them
|
|
%% #1: row number, #2 the line text
|
|
\cs_new_protected:Npn \__tblr_split_one_line:nn #1 #2
|
|
{
|
|
\seq_set_split:Nnn \l_tmpa_seq { & } { #2 }
|
|
\int_set:Nn \c@rownum {#1}
|
|
\int_zero:N \c@colnum
|
|
\seq_map_inline:Nn \l_tmpa_seq
|
|
{
|
|
\tl_set:Nn \l_tmpa_tl { ##1 }
|
|
\__tblr_remove_braces:N \l_tmpa_tl
|
|
\__tblr_trim_par_space_tokens:N \l_tmpa_tl
|
|
\int_incr:N \c@colnum
|
|
\__tblr_extract_table_commands:N \l_tmpa_tl
|
|
\__tblr_trim_par_space_tokens:N \l_tmpa_tl
|
|
\__tblr_spec_gput:neV { text } { [#1][\int_use:N \c@colnum] } \l_tmpa_tl
|
|
}
|
|
%% Decrease row count by 1 if the last row has only one empty cell text
|
|
%% We need to do it here since the > or < column type may add text to cells
|
|
\bool_lazy_all:nTF
|
|
{
|
|
{ \int_compare_p:nNn {#1} = {\c@rowcount} }
|
|
{ \int_compare_p:nNn {\c@colnum} = {1} }
|
|
{ \tl_if_empty_p:N \l_tmpa_tl }
|
|
}
|
|
{ \int_decr:N \c@rowcount }
|
|
{
|
|
\__tblr_prop_gput:nnx
|
|
{row} { [#1] / cell-number } { \int_use:N \c@colnum }
|
|
\int_compare:nT { \c@colnum > \c@colcount }
|
|
{
|
|
\int_set_eq:NN \c@colcount \c@colnum
|
|
}
|
|
}
|
|
}
|
|
|
|
\regex_const:Nn \c__tblr_trim_left_par_space_regex { ^ \c{par} ? \s * }
|
|
\regex_const:Nn \c__tblr_trim_right_space_par_regex { \s * \c{par} ? $ }
|
|
|
|
\cs_new_protected:Npn \__tblr_trim_par_space_tokens:N #1
|
|
{
|
|
\regex_replace_once:NnN \c__tblr_trim_left_par_space_regex {} #1
|
|
\regex_replace_once:NnN \c__tblr_trim_right_space_par_regex {} #1
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Extract Table Commands from Cell Text}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% Extract table commands defined with \NewTableCommand from cell text
|
|
|
|
\tl_new:N \l__tblr_saved_table_commands_before_cell_text_tl
|
|
\tl_new:N \l__tblr_saved_cell_text_after_table_commands_tl
|
|
|
|
\cs_new_protected:Npn \__tblr_extract_table_commands:N #1
|
|
{
|
|
\tl_clear:N \l__tblr_saved_table_commands_before_cell_text_tl
|
|
\tl_clear:N \l__tblr_saved_cell_text_after_table_commands_tl
|
|
\exp_last_unbraced:NV \__tblr_extract_table_commands_next:n #1 \q_stop
|
|
\tl_if_empty:NF \l__tblr_saved_table_commands_before_cell_text_tl
|
|
{
|
|
\__tblr_prop_gput:nxV { command }
|
|
{[\int_use:N \c@rownum][\int_use:N \c@colnum]}
|
|
\l__tblr_saved_table_commands_before_cell_text_tl
|
|
}
|
|
\tl_set_eq:NN #1 \l__tblr_saved_cell_text_after_table_commands_tl
|
|
}
|
|
|
|
%% #1 maybe a single token or multiple tokens from a pair of braces
|
|
\cs_new_protected:Npn \__tblr_extract_table_commands_next:n #1
|
|
{
|
|
\tl_if_single_token:nTF {#1}
|
|
{
|
|
\clist_if_in:NnTF \g__tblr_table_commands_clist { #1 }
|
|
{ \__tblr_extract_one_table_command:N #1 }
|
|
{
|
|
\token_if_eq_meaning:NNF #1 \q_stop
|
|
{ \__tblr_save_real_cell_text:w #1 }
|
|
}
|
|
}
|
|
{ \__tblr_save_real_cell_text:w {#1} }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_extract_one_table_command:N #1
|
|
{
|
|
\int_set:Nn \l__tblr_a_int
|
|
{ \cs:w g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl \cs_end: }
|
|
\tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl {#1}
|
|
\int_compare:nNnTF {\l__tblr_a_int} < {0}
|
|
{
|
|
\int_set:Nn \l__tblr_a_int { \int_abs:n {\l__tblr_a_int} - 1 }
|
|
\peek_charcode:NTF [
|
|
{ \__tblr_extract_table_command_arg_o:w }
|
|
{ \__tblr_extract_table_command_arg_next: }
|
|
}
|
|
{ \__tblr_extract_table_command_arg_next: }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_extract_table_command_arg_o:w [#1]
|
|
{
|
|
\tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl { [#1] }
|
|
\__tblr_extract_table_command_arg_next:
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_extract_table_command_arg_m:n #1
|
|
{
|
|
\tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl { {#1} }
|
|
\__tblr_extract_table_command_arg_next:
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_extract_table_command_arg_next:
|
|
{
|
|
\int_compare:nNnTF {\l__tblr_a_int} > {0}
|
|
{
|
|
\int_decr:N \l__tblr_a_int
|
|
\__tblr_extract_table_command_arg_m:n
|
|
}
|
|
{ \__tblr_extract_table_commands_next:n }
|
|
}
|
|
|
|
%% The outermost set of braces of cell text #1 will be removed
|
|
\cs_new_protected:Npn \__tblr_save_real_cell_text:w #1 \q_stop
|
|
{
|
|
\tl_set:Nn \l__tblr_saved_cell_text_after_table_commands_tl {#1}
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Initialize Table Inner Specifications}
|
|
%%% --------------------------------------------------------
|
|
|
|
\prop_gset_from_keyval:Nn \g__tblr_initial_table_prop
|
|
{
|
|
stretch = 1,
|
|
rulesep = 2pt,
|
|
}
|
|
|
|
\prop_gset_from_keyval:Nn \g__tblr_initial_rows_prop
|
|
{
|
|
abovesep = 2pt,
|
|
belowsep = 2pt,
|
|
@row-height = 0pt,
|
|
@row-head = 0pt,
|
|
@row-foot = 0pt,
|
|
@row-upper = 0pt,
|
|
@row-lower = 0pt,
|
|
}
|
|
|
|
\prop_gset_from_keyval:Nn \g__tblr_initial_columns_prop
|
|
{
|
|
leftsep = 6pt,
|
|
rightsep = 6pt,
|
|
width = -1pt, % column width unset
|
|
coefficient = 0, % column coefficient unset
|
|
@col-width = 0pt,
|
|
}
|
|
|
|
\prop_gset_from_keyval:Nn \g__tblr_initial_cells_prop
|
|
{
|
|
halign = j,
|
|
valign = t,
|
|
width = -1pt, % cell width unset
|
|
rowspan = 1,
|
|
colspan = 1,
|
|
omit = 0,
|
|
}
|
|
|
|
\prop_gset_from_keyval:Nn \g__tblr_initial_hlines_prop
|
|
{
|
|
@hline-count = 0,
|
|
}
|
|
|
|
\prop_gset_from_keyval:Nn \g__tblr_initial_vlines_prop
|
|
{
|
|
@vline-count = 0,
|
|
}
|
|
|
|
\tl_new:N \l__tblr_inner_spec_measure_tl
|
|
\tl_new:N \l__tblr_inner_spec_verb_tl
|
|
|
|
\cs_new_protected:Npn \__tblr_init_table_inner_spec:
|
|
{
|
|
\prop_map_inline:Nn \g__tblr_initial_table_prop
|
|
{
|
|
\__tblr_prop_gput:nxn { inner } { ##1 } {##2}
|
|
}
|
|
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
|
|
{
|
|
\prop_map_inline:Nn \g__tblr_initial_rows_prop
|
|
{
|
|
\__tblr_data_gput:nVnn { row } \l__tblr_i_tl {##1} {##2}
|
|
}
|
|
\prop_map_inline:Nn \g__tblr_initial_hlines_prop
|
|
{
|
|
\__tblr_spec_gput:nen { hline } { [\l__tblr_i_tl] / ##1 } {##2}
|
|
}
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\prop_map_inline:Nn \g__tblr_initial_cells_prop
|
|
{
|
|
\__tblr_data_gput:neeen { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } {##1} {##2}
|
|
}
|
|
}
|
|
}
|
|
\prop_map_inline:Nn \g__tblr_initial_hlines_prop
|
|
{
|
|
\__tblr_spec_gput:nen { hline }
|
|
{ [\int_eval:n { \c@rowcount + 1}] / ##1 } {##2}
|
|
}
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\prop_map_inline:Nn \g__tblr_initial_columns_prop
|
|
{
|
|
\__tblr_data_gput:nenn { column } { \l__tblr_j_tl } {##1} {##2}
|
|
}
|
|
\prop_map_inline:Nn \g__tblr_initial_vlines_prop
|
|
{
|
|
\__tblr_spec_gput:nen { vline } { [\l__tblr_j_tl] / ##1 } {##2}
|
|
}
|
|
}
|
|
\prop_map_inline:Nn \g__tblr_initial_vlines_prop
|
|
{
|
|
\__tblr_spec_gput:nen { vline }
|
|
{ [\int_eval:n { \c@colcount + 1}] / ##1 } {##2}
|
|
}
|
|
\tl_clear:N \l__tblr_inner_spec_measure_tl
|
|
\tl_clear:N \l__tblr_inner_spec_verb_tl
|
|
\keys_set:nv { tblr } { l__tblr_default_ \l__tblr_env_name_tl _inner_tl }
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Parse Table Inner Specifications}
|
|
%%% --------------------------------------------------------
|
|
|
|
\clist_new:N \g__tblr_table_known_keys_clist
|
|
\clist_gset:Nn \g__tblr_table_known_keys_clist
|
|
{
|
|
colspec, rowspec, column, row, cell, hline, vline, hborder, vborder, width,
|
|
rowhead, rowfoot, columns, rows, cells, hlines, vlines, % hborders, vborders,
|
|
leftsep, rightsep, colsep, abovesep, belowsep, rowsep, rulesep,
|
|
baseline, hspan, vspan, stretch, verb, delimiter
|
|
}
|
|
|
|
\keys_define:nn { tblr }
|
|
{
|
|
colspec .code:n = \__tblr_parse_colrow_spec:nn { column } {#1},
|
|
rowspec .code:n = \__tblr_parse_colrow_spec:nn { row } {#1},
|
|
width .code:n = \__tblr_keys_gput:nx { width } { \dim_eval:n {#1} },
|
|
hspan .code:n = \__tblr_keys_gput:nn { hspan } {#1},
|
|
vspan .code:n = \__tblr_keys_gput:nn { vspan } {#1},
|
|
stretch .code:n = \__tblr_keys_gput:nn { stretch } {#1},
|
|
verb .tl_set:N = \l__tblr_inner_spec_verb_tl,
|
|
verb .default:n = lite,
|
|
columns .code:n = \__tblr_set_every_column_aux:n {#1},
|
|
rows .code:n = \__tblr_set_every_row_aux:n {#1},
|
|
cells .code:n = \__tblr_set_every_cell_aux:n {#1},
|
|
hlines .code:n = \__tblr_set_every_hline_aux:n {#1},
|
|
vlines .code:n = \__tblr_set_every_vline_aux:n {#1},
|
|
leftsep .code:n = \tblr_set_every_column:nn { } { leftsep = #1 },
|
|
rightsep .code:n = \tblr_set_every_column:nn { } { rightsep = #1 },
|
|
colsep .meta:n = { leftsep = #1, rightsep = #1 },
|
|
abovesep .code:n = \tblr_set_every_row:nn { } { abovesep = #1 },
|
|
belowsep .code:n = \tblr_set_every_row:nn { } { belowsep = #1 },
|
|
rowsep .meta:n = { abovesep = #1, belowsep = #1 },
|
|
rulesep .code:n = \__tblr_keys_gput:nn { rulesep } {#1},
|
|
rowhead .code:n = \__tblr_keys_gput:nn { rowhead } {#1},
|
|
rowfoot .code:n = \__tblr_keys_gput:nn { rowfoot } {#1},
|
|
delimiter .code:n = \__tblr_set_delimiter:n {#1},
|
|
baseline .code:n = \__tblr_outer_gput_spec:nn { baseline } {#1},
|
|
unknown .code:n = \__tblr_table_special_key:Vn \l_keys_key_str {#1},
|
|
}
|
|
|
|
\regex_const:Nn \c__tblr_split_key_name_regex { ^ ( [a-z] + ) ( . * ) }
|
|
|
|
\cs_new_protected:Npn \__tblr_table_special_key:nn #1 #2
|
|
{
|
|
\regex_extract_once:NnNT \c__tblr_split_key_name_regex {#1} \l_tmpa_seq
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {2} }
|
|
\tl_set_rescan:Nnx \l__tblr_b_tl {} { \seq_item:Nn \l_tmpa_seq {3} }
|
|
\cs:w __tblr_set_ \l__tblr_a_tl _aux:Vn \cs_end: \l__tblr_b_tl {#2}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_table_special_key:nn { Vn }
|
|
|
|
%% If the first key name is known, treat #1 is the table spec;
|
|
%% otherwise, treat #1 as colspec.
|
|
|
|
\regex_const:Nn \c__tblr_first_key_name_regex { ^ \s * ( [A-Za-z\-] + ) }
|
|
|
|
\cs_new_protected:Npn \__tblr_parse_table_spec:n #1
|
|
{
|
|
\regex_extract_once:NnNTF \c__tblr_first_key_name_regex {#1} \l_tmpa_seq
|
|
{
|
|
\clist_if_in:NxTF \g__tblr_table_known_keys_clist
|
|
{ \seq_item:Nn \l_tmpa_seq {2} }
|
|
{ \keys_set:nn { tblr } {#1} }
|
|
{ \__tblr_parse_colrow_spec:nn { column } {#1} }
|
|
}
|
|
{ \__tblr_parse_colrow_spec:nn { column } {#1} }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_keys_gput:nn #1 #2
|
|
{
|
|
\__tblr_prop_gput:nnn { inner } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_keys_gput:nn { nx }
|
|
|
|
\keys_define:nn { tblr-delimiter }
|
|
{
|
|
left .code:n = \__tblr_keys_gput:nn { delim-left } { \left #1 },
|
|
right .code:n = \__tblr_keys_gput:nn { delim-right } { \right #1 }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_set_delimiter:n #1
|
|
{
|
|
\keys_set:nn { tblr-delimiter } {#1}
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Initialize and Parse Table Outer Specifications}
|
|
%%% --------------------------------------------------------
|
|
|
|
\msg_new:nnn { tabularray } { used-theme-name }
|
|
{ theme ~ name ~ #1 ~ has ~ been ~ used! }
|
|
|
|
%% #1: theme names; #2: template and style commands
|
|
\NewDocumentCommand \NewTblrTheme { m +m }
|
|
{
|
|
\tl_if_exist:cTF { g__tblr_theme_ #1 _code_tl }
|
|
{ \msg_error:nnn { tabularray } { used-theme-name } { #1 } }
|
|
{
|
|
\tl_set:cn { g__tblr_theme_ #1 _code_tl } {#2}
|
|
\ignorespaces
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_use_theme:n #1
|
|
{
|
|
\ignorespaces
|
|
\tl_use:c { g__tblr_theme_ #1 _code_tl }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_init_table_outer_spec:
|
|
{
|
|
\keys_set:nv { tblr-outer } { l__tblr_default_ \l__tblr_env_name_tl _outer_tl }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_parse_table_option:n #1
|
|
{
|
|
\keys_set:nn { tblr-outer } {#1}
|
|
}
|
|
|
|
\keys_define:nn { tblr-outer }
|
|
{
|
|
long .code:n = \__tblr_outer_gput_spec:nn { long } { true },
|
|
tall .code:n = \__tblr_outer_gput_spec:nn { tall } { true },
|
|
halign .code:n = \__tblr_outer_gput_spec:nn { halign } {#1},
|
|
baseline .code:n = \__tblr_outer_gput_spec:nn { baseline } {#1},
|
|
l .meta:n = { halign = l },
|
|
c .meta:n = { halign = c },
|
|
r .meta:n = { halign = r },
|
|
t .meta:n = { baseline = t },
|
|
T .meta:n = { baseline = T },
|
|
m .meta:n = { baseline = m },
|
|
M .meta:n = { baseline = M },
|
|
b .meta:n = { baseline = b },
|
|
B .meta:n = { baseline = B },
|
|
valign .meta:n = { baseline = #1 }, % obsolete, will be removed some day
|
|
expand .code:n = \__tblr_outer_gput_spec:nn { expand } {#1},
|
|
headsep .code:n = \__tblr_outer_gput_spec:nn { headsep } {#1},
|
|
footsep .code:n = \__tblr_outer_gput_spec:nn { footsep } {#1},
|
|
presep .code:n = \__tblr_outer_gput_spec:nn { presep } {#1},
|
|
postsep .code:n = \__tblr_outer_gput_spec:nn { postsep } {#1},
|
|
theme .code:n = \__tblr_use_theme:n {#1},
|
|
caption .code:n = \__tblr_outer_gput_spec:nn { caption } {#1},
|
|
entry .code:n = \__tblr_outer_gput_spec:nn { entry } {#1},
|
|
label .code:n = \__tblr_outer_gput_spec:nn { label } {#1},
|
|
unknown .code:n = \__tblr_table_option_key:Vn \l_keys_key_str {#1},
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_outer_gput_spec:nn #1 #2
|
|
{
|
|
\__tblr_spec_gput:nen { outer } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_outer_gput_spec:nn { ne }
|
|
|
|
\regex_const:Nn \c__tblr_option_key_name_regex { ^ [A-Za-z\-] + $ }
|
|
|
|
\msg_new:nnn { tabularray } { unknown-outer-key }
|
|
{ Unknown ~ outer ~ key ~ name ~ #1! }
|
|
|
|
\cs_new_protected:Npn \__tblr_table_option_key:nn #1 #2
|
|
{
|
|
\regex_match:NnTF \c__tblr_option_key_name_regex {#1}
|
|
{ \msg_error:nnn { tabularray } { unknown-outer-key } {#1} }
|
|
{
|
|
\regex_extract_once:NnNT \c__tblr_split_key_name_regex {#1} \l_tmpa_seq
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {2} }
|
|
\tl_set_rescan:Nnx \l__tblr_b_tl {} { \seq_item:Nn \l_tmpa_seq {3} }
|
|
\tl_set:Nx \l__tblr_c_tl { \tl_head:N \l__tblr_b_tl }
|
|
\use:c { __tblr_outer_gput_ \l__tblr_a_tl :Vn } \l__tblr_c_tl {#2}
|
|
}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_table_option_key:nn { Vn }
|
|
|
|
\cs_new_protected:Npn \__tblr_outer_gput_note:nn #1 #2
|
|
{
|
|
\__tblr_prop_gput:nnn { note } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_outer_gput_note:nn { Vn }
|
|
|
|
\cs_new_protected:Npn \__tblr_outer_gput_remark:nn #1 #2
|
|
{
|
|
\__tblr_prop_gput:nnn { remark } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_outer_gput_remark:nn { Vn }
|
|
|
|
\cs_new_protected:Npn \__tblr_outer_gput_more:nn #1 #2
|
|
{
|
|
\__tblr_prop_gput:nnn { more } {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_outer_gput_more:nn { Vn }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Typeset and Calculate Sizes}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% Calculate the width and height for every cell and border
|
|
|
|
\cs_new_protected:Npn \__tblr_calc_cell_and_line_sizes:
|
|
{
|
|
\__tblr_prepare_stretch:
|
|
\__tblr_calculate_line_sizes:
|
|
\__tblr_calculate_cell_sizes:
|
|
\LogTblrTracing { cell, row, column, hline, vline }
|
|
\__tblr_compute_extendable_column_width:
|
|
\__tblr_adjust_sizes_for_span_cells:
|
|
}
|
|
|
|
%% prepare stretch option of the table
|
|
\fp_new:N \l__tblr_stretch_fp
|
|
\dim_new:N \l__tblr_strut_dp_dim
|
|
\dim_new:N \l__tblr_strut_ht_dim
|
|
\cs_new_protected:Npn \__tblr_prepare_stretch:
|
|
{
|
|
\fp_set:Nn \l__tblr_stretch_fp
|
|
{ \__tblr_prop_item:nn { inner } { stretch } }
|
|
\fp_compare:nNnTF \l__tblr_stretch_fp > \c_zero_fp
|
|
{
|
|
\dim_set:Nn \l__tblr_strut_dp_dim
|
|
{ \fp_use:N \l__tblr_stretch_fp \box_dp:N \strutbox }
|
|
\dim_set:Nn \l__tblr_strut_ht_dim
|
|
{ \fp_use:N \l__tblr_stretch_fp \box_ht:N \strutbox }
|
|
\cs_set_eq:NN \__tblr_leave_vmode: \mode_leave_vertical:
|
|
\cs_set_eq:NN \__tblr_process_stretch: \__tblr_process_stretch_real:
|
|
}
|
|
{
|
|
\cs_set_eq:NN \__tblr_process_stretch: \prg_do_nothing:
|
|
\fp_compare:nNnTF \l__tblr_stretch_fp < \c_zero_fp
|
|
{ \cs_set_eq:NN \__tblr_leave_vmode: \@setminipage } % for lists (see issue #99)
|
|
{ \cs_set_eq:NN \__tblr_leave_vmode: \mode_leave_vertical: }
|
|
}
|
|
}
|
|
\cs_new_eq:NN \__tblr_leave_vmode: \mode_leave_vertical:
|
|
\cs_new_protected:Npn \__tblr_process_stretch_real:
|
|
{
|
|
\dim_compare:nNnT \l__tblr_strut_dp_dim > { \box_dp:N \l_tmpb_box }
|
|
{
|
|
\box_set_dp:Nn \l_tmpa_box
|
|
{
|
|
\box_dp:N \l_tmpa_box
|
|
- \box_dp:N \l_tmpb_box
|
|
+ \l__tblr_strut_dp_dim
|
|
}
|
|
\box_set_dp:Nn \l_tmpb_box { \l__tblr_strut_dp_dim }
|
|
}
|
|
\dim_compare:nNnT \l__tblr_strut_ht_dim > { \box_ht:N \l_tmpa_box }
|
|
{
|
|
\hbox_set:Nn \l_tmpa_box { \box_use:N \l_tmpa_box }
|
|
\hbox_set:Nn \l_tmpb_box { \box_use:N \l_tmpb_box }
|
|
\box_set_ht:Nn \l_tmpb_box
|
|
{
|
|
\box_ht:N \l_tmpb_box
|
|
- \box_ht:N \l_tmpa_box
|
|
+ \l__tblr_strut_ht_dim
|
|
}
|
|
\box_set_ht:Nn \l_tmpa_box { \l__tblr_strut_ht_dim }
|
|
%% return vbox for vertical-align: \c__tblr_middle_m_tl
|
|
\vbox_set_top:Nn \l_tmpa_box { \box_use:N \l_tmpa_box }
|
|
\vbox_set:Nn \l_tmpb_box { \box_use:N \l_tmpb_box }
|
|
}
|
|
}
|
|
\cs_new_eq:NN \__tblr_process_stretch: \__tblr_process_stretch_real:
|
|
|
|
%% Calculate the thickness for every hline and vline
|
|
\cs_new_protected:Npn \__tblr_calculate_line_sizes:
|
|
{
|
|
%% We need these two counters in executing hline and vline commands
|
|
\int_zero:N \c@rownum
|
|
\int_zero:N \c@colnum
|
|
\int_step_inline:nn { \c@rowcount + 1 }
|
|
{
|
|
\int_incr:N \c@rownum
|
|
\int_zero:N \c@colnum
|
|
\int_step_inline:nn { \c@colcount + 1 }
|
|
{
|
|
\int_incr:N \c@colnum
|
|
\int_compare:nNnT { ##1 } < { \c@rowcount + 1 }
|
|
{
|
|
\__tblr_measure_and_update_vline_size:nn { ##1 } { ####1 }
|
|
}
|
|
\int_compare:nNnT { ####1 } < { \c@colcount + 1 }
|
|
{
|
|
\__tblr_measure_and_update_hline_size:nn { ##1 } { ####1 }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
%% Measure and update thickness of the vline
|
|
%% #1: row number, #2 column number
|
|
\cs_new_protected:Npn \__tblr_measure_and_update_vline_size:nn #1 #2
|
|
{
|
|
\dim_zero:N \l__tblr_w_dim
|
|
\tl_set:Nx \l__tblr_n_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#2] / @vline-count } }
|
|
\int_compare:nNnT { \l__tblr_n_tl } > {0}
|
|
{
|
|
\tl_set:Nx \l__tblr_s_tl
|
|
{ \__tblr_prop_item:ne { inner } { rulesep } }
|
|
\int_step_inline:nn { \l__tblr_n_tl }
|
|
{
|
|
\vbox_set_to_ht:Nnn \l__tblr_b_box {1pt}
|
|
{
|
|
\__tblr_get_vline_segment_child:nnnnn
|
|
{#1} {#2} {##1} {1pt} {1pt}
|
|
}
|
|
\tl_set:Nx \l__tblr_w_tl { \dim_eval:n { \box_wd:N \l__tblr_b_box } }
|
|
\__tblr_spec_gput_if_larger:nee { vline }
|
|
{ [#2](##1) / @vline-width } { \l__tblr_w_tl }
|
|
\dim_add:Nn \l__tblr_w_dim
|
|
{
|
|
\__tblr_spec_item:nn { vline } { [#2](##1) / @vline-width }
|
|
}
|
|
\dim_add:Nn \l__tblr_w_dim { \l__tblr_s_tl }
|
|
}
|
|
\dim_add:Nn \l__tblr_w_dim { - \l__tblr_s_tl }
|
|
}
|
|
\__tblr_spec_gput_if_larger:nee { vline }
|
|
{ [#2]/ @vline-width } { \dim_use:N \l__tblr_w_dim }
|
|
}
|
|
|
|
%% Get text of a vline segment
|
|
%% #1: row number, #2: column number; #3: index number; #4: height; #5: depth
|
|
%% We put all code inside a group to avoid conflicts of local variables
|
|
\cs_new_protected:Npn \__tblr_get_vline_segment_child:nnnnn #1 #2 #3 #4 #5
|
|
{
|
|
\group_begin:
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#1][#2](#3) / wd } }
|
|
\tl_if_empty:NF \l__tblr_w_tl { \dim_set:Nn \rulewidth { \l__tblr_w_tl } }
|
|
\tl_set:Nx \l__tblr_d_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#1][#2](#3) / @dash } }
|
|
\tl_set:Nx \l__tblr_a_tl { \tl_head:N \l__tblr_d_tl }
|
|
\tl_set:Nx \l__tblr_b_tl { \tl_tail:N \l__tblr_d_tl }
|
|
\exp_args:NV \tl_if_eq:NNTF \l__tblr_a_tl \@tblr@dash
|
|
{
|
|
\__tblr_get_vline_dash_style:N \l__tblr_b_tl
|
|
\xleaders \l__tblr_b_tl \vfil
|
|
}
|
|
{
|
|
%% When using text as vline, we need to omit abovepos and belowpos.
|
|
\unskip
|
|
\hbox_set:Nn \l__tblr_d_box
|
|
{
|
|
\bool_if:NTF \l__tblr_math_mode_bool
|
|
{ $ \l__tblr_b_tl $ } { \l__tblr_b_tl }
|
|
}
|
|
\box_set_ht:Nn \l__tblr_d_box {#4}
|
|
\box_set_dp:Nn \l__tblr_d_box {#5}
|
|
\box_use:N \l__tblr_d_box
|
|
\vss
|
|
}
|
|
\group_end:
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_get_vline_segment_child:nnnnn { nnnxx }
|
|
|
|
%% Measure and update thickness of the hline
|
|
%% #1: row number, #2 column number
|
|
\cs_new_protected:Npn \__tblr_measure_and_update_hline_size:nn #1 #2
|
|
{
|
|
\dim_zero:N \l__tblr_h_dim
|
|
\tl_set:Nx \l__tblr_n_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1] / @hline-count } }
|
|
\int_compare:nNnT { \l__tblr_n_tl } > {0}
|
|
{
|
|
\tl_set:Nx \l__tblr_s_tl
|
|
{ \__tblr_prop_item:ne { inner } { rulesep } }
|
|
\int_step_inline:nn { \l__tblr_n_tl }
|
|
{
|
|
\hbox_set_to_wd:Nnn \l__tblr_b_box {1pt}
|
|
{ \__tblr_get_hline_segment_child:nnn {#1} {#2} {##1} }
|
|
\tl_set:Nx \l__tblr_h_tl
|
|
{
|
|
\dim_eval:n
|
|
{ \box_ht:N \l__tblr_b_box + \box_dp:N \l__tblr_b_box }
|
|
}
|
|
\__tblr_spec_gput_if_larger:nee { hline }
|
|
{ [#1](##1) / @hline-height } { \l__tblr_h_tl }
|
|
\dim_add:Nn \l__tblr_h_dim
|
|
{
|
|
\__tblr_spec_item:nn { hline } { [#1](##1) / @hline-height }
|
|
}
|
|
\dim_add:Nn \l__tblr_h_dim { \l__tblr_s_tl }
|
|
}
|
|
\dim_add:Nn \l__tblr_h_dim { - \l__tblr_s_tl }
|
|
}
|
|
\__tblr_spec_gput_if_larger:nee { hline }
|
|
{ [#1] / @hline-height } { \dim_use:N \l__tblr_h_dim }
|
|
}
|
|
|
|
%% Get text of a hline segment
|
|
%% #1: row number, #2: column number; #3: index number
|
|
\cs_new_protected:Npn \__tblr_get_hline_segment_child:nnn #1 #2 #3
|
|
{
|
|
\group_begin:
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1][#2](#3) / wd } }
|
|
\tl_if_empty:NF \l__tblr_w_tl { \dim_set:Nn \rulewidth { \l__tblr_w_tl } }
|
|
\tl_set:Nx \l__tblr_d_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1][#2](#3) / @dash } }
|
|
\tl_set:Nx \l__tblr_a_tl { \tl_head:N \l__tblr_d_tl }
|
|
\tl_set:Nx \l__tblr_b_tl { \tl_tail:N \l__tblr_d_tl }
|
|
\exp_args:NV \tl_if_eq:NNTF \l__tblr_a_tl \@tblr@dash
|
|
{
|
|
\__tblr_get_hline_dash_style:N \l__tblr_b_tl
|
|
\xleaders \l__tblr_b_tl \hfil
|
|
}
|
|
{
|
|
\bool_if:NTF \l__tblr_math_mode_bool
|
|
{ $ \l__tblr_b_tl $ } { \l__tblr_b_tl }
|
|
\hfil
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% current cell alignments
|
|
\tl_new:N \g__tblr_cell_halign_tl
|
|
\tl_new:N \g__tblr_cell_valign_tl
|
|
\tl_new:N \g__tblr_cell_middle_tl
|
|
|
|
\tl_const:Nn \c__tblr_valign_h_tl { h }
|
|
\tl_const:Nn \c__tblr_valign_m_tl { m }
|
|
\tl_const:Nn \c__tblr_valign_f_tl { f }
|
|
\tl_const:Nn \c__tblr_valign_t_tl { t }
|
|
\tl_const:Nn \c__tblr_valign_b_tl { b }
|
|
|
|
\tl_const:Nn \c__tblr_middle_t_tl { t }
|
|
\tl_const:Nn \c__tblr_middle_m_tl { m }
|
|
\tl_const:Nn \c__tblr_middle_b_tl { b }
|
|
|
|
%% #1: row number; #2: column number
|
|
\cs_new_protected:Npn \__tblr_get_cell_alignments:nn #1 #2
|
|
{
|
|
\group_begin:
|
|
\tl_gset:Nx \g__tblr_cell_halign_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { halign } }
|
|
\tl_set:Nx \l__tblr_v_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { valign } }
|
|
\tl_case:NnF \l__tblr_v_tl
|
|
{
|
|
\c__tblr_valign_t_tl
|
|
{
|
|
\tl_gset:Nn \g__tblr_cell_valign_tl {m}
|
|
\tl_gset:Nn \g__tblr_cell_middle_tl {t}
|
|
}
|
|
\c__tblr_valign_m_tl
|
|
{
|
|
\tl_gset:Nn \g__tblr_cell_valign_tl {m}
|
|
\tl_gset:Nn \g__tblr_cell_middle_tl {m}
|
|
}
|
|
\c__tblr_valign_b_tl
|
|
{
|
|
\tl_gset:Nn \g__tblr_cell_valign_tl {m}
|
|
\tl_gset:Nn \g__tblr_cell_middle_tl {b}
|
|
}
|
|
}
|
|
{
|
|
\tl_gset_eq:NN \g__tblr_cell_valign_tl \l__tblr_v_tl
|
|
\tl_gclear:N \g__tblr_cell_middle_tl
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% current cell dimensions
|
|
\dim_new:N \g__tblr_cell_wd_dim
|
|
\dim_new:N \g__tblr_cell_ht_dim
|
|
\dim_new:N \g__tblr_cell_head_dim
|
|
\dim_new:N \g__tblr_cell_foot_dim
|
|
|
|
%% Calculate the width and height for every cell
|
|
\cs_new_protected:Npn \__tblr_calculate_cell_sizes:
|
|
{
|
|
%% You can use these two counters in cell text
|
|
\int_zero:N \c@rownum
|
|
\int_zero:N \c@colnum
|
|
\__tblr_save_counters:n { table }
|
|
\int_step_inline:nn { \c@rowcount }
|
|
{
|
|
\int_incr:N \c@rownum
|
|
\int_zero:N \c@colnum
|
|
\__tblr_update_rowsep_registers:
|
|
\tl_set:Nx \l__tblr_h_tl
|
|
{ \__tblr_data_item:nen { row } { \int_use:N \c@rownum } { height } }
|
|
%% We didn't initialize row heights with -1pt
|
|
\dim_compare:nNnF { \l__tblr_h_tl } = { 0pt }
|
|
{
|
|
\__tblr_data_gput:nenV { row } { \int_use:N \c@rownum }
|
|
{ @row-height } \l__tblr_h_tl
|
|
}
|
|
\int_step_inline:nn { \c@colcount }
|
|
{
|
|
\int_incr:N \c@colnum
|
|
\__tblr_update_colsep_registers:
|
|
\__tblr_measure_cell_update_sizes:nnNNNN
|
|
{ \int_use:N \c@rownum }
|
|
{ \int_use:N \c@colnum }
|
|
\g__tblr_cell_wd_dim
|
|
\g__tblr_cell_ht_dim
|
|
\g__tblr_cell_head_dim
|
|
\g__tblr_cell_foot_dim
|
|
}
|
|
}
|
|
\__tblr_restore_counters:n { table }
|
|
\int_step_inline:nn { \c@colcount }
|
|
{
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \__tblr_data_item:nen { column } {##1} { width } }
|
|
\dim_compare:nNnF { \l__tblr_w_tl } < { 0pt }
|
|
{
|
|
\__tblr_data_gput:nenV { column } {##1} { @col-width } \l__tblr_w_tl
|
|
}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_update_rowsep_registers:
|
|
{
|
|
\dim_set:Nn \abovesep
|
|
{ \__tblr_data_item:nen { row } { \int_use:N \c@rownum } { abovesep } }
|
|
\dim_set:Nn \belowsep
|
|
{ \__tblr_data_item:nen { row } { \int_use:N \c@rownum } { belowsep } }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_update_colsep_registers:
|
|
{
|
|
\dim_set:Nn \leftsep
|
|
{ \__tblr_data_item:nen { column } { \int_use:N \c@colnum } { leftsep } }
|
|
\dim_set:Nn \rightsep
|
|
{ \__tblr_data_item:nen { column } { \int_use:N \c@colnum } { rightsep } }
|
|
}
|
|
|
|
%% Measure and update natural dimensions of the row/column/cell
|
|
%% #1: row number; #2 column number; #3: width dimension;
|
|
%% #4: total height dimension; #5: head dimension; #6: foot dimension
|
|
\cs_new_protected:Npn \__tblr_measure_cell_update_sizes:nnNNNN #1 #2 #3 #4 #5 #6
|
|
{
|
|
\__tblr_get_cell_alignments:nn {#1} {#2}
|
|
\hbox_set:Nn \l_tmpa_box { \__tblr_get_cell_text:nn {#1} {#2} }
|
|
\__tblr_update_cell_size:nnNNNN {#1} {#2} #3 #4 #5 #6
|
|
\__tblr_update_row_size:nnNNN {#1} {#2} #4 #5 #6
|
|
\__tblr_update_col_size:nN {#2} #3
|
|
}
|
|
|
|
%% #1: row number, #2: column number
|
|
\cs_new_protected:Npn \__tblr_get_cell_text:nn #1 #2
|
|
{
|
|
\int_compare:nNnTF { \__tblr_data_item:neen { cell } {#1} {#2} { omit } } > {0}
|
|
{
|
|
\dim_gzero:N \g__tblr_cell_wd_dim
|
|
\dim_gzero:N \g__tblr_cell_ht_dim
|
|
\dim_gzero:N \g__tblr_cell_head_dim
|
|
\dim_gzero:N \g__tblr_cell_foot_dim
|
|
}
|
|
{ \__tblr_get_cell_text_real:nn { #1 } { #2 } }
|
|
}
|
|
|
|
\tl_new:N \l__tblr_cell_fg_tl
|
|
\tl_new:N \l__tblr_cell_cmd_tl
|
|
\tl_new:N \l__tblr_cell_mode_tl
|
|
\bool_new:N \l__tblr_cell_math_mode_bool
|
|
\tl_const:Nn \l__tblr_cell_math_style_tl { \relax }
|
|
\tl_const:Nn \l__tblr_cell_imath_style_tl { \textstyle }
|
|
\tl_const:Nn \l__tblr_cell_dmath_style_tl { \displaystyle }
|
|
|
|
%% Get cell text, #1: row number, #2: column number
|
|
%% If the width of the cell is not set, split it with \\ and compute the width
|
|
%% Therefore we always get a vbox for any cell
|
|
\cs_new_protected:Npn \__tblr_get_cell_text_real:nn #1 #2
|
|
{
|
|
\group_begin:
|
|
\tl_set:Nx \l__tblr_c_tl { \__tblr_spec_item:ne { text } {[#1][#2]} }
|
|
%% when the cell text is guarded by a pair of curly braces,
|
|
%% we unbrace it and ignore cmd option of the cell, see issue #90.
|
|
\bool_lazy_and:nnTF
|
|
{ \tl_if_single_p:N \l__tblr_c_tl }
|
|
{ \exp_args:NV \tl_if_head_is_group_p:n \l__tblr_c_tl }
|
|
{ \exp_last_unbraced:NNV \tl_set:Nn \l__tblr_c_tl \l__tblr_c_tl }
|
|
{
|
|
\tl_set:Nx \l__tblr_cell_cmd_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { cmd } }
|
|
\tl_if_empty:NF \l__tblr_cell_cmd_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_c_tl
|
|
{ \exp_not:V \l__tblr_cell_cmd_tl { \exp_not:V \l__tblr_c_tl } }
|
|
}
|
|
}
|
|
\tl_set:Nx \l__tblr_cell_mode_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { mode } }
|
|
\tl_if_empty:NT \l__tblr_cell_mode_tl
|
|
{
|
|
\bool_if:NTF \l__tblr_math_mode_bool
|
|
{ \tl_set:Nn \l__tblr_cell_mode_tl { math } }
|
|
{ \tl_set:Nn \l__tblr_cell_mode_tl { text } }
|
|
}
|
|
\tl_if_eq:NnTF \l__tblr_cell_mode_tl { text }
|
|
{ \bool_set_false:N \l__tblr_cell_math_mode_bool }
|
|
{
|
|
\bool_set_true:N \l__tblr_cell_math_mode_bool
|
|
\tl_put_left:Nv \l__tblr_c_tl
|
|
{ l__tblr_cell_ \l__tblr_cell_mode_tl _style_tl }
|
|
\tl_put_left:Nn \l__tblr_c_tl { $ }
|
|
\tl_put_right:Nn \l__tblr_c_tl { $ }
|
|
}
|
|
\tl_set:Nx \l__tblr_f_tl { \__tblr_data_item:neen { cell } {#1} {#2} { font } }
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { width } }
|
|
\dim_compare:nNnT { \l__tblr_w_tl } < { 0pt } % cell width unset
|
|
{
|
|
\int_compare:nNnT
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { colspan } } < {2}
|
|
{
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \__tblr_data_item:nen { column } {#2} { width } }
|
|
}
|
|
}
|
|
\dim_compare:nNnT { \l__tblr_w_tl } < { 0pt } % column width unset
|
|
{
|
|
\__tblr_save_counters:n { cell }
|
|
\bool_if:NTF \l__tblr_cell_math_mode_bool
|
|
{
|
|
%% Note that font = \boldmath will increase cell width (issue #137)
|
|
\hbox_set:Nn \l_tmpa_box { \l__tblr_f_tl \l__tblr_c_tl }
|
|
\tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box }
|
|
}
|
|
{
|
|
\__tblr_get_cell_size_with_box:
|
|
}
|
|
\__tblr_restore_counters:n { cell }
|
|
}
|
|
\tl_put_left:NV \l__tblr_c_tl \l__tblr_f_tl
|
|
\tl_set:Nx \l__tblr_cell_fg_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { foreground } }
|
|
\tl_if_empty:NF \l__tblr_cell_fg_tl
|
|
{ \exp_args:NV \color \l__tblr_cell_fg_tl }
|
|
\__tblr_get_vcell_and_sizes:NN \l__tblr_c_tl \l__tblr_w_tl
|
|
\group_end:
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_get_cell_size_with_box:
|
|
{
|
|
\tl_if_eq:NnTF \l__tblr_inner_spec_measure_tl { vbox }
|
|
{ \__tblr_get_cell_size_with_vbox: }
|
|
{ \__tblr_get_cell_size_with_hbox: }
|
|
}
|
|
|
|
%% Varwidth won't work as expected when \color command occurs in it,
|
|
%% and we can not fix this problem with \leavevmode command.
|
|
%% See https://tex.stackexchange.com/q/460489.
|
|
%% But we need to use \color command for fg option,
|
|
%% or users may use it in the middle of the cell text,
|
|
%% so we have redefine \color command and disable it before measuring cell.
|
|
|
|
%% In order to correctly measure an enumerate environment,
|
|
%% we need to enclose varwidth with NoHyper environment (see issue #196).
|
|
|
|
\NewDocumentCommand \__tblr_fake_color_command:w { o m } { }
|
|
|
|
\cs_new_protected:Npn \__tblr_get_cell_size_with_vbox:
|
|
{
|
|
\hbox_set:Nn \l_tmpa_box
|
|
{
|
|
\cs_set_eq:NN \color \__tblr_fake_color_command:w
|
|
\begin{tblrNoHyper}
|
|
\begin{varwidth}{\paperwidth}
|
|
\l__tblr_f_tl
|
|
\__tblr_rescan_cell_tokens:N \l__tblr_c_tl
|
|
\end{varwidth}
|
|
\end{tblrNoHyper}
|
|
}
|
|
\tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_get_cell_size_with_hbox:
|
|
{
|
|
\tl_set_eq:NN \l_tmpb_tl \l__tblr_c_tl
|
|
\__tblr_insert_braces:N \l_tmpb_tl
|
|
\seq_set_split:NnV \l_tmpa_seq { \\ } \l_tmpb_tl
|
|
\tl_set:Nn \l__tblr_w_tl { 0pt }
|
|
\seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl
|
|
{
|
|
\__tblr_remove_braces:N \l_tmpa_tl
|
|
\hbox_set:Nn \l_tmpa_box
|
|
{
|
|
\l__tblr_f_tl
|
|
\__tblr_rescan_cell_tokens:N \l_tmpa_tl
|
|
}
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \dim_max:nn { \l__tblr_w_tl } { \box_wd:N \l_tmpa_box } }
|
|
}
|
|
}
|
|
|
|
%% #1: cell text; #2: box width
|
|
\cs_new_protected:Npn \__tblr_get_vcell_and_sizes:NN #1 #2
|
|
{
|
|
\group_begin:
|
|
\vbox_set:Nn \l_tmpb_box { \__tblr_make_vcell_text:NN #1 #2 }
|
|
\vbox_set_top:Nn \l_tmpa_box { \vbox_unpack:N \l_tmpb_box }
|
|
\__tblr_process_stretch:
|
|
\dim_gset:Nn \g__tblr_cell_wd_dim { \box_wd:N \l_tmpb_box }
|
|
\dim_gset:Nn \g__tblr_cell_ht_dim
|
|
{ \box_ht:N \l_tmpb_box + \box_dp:N \l_tmpb_box }
|
|
\dim_gset:Nn \g__tblr_cell_head_dim { \box_ht:N \l_tmpa_box }
|
|
\dim_gset:Nn \g__tblr_cell_foot_dim { \box_dp:N \l_tmpb_box }
|
|
\tl_case:Nn \g__tblr_cell_valign_tl
|
|
{
|
|
\c__tblr_valign_h_tl
|
|
{ \box_use:N \l_tmpa_box }
|
|
\c__tblr_valign_m_tl
|
|
{
|
|
\tl_case:Nn \g__tblr_cell_middle_tl
|
|
{
|
|
\c__tblr_middle_t_tl
|
|
{ \box_use:N \l_tmpa_box }
|
|
\c__tblr_middle_m_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_b_tl
|
|
{
|
|
\dim_eval:n
|
|
{
|
|
( \g__tblr_cell_ht_dim - \g__tblr_cell_head_dim
|
|
- \g__tblr_cell_foot_dim ) / 2
|
|
}
|
|
}
|
|
\box_set_ht:Nn \l_tmpb_box
|
|
{ \g__tblr_cell_head_dim + \l__tblr_b_tl }
|
|
\box_set_dp:Nn \l_tmpb_box
|
|
{ \g__tblr_cell_foot_dim + \l__tblr_b_tl }
|
|
\box_use:N \l_tmpb_box
|
|
}
|
|
\c__tblr_middle_b_tl
|
|
{ \box_use:N \l_tmpb_box }
|
|
}
|
|
}
|
|
\c__tblr_valign_f_tl
|
|
{ \box_use:N \l_tmpb_box }
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
%% #1: cell text; #2: box width
|
|
%% All halign commands are defined at the beginning of the file
|
|
\cs_new_protected:Npn \__tblr_make_vcell_text:NN #1 #2
|
|
{
|
|
\dim_set:Nn \tex_hsize:D { #2 }
|
|
\TblrParboxRestore
|
|
\cs:w __tblr_halign_command_ \g__tblr_cell_halign_tl : \cs_end:
|
|
\__tblr_leave_vmode:
|
|
\bool_if:NTF \l__tblr_cell_math_mode_bool
|
|
{ #1 }
|
|
{ \__tblr_rescan_cell_tokens:N #1 }
|
|
}
|
|
|
|
%% When using verb option, there is an end-of-line character at the end.
|
|
%% This character causes extra horizontal space at the end when "measure=hbox",
|
|
%% or causes extra vertical space at the end with "measure=vbox".
|
|
%% Therefore we have to use an \empty to remove it.
|
|
%% See https://tex.stackexchange.com/q/213659
|
|
\cs_new_protected:Npn \__tblr_rescan_cell_tokens:N #1
|
|
{
|
|
\tl_if_empty:NTF \l__tblr_inner_spec_verb_tl
|
|
{ #1 }
|
|
{
|
|
%% insert space characters after some control sequences first (issue #112)
|
|
\regex_replace_all:nnN { (\c{[A-Za-z]*}) ([A-Za-z]) } { \1 \ \2 } #1
|
|
\regex_replace_all:nnN { . } { \c{string} \0 } #1
|
|
\tl_set:Nx #1 { #1 \noexpand \empty }
|
|
\exp_args:NV \tex_scantokens:D #1
|
|
}
|
|
}
|
|
|
|
%% #1: total height dimension; #2: head dimension; #3: foot dimension;
|
|
%% #4: tl for resulting upper size; #5: tl for resulting lower size
|
|
|
|
\tl_new:N \l__tblr_middle_body_tl
|
|
|
|
\cs_new_protected:Npn \__tblr_get_middle_cell_upper_lower:NNNNN #1 #2 #3 #4 #5
|
|
{
|
|
\tl_case:Nn \g__tblr_cell_middle_tl
|
|
{
|
|
\c__tblr_middle_t_tl
|
|
{
|
|
\tl_set:Nx #4 { \dim_use:N #2 }
|
|
\tl_set:Nx #5 { \dim_eval:n { #1 - #2 } }
|
|
}
|
|
\c__tblr_middle_m_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_middle_body_tl { \dim_eval:n { #1 - #2 - #3 } }
|
|
\tl_set:Nx #4 { \dim_eval:n { #2 + \l__tblr_middle_body_tl / 2 } }
|
|
\tl_set:Nx #5 { \dim_eval:n { #3 + \l__tblr_middle_body_tl / 2 } }
|
|
}
|
|
\c__tblr_middle_b_tl
|
|
{
|
|
\tl_set:Nx #4 { \dim_eval:n { #1 - #3 } }
|
|
\tl_set:Nx #5 { \dim_use:N #3 }
|
|
}
|
|
}
|
|
}
|
|
|
|
%% Update natural dimensions of the cell
|
|
%% #1: row number; #2 column number; #3: width dimension;
|
|
%% #4: total height dimension; #5: head dimension; #6: foot dimension
|
|
\cs_new_protected:Npn \__tblr_update_cell_size:nnNNNN #1 #2 #3 #4 #5 #6
|
|
{
|
|
\group_begin:
|
|
\tl_set:Nx \l__tblr_c_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { colspan } }
|
|
\int_compare:nNnT { \l__tblr_c_tl } > {1}
|
|
{
|
|
\__tblr_data_gput:neene { cell } {#1} {#2} { @cell-width } {\dim_use:N #3}
|
|
\dim_gzero:N #3 % don't affect column width
|
|
}
|
|
\tl_set:Nx \l__tblr_r_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { rowspan } }
|
|
\int_compare:nNnT { \l__tblr_r_tl } > {1}
|
|
{
|
|
\tl_case:Nn \g__tblr_cell_valign_tl
|
|
{
|
|
\c__tblr_valign_h_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_u_tl { \dim_use:N #5 }
|
|
\tl_set:Nx \l__tblr_v_tl { \dim_eval:n { #4 - #5 } }
|
|
%% Update the head size of the first span row here
|
|
\__tblr_data_gput_if_larger:nene
|
|
{ row } {#1} { @row-head } { \dim_use:N #5 }
|
|
}
|
|
\c__tblr_valign_f_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_u_tl { \dim_eval:n { #4 - #6 } }
|
|
\tl_set:Nx \l__tblr_v_tl { \dim_use:N #6 }
|
|
%% Update the foot size of the last span row here
|
|
\__tblr_data_gput_if_larger:nene
|
|
{ row }
|
|
{ \int_eval:n { #1 + \l__tblr_r_tl - 1 } }
|
|
{ @row-foot }
|
|
{ \dim_use:N #6 }
|
|
}
|
|
\c__tblr_valign_m_tl
|
|
{
|
|
\__tblr_get_middle_cell_upper_lower:NNNNN
|
|
#4 #5 #6 \l__tblr_u_tl \l__tblr_v_tl
|
|
}
|
|
}
|
|
\__tblr_data_gput:neenV { cell } {#1} {#2} { @cell-height } \l__tblr_u_tl
|
|
\__tblr_data_gput:neenV { cell } {#1} {#2} { @cell-depth } \l__tblr_v_tl
|
|
%% Don't affect row sizes
|
|
\dim_gzero:N #4
|
|
\dim_gzero:N #5
|
|
\dim_gzero:N #6
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
|
|
%% Update size of the row. #1: row number; #2: column number;
|
|
%% #3: total height dimension; #4: head dimension; #5: foot dimension
|
|
\cs_new_protected:Npn \__tblr_update_row_size:nnNNN #1 #2 #3 #4 #5
|
|
{
|
|
\group_begin:
|
|
%% Note that \l__tblr_h_tl may be empty
|
|
\tl_set:Nx \l__tblr_h_tl
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-height } }
|
|
\tl_if_eq:NNTF \g__tblr_cell_valign_tl \c__tblr_valign_m_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-upper } }
|
|
\tl_set:Nx \l__tblr_b_tl
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-lower } }
|
|
\__tblr_get_middle_cell_upper_lower:NNNNN
|
|
#3 #4 #5 \l__tblr_u_tl \l__tblr_v_tl
|
|
\dim_compare:nNnT { \l__tblr_u_tl } > { \l__tblr_a_tl }
|
|
{
|
|
\tl_set_eq:NN \l__tblr_a_tl \l__tblr_u_tl
|
|
\__tblr_data_gput:nenV { row } {#1} { @row-upper } \l__tblr_a_tl
|
|
}
|
|
\dim_compare:nNnT { \l__tblr_v_tl } > { \l__tblr_b_tl }
|
|
{
|
|
\tl_set_eq:NN \l__tblr_b_tl \l__tblr_v_tl
|
|
\__tblr_data_gput:nenV { row } {#1} { @row-lower } \l__tblr_b_tl
|
|
}
|
|
\dim_compare:nNnT
|
|
{ \l__tblr_a_tl + \l__tblr_b_tl } > { \l__tblr_h_tl + 0pt }
|
|
{
|
|
\__tblr_data_gput:nene { row } {#1} { @row-height }
|
|
{ \dim_eval:n { \l__tblr_a_tl + \l__tblr_b_tl } }
|
|
}
|
|
}
|
|
{
|
|
\tl_set:Nx \l__tblr_e_tl
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-head } }
|
|
\tl_set:Nx \l__tblr_f_tl
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-foot } }
|
|
\dim_compare:nNnT {#4} > {\l__tblr_e_tl}
|
|
{
|
|
\__tblr_data_gput:nene { row } {#1} { @row-head } { \dim_use:N #4 }
|
|
}
|
|
\dim_compare:nNnT {#5} > {\l__tblr_f_tl}
|
|
{
|
|
\__tblr_data_gput:nene { row } {#1} { @row-foot } { \dim_use:N #5 }
|
|
}
|
|
\tl_set:Nx \l__tblr_x_tl { \dim_max:nn {#4} { \l__tblr_e_tl } }
|
|
\tl_set:Nx \l__tblr_y_tl { \dim_max:nn {#5} { \l__tblr_f_tl } }
|
|
\dim_compare:nNnT
|
|
{ #3 - #4 - #5 } > { \l__tblr_h_tl - \l__tblr_x_tl - \l__tblr_y_tl }
|
|
{
|
|
\__tblr_data_gput:nene { row } {#1} { @row-height }
|
|
{
|
|
\dim_eval:n
|
|
{
|
|
\l__tblr_x_tl
|
|
+ \dim_use:N #3 - \dim_use:N #4 - \dim_use:N #5
|
|
+ \l__tblr_y_tl
|
|
}
|
|
}
|
|
}
|
|
}
|
|
\group_end:
|
|
}
|
|
|
|
|
|
%% Update size of the column. #1: column number; #2: width dimension
|
|
|
|
\cs_new_protected:Npn \__tblr_update_col_size:nN #1 #2
|
|
{
|
|
\tl_set:Nx \l_tmpb_tl
|
|
{ \__tblr_data_item:nen { column } {#1} { @col-width } }
|
|
\bool_lazy_or:nnT
|
|
{ \tl_if_empty_p:N \l_tmpb_tl }
|
|
{ \dim_compare_p:nNn { \dim_use:N #2 } > { \l_tmpb_tl } }
|
|
{
|
|
\__tblr_data_gput:nene { column } {#1} { @col-width } { \dim_use:N #2 }
|
|
}
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Calculate and Adjust Extendable Columns}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% Compute column widths when there are some extendable columns
|
|
|
|
\dim_new:N \l__column_target_dim
|
|
\prop_new:N \l__column_coefficient_prop
|
|
\prop_new:N \l__column_natural_width_prop
|
|
\prop_new:N \l__column_computed_width_prop
|
|
|
|
\msg_new:nnn { tabularray } { table-width-too-small }
|
|
{ Table ~ width ~ is ~ too ~ small, ~ need ~ #1 ~ more! }
|
|
|
|
\cs_new_protected:Npn \__tblr_compute_extendable_column_width:
|
|
{
|
|
\__tblr_collect_extendable_column_width:
|
|
\dim_compare:nNnTF { \l__column_target_dim } < { 0pt }
|
|
{
|
|
\msg_warning:nnx { tabularray } { table-width-too-small }
|
|
{ \dim_abs:n { \l__column_target_dim } }
|
|
}
|
|
{
|
|
\prop_if_empty:NF \l__column_coefficient_prop
|
|
{ \__tblr_adjust_extendable_column_width: }
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_collect_extendable_column_width:
|
|
{
|
|
\tl_set:Nx \l_tmpa_tl { \__tblr_prop_item:nn { inner } { width } }
|
|
\tl_if_empty:NTF \l_tmpa_tl
|
|
{ \dim_set_eq:NN \l__column_target_dim \linewidth }
|
|
{ \dim_set:Nn \l__column_target_dim { \l_tmpa_tl } }
|
|
\prop_clear:N \l__column_coefficient_prop
|
|
\prop_clear:N \l__column_natural_width_prop
|
|
\prop_clear:N \l__column_computed_width_prop
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { width } }
|
|
\tl_set:Nx \l__tblr_b_tl
|
|
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { coefficient } }
|
|
\tl_set:Nx \l__tblr_c_tl
|
|
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { @col-width } }
|
|
\dim_compare:nNnTF { \l__tblr_a_tl } < { 0pt } % column width unset
|
|
{
|
|
\dim_compare:nNnTF { \l__tblr_b_tl pt } = { 0pt }
|
|
{ \dim_sub:Nn \l__column_target_dim { \l__tblr_c_tl } }
|
|
{
|
|
\prop_put:Nxx \l__column_coefficient_prop
|
|
{ \l__tblr_j_tl } { \l__tblr_b_tl }
|
|
\prop_put:Nxn \l__column_computed_width_prop
|
|
{ \l__tblr_j_tl } { 0pt }
|
|
\dim_compare:nNnF { \l__tblr_b_tl pt } > { 0pt }
|
|
{
|
|
\prop_put:Nxx \l__column_natural_width_prop
|
|
{ \l__tblr_j_tl } { \l__tblr_c_tl }
|
|
}
|
|
}
|
|
}
|
|
{ \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } }
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{ \__tblr_spec_item:ne { vline } { [\l__tblr_j_tl] / @vline-width } }
|
|
\tl_set:Nx \l__tblr_b_tl
|
|
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { leftsep } }
|
|
\tl_set:Nx \l__tblr_c_tl
|
|
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { rightsep } }
|
|
\dim_set:Nn \l__column_target_dim
|
|
{ \l__column_target_dim - \l__tblr_a_tl - \l__tblr_b_tl - \l__tblr_c_tl }
|
|
}
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{
|
|
\__tblr_spec_item:ne { vline }
|
|
{ [\int_eval:n {\c@colcount + 1}] / @vline-width }
|
|
}
|
|
\tl_if_empty:NF \l__tblr_a_tl
|
|
{ \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } }
|
|
\LogTblrTracing { target }
|
|
}
|
|
|
|
%% If all columns have negative coefficients and small natural widths,
|
|
%% \l__column_coefficient_prop will be empty after one or more rounds.
|
|
%% We reset @row-height, etc for \linewidth graphics in X columns (issue #80)
|
|
\cs_new_protected:Npn \__tblr_adjust_extendable_column_width:
|
|
{
|
|
\bool_while_do:nn
|
|
{ \dim_compare_p:nNn { \l__column_target_dim } > { \hfuzz } }
|
|
{
|
|
\prop_if_empty:NTF \l__column_coefficient_prop
|
|
{ \__tblr_adjust_extendable_column_width_negative: }
|
|
{ \__tblr_adjust_extendable_column_width_once: }
|
|
}
|
|
\prop_map_inline:Nn \l__column_computed_width_prop
|
|
{
|
|
\__tblr_data_gput:nnne { column } {##1} { width } {##2}
|
|
\__tblr_data_gput:nnnn { column } {##1} { @col-width } { 0pt }
|
|
}
|
|
\int_step_inline:nn { \c@rowcount }
|
|
{
|
|
\__tblr_data_gput:nnnn { row } {##1} { @row-height } { 0pt }
|
|
\__tblr_data_gput:nnnn { row } {##1} { @row-head } { 0pt }
|
|
\__tblr_data_gput:nnnn { row } {##1} { @row-foot } { 0pt }
|
|
\__tblr_data_gput:nnnn { row } {##1} { @row-upper } { 0pt }
|
|
\__tblr_data_gput:nnnn { row } {##1} { @row-lower } { 0pt }
|
|
}
|
|
\__tblr_calculate_cell_sizes:
|
|
}
|
|
|
|
%% We use dimen register, since the coefficient may be a decimal number
|
|
\cs_new_protected:Npn \__tblr_adjust_extendable_column_width_once:
|
|
{
|
|
\dim_zero:N \l_tmpa_dim
|
|
\prop_map_inline:Nn \l__column_coefficient_prop
|
|
{
|
|
\dim_add:Nn \l_tmpa_dim { \dim_abs:n { ##2 pt } }
|
|
}
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \dim_ratio:nn { \l__column_target_dim } { \l_tmpa_dim } }
|
|
\dim_zero:N \l__column_target_dim
|
|
\prop_map_inline:Nn \l__column_coefficient_prop
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{ \dim_eval:n { \dim_abs:n { ##2 pt } * \l__tblr_w_tl } }
|
|
\dim_compare:nNnTF { ##2 pt } > { 0pt }
|
|
{
|
|
\__tblr_add_dimen_value:Nnn
|
|
\l__column_computed_width_prop { ##1 } { \l__tblr_a_tl }
|
|
}
|
|
{
|
|
\tl_set:Nx \l__tblr_b_tl
|
|
{ \prop_item:Nn \l__column_natural_width_prop { ##1 } }
|
|
\tl_set:Nx \l__tblr_c_tl
|
|
{ \prop_item:Nn \l__column_computed_width_prop { ##1 } }
|
|
\dim_compare:nNnTF { \l__tblr_a_tl + \l__tblr_c_tl } > { \l__tblr_b_tl }
|
|
{
|
|
\prop_put:Nnx \l__column_computed_width_prop
|
|
{ ##1 } { \l__tblr_b_tl }
|
|
\dim_add:Nn \l__column_target_dim
|
|
{ \l__tblr_a_tl + \l__tblr_c_tl - \l__tblr_b_tl }
|
|
\prop_remove:Nn \l__column_coefficient_prop { ##1 }
|
|
}
|
|
{
|
|
\__tblr_add_dimen_value:Nnn
|
|
\l__column_computed_width_prop { ##1 } { \l__tblr_a_tl }
|
|
}
|
|
}
|
|
}
|
|
\LogTblrTracing { target }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_adjust_extendable_column_width_negative:
|
|
{
|
|
\dim_zero:N \l_tmpa_dim
|
|
\prop_map_inline:Nn \l__column_natural_width_prop
|
|
{ \dim_add:Nn \l_tmpa_dim { ##2 } }
|
|
\tl_set:Nx \l_tmpa_tl
|
|
{ \dim_ratio:nn { \l__column_target_dim } { \l_tmpa_dim } }
|
|
\dim_zero:N \l__column_target_dim
|
|
\prop_map_inline:Nn \l__column_natural_width_prop
|
|
{
|
|
\tl_set:Nx \l_tmpb_tl { \dim_eval:n { ##2 * \l_tmpa_tl } }
|
|
\__tblr_add_dimen_value:Nnn
|
|
\l__column_computed_width_prop { ##1 } { \l_tmpb_tl }
|
|
}
|
|
\LogTblrTracing { target }
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Calculate and Adjust Multispan Cells}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% Compute and adjust widths when there are some span cells.
|
|
%% By default, we will compute column widths from span widths;
|
|
%% but if we set table option "hspan = minimal",
|
|
%% we will compute span widths from column widths.
|
|
|
|
\cs_new_protected:Npn \__tblr_adjust_sizes_for_span_cells:
|
|
{
|
|
\__tblr_prop_if_in:nnT { inner } { colspan }
|
|
{
|
|
\__tblr_collect_column_widths_skips:
|
|
\str_if_eq:xnTF
|
|
{ \__tblr_prop_item:ne { inner } { hspan } } { minimal }
|
|
{
|
|
\__tblr_set_span_widths_from_column_widths:
|
|
}
|
|
{
|
|
\__tblr_collect_span_widths:
|
|
\__tblr_set_column_widths_from_span_widths:
|
|
}
|
|
\LogTblrTracing { column }
|
|
\__tblr_calculate_cell_sizes:
|
|
}
|
|
\__tblr_prop_if_in:nnT { inner } { rowspan }
|
|
{
|
|
\__tblr_collect_row_heights_skips:
|
|
\__tblr_collect_span_heights:
|
|
\__tblr_set_row_heights_from_span_heights:
|
|
\LogTblrTracing { row }
|
|
}
|
|
}
|
|
|
|
\prop_new:N \l__tblr_col_item_skip_size_prop
|
|
\prop_new:N \l__tblr_col_span_size_prop
|
|
\prop_new:N \l__tblr_row_item_skip_size_prop
|
|
\prop_new:N \l__tblr_row_span_size_prop
|
|
|
|
\cs_new_protected:Npn \__tblr_collect_column_widths_skips:
|
|
{
|
|
\prop_clear:N \l__tblr_col_item_skip_size_prop
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\int_compare:nNnTF { \l__tblr_j_tl } > { 1 }
|
|
{
|
|
\prop_put:Nxx \l__tblr_col_item_skip_size_prop { skip[\l__tblr_j_tl] }
|
|
{
|
|
\dim_eval:n
|
|
{
|
|
\__tblr_data_item:nen { column }
|
|
{ \int_eval:n { \l__tblr_j_tl - 1 } } { rightsep }
|
|
+
|
|
\__tblr_spec_item:ne { vline }
|
|
{ [\l__tblr_j_tl] / @vline-width }
|
|
+
|
|
\__tblr_data_item:nen { column } { \l__tblr_j_tl } { leftsep }
|
|
}
|
|
}
|
|
}
|
|
{
|
|
\prop_put:Nxn \l__tblr_col_item_skip_size_prop { skip[\l__tblr_j_tl] }
|
|
{ 0pt }
|
|
}
|
|
\prop_put:Nxx \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] }
|
|
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { @col-width } }
|
|
}
|
|
\__tblr_do_if_tracing:nn { cellspan }
|
|
{ \prop_log:N \l__tblr_col_item_skip_size_prop }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_collect_row_heights_skips:
|
|
{
|
|
\prop_clear:N \l__tblr_row_item_skip_size_prop
|
|
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
|
|
{
|
|
\int_compare:nNnTF { \l__tblr_i_tl } > { 1 }
|
|
{
|
|
\prop_put:Nxx \l__tblr_row_item_skip_size_prop { skip[\l__tblr_i_tl] }
|
|
{
|
|
\dim_eval:n
|
|
{
|
|
\__tblr_data_item:nen { row }
|
|
{ \int_eval:n {\l__tblr_i_tl - 1} } { belowsep }
|
|
+
|
|
\__tblr_spec_item:ne { hline }
|
|
{ [\l__tblr_i_tl] / @hline-height }
|
|
+
|
|
\__tblr_data_item:nen { row } { \l__tblr_i_tl } { abovesep }
|
|
}
|
|
}
|
|
}
|
|
{
|
|
\prop_put:Nxn \l__tblr_row_item_skip_size_prop { skip[\l__tblr_i_tl] }
|
|
{ 0pt }
|
|
}
|
|
\__tblr_collect_one_row_height:NN \l__tblr_i_tl \l__tblr_h_tl
|
|
\prop_put:Nxx \l__tblr_row_item_skip_size_prop
|
|
{ item[\l__tblr_i_tl] } { \l__tblr_h_tl }
|
|
}
|
|
\__tblr_do_if_tracing:nn { cellspan }
|
|
{ \prop_log:N \l__tblr_row_item_skip_size_prop }
|
|
}
|
|
|
|
%% #1: row number; #2: tl with result
|
|
\cs_new_protected:Npn \__tblr_collect_one_row_height:NN #1 #2
|
|
{
|
|
\tl_set:Nx #2 { \__tblr_data_item:nen { row } {#1} { @row-height } }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_collect_span_widths:
|
|
{
|
|
\prop_clear:N \l__tblr_col_span_size_prop
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{
|
|
\__tblr_data_item:neen { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { colspan }
|
|
}
|
|
\int_compare:nNnT { \l__tblr_a_tl } > {1}
|
|
{
|
|
\__tblr_put_if_larger:Nxx \l__tblr_col_span_size_prop
|
|
{
|
|
( \l__tblr_j_tl -
|
|
\int_eval:n {\l__tblr_j_tl + \l__tblr_a_tl - 1} )
|
|
}
|
|
{
|
|
\__tblr_data_item:neen { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-width }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
\__tblr_do_if_tracing:nn { cellspan }
|
|
{ \prop_log:N \l__tblr_col_span_size_prop }
|
|
}
|
|
|
|
\prop_new:N \l__tblr_row_span_to_row_prop
|
|
|
|
\cs_new_protected:Npn \__tblr_collect_span_heights:
|
|
{
|
|
\prop_clear:N \l__tblr_row_span_to_row_prop
|
|
\prop_clear:N \l__tblr_row_span_size_prop
|
|
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
|
|
{
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{
|
|
\__tblr_data_item:neen { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { rowspan }
|
|
}
|
|
\int_compare:nNnT { \l__tblr_a_tl } > {1}
|
|
{
|
|
\tl_set:Nx \l__tblr_v_tl
|
|
{
|
|
\__tblr_data_item:neen { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { valign }
|
|
}
|
|
\tl_if_eq:NnT \l__tblr_v_tl { h }
|
|
{
|
|
\tl_set:Nx \l__tblr_h_tl
|
|
{
|
|
\__tblr_data_item:nen { row }
|
|
{ \l__tblr_i_tl } { @row-head }
|
|
}
|
|
\__tblr_data_gput:neenV { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-height }
|
|
\l__tblr_h_tl
|
|
}
|
|
\tl_if_eq:NnT \l__tblr_v_tl { f }
|
|
{
|
|
\tl_set:Nx \l__tblr_d_tl
|
|
{
|
|
\__tblr_data_item:nen
|
|
{ row }
|
|
{ \int_eval:n { \l__tblr_i_tl + \l__tblr_a_tl - 1 } }
|
|
{ @row-foot }
|
|
}
|
|
\__tblr_data_gput:neenV { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-depth }
|
|
\l__tblr_d_tl
|
|
}
|
|
\__tblr_put_if_larger:Nxx \l__tblr_row_span_size_prop
|
|
{
|
|
( \l__tblr_i_tl -
|
|
\int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1} )
|
|
}
|
|
{
|
|
\dim_eval:n
|
|
{
|
|
\__tblr_data_item:neen { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-height }
|
|
+
|
|
\__tblr_data_item:neen { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-depth }
|
|
}
|
|
}
|
|
\prop_put:Nxx \l__tblr_row_span_to_row_prop
|
|
{ [\l__tblr_i_tl][\l__tblr_j_tl] }
|
|
{ \int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1} }
|
|
}
|
|
}
|
|
}
|
|
\__tblr_do_if_tracing:nn { cellspan }
|
|
{
|
|
\prop_log:N \l__tblr_row_span_to_row_prop
|
|
\prop_log:N \l__tblr_row_span_size_prop
|
|
}
|
|
}
|
|
|
|
%% Compute and set column widths from span widths
|
|
\cs_new_protected:Npn \__tblr_set_column_widths_from_span_widths:
|
|
{
|
|
\str_if_eq:xnTF
|
|
{ \__tblr_prop_item:ne { inner } { hspan } }
|
|
{ even }
|
|
{
|
|
\__tblr_distribute_span_sizes_even:xNN
|
|
{ \int_use:N \c@colcount }
|
|
\l__tblr_col_item_skip_size_prop
|
|
\l__tblr_col_span_size_prop
|
|
}
|
|
{
|
|
\__tblr_distribute_span_sizes_default:xNN
|
|
{ \int_use:N \c@colcount }
|
|
\l__tblr_col_item_skip_size_prop
|
|
\l__tblr_col_span_size_prop
|
|
}
|
|
\__tblr_set_all_column_widths:
|
|
}
|
|
|
|
%% Compute and set row heights from span heights
|
|
\cs_new_protected:Npn \__tblr_set_row_heights_from_span_heights:
|
|
{
|
|
\str_if_eq:xnTF
|
|
{ \__tblr_prop_item:ne { inner } { vspan } }
|
|
{ even }
|
|
{
|
|
\__tblr_distribute_span_sizes_even:nNN
|
|
{ \int_use:N \c@rowcount }
|
|
\l__tblr_row_item_skip_size_prop
|
|
\l__tblr_row_span_size_prop
|
|
}
|
|
{
|
|
\__tblr_distribute_span_sizes_default:xNN
|
|
{ \int_use:N \c@rowcount }
|
|
\l__tblr_row_item_skip_size_prop
|
|
\l__tblr_row_span_size_prop
|
|
}
|
|
\__tblr_set_all_row_heights:
|
|
}
|
|
|
|
%% See page 245 in Chapter 22 of TeXbook
|
|
%% #1: total number of items
|
|
%% #2: prop list with item sizes and skip sizes; #3: prop list with span sizes
|
|
\cs_new_protected:Npn \__tblr_distribute_span_sizes_default:nNN #1 #2 #3
|
|
{
|
|
\int_step_variable:nNn { #1 } \l__tblr_j_tl
|
|
{
|
|
\dim_set:Nn \l__tblr_w_dim
|
|
{
|
|
\prop_item:Ne #2 { item[\l__tblr_j_tl] }
|
|
}
|
|
\int_step_variable:nNn { \l__tblr_j_tl - 1 } \l__tblr_i_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{ \prop_item:Ne #3 { (\l__tblr_i_tl-\l__tblr_j_tl) } }
|
|
\tl_if_empty:NF \l__tblr_a_tl
|
|
{
|
|
\int_step_variable:nnNn
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl - 1 } \l__tblr_k_tl
|
|
{
|
|
\__tblr_do_if_tracing:nn { cellspan }
|
|
{
|
|
\tl_log:x
|
|
{ \l__tblr_j_tl : \l__tblr_i_tl -> \l__tblr_k_tl }
|
|
}
|
|
\tl_set:Nx \l_tmpa_tl
|
|
{
|
|
\prop_item:Ne #2 { itemskip[\l__tblr_k_tl] }
|
|
}
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{ \dim_eval:n { \l__tblr_a_tl - \l_tmpa_tl } }
|
|
}
|
|
\dim_compare:nNnT { \l__tblr_a_tl } > { \l__tblr_w_dim }
|
|
{
|
|
\dim_set:Nn \l__tblr_w_dim { \l__tblr_a_tl }
|
|
}
|
|
}
|
|
}
|
|
\prop_put:Nxx #2
|
|
{ item[\l__tblr_j_tl] } { \dim_use:N \l__tblr_w_dim }
|
|
\int_compare:nNnT { \l__tblr_j_tl } < { #1 }
|
|
{
|
|
\tl_set:Nx \l_tmpb_tl
|
|
{
|
|
\prop_item:Ne #2
|
|
{ skip[\int_eval:n { \l__tblr_j_tl + 1} ] }
|
|
}
|
|
\dim_add:Nn \l__tblr_w_dim { \l_tmpb_tl }
|
|
\prop_put:Nxx #2
|
|
{ itemskip[\l__tblr_j_tl] } { \dim_use:N \l__tblr_w_dim }
|
|
}
|
|
}
|
|
\__tblr_do_if_tracing:nn { cellspan } { \prop_log:N #2 }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_distribute_span_sizes_default:nNN { x }
|
|
|
|
%% #1: total number of items
|
|
%% #2: prop list with item sizes and skip sizes; #3: prop list with span sizes
|
|
\cs_new_protected:Npn \__tblr_distribute_span_sizes_even:nNN #1 #2 #3
|
|
{
|
|
\prop_clear:N \l_tmpa_prop
|
|
\prop_map_inline:Nn #3
|
|
{
|
|
\__tblr_get_span_from_to:w ##1
|
|
\dim_set:Nn \l_tmpa_dim {##2}
|
|
\dim_sub:Nn \l_tmpa_dim { \prop_item:Ne #2 { item[\l__tblr_a_tl] } }
|
|
\int_step_inline:nnn { \l__tblr_a_tl + 1 } { \l__tblr_b_tl }
|
|
{
|
|
\dim_sub:Nn \l_tmpa_dim
|
|
{
|
|
\prop_item:Ne #2 { skip[####1] } + \prop_item:Nn #2 { item[####1] }
|
|
}
|
|
}
|
|
\__tblr_do_if_tracing:nn { cellspan }
|
|
{
|
|
\tl_log:x { \l__tblr_a_tl -> \l__tblr_b_tl : ~ \dim_use:N \l_tmpa_dim }
|
|
}
|
|
\dim_compare:nNnT {\l_tmpa_dim} > {0pt}
|
|
{
|
|
\tl_set:Nx \l_tmpa_tl
|
|
{ \dim_eval:n { \l_tmpa_dim / (\l__tblr_b_tl - \l__tblr_a_tl + 1) } }
|
|
\int_step_inline:nnn { \l__tblr_a_tl } { \l__tblr_b_tl }
|
|
{
|
|
\__tblr_put_if_larger:NnV \l_tmpa_prop {####1} \l_tmpa_tl
|
|
}
|
|
}
|
|
}
|
|
\__tblr_do_if_tracing:nn { cellspan } { \prop_log:N \l_tmpa_prop }
|
|
\prop_map_inline:Nn \l_tmpa_prop
|
|
{
|
|
\__tblr_add_dimen_value:Nnn #2 {item[##1]} {##2}
|
|
}
|
|
\__tblr_do_if_tracing:nn { cellspan } { \prop_log:N #2 }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_distribute_span_sizes_even:nNN { x }
|
|
|
|
\cs_new_protected:Npn \__tblr_get_span_from_to:w (#1-#2)
|
|
{
|
|
\tl_set:Nn \l__tblr_a_tl {#1}
|
|
\tl_set:Nn \l__tblr_b_tl {#2}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_set_all_column_widths:
|
|
{
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\__tblr_data_gput:nene { column }
|
|
{ \l__tblr_j_tl } { width }
|
|
{ \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] } }
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_set_all_row_heights:
|
|
{
|
|
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_h_tl
|
|
{
|
|
\__tblr_data_item:nen { row } { \l__tblr_i_tl } { @row-head }
|
|
}
|
|
\tl_set:Nx \l__tblr_d_tl
|
|
{
|
|
\__tblr_data_item:nen { row } { \l__tblr_i_tl } { @row-foot }
|
|
}
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{
|
|
\prop_item:Ne \l__tblr_row_item_skip_size_prop { item[\l__tblr_i_tl] }
|
|
}
|
|
\__tblr_collect_one_row_height:NN \l__tblr_i_tl \l__tblr_t_tl
|
|
\__tblr_data_gput:nene { row }
|
|
{ \l__tblr_i_tl } { @row-height } { \l__tblr_a_tl }
|
|
}
|
|
}
|
|
|
|
%% Compute and set span widths from column widths
|
|
\cs_new_protected:Npn \__tblr_set_span_widths_from_column_widths:
|
|
{
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
|
|
{
|
|
\tl_set:Nx \l__tblr_a_tl
|
|
{
|
|
\__tblr_data_item:neen { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { colspan }
|
|
}
|
|
\int_compare:nNnT { \l__tblr_a_tl } > {1}
|
|
{
|
|
\__tblr_calc_span_widths:xxN
|
|
{ \l__tblr_j_tl }
|
|
{ \int_eval:n { \l__tblr_j_tl + \l__tblr_a_tl - 1 } }
|
|
\l__tblr_w_dim
|
|
\__tblr_data_gput:neene { cell }
|
|
{ \l__tblr_i_tl } { \l__tblr_j_tl } { width }
|
|
{ \dim_use:N \l__tblr_w_dim }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
%% Cell is spanned from col #1 to col #2, #3 is the return dim
|
|
\cs_new_protected:Npn \__tblr_calc_span_widths:nnN #1 #2 #3
|
|
{
|
|
\dim_set:Nn #3 { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[#1] } }
|
|
\int_step_inline:nnn { #1 + 1 } { #2 }
|
|
{
|
|
\tl_set:Nx \l_tmpa_tl
|
|
{ \prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] } }
|
|
\tl_set:Nx \l_tmpb_tl
|
|
{ \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] } }
|
|
\dim_add:Nn #3 { \dim_eval:n { \l_tmpa_tl + \l_tmpb_tl } }
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_calc_span_widths:nnN { xxN }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Header and Footer Styles}
|
|
%%% --------------------------------------------------------
|
|
|
|
\prop_new:N \l__tblr_element_styles_prop
|
|
|
|
\cs_new_protected:Npn \__tblr_style_put:nn #1 #2
|
|
{
|
|
\prop_put:Nnn \l__tblr_element_styles_prop {#1} {#2}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_style_put:nn { nV, ne, en, eV }
|
|
|
|
\cs_new:Npn \__tblr_style_item:n #1
|
|
{
|
|
\prop_item:Nn \l__tblr_element_styles_prop {#1}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_style_log:
|
|
{
|
|
\prop_log:N \l__tblr_element_styles_prop
|
|
}
|
|
|
|
\tl_new:N \l__tblr_element_name_tl
|
|
\tl_new:N \l__tblr_element_styles_tl
|
|
|
|
%% #1: list of element names; #2: element styles
|
|
\NewDocumentCommand \SetTblrStyle { m +m }
|
|
{
|
|
\tl_set:Nn \l__tblr_element_styles_tl {#2}
|
|
\keys_set:nn { tblr-element } {#1}
|
|
\ignorespaces
|
|
}
|
|
|
|
\keys_define:nn { tblr-element }
|
|
{
|
|
head .meta:n = { firsthead, middlehead, lasthead },
|
|
foot .meta:n = { firstfoot, middlefoot, lastfoot },
|
|
unknown .code:n = \__tblr_set_element_styles:V \l_keys_key_str,
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_set_element_styles:n #1
|
|
{
|
|
\tl_set:Nn \l__tblr_element_name_tl {#1}
|
|
\keys_set:nV { tblr-style } \l__tblr_element_styles_tl
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_element_styles:n { V }
|
|
|
|
\keys_define:nn { tblr-style }
|
|
{
|
|
halign .code:n = \__tblr_element_gput_style:nn { halign } {#1},
|
|
l .meta:n = { halign = l },
|
|
c .meta:n = { halign = c },
|
|
r .meta:n = { halign = r },
|
|
j .meta:n = { halign = j },
|
|
fg .code:n = \__tblr_element_gput_style:nn { fg } {#1},
|
|
font .code:n = \__tblr_element_gput_style:nn { font } {#1},
|
|
hang .code:n = \__tblr_element_gput_style:nn { hang } {#1},
|
|
indent .code:n = \__tblr_element_gput_style:nn { indent } {#1},
|
|
unknown .code:n = \__tblr_element_unknown_key:Vn \l_keys_key_str {#1},
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_element_gput_style:nn #1 #2
|
|
{
|
|
\__tblr_style_put:en { \l__tblr_element_name_tl / #1 } {#2}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_element_unknown_key:nn #1 #2
|
|
{
|
|
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
|
|
{ \__tblr_style_put:en { \l__tblr_element_name_tl / fg } {#1} }
|
|
{
|
|
%% unknown key name has been changed to string in \l_keys_key_str
|
|
\tl_set_rescan:Nnn \l__tblr_f_tl {} {#1}
|
|
\tl_if_head_eq_catcode:VNTF \l__tblr_f_tl \scan_stop:
|
|
{
|
|
\__tblr_style_put:eV { \l__tblr_element_name_tl / font } \l__tblr_f_tl
|
|
}
|
|
{
|
|
\__tblr_style_put:en { \l__tblr_element_name_tl / #1 } {#2}
|
|
}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_element_unknown_key:nn { Vn }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Helper Functions for Templates}
|
|
%%% --------------------------------------------------------
|
|
|
|
\tl_new:N \l__tblr_template_name_tl
|
|
\tl_new:N \l__tblr_template_code_tl
|
|
|
|
\keys_define:nn { tblr-def-template }
|
|
{
|
|
unknown .code:n = \__tblr_def_template:V \l_keys_key_str,
|
|
}
|
|
|
|
%% #1: head/foot element; #2: template name; #3: template code
|
|
%% If the template name = default, we enable the template at once
|
|
%% Otherwise, we may enable the template by using \SetTblrTemplate command
|
|
\NewDocumentCommand \DefTblrTemplate { m m +m }
|
|
{
|
|
\tl_set:Nn \l__tblr_template_name_tl {#2}
|
|
\tl_set:Nn \l__tblr_template_code_tl {#3}
|
|
\keys_set:nn { tblr-def-template } {#1}
|
|
\ignorespaces
|
|
}
|
|
\cs_new_eq:NN \DeclareTblrTemplate \DefTblrTemplate
|
|
|
|
\cs_new_protected:Npn \__tblr_def_template:n #1
|
|
{
|
|
\tl_set_eq:cN { l__tblr_template_ #1 _ \l__tblr_template_name_tl _tl }
|
|
\l__tblr_template_code_tl
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_def_template:n { V }
|
|
|
|
\keys_define:nn { tblr-set-template }
|
|
{
|
|
unknown .code:n = \__tblr_set_template:V \l_keys_key_str,
|
|
}
|
|
|
|
%% #1: head/foot element; #2: template name
|
|
\NewDocumentCommand \SetTblrTemplate { m m }
|
|
{
|
|
\tl_set:Nn \l__tblr_template_name_tl {#2}
|
|
\keys_set:nn { tblr-set-template } {#1}
|
|
\ignorespaces
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_set_template:n #1
|
|
{
|
|
\tl_set_eq:cc { l__tblr_template_ #1 _default_tl }
|
|
{ l__tblr_template_ #1 _ \l__tblr_template_name_tl _tl }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_set_template:n { V }
|
|
|
|
\NewExpandableDocumentCommand \GetTblrStyle { m m }
|
|
{
|
|
\__tblr_style_item:n { #1 / #2 }
|
|
}
|
|
|
|
\NewDocumentCommand \UseTblrFont { m }
|
|
{
|
|
\GetTblrStyle {#1} { font } \selectfont
|
|
}
|
|
|
|
\tl_new:N \l__tblr_use_color_tl
|
|
|
|
\NewDocumentCommand \UseTblrColor { m }
|
|
{
|
|
\tl_set:Nx \l__tblr_use_color_tl { \GetTblrStyle {#1} { fg } }
|
|
\tl_if_empty:NF \l__tblr_use_color_tl { \color { \l__tblr_use_color_tl } }
|
|
}
|
|
|
|
%% All halign commands are defined at the beginning of the file
|
|
\NewDocumentCommand \UseTblrAlign { m }
|
|
{
|
|
\use:c { __tblr_halign_command_ \GetTblrStyle {#1} { halign } : }
|
|
}
|
|
|
|
\tl_new:N \l__tblr_use_hang_tl
|
|
|
|
\NewDocumentCommand \UseTblrHang { m }
|
|
{
|
|
\tl_set:Nx \l__tblr_use_hang_tl { \GetTblrStyle {#1} { hang } }
|
|
\tl_if_empty:NF \l__tblr_use_hang_tl
|
|
{
|
|
\tl_put_left:Nn \l__tblr_use_hang_tl
|
|
{ \hangafter = 1 \relax \hangindent = }
|
|
\tl_put_right:Nn \l__tblr_use_hang_tl { \relax }
|
|
\exp_args:NV \everypar \l__tblr_use_hang_tl
|
|
}
|
|
}
|
|
|
|
\tl_new:N \l__tblr_use_indent_tl
|
|
|
|
\NewDocumentCommand \UseTblrIndent { m }
|
|
{
|
|
\tl_set:Nx \l__tblr_use_indent_tl { \GetTblrStyle {#1} { indent } }
|
|
\tl_if_empty:NF \l__tblr_use_indent_tl
|
|
{ \exp_args:NNV \setlength \parindent \l__tblr_use_indent_tl }
|
|
}
|
|
|
|
\AtBeginDocument
|
|
{
|
|
\@ifpackageloaded{xcolor}{}{\RenewDocumentCommand \UseTblrColor {m} {}}
|
|
}
|
|
|
|
%% #1: head/foot element; #2: template name
|
|
\NewExpandableDocumentCommand \ExpTblrTemplate { m m }
|
|
{
|
|
\tl_use:c { l__tblr_template_ #1 _ #2 _tl }
|
|
}
|
|
|
|
%% #1: head/foot element; #2: template name
|
|
\NewDocumentCommand \UseTblrTemplate { m m }
|
|
{
|
|
\group_begin:
|
|
\UseTblrFont {#1}
|
|
\UseTblrColor {#1}
|
|
\tl_use:c { l__tblr_template_ #1 _ #2 _tl }
|
|
\group_end:
|
|
}
|
|
|
|
\NewDocumentCommand \MapTblrNotes { +m }
|
|
{
|
|
\__tblr_prop_map_inline:nn { note }
|
|
{
|
|
\tl_set_rescan:Nnn \InsertTblrNoteTag {} {##1}
|
|
\tl_set:Nn \InsertTblrNoteText {##2}
|
|
#1
|
|
}
|
|
}
|
|
|
|
\NewDocumentCommand \MapTblrRemarks { +m }
|
|
{
|
|
\__tblr_prop_map_inline:nn { remark }
|
|
{
|
|
\tl_set_rescan:Nnn \InsertTblrRemarkTag {} {##1}
|
|
\tl_set:Nn \InsertTblrRemarkText {##2}
|
|
#1
|
|
}
|
|
}
|
|
|
|
\NewExpandableDocumentCommand \InsertTblrText { m }
|
|
{
|
|
\__tblr_spec_item:nn { outer } {#1}
|
|
}
|
|
|
|
\NewExpandableDocumentCommand \InsertTblrMore { m }
|
|
{
|
|
\__tblr_prop_item:nn { more } {#1}
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Table Continuation Templates}
|
|
%%% --------------------------------------------------------
|
|
|
|
\tl_if_exist:NF \tblrcontfootname
|
|
{
|
|
\tl_set:Nn \tblrcontfootname { Continued ~ on ~ next ~ page }
|
|
}
|
|
|
|
\tl_if_exist:NF \tblrcontheadname
|
|
{
|
|
\tl_set:Nn \tblrcontheadname { ( Continued ) }
|
|
}
|
|
|
|
\DefTblrTemplate { contfoot-text } { normal } { \tblrcontfootname }
|
|
\SetTblrTemplate { contfoot-text } { normal }
|
|
|
|
\DefTblrTemplate { contfoot } { empty } { }
|
|
\DefTblrTemplate { contfoot } { plain }
|
|
{
|
|
\noindent
|
|
\raggedleft
|
|
\UseTblrTemplate { contfoot-text } { default }
|
|
\par
|
|
}
|
|
\DefTblrTemplate { contfoot } { normal }
|
|
{
|
|
%% need to set parindent after alignment
|
|
\raggedleft
|
|
\UseTblrAlign { contfoot }
|
|
\UseTblrIndent { contfoot }
|
|
\UseTblrHang { contfoot }
|
|
\leavevmode
|
|
\UseTblrTemplate { contfoot-text } { default }
|
|
\par
|
|
}
|
|
\SetTblrTemplate { contfoot } { normal }
|
|
|
|
\DefTblrTemplate { conthead-pre } { empty } { }
|
|
\DefTblrTemplate { conthead-pre } { normal } { \space }
|
|
\SetTblrTemplate { conthead-pre } { normal }
|
|
|
|
\DefTblrTemplate { conthead-text } { normal } { \tblrcontheadname }
|
|
\SetTblrTemplate { conthead-text } { normal }
|
|
|
|
\DefTblrTemplate { conthead } { empty } { }
|
|
\DefTblrTemplate { conthead } { plain }
|
|
{
|
|
\noindent
|
|
\raggedright
|
|
\UseTblrTemplate { conthead-text } { default }
|
|
\par
|
|
}
|
|
\DefTblrTemplate { conthead } { normal }
|
|
{
|
|
%% need to set parindent after alignment
|
|
\raggedright
|
|
\UseTblrAlign { conthead }
|
|
\UseTblrIndent { conthead }
|
|
\UseTblrHang { conthead }
|
|
\leavevmode
|
|
\UseTblrTemplate { conthead-text } { default }
|
|
\par
|
|
}
|
|
\SetTblrTemplate { conthead } { normal }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Table Caption Templates}
|
|
%%% --------------------------------------------------------
|
|
|
|
\tl_new:N \l__tblr_caption_short_tl
|
|
|
|
\DefTblrTemplate { caption-lot } { empty } { }
|
|
\DefTblrTemplate { caption-lot } { normal }
|
|
{
|
|
\tl_if_empty:NTF \lTblrEntryTl
|
|
{ \tl_set_eq:NN \l__tblr_caption_short_tl \lTblrCaptionTl }
|
|
{ \tl_set_eq:NN \l__tblr_caption_short_tl \lTblrEntryTl }
|
|
\addcontentsline { lot } { table }
|
|
{ \protect\numberline { \thetable } { \l__tblr_caption_short_tl } }
|
|
}
|
|
\SetTblrTemplate { caption-lot } { normal }
|
|
|
|
%% We need to use \hspace and \enskip, but not ~ or \space,
|
|
%% since we want a correct hangindent caption paragraph.
|
|
|
|
\DefTblrTemplate { caption-tag } { empty } { }
|
|
\DefTblrTemplate { caption-tag } { normal } { \tablename\hspace{0.25em}\thetable }
|
|
\SetTblrTemplate { caption-tag } { normal }
|
|
|
|
\DefTblrTemplate { caption-sep } { empty } { }
|
|
\DefTblrTemplate { caption-sep } { normal } { : \enskip }
|
|
\SetTblrTemplate { caption-sep } { normal }
|
|
|
|
\DefTblrTemplate { caption-text } { empty } { }
|
|
\DefTblrTemplate { caption-text } { normal } { \InsertTblrText { caption } }
|
|
\SetTblrTemplate { caption-text } { normal }
|
|
|
|
\box_new:N \l__tblr_caption_box
|
|
\box_new:N \l__tblr_caption_left_box
|
|
|
|
\DefTblrTemplate { caption } { empty } { }
|
|
\DefTblrTemplate { caption } { plain }
|
|
{
|
|
\hbox_set:Nn \l__tblr_caption_box
|
|
{
|
|
\UseTblrTemplate { caption-tag } { default }
|
|
\UseTblrTemplate { caption-sep } { default }
|
|
\UseTblrTemplate { caption-text } { default }
|
|
}
|
|
\dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize }
|
|
{
|
|
\noindent
|
|
\hbox_unpack:N \l__tblr_caption_box
|
|
\par
|
|
}
|
|
{
|
|
\centering
|
|
\makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
|
|
\par
|
|
}
|
|
}
|
|
\DefTblrTemplate { caption } { normal }
|
|
{
|
|
\hbox_set:Nn \l__tblr_caption_box
|
|
{
|
|
\UseTblrTemplate { caption-tag } { default }
|
|
\UseTblrTemplate { caption-sep } { default }
|
|
\UseTblrTemplate { caption-text } { default }
|
|
}
|
|
\dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize }
|
|
{
|
|
\UseTblrAlign { caption }
|
|
\UseTblrIndent { caption }
|
|
\hbox_set:Nn \l__tblr_caption_left_box
|
|
{
|
|
\UseTblrTemplate { caption-tag } { default }
|
|
\UseTblrTemplate { caption-sep } { default }
|
|
}
|
|
\hangindent = \box_wd:N \l__tblr_caption_left_box
|
|
\hangafter = 1
|
|
\UseTblrHang { caption }
|
|
\leavevmode
|
|
\hbox_unpack:N \l__tblr_caption_box
|
|
\par
|
|
}
|
|
{
|
|
\centering
|
|
\makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
|
|
\par
|
|
}
|
|
}
|
|
\DefTblrTemplate { caption } { simple }
|
|
{
|
|
\UseTblrAlign { caption }
|
|
\UseTblrIndent { caption }
|
|
\UseTblrHang { caption }
|
|
\leavevmode
|
|
\UseTblrTemplate { caption-tag } { default }
|
|
\UseTblrTemplate { caption-sep } { default }
|
|
\UseTblrTemplate { caption-text } { default }
|
|
\par
|
|
}
|
|
\SetTblrTemplate { caption } { normal }
|
|
|
|
\DefTblrTemplate { capcont } { empty } { }
|
|
\DefTblrTemplate { capcont } { plain }
|
|
{
|
|
\hbox_set:Nn \l__tblr_caption_box
|
|
{
|
|
\UseTblrTemplate { caption-tag } { default }
|
|
\UseTblrTemplate { caption-sep } { default }
|
|
\UseTblrTemplate { caption-text } { default }
|
|
\UseTblrTemplate { conthead-pre } { default }
|
|
\UseTblrTemplate { conthead-text } { default }
|
|
}
|
|
\dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize }
|
|
{
|
|
\noindent
|
|
\hbox_unpack:N \l__tblr_caption_box
|
|
\par
|
|
}
|
|
{
|
|
\centering
|
|
\makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
|
|
\par
|
|
}
|
|
}
|
|
\DefTblrTemplate { capcont } { normal }
|
|
{
|
|
\hbox_set:Nn \l__tblr_caption_box
|
|
{
|
|
\UseTblrTemplate { caption-tag } { default }
|
|
\UseTblrTemplate { caption-sep } { default }
|
|
\UseTblrTemplate { caption-text } { default }
|
|
\UseTblrTemplate { conthead-pre } { default }
|
|
\UseTblrTemplate { conthead-text } { default }
|
|
}
|
|
\dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize }
|
|
{
|
|
\UseTblrAlign { capcont }
|
|
\UseTblrIndent { capcont }
|
|
\hbox_set:Nn \l__tblr_caption_left_box
|
|
{
|
|
\UseTblrTemplate { caption-tag } { default }
|
|
\UseTblrTemplate { caption-sep } { default }
|
|
}
|
|
\hangindent = \box_wd:N \l__tblr_caption_left_box
|
|
\hangafter = 1
|
|
\UseTblrHang { capcont }
|
|
\leavevmode
|
|
\hbox_unpack:N \l__tblr_caption_box
|
|
\par
|
|
}
|
|
{
|
|
\centering
|
|
\makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
|
|
\par
|
|
}
|
|
}
|
|
\DefTblrTemplate { capcont } { simple }
|
|
{
|
|
\UseTblrAlign { caption }
|
|
\UseTblrIndent { caption }
|
|
\UseTblrHang { caption }
|
|
\leavevmode
|
|
\UseTblrTemplate { caption-tag } { default }
|
|
\UseTblrTemplate { caption-sep } { default }
|
|
\UseTblrTemplate { caption-text } { default }
|
|
\UseTblrTemplate { conthead-pre } { default }
|
|
\UseTblrTemplate { conthead-text } { default }
|
|
\par
|
|
}
|
|
\SetTblrTemplate { capcont} { normal }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Table Notes Templates}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% By default the targets generated by \hypertarget are too low
|
|
%% Therefore we need to use \Hy@raisedlink command to fix this problem
|
|
%% See https://tex.stackexchange.com/questions/17057
|
|
%% We also use \use:c in case the private command \Hy@raisedlink is removed
|
|
\cs_new_protected:Npn \__tblr_hyper_target:n #1
|
|
{
|
|
\cs_if_exist:NT \hypertarget
|
|
{
|
|
\use:c { Hy@raisedlink }
|
|
{
|
|
\hypertarget
|
|
{ tblr / \int_use:N \g__tblr_table_count_int / \tl_to_str:n {#1} }
|
|
{ }
|
|
}
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_hyper_target:n { V }
|
|
|
|
\cs_new_protected:Npn \__tblr_hyper_link:nn #1 #2
|
|
{
|
|
\cs_if_exist:NTF \hyperlink
|
|
{
|
|
\hyperlink
|
|
{ tblr / \int_use:N \g__tblr_table_count_int / \tl_to_str:n {#1} }
|
|
{ #2 }
|
|
}
|
|
{ #2 }
|
|
}
|
|
|
|
\DefTblrTemplate { note-border } { empty }
|
|
{
|
|
\hypersetup { pdfborder = { 0 ~ 0 ~ 0 } }
|
|
}
|
|
\DefTblrTemplate { note-border } { normal }
|
|
{
|
|
\hypersetup { pdfborder = { 0 ~ 0 ~ 1 } }
|
|
}
|
|
\SetTblrTemplate { note-border } { empty }
|
|
|
|
\cs_set_eq:NN \TblrOverlap \rlap
|
|
|
|
\NewDocumentCommand \TblrNote { m }
|
|
{
|
|
\cs_if_exist:NT \hypersetup { \ExpTblrTemplate { note-border }{ default } }
|
|
\TblrOverlap
|
|
{
|
|
\__tblr_hyper_link:nn {#1}
|
|
{ \textsuperscript { \sffamily \UseTblrFont { note-tag } #1 } }
|
|
}
|
|
}
|
|
|
|
\DefTblrTemplate { note-tag } { empty } { }
|
|
\DefTblrTemplate { note-tag } { normal }
|
|
{
|
|
\textsuperscript { \sffamily \UseTblrFont { note-tag } \InsertTblrNoteTag }
|
|
}
|
|
\SetTblrTemplate { note-tag } { normal }
|
|
|
|
\DefTblrTemplate { note-target } { normal }
|
|
{
|
|
\__tblr_hyper_target:V \InsertTblrNoteTag
|
|
}
|
|
\SetTblrTemplate { note-target } { normal }
|
|
|
|
\DefTblrTemplate { note-sep } { empty } { }
|
|
\DefTblrTemplate { note-sep } { normal } { \space }
|
|
\SetTblrTemplate { note-sep } { normal }
|
|
|
|
\DefTblrTemplate { note-text } { empty } { }
|
|
\DefTblrTemplate { note-text } { normal } { \InsertTblrNoteText }
|
|
\SetTblrTemplate { note-text } { normal }
|
|
|
|
\DefTblrTemplate { note } { empty } { }
|
|
\DefTblrTemplate { note } { plain }
|
|
{
|
|
\MapTblrNotes
|
|
{
|
|
\noindent
|
|
\UseTblrTemplate { note-tag } { default }
|
|
\UseTblrTemplate { note-target } { default }
|
|
\UseTblrTemplate { note-sep } { default }
|
|
\UseTblrTemplate { note-text } { default }
|
|
\par
|
|
}
|
|
}
|
|
\DefTblrTemplate { note } { normal }
|
|
{
|
|
\UseTblrAlign { note }
|
|
\UseTblrIndent { note }
|
|
\MapTblrNotes
|
|
{
|
|
\hangindent = 0.7em
|
|
\hangafter = 1
|
|
\UseTblrHang { note }
|
|
\leavevmode
|
|
\hbox_to_wd:nn { \the\hangindent }
|
|
{
|
|
\UseTblrTemplate { note-tag } { default }
|
|
\UseTblrTemplate { note-target } { default }
|
|
\hfil
|
|
}
|
|
\UseTblrTemplate { note-text } { default }
|
|
\par
|
|
}
|
|
}
|
|
\DefTblrTemplate { note } { inline }
|
|
{
|
|
\UseTblrAlign { note }
|
|
\UseTblrIndent { note }
|
|
\UseTblrHang { note }
|
|
\leavevmode
|
|
\MapTblrNotes
|
|
{
|
|
\UseTblrTemplate { note-tag } { default }
|
|
\UseTblrTemplate { note-target } { default }
|
|
\UseTblrTemplate { note-sep } { default }
|
|
\UseTblrTemplate { note-text } { default }
|
|
\quad
|
|
}
|
|
\par
|
|
}
|
|
\SetTblrTemplate { note } { normal }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Table Remarks Templates}
|
|
%%% --------------------------------------------------------
|
|
|
|
\DefTblrTemplate { remark-tag } { empty } { }
|
|
\DefTblrTemplate { remark-tag } { normal }
|
|
{
|
|
\itshape \UseTblrFont { remark-tag } \InsertTblrRemarkTag
|
|
}
|
|
\SetTblrTemplate { remark-tag } { normal }
|
|
|
|
\DefTblrTemplate { remark-sep } { empty } { }
|
|
\DefTblrTemplate { remark-sep } { normal } { : \space }
|
|
\SetTblrTemplate { remark-sep } { normal }
|
|
|
|
\DefTblrTemplate { remark-text } { empty } { }
|
|
\DefTblrTemplate { remark-text } { normal } { \InsertTblrRemarkText }
|
|
\SetTblrTemplate { remark-text } { normal }
|
|
|
|
\DefTblrTemplate { remark } { empty } { }
|
|
\DefTblrTemplate { remark } { plain }
|
|
{
|
|
\MapTblrRemarks
|
|
{
|
|
\noindent
|
|
\UseTblrTemplate { remark-tag } { default }
|
|
\UseTblrTemplate { remark-sep } { default }
|
|
\UseTblrTemplate { remark-text } { default }
|
|
\par
|
|
}
|
|
}
|
|
\DefTblrTemplate { remark } { normal }
|
|
{
|
|
\UseTblrAlign { remark }
|
|
\UseTblrIndent { remark }
|
|
\MapTblrRemarks
|
|
{
|
|
\hangindent = 0.7em
|
|
\hangafter = 1
|
|
\UseTblrHang { remark }
|
|
\leavevmode
|
|
\UseTblrTemplate { remark-tag } { default }
|
|
\UseTblrTemplate { remark-sep } { default }
|
|
\UseTblrTemplate { remark-text } { default }
|
|
\par
|
|
}
|
|
}
|
|
\DefTblrTemplate { remark } { inline }
|
|
{
|
|
\UseTblrAlign { remark }
|
|
\UseTblrIndent { remark }
|
|
\UseTblrHang { remark }
|
|
\leavevmode
|
|
\MapTblrRemarks
|
|
{
|
|
\UseTblrTemplate { remark-tag } { default }
|
|
\UseTblrTemplate { remark-sep } { default }
|
|
\UseTblrTemplate { remark-text } { default }
|
|
\quad
|
|
}
|
|
\par
|
|
}
|
|
\SetTblrTemplate { remark } { normal }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Header and Footer Templates}
|
|
%%% --------------------------------------------------------
|
|
|
|
\tl_new:N \g__tblr_template_firsthead_default_tl
|
|
\tl_new:N \g__tblr_template_middlehead_default_tl
|
|
\tl_new:N \g__tblr_template_lasthead_default_tl
|
|
\tl_new:N \g__tblr_template_firstfoot_default_tl
|
|
\tl_new:N \g__tblr_template_middlefoot_default_tl
|
|
\tl_new:N \g__tblr_template_lastfoot_default_tl
|
|
|
|
\keys_define:nn { tblr-def-template }
|
|
{
|
|
head .meta:n = { firsthead, middlehead, lasthead },
|
|
foot .meta:n = { firstfoot, middlefoot, lastfoot },
|
|
}
|
|
|
|
\keys_define:nn { tblr-set-template }
|
|
{
|
|
head .meta:n = { firsthead, middlehead, lasthead },
|
|
foot .meta:n = { firstfoot, middlefoot, lastfoot },
|
|
}
|
|
|
|
\DefTblrTemplate { head } { empty } { }
|
|
\DefTblrTemplate { foot } { empty } { }
|
|
|
|
\DefTblrTemplate { firsthead } { normal }
|
|
{
|
|
\UseTblrTemplate { caption } { default }
|
|
}
|
|
|
|
\DefTblrTemplate { middlehead, lasthead } { normal }
|
|
{
|
|
\UseTblrTemplate { capcont } { default }
|
|
}
|
|
|
|
\DefTblrTemplate { firstfoot, middlefoot } { normal }
|
|
{
|
|
\UseTblrTemplate { contfoot } { default }
|
|
}
|
|
|
|
\DefTblrTemplate { lastfoot } { normal }
|
|
{
|
|
\UseTblrTemplate { note } { default }
|
|
\UseTblrTemplate { remark } { default }
|
|
}
|
|
|
|
\SetTblrTemplate { head } { normal }
|
|
\SetTblrTemplate { foot } { normal }
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Build the Whole Table}
|
|
%%% --------------------------------------------------------
|
|
|
|
\cs_new:Npn \__tblr_box_height:N #1
|
|
{
|
|
\dim_eval:n { \box_ht:N #1 + \box_dp:N #1 }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_build_head_foot:
|
|
{
|
|
\__tblr_build_row_head_foot:
|
|
\__tblr_build_table_head_foot:
|
|
}
|
|
|
|
\tl_new:N \l__tblr_row_head_tl
|
|
\tl_new:N \l__tblr_row_foot_tl
|
|
\box_new:N \l__tblr_row_head_box
|
|
\box_new:N \l__tblr_row_foot_box
|
|
\dim_new:N \l__tblr_row_head_foot_dim
|
|
|
|
\cs_new_protected:Npn \__tblr_build_row_head_foot:
|
|
{
|
|
%% \l__tblr_row_head_tl and \l__tblr_row_foot_tl may be empty
|
|
\tl_set:Nx \l__tblr_row_head_tl { \__tblr_prop_item:ne { inner } { rowhead } }
|
|
\int_compare:nNnTF { \l__tblr_row_head_tl + 0 } > { 0 }
|
|
{
|
|
\__tblr_build_one_table:nnNN {1} { \l__tblr_row_head_tl }
|
|
\c_true_bool \c_true_bool
|
|
}
|
|
{ \__tblr_build_one_hline:n {1} }
|
|
\box_set_eq:NN \l__tblr_row_head_box \l__tblr_table_box
|
|
\tl_set:Nx \l__tblr_row_foot_tl { \__tblr_prop_item:ne { inner } { rowfoot } }
|
|
\int_compare:nNnTF { \l__tblr_row_foot_tl + 0 } > { 0 }
|
|
{
|
|
\__tblr_build_one_table:nnNN
|
|
{ \c@rowcount - \l__tblr_row_foot_tl + 1 } { \c@rowcount }
|
|
\c_true_bool \c_true_bool
|
|
}
|
|
{ \__tblr_build_one_hline:n { \int_eval:n { \c@rowcount + 1 } } }
|
|
\box_set_eq:NN \l__tblr_row_foot_box \l__tblr_table_box
|
|
\dim_set:Nn \l__tblr_row_head_foot_dim
|
|
{
|
|
\__tblr_box_height:N \l__tblr_row_head_box
|
|
+ \__tblr_box_height:N \l__tblr_row_foot_box
|
|
}
|
|
}
|
|
|
|
\dim_new:N \tablewidth
|
|
|
|
\cs_new_protected:Npn \__tblr_get_table_width:
|
|
{
|
|
\dim_zero:N \tablewidth
|
|
\int_step_inline:nn { \c@colcount }
|
|
{
|
|
\dim_add:Nn \tablewidth
|
|
{
|
|
\__tblr_spec_item:nn { vline } { [##1] / @vline-width }
|
|
+
|
|
\__tblr_data_item:nnn { column } {##1} { leftsep }
|
|
+
|
|
\__tblr_data_item:nnn { column } {##1} { @col-width }
|
|
+
|
|
\__tblr_data_item:nnn { column } {##1} { rightsep }
|
|
}
|
|
}
|
|
\dim_add:Nn \tablewidth
|
|
{
|
|
\__tblr_spec_item:ne { vline }
|
|
{ [\int_eval:n { \c@colcount + 1 }] / @vline-width }
|
|
}
|
|
}
|
|
|
|
\box_new:N \l__tblr_table_firsthead_box
|
|
\box_new:N \l__tblr_table_middlehead_box
|
|
\box_new:N \l__tblr_table_lasthead_box
|
|
\box_new:N \l__tblr_table_firstfoot_box
|
|
\box_new:N \l__tblr_table_middlefoot_box
|
|
\box_new:N \l__tblr_table_lastfoot_box
|
|
|
|
\cs_new_protected:Npn \__tblr_build_table_head_foot:
|
|
{
|
|
\__tblr_get_table_width:
|
|
% make each of \lTblrCaptionTl, \lTblrEntryTl, \lTblrLabelTl and the
|
|
% three corresponding booleans available in all head-foot templates
|
|
\__tblr_set_table_label_entry:
|
|
\__tblr_build_table_head_aux:Nn \l__tblr_table_firsthead_box
|
|
{
|
|
\__tblr_build_table_label_entry:
|
|
\UseTblrTemplate { firsthead } { default }
|
|
}
|
|
\__tblr_build_table_head_aux:Nn \l__tblr_table_middlehead_box
|
|
{
|
|
\UseTblrTemplate { middlehead } { default }
|
|
}
|
|
\__tblr_build_table_head_aux:Nn \l__tblr_table_lasthead_box
|
|
{
|
|
\UseTblrTemplate { lasthead } { default }
|
|
}
|
|
\__tblr_build_table_foot_aux:Nn \l__tblr_table_firstfoot_box
|
|
{
|
|
\UseTblrTemplate { firstfoot } { default }
|
|
}
|
|
\__tblr_build_table_foot_aux:Nn \l__tblr_table_middlefoot_box
|
|
{
|
|
\UseTblrTemplate { middlefoot } { default }
|
|
}
|
|
\__tblr_build_table_foot_aux:Nn \l__tblr_table_lastfoot_box
|
|
{
|
|
\UseTblrTemplate { lastfoot } { default }
|
|
}
|
|
}
|
|
|
|
\bool_new:N \l__tblr_table_no_title_bool
|
|
\bool_new:N \l__tblr_table_no_entry_bool
|
|
\bool_new:N \l__tblr_table_no_label_bool
|
|
\tl_const:Nn \c_tblr_none_tl { none }
|
|
|
|
\cs_new_protected:Npn \__tblr_set_table_label_entry:
|
|
{
|
|
\tl_set:Nx \lTblrCaptionTl { \InsertTblrText { caption } }
|
|
\tl_set:Nx \lTblrEntryTl { \InsertTblrText { entry } }
|
|
\tl_set:Nx \lTblrLabelTl { \InsertTblrText { label } }
|
|
\bool_set:Nn \l__tblr_table_no_title_bool
|
|
{ \tl_if_empty_p:N \lTblrCaptionTl }
|
|
\bool_set:Nn \l__tblr_table_no_entry_bool
|
|
{ \tl_if_eq_p:NN \lTblrEntryTl \c_tblr_none_tl }
|
|
\bool_set:Nn \l__tblr_table_no_label_bool
|
|
{ \tl_if_eq_p:NN \lTblrLabelTl \c_tblr_none_tl }
|
|
\bool_if:NT \l__tblr_table_no_title_bool
|
|
{
|
|
\SetTblrTemplate { conthead-pre } { empty }
|
|
}
|
|
\bool_if:NT \l__tblr_table_no_label_bool
|
|
{
|
|
\SetTblrTemplate { caption-tag }{ empty }
|
|
\SetTblrTemplate { caption-sep }{ empty }
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_build_tall_table_head_foot:
|
|
{
|
|
\__tblr_get_table_width:
|
|
\__tblr_set_table_label_entry:
|
|
\__tblr_build_table_head_aux:Nn \l__tblr_table_firsthead_box
|
|
{
|
|
\__tblr_build_table_label_entry:
|
|
\UseTblrTemplate { firsthead } { default }
|
|
}
|
|
\__tblr_build_table_foot_aux:Nn
|
|
\l__tblr_table_lastfoot_box { \UseTblrTemplate { lastfoot } { default } }
|
|
}
|
|
|
|
\tl_new:N \lTblrCaptionTl
|
|
\tl_new:N \lTblrEntryTl
|
|
\tl_new:N \lTblrLabelTl
|
|
\clist_new:N \lTblrRefMoreClist
|
|
|
|
\cs_new_protected:Npn \__tblr_build_table_label_entry:
|
|
{
|
|
\bool_if:NF \l__tblr_table_no_label_bool
|
|
{
|
|
\refstepcounter { table }
|
|
\tl_if_empty:NF \lTblrLabelTl
|
|
{
|
|
\clist_map_inline:Nn \lTblrRefMoreClist
|
|
{ \ExpTblrTemplate { caption-ref } { ##1 } }
|
|
\exp_args:NV \label \lTblrLabelTl
|
|
}
|
|
}
|
|
%% We put caption-lot code at last, so that a user can modify \lTblrEntryTl
|
|
%% in a caption-label template. For example, a user may want to use
|
|
%% short caption in nameref, but at the same time not to add LoT entry.
|
|
\bool_if:NF \l__tblr_table_no_entry_bool
|
|
{ \UseTblrTemplate { caption-lot } { default } }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_build_table_head_aux:Nn #1 #2
|
|
{
|
|
\vbox_set:Nn #1
|
|
{
|
|
\hsize = \tablewidth
|
|
\TblrParboxRestore % it will set \linewidth = \hsize
|
|
\vbox_set:Nn \l_tmpa_box {#2}
|
|
\box_use:N \l_tmpa_box
|
|
\dim_compare:nNnT
|
|
{ \box_ht:N \l_tmpa_box + \box_dp:N \l_tmpa_box } > { 0pt }
|
|
{ \skip_vertical:n { \__tblr_spec_item:nn { outer } { headsep } } }
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_build_table_foot_aux:Nn #1 #2
|
|
{
|
|
\vbox_set:Nn #1
|
|
{
|
|
\hsize = \tablewidth
|
|
\TblrParboxRestore % it will set \linewidth = \hsize
|
|
\vbox_set:Nn \l_tmpb_box {#2}
|
|
\dim_compare:nNnT
|
|
{ \box_ht:N \l_tmpb_box + \box_dp:N \l_tmpb_box } > { 0pt }
|
|
{ \skip_vertical:n { \__tblr_spec_item:nn { outer } { footsep } } }
|
|
\box_use:N \l_tmpb_box
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_build_whole:
|
|
{
|
|
\tl_if_eq:enTF { \__tblr_spec_item:nn { outer } { long } } { true }
|
|
{ \__tblr_build_long_table:e { \__tblr_spec_item:nn { outer } { halign } } }
|
|
{
|
|
\tl_if_eq:enTF { \__tblr_spec_item:nn { outer } { tall } } { true }
|
|
{
|
|
\__tblr_build_tall_table:e
|
|
{ \__tblr_spec_item:nn { outer } { baseline } }
|
|
}
|
|
{
|
|
\__tblr_build_short_table:e
|
|
{ \__tblr_spec_item:nn { outer } { baseline } }
|
|
}
|
|
}
|
|
}
|
|
|
|
\dim_new:N \l__tblr_remain_height_dim
|
|
\int_new:N \l__tblr_long_from_int
|
|
\int_new:N \l__tblr_long_to_int
|
|
\int_new:N \l__tblr_curr_i_int
|
|
\int_new:N \l__tblr_prev_i_int
|
|
\int_new:N \l__tblr_table_page_int
|
|
\bool_new:N \l__tblr_page_break_curr_bool
|
|
\bool_new:N \l__tblr_page_break_prev_bool
|
|
|
|
%% #1: table alignment
|
|
%% For long table, we need to leave hmode first to get correct \pagetotal
|
|
%% Also remove topskip and presep if we are at the beginning of the page
|
|
\cs_new_protected:Npn \__tblr_build_long_table:n #1
|
|
{
|
|
\LogTblrTracing { page }
|
|
\par
|
|
\skip_zero:N \parskip % see issue #203
|
|
\LogTblrTracing { page }
|
|
\dim_compare:nNnTF { \pagegoal } = { \maxdimen }
|
|
{ \hbox{}\kern-\topskip\nobreak }
|
|
{ \skip_vertical:n { \__tblr_spec_item:nn { outer } { presep } } }
|
|
\LogTblrTracing { page }
|
|
\nointerlineskip
|
|
\mode_leave_vertical: % enter horizontal mode to update \pagetotal
|
|
\LogTblrTracing { page }
|
|
\hrule height ~ 0pt
|
|
\nobreak % prevent page break after \hrule (see issue #42)
|
|
\LogTblrTracing { page }
|
|
\int_set:Nn \l__tblr_table_page_int {1}
|
|
\__tblr_build_head_foot:
|
|
\dim_set:Nn \l__tblr_remain_height_dim
|
|
{ \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim }
|
|
\int_set:Nn \l__tblr_long_from_int { \l__tblr_row_head_tl + 1 }
|
|
\int_set:Nn \l__tblr_long_to_int { \c@rowcount - ( \l__tblr_row_foot_tl + 0 ) }
|
|
\int_set:Nn \l__tblr_curr_i_int { \l__tblr_long_from_int - 1 }
|
|
\int_do_while:nNnn { \l__tblr_curr_i_int } < { \l__tblr_long_to_int }
|
|
{
|
|
\int_set_eq:NN \l__tblr_prev_i_int \l__tblr_curr_i_int
|
|
\__tblr_get_next_table_rows:NNNN
|
|
\l__tblr_long_to_int \l__tblr_curr_i_int
|
|
\l_tmpa_dim \l__tblr_page_break_curr_bool
|
|
\__tblr_check_table_page_break:NNN
|
|
\l__tblr_remain_height_dim \l_tmpa_dim \l__tblr_page_break_prev_bool
|
|
\__tblr_do_if_tracing:nn { page } { \int_log:N \l__tblr_curr_i_int }
|
|
\bool_if:NTF \l__tblr_page_break_prev_bool
|
|
{
|
|
\int_compare:nNnTF
|
|
{ \l__tblr_long_from_int } > { \l__tblr_prev_i_int }
|
|
{
|
|
% See issue #42: if longtblr starts at the bottom of a page,
|
|
% \pagetotal maybe exceed \pagegoal after adding presep,
|
|
% or after adding rowhead or rowfoot of the table.
|
|
% In these cases, we will not typeset table in this page,
|
|
% but rather do some negative \vskip and execute \newpage.
|
|
\skip_vertical:n { \pagegoal - \pagetotal }
|
|
}
|
|
{
|
|
\__tblr_build_page_table:nnx {#1}
|
|
{ \int_use:N \l__tblr_long_from_int }
|
|
{ \int_use:N \l__tblr_prev_i_int }
|
|
\int_incr:N \l__tblr_table_page_int
|
|
\int_set:Nn \l__tblr_long_from_int { \l__tblr_prev_i_int + 1 }
|
|
}
|
|
\TblrNewPage
|
|
\hbox{}\kern-\topskip\nobreak
|
|
\noindent
|
|
\LogTblrTracing { page }
|
|
\dim_set:Nn \l__tblr_remain_height_dim
|
|
{ \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim - \l_tmpa_dim }
|
|
}
|
|
{
|
|
\bool_if:NTF \l__tblr_page_break_curr_bool
|
|
{
|
|
\__tblr_build_page_table:nnx {#1}
|
|
{ \int_use:N \l__tblr_long_from_int }
|
|
{ \int_use:N \l__tblr_curr_i_int }
|
|
\int_incr:N \l__tblr_table_page_int
|
|
\TblrNewPage
|
|
\hbox{}\kern-\topskip\nobreak
|
|
\noindent
|
|
\LogTblrTracing { page }
|
|
\dim_set:Nn \l__tblr_remain_height_dim
|
|
{ \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim }
|
|
\int_set:Nn \l__tblr_long_from_int { \l__tblr_curr_i_int + 1 }
|
|
}
|
|
{ \dim_add:Nn \l__tblr_remain_height_dim { -\l_tmpa_dim } }
|
|
}
|
|
}
|
|
\int_compare:nNnTF { \l__tblr_table_page_int } = {1}
|
|
{
|
|
\box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_firsthead_box
|
|
\box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_lastfoot_box
|
|
}
|
|
{
|
|
\box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_lasthead_box
|
|
\box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_lastfoot_box
|
|
}
|
|
\__tblr_build_page_table:nnn {#1}
|
|
{ \int_use:N \l__tblr_long_from_int } { \int_use:N \l__tblr_long_to_int }
|
|
\skip_vertical:n { \__tblr_spec_item:nn { outer } { postsep } }
|
|
% In the past we used "\hrule height ~ 0pt" to get strict postsep,
|
|
% but the postsep was not discarded when page breaks, see issue #39.
|
|
% Therefore we use \nointerlineskip here.
|
|
\nointerlineskip
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_build_long_table:n { e }
|
|
|
|
%% #1: int with index of the last row; #2: int with index of current row;
|
|
%% #3: row dimension; #4: break page or not.
|
|
\cs_new_protected:Npn \__tblr_get_next_table_rows:NNNN #1 #2 #3 #4
|
|
{
|
|
\bool_set_true:N \l_tmpa_bool
|
|
\dim_zero:N #3
|
|
\bool_set_false:N #4
|
|
\bool_while_do:Nn \l_tmpa_bool
|
|
{
|
|
\int_incr:N #2
|
|
\dim_add:Nn #3
|
|
{
|
|
\__tblr_data_item:nen { row } { \int_use:N #2 } { abovesep }
|
|
+
|
|
\__tblr_data_item:nen { row } { \int_use:N #2 } { @row-height }
|
|
+
|
|
\__tblr_data_item:nen { row } { \int_use:N #2 } { belowsep }
|
|
+
|
|
\__tblr_spec_item:ne { hline }
|
|
{ [ \int_eval:n { #2 + 1 } ] / @hline-height }
|
|
}
|
|
\int_compare:nNnTF {#2} < {#1}
|
|
{
|
|
\tl_set:Nx \l__tblr_b_tl
|
|
{
|
|
\__tblr_spec_item:ne { hline }
|
|
{ [ \int_eval:n { #2 + 1 } ] / @pagebreak }
|
|
}
|
|
% Note that \l__tblr_b_tl may be empty
|
|
\int_compare:nNnTF { \l__tblr_b_tl + 0 } < { 0 }
|
|
{ \bool_set_true:N \l_tmpa_bool }
|
|
{
|
|
\bool_set_false:N \l_tmpa_bool
|
|
\int_compare:nNnT { \l__tblr_b_tl + 0 } > { 0 }
|
|
{ \bool_set_true:N #4 }
|
|
}
|
|
}
|
|
{ \bool_set_false:N \l_tmpa_bool }
|
|
}
|
|
}
|
|
|
|
\box_new:N \l__tblr_table_head_box
|
|
\box_new:N \l__tblr_table_foot_box
|
|
\dim_new:N \l__tblr_table_head_foot_dim
|
|
\dim_new:N \l__tblr_table_head_body_foot_dim
|
|
|
|
%% #1: remain dimension; #2: row dimension; #3: break page or not
|
|
\cs_new_protected:Npn \__tblr_check_table_page_break:NNN #1 #2 #3
|
|
{
|
|
\int_compare:nNnTF { \l__tblr_table_page_int } = {1}
|
|
{
|
|
\dim_set:Nn \l__tblr_table_head_body_foot_dim
|
|
{
|
|
\__tblr_box_height:N \l__tblr_table_firsthead_box
|
|
+ #2 + \__tblr_box_height:N \l__tblr_table_firstfoot_box
|
|
}
|
|
\box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_firsthead_box
|
|
\dim_compare:nNnTF
|
|
{ \l__tblr_table_head_body_foot_dim } > {#1}
|
|
{
|
|
\bool_set_true:N #3
|
|
\box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_firstfoot_box
|
|
}
|
|
{ \bool_set_false:N #3 }
|
|
}
|
|
{
|
|
\dim_set:Nn \l__tblr_table_head_body_foot_dim
|
|
{
|
|
\__tblr_box_height:N \l__tblr_table_middlehead_box
|
|
+ #2 + \__tblr_box_height:N \l__tblr_table_middlefoot_box
|
|
}
|
|
\box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_middlehead_box
|
|
\dim_compare:nNnTF
|
|
{ \l__tblr_table_head_body_foot_dim } > {#1}
|
|
{
|
|
\bool_set_true:N #3
|
|
\box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_middlefoot_box
|
|
}
|
|
{ \bool_set_false:N #3 }
|
|
}
|
|
}
|
|
|
|
\box_new:N \l__tblr_table_box
|
|
|
|
%% #1: table alignment; #2: row from; #3: row to
|
|
\cs_new_protected:Npn \__tblr_build_page_table:nnn #1 #2 #3
|
|
{
|
|
\__tblr_build_one_table:nnNN {#2} {#3} \c_false_bool \c_false_bool
|
|
\vbox_set:Nn \l__tblr_table_box
|
|
{
|
|
\box_use:N \l__tblr_table_head_box
|
|
\__tblr_cover_two_vboxes:NN \l__tblr_row_head_box \l__tblr_table_box
|
|
\box_use:N \l__tblr_row_foot_box
|
|
\hrule height ~ 0pt
|
|
\box_use:N \l__tblr_table_foot_box
|
|
}
|
|
\__tblr_halign_whole:Nn \l__tblr_table_box {#1}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_build_page_table:nnn { nnx }
|
|
|
|
%% To solve the problem of missing hlines of long tables in some PDF readers,
|
|
%% We need to draw body rows before head rows (see issue #88).
|
|
\cs_new_protected:Npn \__tblr_cover_two_vboxes:NN #1 #2
|
|
{
|
|
\dim_set:Nn \l_tmpa_dim { \box_ht:N #1 + \box_dp:N #1 }
|
|
\dim_set:Nn \l_tmpb_dim { \box_ht:N #2 + \box_dp:N #2 }
|
|
\skip_vertical:N \l_tmpa_dim
|
|
\hrule height ~ 0pt
|
|
\box_use:N #2
|
|
\skip_vertical:n { - \l_tmpa_dim - \l_tmpb_dim }
|
|
\hrule height ~ 0pt
|
|
\box_use:N #1
|
|
\skip_vertical:N \l_tmpb_dim
|
|
\hrule height ~ 0pt
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_halign_whole:Nn #1 #2
|
|
{
|
|
\noindent
|
|
\hbox_to_wd:nn { \linewidth }
|
|
{
|
|
\tl_if_eq:nnF {#2} {l} { \hfil }
|
|
\box_use:N #1
|
|
\tl_if_eq:nnF {#2} {r} { \hfil }
|
|
}
|
|
}
|
|
|
|
%% #1: table alignment
|
|
%% For tall table, we need to leave vmode first.
|
|
%% Since there may be \centering in table environment,
|
|
%% We use \raggedright to reset alignement for table head/foot.
|
|
\cs_new_protected:Npn \__tblr_build_tall_table:n #1
|
|
{
|
|
\mode_leave_vertical:
|
|
\__tblr_build_tall_table_head_foot:
|
|
\__tblr_build_one_table:nnNN {1} {\c@rowcount} \c_true_bool \c_true_bool
|
|
\vbox_set:Nn \l__tblr_table_box
|
|
{
|
|
\box_use:N \l__tblr_table_firsthead_box
|
|
\hrule height ~ 0pt
|
|
\box_use:N \l__tblr_table_box
|
|
\hrule height ~ 0pt
|
|
\box_use:N \l__tblr_table_lastfoot_box
|
|
}
|
|
\__tblr_valign_whole:Nn \l__tblr_table_box {#1}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_build_tall_table:n { e }
|
|
|
|
%% #1: table alignment
|
|
%% For short table, we need to leave vmode first
|
|
\cs_new_protected:Npn \__tblr_build_short_table:n #1
|
|
{
|
|
\mode_leave_vertical:
|
|
\__tblr_build_one_table:nnNN {1} {\c@rowcount} \c_true_bool \c_true_bool
|
|
\__tblr_valign_whole:Nn \l__tblr_table_box {#1}
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_build_short_table:n { e }
|
|
|
|
\box_new:N \l__tblr_table_hlines_box
|
|
\box_new:N \l__tblr_hline_box
|
|
\box_new:N \l__tblr_row_box
|
|
|
|
%% #1: row from; #2: row to
|
|
%% #3: whether build first hline or not; #4: whether build last hline or not
|
|
%% To fix disappeared hlines with colorful tables in Adobe Reader (see #76),
|
|
%% we collect all hlines and draw them at the end of the table.
|
|
\cs_new_protected:Npn \__tblr_build_one_table:nnNN #1 #2 #3 #4
|
|
{
|
|
\box_clear:N \l__tblr_table_hlines_box
|
|
\vbox_set:Nn \l__tblr_table_box
|
|
{
|
|
\int_step_variable:nnNn {#1} {#2} \l__tblr_i_tl
|
|
{
|
|
\bool_lazy_or:nnT
|
|
{ \int_compare_p:nNn { \l__tblr_i_tl } > {#1} }
|
|
{ \bool_if_p:N #3 }
|
|
{ \__tblr_put_one_hline:n { \__tblr_build_hline:V \l__tblr_i_tl } }
|
|
\hrule height ~ 0pt % remove lineskip between hlines and rows
|
|
\__tblr_put_one_row:n { \__tblr_build_row:N \l__tblr_i_tl }
|
|
\hrule height ~ 0pt
|
|
}
|
|
\bool_if:NT #4
|
|
{
|
|
\__tblr_put_one_hline:n
|
|
{ \__tblr_build_hline:n { \int_eval:n {#2 + 1} } }
|
|
}
|
|
\skip_vertical:n
|
|
{
|
|
- \box_ht:N \l__tblr_table_hlines_box
|
|
- \box_dp:N \l__tblr_table_hlines_box
|
|
}
|
|
\box_use:N \l__tblr_table_hlines_box
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_put_one_hline:n #1
|
|
{
|
|
\hbox_set:Nn \l__tblr_hline_box {#1}
|
|
\skip_vertical:n { \box_ht:N \l__tblr_hline_box + \box_dp:N \l__tblr_hline_box }
|
|
\vbox_set:Nn \l__tblr_table_hlines_box
|
|
{
|
|
\vbox_unpack:N \l__tblr_table_hlines_box
|
|
\box_use:N \l__tblr_hline_box
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_put_one_row:n #1
|
|
{
|
|
\hbox_set:Nn \l__tblr_row_box {#1}
|
|
\vbox_set:Nn \l__tblr_table_hlines_box
|
|
{
|
|
\vbox_unpack:N \l__tblr_table_hlines_box
|
|
\skip_vertical:n
|
|
{ \box_ht:N \l__tblr_row_box + \box_dp:N \l__tblr_row_box }
|
|
}
|
|
\box_use:N \l__tblr_row_box
|
|
}
|
|
|
|
%% #1: hline number
|
|
\cs_new_protected:Npn \__tblr_build_one_hline:n #1
|
|
{
|
|
\vbox_set:Nn \l__tblr_table_box { \hbox:n { \__tblr_build_hline:n { #1 } } }
|
|
}
|
|
|
|
\tl_new:N \__tblr_vbox_align_tl
|
|
\tl_const:Nn \__tblr_vbox_t_tl {t}
|
|
\tl_const:Nn \__tblr_vbox_T_tl {T}
|
|
\tl_const:Nn \__tblr_vbox_m_tl {m}
|
|
\tl_const:Nn \__tblr_vbox_M_tl {M}
|
|
\tl_const:Nn \__tblr_vbox_c_tl {c}
|
|
\tl_const:Nn \__tblr_vbox_b_tl {b}
|
|
\tl_const:Nn \__tblr_vbox_B_tl {B}
|
|
|
|
\regex_const:Nn \c__tblr_is_positive_integer_regex { ^ \d+ $ }
|
|
\regex_const:Nn \c__tblr_is_negative_integer_regex { ^ - \d+ $ }
|
|
|
|
\tl_new:N \l__tblr_delim_left_tl
|
|
\tl_new:N \l__tblr_delim_right_tl
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole:Nn #1 #2
|
|
{
|
|
\group_begin:
|
|
\tl_set:Nx \l__tblr_delim_left_tl
|
|
{ \__tblr_prop_item:nn { inner } { delim-left } }
|
|
\tl_set:Nx \l__tblr_delim_right_tl
|
|
{ \__tblr_prop_item:nn { inner } { delim-right } }
|
|
\tl_set:Nn \__tblr_vbox_align_tl {#2}
|
|
\dim_set:Nn \l__tblr_t_dim { \box_ht:N #1 + \box_dp:N #1 }
|
|
\tl_case:NnF \__tblr_vbox_align_tl
|
|
{
|
|
\__tblr_vbox_m_tl
|
|
{ \__tblr_valign_whole_middle:N #1 }
|
|
\__tblr_vbox_c_tl
|
|
{ \__tblr_valign_whole_middle:N #1 }
|
|
\__tblr_vbox_M_tl
|
|
{ \__tblr_valign_whole_middle_row_or_border:N #1 }
|
|
\__tblr_vbox_t_tl
|
|
{ \__tblr_valign_whole_top:N #1 }
|
|
\__tblr_vbox_T_tl
|
|
{
|
|
\tl_set:Nn \__tblr_vbox_align_tl {1}
|
|
\__tblr_valign_whole_at_row_from_above:N #1
|
|
}
|
|
\__tblr_vbox_b_tl
|
|
{ \__tblr_valign_whole_bottom:N #1 }
|
|
\__tblr_vbox_B_tl
|
|
{
|
|
\tl_set:Nx \__tblr_vbox_align_tl { \int_use:N \c@rowcount }
|
|
\__tblr_valign_whole_at_row_from_below:N #1
|
|
}
|
|
}
|
|
{
|
|
\regex_match:NVTF \c__tblr_is_positive_integer_regex \__tblr_vbox_align_tl
|
|
{ \__tblr_valign_whole_at_row:N #1 }
|
|
{
|
|
\regex_match:NVTF
|
|
\c__tblr_is_negative_integer_regex \__tblr_vbox_align_tl
|
|
{ \__tblr_valign_whole_at_border:N #1 }
|
|
{ \__tblr_valign_whole_middle:N #1 }
|
|
}
|
|
}
|
|
%% we have done the job when valign is m or c
|
|
\box_if_empty:NF #1 { \__tblr_add_delimiters_to_box:N #1 }
|
|
\group_end:
|
|
}
|
|
|
|
%% We use the idea of delarray package to shift table box
|
|
%% when there are delimiters around the table
|
|
\cs_new_protected:Npn \__tblr_add_delimiters_to_box:N #1
|
|
{
|
|
\tl_if_empty:NTF \l__tblr_delim_left_tl
|
|
{ \box_use_drop:N #1 }
|
|
{
|
|
\box_move_down:nn
|
|
{
|
|
( \box_dp:N #1 - \box_ht:N #1 ) / 2
|
|
+ \tex_fontdimen:D 22 \tex_textfont:D 2
|
|
}
|
|
{ \__tblr_get_vcenter_box:N #1 }
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_get_vcenter_box:N #1
|
|
{
|
|
\hbox:n
|
|
{
|
|
$ \m@th \l__tblr_delim_left_tl
|
|
\tex_vcenter:D { \vbox_unpack_drop:N #1 }
|
|
\l__tblr_delim_right_tl $
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_middle:N #1
|
|
{
|
|
\__tblr_get_vcenter_box:N #1
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_top:N #1
|
|
{
|
|
\dim_set:Nn \l__tblr_h_dim { \__tblr_valign_get_hline_total:n {1} }
|
|
\dim_compare:nNnT \l__tblr_h_dim = { 0pt }
|
|
{ \dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_row_height:n {1} } }
|
|
\box_set_ht:Nn #1 { \l__tblr_h_dim }
|
|
\box_set_dp:Nn #1 { \l__tblr_t_dim - \l__tblr_h_dim }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_bottom:N #1
|
|
{
|
|
\dim_set:Nn \l__tblr_d_dim
|
|
{ \__tblr_valign_get_hline_total:n { \int_eval:n { \c@rowcount + 1 } } }
|
|
\dim_compare:nNnTF \l__tblr_d_dim = { 0pt }
|
|
{
|
|
\dim_set:Nn \l__tblr_d_dim
|
|
{ \__tblr_valign_get_row_depth:n { \int_use:N \c@rowcount } }
|
|
}
|
|
{ \dim_zero:N \l__tblr_d_dim }
|
|
\box_set_ht:Nn #1 { \l__tblr_t_dim - \l__tblr_d_dim }
|
|
\box_set_dp:Nn #1 { \l__tblr_d_dim }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_middle_row_or_border:N #1
|
|
{
|
|
\int_if_odd:nTF { \c@rowcount }
|
|
{
|
|
\tl_set:Nx \__tblr_vbox_align_tl { \int_eval:n { (\c@rowcount + 1) / 2 } }
|
|
\__tblr_valign_whole_at_row_from_above:N #1
|
|
}
|
|
{
|
|
\tl_set:Nx \__tblr_vbox_align_tl { \int_eval:n { \c@rowcount / 2 + 1 } }
|
|
\__tblr_valign_whole_at_border_from_above:N #1
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_at_row:N #1
|
|
{
|
|
\int_compare:nNnTF { 2 * \__tblr_vbox_align_tl } > { \c@rowcount }
|
|
{ \__tblr_valign_whole_at_row_from_below:N #1 }
|
|
{ \__tblr_valign_whole_at_row_from_above:N #1 }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_at_row_from_above:N #1
|
|
{
|
|
\dim_set:Nn \l__tblr_h_dim
|
|
{ \__tblr_valign_get_hline_total:n { \__tblr_vbox_align_tl } }
|
|
\dim_add:Nn \l__tblr_h_dim
|
|
{ \__tblr_valign_get_row_height:n { \__tblr_vbox_align_tl } }
|
|
\int_step_inline:nn { \__tblr_vbox_align_tl - 1 }
|
|
{
|
|
\dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_hline_total:n {##1} }
|
|
\dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_row_total:n {##1} }
|
|
}
|
|
\box_set_ht:Nn #1 { \l__tblr_h_dim }
|
|
\box_set_dp:Nn #1 { \l__tblr_t_dim - \l__tblr_h_dim }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_at_row_from_below:N #1
|
|
{
|
|
\dim_set:Nn \l__tblr_d_dim
|
|
{ \__tblr_valign_get_hline_total:n { \int_eval:n {\c@rowcount + 1} } }
|
|
\dim_add:Nn \l__tblr_d_dim
|
|
{ \__tblr_valign_get_row_depth:n { \__tblr_vbox_align_tl } }
|
|
\int_step_inline:nnn { \__tblr_vbox_align_tl + 1 } { \c@rowcount }
|
|
{
|
|
\dim_add:Nn \l__tblr_d_dim { \__tblr_valign_get_hline_total:n {##1} }
|
|
\dim_add:Nn \l__tblr_d_dim { \__tblr_valign_get_row_total:n {##1} }
|
|
}
|
|
\box_set_dp:Nn #1 { \l__tblr_d_dim }
|
|
\box_set_ht:Nn #1 { \l__tblr_t_dim - \l__tblr_d_dim }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_at_border:N #1
|
|
{
|
|
\tl_set:Nx \__tblr_vbox_align_tl { \int_eval:n { - \__tblr_vbox_align_tl } }
|
|
\int_compare:nNnTF { 2 * \__tblr_vbox_align_tl - 2 } > { \c@rowcount }
|
|
{ \__tblr_valign_whole_at_border_from_below:N #1 }
|
|
{ \__tblr_valign_whole_at_border_from_above:N #1 }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_at_border_from_above:N #1
|
|
{
|
|
\dim_set:Nn \l__tblr_h_dim
|
|
{ \__tblr_valign_get_hline_total:n { \__tblr_vbox_align_tl } }
|
|
\int_step_inline:nn { \__tblr_vbox_align_tl - 1 }
|
|
{
|
|
\dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_hline_total:n {##1} }
|
|
\dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_row_total:n {##1} }
|
|
}
|
|
\box_set_ht:Nn #1 { \l__tblr_h_dim }
|
|
\box_set_dp:Nn #1 { \l__tblr_t_dim - \l__tblr_h_dim }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_valign_whole_at_border_from_below:N #1
|
|
{
|
|
\dim_zero:N \l__tblr_d_dim
|
|
\int_step_inline:nnn { \__tblr_vbox_align_tl } { \c@rowcount }
|
|
{
|
|
\dim_add:Nn \l__tblr_d_dim { \__tblr_valign_get_row_total:n {##1} }
|
|
\dim_add:Nn \l__tblr_d_dim
|
|
{ \__tblr_valign_get_hline_total:n { \int_eval:n { ##1 + 1 } } }
|
|
}
|
|
\box_set_dp:Nn #1 { \l__tblr_d_dim }
|
|
\box_set_ht:Nn #1 { \l__tblr_t_dim - \l__tblr_d_dim }
|
|
}
|
|
|
|
\cs_new_nopar:Npn \__tblr_valign_get_hline_total:n #1
|
|
{
|
|
\__tblr_spec_item:ne { hline } { [#1] / @hline-height }
|
|
}
|
|
|
|
\cs_new_nopar:Npn \__tblr_valign_get_row_total:n #1
|
|
{
|
|
\__tblr_data_item:nnn { row } {#1} { abovesep }
|
|
+
|
|
\__tblr_data_item:nnn { row } {#1} { @row-height }
|
|
+
|
|
\__tblr_data_item:nnn { row } {#1} { belowsep }
|
|
}
|
|
|
|
\cs_new_nopar:Npn \__tblr_valign_get_row_height:n #1
|
|
{
|
|
\__tblr_data_item:nnn { row } {#1} { abovesep }
|
|
+
|
|
( \__tblr_data_item:nnn { row } {#1} { @row-height }
|
|
+
|
|
\__tblr_data_item:nnn { row } {#1} { @row-upper }
|
|
-
|
|
\__tblr_data_item:nnn { row } {#1} { @row-lower }
|
|
) / 2
|
|
}
|
|
|
|
\cs_new_nopar:Npn \__tblr_valign_get_row_depth:n #1
|
|
{
|
|
( \__tblr_data_item:nen { row } {#1} { @row-height }
|
|
-
|
|
\__tblr_data_item:nen { row } {#1} { @row-upper }
|
|
+
|
|
\__tblr_data_item:nen { row } {#1} { @row-lower }
|
|
) / 2
|
|
+
|
|
\__tblr_data_item:nnn { row } {#1} { belowsep }
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Build Table Components}
|
|
%%% --------------------------------------------------------
|
|
|
|
\dim_new:N \l__tblr_col_o_wd_dim
|
|
\dim_new:N \l__tblr_col_b_wd_dim
|
|
|
|
%% Build hline. #1: row number
|
|
\cs_new_protected:Npn \__tblr_build_hline:n #1
|
|
{
|
|
\int_step_inline:nn { \c@colcount }
|
|
{ \__tblr_build_hline_segment:nn { #1 } { ##1 } }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_build_hline:n { x, V }
|
|
|
|
%% #1: row number, #2: column number
|
|
\cs_new_protected:Npn \__tblr_build_hline_segment:nn #1 #2
|
|
{
|
|
\tl_set:Nx \l__tblr_n_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1] / @hline-count } }
|
|
\tl_set:Nx \l__tblr_o_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1][#2] / omit } }
|
|
\__tblr_get_col_outer_width_border_width:nNN {#2}
|
|
\l__tblr_col_o_wd_dim \l__tblr_col_b_wd_dim
|
|
\tl_if_empty:NTF \l__tblr_o_tl
|
|
{
|
|
\int_compare:nNnT { \l__tblr_n_tl } > {0}
|
|
{ \__tblr_build_hline_segment_real:nn {#1} {#2} }
|
|
}
|
|
{ \__tblr_build_hline_segment_omit:nn {#1} {#2} }
|
|
}
|
|
|
|
%% #1: row number, #2: column number
|
|
\cs_new_protected:Npn \__tblr_build_hline_segment_omit:nn #1 #2
|
|
{
|
|
\skip_horizontal:n { \l__tblr_col_o_wd_dim - \l__tblr_col_b_wd_dim }
|
|
}
|
|
|
|
%% #1: row number, #2: column number
|
|
\cs_new_protected:Npn \__tblr_build_hline_segment_real:nn #1 #2
|
|
{
|
|
\tl_set:Nx \l__tblr_s_tl
|
|
{ \__tblr_prop_item:ne { inner } { rulesep } }
|
|
\vbox_set:Nn \l__tblr_c_box
|
|
{
|
|
%% add an empty hbox to support vbox width
|
|
\tex_hbox:D to \l__tblr_col_o_wd_dim {}
|
|
\int_step_inline:nn { \l__tblr_n_tl }
|
|
{
|
|
\tl_set:Nx \l__tblr_h_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1](##1) / @hline-height } }
|
|
\hrule height ~ 0pt % remove lineskip
|
|
\hbox_set_to_wd:Nnn \l__tblr_b_box { \l__tblr_col_o_wd_dim }
|
|
{
|
|
\__tblr_get_hline_left_right_skips:nnn {#1} {#2} {##1}
|
|
\skip_horizontal:N \l__tblr_hline_leftskip_dim
|
|
\tl_set:Nx \l__tblr_f_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1][#2](##1) / fg } }
|
|
\tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} }
|
|
\__tblr_get_hline_segment_child:nnn {#1} {#2} {##1}
|
|
\skip_horizontal:N \l__tblr_hline_rightskip_dim
|
|
}
|
|
\box_set_ht:Nn \l__tblr_b_box { \l__tblr_h_tl }
|
|
\box_set_dp:Nn \l__tblr_b_box { 0pt }
|
|
\box_use:N \l__tblr_b_box
|
|
\skip_vertical:n { \l__tblr_s_tl }
|
|
}
|
|
\skip_vertical:n { - \l__tblr_s_tl }
|
|
}
|
|
\box_use:N \l__tblr_c_box
|
|
\skip_horizontal:n { - \l__tblr_col_b_wd_dim }
|
|
}
|
|
|
|
%% Read from table specifications and calculate the widths of row and border
|
|
%% column outer width = content width + colsep width + border width
|
|
%% #1: the column number, #2: outer width, #3: border width
|
|
\cs_new_protected:Npn \__tblr_get_col_outer_width_border_width:nNN #1 #2 #3
|
|
{
|
|
\dim_set:Nn #3
|
|
{ \__tblr_spec_item:ne { vline } { [\int_eval:n {#1 + 1}] / @vline-width } }
|
|
\dim_set:Nn #2
|
|
{
|
|
\__tblr_spec_item:ne { vline } { [#1] / @vline-width }
|
|
+
|
|
\__tblr_data_item:nen { column } {#1} { leftsep }
|
|
+
|
|
\__tblr_data_item:nen { column } {#1} { @col-width }
|
|
+
|
|
\__tblr_data_item:nen { column } {#1} { rightsep }
|
|
+
|
|
#3
|
|
}
|
|
}
|
|
|
|
\dim_new:N \l__tblr_hline_leftskip_dim
|
|
\dim_new:N \l__tblr_hline_rightskip_dim
|
|
|
|
%% Calculate left and right skips from leftpos and rightpos specifications
|
|
%% #1: row number; #2: column number; #3: hline index;
|
|
\cs_new_protected:Npn \__tblr_get_hline_left_right_skips:nnn #1 #2 #3
|
|
{
|
|
\tl_set:Nx \l__tblr_hline_leftpos_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1][#2](#3) / leftpos } }
|
|
\tl_if_empty:NT \l__tblr_hline_leftpos_tl
|
|
{ \tl_set:Nn \l__tblr_hline_leftpos_tl {1} } % default position
|
|
\tl_set:Nx \l__tblr_hline_rightpos_tl
|
|
{ \__tblr_spec_item:ne { hline } { [#1][#2](#3) / rightpos } }
|
|
\tl_if_empty:NT \l__tblr_hline_rightpos_tl
|
|
{ \tl_set:Nn \l__tblr_hline_rightpos_tl {1} } % default position
|
|
\fp_compare:nNnT { \l__tblr_hline_leftpos_tl } < {1}
|
|
{
|
|
\dim_set:Nn \l_tmpa_dim
|
|
{ \__tblr_spec_item:ne { vline } { [#2] / @vline-width } }
|
|
\dim_set:Nn \l_tmpb_dim
|
|
{ \__tblr_data_item:nen { column } {#2} { leftsep } }
|
|
\fp_compare:nNnTF { \l__tblr_hline_leftpos_tl } < {0}
|
|
{
|
|
\dim_set:Nn \l__tblr_hline_leftskip_dim
|
|
{ \l_tmpa_dim - \l__tblr_hline_leftpos_tl \l_tmpb_dim }
|
|
}
|
|
{
|
|
\dim_set:Nn \l__tblr_hline_leftskip_dim
|
|
{ \l_tmpa_dim - \l__tblr_hline_leftpos_tl \l_tmpa_dim }
|
|
}
|
|
}
|
|
\fp_compare:nNnT { \l__tblr_hline_rightpos_tl } < {1}
|
|
{
|
|
\dim_set:Nn \l_tmpa_dim
|
|
{
|
|
\__tblr_spec_item:ne { vline }
|
|
{ [\int_eval:n { #2 + 1 }] / @vline-width }
|
|
}
|
|
\dim_set:Nn \l_tmpb_dim
|
|
{ \__tblr_data_item:nen { column } {#2} { rightsep } }
|
|
\fp_compare:nNnTF { \l__tblr_hline_rightpos_tl } < {0}
|
|
{
|
|
\dim_set:Nn \l__tblr_hline_rightskip_dim
|
|
{ \l_tmpa_dim - \l__tblr_hline_rightpos_tl \l_tmpb_dim }
|
|
}
|
|
{
|
|
\dim_set:Nn \l__tblr_hline_rightskip_dim
|
|
{ \l_tmpa_dim - \l__tblr_hline_rightpos_tl \l_tmpa_dim }
|
|
}
|
|
}
|
|
}
|
|
|
|
\dim_new:N \l__tblr_row_ht_dim
|
|
\dim_new:N \l__tblr_row_dp_dim
|
|
\dim_new:N \l__tblr_row_abovesep_dim
|
|
\dim_new:N \l__tblr_row_belowsep_dim
|
|
\box_new:N \l__tblr_row_vlines_box
|
|
\box_new:N \l__tblr_vline_box
|
|
\box_new:N \l__tblr_cell_box
|
|
|
|
%% Build current row, #1: row number
|
|
%% To fix disappeared vlines with colorful tables in Adobe Reader (see #76),
|
|
%% we collect all vlines and draw them at the end of the row.
|
|
\cs_new_protected:Npn \__tblr_build_row:N #1
|
|
{
|
|
\int_set:Nn \c@rownum {#1}
|
|
\__tblr_update_rowsep_registers:
|
|
\__tblr_get_row_inner_height_depth:VNNNN #1
|
|
\l__tblr_row_ht_dim \l__tblr_row_dp_dim
|
|
\l__tblr_row_abovesep_dim \l__tblr_row_belowsep_dim
|
|
\vrule width ~ 0pt ~ height ~ \l__tblr_row_ht_dim ~ depth ~ \l__tblr_row_dp_dim
|
|
\hbox_set:Nn \l__tblr_row_vlines_box
|
|
{
|
|
\vrule width ~ 0pt ~ height ~ \l__tblr_row_ht_dim
|
|
~ depth ~ \l__tblr_row_dp_dim
|
|
}
|
|
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
|
|
{
|
|
\__tblr_put_one_vline:n
|
|
{ \__tblr_build_vline_segment:nn {#1} { \l__tblr_j_tl } }
|
|
\__tblr_put_one_cell:n { \__tblr_build_cell:NN #1 \l__tblr_j_tl }
|
|
}
|
|
\__tblr_put_one_vline:n
|
|
{ \__tblr_build_vline_segment:nn {#1} { \int_eval:n {\c@colcount + 1} } }
|
|
\skip_horizontal:n { - \box_wd:N \l__tblr_row_vlines_box }
|
|
\box_use:N \l__tblr_row_vlines_box
|
|
}
|
|
|
|
%% Read from table specifications and calculate inner height/depth of the row
|
|
%% inner height = abovesep + above vspace + row upper
|
|
%% inner depth = row lower + below vspace + belowsep
|
|
%% #1: the row number; #2: resulting inner height; #3: resulting inner depth;
|
|
%% #4: restulting abovesep; #5: restulting belowsep.
|
|
|
|
\dim_new:N \l__row_upper_dim
|
|
\dim_new:N \l__row_lower_dim
|
|
\dim_new:N \l__row_vpace_dim
|
|
|
|
\cs_new_protected:Npn \__tblr_get_row_inner_height_depth:nNNNN #1 #2 #3 #4 #5
|
|
{
|
|
\dim_set:Nn #4
|
|
{ \__tblr_data_item:nen { row } {#1} { abovesep } }
|
|
\dim_set:Nn #5
|
|
{ \__tblr_data_item:nen { row } {#1} { belowsep } }
|
|
\dim_set:Nn \l__row_upper_dim
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-upper } }
|
|
\dim_set:Nn \l__row_lower_dim
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-lower } }
|
|
\dim_set:Nn \l__row_vpace_dim
|
|
{
|
|
( \__tblr_data_item:nen { row } {#1} { @row-height }
|
|
- \l__row_upper_dim - \l__row_lower_dim ) / 2
|
|
}
|
|
\dim_set:Nn #2 { #4 + \l__row_vpace_dim + \l__row_upper_dim }
|
|
\dim_set:Nn #3 { \l__row_lower_dim + \l__row_vpace_dim + #5 }
|
|
}
|
|
\cs_generate_variant:Nn \__tblr_get_row_inner_height_depth:nNNNN { V }
|
|
|
|
\cs_new_protected:Npn \__tblr_put_one_vline:n #1
|
|
{
|
|
\hbox_set:Nn \l__tblr_vline_box {#1}
|
|
\skip_horizontal:n { \box_wd:N \l__tblr_vline_box }
|
|
\hbox_set:Nn \l__tblr_row_vlines_box
|
|
{
|
|
\hbox_unpack:N \l__tblr_row_vlines_box
|
|
\box_use:N \l__tblr_vline_box
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_put_one_cell:n #1
|
|
{
|
|
\hbox_set:Nn \l__tblr_cell_box {#1}
|
|
\hbox_set:Nn \l__tblr_row_vlines_box
|
|
{
|
|
\hbox_unpack:N \l__tblr_row_vlines_box
|
|
\skip_horizontal:n { \box_wd:N \l__tblr_cell_box }
|
|
}
|
|
\box_use:N \l__tblr_cell_box
|
|
}
|
|
|
|
%% #1: row number, #2: column number
|
|
\cs_new_protected:Npn \__tblr_build_vline_segment:nn #1 #2
|
|
{
|
|
\tl_set:Nx \l__tblr_n_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#2] / @vline-count } }
|
|
\tl_set:Nx \l__tblr_o_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#1][#2] / omit } }
|
|
\tl_if_empty:NTF \l__tblr_o_tl
|
|
{
|
|
\int_compare:nNnT { \l__tblr_n_tl } > {0}
|
|
{ \__tblr_build_vline_segment_real:nn {#1} {#2} }
|
|
}
|
|
{ \__tblr_build_vline_segment_omit:nn {#1} {#2} }
|
|
}
|
|
|
|
%% #1: row number, #2: column number
|
|
\cs_new_protected:Npn \__tblr_build_vline_segment_omit:nn #1 #2
|
|
{
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#2] / @vline-width } }
|
|
\skip_horizontal:N \l__tblr_w_tl
|
|
}
|
|
|
|
%% #1: row number, #2: column number
|
|
%% We make every vline segment intersect with first hline below
|
|
%% to remove gaps in vlines around multirow cells
|
|
\cs_new_protected:Npn \__tblr_build_vline_segment_real:nn #1 #2
|
|
{
|
|
\tl_set:Nx \l__tblr_s_tl
|
|
{ \__tblr_prop_item:ne { inner } { rulesep } }
|
|
\hbox_set:Nn \l__tblr_a_box
|
|
{
|
|
\int_step_inline:nn { \l__tblr_n_tl }
|
|
{
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#2](##1) / @vline-width } }
|
|
\vbox_set_to_ht:Nnn \l__tblr_b_box
|
|
{ \dim_eval:n { \l__tblr_row_ht_dim + \l__tblr_row_dp_dim } }
|
|
{
|
|
\tl_set:Nx \l__tblr_f_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#1][#2](##1) / fg } }
|
|
\tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} }
|
|
\__tblr_get_vline_above_below_skips:nnn {#1} {#2} {##1}
|
|
\skip_vertical:N \l__tblr_vline_aboveskip_dim
|
|
\__tblr_get_vline_segment_child:nnnxx {#1} {#2} {##1}
|
|
{ \dim_eval:n { \l__tblr_row_ht_dim } }
|
|
{ \dim_eval:n { \l__tblr_row_dp_dim } }
|
|
\skip_vertical:N \l__tblr_vline_belowskip_dim
|
|
}
|
|
\box_set_wd:Nn \l__tblr_b_box { \l__tblr_w_tl }
|
|
\box_use:N \l__tblr_b_box
|
|
\skip_horizontal:n { \l__tblr_s_tl }
|
|
}
|
|
\skip_horizontal:n { - \l__tblr_s_tl }
|
|
}
|
|
\vbox_set:Nn \l__tblr_c_box { \box_use:N \l__tblr_a_box }
|
|
\box_set_ht:Nn \l__tblr_c_box { \dim_use:N \l__tblr_row_ht_dim }
|
|
\box_set_dp:Nn \l__tblr_c_box { \dim_use:N \l__tblr_row_dp_dim }
|
|
\box_use:N \l__tblr_c_box
|
|
}
|
|
|
|
\dim_new:N \l__tblr_vline_aboveskip_dim
|
|
\dim_new:N \l__tblr_vline_belowskip_dim
|
|
|
|
%% Calculate above and below skips from abovepos and belowpos specifications
|
|
%% #1: row number; #2: column number; #3: vline index;
|
|
\cs_new_protected:Npn \__tblr_get_vline_above_below_skips:nnn #1 #2 #3
|
|
{
|
|
\tl_set:Nx \l__tblr_vline_abovepos_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#1][#2](#3) / abovepos } }
|
|
\tl_if_empty:NT \l__tblr_vline_abovepos_tl
|
|
{
|
|
\tl_set:Nn \l__tblr_vline_abovepos_tl {0} % default position
|
|
}
|
|
\fp_compare:nNnF { \l__tblr_vline_abovepos_tl } = {0}
|
|
{
|
|
\dim_set:Nn \l_tmpa_dim
|
|
{ \__tblr_spec_item:ne { hline } { [#1] / @hline-height } }
|
|
\fp_compare:nNnTF { \l__tblr_vline_abovepos_tl } < {0}
|
|
{
|
|
\dim_set:Nn \l__tblr_vline_aboveskip_dim
|
|
{ - \l__tblr_vline_abovepos_tl \l__tblr_row_abovesep_dim }
|
|
}
|
|
{
|
|
\dim_set:Nn \l__tblr_vline_aboveskip_dim
|
|
{ - \l__tblr_vline_abovepos_tl \l_tmpa_dim }
|
|
}
|
|
}
|
|
%% To join two vline segment above and below a cline,
|
|
%% we choose to extend every vline downwards a little (#55, #272).
|
|
\tl_set:Nx \l__tblr_vline_belowpos_tl
|
|
{ \__tblr_spec_item:ne { vline } { [#1][#2](#3) / belowpos } }
|
|
\tl_if_empty:NTF \l__tblr_vline_belowpos_tl
|
|
{
|
|
\dim_set:Nn \l__tblr_vline_belowskip_dim
|
|
{
|
|
- \__tblr_spec_item:ne { hline }
|
|
{ [\int_eval:n { #1 + 1 }](1) / @hline-height }
|
|
+ 0pt
|
|
}
|
|
}
|
|
{
|
|
\dim_set:Nn \l_tmpa_dim
|
|
{
|
|
\__tblr_spec_item:ne { hline }
|
|
{ [\int_eval:n { #1 + 1 }] / @hline-height }
|
|
}
|
|
\fp_compare:nNnTF { \l__tblr_vline_belowpos_tl } < {0}
|
|
{
|
|
\dim_set:Nn \l__tblr_vline_belowskip_dim
|
|
{ - \l__tblr_vline_belowpos_tl \l__tblr_row_belowsep_dim }
|
|
}
|
|
{
|
|
\dim_set:Nn \l__tblr_vline_belowskip_dim
|
|
{ - \l__tblr_vline_belowpos_tl \l_tmpa_dim }
|
|
}
|
|
}
|
|
}
|
|
|
|
\tl_new:N \l__tblr_cell_rowspan_tl
|
|
\tl_new:N \l__tblr_cell_colspan_tl
|
|
\dim_new:N \l__tblr_cell_wd_dim
|
|
\dim_new:N \l__tblr_cell_ht_dim
|
|
|
|
\cs_new_protected:Npn \__tblr_build_cell:NN #1 #2
|
|
{
|
|
\int_set:Nn \c@colnum {#2}
|
|
\__tblr_update_colsep_registers:
|
|
\group_begin:
|
|
\tl_set:Nx \l__tblr_w_tl
|
|
{ \__tblr_data_item:nen { column } {#2} { @col-width } }
|
|
\tl_set:Nx \l__tblr_h_tl
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-height } }
|
|
\tl_set:Nx \l__tblr_x_tl
|
|
{ \__tblr_data_item:nen { column } {#2} { leftsep} }
|
|
\tl_set:Nx \l__tblr_y_tl
|
|
{ \__tblr_data_item:nen { column } {#2} { rightsep } }
|
|
\tl_set:Nx \l__tblr_cell_colspan_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { colspan } }
|
|
\int_compare:nNnTF { \l__tblr_cell_colspan_tl } < {2}
|
|
{ \dim_set:Nn \l__tblr_cell_wd_dim { \l__tblr_w_tl } }
|
|
{
|
|
\__tblr_get_span_horizontal_sizes:NNNNN #1 #2
|
|
\l__tblr_o_dim \l__tblr_cell_wd_dim \l__tblr_q_dim
|
|
}
|
|
\tl_set:Nx \l__tblr_cell_rowspan_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { rowspan } }
|
|
\int_compare:nNnTF { \l__tblr_cell_rowspan_tl } < {2}
|
|
{ \dim_set:Nn \l__tblr_cell_ht_dim { \l__tblr_h_tl } }
|
|
{
|
|
\__tblr_get_span_vertical_sizes:NNNNN #1 #2
|
|
\l__tblr_r_dim \l__tblr_cell_ht_dim \l__tblr_t_dim
|
|
}
|
|
\__tblr_get_cell_alignments:nn {#1} {#2}
|
|
\__tblr_build_cell_background:NN #1 #2
|
|
\__tblr_build_cell_content:NN #1 #2
|
|
\group_end:
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_build_cell_content:NN #1 #2
|
|
{
|
|
\hbox_set_to_wd:Nnn \l__tblr_a_box { \l__tblr_cell_wd_dim }
|
|
{
|
|
\tl_if_eq:NnTF \g__tblr_cell_halign_tl {j}
|
|
% cell width may be less than column width for j cells
|
|
{ \__tblr_get_cell_text:nn {#1} {#2} \hfil }
|
|
{
|
|
\tl_if_eq:NnF \g__tblr_cell_halign_tl {l} { \hfil }
|
|
\__tblr_get_cell_text:nn {#1} {#2}
|
|
\tl_if_eq:NnF \g__tblr_cell_halign_tl {r} { \hfil }
|
|
}
|
|
}
|
|
\vbox_set_to_ht:Nnn \l__tblr_b_box { \l__tblr_cell_ht_dim }
|
|
{
|
|
\tl_case:Nn \g__tblr_cell_valign_tl
|
|
{
|
|
\c__tblr_valign_m_tl
|
|
{
|
|
\vfil
|
|
\int_compare:nNnT { \l__tblr_cell_rowspan_tl } < {2}
|
|
{
|
|
\box_set_ht:Nn \l__tblr_a_box
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-upper } }
|
|
\box_set_dp:Nn \l__tblr_a_box
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-lower } }
|
|
}
|
|
\box_use:N \l__tblr_a_box
|
|
\vfil
|
|
}
|
|
\c__tblr_valign_h_tl
|
|
{
|
|
\box_set_ht:Nn \l__tblr_a_box
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-head } }
|
|
\box_use:N \l__tblr_a_box
|
|
\vfil
|
|
}
|
|
\c__tblr_valign_f_tl
|
|
{
|
|
\vfil
|
|
\int_compare:nNnTF { \l__tblr_cell_rowspan_tl } < {2}
|
|
{
|
|
\box_set_dp:Nn \l__tblr_a_box
|
|
{ \__tblr_data_item:nen { row } {#1} { @row-foot } }
|
|
}
|
|
{
|
|
\box_set_dp:Nn \l__tblr_a_box
|
|
{
|
|
\__tblr_data_item:nen
|
|
{ row }
|
|
{ \int_eval:n { #1 + \l__tblr_cell_rowspan_tl - 1 } }
|
|
{ @row-foot }
|
|
}
|
|
}
|
|
\box_use:N \l__tblr_a_box
|
|
}
|
|
}
|
|
\hrule height ~ 0pt %% zero depth
|
|
}
|
|
\vbox_set_to_ht:Nnn \l__tblr_c_box
|
|
{ \l__tblr_row_ht_dim - \l__tblr_row_abovesep_dim }
|
|
{
|
|
\box_use:N \l__tblr_b_box
|
|
\vss
|
|
}
|
|
\skip_horizontal:n { \l__tblr_x_tl }
|
|
\box_use:N \l__tblr_c_box
|
|
\skip_horizontal:n { \l__tblr_y_tl - \l__tblr_cell_wd_dim + \l__tblr_w_tl }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_build_cell_background:NN #1 #2
|
|
{
|
|
\int_compare:nNnT { \__tblr_data_item:neen { cell } {#1} {#2} { omit } } = {0}
|
|
{
|
|
\group_begin:
|
|
\tl_set:Nx \l__tblr_b_tl
|
|
{ \__tblr_data_item:neen { cell } {#1} {#2} { background } }
|
|
\tl_if_empty:NF \l__tblr_b_tl
|
|
{
|
|
\__tblr_get_cell_background_width:NNN #1 #2 \l_tmpa_dim
|
|
\__tblr_get_cell_background_depth:NNN #1 #2 \l_tmpb_dim
|
|
\__tblr_build_cell_background:nnnn
|
|
{ \dim_use:N \l_tmpa_dim }
|
|
{ \l__tblr_row_ht_dim }
|
|
{ \dim_use:N \l_tmpb_dim }
|
|
{ \l__tblr_b_tl }
|
|
}
|
|
\group_end:
|
|
}
|
|
}
|
|
|
|
%% #1: row number; #2: column number; #3 resulting dimension
|
|
\cs_new_protected:Npn \__tblr_get_cell_background_width:NNN #1 #2 #3
|
|
{
|
|
\int_compare:nNnTF { \l__tblr_cell_colspan_tl } < {2}
|
|
{ \dim_set:Nn #3 { \l__tblr_x_tl + \l__tblr_w_tl + \l__tblr_y_tl } }
|
|
{
|
|
\dim_set:Nn #3 { \l__tblr_o_dim + \l__tblr_cell_wd_dim + \l__tblr_q_dim }
|
|
}
|
|
}
|
|
|
|
%% #1: row number; #2: column number; #3 resulting dimension
|
|
\cs_new_protected:Npn \__tblr_get_cell_background_depth:NNN #1 #2 #3
|
|
{
|
|
\int_compare:nNnTF { \l__tblr_cell_rowspan_tl } < {2}
|
|
{ \dim_set_eq:NN #3 \l__tblr_row_dp_dim }
|
|
{
|
|
\dim_set:Nn #3
|
|
{
|
|
\l__tblr_r_dim + \l__tblr_cell_ht_dim
|
|
+ \l__tblr_t_dim - \l__tblr_row_ht_dim
|
|
}
|
|
}
|
|
}
|
|
|
|
%% #1: width, #2: height, #3: depth, #4: color
|
|
\cs_new_protected:Npn \__tblr_build_cell_background:nnnn #1 #2 #3 #4
|
|
{
|
|
\hbox_set:Nn \l__tblr_a_box
|
|
{
|
|
\color {#4}
|
|
\vrule width ~ #1 ~ height ~ #2 ~ depth ~ #3
|
|
}
|
|
\box_set_dp:Nn \l__tblr_a_box { 0pt }
|
|
\box_use:N \l__tblr_a_box
|
|
\skip_horizontal:n { - #1 }
|
|
}
|
|
|
|
%% #1: row number; #2: column number; #3: dimen register for rowsep above.
|
|
%% #4: dimen register for total height; #5: dimen register for rowsep below.
|
|
%% We can use \l__tblr_row_item_skip_size_prop which was made before
|
|
%% But when vspan=even, there are no itemskip in the prop list.
|
|
%% Therefore we need to calculate them from the sizes of items and skips
|
|
\cs_new_protected:Npn \__tblr_get_span_vertical_sizes:NNNNN #1 #2 #3 #4 #5
|
|
{
|
|
\dim_set:Nn #3
|
|
{ \__tblr_data_item:nen { row } {#1} { abovesep } }
|
|
\dim_zero:N #4
|
|
\dim_add:Nn #4
|
|
{ \prop_item:Ne \l__tblr_row_item_skip_size_prop { item[#1] } }
|
|
\int_step_inline:nnn { #1 + 1 } { #1 + \l__tblr_cell_rowspan_tl - 1 }
|
|
{
|
|
\dim_add:Nn #4
|
|
{
|
|
\prop_item:Ne \l__tblr_row_item_skip_size_prop { skip[##1] }
|
|
+
|
|
\prop_item:Ne \l__tblr_row_item_skip_size_prop { item[##1] }
|
|
}
|
|
}
|
|
\dim_set:Nn #5
|
|
{
|
|
\__tblr_data_item:nen { row }
|
|
{ \int_eval:n { #1 + \l__tblr_cell_rowspan_tl - 1 } } { belowsep }
|
|
}
|
|
%\tl_log:x { cell[#1][#2] ~:~ \dim_use:N #3, \dim_use:N #4, \dim_use:N #5 }
|
|
}
|
|
|
|
%% #1: row number; #2: column number; #3: dimen register for colsep left.
|
|
%% #4: dimen register for total width; #5: dimen register for colsep right.
|
|
%% We can use \l__tblr_col_item_skip_size_prop which was made before
|
|
%% But when hspan=even or hspan=minimal, there are no itemskip in the prop list.
|
|
%% Therefore we need to calculate them from the sizes of items and skips
|
|
\cs_new_protected:Npn \__tblr_get_span_horizontal_sizes:NNNNN #1 #2 #3 #4 #5
|
|
{
|
|
\dim_set:Nn #3
|
|
{ \__tblr_data_item:nen { column } {#2} { leftsep } }
|
|
\dim_zero:N #4
|
|
\dim_add:Nn #4
|
|
{ \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[#2] } }
|
|
\int_step_inline:nnn { #2 + 1 } { #2 + \l__tblr_cell_colspan_tl - 1 }
|
|
{
|
|
\dim_add:Nn #4
|
|
{
|
|
\prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] }
|
|
+
|
|
\prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] }
|
|
}
|
|
}
|
|
\dim_set:Nn #5
|
|
{
|
|
\__tblr_data_item:nen { column }
|
|
{ \int_eval:n {#2 + \l__tblr_cell_colspan_tl - 1} } { rightsep }
|
|
}
|
|
%\tl_log:x { cell[#1][#2] ~:~ \dim_use:N #3, \dim_use:N #4, \dim_use:N #5 }
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Tracing Tabularray}
|
|
%%% --------------------------------------------------------
|
|
|
|
\NewDocumentCommand \SetTblrTracing { m }
|
|
{
|
|
\keys_set:nn { tblr-set-tracing } {#1}
|
|
}
|
|
|
|
\bool_new:N \g__tblr_tracing_text_bool
|
|
\bool_new:N \g__tblr_tracing_command_bool
|
|
\bool_new:N \g__tblr_tracing_option_bool
|
|
\bool_new:N \g__tblr_tracing_theme_bool
|
|
\bool_new:N \g__tblr_tracing_outer_bool
|
|
\bool_new:N \g__tblr_tracing_inner_bool
|
|
\bool_new:N \g__tblr_tracing_column_bool
|
|
\bool_new:N \g__tblr_tracing_row_bool
|
|
\bool_new:N \g__tblr_tracing_cell_bool
|
|
\bool_new:N \g__tblr_tracing_vline_bool
|
|
\bool_new:N \g__tblr_tracing_hline_bool
|
|
\bool_new:N \g__tblr_tracing_colspec_bool
|
|
\bool_new:N \g__tblr_tracing_rowspec_bool
|
|
\bool_new:N \g__tblr_tracing_target_bool
|
|
\bool_new:N \g__tblr_tracing_cellspan_bool
|
|
\bool_new:N \g__tblr_tracing_intarray_bool
|
|
\bool_new:N \g__tblr_tracing_page_bool
|
|
\bool_new:N \g__tblr_tracing_step_bool
|
|
|
|
\bool_gset_true:N \g__tblr_tracing_step_bool
|
|
|
|
\keys_define:nn { tblr-set-tracing }
|
|
{
|
|
+text .code:n = \bool_gset_true:N \g__tblr_tracing_text_bool,
|
|
-text .code:n = \bool_gset_false:N \g__tblr_tracing_text_bool,
|
|
+command .code:n = \bool_gset_true:N \g__tblr_tracing_command_bool,
|
|
-command .code:n = \bool_gset_false:N \g__tblr_tracing_command_bool,
|
|
+option .code:n = \bool_gset_true:N \g__tblr_tracing_option_bool,
|
|
-option .code:n = \bool_gset_false:N \g__tblr_tracing_option_bool,
|
|
+theme .code:n = \bool_gset_true:N \g__tblr_tracing_theme_bool,
|
|
-theme .code:n = \bool_gset_false:N \g__tblr_tracing_theme_bool,
|
|
+outer .code:n = \bool_gset_true:N \g__tblr_tracing_outer_bool,
|
|
-outer .code:n = \bool_gset_false:N \g__tblr_tracing_outer_bool,
|
|
+inner .code:n = \bool_gset_true:N \g__tblr_tracing_inner_bool,
|
|
-inner .code:n = \bool_gset_false:N \g__tblr_tracing_inner_bool,
|
|
+column .code:n = \bool_gset_true:N \g__tblr_tracing_column_bool,
|
|
-column .code:n = \bool_gset_false:N \g__tblr_tracing_column_bool,
|
|
+row .code:n = \bool_gset_true:N \g__tblr_tracing_row_bool,
|
|
-row .code:n = \bool_gset_false:N \g__tblr_tracing_row_bool,
|
|
+cell .code:n = \bool_gset_true:N \g__tblr_tracing_cell_bool,
|
|
-cell .code:n = \bool_gset_false:N \g__tblr_tracing_cell_bool,
|
|
+vline .code:n = \bool_gset_true:N \g__tblr_tracing_vline_bool,
|
|
-vline .code:n = \bool_gset_false:N \g__tblr_tracing_vline_bool,
|
|
+hline .code:n = \bool_gset_true:N \g__tblr_tracing_hline_bool,
|
|
-hline .code:n = \bool_gset_false:N \g__tblr_tracing_hline_bool,
|
|
+colspec .code:n = \bool_gset_true:N \g__tblr_tracing_colspec_bool,
|
|
-colspec .code:n = \bool_gset_false:N \g__tblr_tracing_colspec_bool,
|
|
+rowspec .code:n = \bool_gset_true:N \g__tblr_tracing_rowspec_bool,
|
|
-rowspec .code:n = \bool_gset_false:N \g__tblr_tracing_rowspec_bool,
|
|
+target .code:n = \bool_gset_true:N \g__tblr_tracing_target_bool,
|
|
-target .code:n = \bool_gset_false:N \g__tblr_tracing_target_bool,
|
|
+cellspan .code:n = \bool_gset_true:N \g__tblr_tracing_cellspan_bool,
|
|
-cellspan .code:n = \bool_gset_false:N \g__tblr_tracing_cellspan_bool,
|
|
+intarray .code:n = \bool_gset_true:N \g__tblr_tracing_intarray_bool,
|
|
-intarray .code:n = \bool_gset_false:N \g__tblr_tracing_intarray_bool,
|
|
+page .code:n = \bool_gset_true:N \g__tblr_tracing_page_bool,
|
|
-page .code:n = \bool_gset_false:N \g__tblr_tracing_page_bool,
|
|
+step .code:n = \bool_gset_true:N \g__tblr_tracing_step_bool,
|
|
-step .code:n = \bool_gset_false:N \g__tblr_tracing_step_bool,
|
|
all .code:n = \__tblr_enable_all_tracings:,
|
|
none .code:n = \__tblr_disable_all_tracings:,
|
|
}
|
|
|
|
\cs_new_protected_nopar:Npn \__tblr_enable_all_tracings:
|
|
{
|
|
\bool_gset_true:N \g__tblr_tracing_text_bool
|
|
\bool_gset_true:N \g__tblr_tracing_command_bool
|
|
\bool_gset_true:N \g__tblr_tracing_option_bool
|
|
\bool_gset_true:N \g__tblr_tracing_theme_bool
|
|
\bool_gset_true:N \g__tblr_tracing_outer_bool
|
|
\bool_gset_true:N \g__tblr_tracing_inner_bool
|
|
\bool_gset_true:N \g__tblr_tracing_column_bool
|
|
\bool_gset_true:N \g__tblr_tracing_row_bool
|
|
\bool_gset_true:N \g__tblr_tracing_cell_bool
|
|
\bool_gset_true:N \g__tblr_tracing_vline_bool
|
|
\bool_gset_true:N \g__tblr_tracing_hline_bool
|
|
\bool_gset_true:N \g__tblr_tracing_colspec_bool
|
|
\bool_gset_true:N \g__tblr_tracing_rowspec_bool
|
|
\bool_gset_true:N \g__tblr_tracing_target_bool
|
|
\bool_gset_true:N \g__tblr_tracing_cellspan_bool
|
|
\bool_gset_true:N \g__tblr_tracing_intarray_bool
|
|
\bool_gset_true:N \g__tblr_tracing_page_bool
|
|
\bool_gset_true:N \g__tblr_tracing_step_bool
|
|
}
|
|
|
|
\cs_new_protected_nopar:Npn \__tblr_disable_all_tracings:
|
|
{
|
|
\bool_gset_false:N \g__tblr_tracing_text_bool
|
|
\bool_gset_false:N \g__tblr_tracing_command_bool
|
|
\bool_gset_false:N \g__tblr_tracing_option_bool
|
|
\bool_gset_false:N \g__tblr_tracing_theme_bool
|
|
\bool_gset_false:N \g__tblr_tracing_outer_bool
|
|
\bool_gset_false:N \g__tblr_tracing_inner_bool
|
|
\bool_gset_false:N \g__tblr_tracing_column_bool
|
|
\bool_gset_false:N \g__tblr_tracing_row_bool
|
|
\bool_gset_false:N \g__tblr_tracing_cell_bool
|
|
\bool_gset_false:N \g__tblr_tracing_vline_bool
|
|
\bool_gset_false:N \g__tblr_tracing_hline_bool
|
|
\bool_gset_false:N \g__tblr_tracing_colspec_bool
|
|
\bool_gset_false:N \g__tblr_tracing_rowspec_bool
|
|
\bool_gset_false:N \g__tblr_tracing_target_bool
|
|
\bool_gset_false:N \g__tblr_tracing_cellspan_bool
|
|
\bool_gset_false:N \g__tblr_tracing_intarray_bool
|
|
\bool_gset_false:N \g__tblr_tracing_page_bool
|
|
\bool_gset_false:N \g__tblr_tracing_step_bool
|
|
}
|
|
|
|
\NewDocumentCommand \LogTblrTracing { m }
|
|
{
|
|
\keys_set:nn { tblr-log-tracing } {#1}
|
|
}
|
|
|
|
\keys_define:nn { tblr-log-tracing }
|
|
{
|
|
step .code:n = \__tblr_log_tracing_step:n {#1},
|
|
unknown .code:n = \__tblr_log_tracing:N \l_keys_key_str
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing:N #1
|
|
{
|
|
\bool_if:cT { g__tblr_tracing_ #1 _bool }
|
|
{ \cs:w __tblr_log_tracing _ #1 : \cs_end: }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_text:
|
|
{
|
|
\__tblr_spec_log:n { text }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_command:
|
|
{
|
|
\__tblr_prop_log:n { command }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_option:
|
|
{
|
|
\__tblr_prop_log:n { note }
|
|
\__tblr_prop_log:n { remark }
|
|
\__tblr_prop_log:n { more }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_theme:
|
|
{
|
|
\__tblr_style_log:
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_outer:
|
|
{
|
|
\__tblr_spec_log:n { outer }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_inner:
|
|
{
|
|
\__tblr_prop_log:n { inner }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_column:
|
|
{
|
|
\__tblr_data_log:n { column }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_row:
|
|
{
|
|
\__tblr_data_log:n { row }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_cell:
|
|
{
|
|
\__tblr_data_log:n { cell }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_vline:
|
|
{
|
|
\__tblr_spec_log:n { vline }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_hline:
|
|
{
|
|
\__tblr_spec_log:n { hline }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_colspec:
|
|
{
|
|
\tl_if_eq:NnT \g__tblr_column_or_row_tl { column }
|
|
{ \tl_log:N \g__tblr_expanded_colrow_spec_tl }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_rowspec:
|
|
{
|
|
\tl_if_eq:NnT \g__tblr_column_or_row_tl { row }
|
|
{ \tl_log:N \g__tblr_expanded_colrow_spec_tl }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_target:
|
|
{
|
|
\dim_log:N \l__column_target_dim
|
|
\prop_log:N \l__column_coefficient_prop
|
|
\prop_log:N \l__column_natural_width_prop
|
|
\prop_log:N \l__column_computed_width_prop
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_cellspan:
|
|
{
|
|
\prop_log:N \l__tblr_col_item_skip_size_prop
|
|
\prop_log:N \l__tblr_col_span_size_prop
|
|
\prop_log:N \l__tblr_row_item_skip_size_prop
|
|
\prop_log:N \l__tblr_row_span_size_prop
|
|
\prop_log:N \l__tblr_row_span_to_row_prop
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_page:
|
|
{
|
|
\dim_log:N \pagegoal
|
|
\dim_log:N \pagetotal
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_log_tracing_step:n #1
|
|
{
|
|
\bool_if:NT \g__tblr_tracing_step_bool { \tl_log:x {Step :~ #1} }
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_do_if_tracing:nn #1 #2
|
|
{
|
|
\bool_if:cT { g__tblr_tracing_ #1 _bool } {#2}
|
|
}
|
|
|
|
%%% --------------------------------------------------------
|
|
%%> \section{Tabularray Libraries}
|
|
%%% --------------------------------------------------------
|
|
|
|
%% \NewTblrLibrary and \UseTblrLibrary commands
|
|
|
|
\NewDocumentCommand \NewTblrLibrary { m m }
|
|
{
|
|
\cs_new_protected:cpn { __tblr_use_lib_ #1: } {#2}
|
|
}
|
|
|
|
\NewDocumentCommand \UseTblrLibrary { m }
|
|
{
|
|
\clist_map_inline:nn {#1} { \use:c { __tblr_use_lib_ ##1: } }
|
|
}
|
|
|
|
%% Library amsmath and environments +array, +matrix, +cases, ...
|
|
|
|
\NewTblrLibrary { amsmath }
|
|
{
|
|
\RequirePackage { amsmath }
|
|
\NewTblrEnviron { +array }
|
|
\SetTblrInner[+array]{colsep = 5pt}
|
|
\NewDocumentEnvironment { +matrix } { O{} +b } {
|
|
\begin{+array}{
|
|
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
|
|
cells = {c}, ##1
|
|
}
|
|
##2
|
|
\end{+array}
|
|
} { }
|
|
\NewDocumentEnvironment { +bmatrix } { O{} +b } {
|
|
\begin{+array}{
|
|
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
|
|
cells = {c}, delimiter = {left = [, right = ]}, ##1
|
|
}
|
|
##2
|
|
\end{+array}
|
|
} { }
|
|
\NewDocumentEnvironment { +Bmatrix } { O{} +b } {
|
|
\begin{+array} {
|
|
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
|
|
cells = {c}, delimiter = {left = \lbrace, right = \rbrace}, ##1
|
|
}
|
|
##2
|
|
\end{+array}
|
|
} { }
|
|
\NewDocumentEnvironment { +pmatrix } { O{} +b } {
|
|
\begin{+array} {
|
|
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
|
|
cells = {c}, delimiter = {left = (, right = )}, ##1
|
|
}
|
|
##2
|
|
\end{+array}
|
|
} { }
|
|
\NewDocumentEnvironment { +vmatrix } { O{} +b } {
|
|
\begin{+array} {
|
|
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
|
|
cells = {c}, delimiter = {left = \lvert, right = \rvert}, ##1
|
|
}
|
|
##2
|
|
\end{+array}
|
|
} { }
|
|
\NewDocumentEnvironment { +Vmatrix } { O{} +b } {
|
|
\begin{+array} {
|
|
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
|
|
cells = {c}, delimiter = {left = \lVert, right = \rVert}, ##1
|
|
}
|
|
##2
|
|
\end{+array}
|
|
} { }
|
|
\NewDocumentEnvironment { +cases } { O{} +b } {
|
|
\begin{+array} {
|
|
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
|
|
colspec = {ll}, stretch = 1.2, delimiter = {left=\lbrace, right=.}, ##1
|
|
}
|
|
##2
|
|
\end{+array}
|
|
} { }
|
|
}
|
|
|
|
%% Library booktabs and commands \toprule, \midrule, \bottomrule
|
|
|
|
\NewTblrLibrary { booktabs }
|
|
{
|
|
% We only use dimensions \aboverulesep and \belowrulesep in booktabs package
|
|
\RequirePackage { booktabs }
|
|
\newcommand \tblr@booktabs@hline [1] [] { \hline [##1] }
|
|
\newcommand \tblr@booktabs@oldhline [1] [] {
|
|
\hline [##1]
|
|
\hborder { abovespace = \aboverulesep, belowspace = \belowrulesep }
|
|
}
|
|
\newcommand \tblr@booktabs@cline [2] [] { \cline [##1] {##2} }
|
|
\newcommand \tblr@booktabs@oldcline [2] [] {
|
|
\cline [##1] {##2}
|
|
\hborder { abovespace = \aboverulesep, belowspace = \belowrulesep }
|
|
}
|
|
\newcommand \tblr@booktabs@cline@more [2] [] { \SetHline [+] {##2} {##1} }
|
|
\newcommand \tblr@booktabs@oldcline@more [2] [] {
|
|
\SetHline [+] {##2} {##1}
|
|
\hborder { abovespace = \aboverulesep, belowspace = \belowrulesep }
|
|
}
|
|
\NewTableCommand \toprule [1] [] {
|
|
\tblr@booktabs@hline [wd=\heavyrulewidth, ##1]
|
|
}
|
|
\NewTableCommand \midrule [1] [] {
|
|
\tblr@booktabs@hline [wd=\lightrulewidth, ##1]
|
|
}
|
|
\NewTableCommand \bottomrule [1] [] {
|
|
\tblr@booktabs@hline [wd=\heavyrulewidth, ##1]
|
|
}
|
|
\NewTableCommand \cmidrule [2] [] {
|
|
\tblr@booktabs@cline [wd=\cmidrulewidth, endpos, ##1] {##2}
|
|
}
|
|
\NewTableCommand \cmidrulemore [2] [] {
|
|
\tblr@booktabs@cline@more [wd=\cmidrulewidth, endpos, ##1] {##2}
|
|
}
|
|
\newcommand \tblr@booktabs@change@more [1] { \cmidrulemore }
|
|
\NewTableCommand \morecmidrules {
|
|
\peek_meaning:NTF \cmidrule { \tblr@booktabs@change@more } { \relax }
|
|
}
|
|
\NewTblrEnviron { booktabs }
|
|
\NewTblrEnviron { longtabs }
|
|
\NewTblrEnviron { talltabs }
|
|
\SetTblrInner [ booktabs ] { rowsep = 0pt }
|
|
\SetTblrInner [ longtabs ] { rowsep = 0pt }
|
|
\SetTblrInner [ talltabs ] { rowsep = 0pt }
|
|
\SetTblrOuter [ longtabs ] { long }
|
|
\SetTblrOuter [ talltabs ] { tall }
|
|
\RequirePackage { etoolbox }
|
|
\newcommand \tblr@booktabs@begin@hook
|
|
{
|
|
\let \tblr@booktabs@hline = \tblr@booktabs@oldhline
|
|
\let \tblr@booktabs@cline = \tblr@booktabs@oldcline
|
|
\let \tblr@booktabs@cline@more = \tblr@booktabs@oldcline@more
|
|
}
|
|
\AtBeginEnvironment { booktabs } { \tblr@booktabs@begin@hook }
|
|
\AtBeginEnvironment { longtabs } { \tblr@booktabs@begin@hook }
|
|
\AtBeginEnvironment { talltabs } { \tblr@booktabs@begin@hook }
|
|
\NewTableCommand \specialrule [3]
|
|
{ \hline [##1] \hborder { abovespace = ##2, belowspace = ##3 } }
|
|
\NewTableCommand \addrowspace [1] [\defaultaddspace]
|
|
{ \hborder { abovespace+ = (##1) / 2, belowspace+ = (##1) / 2 } }
|
|
\NewTableCommand \addlinespace [1] [\defaultaddspace]
|
|
{ \hborder { abovespace+ = (##1) / 2, belowspace+ = (##1) / 2 } }
|
|
}
|
|
|
|
%% Library counter for resetting all counters
|
|
|
|
\tl_new:N \__tblr_saved_trial_counters_tl
|
|
\tl_new:N \__tblr_saved_cell_counters_tl
|
|
|
|
\cs_new_protected:Npn \__tblr_save_counters:n #1 { }
|
|
\cs_new_protected:Npn \__tblr_restore_counters:n #1 { }
|
|
|
|
%% We use code from tabularx package for resetting all LaTeX counters,
|
|
%% where internal macro \cl@@ckpt looks like the following:
|
|
%% \@elt{page} \@elt{equation} \@elt{enumi} \@elt{enumii} \@elt{enumiii} ...
|
|
|
|
\NewTblrLibrary { counter }
|
|
{
|
|
\cs_set_protected:Npn \__tblr_save_counters:n ##1
|
|
{
|
|
\def \@elt ####1 { \global\value{####1} = \the\value{####1} \relax }
|
|
\tl_set:cx { __tblr_saved_ ##1 _counters_tl } { \cl@@ckpt }
|
|
\let \@elt = \relax
|
|
}
|
|
\cs_set_protected:Npn \__tblr_restore_counters:n ##1
|
|
{
|
|
\tl_use:c { __tblr_saved_ ##1 _counters_tl }
|
|
}
|
|
}
|
|
|
|
%% Library diagbox and command \diagbox
|
|
|
|
\NewTblrLibrary { diagbox }
|
|
{
|
|
\RequirePackage{ diagbox }
|
|
\cs_set_eq:NN \__tblr_lib_saved_diagbox:w \diagbox
|
|
\NewContentCommand \diagbox [3] []
|
|
{
|
|
\__tblr_lib_diagbox_fix:n
|
|
{
|
|
\__tblr_lib_saved_diagbox:w
|
|
[ leftsep=\leftsep, rightsep=\rightsep, ##1 ]
|
|
{ \__tblr_lib_diagbox_math_or_text:n {##2} }
|
|
{ \__tblr_lib_diagbox_math_or_text:n {##3} }
|
|
}
|
|
}
|
|
\NewContentCommand \diagboxthree [4] []
|
|
{
|
|
\__tblr_lib_diagbox_fix:n
|
|
{
|
|
\__tblr_lib_saved_diagbox:w
|
|
[ leftsep=\leftsep, rightsep=\rightsep, ##1 ]
|
|
{ \__tblr_lib_diagbox_math_or_text:n {##2} }
|
|
{ \__tblr_lib_diagbox_math_or_text:n {##3} }
|
|
{ \__tblr_lib_diagbox_math_or_text:n {##4} }
|
|
}
|
|
}
|
|
}
|
|
|
|
\cs_new_protected:Npn \__tblr_lib_diagbox_math_or_text:n #1
|
|
{
|
|
\bool_if:NTF \l__tblr_cell_math_mode_bool {$#1$} {#1}
|
|
}
|
|
|
|
\box_new:N \l__tblr_diag_box
|
|
|
|
\cs_new_protected:Npn \__tblr_lib_diagbox_fix:n #1
|
|
{
|
|
\hbox_set:Nn \l__tblr_diag_box {#1}
|
|
\box_set_ht:Nn \l__tblr_diag_box { \box_ht:N \l__tblr_diag_box - \abovesep }
|
|
\box_set_dp:Nn \l__tblr_diag_box { \box_dp:N \l__tblr_diag_box - \belowsep }
|
|
\box_use:N \l__tblr_diag_box
|
|
}
|
|
|
|
%% Library functional with evaluate and process options
|
|
|
|
\cs_set_eq:NN \__tblr_functional_calculation: \prg_do_nothing:
|
|
|
|
\NewTblrLibrary { functional }
|
|
{
|
|
\RequirePackage { functional }
|
|
%% Add outer specification "evaluate"
|
|
\keys_define:nn { tblr-outer }
|
|
{ evaluate .code:n = \__tblr_outer_gput_spec:nn { evaluate } {##1} }
|
|
\tl_new:N \l__tblr_evaluate_tl
|
|
\cs_set_protected:Npn \__tblr_hook_split_before:
|
|
{
|
|
\tl_set:Nx \l__tblr_evaluate_tl
|
|
{ \__tblr_spec_item:nn { outer } { evaluate } }
|
|
\tl_if_empty:NF \l__tblr_evaluate_tl
|
|
{
|
|
\tl_if_eq:NnTF \l__tblr_evaluate_tl { all }
|
|
{
|
|
\tlSet \l__tblr_body_tl { \evalWhole {\expValue \l__tblr_body_tl} }
|
|
}
|
|
{
|
|
\exp_last_unbraced:NNV
|
|
\__tblr_evaluate_table_body:NN \l__tblr_body_tl \l__tblr_evaluate_tl
|
|
}
|
|
}
|
|
}
|
|
%% Evaluate every occurrence of the specified function
|
|
%% Note that funtional package runs every return processor inside a group
|
|
%% #1: tl with table content; #2: function to be evaluated
|
|
\tl_new:N \g__tblr_functional_result_tl
|
|
\cs_new_protected:Npn \__tblr_evaluate_table_body:NN ##1 ##2
|
|
{
|
|
\tl_gclear:N \g__tblr_functional_result_tl
|
|
\cs_set_protected:Npn \__tblr_evaluate_table_body_aux:w ####1 ##2
|
|
{
|
|
\tl_gput_right:Nn \g__tblr_functional_result_tl {####1}
|
|
\peek_meaning:NTF \q_stop { \use_none:n } {##2}
|
|
}
|
|
\fun_run_return_processor:nn
|
|
{
|
|
\exp_last_unbraced:NV \__tblr_evaluate_table_body_aux:w \gResultTl
|
|
}
|
|
{
|
|
\exp_last_unbraced:NV
|
|
\__tblr_evaluate_table_body_aux:w ##1 ##2 \q_stop
|
|
}
|
|
\tl_set_eq:NN ##1 \g__tblr_functional_result_tl
|
|
}
|
|
%% Add inner specification "process"
|
|
\clist_put_right:Nn \g__tblr_table_known_keys_clist { process }
|
|
\keys_define:nn { tblr }
|
|
{ process .code:n = \__tblr_keys_gput:nn { process } {##1} }
|
|
\cs_set:Npn \__tblr_functional_calculation:
|
|
{
|
|
\LogTblrTracing { step = do ~ functional ~ calculation }
|
|
\__tblr_prop_item:nn { inner } { process }
|
|
}
|
|
\prgNewFunction \cellGetText { m m }
|
|
{
|
|
\expWhole { \__tblr_spec_item:nn { text } { [##1][##2] } }
|
|
}
|
|
\prgNewFunction \cellSetText { m m m }
|
|
{
|
|
\__tblr_spec_gput:nnn { text } { [##1][##2] } {##3}
|
|
}
|
|
\prgNewFunction \cellSetStyle { m m m }
|
|
{
|
|
\tblr_set_cell:nnnn {##1} {##2} {} {##3}
|
|
}
|
|
\prgNewFunction \rowSetStyle { m m }
|
|
{
|
|
\tblr_set_row:nnn {##1} {} {##2}
|
|
}
|
|
\prgNewFunction \columnSetStyle { m m }
|
|
{
|
|
\tblr_set_column:nnn {##1} {} {##2}
|
|
}
|
|
}
|
|
|
|
%% Library nameref and its caption-ref template
|
|
|
|
\NewTblrLibrary { nameref }
|
|
{
|
|
\RequirePackage { nameref }
|
|
\clist_if_in:NnF \lTblrRefMoreClist { nameref }
|
|
{
|
|
\clist_put_right:Nn \lTblrRefMoreClist { nameref }
|
|
\DefTblrTemplate { caption-ref }{ nameref }
|
|
{
|
|
\tl_if_eq:NnTF \lTblrEntryTl { none }
|
|
{ \exp_args:NV \GetTitleString \lTblrCaptionTl }
|
|
{
|
|
\tl_if_empty:NTF \lTblrEntryTl
|
|
{ \exp_args:NV \GetTitleString \lTblrCaptionTl }
|
|
{ \exp_args:NV \GetTitleString \lTblrEntryTl }
|
|
}
|
|
\tl_set_eq:NN \@currentlabelname \GetTitleStringResult
|
|
}
|
|
}
|
|
}
|
|
|
|
%% Library siunitx and S columns
|
|
|
|
\NewTblrLibrary { siunitx }
|
|
{
|
|
\RequirePackage { siunitx }
|
|
\NewColumnType { S } [1] [] { Q[si = {##1}, c] }
|
|
\NewColumnType { s } [1] [] { Q[si = {##1}, c, cmd = \TblrUnit] }
|
|
\__tblr_data_new_key:nnn { cell } { si } { str }
|
|
\keys_define:nn { tblr-column }
|
|
{
|
|
si .code:n = \__tblr_siunitx_setcolumn:n {##1}
|
|
}
|
|
\cs_new_protected:Npn \__tblr_siunitx_setcolumn:n ##1
|
|
{
|
|
\__tblr_column_gput_cell:nn { si } {##1}
|
|
\__tblr_column_gput_cell:nn { cmd } { \TblrNum }
|
|
}
|
|
\NewDocumentCommand \TblrNum { m }
|
|
{
|
|
\__tblr_siunitx_process:Nn \tablenum {##1}
|
|
}
|
|
\NewDocumentCommand \TblrUnit { m }
|
|
{
|
|
\__tblr_siunitx_process:Nn \si {##1}
|
|
}
|
|
\cs_new_protected:Npn \__tblr_siunitx_process:Nn ##1 ##2
|
|
{
|
|
\tl_if_head_is_group:nTF {##2}
|
|
{ ##2 }
|
|
{
|
|
\group_begin:
|
|
\tl_set:Nx \l_tmpa_tl
|
|
{
|
|
\__tblr_data_item:neen { cell }
|
|
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { si }
|
|
}
|
|
\exp_args:NV \sisetup \l_tmpa_tl
|
|
##1 {##2}
|
|
\group_end:
|
|
}
|
|
}
|
|
\keys_define:nn { tblr-cell-spec } { guard .meta:n = { cmd = } }
|
|
\keys_define:nn { tblr-row } { guard .meta:n = { cmd = } }
|
|
\keys_define:nn { tblr-column } { guard .meta:n = { cmd = } }
|
|
}
|
|
|
|
%% Library varwidth and measure option
|
|
|
|
\NewTblrLibrary { varwidth }
|
|
{
|
|
\RequirePackage { varwidth }
|
|
\clist_gput_left:Nn \g__tblr_table_known_keys_clist { measure }
|
|
\keys_define:nn { tblr } { measure .tl_set:N = \l__tblr_inner_spec_measure_tl }
|
|
}
|
|
|
|
%% Library zref and its caption-ref template
|
|
|
|
\NewTblrLibrary { zref }
|
|
{
|
|
\RequirePackage { zref-user }
|
|
\clist_if_in:NnF \lTblrRefMoreClist { zref }
|
|
{
|
|
\clist_put_right:Nn \lTblrRefMoreClist { zref }
|
|
\DefTblrTemplate { caption-ref }{ zref }
|
|
{
|
|
\exp_args:NV \zlabel \lTblrLabelTl
|
|
}
|
|
}
|
|
}
|
|
|