elog2labfolder/_build/latex/sphinxmulticell.sty
changeset 3 b71be85a294c
equal deleted inserted replaced
2:5e51ce17f274 3:b71be85a294c
       
     1 \NeedsTeXFormat{LaTeX2e}
       
     2 \ProvidesPackage{sphinxmulticell}%
       
     3     [2017/02/23 v1.6 better span rows and columns of a table (Sphinx team)]%
       
     4 \DeclareOption*{\PackageWarning{sphinxmulticell}{Option `\CurrentOption' is unknown}}%
       
     5 \ProcessOptions\relax
       
     6 %
       
     7 % --- MULTICOLUMN ---
       
     8 % standard LaTeX's \multicolumn
       
     9 % 1. does not allow verbatim contents,
       
    10 % 2. interacts very poorly with tabulary.
       
    11 %
       
    12 % It is needed to write own macros for Sphinx: to allow code-blocks in merged
       
    13 % cells rendered by tabular/longtable, and to allow multi-column cells with
       
    14 % paragraphs to be taken into account sanely by tabulary algorithm for column
       
    15 % widths.
       
    16 %
       
    17 % This requires quite a bit of hacking. First, in Sphinx, the multi-column
       
    18 % contents will *always* be wrapped in a varwidth environment. The issue
       
    19 % becomes to pass it the correct target width. We must trick tabulary into
       
    20 % believing the multicolumn is simply separate columns, else tabulary does not
       
    21 % incorporate the contents in its algorithm. But then we must clear the
       
    22 % vertical rules...
       
    23 %
       
    24 % configuration of tabulary
       
    25 \setlength{\tymin}{3\fontcharwd\font`0 }% minimal width of "squeezed" columns
       
    26 \setlength{\tymax}{10000pt}% allow enough room for paragraphs to "compete"
       
    27 % we need access to tabulary's final computed width. \@tempdima is too volatile
       
    28 % to hope it has kept tabulary's value when \sphinxcolwidth needs it.
       
    29 \newdimen\sphinx@TY@tablewidth
       
    30 \def\tabulary{%
       
    31   \def\TY@final{\sphinx@TY@tablewidth\@tempdima\tabular}%
       
    32   \let\endTY@final\endtabular
       
    33   \TY@tabular}%
       
    34 % next hack is needed only if user has set latex_use_latex_multicolumn to True:
       
    35 % it fixes tabulary's bug with \multicolumn defined "short" in first pass. (if
       
    36 % upstream tabulary adds a \long, our extra one causes no harm)
       
    37 \def\sphinx@tempa #1\def\multicolumn#2#3#4#5#6#7#8#9\sphinx@tempa
       
    38    {\def\TY@tab{#1\long\def\multicolumn####1####2####3{\multispan####1\relax}#9}}%
       
    39 \expandafter\sphinx@tempa\TY@tab\sphinx@tempa
       
    40 %
       
    41 % TN. 1: as \omit is never executed, Sphinx multicolumn does not need to worry
       
    42 % like standard multicolumn about |l| vs l|. On the other hand it assumes
       
    43 % columns are separated by a | ... (if not it will add extraneous
       
    44 % \arrayrulewidth space for each column separation in its estimate of available
       
    45 % width).
       
    46 %
       
    47 % TN. 1b: as Sphinx multicolumn uses neither \omit nor \span, it can not
       
    48 % (easily) get rid of extra macros from >{...} or <{...} between columns. At
       
    49 % least, it has been made compatible with colortbl's \columncolor.
       
    50 %
       
    51 % TN. 2: tabulary's second pass is handled like tabular/longtable's single
       
    52 % pass, with the difference that we hacked \TY@final to set in
       
    53 % \sphinx@TY@tablewidth the final target width as computed by tabulary. This is
       
    54 % needed only to handle columns with a "horizontal" specifier: "p" type columns
       
    55 % (inclusive of tabulary's LJRC) holds the target column width in the
       
    56 % \linewidth dimension.
       
    57 %
       
    58 % TN. 3: use of \begin{sphinxmulticolumn}...\end{sphinxmulticolumn} mark-up
       
    59 % would need some hacking around the fact that groups can not span across table
       
    60 % cells (the code does inserts & tokens, see TN1b). It was decided to keep it
       
    61 % simple with \sphinxstartmulticolumn...\sphinxstopmulticolumn.
       
    62 %
       
    63 % MEMO about nesting: if sphinxmulticolumn is encountered in a nested tabular
       
    64 % inside a tabulary it will think to be at top level in the tabulary. But
       
    65 % Sphinx generates no nested tables, and if some LaTeX macro uses internally a
       
    66 % tabular this will not have a \sphinxstartmulticolumn within it!
       
    67 %
       
    68 \def\sphinxstartmulticolumn{%
       
    69     \ifx\equation$% $ tabulary's first pass
       
    70         \expandafter\sphinx@TYI@start@multicolumn
       
    71     \else % either not tabulary or tabulary's second pass
       
    72         \expandafter\sphinx@start@multicolumn
       
    73     \fi
       
    74 }%
       
    75 \def\sphinxstopmulticolumn{%
       
    76     \ifx\equation$% $ tabulary's first pass
       
    77         \expandafter\sphinx@TYI@stop@multicolumn
       
    78     \else % either not tabulary or tabulary's second pass
       
    79         \ignorespaces
       
    80     \fi
       
    81 }%
       
    82 \def\sphinx@TYI@start@multicolumn#1{%
       
    83     % use \gdef always to avoid stack space build up
       
    84     \gdef\sphinx@tempa{#1}\begingroup\setbox\z@\hbox\bgroup
       
    85 }%
       
    86 \def\sphinx@TYI@stop@multicolumn{\egroup % varwidth was used with \tymax
       
    87     \xdef\sphinx@tempb{\the\dimexpr\wd\z@/\sphinx@tempa}% per column width
       
    88     \endgroup
       
    89     \expandafter\sphinx@TYI@multispan\expandafter{\sphinx@tempa}%
       
    90 }%
       
    91 \def\sphinx@TYI@multispan #1{%
       
    92     \kern\sphinx@tempb\ignorespaces % the per column occupied width
       
    93     \ifnum#1>\@ne % repeat, taking into account subtleties of TeX's & ...
       
    94       \expandafter\sphinx@TYI@multispan@next\expandafter{\the\numexpr#1-\@ne\expandafter}%
       
    95     \fi
       
    96 }%
       
    97 \def\sphinx@TYI@multispan@next{&\relax\sphinx@TYI@multispan}%
       
    98 %
       
    99 % Now the branch handling either the second pass of tabulary or the single pass
       
   100 % of tabular/longtable. This is the delicate part where we gather the
       
   101 % dimensions from the p columns either set-up by tabulary or by user p column
       
   102 % or Sphinx \X, \Y columns. The difficulty is that to get the said width, the
       
   103 % template must be inserted (other hacks would be horribly complicated except
       
   104 % if we rewrote crucial parts of LaTeX's \@array !) and we can not do
       
   105 % \omit\span like standard \multicolumn's easy approach. Thus we must cancel
       
   106 % the \vrule separators. Also, perhaps the column specifier is of the l, c, r
       
   107 % type, then we attempt an ad hoc rescue to give varwidth a reasonable target
       
   108 % width.
       
   109 \def\sphinx@start@multicolumn#1{%
       
   110     \gdef\sphinx@multiwidth{0pt}\gdef\sphinx@tempa{#1}\sphinx@multispan{#1}%
       
   111 }%
       
   112 \def\sphinx@multispan #1{%
       
   113     \ifnum#1=\@ne\expandafter\sphinx@multispan@end
       
   114             \else\expandafter\sphinx@multispan@next
       
   115     \fi {#1}%
       
   116 }%
       
   117 \def\sphinx@multispan@next #1{%
       
   118     % trick to recognize L, C, R, J or p, m, b type columns
       
   119     \ifdim\baselineskip>\z@
       
   120        \gdef\sphinx@tempb{\linewidth}%
       
   121     \else
       
   122     % if in an l, r, c type column, try and hope for the best
       
   123        \xdef\sphinx@tempb{\the\dimexpr(\ifx\TY@final\@undefined\linewidth\else
       
   124             \sphinx@TY@tablewidth\fi-\arrayrulewidth)/\sphinx@tempa
       
   125             -\tw@\tabcolsep-\arrayrulewidth\relax}%
       
   126     \fi
       
   127     \noindent\kern\sphinx@tempb\relax
       
   128     \xdef\sphinx@multiwidth
       
   129            {\the\dimexpr\sphinx@multiwidth+\sphinx@tempb+\tw@\tabcolsep+\arrayrulewidth}%
       
   130     % hack the \vline and the colortbl macros
       
   131     \sphinx@hack@vline\sphinx@hack@CT&\relax
       
   132     % repeat
       
   133     \expandafter\sphinx@multispan\expandafter{\the\numexpr#1-\@ne}%
       
   134 }%
       
   135 % packages like colortbl add group levels, we need to "climb back up" to be
       
   136 % able to hack the \vline and also the colortbl inserted tokens. This creates
       
   137 % empty space whether or not the columns were | separated:
       
   138 \def\sphinx@hack@vline{\ifnum\currentgrouptype=6\relax
       
   139     \kern\arrayrulewidth\arrayrulewidth\z@\else\aftergroup\sphinx@hack@vline\fi}%
       
   140 \def\sphinx@hack@CT{\ifnum\currentgrouptype=6\relax
       
   141     \let\CT@setup\sphinx@CT@setup\else\aftergroup\sphinx@hack@CT\fi}%
       
   142 % It turns out \CT@row@color is not expanded contrarily to \CT@column@color
       
   143 % during LaTeX+colortbl preamble preparation, hence it would be possible for
       
   144 % \sphinx@CT@setup to discard only the column color and choose to obey or not
       
   145 % row color and cell color. It would even be possible to propagate cell color
       
   146 % to row color for the duration of the Sphinx multicolumn... the (provisional?)
       
   147 % choice has been made to cancel the colortbl colours for the multicolumn
       
   148 % duration.
       
   149 \def\sphinx@CT@setup #1\endgroup{\endgroup}% hack to remove colour commands
       
   150 \def\sphinx@multispan@end#1{%
       
   151     % first, trace back our steps horizontally
       
   152     \noindent\kern-\dimexpr\sphinx@multiwidth\relax
       
   153     % and now we set the final computed width for the varwidth environment
       
   154     \ifdim\baselineskip>\z@
       
   155        \xdef\sphinx@multiwidth{\the\dimexpr\sphinx@multiwidth+\linewidth}%
       
   156     \else
       
   157        \xdef\sphinx@multiwidth{\the\dimexpr\sphinx@multiwidth+
       
   158          (\ifx\TY@final\@undefined\linewidth\else
       
   159           \sphinx@TY@tablewidth\fi-\arrayrulewidth)/\sphinx@tempa
       
   160           -\tw@\tabcolsep-\arrayrulewidth\relax}%
       
   161     \fi
       
   162     % we need to remove colour set-up also for last cell of the multi-column
       
   163     \aftergroup\sphinx@hack@CT
       
   164 }%
       
   165 \newcommand*\sphinxcolwidth[2]{%
       
   166   % this dimension will always be used for varwidth, and serves as maximum
       
   167   % width when cells are merged either via multirow or multicolumn or both,
       
   168   % as always their contents is wrapped in varwidth environment.
       
   169   \ifnum#1>\@ne % multi-column (and possibly also multi-row)
       
   170   % we wrote our own multicolumn code especially to handle that (and allow
       
   171   % verbatim contents)
       
   172    \ifx\equation$%$
       
   173        \tymax % first pass of tabulary (cf MEMO above regarding nesting)
       
   174    \else % the \@gobble thing is for compatibility with standard \multicolumn
       
   175        \sphinx@multiwidth\@gobble{#1/#2}%
       
   176    \fi
       
   177   \else % single column multirow
       
   178    \ifx\TY@final\@undefined % not a tabulary.
       
   179     \ifdim\baselineskip>\z@
       
   180         % in a p{..} type column, \linewidth is the target box width
       
   181         \linewidth
       
   182     \else
       
   183         % l, c, r columns. Do our best.
       
   184         \dimexpr(\linewidth-\arrayrulewidth)/#2-
       
   185                 \tw@\tabcolsep-\arrayrulewidth\relax
       
   186     \fi
       
   187    \else % in tabulary
       
   188     \ifx\equation$%$% first pass
       
   189         \tymax % it is set to a big value so that paragraphs can express themselves
       
   190     \else
       
   191      % second pass.
       
   192      \ifdim\baselineskip>\z@
       
   193          \linewidth % in a L, R, C, J column or a p, \X, \Y ...
       
   194      \else
       
   195          % we have hacked \TY@final to put in \sphinx@TY@tablewidth the table width
       
   196          \dimexpr(\sphinx@TY@tablewidth-\arrayrulewidth)/#2-
       
   197                  \tw@\tabcolsep-\arrayrulewidth\relax
       
   198      \fi
       
   199     \fi
       
   200    \fi
       
   201   \fi
       
   202 }%
       
   203 % fallback default in case user has set latex_use_latex_multicolumn to True:
       
   204 % \sphinxcolwidth will use this only inside LaTeX's standard \multicolumn
       
   205 \def\sphinx@multiwidth #1#2{\dimexpr % #1 to gobble the \@gobble (!)
       
   206     (\ifx\TY@final\@undefined\linewidth\else\sphinx@TY@tablewidth\fi
       
   207      -\arrayrulewidth)*#2-\tw@\tabcolsep-\arrayrulewidth\relax}%
       
   208 %
       
   209 % --- MULTIROW ---
       
   210 % standard \multirow
       
   211 % 1. does not allow verbatim contents,
       
   212 % 2. does not allow blank lines in its argument,
       
   213 % 3. its * specifier means to typeset "horizontally" which is very
       
   214 %    bad for paragraph content. 2016 version has = specifier but it
       
   215 %    must be used with p type columns only, else results are bad,
       
   216 % 4. it requires manual intervention if the contents is too long to fit
       
   217 %    in the asked-for number of rows.
       
   218 % 5. colour panels (either from \rowcolor or \columncolor) will hide
       
   219 %    the bottom part of multirow text, hence manual tuning is needed
       
   220 %    to put the multirow insertion at the _bottom_.
       
   221 %
       
   222 % The Sphinx solution consists in always having contents wrapped
       
   223 % in a varwidth environment so that it makes sense to estimate how many
       
   224 % lines it will occupy, and then ensure by insertion of suitable struts
       
   225 % that the table rows have the needed height. The needed mark-up is done
       
   226 % by LaTeX writer, which has its own id for the merged cells.
       
   227 %
       
   228 % The colour issue is solved by clearing colour panels in all cells,
       
   229 % whether or not the multirow is single-column or multi-column.
       
   230 %
       
   231 % In passing we obtain baseline alignements across rows (only if
       
   232 % \arraylinestretch is 1, as LaTeX's does not obey \arraylinestretch in "p"
       
   233 % multi-line contents, only first and last line...)
       
   234 %
       
   235 % TODO: examine the situation with \arraylinestretch > 1. The \extrarowheight
       
   236 % is hopeless for multirow anyhow, it makes baseline alignment strictly
       
   237 % impossible.
       
   238 \newcommand\sphinxmultirow[2]{\begingroup
       
   239   % #1 = nb of spanned rows, #2 = Sphinx id of "cell", #3 = contents
       
   240   % but let's fetch #3 in a way allowing verbatim contents !
       
   241   \def\sphinx@nbofrows{#1}\def\sphinx@cellid{#2}%
       
   242   \afterassignment\sphinx@multirow\let\next=
       
   243 }%
       
   244 \def\sphinx@multirow {%
       
   245   \setbox\z@\hbox\bgroup\aftergroup\sphinx@@multirow\strut
       
   246 }%
       
   247 \def\sphinx@@multirow {%
       
   248   % The contents, which is a varwidth environment, has been captured in
       
   249   % \box0 (a \hbox).
       
   250   % We have with \sphinx@cellid an assigned unique id. The goal is to give
       
   251   % about the same height to all the involved rows.
       
   252   % For this Sphinx will insert a \sphinxtablestrut{cell_id} mark-up
       
   253   % in LaTeX file and the expansion of the latter will do the suitable thing.
       
   254   \dimen@\dp\z@
       
   255   \dimen\tw@\ht\@arstrutbox
       
   256   \advance\dimen@\dimen\tw@
       
   257   \advance\dimen\tw@\dp\@arstrutbox
       
   258   \count@=\dimen@       % type conversion dim -> int
       
   259   \count\tw@=\dimen\tw@
       
   260   \divide\count@\count\tw@ % TeX division truncates
       
   261   \advance\dimen@-\count@\dimen\tw@
       
   262   % 1300sp is about 0.02pt. For comparison a rule default width is 0.4pt.
       
   263   % (note that if \count@ holds 0, surely \dimen@>1300sp)
       
   264   \ifdim\dimen@>1300sp \advance\count@\@ne \fi
       
   265   % now \count@ holds the count L of needed "lines"
       
   266   % and \sphinx@nbofrows holds the number N of rows
       
   267   % we have L >= 1 and N >= 1
       
   268   % if L is a multiple of N, ... clear what to do !
       
   269   % else write L = qN + r, 1 <= r < N and we will
       
   270   % arrange for each row to have enough space for:
       
   271   %     q+1 "lines" in each of the first r rows
       
   272   %       q "lines" in each of the (N-r) bottom rows
       
   273   % for a total of (q+1) * r + q * (N-r) = q * N + r = L
       
   274   % It is possible that q == 0.
       
   275   \count\tw@\count@
       
   276   % the TeX division truncates
       
   277   \divide\count\tw@\sphinx@nbofrows\relax
       
   278   \count4\count\tw@ % q
       
   279   \multiply\count\tw@\sphinx@nbofrows\relax
       
   280   \advance\count@-\count\tw@ % r
       
   281   \expandafter\xdef\csname sphinx@tablestrut_\sphinx@cellid\endcsname
       
   282      {\noexpand\sphinx@tablestrut{\the\count4}{\the\count@}{\sphinx@cellid}}%
       
   283   \dp\z@\z@
       
   284   % this will use the real height if it is >\ht\@arstrutbox
       
   285   \sphinxtablestrut{\sphinx@cellid}\box\z@
       
   286   \endgroup % group was opened in \sphinxmultirow
       
   287 }%
       
   288 \newcommand*\sphinxtablestrut[1]{%
       
   289   % #1 is a "cell_id", i.e. the id of a merged group of table cells
       
   290   \csname sphinx@tablestrut_#1\endcsname
       
   291 }%
       
   292 % LaTeX typesets the table row by row, hence each execution can do
       
   293 % an update for the next row.
       
   294 \newcommand*\sphinx@tablestrut[3]{\begingroup
       
   295   % #1 = q, #2 = (initially) r, #3 = cell_id, q+1 lines in first r rows
       
   296   % if #2 = 0, create space for max(q,1) table lines
       
   297   % if #2 > 0, create space for q+1 lines and decrement #2
       
   298   \leavevmode
       
   299   \count@#1\relax
       
   300   \ifnum#2=\z@
       
   301     \ifnum\count@=\z@\count@\@ne\fi
       
   302   \else
       
   303     % next row will be with a #2 decremented by one
       
   304     \expandafter\xdef\csname sphinx@tablestrut_#3\endcsname
       
   305       {\noexpand\sphinx@tablestrut{#1}{\the\numexpr#2-\@ne}{#3}}%
       
   306    \advance\count@\@ne
       
   307   \fi
       
   308   \vrule\@height\ht\@arstrutbox
       
   309         \@depth\dimexpr\count@\ht\@arstrutbox+\count@\dp\@arstrutbox-\ht\@arstrutbox\relax
       
   310         \@width\z@
       
   311   \endgroup
       
   312   % we need this to avoid colour panels hiding bottom parts of multirow text
       
   313   \sphinx@hack@CT
       
   314 }%
       
   315 \endinput
       
   316 %%
       
   317 %% End of file `sphinxmulticell.sty'.