summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2010-10-08 22:55:52 +0000
committerKarl Berry <karl@freefriends.org>2010-10-08 22:55:52 +0000
commit0defb3a486d0ea4acc281201f2fe3dfb1fe58677 (patch)
treeb131bfc838dce3c5248b8cafc79728ca2ea348ee /Master
parent642d21e6f53417257b6ff173b9216d3862139fe1 (diff)
new latex pkg cals (8oct01)
git-svn-id: svn://tug.org/texlive/trunk@20025 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r--Master/texmf-dist/doc/latex/cals/README48
-rw-r--r--Master/texmf-dist/doc/latex/cals/cals.pdfbin0 -> 261090 bytes
-rw-r--r--Master/texmf-dist/doc/latex/cals/examples/demo.pdfbin0 -> 62193 bytes
-rw-r--r--Master/texmf-dist/doc/latex/cals/examples/demo.tex66
-rw-r--r--Master/texmf-dist/doc/latex/cals/examples/table1.tex18
-rw-r--r--Master/texmf-dist/doc/latex/cals/examples/table2.tex33
-rw-r--r--Master/texmf-dist/doc/latex/cals/examples/table3.tex33
-rw-r--r--Master/texmf-dist/doc/latex/cals/examples/table4.tex32
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/README13
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_10_create.chk45
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_10_create.tex22
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_20_colwidth.chk10
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_20_colwidth.tex9
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_30_decor.chk38
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_30_decor.tex29
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_40_width.chk26
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_40_width.tex15
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_50_hooks.chk4
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/cell/test_50_hooks.tex12
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/colsep/test_10_outone.chk62
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/colsep/test_10_outone.tex57
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/colsep/test_20_row.chk91
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/colsep/test_20_row.tex55
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_10_withwidth2.chk7
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_10_withwidth2.tex32
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_20_withcolor2.chk4
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_20_withcolor2.tex23
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_30_halfwidth.chk3
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_30_halfwidth.tex9
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_50_maxwidth.chk9
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_50_maxwidth.tex28
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_60_row.chk54
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_60_row.tex65
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_70_align.chk8
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/decoration/test_70_align.tex15
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/llt/test_10_cons_rot.chk23
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/llt/test_10_cons_rot.tex23
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/llt/test_20_snoc_decons.chk14
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/llt/test_20_snoc_decons.tex18
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/llt/test_30_all.chk24
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/llt/test_30_all.tex26
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_010_wrongbreak.chk7
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_010_wrongbreak.tex33
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_020_wrongnobreak.chk11
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_020_wrongnobreak.tex21
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_030_spanbreak.chk11
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_030_spanbreak.tex32
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_040_rowheight.chk3
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_040_rowheight.tex40
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_050_leftskip_rowspan.chk2
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/regression/test_050_leftskip_rowspan.tex24
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_10_waitrule.chk47
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_10_waitrule.tex68
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_15_waitover.chk36
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_15_waitover.tex51
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_20_pack.chk38
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_20_pack.tex32
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_30_jointwo.chk29
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_30_jointwo.tex34
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_35_joinone.chk16
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_35_joinone.tex27
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_40_construct.chk21
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/rowsep/test_40_construct.tex36
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_10_queue.chk5
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_10_queue.tex10
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_20_decor.chk84
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_20_decor.tex31
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_30_iftlrb.chk16
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_30_iftlrb.tex15
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_40_lr_queue.chk14
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_40_lr_queue.tex28
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_50_dimen.chk38
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_50_dimen.tex40
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_60_content.chk16
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_60_content.tex15
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_70_intercept.chk16
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_70_intercept.tex28
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_80_marker.chk20
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/span/test_80_marker.tex35
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/support/LatexTest.py163
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/support/run_tests.py66
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_10_ifbreak.chk22
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_10_ifbreak.tex53
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_20_dispatch.chk56
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_20_dispatch.tex65
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_30_issue_rowsep.chk110
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_30_issue_rowsep.tex52
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_40_issuerow.chk27
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_40_issuerow.tex25
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_50_row.chk99
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_50_row.tex44
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_60_whitespace.chk2
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_60_whitespace.tex21
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_70_lrskip.chk32
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/table/test_70_lrskip.tex22
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/template.txt33
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.chk0
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.pngbin0 -> 29731 bytes
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.tex11
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.chk0
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.pngbin0 -> 36579 bytes
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.tex20
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.chk0
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.pngbin0 -> 40690 bytes
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.tex27
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.chk0
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.pngbin0 -> 42576 bytes
-rw-r--r--Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.tex52
-rw-r--r--Master/texmf-dist/source/latex/cals/cals.dtx168
-rw-r--r--Master/texmf-dist/source/latex/cals/cals.ins62
-rw-r--r--Master/texmf-dist/source/latex/cals/cell.dtx314
-rw-r--r--Master/texmf-dist/source/latex/cals/colsep.dtx126
-rw-r--r--Master/texmf-dist/source/latex/cals/decor.dtx227
-rw-r--r--Master/texmf-dist/source/latex/cals/lltokens.dtx170
-rw-r--r--Master/texmf-dist/source/latex/cals/rowsep.dtx360
-rw-r--r--Master/texmf-dist/source/latex/cals/span.dtx176
-rw-r--r--Master/texmf-dist/source/latex/cals/table.dtx387
-rw-r--r--Master/texmf-dist/tex/latex/cals/cals.sty703
-rwxr-xr-xMaster/tlpkg/bin/tlpkg-ctan-check2
-rwxr-xr-xMaster/tlpkg/libexec/ctan2tds7
-rw-r--r--Master/tlpkg/tlpsrc/cals.tlpsrc0
-rw-r--r--Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc1
122 files changed, 5837 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/latex/cals/README b/Master/texmf-dist/doc/latex/cals/README
new file mode 100644
index 00000000000..e6bfcf975a5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/README
@@ -0,0 +1,48 @@
+CALS tables
+
+The "cals" package is a set of macros to typeset multipage tables
+with repeatable headers and footers, with cells spanned over
+rows and columns. Decorations are supported: padding, background
+color, width of separation rules. The code is compatible with
+multicols and pdfsync.
+
+The work is released to public (LaTeX license, see below)
+by bitplant.de GmbH, a company which provides technical
+documentation services to industry.
+
+
+Contents:
+
+README:
+ This file.
+
+cals.pdf:
+ Documentation.
+
+dev/
+ The source code of the package. To generate cals.sty:
+ $ cd cals
+ $ latex cals.ins
+
+examples/
+ The file "demo.pdf", produced from "demo.tex" and several
+ include files, demonstrates features of the cals package.
+ To re-generate demo.pdf, after you got cals.ins:
+ $ export TEXINPUTS=../cals:
+ $ pdflatex demo.tex
+
+tests/
+ Unit tests. See "README" inside.
+
+
+Copyright (C) 2010 by Oleg Parashchenko <olpa uucode com>
+
+Files from this pacjage may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3c
+of this license or (at your option) any later version.
+The latest version of this license is in:
+
+http://www.latex-project.org/lppl.txt
+
+and version 1.3c or later is part of all distributions of LaTeX
+version 2006/05/20 or later.
diff --git a/Master/texmf-dist/doc/latex/cals/cals.pdf b/Master/texmf-dist/doc/latex/cals/cals.pdf
new file mode 100644
index 00000000000..0e9bafd05b3
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/cals.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/cals/examples/demo.pdf b/Master/texmf-dist/doc/latex/cals/examples/demo.pdf
new file mode 100644
index 00000000000..2428fd5375d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/examples/demo.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/cals/examples/demo.tex b/Master/texmf-dist/doc/latex/cals/examples/demo.tex
new file mode 100644
index 00000000000..2dfe0c03e53
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/examples/demo.tex
@@ -0,0 +1,66 @@
+\documentclass[twocolumn]{minimal}
+\usepackage[paper=a5paper,landscape=true,margin=1cm,
+ twocolumn=true,columnsep=1cm]{geometry}
+\usepackage[T1]{fontenc}
+\usepackage{helvet}
+\usepackage{times}
+\usepackage{color}
+\usepackage{fancyvrb}
+\usepackage{multicol}
+\usepackage{cals}
+\usepackage{pdfsync}
+
+% pdfsync setup. The command \pdfsyncstart is not defined yet,
+% therefore I use "def" instead of "let".
+\makeatletter
+\let\oldcalstable=\calstable
+\def\calstable{\oldcalstable\pdfsyncstop}
+\def\cals@AtBeginCell{\pdfsyncstart}
+
+\newcommand\newcolumn{\vfil\penalty-10000 }
+\newcommand\small{\fontsize{9pt}{11pt}\selectfont}
+\newcommand\Small{\fontsize{8pt}{9pt}\selectfont}
+\newcommand\Large{\fontsize{12pt}{14pt}\selectfont}
+
+\newcommand\header[1]{\noindent{\Large\bfseries#1\strut}\par\bigskip}
+
+\showboxdepth=100
+\showboxbreadth=100
+
+\begin{document}
+\makeatletter
+
+\header{CALS tables demo}
+\newcolumn
+\parindent=0pt
+by Oleg Parashchenko\par
+\textless{}olpa uucode com\textgreater\par
+\par
+26 August 2010\par
+\clearpage
+
+\header{Simple table}
+\input table1
+\newcolumn
+\VerbatimInput{table1.tex}
+\clearpage
+
+\header{Decorations}
+\input table2
+\newcolumn
+\VerbatimInput[fontsize=\small]{table2.tex}
+\clearpage
+
+\header{Cell spanning}
+\input table3
+\newcolumn
+\VerbatimInput[fontsize=\small]{table3.tex}
+\clearpage
+
+\header{Multipage table (in a multicols in a table)}
+\input table4
+\newcolumn
+\VerbatimInput[fontsize=\small]{table4.tex}
+\clearpage
+
+\end{document}
diff --git a/Master/texmf-dist/doc/latex/cals/examples/table1.tex b/Master/texmf-dist/doc/latex/cals/examples/table1.tex
new file mode 100644
index 00000000000..28d367c2b12
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/examples/table1.tex
@@ -0,0 +1,18 @@
+\begin{calstable}
+\colwidths{{3cm}{4cm}}
+\thead{
+ I'm a caption in the header\par
+ \bfseries
+ \brow \cell{head 1.1}\cell{head 1.2} \erow
+ \brow \cell{head 2.1}\cell{head 2.2} \erow
+ \mdseries}
+
+\tfoot{
+ \brow \cell{foot 1.1} \cell{foot 1.2} \erow
+ \lastrule
+ I'm a caption in the footer\par}
+
+\brow \cell{body 1.1}\cell{body 1.2} \erow
+\brow \cell{body 2.1}\cell{body 2.2} \erow
+\brow \cell{body 3.1}\cell{body 3.2} \erow
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/examples/table2.tex b/Master/texmf-dist/doc/latex/cals/examples/table2.tex
new file mode 100644
index 00000000000..b4515f622ee
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/examples/table2.tex
@@ -0,0 +1,33 @@
+\makeatletter
+\newcommand\bbrow{\brow\setbox\cals@current@row=
+ \hbox{\vbox to 3cm{}}}
+
+\newenvironment{decotable}{\begin{calstable}
+\fontsize{15pt}{17pt}\selectfont
+\cals@setpadding{Ag}\cals@setcellprevdepth{Al}
+\cals@paddingL=0pt \relax
+\cals@paddingR=0pt \relax
+\def\cals@framecs@width{2pt}
+\def\cals@rs@width{8pt}
+\def\cals@cs@width{4pt}
+}{\end{calstable}}
+
+\begin{decotable}
+\colwidths{{3cm}{3cm}{3cm}}
+\bbrow
+ \cell{left,\\top}
+ \alignC \cell{center,\\top}
+ \def\cals@borderL{0pt}\def\cals@borderB{0pt}
+ \alignR \cell{right,\\top} \erow
+ \let\cals@borderL=\relax \let\cals@borderB=\relax
+\bbrow
+ \alignL \cell{\vfil left,\\middle}
+ \alignC \cell{\vfil center,\\middle}
+ \alignR \cell{\vfil right,\\middle} \erow
+\bbrow
+ \def\cals@bgcolor{green}
+ \alignL \cell{\vfill left,\\bottom}
+ \def\cals@bgcolor{}
+ \alignC \cell{\vfill center,\\bottom}
+ \alignR \cell{\vfill right,\\bottom} \erow
+\end{decotable}
diff --git a/Master/texmf-dist/doc/latex/cals/examples/table3.tex b/Master/texmf-dist/doc/latex/cals/examples/table3.tex
new file mode 100644
index 00000000000..2a740fafd97
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/examples/table3.tex
@@ -0,0 +1,33 @@
+\makeatletter \let\olderow=\erow
+\def\erow{\ht\cals@current@row=1.3cm \olderow}
+
+\begin{calstable}
+\def\cals@framecs@width{.4pt}
+\def\cals@framers@width{.4pt}
+\colwidths{{1.3cm}}
+\brow
+ \cell{a6} \cell{b6} \cell{c6}
+ \cell{d6} \cell{e6} \cell{f6} \erow
+\brow
+ \cell{a5} \nullcell{ltb} \nullcell{tb}
+ \nullcell{rtb}\spancontent{b5, c5, d5}
+ \nullcell{ltr} \cell{f5} \erow
+\brow
+ \cell{a4} \nullcell{ltr} \nullcell{tl}
+ \nullcell{tr} \nullcell{lr} \cell{f4} \erow
+\brow
+ \cell{a3} \nullcell{lr} \nullcell{lb}
+ \nullcell{rb}\spancontent{c3, c4, d3, d4}
+ \nullcell{lrb}\spancontent{e3, e4, e5}
+ \cell{f3} \erow
+\brow
+ \cell{a2}
+ \nullcell{lrb}\spancontent{b2, b3, b4}
+ \nullcell{ltb} \nullcell{tb}
+ \nullcell{tbr}\spancontent{c2, d2, e2}
+ \cell{f2} \erow
+\brow
+ \cell{a1} \cell{b1} \cell{c1}
+ \cell{d1} \cell{e1} \cell{f1} \erow
+\end{calstable}
+\let\erow=\olderow
diff --git a/Master/texmf-dist/doc/latex/cals/examples/table4.tex b/Master/texmf-dist/doc/latex/cals/examples/table4.tex
new file mode 100644
index 00000000000..5f19645ddb1
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/examples/table4.tex
@@ -0,0 +1,32 @@
+\begin{calstable}
+\colwidths{{1cm}{7cm}{1cm}}
+\brow \cell{x} \cell{x} \cell{x} \erow
+\brow \cell{x} \cell{
+\columnsep=0cm\relax
+% Force multicols to regard our \leftskip
+% by pretending that we are a list.
+\@totalleftmargin=\cals@paddingL\relax
+\begin{multicols}{2}
+
+\begin{calstable}
+\alignR
+\colwidths{{1.5cm}{1.5cm}}
+\thead{\brow \cell{$n$}\cell{$n^2$} \erow}
+\tfoot{\brow \cell{$n$}\cell{$n^2$} \erow}
+\brow \cell{2} \cell{4} \erow
+\brow \cell{3} \cell{9} \erow
+\brow \cell{4} \cell{16} \erow
+\brow \cell{5} \cell{25} \erow
+\brow \cell{6} \cell{36} \erow
+\tbreak{\break }
+\brow \cell{7} \cell{49} \erow
+\brow \cell{8} \cell{64} \erow
+\brow \cell{9} \cell{81} \erow
+\brow \cell{10} \cell{100} \erow
+\brow \cell{11} \cell{121} \erow
+\end{calstable}
+
+\end{multicols}
+} \cell{x} \erow
+\brow \cell{x} \cell{x} \cell{x} \erow
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/README b/Master/texmf-dist/doc/latex/cals/test/README
new file mode 100644
index 00000000000..08e9f94dd16
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/README
@@ -0,0 +1,13 @@
+Unit tests for the CALS package. Usage:
+
+$ export TEXINPUTS=`pwd`/../cals:
+$ python support/run_tests.py
+ or, to execute a subset of the tests,
+$ python support/run_tests.py cell/test_10
+
+Expect that the tests in the directory "visual_tables" fail.
+Depending on the OS and TeX distro version, the font drawing
+might look different.
+
+Probably I need to package the unit testing code as a separate
+package and publish an article about it.
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_10_create.chk b/Master/texmf-dist/doc/latex/cals/test/cell/test_10_create.chk
new file mode 100644
index 00000000000..e30f50c4cd1
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_10_create.chk
@@ -0,0 +1,45 @@
+> \boxXX=
+\vbox(40.0+0.0)x200.0
+.\glue 14.0
+.\glue 0.0 plus -1.0
+.\glue(\parskip) 0.0 plus 1.0
+.\glue(\baselineskip) 6.0
+.\hbox(3.0+2.0)x200.0, glue set 174.0fil
+..\glue(\leftskip) 12.0
+..\rule(3.0+2.0)x1.0
+..\penalty 10000
+..\glue(\parfillskip) 0.0 plus 1.0fil
+..\glue(\rightskip) 13.0
+.\glue 0.0 plus 1.0fil
+.\glue 15.0
+> \boxXX=
+\vbox(-60.0+0.0)x200.0
+.\glue -100.0
+.\glue 14.0
+.\glue 0.0 plus -1.0
+.\glue(\parskip) 0.0 plus 1.0
+.\glue(\baselineskip) 6.0
+.\hbox(3.0+2.0)x200.0, glue set 174.0fil
+..\glue(\leftskip) 12.0
+..\rule(3.0+2.0)x1.0
+..\penalty 10000
+..\glue(\parfillskip) 0.0 plus 1.0fil
+..\glue(\rightskip) 13.0
+.\glue 0.0 plus 1.0fil
+.\glue 15.0
+%
+% Zero width
+%
+> \boxXX=
+\vbox(50.0+0.0)x200.0
+.\glue 0.0
+.\glue 0.0 plus -1.0
+.\glue(\parskip) 0.0 plus 1.0
+.\glue(\lineskip) 0.0
+.\hbox(50.0+0.0)x200.0
+..\rule(50.0+0.0)x200.0
+..\penalty 10000
+..\glue(\parfillskip) 0.0 plus 1.0fil
+..\glue(\rightskip) 0.0
+.\glue 0.0 plus 1.0fil
+.\glue 0.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_10_create.tex b/Master/texmf-dist/doc/latex/cals/test/cell/test_10_create.tex
new file mode 100644
index 00000000000..6692b6e6141
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_10_create.tex
@@ -0,0 +1,22 @@
+\cals@paddingL=12pt \relax
+\cals@paddingR=13pt \relax
+\setlength{\cals@paddingT}{14pt}
+\setlength{\cals@paddingB}{15pt}
+
+\cals@paddingD=1pt \relax
+\setlength{\baselineskip}{10pt}
+
+\def\cals@celll@end{}
+
+\setbox0=\cals@cell{200pt}{0pt}{\noindent \vrule height3pt depth2pt width1pt}
+\showbox0
+
+\setbox0=\cals@cell{200pt}{100pt}{\noindent \vrule height3pt depth2pt width1pt}
+\showbox0
+
+%
+% Zero width makes exact size
+%
+\cals@setpadding{}\cals@setcellprevdepth{}
+\setbox0=\cals@cell{200pt}{0pt}{\noindent \vrule height50pt depth0pt width200pt}
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_20_colwidth.chk b/Master/texmf-dist/doc/latex/cals/test/cell/test_20_colwidth.chk
new file mode 100644
index 00000000000..9bc5c27f1c5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_20_colwidth.chk
@@ -0,0 +1,10 @@
+> \cals@colwidths=macro:
+->{100pt}{200pt}.
+> \llt@car=macro:
+->100pt.
+> \cals@colwidths=macro:
+->{200pt}{100pt}.
+> \llt@car=macro:
+->200pt.
+> \cals@colwidths=macro:
+->{100pt}{200pt}.
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_20_colwidth.tex b/Master/texmf-dist/doc/latex/cals/test/cell/test_20_colwidth.tex
new file mode 100644
index 00000000000..ec8a1f3f9a8
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_20_colwidth.tex
@@ -0,0 +1,9 @@
+\def\x{200pt}
+\colwidths{{100pt}{\x}}
+\show\cals@colwidths
+\llt@rot\cals@colwidths
+\show\llt@car
+\show\cals@colwidths
+\llt@rot\cals@colwidths
+\show\llt@car
+\show\cals@colwidths
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_30_decor.chk b/Master/texmf-dist/doc/latex/cals/test/cell/test_30_decor.chk
new file mode 100644
index 00000000000..6b6be1d2cfc
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_30_decor.chk
@@ -0,0 +1,38 @@
+> \boxXX=
+\hbox(0.0+0.0)x100.0
+.\pdfcolorstack 0 push {1 0 0 rg 1 0 0 RG}
+.\rule(*+0.0)x100.0
+.\pdfcolorstack 0 pop
+.\glue -100.0
+.\glue 100.0
+> \cals@lastWidth=\relax.
+%
+%
+> \boxXX=
+\hbox(0.0+0.0)x300.0
+.\pdfcolorstack 0 push {1 0 0 rg 1 0 0 RG}
+.\rule(*+0.0)x100.0
+.\pdfcolorstack 0 pop
+.\glue -100.0
+.\glue 100.0
+.\pdfcolorstack 0 push {0 1 0 rg 0 1 0 RG}
+.\rule(*+0.0)x200.0
+.\pdfcolorstack 0 pop
+.\glue -200.0
+.\glue -1.0
+.\rule(*+0.0)x2.0
+.\glue -1.0
+.\glue 200.0
+> \cals@current@rs@above=macro:
+->{{100pt}{0pt}{2pt}\relax }.
+> \cals@current@rs@below=macro:
+->{{100pt}{0pt}{2pt}\relax }.
+> \cals@lastWidth=macro:
+->4pt.
+%
+%
+%
+> \cals@current@rs@above=macro:
+->{{100pt}{0pt}{2pt}\relax }{{200pt}{2pt}{4pt}{3pt}}.
+> \cals@current@rs@below=macro:
+->{{100pt}{0pt}{2pt}\relax }{{200pt}{2pt}{4pt}{5pt}}.
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_30_decor.tex b/Master/texmf-dist/doc/latex/cals/test/cell/test_30_decor.tex
new file mode 100644
index 00000000000..ee65891a60b
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_30_decor.tex
@@ -0,0 +1,29 @@
+\def\cals@framecs@width{0pt}
+\def\cals@cs@width{1pt}
+\def\cals@bgcolor{red}
+
+\let\cals@borderL=\relax
+\let\cals@borderR=\relax
+\let\cals@borderT=\relax
+\let\cals@borderB=\relax
+
+\colwidths{{100pt}{200pt}}
+\cals@decor@begin
+
+\cell{aaaa}
+\showbox\cals@current@cs
+\show\cals@lastWidth
+\def\cals@borderL{2pt}
+\def\cals@borderT{3pt}
+\def\cals@borderR{4pt}
+\def\cals@borderB{5pt}
+\def\cals@bgcolor{green}
+\cell{b}
+\showbox\cals@current@cs
+\show\cals@current@rs@above
+\show\cals@current@rs@below
+\show\cals@lastWidth
+
+\cals@decor@end\cals@borderR
+\show\cals@current@rs@above
+\show\cals@current@rs@below
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_40_width.chk b/Master/texmf-dist/doc/latex/cals/test/cell/test_40_width.chk
new file mode 100644
index 00000000000..b3af972f4a5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_40_width.chk
@@ -0,0 +1,26 @@
+> \boxXX=
+\hbox(20.0+0.0)x300.0
+.\vbox(0.0+0.0)x100.0
+..\glue 0.0
+..\glue 0.0 plus -1.0
+..\glue 0.0 plus 1.0fil
+..\glue 0.0
+.\vbox(20.0+0.0)x200.0
+..\glue 0.0
+..\glue 0.0 plus -1.0
+..\rule(20.0+0.0)x300.0
+..\glue 0.0 plus 1.0fil
+..\glue 0.0
+> \boxXX=
+\hbox(20.0+0.0)x300.0
+.\vbox(20.0+0.0)x100.0, glue set 20.0fil
+..\glue 0.0
+..\glue 0.0 plus -1.0
+..\glue 0.0 plus 1.0fil
+..\glue 0.0
+.\vbox(20.0+0.0)x200.0
+..\glue 0.0
+..\glue 0.0 plus -1.0
+..\rule(20.0+0.0)x300.0
+..\glue 0.0 plus 1.0fil
+..\glue 0.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_40_width.tex b/Master/texmf-dist/doc/latex/cals/test/cell/test_40_width.tex
new file mode 100644
index 00000000000..0f3816cfd9c
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_40_width.tex
@@ -0,0 +1,15 @@
+%
+% Force width if force major
+%
+\begin{calstable}
+\cals@setpadding{}
+\cals@setcellprevdepth{}
+\colwidths{{100pt}{200pt}}
+\brow
+\cell{}
+\cell{\hrule width300pt height20pt depth0pt}
+\showbox\cals@current@row
+\cals@reheight@cells\cals@current@row
+\showbox\cals@current@row
+\erow
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_50_hooks.chk b/Master/texmf-dist/doc/latex/cals/test/cell/test_50_hooks.chk
new file mode 100644
index 00000000000..7ab3e2dbc36
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_50_hooks.chk
@@ -0,0 +1,4 @@
+> the letter A.
+> the letter B.
+> the letter C.
+> the letter D.
diff --git a/Master/texmf-dist/doc/latex/cals/test/cell/test_50_hooks.tex b/Master/texmf-dist/doc/latex/cals/test/cell/test_50_hooks.tex
new file mode 100644
index 00000000000..21ef65f571a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/cell/test_50_hooks.tex
@@ -0,0 +1,12 @@
+\begin{calstable}
+\colwidths{{100pt}}
+\brow
+\def\cals@AtBeginCell{\show A}
+\def\cals@AtEndCell{\show B}
+\cell{a}
+\def\cals@AtBeginCell{\show C}
+\def\cals@AtEndCell{\show D}
+\nullcell{ltb}
+\nullcell{rtb}\spancontent{b}
+\erow
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/colsep/test_10_outone.chk b/Master/texmf-dist/doc/latex/cals/test/colsep/test_10_outone.chk
new file mode 100644
index 00000000000..40befd43b3a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/colsep/test_10_outone.chk
@@ -0,0 +1,62 @@
+%
+% test1
+%
+> \cals@lastLeftWidth=macro:
+->0pt.
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+%
+% test2
+%
+> \cals@lastLeftWidth=macro:
+->4pt.
+> \boxXX=
+\hbox(0.0+0.0)x50.0
+.\pdfcolorstack 0 push {1 0 0 rg 1 0 0 RG}
+.\rule(*+0.0)x50.0
+.\pdfcolorstack 0 pop
+.\glue -50.0
+.\glue -2.0
+.\rule(*+0.0)x4.0
+.\glue -2.0
+.\glue 50.0
+%
+% test3
+%
+> \cals@lastLeftWidth=macro:
+->2pt.
+> \boxXX=
+\hbox(0.0+0.0)x100.0
+.\pdfcolorstack 0 push {0 1 0 rg 0 1 0 RG}
+.\rule(*+0.0)x100.0
+.\pdfcolorstack 0 pop
+.\glue -100.0
+.\glue -1.0
+.\rule(*+0.0)x2.0
+.\glue -1.0
+.\glue 100.0
+%
+% test4
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+.\glue -1.0
+.\rule(*+0.0)x2.0
+.\glue -1.0
+%
+% test5
+%
+> \boxXX=
+\hbox(0.0+0.0)x300.0
+.\glue 300.0
+%
+% test6
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+.\glue 0.0
+%
+% test7
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/colsep/test_10_outone.tex b/Master/texmf-dist/doc/latex/cals/test/colsep/test_10_outone.tex
new file mode 100644
index 00000000000..fec00899ac7
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/colsep/test_10_outone.tex
@@ -0,0 +1,57 @@
+%
+%
+\def\cals@cs@width{2pt}
+\def\cals@bgcolor{green}
+
+%
+% cals@cs@outone:
+% #1: cell width
+% #2: left border width
+% #3: background color
+%
+%
+% test1: everything disabled
+%
+\setbox0=\hbox{\cals@cs@outOne\relax{0pt}{}%
+\show\cals@lastLeftWidth
+}
+\showbox0
+
+%
+% test2: everything specified
+%
+\setbox0=\hbox{\cals@cs@outOne{50pt}{4pt}{red}%
+\show\cals@lastLeftWidth
+}
+\showbox0
+%
+% test3: use defaults for everything
+%
+\setbox0=\hbox{\cals@cs@outOne{100pt}\relax\relax%
+\show\cals@lastLeftWidth
+}
+\showbox0
+%
+% test4: background color ignored if no cell width
+%
+\setbox0=\hbox{\cals@cs@outOne\relax{2pt}{green}}
+\showbox0
+%
+% test5: defaults are no colors, no borders
+%
+\def\cals@cs@width{0pt}
+\def\cals@bgcolor{}
+\setbox0=\hbox{\cals@cs@outOne{300pt}\relax\relax}
+\showbox0
+%
+% test6: cell width: 0pt != \relax
+%
+\setbox0=\hbox{\cals@cs@outOne{0pt}{0pt}{}}
+\showbox0
+
+%
+% test7: only \relax
+% (Bug hunting for a space)
+%
+\setbox0=\hbox{\cals@cs@outOne\relax\relax\relax}
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/colsep/test_20_row.chk b/Master/texmf-dist/doc/latex/cals/test/colsep/test_20_row.chk
new file mode 100644
index 00000000000..01e57020f16
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/colsep/test_20_row.chk
@@ -0,0 +1,91 @@
+%
+% Test 1
+%
+> \boxXX=
+\hbox(0.0+0.0)x210.0
+% first cell
+.\pdfcolorstack 0 push {0 1 0 rg 0 1 0 RG}
+.\rule(*+0.0)x100.0
+.\pdfcolorstack 0 pop
+.\glue -100.0
+.\glue -1.5
+.\rule(*+0.0)x3.0
+.\glue -1.5
+.\glue 100.0
+% second cell
+.\pdfcolorstack 0 push {1 0 0 rg 1 0 0 RG}
+.\rule(*+0.0)x110.0
+.\pdfcolorstack 0 pop
+.\glue -110.0
+.\glue -2.5
+.\rule(*+0.0)x5.0
+.\glue -2.5
+.\glue 110.0
+% right frame
+.\glue -3.0
+.\rule(*+0.0)x6.0
+.\glue -3.0
+%
+% Test2 (no columns, only frame border)
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+.\glue -1.0
+.\rule(*+0.0)x2.0
+.\glue -1.0
+%
+% Test3 (defaults are used)
+%
+> \boxXX=
+\hbox(0.0+0.0)x250.0
+% first cell
+.\pdfcolorstack 0 push {0 g 0 G}
+.\rule(*+0.0)x120.0
+.\pdfcolorstack 0 pop
+.\glue -120.0
+.\glue -1.0
+.\rule(*+0.0)x2.0
+.\glue -1.0
+.\glue 120.0
+% second cell
+.\pdfcolorstack 0 push {0 g 0 G}
+.\rule(*+0.0)x130.0
+.\pdfcolorstack 0 pop
+.\glue -130.0
+.\glue -0.5
+.\rule(*+0.0)x1.0
+.\glue -0.5
+.\glue 130.0
+% right frame
+.\glue -1.0
+.\rule(*+0.0)x2.0
+.\glue -1.0
+%
+% Test 4: frame width is bigger as user-specified
+%
+> \boxXX=
+\hbox(0.0+0.0)x100.0
+.\glue -1.5
+.\rule(*+0.0)x3.0
+.\glue -1.5
+.\glue 100.0
+.\glue -2.0
+.\rule(*+0.0)x4.0
+.\glue -2.0
+> \boxXX=
+\hbox(0.0+0.0)x100.0
+.\glue -1.5
+.\rule(*+0.0)x3.0
+.\glue -1.5
+.\glue 100.0
+.\glue -2.0
+.\rule(*+0.0)x4.0
+.\glue -2.0
+%
+% Bug hunting for a space
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+.\glue -5.0
+.\rule(*+0.0)x10.0
+.\glue -5.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/colsep/test_20_row.tex b/Master/texmf-dist/doc/latex/cals/test/colsep/test_20_row.tex
new file mode 100644
index 00000000000..db97970dd32
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/colsep/test_20_row.tex
@@ -0,0 +1,55 @@
+\def\cals@cs@width{1pt}
+\def\cals@framecs@width{2pt}
+\def\cals@bgcolor{black}
+
+%
+% Normal use
+%
+\cals@csrow@begin
+\def\rborder{4pt}
+\cals@csrow@nextcell{100pt}{3pt}\rborder{green}
+\def\rborder{6pt}
+\cals@csrow@nextcell{110pt}{5pt}\rborder{red}
+\cals@csrow@end
+\showbox\cals@current@cs
+
+%
+% What happens if we have no columns (should never happen)
+%
+\cals@csrow@begin
+\cals@csrow@end
+\showbox\cals@current@cs
+
+%
+% Defaults are used
+%
+\cals@csrow@begin
+\cals@csrow@nextcell{120pt}\relax\relax\relax
+\cals@csrow@nextcell{130pt}\relax\relax\relax
+\cals@csrow@end
+\showbox\cals@current@cs
+
+%
+% test: left frame is bigger as the user-specified width:
+% we should not use the maximal width, but drop the default.
+% (The first run is not for the test, but for comparation.)
+%
+\def\rborder{4pt}
+\def\cals@framecs@width{2pt}
+\cals@csrow@begin
+\cals@csrow@nextcell{100pt}{3pt}\rborder{}
+\cals@csrow@end
+\showbox\cals@current@cs
+\def\cals@framecs@width{10pt}
+\cals@csrow@begin
+\cals@csrow@nextcell{100pt}{3pt}\rborder{}
+\cals@csrow@end
+\showbox\cals@current@cs
+
+%
+% Bug hunting (a space)
+%
+\setbox\cals@current@cs=\hbox{}
+\let\cals@lastWidth=\relax
+\cals@csrow@nextcell\relax\cals@framecs@width\relax\relax
+\showbox\cals@current@cs
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_10_withwidth2.chk b/Master/texmf-dist/doc/latex/cals/test/decoration/test_10_withwidth2.chk
new file mode 100644
index 00000000000..8921cc46ba2
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_10_withwidth2.chk
@@ -0,0 +1,7 @@
+user width: 5pt
+no width
+default width: 2pt
+no width
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+.\hbox(0.0+0.0)x0.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_10_withwidth2.tex b/Master/texmf-dist/doc/latex/cals/test/decoration/test_10_withwidth2.tex
new file mode 100644
index 00000000000..40f4832b877
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_10_withwidth2.tex
@@ -0,0 +1,32 @@
+\cals@withWidthII{1pt}{5pt}\iftrue
+ \PackageInfo{test}{user width: \cals@width}
+\else
+ \PackageInfo{test}{fail}
+\fi
+
+\def\defaultDimen{2pt}
+\cals@withWidthII\defaultDimen{0pt}\iftrue
+ \PackageInfo{test}{fail}
+\else
+ \PackageInfo{test}{no width}
+\fi
+
+\cals@withWidthII\defaultDimen\relax\iftrue
+ \PackageInfo{test}{default width: \cals@width}
+\else
+ \PackageInfo{test}{fail}
+\fi
+
+\cals@withWidthII{0pt}\relax\iftrue
+ \PackageInfo{test}{fail}
+\else
+ \PackageInfo{test}{no width}
+\fi
+
+%
+% Bug hunting: a space
+%
+\def\cals@default@cs@width{4pt}
+\setbox0=\hbox{\hbox{}%
+\cals@withWidthII\cals@default@cs@width\relax\iftrue \fi}
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_20_withcolor2.chk b/Master/texmf-dist/doc/latex/cals/test/decoration/test_20_withcolor2.chk
new file mode 100644
index 00000000000..a959bc92cfb
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_20_withcolor2.chk
@@ -0,0 +1,4 @@
+user color: blue
+(user) no color
+default color: black
+(default) no color
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_20_withcolor2.tex b/Master/texmf-dist/doc/latex/cals/test/decoration/test_20_withcolor2.tex
new file mode 100644
index 00000000000..9bb4c78f4dc
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_20_withcolor2.tex
@@ -0,0 +1,23 @@
+\cals@withColorII{black}{blue}\iftrue
+ \PackageInfo{test}{user color: \cals@color }
+\else
+ \PackageInfo{test}{fail}
+\fi
+
+\cals@withColorII{black}{}\iftrue
+ \PackageInfo{test}{fail}
+\else
+ \PackageInfo{test}{(user) no color}
+\fi
+
+\cals@withColorII{black}\relax\iftrue
+ \PackageInfo{test}{default color: \cals@color}
+\else
+ \PackageInfo{test}{fail}
+\fi
+
+\cals@withColorII{}\relax\iftrue
+ \PackageInfo{test}{fail}
+\else
+ \PackageInfo{test}{(default) no color}
+\fi
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_30_halfwidth.chk b/Master/texmf-dist/doc/latex/cals/test/decoration/test_30_halfwidth.chk
new file mode 100644
index 00000000000..7f00f1944e9
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_30_halfwidth.chk
@@ -0,0 +1,3 @@
+half of 200pt: 100.0pt
+half of 0pt: 0.0pt
+half of 100pt: 50.0pt
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_30_halfwidth.tex b/Master/texmf-dist/doc/latex/cals/test/decoration/test_30_halfwidth.tex
new file mode 100644
index 00000000000..a9aee3cab49
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_30_halfwidth.tex
@@ -0,0 +1,9 @@
+\def\cals@width{200pt}
+\cals@halfWidthToDimen0 \cals@width
+\PackageInfo{test}{half of 200pt: \the\dimen0}
+
+\cals@halfWidthToDimen0 {0pt}
+\PackageInfo{test}{half of 0pt: \the\dimen0}
+
+\cals@halfWidthToDimen2{100pt}
+\PackageInfo{test}{half of 100pt: \the\dimen2}
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_50_maxwidth.chk b/Master/texmf-dist/doc/latex/cals/test/decoration/test_50_maxwidth.chk
new file mode 100644
index 00000000000..33b32e6078a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_50_maxwidth.chk
@@ -0,0 +1,9 @@
+10pt vs relax: 10pt
+relax vs 20pt: 20pt
+relax vs relax: \cals@width
+30pt vs 40pt: 40pt
+60pt vs 50pt: 60pt
+70pt vs 70pt: 70pt
+regression, recursion avoid: 50pt
+regression, recursion avoid: 50pt
+regression, recursion avoid: 50pt
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_50_maxwidth.tex b/Master/texmf-dist/doc/latex/cals/test/decoration/test_50_maxwidth.tex
new file mode 100644
index 00000000000..e3e899c1f86
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_50_maxwidth.tex
@@ -0,0 +1,28 @@
+\cals@maxWidth{10pt}\relax
+\PackageInfo{test}{10pt vs relax: \cals@width}
+
+\cals@maxWidth\relax{20pt}
+\PackageInfo{test}{relax vs 20pt: \cals@width}
+
+\cals@maxWidth\relax\relax
+\PackageInfo{test}{relax vs relax: \cals@width}
+
+\cals@maxWidth{30pt}{40pt}
+\PackageInfo{test}{30pt vs 40pt: \cals@width}
+
+\cals@maxWidth{60pt}{50pt}
+\PackageInfo{test}{60pt vs 50pt: \cals@width}
+
+\cals@maxWidth{70pt}{70pt}
+\PackageInfo{test}{70pt vs 70pt: \cals@width}
+
+%
+% Regression test: avoid recursion
+%
+\def\cals@width{50pt}
+\cals@maxWidth{10pt}\cals@width
+\PackageInfo{test}{regression, recursion avoid: \cals@width}
+\cals@maxWidth\cals@width{10pt}
+\PackageInfo{test}{regression, recursion avoid: \cals@width}
+\cals@maxWidth\cals@width\cals@width
+\PackageInfo{test}{regression, recursion avoid: \cals@width}
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_60_row.chk b/Master/texmf-dist/doc/latex/cals/test/decoration/test_60_row.chk
new file mode 100644
index 00000000000..6c96c188b8f
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_60_row.chk
@@ -0,0 +1,54 @@
+%
+% Empty row
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+> \cals@current@rs@above=macro:
+->.
+> \cals@current@rs@below=macro:
+->.
+%
+% One cell
+%
+> \boxXX=
+\hbox(0.0+0.0)x100.0
+.\glue 100.0
+> \cals@current@rs@above=macro:
+->{{100pt}{0pt}{0pt}\relax }.
+> \cals@current@rs@below=macro:
+->{{100pt}{0pt}{0pt}\relax }.
+%
+% Two cells, no overrides
+%
+> \boxXX=
+\hbox(0.0+0.0)x300.0
+.\glue 100.0
+.\glue -1.0
+.\rule(*+0.0)x2.0
+.\glue -1.0
+.\glue 200.0
+> \cals@current@rs@above=macro:
+->{{100pt}{0pt}{2pt}\relax }{{200pt}{2pt}{0pt}\relax }.
+> \cals@current@rs@below=macro:
+->{{100pt}{0pt}{2pt}\relax }{{200pt}{2pt}{0pt}\relax }.
+%
+% Two cells, no overrides
+%
+> \boxXX=
+\hbox(0.0+0.0)x300.0
+.\pdfcolorstack 0 push {0 1 0 rg 0 1 0 RG}
+.\rule(*+0.0)x100.0
+.\pdfcolorstack 0 pop
+.\glue -100.0
+.\glue -2.0
+.\rule(*+0.0)x4.0
+.\glue -2.0
+.\glue 100.0
+.\glue -3.0
+.\rule(*+0.0)x6.0
+.\glue -3.0
+.\glue 200.0
+> \cals@current@rs@above=macro:
+->{{100pt}{4pt}{6pt}\relax }{{200pt}{6pt}{0pt}{8pt}}.
+> \cals@current@rs@below=macro:
+->{{100pt}{4pt}{6pt}\relax }{{200pt}{6pt}{0pt}{10pt}}.
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_60_row.tex b/Master/texmf-dist/doc/latex/cals/test/decoration/test_60_row.tex
new file mode 100644
index 00000000000..0ee43953837
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_60_row.tex
@@ -0,0 +1,65 @@
+\def\contentI{\noindent\vrule height10pt depth0pt width30pt\hfil}
+\def\contentII{\noindent\vrule height20pt depth2pt width60pt\hfil}
+
+\def\cals@cs@width{2pt}
+\def\cals@framecs@width{0pt}
+\def\cals@bgcolor{}
+
+\def\wC{100pt}
+\def\wCC{200pt}
+
+%
+% Empty row
+%
+\cals@decor@begin
+\cals@decor@end
+\showbox\cals@current@cs
+\show\cals@current@rs@above
+\show\cals@current@rs@below
+
+%
+% One cell, no overrides
+%
+\cals@decor@begin
+\let\cals@borderL=\relax
+\let\cals@borderR=\relax
+\let\cals@borderT=\relax
+\let\cals@borderB=\relax
+\def\cals@bgcolor{}
+\cals@decor@next\wC{\contentI}
+\cals@decor@end
+\showbox\cals@current@cs
+\show\cals@current@rs@above
+\show\cals@current@rs@below
+
+%
+% Two cells, no overrides
+%
+\cals@decor@begin
+\cals@decor@next\wC{\contentI}
+\cals@decor@next\wCC{\contentII}
+\cals@decor@end
+\showbox\cals@current@cs
+\show\cals@current@rs@above
+\show\cals@current@rs@below
+
+%
+% Two cells, overrides
+%
+\cals@decor@begin
+\def\cals@borderL{4pt}
+\def\cals@borderR{6pt}
+\let\cals@borderT=\relax
+\let\cals@borderB=\relax
+\def\cals@bgcolor{green}
+\cals@decor@next\wC{\contentI}
+\let\cals@borderL=\relax
+\let\cals@borderR=\relax
+\def\cals@borderT{8pt}
+\def\cals@borderB{10pt}
+\def\cals@bgcolor{}
+\cals@decor@next\wCC{\contentII}
+\cals@decor@end
+\showbox\cals@current@cs
+\show\cals@current@rs@above
+\show\cals@current@rs@below
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_70_align.chk b/Master/texmf-dist/doc/latex/cals/test/decoration/test_70_align.chk
new file mode 100644
index 00000000000..7213fce686e
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_70_align.chk
@@ -0,0 +1,8 @@
+> 2.0pt plus 1.0fill.
+> 4.0pt plus 1.0fill.
+%
+> 2.0pt plus 1.0fill.
+> 4.0pt.
+%
+> 2.0pt.
+> 4.0pt.
diff --git a/Master/texmf-dist/doc/latex/cals/test/decoration/test_70_align.tex b/Master/texmf-dist/doc/latex/cals/test/decoration/test_70_align.tex
new file mode 100644
index 00000000000..a34b3058e3b
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/decoration/test_70_align.tex
@@ -0,0 +1,15 @@
+\cals@paddingL=2pt \relax
+\cals@paddingR=4pt \relax
+
+
+\alignC
+\showthe\cals@paddingL
+\showthe\cals@paddingR
+
+\alignR
+\showthe\cals@paddingL
+\showthe\cals@paddingR
+
+\alignL
+\showthe\cals@paddingL
+\showthe\cals@paddingR
diff --git a/Master/texmf-dist/doc/latex/cals/test/llt/test_10_cons_rot.chk b/Master/texmf-dist/doc/latex/cals/test/llt/test_10_cons_rot.chk
new file mode 100644
index 00000000000..e18933034aa
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/llt/test_10_cons_rot.chk
@@ -0,0 +1,23 @@
+> \lst=macro:
+->{abcd}{efgh}{ijkl}.
+> \lst=macro:
+->{efgh}{ijkl}{abcd}.
+> \llt@car=macro:
+->abcd.
+> \lst=macro:
+->{abcd}{efgh}.
+> \lst=macro:
+->{efgh}{abcd}.
+> \llt@car=macro:
+->abcd.
+> \lst=macro:
+->{abcd}.
+> \lst=macro:
+->{abcd}.
+> \llt@car=macro:
+->abcd.
+> \lst=macro:
+->.
+> \lst=macro:
+->.
+> \llt@car=\relax.
diff --git a/Master/texmf-dist/doc/latex/cals/test/llt/test_10_cons_rot.tex b/Master/texmf-dist/doc/latex/cals/test/llt/test_10_cons_rot.tex
new file mode 100644
index 00000000000..20312cd0ec8
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/llt/test_10_cons_rot.tex
@@ -0,0 +1,23 @@
+\def\abcd{abcd}
+\def\efgh{efgh}
+\def\ijkl{ijkl}
+\def\rotandshow{
+\show\lst
+\llt@rot{\lst}
+\show\lst
+\show\llt@car}
+
+\def\lst{}
+\llt@cons{\ijkl}{\lst}
+\llt@cons{\efgh}{\lst}
+\llt@cons{\abcd}{\lst}
+\rotandshow
+\def\lst{}
+\llt@cons{\efgh}{\lst}
+\llt@cons{\abcd}{\lst}
+\rotandshow
+\def\lst{}
+\llt@cons{\abcd}{\lst}
+\rotandshow
+\def\lst{}
+\rotandshow
diff --git a/Master/texmf-dist/doc/latex/cals/test/llt/test_20_snoc_decons.chk b/Master/texmf-dist/doc/latex/cals/test/llt/test_20_snoc_decons.chk
new file mode 100644
index 00000000000..10010a80011
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/llt/test_20_snoc_decons.chk
@@ -0,0 +1,14 @@
+> \lst=macro:
+->.
+> \lst=macro:
+->{snoc-a}.
+> \lst=macro:
+->{snoc-a}{snoc-b}.
+> \lst=macro:
+->{snoc-b}.
+> \lst=macro:
+->.
+> \lst=macro:
+->{}.
+> \lst=macro:
+->.
diff --git a/Master/texmf-dist/doc/latex/cals/test/llt/test_20_snoc_decons.tex b/Master/texmf-dist/doc/latex/cals/test/llt/test_20_snoc_decons.tex
new file mode 100644
index 00000000000..7a61a785f54
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/llt/test_20_snoc_decons.tex
@@ -0,0 +1,18 @@
+\def\lst{}
+\show\lst
+\def\snoca{snoc-a}
+\def\snocb{snoc-b}
+\llt@snoc{\lst}{\snoca}
+\show\lst
+\llt@snoc{\lst}{\snocb}
+\show\lst
+\llt@decons{\lst}
+\show\lst
+\llt@decons{\lst}
+\show\lst
+
+\def\lst{{}{}}
+\llt@decons{\lst}
+\show\lst
+\llt@decons{\lst}
+\show\lst
diff --git a/Master/texmf-dist/doc/latex/cals/test/llt/test_30_all.chk b/Master/texmf-dist/doc/latex/cals/test/llt/test_30_all.chk
new file mode 100644
index 00000000000..37803a26398
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/llt/test_30_all.chk
@@ -0,0 +1,24 @@
+> \lst=macro:
+->{\multiply \cals@borderwidthL by 3\relax }{}.
+> \llt@car=macro:
+->.
+> \lst=macro:
+->{item1}{item2}.
+> \llt@car=macro:
+->item3.
+> \lst=macro:
+->.
+> \lst=macro:
+->{bbb}.
+> \lst=macro:
+->{bbb}{ccc}.
+> \lst=macro:
+->{aaa}{bbb}{ccc}.
+> \llt@car=macro:
+->aaa.
+> \lst=macro:
+->{bbb}{ccc}.
+> \llt@car=macro:
+->bbb.
+> \lst=macro:
+->{ccc}{bbb}.
diff --git a/Master/texmf-dist/doc/latex/cals/test/llt/test_30_all.tex b/Master/texmf-dist/doc/latex/cals/test/llt/test_30_all.tex
new file mode 100644
index 00000000000..f683984d240
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/llt/test_30_all.tex
@@ -0,0 +1,26 @@
+\def\lst{{\multiply \cals@borderwidthL by 3\relax}{}{}}
+\llt@desnoc{\lst}
+\show\lst
+\show\llt@car
+\def\lst{{item1}{item2}{item3}}
+\llt@desnoc{\lst}
+\show\lst
+\show\llt@car
+
+\def\aaa{aaa}
+\def\bbb{bbb}
+\def\ccc{ccc}
+\def\lst{} % empty list
+\show\lst
+\llt@cons\bbb\lst % \lst -> "{bbb}"
+\show\lst
+\llt@snoc\lst\ccc % \lst -> "{bbb}{ccc}"
+\show\lst
+\llt@cons\aaa\lst % \lst -> "{aaa}{bbb}{ccc}"
+\show\lst
+\llt@decons\lst % \llt@car -> "aaa", \lst -> "{bbb}{ccc}"
+\show\llt@car
+\show\lst
+\llt@rot\lst % \llt@car -> "bbb", \lst -> "{ccc}{bbb}"
+\show\llt@car
+\show\lst
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_010_wrongbreak.chk b/Master/texmf-dist/doc/latex/cals/test/regression/test_010_wrongbreak.chk
new file mode 100644
index 00000000000..86b6c040eaa
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_010_wrongbreak.chk
@@ -0,0 +1,7 @@
+> the letter F.
+> the letter O.
+> the letter F.
+> the letter F.
+> the letter O.
+> the letter O.
+> the letter O.
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_010_wrongbreak.tex b/Master/texmf-dist/doc/latex/cals/test/regression/test_010_wrongbreak.tex
new file mode 100644
index 00000000000..cbb6ce278a9
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_010_wrongbreak.tex
@@ -0,0 +1,33 @@
+% Wrong behaviour:
+% - page 1: "a"
+% - page 2: thead, tbody1
+% - page 3: thead, tbody2, tbody3
+% Right behaviour:
+% - page 1: "a"
+% - page 2: thead, tbody1, tbody2, tbody3
+%
+%
+\edef\oldoutput{\the\output}
+\output={\immediate\show O%
+\oldoutput}
+\let\oldifbreak=\cals@ifbreak
+\def\cals@ifbreak{%
+\oldifbreak\iftrue \immediate\show T\else \immediate\show F\fi
+\cals@tmp}
+%\tracingoutput=1
+%\tracingpages=1
+%
+%
+%
+a\par
+\dimen0=\pagegoal\relax
+\advance\dimen0 by -\pagetotal\relax
+\advance\dimen0 by -150pt
+\vskip\dimen0\relax
+\begin{calstable}
+\colwidths{{100pt}{100pt}}
+\thead{\brow\cell{thead}\cell{\vrule width10pt height100pt depth0pt}\erow}
+\brow\cell{tbody1}\cell{\vrule width10pt height100pt depth0pt}\erow
+\brow\cell{tbody2}\cell{\vrule width10pt height100pt depth0pt}\erow
+\brow\cell{tbody3}\cell{\vrule width10pt height100pt depth0pt}\erow
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_020_wrongnobreak.chk b/Master/texmf-dist/doc/latex/cals/test/regression/test_020_wrongnobreak.chk
new file mode 100644
index 00000000000..5dae18a2371
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_020_wrongnobreak.chk
@@ -0,0 +1,11 @@
+> the letter H.
+> the character 1.
+> the letter O.
+> the letter H.
+> the character 2.
+> the letter O.
+> the letter H.
+> the character 3.
+> the letter O.
+> the letter O.
+> the letter O.
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_020_wrongnobreak.tex b/Master/texmf-dist/doc/latex/cals/test/regression/test_020_wrongnobreak.tex
new file mode 100644
index 00000000000..891c1091adb
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_020_wrongnobreak.tex
@@ -0,0 +1,21 @@
+% I use a penalty to force a run of the output routine.
+% But I was afraid that this penalty prohibites a break.
+
+\edef\oldoutput{\the\output}
+\output={\immediate\show O%
+\oldoutput}
+
+\dimen0=\vsize
+\divide \dimen0 by 3
+\advance \dimen0 by 1cm
+\let\olderow=\erow
+\edef\erow{\ht\cals@current@row=\the\dimen0 \noexpand\olderow}
+%\show\erow
+
+\begin{calstable}
+\colwidths{{100pt}}
+\thead{\brow \cell{aaa} \erow \immediate\show H}
+\brow \cell{bbb} \erow \immediate\show 1
+\brow \cell{ccc} \erow \immediate\show 2
+\brow \cell{ddd} \erow \immediate\show 3
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_030_spanbreak.chk b/Master/texmf-dist/doc/latex/cals/test/regression/test_030_spanbreak.chk
new file mode 100644
index 00000000000..44af9bc224d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_030_spanbreak.chk
@@ -0,0 +1,11 @@
+> the letter H.
+> the character 1.
+> the letter R.
+> the letter O.
+> the letter H.
+> the letter O.
+> the character 2.
+> the character 3.
+> the letter O.
+> the letter O.
+> the letter O.
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_030_spanbreak.tex b/Master/texmf-dist/doc/latex/cals/test/regression/test_030_spanbreak.tex
new file mode 100644
index 00000000000..b04155899ad
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_030_spanbreak.tex
@@ -0,0 +1,32 @@
+%
+% Do not break rowspanned cells
+%
+
+%
+% Unfortunately, this test seems does not check it.
+% Probably I should look at \tracingoutput
+%
+
+\edef\oldoutput{\the\output}
+\output={\immediate\show O%
+\oldoutput}
+
+\dimen0=\vsize
+\divide \dimen0 by 3
+\advance \dimen0 by 1cm
+\let\olderow=\erow
+\edef\erow{\ht\cals@current@row=\the\dimen0 \noexpand\olderow}
+%\show\erow
+
+\begin{calstable}
+\colwidths{{100pt}{100pt}}
+\thead{\brow \cell{h1}\cell{h2} \erow \immediate\show H}
+\brow \cell{r0c1}\cell{r0c2} \olderow
+\brow \cell{r1}\nullcell{ltr} \erow \immediate\show 1
+\cals@ifInRspan\iftrue \show R \else \show X \fi
+\brow \cell{r2}\nullcell{lbr}\spancontent{r1+r2} \erow \immediate\show 2
+%
+% Unfortunately yes, this row is orphan
+%
+\brow \cell{r3a}\cell{r3b} \erow \immediate\show 3
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_040_rowheight.chk b/Master/texmf-dist/doc/latex/cals/test/regression/test_040_rowheight.chk
new file mode 100644
index 00000000000..7eb72392533
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_040_rowheight.chk
@@ -0,0 +1,3 @@
+> 30.0pt.
+> 40.0pt.
+> 50.0pt.
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_040_rowheight.tex b/Master/texmf-dist/doc/latex/cals/test/regression/test_040_rowheight.tex
new file mode 100644
index 00000000000..4d028bc4915
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_040_rowheight.tex
@@ -0,0 +1,40 @@
+% Initially, re-height of the current row and setting
+% \cals@last@row@height was in '\cals@issue@row'.
+% After implementing row spanning, this actions were moved
+% to \erow. Unfortunately, I forget to move the second action.
+\begin{calstable}
+\cals@setpadding{}
+\cals@setcellprevdepth{}
+\colwidths{{100pt}{100pt}{100pt}}
+
+\thead{%
+\brow
+ \cell{h1}\cell{h2}\cell{h3}
+\erow
+}
+
+\brow
+ \cell{a1}
+ \cell{a2}
+ \cell{a3}
+ \ht\cals@current@row=30pt
+\erow
+\showthe\cals@last@row@height
+
+\brow
+ \cell{b1}
+ \nullcell{ltr}
+ \nullcell{ltr}
+ \ht\cals@current@row=40pt
+\erow
+\showthe\cals@last@row@height
+
+\brow
+ \cell{c1}
+ \nullcell{lbr}\spancontent{s2}
+ \nullcell{lbr}\spancontent{s3}
+ \ht\cals@current@row=50pt
+\erow
+\showthe\cals@last@row@height
+
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_050_leftskip_rowspan.chk b/Master/texmf-dist/doc/latex/cals/test/regression/test_050_leftskip_rowspan.chk
new file mode 100644
index 00000000000..53ba792c3d7
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_050_leftskip_rowspan.chk
@@ -0,0 +1,2 @@
+> 210.0pt.
+> 10.0pt.
diff --git a/Master/texmf-dist/doc/latex/cals/test/regression/test_050_leftskip_rowspan.tex b/Master/texmf-dist/doc/latex/cals/test/regression/test_050_leftskip_rowspan.tex
new file mode 100644
index 00000000000..549fd6ac53f
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/regression/test_050_leftskip_rowspan.tex
@@ -0,0 +1,24 @@
+\parindent=0pt
+par1\par
+par2\par
+\leftskip=10pt
+par3\par
+par4\par
+\setbox0=\vbox{%
+\begin{calstable}
+\colwidths{{100pt}}
+\brow
+ \cell{c}
+ \nullcell{ltr}
+\erow
+\brow
+ \cell{c}
+ \nullcell{lbr}\spancontent{c}
+\erow
+\end{calstable}
+}
+\showthe\wd0
+\box0
+par5\par
+par6\par
+\showthe\leftskip
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_10_waitrule.chk b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_10_waitrule.chk
new file mode 100644
index 00000000000..30e283b630f
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_10_waitrule.chk
@@ -0,0 +1,47 @@
+%
+% Empty
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+%
+% One
+%
+> \boxXX=
+\hbox(0.5+0.5)x100.0
+.\glue -1.0
+.\rule(0.5+0.5)x103.0
+.\glue -2.0
+%
+% Several, same width
+%
+> \boxXX=
+\hbox(0.5+0.5)x300.0
+.\glue -1.0
+.\rule(0.5+0.5)x303.0
+.\glue -2.0
+%
+% Mixed
+%
+> \boxXX=
+\hbox(2.5+2.5)x300.0
+.\glue -1.0
+.\rule(0.5+0.5)x103.0
+.\glue -2.0
+.\glue -1.0
+.\rule(1.5+1.5)x103.0
+.\glue -2.0
+.\glue -1.0
+.\rule(2.5+2.5)x103.0
+.\glue -2.0
+%
+% No rule at all
+%
+> \boxXX=
+\hbox(1.0+1.0)x400.0
+.\glue -1.0
+.\rule(1.0+1.0)x103.0
+.\glue -2.0
+.\glue 200.0
+.\glue -1.0
+.\rule(1.0+1.0)x103.0
+.\glue -2.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_10_waitrule.tex b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_10_waitrule.tex
new file mode 100644
index 00000000000..537b3df7414
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_10_waitrule.tex
@@ -0,0 +1,68 @@
+%
+% Testing "waiting" rule
+%
+
+%
+% Empty
+%
+\setbox0=\hbox{%
+\cals@rs@sofar@reset
+\cals@rs@sofar@end
+}
+\showbox0
+
+%
+% One element
+%
+\def\ll{100pt}
+\def\dl{2pt}
+\def\dr{4pt}
+\def\w{1pt}
+\setbox0=\hbox{%
+\cals@rs@sofar@reset
+\cals@rs@sofar@next\ll\dl\dr\w
+\cals@rs@sofar@end
+}
+\showbox0
+
+%
+% Elements of the same width
+%
+\setbox0=\hbox{%
+\cals@rs@sofar@reset
+\cals@rs@sofar@next\ll\dl\dr\w
+\cals@rs@sofar@next\ll\dl\dr\w
+\cals@rs@sofar@next\ll\dl\dr\w
+\cals@rs@sofar@end
+}
+\showbox0
+
+%
+% Elements of different widths
+%
+\setbox0=\hbox{%
+\cals@rs@sofar@reset
+\cals@rs@sofar@next\ll\dl\dr\w
+\def\w{3pt}%
+\cals@rs@sofar@next\ll\dl\dr\w
+\def\w{5pt}%
+\cals@rs@sofar@next\ll\dl\dr\w
+\cals@rs@sofar@end
+}
+\showbox0
+
+%
+% 0pt width=no rule at all
+%
+\setbox0=\hbox{%
+\def\w{2pt}%
+\cals@rs@sofar@reset
+\cals@rs@sofar@next\ll\dl\dr\w
+\def\w{0pt}%
+\cals@rs@sofar@next\ll\dl\dr\w
+\cals@rs@sofar@next\ll\dl\dr\w
+\def\w{2pt}%
+\cals@rs@sofar@next\ll\dl\dr\w
+\cals@rs@sofar@end
+}
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_15_waitover.chk b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_15_waitover.chk
new file mode 100644
index 00000000000..646dd34aaa4
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_15_waitover.chk
@@ -0,0 +1,36 @@
+%
+% Same width
+%
+> \boxXX=
+\hbox(1.0+1.0)x100.0
+.\glue -1.0
+.\rule(1.0+1.0)x103.0
+.\glue -2.0
+%
+% Different borders
+%
+> \boxXX=
+\hbox(1.0+1.0)x100.0
+.\glue -3.0
+.\rule(1.0+1.0)x107.0
+.\glue -4.0
+%
+% Different widths
+%
+> \boxXX=
+\hbox(2.0+2.0)x100.0
+.\glue -1.0
+.\rule(1.0+1.0)x103.0
+.\glue -2.0
+.\glue -100.0
+.\glue -1.0
+.\rule(2.0+2.0)x103.0
+.\glue -2.0
+%
+% Different widths, second is 0pt
+%
+> \boxXX=
+\hbox(1.0+1.0)x100.0
+.\glue -1.0
+.\rule(1.0+1.0)x103.0
+.\glue -2.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_15_waitover.tex b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_15_waitover.tex
new file mode 100644
index 00000000000..b04a81587ec
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_15_waitover.tex
@@ -0,0 +1,51 @@
+\def\ll{100pt}
+\def\dl{2pt}
+\def\dr{4pt}
+%
+% Same width and borders
+%
+\def\w{2pt}
+\setbox0=\hbox{%
+\cals@rs@sofar@reset
+\cals@rs@sofar@next\ll\dl\dr\w
+\cals@rs@sofar@over\ll\dl\dr\w
+\cals@rs@sofar@end
+}
+\showbox0
+
+%
+% Same width, bigger borders
+%
+\setbox0=\hbox{%
+\cals@rs@sofar@reset
+\cals@rs@sofar@next\ll\dl\dr\w
+\def\dlII{6pt}%
+\def\drII{8pt}%
+\cals@rs@sofar@over\ll\dlII\drII\w
+\cals@rs@sofar@end
+}
+\showbox0
+
+%
+% Different widths
+%
+\setbox0=\hbox{%
+\cals@rs@sofar@reset
+\cals@rs@sofar@next\ll\dl\dr\w
+\def\wII{4pt}%
+\cals@rs@sofar@over\ll\dl\dr\wII
+\cals@rs@sofar@end
+}
+\showbox0
+
+%
+% Different widths, second is 0pt
+%
+\setbox0=\hbox{%
+\cals@rs@sofar@reset
+\cals@rs@sofar@next\ll\dl\dr\w
+\def\wII{0pt}%
+\cals@rs@sofar@over\ll\dl\dr\wII
+\cals@rs@sofar@end
+}
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_20_pack.chk b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_20_pack.chk
new file mode 100644
index 00000000000..4af37cfac10
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_20_pack.chk
@@ -0,0 +1,38 @@
+%
+% 0pt
+%
+> \tmp=macro:
+->{100pt}{2pt}{4pt}{0pt}.
+> \ll=macro:
+->100pt.
+> \dl=macro:
+->2pt.
+> \dr=macro:
+->4pt.
+> \w=macro:
+->0pt.
+%
+% \relax
+%
+> \tmp=macro:
+->{200pt}{2pt}{4pt}\relax .
+> \ll=macro:
+->200pt.
+> \dl=macro:
+->2pt.
+> \dr=macro:
+->4pt.
+> \w=\relax.
+%
+% User-specified
+%
+> \tmp=macro:
+->{300pt}{0pt}{0pt}{3pt}.
+> \ll=macro:
+->300pt.
+> \dl=macro:
+->0pt.
+> \dr=macro:
+->0pt.
+> \w=macro:
+->3pt.
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_20_pack.tex b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_20_pack.tex
new file mode 100644
index 00000000000..9f881ed4948
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_20_pack.tex
@@ -0,0 +1,32 @@
+%
+% 0pt for thick
+%
+\cals@rs@pack\tmp{100pt}{2pt}{4pt}{0pt}
+\show\tmp
+\cals@rs@unpack\tmp\ll\dl\dr\w
+\show\ll
+\show\dl
+\show\dr
+\show\w
+
+%
+% Use default think
+%
+\cals@rs@pack\tmp{200pt}{2pt}{4pt}\relax
+\show\tmp
+\cals@rs@unpack\tmp\ll\dl\dr\w
+\show\ll
+\show\dl
+\show\dr
+\show\w
+
+%
+% User-specified thick
+%
+\cals@rs@pack\tmp{300pt}{0pt}{0pt}{3pt}
+\show\tmp
+\cals@rs@unpack\tmp\ll\dl\dr\w
+\show\ll
+\show\dl
+\show\dr
+\show\w
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_30_jointwo.chk b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_30_jointwo.chk
new file mode 100644
index 00000000000..644d9520d5d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_30_jointwo.chk
@@ -0,0 +1,29 @@
+%
+% Empty
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+%
+% One element
+%
+> \boxXX=
+\hbox(3.0+3.0)x100.0
+.\glue -1.5
+.\rule(3.0+3.0)x104.0
+.\glue -2.5
+%
+% Several elements
+%
+> \boxXX=
+\hbox(4.0+4.0)x303.0
+.\glue -1.0
+.\rule(3.0+3.0)x103.0
+.\glue -2.0
+.\glue -100.0
+.\glue -2.0
+.\rule(4.0+4.0)x104.0
+.\glue -2.0
+.\glue -1.0
+.\rule(0.5+0.5)x104.0
+.\glue -2.0
+.\glue 102.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_30_jointwo.tex b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_30_jointwo.tex
new file mode 100644
index 00000000000..e6f1c11734d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_30_jointwo.tex
@@ -0,0 +1,34 @@
+\def\defaultwidth{1pt}
+
+%
+% Empty
+%
+\def\rsI{}
+\def\rsII{}
+\def\mkbox{\setbox0=\hbox{\cals@rs@sofar@reset \cals@rs@joinTwo\defaultwidth\rsI\rsII \cals@rs@sofar@end}}
+\mkbox
+\showbox0
+
+%
+% One element
+%
+\cals@rs@pack\rsI{100pt}{2pt}{4pt}{6pt}
+\cals@rs@pack\rsII{100pt}{3pt}{5pt}{6pt}
+\edef\rsI{{\rsI}}
+\edef\rsII{{\rsII}}
+\mkbox
+\showbox0
+
+%
+% Several elements, with no-line and default
+%
+\cals@rs@pack\frI{100pt}{2pt}{4pt}{6pt}
+\cals@rs@pack\frII{101pt}{2pt}{4pt}\relax
+\cals@rs@pack\frIII{102pt}{2pt}{4pt}{0pt}
+\edef\rsI{{\frI}{\frII}{\frIII}}
+\cals@rs@pack\frI{100pt}{4pt}{4pt}{8pt}
+\cals@rs@pack\frII{101pt}{2pt}{4pt}\relax
+\cals@rs@pack\frIII{102pt}{3pt}{5pt}{0pt}
+\edef\rsII{{\frI}{\frII}{\frIII}}
+\mkbox
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_35_joinone.chk b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_35_joinone.chk
new file mode 100644
index 00000000000..6e24b4c3685
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_35_joinone.chk
@@ -0,0 +1,16 @@
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+> \boxXX=
+\hbox(3.0+3.0)x100.0
+.\glue -1.0
+.\rule(3.0+3.0)x103.0
+.\glue -2.0
+> \boxXX=
+\hbox(3.0+3.0)x403.0
+.\glue -1.0
+.\rule(3.0+3.0)x203.0
+.\glue -2.0
+.\glue -1.0
+.\rule(0.5+0.5)x104.0
+.\glue -2.0
+.\glue 102.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_35_joinone.tex b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_35_joinone.tex
new file mode 100644
index 00000000000..979a3b99505
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_35_joinone.tex
@@ -0,0 +1,27 @@
+\def\defaultwidth{1pt}
+
+%
+% Empty
+%
+\def\rs{}
+\def\mkbox{\setbox0=\hbox{\cals@rs@sofar@reset \cals@rs@joinOne\defaultwidth\rs \cals@rs@sofar@end}}
+\mkbox
+\showbox0
+
+%
+% One element
+%
+\cals@rs@pack\rs{100pt}{2pt}{4pt}{6pt}
+\edef\rs{{\rs}}
+\mkbox
+\showbox0
+
+%
+% Several elements, with no-line and default
+%
+\cals@rs@pack\frI{100pt}{2pt}{4pt}{6pt}
+\cals@rs@pack\frII{101pt}{2pt}{4pt}\relax
+\cals@rs@pack\frIII{102pt}{2pt}{4pt}{0pt}
+\edef\rs{{\frI}{\frI}{\frII}{\frIII}}
+\mkbox
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_40_construct.chk b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_40_construct.chk
new file mode 100644
index 00000000000..0accaf66536
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_40_construct.chk
@@ -0,0 +1,21 @@
+%
+% Empty
+%
+> \cals@current@rs@above=macro:
+->.
+> \cals@current@rs@below=macro:
+->.
+%
+% One element
+%
+> \cals@current@rs@above=macro:
+->{{100pt}{3pt}{5pt}\relax }.
+> \cals@current@rs@below=macro:
+->{{100pt}{3pt}{5pt}{4pt}}.
+%
+% Two elements
+%
+> \cals@current@rs@above=macro:
+->{{100pt}{0pt}{2pt}\relax }{{200pt}{2pt}{8pt}{6pt}}.
+> \cals@current@rs@below=macro:
+->{{100pt}{0pt}{2pt}{4pt}}{{200pt}{2pt}{8pt}\relax }.
diff --git a/Master/texmf-dist/doc/latex/cals/test/rowsep/test_40_construct.tex b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_40_construct.tex
new file mode 100644
index 00000000000..24d895efdb8
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/rowsep/test_40_construct.tex
@@ -0,0 +1,36 @@
+\def\wNone{0pt}
+\def\wII{2pt}
+\def\wIII{3pt}
+\def\wIV{4pt}
+\def\wV{5pt}
+\def\wVI{6pt}
+\def\wVIII{8pt}
+\def\wC{100pt}
+\def\wCC{200pt}
+
+%
+% Empty
+%
+\cals@rs@spec@begin
+\cals@rs@spec@end\wII
+\show\cals@current@rs@above
+\show\cals@current@rs@below
+
+%
+% One element
+%
+\cals@rs@spec@begin
+\cals@rs@spec@next\wC\wIII\relax\wIV % length, borderT, borderB
+\cals@rs@spec@end\wV
+\show\cals@current@rs@above
+\show\cals@current@rs@below
+
+%
+% Two elements
+%
+\cals@rs@spec@begin
+\cals@rs@spec@next\wC\wNone\relax\wIV
+\cals@rs@spec@next\wCC\wII\wVI\relax
+\cals@rs@spec@end\wVIII
+\show\cals@current@rs@above
+\show\cals@current@rs@below
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_10_queue.chk b/Master/texmf-dist/doc/latex/cals/test/span/test_10_queue.chk
new file mode 100644
index 00000000000..252d5cead34
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_10_queue.chk
@@ -0,0 +1,5 @@
+> \cals@spanq@heights=macro:
+->{20.0pt}{40.0pt}.
+> \cals@spanq@heights=macro:
+->{40.0pt}.
+> 20.0pt.
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_10_queue.tex b/Master/texmf-dist/doc/latex/cals/test/span/test_10_queue.tex
new file mode 100644
index 00000000000..742dbd88127
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_10_queue.tex
@@ -0,0 +1,10 @@
+\cals@span@height=20pt
+\cals@span@put
+\cals@span@height=40pt
+\cals@span@put
+\show\cals@spanq@heights
+%
+\cals@span@height=0pt
+\cals@span@get
+\show\cals@spanq@heights
+\showthe\cals@span@height
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_20_decor.chk b/Master/texmf-dist/doc/latex/cals/test/span/test_20_decor.chk
new file mode 100644
index 00000000000..5044b94ca62
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_20_decor.chk
@@ -0,0 +1,84 @@
+%
+% Test 1
+%
+> \boxXX=
+\hbox(0.0+0.0)x260.0
+% column 1
+.\pdfcolorstack 0 push {1 0 0 rg 1 0 0 RG}
+.\rule(*+0.0)x50.0
+.\pdfcolorstack 0 pop
+.\glue -50.0
+.\glue -4.0
+.\rule(*+0.0)x8.0
+.\glue -4.0
+.\glue 50.0
+% column 2
+.\pdfcolorstack 0 push {1 0 0 rg 1 0 0 RG}
+.\rule(*+0.0)x60.0
+.\pdfcolorstack 0 pop
+.\glue -60.0
+.\glue 60.0
+% column 3
+.\pdfcolorstack 0 push {1 0 0 rg 1 0 0 RG}
+.\rule(*+0.0)x70.0
+.\pdfcolorstack 0 pop
+.\glue -70.0
+.\glue 70.0
+% column 4
+.\pdfcolorstack 0 push {1 0 0 rg 1 0 0 RG}
+.\rule(*+0.0)x80.0
+.\pdfcolorstack 0 pop
+.\glue -80.0
+.\glue 80.0
+.\glue -2.0
+.\rule(*+0.0)x4.0
+.\glue -2.0
+%
+> \cals@current@rs@above=macro:
+->{{50pt}{8pt}{0pt}{2pt}}{{60pt}{0pt}{0pt}{2pt}}{{70pt}{0pt}{0pt}{0pt}}{{80pt}{
+0pt}{4pt}{2pt}}.
+> \cals@current@rs@below=macro:
+->{{50pt}{8pt}{0pt}{6pt}}{{60pt}{0pt}{0pt}{6pt}}{{70pt}{0pt}{0pt}{0pt}}{{80pt}{
+0pt}{4pt}{6pt}}.
+%
+% Test 2
+%
+> \boxXX=
+\hbox(0.0+0.0)x260.0
+% column 1
+.\pdfcolorstack 0 push {0 1 0 rg 0 1 0 RG}
+.\rule(*+0.0)x50.0
+.\pdfcolorstack 0 pop
+.\glue -50.0
+.\glue -3.5
+.\rule(*+0.0)x7.0
+.\glue -3.5
+.\glue 50.0
+% column 2
+.\pdfcolorstack 0 push {0 1 0 rg 0 1 0 RG}
+.\rule(*+0.0)x60.0
+.\pdfcolorstack 0 pop
+.\glue -60.0
+.\glue 60.0
+% column 3
+.\pdfcolorstack 0 push {0 1 0 rg 0 1 0 RG}
+.\rule(*+0.0)x70.0
+.\pdfcolorstack 0 pop
+.\glue -70.0
+.\glue 70.0
+% column 4
+.\pdfcolorstack 0 push {0 1 0 rg 0 1 0 RG}
+.\rule(*+0.0)x80.0
+.\pdfcolorstack 0 pop
+.\glue -80.0
+.\glue 80.0
+.\glue -1.5
+.\rule(*+0.0)x3.0
+.\glue -1.5
+%
+> \cals@current@rs@above=macro:
+->{{50pt}{7pt}{0pt}{1pt}}{{60pt}{0pt}{0pt}{0pt}}{{70pt}{0pt}{0pt}{1pt}}{{80pt}{
+0pt}{3pt}{1pt}}.
+> \cals@current@rs@below=macro:
+->{{50pt}{7pt}{0pt}{5pt}}{{60pt}{0pt}{0pt}{0pt}}{{70pt}{0pt}{0pt}{5pt}}{{80pt}{
+0pt}{3pt}{5pt}}.
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_20_decor.tex b/Master/texmf-dist/doc/latex/cals/test/span/test_20_decor.tex
new file mode 100644
index 00000000000..99794bea815
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_20_decor.tex
@@ -0,0 +1,31 @@
+\colwidths{{50pt}{60pt}{70pt}{80pt}}
+
+\def\cals@borderT{2pt}
+\def\cals@borderR{4pt}
+\def\cals@borderB{6pt}
+\def\cals@borderL{8pt}
+\def\cals@bgcolor{red}
+\cals@decor@begin
+\nullcell{ltb}
+\nullcell{tb}
+\nullcell{}
+\nullcell{tbr}
+\cals@decor@end\cals@lastWidth
+\showbox\cals@current@cs
+\show\cals@current@rs@above
+\show\cals@current@rs@below
+
+\def\cals@borderT{1pt}
+\def\cals@borderR{3pt}
+\def\cals@borderB{5pt}
+\def\cals@borderL{7pt}
+\def\cals@bgcolor{green}
+\cals@decor@begin
+\nullcell{ltb}
+\nullcell{}
+\nullcell{tb}
+\nullcell{tbr}
+\cals@decor@end\cals@lastWidth
+\showbox\cals@current@cs
+\show\cals@current@rs@above
+\show\cals@current@rs@below
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_30_iftlrb.chk b/Master/texmf-dist/doc/latex/cals/test/span/test_30_iftlrb.chk
new file mode 100644
index 00000000000..372fdc10041
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_30_iftlrb.chk
@@ -0,0 +1,16 @@
+> \cals@span@ifL=macro:
+#1->\iftrue .
+> \cals@span@ifT=macro:
+#1->\iffalse .
+> \cals@span@ifR=macro:
+#1->\iftrue .
+> \cals@span@ifB=macro:
+#1->\iffalse .
+> \cals@span@ifL=macro:
+#1->\iffalse .
+> \cals@span@ifT=macro:
+#1->\iftrue .
+> \cals@span@ifR=macro:
+#1->\iffalse .
+> \cals@span@ifB=macro:
+#1->\iftrue .
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_30_iftlrb.tex b/Master/texmf-dist/doc/latex/cals/test/span/test_30_iftlrb.tex
new file mode 100644
index 00000000000..a67bdc93a69
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_30_iftlrb.tex
@@ -0,0 +1,15 @@
+\def\cals@spanq@heights{{0pt}}
+\def\cals@lastWidth{0pt}
+\brow
+
+\nullcell{lr}
+\show\cals@span@ifL
+\show\cals@span@ifT
+\show\cals@span@ifR
+\show\cals@span@ifB
+\def\cals@lastWidth{0pt}
+\nullcell{tb}
+\show\cals@span@ifL
+\show\cals@span@ifT
+\show\cals@span@ifR
+\show\cals@span@ifB
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_40_lr_queue.chk b/Master/texmf-dist/doc/latex/cals/test/span/test_40_lr_queue.chk
new file mode 100644
index 00000000000..ca1abf2ce23
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_40_lr_queue.chk
@@ -0,0 +1,14 @@
+> \cals@spanq@heights=macro:
+->.
+> \cals@spanq@heights=macro:
+->{20.0pt}.
+> \cals@spanq@heights=macro:
+->{20.0pt}.
+%
+> 40.0pt.
+> 0.0pt.
+> \cals@spanq@heights=macro:
+->{20.0pt}.
+> 20.0pt.
+> \cals@spanq@heights=macro:
+->.
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_40_lr_queue.tex b/Master/texmf-dist/doc/latex/cals/test/span/test_40_lr_queue.tex
new file mode 100644
index 00000000000..a25633a68b4
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_40_lr_queue.tex
@@ -0,0 +1,28 @@
+\def\cals@lastWidth{2pt}
+\def\cals@rs@spec@ll{2pt}
+\def\cals@rs@spec@bl{2pt}
+\def\cals@rs@spec@bt{2pt}
+\def\cals@current@rs@above{}
+\def\cals@current@rs@below{}
+%
+\colwidths{{100pt}{200pt}{300pt}}
+%
+\cals@span@height=20pt \relax
+\show\cals@spanq@heights
+\brow\def\cals@lastWidth{0pt}
+\nullcell{tr}
+\show\cals@spanq@heights
+\brow\def\cals@lastWidth{0pt}
+\nullcell{br}
+\show\cals@spanq@heights
+%
+\cals@span@height=40pt \relax
+\showthe\cals@span@height
+\let\cals@borderL=\relax \brow\def\cals@lastWidth{0pt}
+\nullcell{lt}
+\showthe\cals@span@height
+\show\cals@spanq@heights
+\brow\def\cals@lastWidth{0pt}
+\nullcell{bl}
+\showthe\cals@span@height
+\show\cals@spanq@heights
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_50_dimen.chk b/Master/texmf-dist/doc/latex/cals/test/span/test_50_dimen.chk
new file mode 100644
index 00000000000..9a079aead07
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_50_dimen.chk
@@ -0,0 +1,38 @@
+> \boxXX=
+\hbox(0.0+0.0)x60.0
+.\vbox(0.0+0.0)x10.0
+..\hbox(0.0+0.0)x10.0
+..\glue 0.0 plus 1.0fil
+.\vbox(0.0+0.0)x20.0
+..\hbox(0.0+0.0)x20.0
+..\glue 0.0 plus 1.0fil
+.\vbox(0.0+0.0)x30.0
+..\hbox(0.0+0.0)x30.0
+..\glue 0.0 plus 1.0fil
+> \cals@spanq@heights=macro:
+->{0.0pt}.
+%
+> \boxXX=
+\hbox(0.0+0.0)x60.0
+.\vbox(0.0+0.0)x10.0
+..\hbox(0.0+0.0)x10.0
+..\glue 0.0 plus 1.0fil
+.\vbox(0.0+0.0)x20.0
+..\hbox(0.0+0.0)x20.0
+..\glue 0.0 plus 1.0fil
+.\vbox(0.0+0.0)x30.0
+..\hbox(0.0+0.0)x30.0
+..\glue 0.0 plus 1.0fil
+> \cals@spanq@heights=macro:
+->{40.0pt}.
+%
+> \boxXX=
+\hbox(0.0+0.0)x0.0
+> \cals@spanq@heights=macro:
+->.
+> 60.0pt.
+> 90.0pt.
+%
+% Bug
+%
+> 60.0pt.
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_50_dimen.tex b/Master/texmf-dist/doc/latex/cals/test/span/test_50_dimen.tex
new file mode 100644
index 00000000000..f6e0b28a560
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_50_dimen.tex
@@ -0,0 +1,40 @@
+\colwidths{{10pt}{20pt}{30pt}}
+\cals@last@row@height=1000pt %
+%
+\brow
+\nullcell{tl}
+\nullcell{t}
+\nullcell{tr}
+%\erow
+\cals@last@row@height=40pt %
+\showbox\cals@current@row
+\show\cals@spanq@heights
+
+\brow
+\nullcell{l}
+\nullcell{}
+\nullcell{r}
+%\erow
+\cals@last@row@height=50pt %
+\showbox\cals@current@row
+\show\cals@spanq@heights
+
+
+\brow
+\nullcell{lb}
+\nullcell{b}
+\nullcell{br}
+%\erow
+\showbox\cals@current@row
+\show\cals@spanq@heights
+\showthe\cals@span@width
+\showthe\cals@span@height
+
+%
+% Bug was here
+%
+\brow
+\nullcell{ltb}
+\nullcell{tb}
+\nullcell{btr}
+\showthe\cals@span@width
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_60_content.chk b/Master/texmf-dist/doc/latex/cals/test/span/test_60_content.chk
new file mode 100644
index 00000000000..0c523e3b33b
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_60_content.chk
@@ -0,0 +1,16 @@
+> \boxXX=
+\hbox(10.0+0.0)x100.0
+.\vbox(10.0+0.0)x100.0
+..\glue -30.0
+..\glue 14.0
+..\glue 0.0 plus -1.0
+..\glue(\parskip) 0.0 plus 1.0
+..\glue(\baselineskip) 6.0
+..\hbox(3.0+2.0)x100.0, glue set 74.0fil
+...\glue(\leftskip) 12.0
+...\rule(3.0+2.0)x1.0
+...\penalty 10000
+...\glue(\parfillskip) 0.0 plus 1.0fil
+...\glue(\rightskip) 13.0
+..\glue 0.0 plus 1.0fil
+..\glue 15.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_60_content.tex b/Master/texmf-dist/doc/latex/cals/test/span/test_60_content.tex
new file mode 100644
index 00000000000..0bc32f86246
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_60_content.tex
@@ -0,0 +1,15 @@
+\setlength{\cals@paddingL}{12pt}
+\setlength{\cals@paddingR}{13pt}
+\setlength{\cals@paddingT}{14pt}
+\setlength{\cals@paddingB}{15pt}
+
+\setlength{\cals@paddingD}{1pt}
+\setlength{\baselineskip}{10pt}
+
+\setbox\cals@current@row=\hbox{}
+
+\cals@span@width=100pt
+\cals@span@height=30pt
+
+\spancontent{\noindent \vrule height3pt depth2pt width1pt}
+\showbox\cals@current@row
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_70_intercept.chk b/Master/texmf-dist/doc/latex/cals/test/span/test_70_intercept.chk
new file mode 100644
index 00000000000..14db368f2c5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_70_intercept.chk
@@ -0,0 +1,16 @@
+% row 1
+> \cals@spanq@heights=macro:
+->{0.0pt}.
+% row 2
+> \cals@spanq@heights=macro:
+->{0.0pt}{0.0pt}.
+> \cals@spanq@heights=macro:
+->{0.0pt}{50.0pt}.
+% row 3
+> \cals@spanq@heights=macro:
+->{50.0pt}{50.0pt}.
+> \cals@spanq@heights=macro:
+->{50.0pt}.
+% row 4
+> \cals@spanq@heights=macro:
+->.
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_70_intercept.tex b/Master/texmf-dist/doc/latex/cals/test/span/test_70_intercept.tex
new file mode 100644
index 00000000000..3052794b06a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_70_intercept.tex
@@ -0,0 +1,28 @@
+%
+% Bug hunting / regresion test
+%
+\begin{calstable}
+\colwidths{{50pt}}
+\cals@setpadding{}\cals@setcellprevdepth{}
+
+\brow
+ \cell{\noindent\vrule height50pt depth0pt width10pt}
+ \cell{\noindent\vrule height50pt depth0pt width10pt}
+ \nullcell{tlr}\show\cals@spanq@heights
+ \erow
+\brow
+ \cell{\noindent\vrule height50pt depth0pt width10pt}
+ \nullcell{tlr}\show\cals@spanq@heights
+ \nullcell{lr}\show\cals@spanq@heights
+ \erow
+\brow
+ \cell{\noindent\vrule height50pt depth0pt width10pt}
+ \nullcell{lr}\show\cals@spanq@heights
+ \nullcell{rlb}\spancontent{\noindent\vrule height50pt depth0pt width10pt}\show\cals@spanq@heights
+ \erow
+\brow
+ \cell{\noindent\vrule height50pt depth0pt width10pt}
+ \nullcell{lrb}\spancontent{\noindent\vrule height50pt depth0pt width10pt}\show\cals@spanq@heights
+ \cell{\noindent\vrule height50pt depth0pt width10pt}
+ \erow
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_80_marker.chk b/Master/texmf-dist/doc/latex/cals/test/span/test_80_marker.chk
new file mode 100644
index 00000000000..134fccb3bda
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_80_marker.chk
@@ -0,0 +1,20 @@
+% 1
+> \cals@ifInRspan=macro:
+#1->\iffalse .
+> the letter L.
+% 2
+> \cals@ifInRspan=macro:
+#1->\iftrue .
+> the letter X.
+% 3
+> \cals@ifInRspan=macro:
+#1->\iftrue .
+> the letter X.
+% 4
+> \cals@ifInRspan=macro:
+#1->\iftrue .
+> the letter L.
+% 5
+> \cals@ifInRspan=macro:
+#1->\iffalse .
+> the letter L.
diff --git a/Master/texmf-dist/doc/latex/cals/test/span/test_80_marker.tex b/Master/texmf-dist/doc/latex/cals/test/span/test_80_marker.tex
new file mode 100644
index 00000000000..d97f3944b93
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/span/test_80_marker.tex
@@ -0,0 +1,35 @@
+\begin{calstable}
+\colwidths{{100pt}{100pt}}
+
+\brow
+\nullcell{ltb}\nullcell{rtb}\spancontent{row1}
+\show\cals@ifInRspan
+\cals@ifLastRspanRow\iftrue \show L \else \show X \fi
+\erow
+
+\brow
+\nullcell{ltr}\cell{r2}
+\show\cals@ifInRspan
+\cals@ifLastRspanRow\iftrue \show L \else \show X \fi
+\erow
+
+\brow
+\nullcell{lbr}\spancontent{r3}\nullcell{ltr}
+\show\cals@ifInRspan
+\cals@ifLastRspanRow\iftrue \show L \else \show X \fi
+\erow
+
+\brow
+\cell{r3}\nullcell{lbr}\spancontent{r4}
+\show\cals@ifInRspan
+\cals@ifLastRspanRow\iftrue \show L \else \show X \fi
+\erow
+
+\brow
+\cell{r4c1}
+\cell{r4c2}
+\show\cals@ifInRspan
+\cals@ifLastRspanRow\iftrue \show L \else \show X \fi
+\erow
+
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/support/LatexTest.py b/Master/texmf-dist/doc/latex/cals/test/support/LatexTest.py
new file mode 100644
index 00000000000..d204f5fad6b
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/support/LatexTest.py
@@ -0,0 +1,163 @@
+# Running a latex
+import unittest, os, shutil, re, glob
+
+settings = None # will be set from the main script
+
+re_macro_start = re.compile(r'''^> \\[^=]+=macro:$''')
+re_box_start = re.compile(r'''^> \\box\d+=''')
+re_some_show = re.compile(r'''^> .*\.$''')
+re_message = re.compile(r'''^! ''')
+re_comment = re.compile(r'''^%[^\r\n]*[\r\n]*''', re.S|re.M)
+
+class LatexTestCase(unittest.TestCase):
+
+ def __init__(self, *ls):
+ unittest.TestCase.__init__(self, *ls)
+ tpl_file = 'template.txt'
+ h = open(tpl_file)
+ self.template = h.read()
+ h.close()
+
+ def get_settings(self):
+ return settings
+
+ def setUp(self):
+ tmp_dir = settings.get_tmp_dir()
+ for fname in os.listdir(tmp_dir):
+ full_name = os.path.join(tmp_dir, fname)
+ os.unlink(full_name)
+
+ def run_latex(self, module, test_name):
+ tmp_dir = settings.get_tmp_dir()
+ src_latex_file = os.path.join(module, test_name + '.tex')
+ tmp_latex_file = os.path.join(tmp_dir, test_name + '.tex')
+ tmp_log_file = os.path.join(tmp_dir, test_name + '.log')
+ #
+ # Create a TeX file from a tempate
+ #
+ h = open(src_latex_file)
+ s = h.read()
+ h.close()
+ s = self.template.replace('##CODE##', s)
+ h = open(tmp_latex_file, 'w')
+ h.write(s)
+ h.close()
+ #
+ # Run LaTeX
+ #
+ cmd = 'cd %s; %s -interaction batchmode %s.tex >/dev/null' % (tmp_dir, settings.get_latex(), test_name)
+ os.system(cmd)
+ return tmp_log_file
+
+ # -------------------------------------------------------
+ # Log-file works
+
+ #
+ # Comparing expected and the got results
+ #
+ def check_log(self, module, test_name, log_file):
+ s_got = self.collect_log(log_file)
+ chk_file = os.path.join(module, test_name + '.chk')
+ h = open(chk_file)
+ s_expected = h.read()
+ h.close()
+ s_expected = re_comment.sub('', s_expected)
+ s_expected = s_expected.strip()
+ s_got = s_got.strip()
+ #
+ # It is convenient to know where exactly start difference
+ #
+ if s_expected != s_got:
+ pos = 0
+ maxpos = min(len(s_expected), len(s_got))
+ while (pos < maxpos) and (s_expected[pos] == s_got[pos]):
+ pos = pos +1
+ s_expected = s_expected[:pos] + '---->' + s_expected[pos:]
+ s_got = s_got[:pos] + '---->' + s_got[pos:]
+ self.assertEqual(s_got, s_expected)
+
+ #
+ # The test case: run latex and check log
+ #
+ def run_test_case(self, module, test_name):
+ log_file = self.run_latex(module, test_name)
+ self.check_log(module, test_name, log_file)
+ self.check_pdf(module, test_name)
+
+ #
+ # Log parsing
+ #
+ def collect_macro(self, h, macro_dump):
+ for l in h:
+ l = l.strip()
+ macro_dump = macro_dump + "\n" + l
+ if (len(l) > 0) and ('.' == l[-1]):
+ break
+ return macro_dump
+
+ def collect_box(self, h, box_dump):
+ box_dump = re.sub('[0-9]+', 'XX', box_dump)
+ for l in h:
+ l = l.strip()
+ if '' == l:
+ break
+ box_dump = box_dump + "\n" + l
+ return box_dump
+
+ def collect_log(self, log_file):
+ s = ''
+ h = open(log_file)
+ for l in h:
+ l = l.strip()
+ if re_macro_start.match(l):
+ macro_dump = self.collect_macro(h, l)
+ s = s + macro_dump + "\n"
+ if re_box_start.match(l):
+ box_dump = self.collect_box(h, l)
+ s = s + box_dump + "\n"
+ if re_some_show.match(l):
+ s = s + l + "\n"
+ if re_message.match(l):
+ if l != '! OK.':
+ s = s + l + "\n"
+ if l.startswith('Package test Info: '):
+ pos = l.index('on input line ')
+ s = s + l[19:pos]
+ s = s.rstrip()
+ s = s + "\n"
+ return s
+
+ # -------------------------------------------------------
+ # Output works
+
+ def check_pdf(self, module, test_name):
+ #
+ # First, check if output testing is required
+ #
+ expected_pngs = glob.glob(os.path.join(module, test_name+'*.png'))
+ if not len(expected_pngs):
+ return
+ expected_pngs = [os.path.basename(x) for x in expected_pngs]
+ #
+ # Generate PNGs and check we got the same number of files
+ #
+ tmp_dir = settings.get_tmp_dir()
+ cmd = "cd %s; convert -density 300x300 %s.pdf %s.png" % (tmp_dir, test_name, test_name)
+ os.system(cmd)
+ got_pngs = glob.glob(os.path.join(tmp_dir, test_name+'*.png'))
+ got_pngs = [os.path.basename(x) for x in got_pngs]
+ self.assertEqual(expected_pngs, got_pngs)
+ #
+ # Compare the PNGs
+ #
+ for png in expected_pngs:
+ expected_png = os.path.join(module, png)
+ got_png = os.path.join(tmp_dir, png)
+ diff_png = os.path.join(tmp_dir, 'diff.png')
+ cmd = "compare -metric RMSE %s %s %s 2>%s" % (expected_png, got_png, diff_png, os.path.join(tmp_dir, 'compare-stdout'))
+ os.system(cmd)
+ h = open(os.path.join(tmp_dir, 'compare-stdout'))
+ s = h.read()
+ h.close()
+ s = s.strip()
+ self.assertEqual('0 (0)', s)
diff --git a/Master/texmf-dist/doc/latex/cals/test/support/run_tests.py b/Master/texmf-dist/doc/latex/cals/test/support/run_tests.py
new file mode 100644
index 00000000000..c4fa70c22e6
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/support/run_tests.py
@@ -0,0 +1,66 @@
+import glob, os, new, sys
+import unittest
+import LatexTest
+
+#
+# Settings
+#
+class Settings:
+ def __init__(self):
+ sty_dir = os.path.normpath(os.path.join(os.getcwd(), '..', 'dev'))
+ old_ti = os.getenv('TEXINPUTS', '')
+ os.environ['TEXINPUTS'] = sty_dir + ':' + old_ti
+ def get_tmp_dir(self):
+ return 'tmp'
+ def get_latex(self):
+ return 'pdflatex'
+LatexTest.settings = Settings()
+
+#
+# Collect tests
+#
+filter = None
+if len(sys.argv) > 1:
+ filter = sys.argv[1]
+test_files = glob.glob('*/test_*.tex')
+modules_and_tests = {}
+for fname in test_files:
+ (dir, basename) = os.path.split(fname)
+ if 'tmp' == dir:
+ continue
+ if filter:
+ if filter not in fname:
+ continue
+ modules_and_tests.setdefault(dir, []).append(basename)
+
+#
+# Test function
+#
+def generic_test_func(self, modname, testname):
+ print 'I am a test case with parameters:', self.__class__, modname, testname
+ self.assertEqual(1, 1)
+
+#
+# Create test classes and functions
+#
+test_classes = []
+for module in modules_and_tests.iterkeys():
+ mtname = 'Test' + module.capitalize()
+ cls = new.classobj(mtname, (LatexTest.LatexTestCase,), {})
+ for test_file in modules_and_tests[module]:
+ test_name = os.path.splitext(test_file)[0]
+ def get_test_func(func, module, test_name):
+ def proxied(self):
+ func(self, module, test_name)
+ return proxied
+ setattr(cls, test_name, get_test_func(LatexTest.LatexTestCase.run_test_case, module, test_name))
+ test_classes.append(cls)
+
+#
+# Run the tests
+#
+if __name__ == '__main__':
+ tl = unittest.TestLoader()
+ tests = [tl.loadTestsFromTestCase(x) for x in test_classes]
+ tests = unittest.TestSuite(tests)
+ unittest.TextTestRunner(verbosity=2).run(tests)
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_10_ifbreak.chk b/Master/texmf-dist/doc/latex/cals/test/table/test_10_ifbreak.chk
new file mode 100644
index 00000000000..e2b30b0f87f
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_10_ifbreak.chk
@@ -0,0 +1,22 @@
+%
+% Test 1
+%
+OK
+%
+% Test 2
+%
+OK
+%
+% Test 3
+%
+OK
+OK
+%
+% Test 4
+%
+OK
+OK
+%
+% Test 5
+%
+OK
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_10_ifbreak.tex b/Master/texmf-dist/doc/latex/cals/test/table/test_10_ifbreak.tex
new file mode 100644
index 00000000000..d8af5811906
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_10_ifbreak.tex
@@ -0,0 +1,53 @@
+%
+\newbox\cals@current@row % To be removed after defined in cals.sty
+%
+\def\mkcurrow#1{\setbox\cals@current@row=\vbox to #1{a\vfil}%
+ \ht\cals@current@row=#1\relax}
+%\def\mkbakrow#1{\setbox\cals@backup@row=\vbox to #1{a\vfil}}
+\def\mkfoot#1{\def\cals@tfoot@tokens{aaa}\def\cals@tfoot@height{#1}}
+\def\rmfoot{\let\cals@tfoot@tokens=\relax}
+
+\def\ok{\PackageInfo{test}{OK}}
+\def\fail{\PackageInfo{test}{FAIL}}
+
+\let\cals@tbreak@tokens=\relax
+
+%
+% 1: Body, no break
+%
+\def\pagegoal{400pt}
+\def\pagetotal{300pt}
+\mkfoot{50pt}
+\mkcurrow{50pt}
+\let\cals@last@context=b
+\let\cals@current@context=b
+\cals@ifbreak\iftrue \fail \else \ok \fi
+
+%
+% 2: Body, break
+%
+\mkcurrow{60pt}
+\cals@ifbreak\iftrue \ok \else \fail \fi
+
+%
+% 3: No break in head or foot
+%
+\let\cals@current@context=h
+\cals@ifbreak\iftrue \fail \else \ok \fi
+\let\cals@current@context=f
+\cals@ifbreak\iftrue \fail \else \ok \fi
+\let\cals@current@context=b
+
+%
+% 4: No break after the header
+%
+\let\cals@current@context=b
+\cals@ifbreak\iftrue \ok \else \fail \fi
+\let\cals@last@context=h
+\cals@ifbreak\iftrue \fail \else \ok \fi
+
+%
+% 5: User forces a break
+%
+\tbreak{ok}
+\cals@ifbreak\iftrue \ok \else \fail \fi
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_20_dispatch.chk b/Master/texmf-dist/doc/latex/cals/test/table/test_20_dispatch.chk
new file mode 100644
index 00000000000..7990c8bc647
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_20_dispatch.chk
@@ -0,0 +1,56 @@
+%
+% Normal table
+%
+> \boxXX=
+\vbox(1020.0+0.0)x220.0
+% Head
+.\vbox(110.0+0.0)x110.0
+..\rule(110.0+0.0)x110.0
+.\vbox(120.0+0.0)x120.0
+..\rule(120.0+0.0)x120.0
+.\vbox(110.0+0.0)x110.0
+..\rule(110.0+0.0)x110.0
+% Body 1 and Body 2
+.\vbox(10.0+0.0)x10.0
+..\rule(10.0+0.0)x10.0
+.\vbox(20.0+0.0)x20.0
+..\rule(20.0+0.0)x20.0
+.\vbox(10.0+0.0)x10.0
+..\rule(10.0+0.0)x10.0
+% Foot 1 and Foot 2
+.\vbox(210.0+0.0)x210.0
+..\rule(210.0+0.0)x210.0
+.\vbox(220.0+0.0)x220.0
+..\rule(220.0+0.0)x220.0
+.\vbox(210.0+0.0)x210.0
+..\rule(210.0+0.0)x210.0
+%
+% A break in a table
+%
+> \boxXX=
+\vbox(470.0+0.0)x210.0
+.\vbox(10.0+0.0)x10.0
+..\rule(10.0+0.0)x10.0
+.\vbox(210.0+0.0)x210.0
+..\rule(210.0+0.0)x210.0
+.\penalty -10000
+.\vbox(110.0+0.0)x110.0
+..\rule(110.0+0.0)x110.0
+.\vbox(120.0+0.0)x120.0
+..\rule(120.0+0.0)x120.0
+.\vbox(20.0+0.0)x20.0
+..\rule(20.0+0.0)x20.0
+%
+% Span
+%
+> \boxXX=
+\vbox(60.0+0.0)x20.0
+.\vbox(10.0+0.0)x10.0
+..\rule(10.0+0.0)x10.0
+.\vbox(30.0+0.0)x20.0
+..\vbox(20.0+0.0)x20.0
+...\rule(20.0+0.0)x20.0
+..\vbox(10.0+0.0)x10.0
+...\rule(10.0+0.0)x10.0
+.\vbox(20.0+0.0)x20.0
+..\rule(20.0+0.0)x20.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_20_dispatch.tex b/Master/texmf-dist/doc/latex/cals/test/table/test_20_dispatch.tex
new file mode 100644
index 00000000000..4d4910c2e26
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_20_dispatch.tex
@@ -0,0 +1,65 @@
+%
+% Some redefs
+%
+\def\cals@issue@rowsep{\vbox{\hrule width400pt height4pt depth0pt}}
+\def\cals@issue@row{\nointerlineskip \box\cals@current@row}
+
+\def\cals@current@rs@above{rsabove}
+\def\cals@current@rs@below{rsbelow}
+\renewcommand\lastrule{}
+
+\def\somerow#1#2{%
+\setbox\cals@current@row=\vbox{\hrule width#1 height#1 depth0pt}%
+\let\cals@current@context=#2%
+\cals@row@dispatch
+}
+
+\def\bodyrowI{\somerow{10pt}b}
+\def\bodyrowII{\somerow{20pt}b}
+\def\headrowI{\somerow{110pt}h}
+\def\headrowII{\somerow{120pt}h}
+\def\footrowI{\somerow{210pt}f}
+\def\footrowII{\somerow{220pt}f}
+
+%
+% Normal table
+%
+\setbox0=\vbox{%
+\headrowI
+\headrowII
+\headrowI
+\bodyrowI
+\bodyrowII
+\bodyrowI
+\footrowI
+\footrowII
+\footrowI
+}
+\showbox0
+
+%
+% Make a break
+%
+\setbox0=\vbox{%
+\def\cals@thead@tokens{\headrowI\headrowII}
+\def\cals@tfoot@tokens{\footrowI}
+\bodyrowI
+\tbreak{\break}
+\bodyrowII
+}
+\showbox0
+
+%
+% Span
+%
+\setbox0=\vbox{%
+\bodyrowI
+ \let\cals@ifInRspan=\cals@iftrue
+ \let\cals@ifLastRspanRow=\cals@iffalse
+\bodyrowII
+ \let\cals@ifLastRspanRow=\cals@iftrue
+\bodyrowI
+ \let\cals@ifInRspan=\cals@iffalse
+\bodyrowII
+}
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_30_issue_rowsep.chk b/Master/texmf-dist/doc/latex/cals/test/table/test_30_issue_rowsep.chk
new file mode 100644
index 00000000000..b416b189ebc
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_30_issue_rowsep.chk
@@ -0,0 +1,110 @@
+%
+% Alone
+%
+> \boxXX=
+\vbox(0.0+0.0)x330.0
+.\hbox(0.0+0.0)x330.0
+..\glue 0.0
+..\glue 210.0
+..\glue -3.0
+..\rule(2.0+2.0)x127.0
+..\glue -4.0
+..\glue 0.0
+%
+% n to h, f, b: exactly the same as "alone"
+%
+> \boxXX=
+\vbox(0.0+0.0)x330.0
+.\hbox(0.0+0.0)x330.0
+..\glue 0.0
+..\glue 210.0
+..\glue -3.0
+..\rule(2.0+2.0)x127.0
+..\glue -4.0
+..\glue 0.0
+> \boxXX=
+\vbox(0.0+0.0)x330.0
+.\hbox(0.0+0.0)x330.0
+..\glue 0.0
+..\glue 210.0
+..\glue -3.0
+..\rule(2.0+2.0)x127.0
+..\glue -4.0
+..\glue 0.0
+> \boxXX=
+\vbox(0.0+0.0)x330.0
+.\hbox(0.0+0.0)x330.0
+..\glue 0.0
+..\glue 210.0
+..\glue -3.0
+..\rule(2.0+2.0)x127.0
+..\glue -4.0
+..\glue 0.0
+%
+% h to h: default width; h to f,b: body separation
+%
+> \boxXX=
+\vbox(0.0+0.0)x330.0
+.\hbox(0.0+0.0)x330.0
+..\glue 0.0
+..\glue -1.0
+% relax-width here
+..\rule(0.5+0.5)x103.0
+..\glue -2.0
+..\glue -2.0
+..\rule(1.0+1.0)x115.0
+..\glue -3.0
+..\glue -110.0
+..\glue -2.0
+% also relax-width
+..\rule(0.5+0.5)x236.0
+..\glue -4.0
+..\glue -120.0
+..\glue -3.0
+..\rule(2.0+2.0)x127.0
+..\glue -4.0
+..\glue 0.0
+%
+% Body separation
+%
+> \boxXX=
+\vbox(0.0+0.0)x330.0
+.\hbox(0.0+0.0)x330.0
+..\glue 0.0
+..\glue -1.0
+% relax-width here
+..\rule(1.5+1.5)x103.0
+..\glue -2.0
+..\glue -2.0
+..\rule(1.0+1.0)x115.0
+..\glue -3.0
+..\glue -110.0
+..\glue -2.0
+% also relax-width
+..\rule(1.5+1.5)x236.0
+..\glue -4.0
+..\glue -120.0
+..\glue -3.0
+..\rule(2.0+2.0)x127.0
+..\glue -4.0
+..\glue 0.0
+> \cals@tmpIII=macro:
+->3pt.
+%
+% f to h and b: never happens, body separation; f to f: default width
+%
+> \cals@tmpIII=macro:
+->3pt.
+> \cals@tmpIII=macro:
+->1pt.
+> \cals@tmpIII=macro:
+->3pt.
+%
+% b to h: never happens, body separation; b to b: default, b to f: body
+%
+> \cals@tmpIII=macro:
+->3pt.
+> \cals@tmpIII=macro:
+->3pt.
+> \cals@tmpIII=macro:
+->1pt.
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_30_issue_rowsep.tex b/Master/texmf-dist/doc/latex/cals/test/table/test_30_issue_rowsep.tex
new file mode 100644
index 00000000000..2e33f8ad57e
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_30_issue_rowsep.tex
@@ -0,0 +1,52 @@
+\def\cals@framers@width{0pt}
+\def\cals@bodyrs@width{3pt}
+\def\cals@rs@width{1pt}
+
+%
+% Reusable definitions
+%
+\def\frameI{{{100pt}{2pt}{4pt}\relax}{{110pt}{4pt}{6pt}{2pt}}{{120pt}{6pt}{8pt}\relax}}
+\def\frameII{{{100pt}{2pt}{4pt}\relax}{{110pt}{4pt}{6pt}\relax}{{120pt}{6pt}{8pt}{4pt}}}
+\def\update{%
+\toks0=\expandafter{\frameI}%
+\edef\cals@last@rs@below{\the\toks0}%
+\toks0=\expandafter{\frameII}%
+\edef\cals@current@rs@above{\the\toks0}%
+}
+
+%
+% Alone
+%
+\update
+\setbox0=\vbox{\cals@issue@rowsep@alone}
+\showbox0
+
+%
+% Different combinations
+%
+\def\combineII#1#2{%
+\let\cals@last@context=#1%
+\let\cals@current@context=#2%
+\update
+\setbox0=\vbox{\cals@issue@rowsep}}
+\def\combine#1#2{\combineII#1#2\showbox0 }
+
+% n h f b vs h f b
+\combine nh
+\combine nf
+\combine nb
+\combine hh
+\combine hf
+
+%
+% Optimize the rest: do not pollute expected results
+%
+\renewcommand\cals@rs@joinTwo[3]{%
+\show#1}
+\combineII hb
+\combineII fh
+\combineII ff
+\combineII fb
+\combineII bh
+\combineII bf
+\combineII bb
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_40_issuerow.chk b/Master/texmf-dist/doc/latex/cals/test/table/test_40_issuerow.chk
new file mode 100644
index 00000000000..5e42a5f3526
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_40_issuerow.chk
@@ -0,0 +1,27 @@
+> \cals@last@context=the letter b.
+> \cals@last@rs@below=macro:
+->{{200pt}{2pt}{2pt}{7pt}}.
+> \boxXX=
+\vbox(20.0+0.0)x300.0
+.\vbox(0.0+0.0)x10.0
+..\hbox(20.0+0.0)x10.0
+...\glue 0.0
+...\hbox(20.0+0.0)x10.0
+....\rule(*+0.0)x10.0
+...\glue 0.0
+.\hbox(0.0+0.0)x200.0
+..\glue 0.0
+..\glue -1.0
+..\rule(2.0+2.0)x202.0
+..\glue -1.0
+..\glue 0.0
+.\hbox(20.0+0.0)x300.0
+..\glue 0.0
+..\hbox(20.0+0.0)x300.0
+...\vbox(20.0+0.0)x100.0, glue set 10.0fil
+....\rule(10.0+0.0)x100.0
+....\glue 0.0 plus 1.0fil
+...\vbox(20.0+0.0)x200.0
+....\rule(20.0+0.0)x200.0
+....\glue 0.0 plus 1.0fil
+..\glue 0.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_40_issuerow.tex b/Master/texmf-dist/doc/latex/cals/test/table/test_40_issuerow.tex
new file mode 100644
index 00000000000..f46144ba3e7
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_40_issuerow.tex
@@ -0,0 +1,25 @@
+%
+% vboxes of the row should be of the same height
+%
+\let\cals@last@context=h
+\let\cals@current@context=b
+\def\cals@bodyrs@width{4pt}
+
+\newbox\cals@current@row
+\setbox\cals@current@row=\hbox{%
+ \vbox{\hrule height10pt depth0pt width100pt \vfil}%
+ \vbox{\hrule height20pt depth0pt width200pt \vfil}%
+}
+\cals@reheight@cells\cals@current@row
+
+\newbox\cals@current@cs
+\setbox\cals@current@cs=\hbox{\vrule width10pt depth0pt}
+\ht\cals@current@cs=\ht\cals@current@row
+\def\cals@current@rs@above{{{200pt}{2pt}{2pt}\relax}}
+\def\cals@current@rs@below{{{200pt}{2pt}{2pt}{7pt}}}
+\def\cals@last@rs@below{{{200pt}{2pt}{2pt}\relax}}
+
+\setbox0=\vbox{\cals@issue@row
+\show\cals@last@context
+\show\cals@last@rs@below}
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_50_row.chk b/Master/texmf-dist/doc/latex/cals/test/table/test_50_row.chk
new file mode 100644
index 00000000000..8488abb63c6
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_50_row.chk
@@ -0,0 +1,99 @@
+> \cals@last@context=the letter b.
+> \cals@last@rs@below=macro:
+->{{100pt}{0pt}{10pt}{10pt}}{{200pt}{10pt}{20pt}{20pt}}.
+> 20.0pt.
+> \cals@last@context=the letter b.
+> \cals@last@rs@below=macro:
+->{{100pt}{0pt}{30pt}{30pt}}{{200pt}{30pt}{40pt}{40pt}}.
+> 40.0pt.
+%
+% The table
+%
+> \boxXX=
+\vbox(60.0+0.0)x300.0
+%
+% Row 1, colsep
+%
+.\vbox(0.0+0.0)x300.0
+..\hbox(20.0+0.0)x300.0
+...\glue 0.0
+...\hbox(20.0+0.0)x300.0
+....\glue 100.0
+....\glue -5.0
+....\rule(*+0.0)x10.0
+....\glue -5.0
+....\glue 200.0
+....\glue -10.0
+....\rule(*+0.0)x20.0
+....\glue -10.0
+...\glue 0.0
+%
+% Rowsep before row 1
+%
+.\hbox(0.0+0.0)x300.0
+..\glue 0.0
+..\glue 300.0
+..\glue 0.0
+%
+% Row 1
+%
+.\hbox(20.0+0.0)x300.0
+..\glue 0.0
+..\hbox(20.0+0.0)x300.0
+...\vbox(20.0+0.0)x100.0, glue set 10.0fil
+....\rule(10.0+0.0)x100.0
+....\glue 0.0 plus 1.0fil
+...\vbox(20.0+0.0)x200.0
+....\rule(20.0+0.0)x200.0
+....\glue 0.0 plus 1.0fil
+..\glue 0.0
+%
+% Output procesure forcing
+%
+.\glue 0.0
+.\penalty 10000
+%
+% Row 2, colsep
+%
+.\vbox(0.0+0.0)x300.0
+..\hbox(40.0+0.0)x300.0
+...\glue 0.0
+...\hbox(40.0+0.0)x300.0
+....\glue 100.0
+....\glue -15.0
+....\rule(*+0.0)x30.0
+....\glue -15.0
+....\glue 200.0
+....\glue -20.0
+....\rule(*+0.0)x40.0
+....\glue -20.0
+...\glue 0.0
+%
+% Rowsep between row 1 and row 2
+%
+.\hbox(0.0+0.0)x300.0
+..\glue 0.0
+..\glue 0.0
+..\rule(5.0+5.0)x115.0
+..\glue -15.0
+..\glue -5.0
+..\rule(10.0+10.0)x215.0
+..\glue -10.0
+..\glue -200.0
+..\glue -15.0
+..\rule(5.0+5.0)x235.0
+..\glue -20.0
+..\glue 0.0
+%
+% Row 2
+%
+.\hbox(40.0+0.0)x300.0
+..\glue 0.0
+..\hbox(40.0+0.0)x300.0
+...\vbox(40.0+0.0)x100.0, glue set 10.0fil
+....\rule(30.0+0.0)x100.0
+....\glue 0.0 plus 1.0fil
+...\vbox(40.0+0.0)x200.0
+....\rule(40.0+0.0)x200.0
+....\glue 0.0 plus 1.0fil
+..\glue 0.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_50_row.tex b/Master/texmf-dist/doc/latex/cals/test/table/test_50_row.tex
new file mode 100644
index 00000000000..5fa49715de5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_50_row.tex
@@ -0,0 +1,44 @@
+%
+% A smoke test for \row
+%
+\def\mkcell#1{\edef\cals@borderB{#1}\edef\cals@borderR{#1}%
+\cell{\nointerlineskip\noindent\vrule height#1 depth0pt width#1}}
+\def\mkcellI{\mkcell{10pt}}
+\def\mkcellII{\mkcell{20pt}}
+\def\mkcellIII{\mkcell{30pt}}
+\def\mkcellIV{\mkcell{40pt}}
+
+\let\cals@last@context=n
+\let\cals@current@context=b
+
+\def\cals@cs@width{0pt}
+\def\cals@framecs@width{0pt}
+\def\cals@rs@width{10pt}
+\def\cals@framers@width{0pt}
+\def\cals@bodyrs@width{0pt}
+\def\cals@bgcolor{}
+\def\cals@bgcolor{}
+\let\cals@borderL=\relax
+\let\cals@borderR=\relax
+\let\cals@borderT=\relax
+\let\cals@borderB=\relax
+
+\def\cals@ifbreak#1{\iffalse}
+\let\oldend=\cals@celll@end
+\def\cals@celll@end{%
+ \setbox0=\vbox{\hrule height\ht0 depth0pt width\wd0 \vfil}%
+ \oldend}
+
+\colwidths{{100pt}{200pt}}
+
+\setbox0=\vbox{%
+\brow \mkcellI\mkcellII \erow
+\show\cals@last@context
+\show\cals@last@rs@below
+\showthe\cals@last@row@height
+\brow \mkcellIII\mkcellIV \erow
+\show\cals@last@context
+\show\cals@last@rs@below
+\showthe\cals@last@row@height
+}
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_60_whitespace.chk b/Master/texmf-dist/doc/latex/cals/test/table/test_60_whitespace.chk
new file mode 100644
index 00000000000..a5e0c8760a4
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_60_whitespace.chk
@@ -0,0 +1,2 @@
+> \boxXX=
+\vbox(0.0+0.0)x0.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_60_whitespace.tex b/Master/texmf-dist/doc/latex/cals/test/table/test_60_whitespace.tex
new file mode 100644
index 00000000000..55d4ca10baf
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_60_whitespace.tex
@@ -0,0 +1,21 @@
+\def\cals@issue@rowsep@alone{}
+\def\cals@issue@rowsep{}
+\def\cals@issue@row{}
+
+%
+% Check that there are no unneeded whitespace in output
+%
+
+\setbox0=\vbox{
+
+\begin{calstable}
+
+\colwidths{{100pt}{200pt}}
+
+\brow{}
+ \cell{aaaaa} \nullcell{ltb} \nullcell{rtb} \spancontent{bbbbb} \cell{bbbb} \erow{} % ok
+\end{calstable}
+
+}
+
+\showbox0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_70_lrskip.chk b/Master/texmf-dist/doc/latex/cals/test/table/test_70_lrskip.chk
new file mode 100644
index 00000000000..f2ef8998bf2
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_70_lrskip.chk
@@ -0,0 +1,32 @@
+> \boxXX=
+\vbox(20.0+0.0)x300.0
+% colsep
+.\vbox(0.0+0.0)x300.0
+..\hbox(20.0+0.0)x300.0
+...\glue 50.0
+...\hbox(20.0+0.0)x100.0
+....\glue 100.0
+...\glue 150.0
+% rowsep
+.\hbox(0.0+0.0)x300.0
+..\glue 50.0
+..\glue 100.0
+..\glue 150.0
+% cell
+.\hbox(20.0+0.0)x300.0
+..\glue 50.0
+..\hbox(20.0+0.0)x100.0
+...\vbox(20.0+0.0)x100.0, glue set 20.0fil
+....\glue 0.0
+....\glue 0.0 plus -1.0
+....\glue 0.0 plus 1.0fil
+....\glue 0.0
+..\glue 150.0
+% thead+row1 break workaround
+.\glue 0.0
+.\penalty 10000
+% rowsep
+.\hbox(0.0+0.0)x300.0
+..\glue 50.0
+..\glue 100.0
+..\glue 150.0
diff --git a/Master/texmf-dist/doc/latex/cals/test/table/test_70_lrskip.tex b/Master/texmf-dist/doc/latex/cals/test/table/test_70_lrskip.tex
new file mode 100644
index 00000000000..a6d507b7381
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/table/test_70_lrskip.tex
@@ -0,0 +1,22 @@
+par1\par
+\parindent=0pt
+par2\par
+
+\setbox0=\vbox{%
+\leftskip=50pt
+\rightskip=150pt
+\begin{calstable}
+\cals@setpadding{}
+\cals@setcellprevdepth{}
+\def\borderL{0pt}
+\let\borderR=\borderL
+\let\borderT=\borderL
+\let\borderB=\borderL
+\colwidths{{100pt}}
+\brow \cell{} \ht\cals@current@row=20pt \erow
+\end{calstable}
+}
+\showbox0
+\box0
+par3\par
+par4\par
diff --git a/Master/texmf-dist/doc/latex/cals/test/template.txt b/Master/texmf-dist/doc/latex/cals/test/template.txt
new file mode 100644
index 00000000000..5e0b64b7380
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/template.txt
@@ -0,0 +1,33 @@
+\documentclass{minimal}
+\usepackage{color}
+\makeatletter
+\showboxdepth=100
+\showboxbreadth=100
+
+%\iftrue
+\iffalse
+\usepackage{cals}
+\else
+\input{cell.dtx}
+\input{table.dtx}
+\input{span.dtx}
+\input{lltokens.dtx}
+\input{decor.dtx}
+\input{colsep.dtx}
+\input{rowsep.dtx}
+\fi
+
+% Variables defined inside calstable environment
+\let\cals@thead@tokens=\relax
+\let\cals@tfoot@tokens=\relax
+\let\cals@tbreak@tokens=\relax
+\let\cals@ifInRspan=\cals@iffalse
+\let\cals@ifLastRspanRow=\cals@iftrue
+\let\cals@borderL=\relax
+\let\cals@borderR=\relax
+\let\cals@borderT=\relax
+\let\cals@borderB=\relax
+
+\begin{document}
+##CODE##
+\end{document}
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.chk b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.chk
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.chk
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.png b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.png
new file mode 100644
index 00000000000..242bc2be544
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.png
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.tex b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.tex
new file mode 100644
index 00000000000..0763a13ef01
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_10_simple_2x2_with_parbreak.tex
@@ -0,0 +1,11 @@
+%
+% Make the same table as in the version 1
+\def\cals@framecs@width{1.2pt }
+\def\cals@framers@width{1.2pt }
+%
+\hrule width\hsize \vskip10pt
+\begin{calstable}
+\colwidths{{60pt}{120pt}}
+\brow \cell{aaa\\a} \cell{bbb} \erow
+\brow \cell{ccc} \cell{ddd\\dg} \erow
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.chk b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.chk
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.chk
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.png b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.png
new file mode 100644
index 00000000000..86f9b2db184
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.png
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.tex b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.tex
new file mode 100644
index 00000000000..86b88dd19af
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_20_thead_tfoot.tex
@@ -0,0 +1,20 @@
+\def\cbll#1{\cell{\textbf{#1}}}
+%
+\begin{calstable}
+\colwidths{{60pt}{120pt}}
+%
+\thead{Hello from the THead caption!\par
+\brow \cbll{eee} \cbll{fff} \erow
+\brow \cbll{ggg} \cbll{hhh} \erow
+}
+%
+\tfoot{
+\brow \cbll{iii} \cbll{jjj} \erow
+\brow \cbll{kkk} \cbll{lll} \erow
+\lastrule
+I am the TFoot caption\par
+}
+%
+\brow \cell{aaa} \cell{bbb} \erow
+\brow \cell{ccc} \cell{ddd} \erow
+\end{calstable}
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.chk b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.chk
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.chk
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.png b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.png
new file mode 100644
index 00000000000..f53e6498bb7
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.png
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.tex b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.tex
new file mode 100644
index 00000000000..ddfbb3b2270
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_30_tbreak.tex
@@ -0,0 +1,27 @@
+\hrule width\hsize \vskip10pt
+
+\begin{calstable}
+\colwidths{{60pt}{120pt}}
+\brow \cell{aaa} \cell{bbb} \erow
+\brow \cell{ccc} \cell{ddd} \erow
+\tbreak{(break)\par}
+\brow \cell{eee} \cell{fff} \erow
+\brow \cell{ggg} \cell{hhh} \erow
+\end{calstable}
+
+\bigskip
+\hrule height5pt depth5pt width180pt
+\bigskip
+
+\def\cbll#1{\cell{\textbf{#1}}}
+\begin{calstable}
+\colwidths{{60pt}{120pt}}
+\thead{\brow\cbll{iii}\cbll{jjj}\erow}
+\tfoot{\brow\cbll{kkk}\cbll{lll}\erow}
+\brow \cell{aaa} \cell{bbb} \erow
+\brow \cell{ccc} \cell{ddd} \erow
+\tbreak{(break)\par}
+\brow \cell{eee} \cell{fff} \erow
+\brow \cell{ggg} \cell{hhh} \erow
+\end{calstable}
+
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.chk b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.chk
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.chk
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.png b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.png
new file mode 100644
index 00000000000..d3f73b584e6
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.png
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.tex b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.tex
new file mode 100644
index 00000000000..08568db94e8
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cals/test/visual_tables/test_40_span.tex
@@ -0,0 +1,52 @@
+\hrule width\hsize \vskip10pt
+\begin{calstable}
+\colwidths{{60pt}}
+\brow
+ \cell{a6} % a6
+ \cell{b6} % b6
+ \cell{c6} % c6
+ \cell{d6} % d6
+ \cell{e6} % e6
+ \cell{f6} % f6
+ \erow
+\brow
+ \cell{a5} % a5
+ \nullcell{ltb} % b5
+ \nullcell{tb} % c5
+ \nullcell{rtb}\spancontent{b5, c5, d5} % d5
+ \nullcell{ltr} % e5
+ \cell{f5} % f5
+ \erow
+\brow
+ \cell{a4} % a4
+ \nullcell{ltr} % b4
+ \nullcell{tl} % c4
+ \nullcell{tr} % d4
+ \nullcell{lr} % e4
+ \cell{f4} % f4
+ \erow
+\brow
+ \cell{a3} % a3
+ \nullcell{lr} % b3
+ \nullcell{lb} % c3
+ \nullcell{rb}\spancontent{c3, c4, d3, d4} % d3
+ \nullcell{lrb}\spancontent{e3, e4, e5} % e3
+ \cell{f3} % f3
+ \erow
+\brow
+ \cell{a2} % a2
+ \nullcell{lrb}\spancontent{b2, b3, b4} % b2
+ \nullcell{ltb} % c2
+ \nullcell{tb} % d2
+ \nullcell{tbr} % e2
+ \spancontent{c2, d2, e2}\cell{f2} % f2
+ \erow
+\brow
+ \cell{a1} % a1
+ \cell{b1} % b1
+ \cell{c1} % c1
+ \cell{d1} % d1
+ \cell{e1} % e1
+ \cell{f1} % f1
+ \erow
+\end{calstable}
diff --git a/Master/texmf-dist/source/latex/cals/cals.dtx b/Master/texmf-dist/source/latex/cals/cals.dtx
new file mode 100644
index 00000000000..e0ae6dbac16
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/cals.dtx
@@ -0,0 +1,168 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2010 by Oleg Parashchenko <olpa@uucode.com>
+% -------------------------------------------------------
+%
+% This file may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.2
+% of this license or (at your option) any later version.
+% The latest version of this license is in:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.2 or later is part of all distributions of LaTeX
+% version 1999/12/01 or later.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\ProvidesFile{cals.dtx}
+%</driver>
+%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package>\ProvidesPackage{cals}
+%<*package>
+ [2010/10/07 CALS tables v.2.0]
+%</package>
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{hyperref}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\begin{document}
+ \DocInput{cals.dtx}
+ \PrintChanges
+ \PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{0}
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+%
+% \changes{v2.0}{2010/10/08}{Complete rewrite with different approach}
+% \changes{v1.0}{2010/06/17}{Initial version from skeleton.dtx}
+%
+% \GetFileInfo{cals.dtx}
+%
+% \DoNotIndex{\newcommand,\newenvironment}
+%
+%
+% \title{The \textsf{cals} package\thanks{This document
+% corresponds to \textsf{cals}~\fileversion, dated \filedate.}}
+% \author{Oleg Parashchenko \\ \texttt{olpa@uucode.com}}
+%
+% \maketitle
+%
+% \section{Introduction}
+%
+% The |cals| package is a set of macros to typeset multipage tables
+% with repeatable headers and footers, with cells spanned over
+% rows and columns. Decorations are supported: padding, background
+% color, width of separation rules. The code is compatible with
+% multicols and pdfsync.
+%
+% The work is released to public (\LaTeX{} license)
+% by \url{bitplant.de}~GmbH, a company which provides technical
+% documentation services to industry.
+%
+% \section{Usage}
+%
+% An users' guide is a separate document, yet to be written.
+% I'll do it for TUGboat 2011:1. At the moment, as a substitute,
+% use the demo document provided with the package. The most
+% important feature: the table (its rows) must start in a vertical
+% mode, the cells content should switch to a horizontal mode.
+%
+% Please post questions and suggestions to the newsgroup
+% |comp.text.tex| and the |texhax| mailing list (see
+% \url{http://tug.org/mailman/listinfo/texhax}),
+% not directly to me.
+%
+% Summary of the user interface:
+% \begin{verbatim}
+% \begin{calstable}
+% \colwidths{{100pt}{200pt}}
+% \brow \cell{a} \cell{b} \erow
+% \end{calstable}
+% \end{verbatim}
+%
+% Table elements: |\thead|, |\tfoot|, |\tbreak{\penalty-10000}|, |\lastrule|.
+%
+% Alignment: |\alignL|, |\alignC|, |\alignR|, |\vfill|.
+%
+% Padding: lengths |\cals@paddingL| (|...T,R,B|), set by |\cals@setpadding{Ag}|,
+% baseline alignment |\cals@paddingD|, set by |\cals@setcellprevdepth{Al}|.
+%
+% Color: |\cals@bgcolor|.
+%
+% Rules: |\cals@cs@width|, |\cals@framecs@width|, |\cals@rs@width|,
+% |\cals@framers@width|, |\cals@bodyrs@width|. Overrides:
+% |\cals@borderL| (|...T,R,B|).
+%
+% Hooks: |\cals@AtBeginCell|, |\cals@AtEndCell|.
+%
+% Spanning: |\nullcell|, |\spancontent|.
+%
+% \StopEventually{}
+%
+% \section{Implementation}
+%
+% What happens. |\cell| creates a table cell, puts it to the
+% current row and updates decorations. At the end of the row
+% (|\erow|) we have the box |\cals@current@row|, the box
+% |\cals@current@cs|---column separation and cells background---and
+% the macros |\cals@current@rs@above| and |\cals@current@rs@below|---all
+% the required data to typeset row separation.
+% Before dispatching the row, all the cells are repacked
+% to the common height. The row dispatcher (|\cals@row@dispatch|)
+% usually just uses |\cals@issue@row|, which
+% outputs |current@cs|, then joins the previous row |cs@below| with the
+% current row |rs@above| and typesets the resulting row separation, and
+% finally prints the row itself. If a table break is required, the
+% dispatcher backups the current row and first typesets the table footer,
+% a page break and the table header. In case of a row span, the set
+% of the rows is converted to one big row.
+%
+% I tried to code as good and robust as I can. In particular,
+% the package contains unit tests. However, being an unexperienced
+% \TeX{} programmer, I could write bad code, especially in the section
+% ``List list of tokens''. Do not hesitate to send me suggestions
+% and corrections, also in the use of English.
+%
+% The description is split on two parts: main functionality and
+% decorations. The first part is bottom-up: creating cells,
+% collecting cells to a row, dispatching a row, top-level table
+% elements. The second part starts with the common code,
+% then explains in-row decorations (column separation and cells
+% background) and between-row decorations (row separation).
+%
+% \input{cell.dtx}
+% \input{span.dtx}
+% \input{table.dtx}
+% \input{lltokens.dtx}
+% \input{decor.dtx}
+% \input{colsep.dtx}
+% \input{rowsep.dtx}
+
+%
+% \Finale
+\endinput
diff --git a/Master/texmf-dist/source/latex/cals/cals.ins b/Master/texmf-dist/source/latex/cals/cals.ins
new file mode 100644
index 00000000000..6c85c8f34e4
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/cals.ins
@@ -0,0 +1,62 @@
+%%
+%% Copyright (C) 2004 by Oleg Parashchenko <olpa@uucode.com>
+%%
+%% This file may be distributed and/or modified under the conditions of
+%% the LaTeX Project Public License, either version 1.2 of this license
+%% or (at your option) any later version. The latest version of this
+%% license is in:
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% and version 1.2 or later is part of all distributions of LaTeX version
+%% 1999/12/01 or later.
+%%
+
+\input docstrip.tex
+\keepsilent
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2004 by Oleg Parashchenko <olpa@uucode.com>
+
+This file may be distributed and/or modified under the conditions of
+the LaTeX Project Public License, either version 1.2 of this license
+or (at your option) any later version. The latest version of this
+license is in:
+
+ http://www.latex-project.org/lppl.txt
+
+and version 1.2 or later is part of all distributions of LaTeX version
+1999/12/01 or later.
+
+\endpreamble
+
+\generate{\file{cals.sty}{
+ \from{cals.dtx}{package}
+ \from{cell.dtx}{package}
+ \from{span.dtx}{package}
+ \from{table.dtx}{package}
+ \from{lltokens.dtx}{package}
+ \from{decor.dtx}{package}
+ \from{colsep.dtx}{package}
+ \from{rowsep.dtx}{package}
+ }}
+
+\obeyspaces
+\Msg{*************************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* cals.sty *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file skeleton.dtx *}
+\Msg{* through LaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{*************************************************************}
+
+\endbatchfile
diff --git a/Master/texmf-dist/source/latex/cals/cell.dtx b/Master/texmf-dist/source/latex/cals/cell.dtx
new file mode 100644
index 00000000000..1d72f279557
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/cell.dtx
@@ -0,0 +1,314 @@
+% \subsection{Creating cells}
+
+% \begin{macro}{\cals@cell}
+% \begin{macro}{\cals@cell@end}
+% Creates an individual cell before socialization into a table.
+% Content of the cell is typeset inside a group.
+% Execution continues in |\cals@celll@end|. Parameters:
+% \begin{enumerate}
+% \item Width of the cell
+% \item Vertical correction: when we have a rowspan, the cell is created while processing the last row. The vertical correction is required to raise the text back to the first row of the rowspan.
+% \item (Implicit parameter.) Content. It is important that it contains a switch to the horizontal mode, otherwise horizontal dimensions of the cell will be incorrect.
+% \end{enumerate}
+% Using an implicit parameter instead of putting it to a macro
+% parameter is probably a premature optimization.
+%
+%
+% \begin{macrocode}
+\newcommand\cals@cell[3]{}
+\def\cals@cell#1#2{%
+% \end{macrocode}
+%
+% Start immediately with |\vbox| to allow |\setbox0=\cals@cell{...}|
+% construction. Later, white integrating the cell into
+% a row, the content will be unvboxed and put to a vbox
+% of the row height.
+%
+% \begin{macrocode}
+\vbox\bgroup%
+% \end{macrocode}
+%
+% Implicitely sets the width and the horizontal paddings
+% of the cell. These settings come into effect on
+% switch from the restricted vertical mode (our |\vbox|) to
+% the horizontal mode. Therefore, the content must force such
+% switch, otherwise the code fails.
+%
+% \begin{macrocode}
+\hsize=#1
+\linewidth=#1
+\leftskip=\cals@paddingL %
+\rightskip=\cals@paddingR %
+% \end{macrocode}
+%
+% Vertical correction and top padding
+%
+% \begin{macrocode}
+\ifdim #2>0pt %
+ \vskip-#2
+\fi
+\vskip\cals@paddingT %
+% \end{macrocode}
+%
+% Tuning the top padding. First, compensate the |\parskip|,
+% which appears on the mode switch. Second, adjusts baselineskip,
+% so in the case of the right preliminimary setup, the top of the
+% letters "Al" touches the padding border. Meanwhile, setting
+% prevdepth aligns the baselines of the first text lines
+% of the row cells.
+%
+% \begin{macrocode}
+\vskip-\parskip %
+\prevdepth=\cals@paddingD %
+% \end{macrocode}
+%
+% Finally, the content. And the switch to the horizontal mode (we hope).
+%
+% We want more work afrer typesetting the content, but it is not
+% desirable to collect all the tokens. Instead, start a group and use
+% |\aftergroup| to finish typesetting. For more explanations, see
+% ``\TeX{} by Topic'', Chapter 12 ``Expansion''.
+%
+% \begin{macrocode}
+\bgroup\aftergroup\cals@cell@end
+\cals@AtBeginCell\let\next=% eat '{' of the content
+}%{Implicit content}
+
+% \end{macrocode}
+%
+% The infinite glue before the bottom padding is useful later,
+% when we will re-height the cells in a row.
+%
+% \begin{macrocode}
+\def\cals@cell@end{\vfil\vskip\cals@paddingB
+\cals@AtEndCell\egroup % finish vbox
+% \end{macrocode}
+% Call the caller
+% \begin{macrocode}
+\cals@celll@end}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+
+% \begin{macro}{\cell}
+% Creates a cell and appends it to the hbox |\cals@current@row|.
+% \begin{macrocode}
+\newcommand\cell[1]{}
+\def\cell{%
+% \end{macrocode}
+% Get the width of the cell and typeset it to the box 0.
+% The execution flow is: |\cell| to |\cals@cell|
+% to |\cals@cell@end| to |\cals@celll@end|.
+% \begin{macrocode}
+\llt@rot\cals@colwidths
+\let\cals@cell@width=\llt@car
+\setbox0=\cals@cell\cals@cell@width{0pt}%
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@AtBeginCell}
+% \begin{macro}{\cals@AtEndCell}
+% Additional code to be executed at the begin and at the end
+% of a cell. An use case is a hook for pdfsync:
+% |\def\cals@AtBeginCell{\pdfsyncstart}|. I am not sure if the end-hook
+% is useful because all the changes are local for the cell group,
+% but decided to retain it for symmetry.
+% \begin{macrocode}
+\let\cals@AtBeginCell=\relax
+\let\cals@AtEndCell=\relax
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+
+% \begin{macro}{\cals@width@cell@put@row}
+% Implicit setting of the cell width can fail (example is an empty cell).
+% In this case, force the width explicitely. Then put the cell
+% to the current row. This code should be a part of |\cals@celll@end|,
+% but due to |\spancontent| is in a separate macro.
+% \begin{macrocode}
+\newcommand\cals@width@cell@put@row{%
+\ifdim \cals@cell@width=\wd0 \relax \else \wd0=\cals@cell@width \fi
+\setbox\cals@current@row=\hbox{\unhbox\cals@current@row\box0 }}%
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@celll@end}
+% After a cell is typeset to the box 0, execution continues here
+% (see notes to |\cell|). Update the current row and its decorations.
+% \begin{macrocode}
+\newcommand\cals@celll@end{%
+\cals@width@cell@put@row
+\cals@decor@next\cals@cell@width}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\spancontent}
+% Typesets a spanned cell (the content is in the implicit argument)
+% and puts it to the current row.
+% The width and height correction are
+% already calculated, the decorations are also already added.
+% \begin{macrocode}
+\newcommand\spancontent[1]{}
+\def\spancontent{%
+\let\cals@tmp=\cals@celll@end
+\let\cals@cell@width=\cals@span@width
+\def\cals@celll@end{%
+ \cals@width@cell@put@row%
+ \let\cals@celll@end=\cals@tmp}%
+\setbox0=\cals@cell{\cals@span@width}{\cals@span@height}%
+}%{Implicit content}
+% \end{macrocode}
+% \end{macro}
+
+% \subsubsection{Cell padding}
+
+% \begin{macro}{\cals@setpadding}
+% \begin{macro}{\cals@paddingL}
+% \begin{macro}{\cals@paddingR}
+% \begin{macro}{\cals@paddingT}
+% \begin{macro}{\cals@paddingB}
+%
+% Calculates and sets the cell padding. It seems that a good value
+% is the half of the font size, calculated as the full height of
+% a box with the content \#1. The calstable environment uses
+% the letters ``Ag''.
+%
+% \begin{macrocode}
+\newskip\cals@paddingL
+\newskip\cals@paddingR
+\newskip\cals@paddingT
+\newskip\cals@paddingB
+
+\newcommand{\cals@setpadding}[1]{%
+\setbox0=\hbox{#1}%
+\dimen0=\ht0 \advance\dimen0 by \dp0 \divide\dimen0 by 2
+\cals@paddingL=\dimen0 \relax
+\cals@paddingR=\cals@paddingL
+\cals@paddingT=\cals@paddingL
+\cals@paddingB=\cals@paddingL
+}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}\end{macro}
+
+% \begin{macro}{\cals@setcellprevdepth}
+% \begin{macro}{\cals@paddingD}
+% The function |\cals@cell| uses the
+% length |\cals@paddingD| to tune the top padding. The macro
+% |\cals@setcellprevdepth| calculates and sets this parameter,
+% so that a box with the content \#1 touches the padding border.
+% The calstable environment uses the letters ``Al''.
+%
+% \begin{macrocode}
+\newdimen\cals@paddingD
+
+\newcommand{\cals@setcellprevdepth}[1]{%
+\setbox0=\vbox{\prevdepth=0pt #1}%
+\setbox1=\vbox{#1}%
+\dimen0=\ht0 \advance\dimen0 by \dp0 %
+\advance\dimen0 by -\ht1 \advance\dimen0 by -\dp1%
+\cals@paddingD=\dimen0 }
+% \end{macrocode}
+% \end{macro}\end{macro}
+
+% \begin{macro}{\alignL}
+% \begin{macro}{\alignC}
+% \begin{macro}{\alignR}
+% To align the table cell text left, center or right we add or
+% remove vfill-part of the left and right padding. Executed
+% by assigning skip to dimen.
+% \begin{macrocode}
+\newcommand\alignL{%
+\dimen0=\cals@paddingL \cals@paddingL=\dimen0 \relax
+\dimen0=\cals@paddingR \cals@paddingR=\dimen0 \relax}
+
+\newcommand\alignC{%
+\dimen0=\cals@paddingL \cals@paddingL=\dimen0 plus 1fill\relax
+\dimen0=\cals@paddingR \cals@paddingR=\dimen0 plus 1fill\relax}
+
+\newcommand\alignR{%
+\dimen0=\cals@paddingL \cals@paddingL=\dimen0 plus 1fill\relax
+\dimen0=\cals@paddingR \cals@paddingR=\dimen0 \relax}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+
+% \subsection{From cells to a row}
+
+% \begin{macro}{\cals@current@row}
+% Rows are first typeset to this hbox.
+% \begin{macrocode}
+\newbox\cals@current@row
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\colwidths}
+% \begin{macro}{\cals@colwidths}
+% The macro |\cals@colwidths| contains a list of column widths.
+% The user sets it through the API macro |\colwidths|, which performs
+% expansion. The list is alive, it is rotated after a cell is finished,
+% so the width of the next cell is always the first element.
+% \begin{macrocode}
+\newcommand\colwidths[1]{}
+\def\colwidths#{\edef\cals@colwidths}
+\def\cals@colwidths{{100pt}}
+% \end{macrocode}
+% \end{macro}\end{macro}
+
+% Initially, I planned to use |\row{...}| to create a row.
+% In order to perform actions at the end of the row I used
+% the aftergroup-trick, like for |\cell| command. Unfortunately,
+% the decorations were lost after the
+% group finished. I tried to save them to global temporary
+% macros at the end of each cell, but the saving list was big.
+% Finally, I decided that the construction |\brow...\erow|
+% is much easier to implement.
+
+% \begin{macro}{\brow}
+% Starts a row. Resets the rowspan markers, |\cals@current@row|
+% and decorations.
+% \begin{macrocode}
+\newcommand\brow{%
+\cals@updateRspanMarkers
+\setbox\cals@current@row=\hbox{}%
+\cals@decor@begin}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\erow}
+% Finishes a row. All the cells are re-layouted to the row height.
+% Decorations are finalized, and the row is dispatched.
+% \begin{macrocode}
+\newcommand\erow{%
+\cals@reheight@cells\cals@current@row
+\cals@last@row@height=\ht\cals@current@row\relax
+\cals@decor@end\cals@lastWidth
+\ht\cals@current@cs=\ht\cals@current@row
+\cals@row@dispatch
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@reheight@cells}
+% Re-heights all the boxes of a row.
+% Retains the widths of these boxes.
+% \begin{macrocode}
+\newcommand\cals@reheight@cells[1]{%
+\dimen0=\ht#1\relax
+\setbox2=\hbox{}%
+\def\next{%
+ \setbox4=\lastbox
+ \ifvoid4
+ \def\next{\global\setbox2=\box2}%
+ \else
+ \dimen4=\wd4
+ \setbox4=\vbox to \dimen0{\unvbox4}%
+ \ifdim \dimen4=\wd4 \relax \else \wd4=\dimen4 \fi
+ \setbox2=\hbox{\box4\unhbox2 }%
+ \fi
+ \next}%
+\setbox0=\hbox{\unhbox#1\next}%
+\setbox#1=\box2 }
+% \end{macrocode}
+% \end{macro}
diff --git a/Master/texmf-dist/source/latex/cals/colsep.dtx b/Master/texmf-dist/source/latex/cals/colsep.dtx
new file mode 100644
index 00000000000..d69222bee6e
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/colsep.dtx
@@ -0,0 +1,126 @@
+% \subsection{Column separation (colsep) and cell background}
+
+% In-row decorations are the vertical borders between the cells
+% and also the background color of the cells.
+
+% \begin{macro}{\cals@cs@outOne}
+% Typesets the background and the left border of a cell.
+% Decorations have zero depth and undefined height.
+% Parameters:
+% \begin{enumerate}
+% \item Width of the cell. The use of |\relax| avoids typesetting
+% the cell itself, which is used when creating the right frame
+% of a table.
+% \item Width of the border. 0pt is no border.
+% \item Color of the background. Empty macro is no color.
+% \end{enumerate}
+% If some arguments are undefined (through |\relax|), global
+% variables are used: |\cals@bgcolor| and |\cals@cs@width|.
+%
+% Corrupts |dimen0|.
+% \begin{macrocode}
+\newcommand\cals@cs@outOne[3]{%
+% \end{macrocode}
+% Create the full-width background
+% \begin{macrocode}
+\ifx \relax#1%
+\else
+ \cals@withColorII\cals@bgcolor{#3}\iftrue
+ \textcolor{\cals@color}{\vrule depth0pt width#1 }%
+ \hskip -#1\relax
+ \fi
+\fi
+% \end{macrocode}
+% The border. I feel that overprinting the background is good,
+% but I don't know why I think so.
+% \begin{macrocode}
+\cals@withWidthII\cals@cs@width{#2}\iftrue
+ \cals@halfWidthToDimen0 \cals@width %
+ \hskip -\dimen0 %
+ \vrule depth0pt width\cals@width\relax
+ \hskip -\dimen0 %
+\fi
+% \end{macrocode}
+% We will need the actual width of the left border in
+% a grand-grand-...-caller, when constructing a rowsep specification.
+% \begin{macrocode}
+\let\cals@lastLeftWidth=\cals@width
+% \end{macrocode}
+% Add width to skip to the next cell.
+% \begin{macrocode}
+\ifx \relax#1\else \hskip#1 \fi
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@current@cs}
+% The box to store column separation.
+% \begin{macrocode}
+\newbox\cals@current@cs
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@csrow@begin}
+% \begin{macro}{\cals@csrow@nextcell}
+% \begin{macro}{\cals@csrow@end}
+% Constructs an hbox with colsep decorations. Call to the begin-macro
+% re-initializes |\cals@current@cs| and makes that the left table frame border
+% is of the correct width. The end-macro creates the right border for
+% the right table frame. The most work is performed in the nextcell-macro.
+% Arguments:
+% \begin{enumerate}
+% \item Width of the cell
+% \item Width of the left border
+% \item Width of the right border, \emph{must be a macro name}
+% \item Background color of the cell
+% \end{enumerate}
+% For the special conditions (|\relax|, 0pt, empty name) see
+% the description of |\cals@cs@outOne|.
+% The right border is not typeset immediately. Instead, it is saved
+% to |\cals@lastWidth| (as |\relax| if no overrides)
+% and is handled by the next call to |nextcell|.
+% \begin{macrocode}
+\newcommand\cals@csrow@begin{%
+\setbox\cals@current@cs=\box\voidb@x %
+\let\cals@lastWidth=\relax}
+
+\newcommand\cals@csrow@nextcell[4]{%
+% \end{macrocode}
+% For the first cell, temporarily re-define the default border width
+% to the frame border. Macro |\next| will restore it back.
+% \begin{macrocode}
+\ifvoid\cals@current@cs
+ \toks0=\expandafter{\cals@cs@width}%
+ \def\next{\edef\cals@cs@width{\the\toks0}}%
+ \edef\cals@cs@width{\cals@framecs@width}%
+\else \let\next=\relax \fi
+% \end{macrocode}
+% Create the decorations, remember the right border.
+% Restore the value |lastLeftWidth| after the end of the hbox-group.
+% \begin{macrocode}
+\cals@maxWidth\cals@lastWidth{#2}%
+\setbox\cals@current@cs=\hbox{\unhbox\cals@current@cs
+ \cals@cs@outOne{#1}\cals@width{#4}%
+ \global\let\cals@tmp=\cals@lastLeftWidth}%
+\let\cals@lastLeftWidth=\cals@tmp
+\let\cals@lastWidth=#3%
+% \end{macrocode}
+% Restore the old value of the default border width.
+% \begin{macrocode}
+\next}
+
+% \end{macrocode}
+% User-specified width (initially by |borderR|, now located in
+% |lastWidth|) must override the frame width.
+% \begin{macrocode}
+\newcommand\cals@csrow@end{%
+\ifx \relax\cals@lastWidth
+ \let\cals@width=\cals@framecs@width
+\else
+ \let\cals@width=\cals@lastWidth
+\fi
+\cals@csrow@nextcell\relax\cals@width\relax\relax}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
diff --git a/Master/texmf-dist/source/latex/cals/decor.dtx b/Master/texmf-dist/source/latex/cals/decor.dtx
new file mode 100644
index 00000000000..4a40097c13e
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/decor.dtx
@@ -0,0 +1,227 @@
+% \section{Decorations}
+
+% How much decoration requires a table? Initially I thought to implement
+% a generic approach, so an user could extend the set of what is
+% possible---for example, a dashed border instead of a solid one.
+% But this is a hard task for me, therefore I switched back
+% to the fixed set of properties. Indeed, the use case for cals
+% tables is technical documentation, not a wanna-be designer showcases.
+%
+% The fixed set of decoration properties:
+% \begin{itemize}
+% \item padding
+% \item border thickness
+% \item cancelled after some thinking: border color
+% \item cell background
+% \end{itemize}
+%
+% In the first version of this package, decorations could be defined
+% for all cells in a row, for all cells in a column and finally
+% specially for a cell. Unfortunately, this approach does not work
+% for borders of multipage tables, when the decorations on a break are
+% different to the internal decorations. Trying different
+% workarounds, I finally found a descriptive and direct approach:
+% define default decorations for a cell plus define
+% decorations for the table frame.
+%
+% How to decorate the common border of two cells? The following
+% seems reasonable:
+% \begin{itemize}
+% \item The priority of settings: from the user, from the table
+% frame, default. If cells have different priorities, use the
+% highest one.
+% \item When priorities are the same, use the maximal thinkness.
+% \end{itemize}
+%
+% Imagine that the user uses only default decorations. Then all
+% the internal vertical borders are the same, and all internal
+% horizontal border are also the same. It took me time to
+% understand this obvious thing, that for the default setup
+% we need to define settings only for vertical and horizontal
+% borders, not for all four borders.
+%
+% Column separation and row separation are two very different
+% creatures. The former is fixed after a row is processed,
+% the latter could change somewhen later due to a table break.
+
+% \subsection{Setters and getters}
+
+% No more setter and getters provided to discourage cell formatting.
+% At the moment, if you really need it, use the knowledge of
+% the internal variables.
+
+% \begin{macro}{\cals@cs@width}
+% Width of column separators (vertical borders). For all the widths, |0pt| disables the rule.
+% \begin{macro}{\cals@framecs@width}
+% Width of the left and right table frame border.
+% \begin{macro}{\cals@rs@width}
+% Width of row separators (horizontal borders).
+% \begin{macro}{\cals@framers@width}
+% Width of the top and bottom table frame border.
+% \begin{macro}{\cals@bodyrs@width}
+% Width of row separators between the body and the header or the footer.
+% \begin{macro}{\cals@bgcolor}
+% Background color of the cells. If the macro is empty, it means no background.
+% \begin{macrocode}
+\newcommand\cals@cs@width{.4pt}
+\newcommand\cals@framecs@width{0pt}
+\newcommand\cals@rs@width{.4pt}
+\newcommand\cals@framers@width{0pt}
+\newcommand\cals@bodyrs@width{1.2pt}
+\newcommand\cals@bgcolor{}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+
+% \begin{macro}{\cals@borderL}
+% \begin{macro}{\cals@borderT}
+% \begin{macro}{\cals@borderR}
+% \begin{macro}{\cals@borderB}
+% Overrides for the widths of the cell borders (left, top, right or bottom).
+% Macros, set to |\relax| by the |calstable| environment.
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+
+% Padding parameters (|\cals@paddingL| etc) and related
+% macros (|\alignC| etc) are defined near the macro |\cell|.
+
+% \subsection{Decorations for a row}
+
+% The whole code in this section is devoted to provide functionality
+% for the functions |\cals@decor@begin|, |...@next|, |...@end|. After a row is ended,
+% we have the following decorations:
+% \begin{itemize}
+% \item column separation: box |\cals@current@cs|
+% \item rowsep specification for the top: macro |\cals@rs@above|
+% \item rowsep specification for the bottom: macro |\cals@rs@below|
+% \end{itemize}
+% The high-level approach is obvious: we construct the decorations
+% cell-by-cell. First, we calculate column separation, getting
+% the width of the left and the right border. Then we use these
+% values to update the border above and below. Unfortunately,
+% there is a lot of small details. For example, as explained later,
+% we construct the decorations with a delay, therefore the end-function
+% is just a special sort of the next-function.
+
+% \begin{macro}{\cals@decor@begin}
+% Initialization.
+% \begin{macrocode}
+\newcommand\cals@decor@begin{\cals@csrow@begin\cals@rs@spec@begin}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@decor@next}
+% Updates the decorations. The argument is the width of the cell.
+% \begin{macrocode}
+\newcommand\cals@decor@next[1]{%
+\cals@csrow@nextcell{#1}\cals@borderL\cals@borderR\cals@bgcolor
+\cals@rs@spec@next{#1}\cals@lastLeftWidth\cals@borderT\cals@borderB}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@decor@end}
+% Finishes the decorations. Uses |\cals@lastLeftWidth|,
+% which is the width of the last right border.
+% \begin{macrocode}
+\newcommand\cals@decor@end{%
+\cals@csrow@end
+\cals@rs@spec@end\cals@lastLeftWidth}
+% \end{macrocode}
+% \end{macro}
+
+% \subsection{Deciding on the width and color}
+
+% \begin{macro}{\cals@widthII}
+% \begin{macro}{\cals@withWidthII}
+% Calculate a final width from the default one (argument 1)
+% and user-specified (argument 2, |\relax| means use the default),
+% put it to the macro |\cals@width|. Also, the macro |withWidthII|
+% start a conditional construction,
+% true branch is executed when the width is not zero.
+% Unused \#3 is for if-fi balancing, see |\cals@iftrue|.
+% \begin{macrocode}
+\newcommand\cals@widthII[2]{%
+\ifx \relax#2\edef\cals@width{#1}%
+ \else \edef\cals@width{#2}\fi}
+
+\newcommand\cals@withWidthII[3]{%
+\cals@widthII{#1}{#2}%
+\ifdim \cals@width>0pt }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+
+% \begin{macro}{\cals@withColorII}
+% Calculate a final color from the default one (argument 1)
+% and user-specified (argument 2, |\relax| means use the default),
+% set the macro |\cals@color| to it. The both arguments must
+% be macro names, not token lists. Start a conditional
+% construction, true branch is executed when the color name is
+% given (not empty).
+% Unused \#3 is for if-fi balancing, see |\cals@iftrue|.
+% \begin{macrocode}
+\newcommand\cals@withColorII[3]{%
+\ifx \relax#2\edef\cals@color{#1}%
+ \else \edef\cals@color{#2}\fi
+% \end{macrocode}
+% Reversing a condition. Based on |\ifnot| macro by David Kastrup
+% posted to comp.text.tex 2 March 1998, Message-ID:
+% |<m2en0lebuc.fsf@mailhost.neuroinformatik.ruhr-uni-bochum.de>#1/1|.
+% \begin{macrocode}
+\ifx \cals@color\empty \else\expandafter\expandafter\fi\iffalse\iftrue\fi}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@halfWidthToDimen}
+% Puts the half of the width in |#2| to the dimension
+% register |#1|.
+% \begin{macrocode}
+\newcommand\cals@halfWidthToDimen[2]{%
+\dimen#1=#2\relax \divide\dimen#1 by 2 }
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@maxWidth}
+% Of two widths, given as macros, selects the maximal and put
+% the result to |\cals@width|. Takes care for |\relax|.
+% \begin{macrocode}
+\newcommand\cals@maxWidth[2]{%
+\ifx \relax#1\relax
+ \ifx \relax#2\let\cals@width=\relax
+ \else \edef\cals@width{#2}\fi
+\else
+ \ifx \relax#2\relax
+ \edef\cals@width{#1}%
+ \else
+ \ifdim #1>#2 \edef\cals@width{#1}%
+ \else \edef\cals@width{#2}\fi\fi\fi}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@iftrue}
+% \begin{macro}{\cals@iffalse}
+% Balancing if-fi. The following does not work:
+% \begin{verbatim}
+% \let\next=\iftrue ...
+% \if ... \next ... \fi ... \fi
+% \end{verbatim}
+% But this code does work:
+% \begin{verbatim}
+% \let\next=\cals@iftrue ...
+% \if ... \next\iftrue ... \fi ... \fi
+% \end{verbatim}
+% We use |\iftrue| (or any other if-start), which is taken into
+% account when scanning for the fi-else-if balance,
+% but ignored when executed.
+% \begin{macrocode}
+\def\cals@iftrue#1{\iftrue}
+\def\cals@iffalse#1{\iffalse}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
diff --git a/Master/texmf-dist/source/latex/cals/lltokens.dtx b/Master/texmf-dist/source/latex/cals/lltokens.dtx
new file mode 100644
index 00000000000..35a1a8e905e
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/lltokens.dtx
@@ -0,0 +1,170 @@
+% \subsection{List list of tokens}
+%
+% Two-dimensional arrays of tokens, or lists of lists of tokens.
+%
+%
+% Format of the list:
+%
+% \begin{verbatim}
+% {...tokens1...}{...tokens2...}...{...tokensN...}
+% \end{verbatim}
+%
+% Token manipulation should not belong to the ``cals'' package,
+% and the macros from this section have the prefix |llt@|
+% instead of |cals@|. Probably it is better to use some CTAN
+% package, but initially the llt-code was small and simple, so
+% I did not want dependencies, and now I do not want to replace
+% working code with something new.
+%
+% In comments to these functions, a parameter of type \textit{token list}
+% is a macro which will be expanded once to get the tokens, and
+% \textit{list list} is a macro which stores the two-dimensional array.
+%
+% An example of use:
+% \begin{verbatim}
+% \def\aaa{aaa}
+% \def\bbb{bbb}
+% \def\ccc{ccc}
+% \def\lst{} % empty list
+% \llt@cons\bbb\lst % \lst -> "{bbb}"
+% \llt@snoc\lst\ccc % \lst -> "{bbb}{ccc}"
+% \llt@cons\aaa\lst % \lst -> "{aaa}{bbb}{ccc}"
+% \llt@decons\lst % \llt@car -> "aaa", \lst -> "{bbb}{ccc}"
+% \llt@rot\lst % \llt@car -> "bbb", \lst -> "{ccc}{bbb}"
+% \end{verbatim}
+%
+%
+
+%
+% \begin{macro}{\llt@cons}
+% Prepends the token list \#1 to the list list \#2.
+% Corrupts the token registers 0 and~2.
+% \begin{macrocode}
+\def\llt@cons#1#2{%
+\toks0=\expandafter{#1}%
+\toks2=\expandafter{#2}%
+\edef#2{\noexpand{\the\toks0}\the\toks2 }%
+}
+% \end{macrocode}
+% \end{macro}
+
+%
+% \begin{macro}{\llt@snoc}
+% Appends the token list \#2 to the list list \#1 (note the order
+% of parameters).
+% Macro corrupts the token registers 0 and 2.
+%
+% \begin{macrocode}
+\def\llt@snoc#1#2{%
+\toks0=\expandafter{#1}%
+\toks2=\expandafter{#2}%
+\edef#1{\the\toks0 \noexpand{\the\toks2}}%
+}
+% \end{macrocode}
+% \end{macro}
+
+%
+% \begin{macro}{\llt@car}
+% A token list, set as a side-effect of the list deconstruction
+% and rotation functions.
+% \end{macro}
+
+%
+% \begin{macro}{\llt@decons}
+% List deconstruction. The first item is removed from the list list \#1
+% and its tokens are put to the token list |\llt@car|.
+% Corrupts the token register 0.
+% Undefined behaviour if the list list has no items.
+%
+% The actual work happens on the |\expandafter| line.
+% It's hard to explain, let me show the macro expansion,
+% I hope it's self-explaining.
+%
+% \begin{verbatim}
+% \expandafter\llt@decons@open\lst} -->
+% \llt@decons@open{aaa}{bbb}{ccc}{ddd}} -->
+% \def\llt@car{aaa} \toks0=\llt@opengroup {bbb}{ccc}{ddd}} -->
+% \def\llt@car{aaa} \toks0={{bbb}{ccc}{ddd}}
+% \end{verbatim}
+%
+% Why I use |\let\llt@opengroup={| inside the definition?
+% Only to balance the number of opening and closing brackets.
+% Otherwise TeX will not compile the definition.
+%
+% Initially I tried to use the following helper:
+%
+% \begin{verbatim}
+% \def\decons@helper#1#2\relax{%
+% \def\llt@car{#1}%
+% \def\list{#2}}
+% \end{verbatim}
+%
+% If a call is |\decons@helper{aaa}{bbb}{ccc}\relax| then
+% all is ok, the helper gets: \#1 is |aaa| and \#2 is
+% |{bbb}{ccc}|.
+%
+% Unfortunately, if the list has two items and the call is
+% |\decons@helper{aaa}{bbb}}\relax|, then the helper gets:
+% \#1 is |aaa| and \#2 is |bbb| instead of |{bbb}|.
+% The grouping tokens are lost, and we can't detect it.
+%
+% \begin{macrocode}
+\def\llt@decons@open#1{%
+\def\llt@car{#1}%
+\toks0=\llt@opengroup
+}
+
+\def\llt@decons#1{%
+\let\llt@opengroup={%
+\expandafter\llt@decons@open#1}%
+\edef#1{\the\toks0}%
+}
+% \end{macrocode}
+% \end{macro}
+
+%
+% \begin{macro}{\llt@rot}
+% Rotates the list list \#1. The first item becomes the last. Also,
+% its tokens are saved to token list |\llt@car|.
+% The second item becomes the first item, the third the second etc.
+% Corrupts the token registers 0 and 2.
+%
+% \begin{macrocode}
+\def\llt@rot#1{%
+\ifx#1\empty
+\let\llt@car=\relax
+\else
+\llt@decons#1%
+\llt@snoc#1\llt@car%
+\fi
+}
+% \end{macrocode}
+% \end{macro}
+
+%
+% \begin{macro}{\llt@desnoc}
+% Very unefficient list deconstruction. The last item is removed
+% from the list list \#1 % and its tokens are put to the token
+% list |\llt@car|. Corrupts the token registers 0 and 2.
+% Undefined behaviour if the list list has no items.
+%
+% |\llt@desnocII| is used to hide |\if| from the loop.
+% \begin{macrocode}
+\def\llt@desnocII#1{
+\ifx\empty#1%
+\let\llt@tmp=n%
+\else
+\llt@snoc{\llt@newlist}{\llt@car}%
+\let\llt@tmp=y%
+\fi
+}
+
+\def\llt@desnoc#1{%
+\def\llt@newlist{}%
+\loop
+\llt@decons{#1}%
+\llt@desnocII{#1}%
+\if y\llt@tmp \repeat
+\let#1=\llt@newlist}
+% \end{macrocode}
+% \end{macro}
diff --git a/Master/texmf-dist/source/latex/cals/rowsep.dtx b/Master/texmf-dist/source/latex/cals/rowsep.dtx
new file mode 100644
index 00000000000..c3c0174c2d2
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/rowsep.dtx
@@ -0,0 +1,360 @@
+% \subsection{Row separation (rowsep)}
+
+% \subsubsection{Data presentation}
+
+% A horizontal line between table rows can't appear in the output
+% immediately. Its formatting should be postponed until the next
+% row and its context are known. Two basic cases:
+% \begin{itemize}
+% \item The default cell formatting is to have a border around cells.
+% For some cell \textit{A} in the middle of a table, the user has
+% overridden formatting to no borders. To imlement the user's wish,
+% we should not create the bottom border for the cell \textit{B}
+% which is above the \textit{A}. But we don't know about the wish
+% for \textit{A} while processing \textit{B}. Therefore, the border
+% between two rows can be established only after processing the
+% both rows.
+% \item The default cell border is 1pt, but a border between
+% a body and a header or a footer row is 2pt. It means that the
+% border between two rows should be created only after we sure
+% that there is no table break.
+% \end{itemize}
+% Our approach is to define the desired formatting of a rowsep
+% as a set of parameters in a token list. Later we can join two
+% rowseps or a rowsep and context to a final rowsep.
+%
+% A rowsep token list consist of several items, each
+% item is a list of tokens or token groups:
+% \begin{enumerate}
+% \item length
+% \item left-border
+% \item right-border
+% \item user-specified thickness
+% \end{enumerate}
+% Values \textit{left-border} and \textit{right-border} are
+% required to get a nice rectangle border around a cell. Without length
+% correction, using the cell dimension, the border could look like:
+% \begin{verbatim}
+% xxxxxxxx
+% xxx cell xxx
+% xxxxxxxx
+% \end{verbatim}
+% With length correction, we get the correct result:
+% \begin{verbatim}
+% xxxxxxxxxxxx
+% xxx cell xxx
+% xxxxxxxxxxxx
+% \end{verbatim}
+%
+% Here is an example of a rowsep specification. It consist of three items.
+% The first item: length is 5cm, width 2pt, borders are 2mm.
+% The second item: length is 9cm, borders are 2mm, no rule at all.
+% The third item: length 2cm, default width, borders are 2pt.
+% The token list for this specification:
+% \begin{verbatim}
+% { {5cm} {2mm} {2mm} {2pt} }
+% { {9cm} {2mm} {2mm} {0pt} }
+% { {2cm} {2pt} {2pt} \relax }
+% \end{verbatim}
+%
+% Cell length and the left and right borders should be the correct lengths,
+% the rule thickness can be |\relax|, in this case the actual thickness
+% will be calculated during output.
+%
+% \begin{macro}{\cals@rs@pack}
+% Construct a rowsep fragment from the arguments 2-5 and
+% put it to the macro 1.
+% \begin{macrocode}
+\newcommand\cals@rs@pack[5]{%
+\edef#1{\noexpand{#2\noexpand}\noexpand{#3\noexpand}\noexpand{#4\noexpand}%
+ \ifx \relax#5\relax \else \noexpand{#5\noexpand}\fi }}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@unpack}
+% The reverse for |\cals@rs@pack|. The first argument is a rowsep
+% fragment (without enclosing curly braces), arguments 2-5 is macro
+% names where to put the results.
+% \begin{macrocode}
+\newcommand\cals@rs@unpack[5]{%
+\def\cals@tmp##1##2##3##4{\edef#2{##1}\edef#3{##2}\edef#4{##3}%
+ \ifx\relax##4\let#5=\relax \else \edef#5{##4}\fi}%
+\expandafter\cals@tmp#1}
+% \end{macrocode}
+% \end{macro}
+
+%
+% ^^A -----------------------------------------------------
+%
+% \subsubsection{From individual decorations to rowsep specification}
+
+% The rowsep specifications are created cell-by-cell and stored
+% in the macros |\cals@current@rs@above| and |\cals@current@rs@below|.
+% The construction happens with delay because we don't know
+% the exact value of the right border until the next cell is processed.
+
+% \begin{macro}{\cals@rs@spec@begin}
+% Initializes |\cals@current@rs@above|, |\cals@current@rs@below|
+% and set the flag of a new row.
+% \begin{macrocode}
+\newcommand\cals@rs@spec@begin{%
+\def\cals@current@rs@above{}%
+\def\cals@current@rs@below{}%
+\let\cals@rs@spec@ll=\relax}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@spec@next}
+% \begin{macro}{\cals@rs@spec@nextII}
+% Finalizes the decorations for the previous cell by using the left border
+% of the current as the right border for the previous. Then
+% remembers the decorations of the current cell ---
+% the left border width,
+% the widths of the top and bottom borders (|\relax| is ok) ---
+% in the macros |\cals@rs@spec@ll|, |...@bl|, |...@bt|, |...@bb|.
+% All the arguments much be macros.
+% \begin{macrocode}
+\newcommand\cals@rs@spec@next[4]{
+\cals@rs@spec@nextII#2
+\let\cals@rs@spec@ll=#1%
+\let\cals@rs@spec@bl=#2%
+\let\cals@rs@spec@bt=#3%
+\let\cals@rs@spec@bb=#4%
+}
+
+\newcommand\cals@rs@spec@nextII[1]{%
+\ifx \relax\cals@rs@spec@ll \else
+ \cals@rs@pack\cals@tmp\cals@rs@spec@ll\cals@rs@spec@bl#1\cals@rs@spec@bt
+ \llt@snoc\cals@current@rs@above\cals@tmp
+ \cals@rs@pack\cals@tmp\cals@rs@spec@ll\cals@rs@spec@bl#1\cals@rs@spec@bb
+ \llt@snoc\cals@current@rs@below\cals@tmp
+\fi
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@spec@end}
+% Finishes the rowsep specification by putting the last cell to it.
+% The only implicit argument (|\cals@lastLeftWidth|) is the width
+% of the right border of the last cell.
+% \begin{macrocode}
+\newcommand\cals@rs@spec@end[1]{}
+\let\cals@rs@spec@end=\cals@rs@spec@nextII
+% \end{macrocode}
+% \end{macro}
+
+%
+% ^^A -----------------------------------------------------
+%
+% \subsubsection{``Waiting'' rowsep}
+%
+% \begin{macro}{\cals@rs@sofar@length}
+% \begin{macro}{\cals@rs@sofar@borderl}
+% \begin{macro}{\cals@rs@sofar@borderr}
+% \begin{macro}{\cals@rs@sofar@width}
+% Typesetting a row separator is not an easy task, especially
+% because we support border-widths. Indeed, consider the worst
+% case: four cells and all the borders are different.
+% Our solution is an optimizer for a good case. We do not typeset
+% a fragment of the rule immediately. Instead, we remember the
+% parameters. If the next fragment is of the same width,
+% we increase the length of the ``waiting'' fragment.
+% Otherwise, we output the waiting fragment and the new fragment
+% becomes the new waiting fragment.
+% \begin{macrocode}
+\newcommand\cals@rs@sofar@length{}
+\newcommand\cals@rs@sofar@borderl{}
+\newcommand\cals@rs@sofar@borderr{}
+\newcommand\cals@rs@sofar@width{}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@sofar@reset}
+% Sets a flag that a new waiting rule should be started.
+% \begin{macrocode}
+\newcommand\cals@rs@sofar@reset{\let\cals@rs@sofar@width=\relax}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@sofar@end}
+% Prints the waiting rule, if exists.
+% \begin{macrocode}
+\newcommand\cals@rs@sofar@end{\ifx\relax\cals@rs@sofar@width
+ \else\cals@rs@sofar@out\fi}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@sofar@next}
+% Enlarges the current waiting rule, or typesets it and
+% starts new if the widths do not match. All the parameters
+% must be macro names. In order: length, left border, right
+% border, width.
+% \begin{macrocode}
+\newcommand\cals@rs@sofar@next[4]{%
+\ifx\relax\cals@rs@sofar@width
+% \end{macrocode}
+% Starts a new waiting rule.
+% \begin{macrocode}
+ \let\cals@rs@sofar@length=#1%
+ \let\cals@rs@sofar@borderl=#2%
+ \let\cals@rs@sofar@borderr=#3%
+ \let\cals@rs@sofar@width=#4%
+\else
+ \ifdim \cals@rs@sofar@width=#4\relax
+% \end{macrocode}
+% Enlarges the waiting rule.
+% \begin{macrocode}
+ \dimen0=\cals@rs@sofar@length\relax
+ \advance\dimen0 by #1\relax
+ \edef\cals@rs@sofar@length{\the\dimen0}%
+ \let\cals@rs@sofar@borderr=#3%
+ \else
+% \end{macrocode}
+% Typesets the current and start a new waiting rule.
+% \begin{macrocode}
+ \cals@rs@sofar@out
+ \let\cals@rs@sofar@length=#1%
+ \let\cals@rs@sofar@borderl=#2%
+ \let\cals@rs@sofar@borderr=#3%
+ \let\cals@rs@sofar@width=#4%
+ \fi
+\fi}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@sofar@over}
+% Repeats the last rowsep fragment, probably with another settings.
+% Arguments are like in |\cals@rs@sofar@next|.
+% \begin{macrocode}
+\newcommand\cals@rs@sofar@over[4]{%
+\ifdim 0pt=#4
+ \relax
+\else
+ \ifdim \cals@rs@sofar@width=#4\relax
+% \end{macrocode}
+% The width is not changed. We probably need to enlarge the right border
+% and probably the left border too. The latter is a bit harder because
+% we don't want to change it if the line continues from another cell
+% (so, change only if |length|+|borderl|\textgreater |sofar@length|+|sofar@borderl|).
+% \begin{macrocode}
+ \ifdim #3>\cals@rs@sofar@borderr\relax
+ \edef\cals@rs@sofar@borderr{#3}%
+ \fi
+ \dimen0=\cals@rs@sofar@length
+ \advance\dimen0 by \cals@rs@sofar@borderl\relax
+ \advance\dimen0 by -#2\relax
+ \ifdim #1>\dimen0 \relax
+ \edef\cals@rs@sofar@borderl{#2}%
+ \fi
+ \else
+% \end{macrocode}
+% Typesets the current and start a new waiting rule.
+% \begin{macrocode}
+ \cals@rs@sofar@out
+ \hskip-#1\relax
+ \let\cals@rs@sofar@length=#1%
+ \let\cals@rs@sofar@borderl=#2%
+ \let\cals@rs@sofar@borderr=#3%
+ \let\cals@rs@sofar@width=#4%
+ \fi
+\fi}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@sofar@out}
+% Typesets the waiting rule
+% \begin{macrocode}
+\newcommand\cals@rs@sofar@out{%
+\ifdim 0pt=\cals@rs@sofar@width\relax
+ \hskip\cals@rs@sofar@length\relax
+\else
+ \cals@halfWidthToDimen0\cals@rs@sofar@borderl
+ \hskip-\dimen0\relax
+ \cals@halfWidthToDimen2\cals@rs@sofar@borderr
+ \dimen4=\cals@rs@sofar@length\relax
+ \advance\dimen4 by \dimen0\relax \advance\dimen4 by \dimen2\relax
+ \cals@halfWidthToDimen6\cals@rs@sofar@width
+ \vrule height\dimen6 depth\dimen6 width\dimen4\relax
+ \hskip-\dimen2\relax
+\fi}
+% \end{macrocode}
+% \end{macro}
+
+% ^^A -----------------------------------------------------
+%
+% \subsubsection{From rowsep specification to typesetting}
+
+% \begin{macro}{\cals@rs@joinTwo}
+% Join and typeset two rowseps (arguments 2 and 3, must be macro names).
+% The number and the lengths of the fragments in the rowseps
+% should match.
+% The argument 1 (also a macro name) is the default width.
+% Corrupts the macros 2 and 3.
+% Call this macro inside |sofar@reset|...|@end| group.
+% \begin{macrocode}
+\newcommand\cals@rs@joinTwo[3]{%
+% \end{macrocode}
+% The loop function.
+% \begin{macrocode}
+\def\next##1{%
+\ifx \eol##1\let\next=\relax
+\else
+ \toks0=\expandafter{##1}%
+ \edef\cals@tmpII{\the\toks0}%
+ \llt@decons#3%
+% \end{macrocode}
+% Now |\cals@tmpII| contains a current fragment of the first rowsep,
+% and |\llt@car| of the second. Unpack the individual parameters.
+% \begin{macrocode}
+ \cals@rs@unpack\cals@tmpII\cals@tmpLI \cals@tmpBlI \cals@tmpBrI \cals@tmpWI
+ \cals@rs@unpack\llt@car \cals@tmpLII\cals@tmpBlII\cals@tmpBrII\cals@tmpWII
+% \end{macrocode}
+% The special case is when we should not typeset a rowsep fragment.
+% \begin{macrocode}
+ \let\cals@tmp=\cals@iftrue
+ \cals@maxWidth\cals@tmpWI\cals@tmpWII
+ \ifx \relax\cals@width\else \ifdim \cals@width=0pt %
+ \cals@rs@sofar@next\cals@tmpLI\cals@tmpBlI\cals@tmpBrI\cals@width
+ \let\cals@tmp=\cals@iffalse
+ \fi\fi
+% \end{macrocode}
+% Not the special case. Put the both definitions, and let the
+% underlying functions take care of calculations.
+% \begin{macrocode}
+ \cals@tmp\ifvoid
+ \cals@widthII#1\cals@tmpWI
+ \cals@rs@sofar@next\cals@tmpLI\cals@tmpBlI\cals@tmpBrI\cals@width
+ \cals@widthII#1\cals@tmpWII
+ \cals@rs@sofar@over\cals@tmpLII\cals@tmpBlII\cals@tmpBrII\cals@width
+ \fi
+\fi
+% \end{macrocode}
+% End of |\next| definition: continue the loop.
+% End of |\cals@rs@joinTwo| definition: start the loop.
+% \begin{macrocode}
+\next}%
+\expandafter\next#2\eol}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@rs@joinOne}
+% A simplified version of the previous macro. We have only one rowsep,
+% and want to join and typeset it with regard to some width,
+% given as the first macro parameter. Call this macro inside
+% |sofar@reset|...|@end| group.
+% \begin{macrocode}
+\newcommand\cals@rs@joinOne[2]{%
+\def\next##1{\ifx\eol##1\let\next=\relax\else
+ \toks0=\expandafter{##1}%
+ \edef\cals@tmpII{\the\toks0}%
+ \cals@rs@unpack\cals@tmpII\cals@tmpL\cals@tmpBl\cals@tmpBr\cals@tmpW
+ \cals@widthII#1\cals@tmpW
+ \cals@rs@sofar@next\cals@tmpL\cals@tmpBl\cals@tmpBr\cals@width
+\fi\next}%
+\expandafter\next#2\eol}
+% \end{macrocode}
+% \end{macro}
diff --git a/Master/texmf-dist/source/latex/cals/span.dtx b/Master/texmf-dist/source/latex/cals/span.dtx
new file mode 100644
index 00000000000..c84a7bfa1ba
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/span.dtx
@@ -0,0 +1,176 @@
+% \subsection{Spanned cells}
+
+% The technical approach:
+% \begin{itemize}
+% \item Spanning is started in the left top corner using the
+% command |\nullcell{lt...}|
+% \item The spanned cell is split on the table cells using the
+% command |\nullcell|. These nullcells are responsible for
+% correct decorations and for calculating the big cell dimensions.
+% \item The content of the spanned cells comes in the end,
+% in the right bottom corner.
+% \end{itemize}
+
+% It is possible to have several active spans at once, therefore we
+% have to remember them. I use a queue. Each time a left column
+% of a span is started, we take span data from the queue. After the
+% right column of the span, we put the data back to the queue,
+% to the end. Probably it is not obvious at the first look (at least,
+% I needed time to find this simple idea) that this rotating queue
+% is always right: when spanning (its left column) starts again,
+% the beginning of the queue always contains data for exactly this spanning.
+
+% \begin{macro}{\cals@spanq@heights}
+% The queue for height tracking. In the first version I also had
+% a queue for decorations, but later cancelled it.
+% I use |\def| instead of |\newcommand| in order that |\show|
+% prints "|macro|" instead of "|\long macro|". The latter breaks
+% unit tests.
+% \begin{macrocode}
+\def\cals@spanq@heights{}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@span@get}
+% Gets |\cals@span@height| from the queue.
+% \begin{macrocode}
+\newcommand\cals@span@get{%
+\llt@decons\cals@spanq@heights \cals@span@height=\llt@car\relax}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@span@put}
+% Puts |\cals@span@height| to the queue.
+% \begin{macrocode}
+\newcommand\cals@span@put{%
+\edef\cals@tmp{\the\cals@span@height}\llt@snoc\cals@spanq@heights\cals@tmp}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\nullcell}
+% The big spanned cell is split on the table cells, which are
+% identified by |\nullcell|s. The task is to produce correct
+% decorations and to track the parameters of the spanned cell.
+% \begin{itemize}
+% \item Decorations: if defined, the background color is always
+% added to the column separation row.
+% \item Decorations: the borders are set to 0pt (disabled),
+% except for the borders which are requested by
+% the parameter of |\nullcell|: |l| for the left border,
+% |t| for the top, |r| for the right, |b| for the bottom.
+% \item More precisely, the letters in the argument are not to
+% specify which decorations to use, but to specify the location
+% of the small cell in the big cell. The use for decorations
+% is just an useful side-effect.
+% \item Action |l|: take the span data from the queue.
+% \item Action |r|: update the height of the current span,
+% put the data to the queue.
+% \item Action |b|: do not put an empty box to the current row.
+% Instead, accumulate the width of the current span.
+% (Preparation for |\spancontent|.)
+% \end{itemize}
+% \begin{macrocode}
+\newcommand\nullcell[1]{%
+% \end{macrocode}
+% First of all, parse the argument and set the if-commands |\cals@span@ifX|.
+% Then get the width of the cell.
+% \begin{macrocode}
+\let\cals@span@ifL=\cals@iffalse
+\let\cals@span@ifT=\cals@iffalse
+\let\cals@span@ifR=\cals@iffalse
+\let\cals@span@ifB=\cals@iffalse
+\def\next##1{\ifx\relax##1\let\next=\relax \else
+ \expandafter\let\csname cals@span@if##1\endcsname=\cals@iftrue \fi
+ \next}%
+\uppercase{\next #1}\relax
+\llt@rot\cals@colwidths \let\cals@nullcell@width=\llt@car
+% \end{macrocode}
+% Action "l": update the height, supress the borders, set the rowspan markers.
+% \begin{macrocode}
+\cals@span@ifL\iftrue
+ \cals@span@ifT\iftrue
+ \cals@span@height=0pt %
+ \else
+ \cals@span@get
+ \advance\cals@span@height by \cals@last@row@height\relax
+ \fi
+ \cals@span@ifB\iftrue \else
+ \let\cals@ifInRspan=\cals@iftrue
+ \let\cals@ifLastRspanRow=\cals@iffalse
+ \fi
+ \let\cals@span@borderL=\cals@borderL \let\cals@span@borderT=\cals@borderT
+ \let\cals@span@borderR=\cals@borderR \let\cals@span@borderB=\cals@borderB
+\fi
+% \end{macrocode}
+% Action "r": put the data to the queue, unless in the end of the spanning.
+% \begin{macrocode}
+\cals@span@ifR\iftrue
+ \cals@span@ifB\iftrue \relax \else \cals@span@put \fi
+\fi
+% \end{macrocode}
+% Update the current row or calculate the span width
+% (in the case of the bottom row).
+% \begin{macrocode}
+\cals@span@ifB\iftrue
+ \cals@span@ifL\iftrue
+ \cals@span@width=\cals@nullcell@width\relax
+ \else
+ \advance\cals@span@width by \cals@nullcell@width\relax
+ \fi
+\else
+ \setbox\cals@current@row=\hbox{%
+ \unhbox\cals@current@row
+ \vbox{\hbox to\cals@nullcell@width{}\vfil}}%
+\fi
+% \end{macrocode}
+% Update decorations
+% \begin{macrocode}
+\cals@span@ifL\iftrue \let\cals@borderL=\cals@span@borderL
+ \else \def\cals@borderL{0pt}\fi
+\cals@span@ifT\iftrue \let\cals@borderT=\cals@span@borderT
+ \else \def\cals@borderT{0pt}\fi
+\cals@span@ifR\iftrue \let\cals@borderR=\cals@span@borderR
+ \else \def\cals@borderR{0pt}\fi
+\cals@span@ifB\iftrue \let\cals@borderB=\cals@span@borderB
+ \else \def\cals@borderB{0pt}\fi
+\cals@decor@next\cals@nullcell@width
+\let\cals@borderL=\cals@span@borderL \let\cals@borderR=\cals@span@borderR
+\let\cals@borderT=\cals@span@borderT \let\cals@borderB=\cals@span@borderB
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@span@width}
+% \begin{macro}{\cals@span@height}
+% The width of the span cell. The height of the spanned cell (without
+% the last row).
+% \begin{macrocode}
+\newdimen\cals@span@width
+\newdimen\cals@span@height
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+
+% \begin{macro}{\cals@ifInRspan}
+% Set to |\cals@iftrue| if the current row is a part of a row span.
+% Otherwise |\cals@iffalse|.
+% \end{macro}
+
+% \begin{macro}{\cals@ifLastRspanRow}
+% Set to |\cals@iftrue| if the current row is the last row of
+% of a row span. Otherwise |\cals@iffalse|.
+% \end{macro}
+
+% \begin{macro}{\cals@updateRspanMarkers}
+% Resets the span markers, which are later updated by |\nullcell|
+% to the correct state for the current row.
+% \begin{macrocode}
+\newcommand\cals@updateRspanMarkers{%
+\ifx \empty\cals@spanq@heights
+ \let\cals@ifInRspan=\cals@iffalse
+\else
+ \let\cals@ifInRspan=\cals@iftrue
+\fi
+\let\cals@ifLastRspanRow=\cals@iftrue}
+% \end{macrocode}
+% \end{macro}
diff --git a/Master/texmf-dist/source/latex/cals/table.dtx b/Master/texmf-dist/source/latex/cals/table.dtx
new file mode 100644
index 00000000000..0e55a9378f1
--- /dev/null
+++ b/Master/texmf-dist/source/latex/cals/table.dtx
@@ -0,0 +1,387 @@
+% \subsection{Row dispatcher}
+
+% \begin{macro}{\cals@row@dispatch}
+% Depending if the current row has a rowspan cell or not,
+% the execution is different.
+% \begin{macrocode}
+\newcommand\cals@row@dispatch{%
+\ifx b\cals@current@context
+ \cals@ifInRspan\iftrue
+ \cals@row@dispatch@span
+ \else
+ \cals@row@dispatch@nospan
+ \fi
+\else
+ \cals@row@dispatch@nospan
+\fi}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@row@dispatch@nospan}
+% After a row is typeset in a box, this macro decides what to do next.
+% Usually, it should just add decorations and output the row.
+% But if a table break is required, it should put the current row
+% to backup, typeset the footer, the break, the header and only then
+% the row from the backup. Summary of main parameters:
+% \begin{itemize}
+% \item rowsep from the last row (|\cals@last@rs|) and the
+% last context (|\cals@last@context|)
+% \item current row (|\cals@current@row|), its decorations
+% (|\cals@current@cs|, |\cals@current@rs@above|,
+% |\cals@current@rs@below|) and context (|\cals@current@context|)
+% \end{itemize}
+% \begin{macrocode}
+\newcommand\cals@row@dispatch@nospan{%
+% \end{macrocode}
+% The header and footer rows are always typeset without further
+% considerations.
+% \begin{macrocode}
+\let\cals@last@context@bak=\cals@last@context
+\ifx h\cals@current@context \else
+\ifx f\cals@current@context \else
+% \end{macrocode}
+% In the body, if a break is required: do it.
+% \begin{macrocode}
+\cals@ifbreak\iftrue
+ \setbox\cals@backup@row=\box\cals@current@row
+ \setbox\cals@backup@cs=\box\cals@current@cs
+ \let\cals@backup@rs@above=\cals@current@rs@above
+ \let\cals@backup@rs@below=\cals@current@rs@below
+ \let\cals@backup@context=\cals@current@context
+ \cals@tfoot@tokens
+ \lastrule
+ \cals@issue@break
+ \cals@thead@tokens
+ \setbox\cals@current@row=\box\cals@backup@row
+ \setbox\cals@current@cs=\box\cals@backup@cs
+ \let\cals@current@rs@above=\cals@backup@rs@above
+ \let\cals@current@rs@below=\cals@backup@rs@below
+ \let\cals@current@context=\cals@backup@context
+\fi\fi\fi
+% \end{macrocode}
+% Typeset the row.
+% \begin{macrocode}
+\cals@issue@row
+% \end{macrocode}
+% Consider a table such that thead+row1 do not fit to a page
+% (see the unit test |regression/test_010_wrongbreak|).
+% Without the next code, the following happens:
+% thead and row1 are typeset, but the output procedure is not
+% executed yet. Therefore, when row2 is ready, we detect that
+% a table break is required and create it. Then the output procedure
+% moves thead+row1 on the next page. The result:
+% thead and row1 on one page, row2 and the rest on the next page
+% instead of the whole table on one page.
+% Solution: force a run of the output procedure after
+% the first row of a table chunk.
+% \begin{macrocode}
+\ifx b\cals@last@context
+ \ifx h\cals@last@context@bak \vskip0pt \penalty10000 \fi
+ \ifx n\cals@last@context@bak \vskip0pt \penalty10000 \fi
+\fi
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@row@dispatch@span}
+% The only specific thing to rowspanned rows is that we should not
+% allow breaks between the rows in one group. We put these rows
+% to one box, and process this big box as a big row.
+% \begin{macrocode}
+\newcommand\cals@row@dispatch@span{%
+% \end{macrocode}
+% Output the row to the backup box. If the row is the first
+% row in the span, let its decorations will be the decorations
+% for the future big row. Also, reset the values of leftskip
+% and rightskip to avoid adding them twice, once in a individual
+% row, and once to the common span box.
+% \begin{macrocode}
+\ifvoid\cals@backup@row
+ \setbox\cals@backup@row=\vbox{\box\cals@current@row}%
+ \setbox\cals@backup@cs=\box\cals@current@cs
+ \let\cals@backup@rs@above=\cals@current@rs@above
+ \let\cals@backup@context=\cals@last@context
+ \cals@backup@leftskip=\leftskip
+ \cals@backup@rightskip=\rightskip
+ \leftskip=0pt \rightskip=0pt \relax
+\else
+ \setbox\cals@backup@row=\vbox{\unvbox\cals@backup@row
+ \cals@issue@row}%
+\fi
+\let\cals@last@rs@below=\cals@current@rs@below
+\let\cals@last@context=\cals@current@context
+% \end{macrocode}
+% If this is the last row of the span, create the fake big row
+% and use the normal dispatcher.
+%
+% \begin{macrocode}
+\cals@ifLastRspanRow\iftrue
+ \setbox\cals@current@row=\box\cals@backup@row
+ \setbox\cals@current@cs=\box\cals@backup@cs
+ \let\cals@current@rs@above=\cals@backup@rs@above
+ \let\cals@last@context=\cals@backup@context
+ \leftskip=\cals@backup@leftskip
+ \rightskip=\cals@backup@rightskip
+ \cals@row@dispatch@nospan
+\fi
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@backup@row}
+% \begin{macro}{\cals@backup@cs}
+% Boxes and skips for backup.
+% \begin{macrocode}
+\newbox\cals@backup@row
+\newbox\cals@backup@cs
+\newskip\cals@backup@leftskip
+\newskip\cals@backup@rightskip
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+
+% To decide on table breaks and row separation decorations,
+% we need to trace context.
+
+% \begin{macro}{\cals@current@context}
+% The context of the current row. Possible values,
+% set as a "|\let|" to a character:
+% \begin{itemize}
+% \item n: no context, should not happen when the value is required
+% \item h: table header
+% \item f: table footer
+% \item b: table body
+% \end{itemize}
+% \end{macro}
+
+% \begin{macro}{\cals@last@context}
+% The context of the previous row. Possible values, set as a
+% "|\let|" to a character:
+% \begin{itemize}
+% \item n: there is no previous row (not only the start of a table,
+% but also the start of a table chunk)
+% \item h, f, b: table header, footer, body
+% \item r: a last rule of the table (or its chunk) is just output.
+% This status is used to allow multiple calls to |\lastrule|.
+% Probably the use of |current| instead of |last| is more logical,
+% but using |last| is more safe. Who knows if an user decides to use
+% |\lastrule| somewhere in a middle of a table.
+% \end{itemize}
+% \end{macro}
+
+% \begin{macro}{\cals@ifbreak}
+% Table breaks can be manual or automatic. The first is easy,
+% the second is near to impossible if we take into account
+% table headers and footer. The following heuristic seems good.
+%
+% Check if the current row plus the footer fits to the
+% rest of the page. If not, a break is required. This approach
+% is based on two assumptions:
+% \begin{itemize}
+% \item the height of the footer is always the same, and
+% \item any body row is larger than the footer.
+% \end{itemize}
+%
+% More precise and technical description: |\cals@ifbreak| decides
+% if an automatic table break is required and leaves the
+% macro |\cals@iftrue| (yes) or |\cals@iffalse| (no) in the input stream.
+% If the user sets |\cals@tbreak@tokens| (using |\tbreak|),
+% break is forced. Otherwise, no break is allowed:
+% \begin{itemize}
+% \item In the header
+% \item In the footer
+% \item Immediately after the header
+% \item At the beginning of a chunk of a table.
+% \end{itemize}
+% Otherwise break is recommended when
+% the sum of the height of the current row and of the footer part
+% is greater as the rest height of the page.
+% The implicit first parameter is used for if-fi balancing,
+% see |\cals@iftrue|.
+% \begin{macrocode}
+\newcommand\cals@ifbreak[1]{}
+\def\cals@ifbreak{%
+\let\cals@tmp=\cals@iffalse
+\let\cals@tmpII=\cals@iftrue
+\ifx\relax\cals@tbreak@tokens
+ \ifx h\cals@current@context \else
+ \ifx f\cals@current@context \else
+ \ifx h\cals@last@context \else
+ \ifx n\cals@last@context \else
+ \dimen0=\pagetotal\relax
+ \advance\dimen0 by \ht\cals@current@row\relax
+ %\showthe\ht\cals@current@row\relax
+ \ifx \cals@tfoot@tokens\relax \else
+ %\show\cals@tfoot@height\relax
+ \advance\dimen0 by \cals@tfoot@height\relax
+ \fi
+ %\showthe\dimen0\relax
+ \ifdim \dimen0>\pagegoal\relax
+ \let\cals@tmp=\cals@tmpII
+ \fi
+ \fi\fi\fi\fi
+\else \let\cals@tmp=\cals@tmpII % tbreak@tokens
+\fi
+\cals@tmp}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@issue@break}
+% By default, force a page break, otherwise use user's tokens
+% set by |\tbreak|.
+% \begin{macrocode}
+\newcommand\cals@issue@break{\ifx \relax\cals@tbreak@tokens \penalty-10000 %
+\else \cals@tbreak@tokens \fi
+\let\cals@tbreak@tokens=\relax
+\let\cals@last@context=n}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@issue@rowsep@alone}
+% Typesets the top (or bottom) frame of a table:
+% combines |\cals@current@rs@above| and |\cals@framers@width|
+% and outputs the row separator.
+% \begin{macrocode}
+\newcommand\cals@issue@rowsep@alone{%
+\setbox0=\hbox{%
+ \hskip\leftskip
+ \cals@rs@sofar@reset
+ \cals@rs@joinOne\cals@framers@width\cals@current@rs@above
+ \cals@rs@sofar@end
+ \hskip\rightskip}%
+\ht0=0pt \dp0=0pt \box0 }
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@issue@rowsep}
+% Combine row separations |\cals@last@rs@below| and |\cals@current@rs@above|,
+% taking into considiration the width of the rule:
+% \begin{itemize}
+% \item n to h, f, b (the top frame): use |\cals@framers@width|
+% and ignore |last@rs@below| because we don't have it
+% \item h to h, b to b, f to f (the usual separator): use |\cals@rs@width|
+% \item for all other combinations (header to body, body to footer),
+% including impossible: use |\cals@bodyrs@width|
+% \end{itemize}
+% \begin{macrocode}
+\newcommand\cals@issue@rowsep{%
+\ifx n\cals@last@context \cals@issue@rowsep@alone \else
+ \ifx \cals@last@context\cals@current@context
+ \let\cals@tmpIII=\cals@rs@width \else
+ \let\cals@tmpIII=\cals@bodyrs@width \fi
+ \setbox0=\hbox{%
+ \hskip\leftskip
+ \cals@rs@sofar@reset
+ \cals@rs@joinTwo\cals@tmpIII\cals@last@rs@below\cals@current@rs@above
+ \cals@rs@sofar@end
+ \hskip\rightskip}%
+ \ht0=0pt \dp0=0pt \box0 %
+\fi}
+% \end{macrocode}
+% \end{macro}
+
+
+% \begin{macro}{\cals@last@row@height}
+% For spanning support, we need to remember the height of the last row
+% \begin{macrocode}
+\newdimen\cals@last@row@height
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@issue@row}
+% Typesets the current row and its decorations, then updates
+% the last context. Regards |\leftskip| and |\rightskip|
+% by putting them inside the row.
+% \begin{macrocode}
+\newcommand\cals@issue@row{%
+% \end{macrocode}
+% Decorations: first the column separation, then the row separation.
+% \begin{macrocode}
+\nointerlineskip
+\setbox0=\vtop{\hbox{\hskip\leftskip \box\cals@current@cs \hskip\rightskip}}%
+ \ht0=0pt \box0
+\nointerlineskip
+\cals@issue@rowsep
+\nointerlineskip
+% \end{macrocode}
+% Output the row, update the last context.
+% \begin{macrocode}
+\hbox{\hskip\leftskip \box\cals@current@row \hskip\rightskip}%
+\let\cals@last@rs@below=\cals@current@rs@below
+\let\cals@last@context=\cals@current@context}
+% \end{macrocode}
+% \end{macro}
+
+% \subsection{Table elements}
+
+% \begin{environment}{\calstable}
+% Setup the parameters and let the row dispatcher to do all the work.
+% \begin{macrocode}
+\newenvironment{calstable}{%
+\let\cals@thead@tokens=\relax
+\let\cals@tfoot@tokens=\relax
+\let\cals@tbreak@tokens=\relax
+\cals@tfoot@height=0pt \relax
+\let\cals@last@context=n%
+\let\cals@current@context=b%
+\parindent=0pt %
+\cals@setpadding{Ag}\cals@setcellprevdepth{Al}%
+\let\cals@borderL=\relax
+\let\cals@borderR=\relax
+\let\cals@borderT=\relax
+\let\cals@borderB=\relax
+}{% End of the table
+\cals@tfoot@tokens\lastrule}
+% \end{macrocode}
+% \end{environment}
+
+% \begin{macro}{\lastrule}
+% Typesets the last rule (bottom frame) of a table chunk.
+% Repeatable calls are ignored.
+% Useful in the macro |\tfoot|.
+% \begin{macrocode}
+\newcommand\lastrule{%
+\ifx r\cals@last@context \relax \else
+ \let\cals@last@context=r%
+ \nointerlineskip
+ \let\cals@current@rs@above=\cals@last@rs@below\cals@issue@rowsep@alone%
+\fi}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\thead}
+% Table: the header. Remember for later use, typeset right now.
+% \begin{macrocode}
+\newcommand\thead[1]{%
+\def\cals@thead@tokens{\let\cals@current@context=h%
+#1\let\cals@current@context=b}%
+\cals@thead@tokens}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\tfoot}
+% Table: the footer. Remember for later use. Right now, typeset
+% to a box to calculate an expected height for the table breaker
+% |\cals@ifbreak|.
+% \begin{macrocode}
+\newcommand\tfoot[1]{%
+\def\cals@tfoot@tokens{\let\cals@current@context=f#1}%
+\setbox0=\vbox{\cals@tfoot@tokens}%
+\cals@tfoot@height=\ht0 \relax}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\cals@tfoot@height}
+% The height of the footer.
+% \begin{macrocode}
+\newdimen\cals@tfoot@height
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\tbreak}
+% Table: force a table break. Argument should contain something
+% like |\penalty-10000 |.
+% \begin{macrocode}
+\newcommand\tbreak[1]{\def\cals@tbreak@tokens{#1}}
+% \end{macrocode}
+% \end{macro}
diff --git a/Master/texmf-dist/tex/latex/cals/cals.sty b/Master/texmf-dist/tex/latex/cals/cals.sty
new file mode 100644
index 00000000000..c187fc25d18
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/cals/cals.sty
@@ -0,0 +1,703 @@
+%%
+%% This is file `cals.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% cals.dtx (with options: `package')
+%% cell.dtx (with options: `package')
+%% span.dtx (with options: `package')
+%% table.dtx (with options: `package')
+%% lltokens.dtx (with options: `package')
+%% decor.dtx (with options: `package')
+%% colsep.dtx (with options: `package')
+%% rowsep.dtx (with options: `package')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2004 by Oleg Parashchenko <olpa@uucode.com>
+%%
+%% This file may be distributed and/or modified under the conditions of
+%% the LaTeX Project Public License, either version 1.2 of this license
+%% or (at your option) any later version. The latest version of this
+%% license is in:
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% and version 1.2 or later is part of all distributions of LaTeX version
+%% 1999/12/01 or later.
+%%
+\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+\ProvidesPackage{cals}
+ [2010/10/07 CALS tables v.2.0]
+
+
+\newcommand\cals@cell[3]{}
+\def\cals@cell#1#2{%
+\vbox\bgroup%
+\hsize=#1
+\linewidth=#1
+\leftskip=\cals@paddingL %
+\rightskip=\cals@paddingR %
+\ifdim #2>0pt %
+ \vskip-#2
+\fi
+\vskip\cals@paddingT %
+\vskip-\parskip %
+\prevdepth=\cals@paddingD %
+\bgroup\aftergroup\cals@cell@end
+\cals@AtBeginCell\let\next=% eat '{' of the content
+}%{Implicit content}
+
+\def\cals@cell@end{\vfil\vskip\cals@paddingB
+\cals@AtEndCell\egroup % finish vbox
+\cals@celll@end}
+
+\newcommand\cell[1]{}
+\def\cell{%
+\llt@rot\cals@colwidths
+\let\cals@cell@width=\llt@car
+\setbox0=\cals@cell\cals@cell@width{0pt}%
+}
+
+\let\cals@AtBeginCell=\relax
+\let\cals@AtEndCell=\relax
+
+\newcommand\cals@width@cell@put@row{%
+\ifdim \cals@cell@width=\wd0 \relax \else \wd0=\cals@cell@width \fi
+\setbox\cals@current@row=\hbox{\unhbox\cals@current@row\box0 }}%
+
+\newcommand\cals@celll@end{%
+\cals@width@cell@put@row
+\cals@decor@next\cals@cell@width}
+
+\newcommand\spancontent[1]{}
+\def\spancontent{%
+\let\cals@tmp=\cals@celll@end
+\let\cals@cell@width=\cals@span@width
+\def\cals@celll@end{%
+ \cals@width@cell@put@row%
+ \let\cals@celll@end=\cals@tmp}%
+\setbox0=\cals@cell{\cals@span@width}{\cals@span@height}%
+}%{Implicit content}
+
+
+\newskip\cals@paddingL
+\newskip\cals@paddingR
+\newskip\cals@paddingT
+\newskip\cals@paddingB
+
+\newcommand{\cals@setpadding}[1]{%
+\setbox0=\hbox{#1}%
+\dimen0=\ht0 \advance\dimen0 by \dp0 \divide\dimen0 by 2
+\cals@paddingL=\dimen0 \relax
+\cals@paddingR=\cals@paddingL
+\cals@paddingT=\cals@paddingL
+\cals@paddingB=\cals@paddingL
+}
+
+\newdimen\cals@paddingD
+
+\newcommand{\cals@setcellprevdepth}[1]{%
+\setbox0=\vbox{\prevdepth=0pt #1}%
+\setbox1=\vbox{#1}%
+\dimen0=\ht0 \advance\dimen0 by \dp0 %
+\advance\dimen0 by -\ht1 \advance\dimen0 by -\dp1%
+\cals@paddingD=\dimen0 }
+
+\newcommand\alignL{%
+\dimen0=\cals@paddingL \cals@paddingL=\dimen0 \relax
+\dimen0=\cals@paddingR \cals@paddingR=\dimen0 \relax}
+
+\newcommand\alignC{%
+\dimen0=\cals@paddingL \cals@paddingL=\dimen0 plus 1fill\relax
+\dimen0=\cals@paddingR \cals@paddingR=\dimen0 plus 1fill\relax}
+
+\newcommand\alignR{%
+\dimen0=\cals@paddingL \cals@paddingL=\dimen0 plus 1fill\relax
+\dimen0=\cals@paddingR \cals@paddingR=\dimen0 \relax}
+
+
+\newbox\cals@current@row
+
+\newcommand\colwidths[1]{}
+\def\colwidths#{\edef\cals@colwidths}
+\def\cals@colwidths{{100pt}}
+
+
+\newcommand\brow{%
+\cals@updateRspanMarkers
+\setbox\cals@current@row=\hbox{}%
+\cals@decor@begin}
+
+\newcommand\erow{%
+\cals@reheight@cells\cals@current@row
+\cals@last@row@height=\ht\cals@current@row\relax
+\cals@decor@end\cals@lastWidth
+\ht\cals@current@cs=\ht\cals@current@row
+\cals@row@dispatch
+}
+
+\newcommand\cals@reheight@cells[1]{%
+\dimen0=\ht#1\relax
+\setbox2=\hbox{}%
+\def\next{%
+ \setbox4=\lastbox
+ \ifvoid4
+ \def\next{\global\setbox2=\box2}%
+ \else
+ \dimen4=\wd4
+ \setbox4=\vbox to \dimen0{\unvbox4}%
+ \ifdim \dimen4=\wd4 \relax \else \wd4=\dimen4 \fi
+ \setbox2=\hbox{\box4\unhbox2 }%
+ \fi
+ \next}%
+\setbox0=\hbox{\unhbox#1\next}%
+\setbox#1=\box2 }
+
+
+
+\def\cals@spanq@heights{}
+
+\newcommand\cals@span@get{%
+\llt@decons\cals@spanq@heights \cals@span@height=\llt@car\relax}
+
+\newcommand\cals@span@put{%
+\edef\cals@tmp{\the\cals@span@height}\llt@snoc\cals@spanq@heights\cals@tmp}
+
+\newcommand\nullcell[1]{%
+\let\cals@span@ifL=\cals@iffalse
+\let\cals@span@ifT=\cals@iffalse
+\let\cals@span@ifR=\cals@iffalse
+\let\cals@span@ifB=\cals@iffalse
+\def\next##1{\ifx\relax##1\let\next=\relax \else
+ \expandafter\let\csname cals@span@if##1\endcsname=\cals@iftrue \fi
+ \next}%
+\uppercase{\next #1}\relax
+\llt@rot\cals@colwidths \let\cals@nullcell@width=\llt@car
+\cals@span@ifL\iftrue
+ \cals@span@ifT\iftrue
+ \cals@span@height=0pt %
+ \else
+ \cals@span@get
+ \advance\cals@span@height by \cals@last@row@height\relax
+ \fi
+ \cals@span@ifB\iftrue \else
+ \let\cals@ifInRspan=\cals@iftrue
+ \let\cals@ifLastRspanRow=\cals@iffalse
+ \fi
+ \let\cals@span@borderL=\cals@borderL \let\cals@span@borderT=\cals@borderT
+ \let\cals@span@borderR=\cals@borderR \let\cals@span@borderB=\cals@borderB
+\fi
+\cals@span@ifR\iftrue
+ \cals@span@ifB\iftrue \relax \else \cals@span@put \fi
+\fi
+\cals@span@ifB\iftrue
+ \cals@span@ifL\iftrue
+ \cals@span@width=\cals@nullcell@width\relax
+ \else
+ \advance\cals@span@width by \cals@nullcell@width\relax
+ \fi
+\else
+ \setbox\cals@current@row=\hbox{%
+ \unhbox\cals@current@row
+ \vbox{\hbox to\cals@nullcell@width{}\vfil}}%
+\fi
+\cals@span@ifL\iftrue \let\cals@borderL=\cals@span@borderL
+ \else \def\cals@borderL{0pt}\fi
+\cals@span@ifT\iftrue \let\cals@borderT=\cals@span@borderT
+ \else \def\cals@borderT{0pt}\fi
+\cals@span@ifR\iftrue \let\cals@borderR=\cals@span@borderR
+ \else \def\cals@borderR{0pt}\fi
+\cals@span@ifB\iftrue \let\cals@borderB=\cals@span@borderB
+ \else \def\cals@borderB{0pt}\fi
+\cals@decor@next\cals@nullcell@width
+\let\cals@borderL=\cals@span@borderL \let\cals@borderR=\cals@span@borderR
+\let\cals@borderT=\cals@span@borderT \let\cals@borderB=\cals@span@borderB
+}
+
+\newdimen\cals@span@width
+\newdimen\cals@span@height
+
+
+
+\newcommand\cals@updateRspanMarkers{%
+\ifx \empty\cals@spanq@heights
+ \let\cals@ifInRspan=\cals@iffalse
+\else
+ \let\cals@ifInRspan=\cals@iftrue
+\fi
+\let\cals@ifLastRspanRow=\cals@iftrue}
+
+\newcommand\cals@row@dispatch{%
+\ifx b\cals@current@context
+ \cals@ifInRspan\iftrue
+ \cals@row@dispatch@span
+ \else
+ \cals@row@dispatch@nospan
+ \fi
+\else
+ \cals@row@dispatch@nospan
+\fi}
+
+\newcommand\cals@row@dispatch@nospan{%
+\let\cals@last@context@bak=\cals@last@context
+\ifx h\cals@current@context \else
+\ifx f\cals@current@context \else
+\cals@ifbreak\iftrue
+ \setbox\cals@backup@row=\box\cals@current@row
+ \setbox\cals@backup@cs=\box\cals@current@cs
+ \let\cals@backup@rs@above=\cals@current@rs@above
+ \let\cals@backup@rs@below=\cals@current@rs@below
+ \let\cals@backup@context=\cals@current@context
+ \cals@tfoot@tokens
+ \lastrule
+ \cals@issue@break
+ \cals@thead@tokens
+ \setbox\cals@current@row=\box\cals@backup@row
+ \setbox\cals@current@cs=\box\cals@backup@cs
+ \let\cals@current@rs@above=\cals@backup@rs@above
+ \let\cals@current@rs@below=\cals@backup@rs@below
+ \let\cals@current@context=\cals@backup@context
+\fi\fi\fi
+\cals@issue@row
+\ifx b\cals@last@context
+ \ifx h\cals@last@context@bak \vskip0pt \penalty10000 \fi
+ \ifx n\cals@last@context@bak \vskip0pt \penalty10000 \fi
+\fi
+}
+
+\newcommand\cals@row@dispatch@span{%
+\ifvoid\cals@backup@row
+ \setbox\cals@backup@row=\vbox{\box\cals@current@row}%
+ \setbox\cals@backup@cs=\box\cals@current@cs
+ \let\cals@backup@rs@above=\cals@current@rs@above
+ \let\cals@backup@context=\cals@last@context
+ \cals@backup@leftskip=\leftskip
+ \cals@backup@rightskip=\rightskip
+ \leftskip=0pt \rightskip=0pt \relax
+\else
+ \setbox\cals@backup@row=\vbox{\unvbox\cals@backup@row
+ \cals@issue@row}%
+\fi
+\let\cals@last@rs@below=\cals@current@rs@below
+\let\cals@last@context=\cals@current@context
+\cals@ifLastRspanRow\iftrue
+ \setbox\cals@current@row=\box\cals@backup@row
+ \setbox\cals@current@cs=\box\cals@backup@cs
+ \let\cals@current@rs@above=\cals@backup@rs@above
+ \let\cals@last@context=\cals@backup@context
+ \leftskip=\cals@backup@leftskip
+ \rightskip=\cals@backup@rightskip
+ \cals@row@dispatch@nospan
+\fi
+}
+
+\newbox\cals@backup@row
+\newbox\cals@backup@cs
+\newskip\cals@backup@leftskip
+\newskip\cals@backup@rightskip
+
+
+
+
+\newcommand\cals@ifbreak[1]{}
+\def\cals@ifbreak{%
+\let\cals@tmp=\cals@iffalse
+\let\cals@tmpII=\cals@iftrue
+\ifx\relax\cals@tbreak@tokens
+ \ifx h\cals@current@context \else
+ \ifx f\cals@current@context \else
+ \ifx h\cals@last@context \else
+ \ifx n\cals@last@context \else
+ \dimen0=\pagetotal\relax
+ \advance\dimen0 by \ht\cals@current@row\relax
+ %\showthe\ht\cals@current@row\relax
+ \ifx \cals@tfoot@tokens\relax \else
+ %\show\cals@tfoot@height\relax
+ \advance\dimen0 by \cals@tfoot@height\relax
+ \fi
+ %\showthe\dimen0\relax
+ \ifdim \dimen0>\pagegoal\relax
+ \let\cals@tmp=\cals@tmpII
+ \fi
+ \fi\fi\fi\fi
+\else \let\cals@tmp=\cals@tmpII % tbreak@tokens
+\fi
+\cals@tmp}
+
+\newcommand\cals@issue@break{\ifx \relax\cals@tbreak@tokens \penalty-10000 %
+\else \cals@tbreak@tokens \fi
+\let\cals@tbreak@tokens=\relax
+\let\cals@last@context=n}
+
+\newcommand\cals@issue@rowsep@alone{%
+\setbox0=\hbox{%
+ \hskip\leftskip
+ \cals@rs@sofar@reset
+ \cals@rs@joinOne\cals@framers@width\cals@current@rs@above
+ \cals@rs@sofar@end
+ \hskip\rightskip}%
+\ht0=0pt \dp0=0pt \box0 }
+
+\newcommand\cals@issue@rowsep{%
+\ifx n\cals@last@context \cals@issue@rowsep@alone \else
+ \ifx \cals@last@context\cals@current@context
+ \let\cals@tmpIII=\cals@rs@width \else
+ \let\cals@tmpIII=\cals@bodyrs@width \fi
+ \setbox0=\hbox{%
+ \hskip\leftskip
+ \cals@rs@sofar@reset
+ \cals@rs@joinTwo\cals@tmpIII\cals@last@rs@below\cals@current@rs@above
+ \cals@rs@sofar@end
+ \hskip\rightskip}%
+ \ht0=0pt \dp0=0pt \box0 %
+\fi}
+
+\newdimen\cals@last@row@height
+
+\newcommand\cals@issue@row{%
+\nointerlineskip
+\setbox0=\vtop{\hbox{\hskip\leftskip \box\cals@current@cs \hskip\rightskip}}%
+ \ht0=0pt \box0
+\nointerlineskip
+\cals@issue@rowsep
+\nointerlineskip
+\hbox{\hskip\leftskip \box\cals@current@row \hskip\rightskip}%
+\let\cals@last@rs@below=\cals@current@rs@below
+\let\cals@last@context=\cals@current@context}
+
+
+\newenvironment{calstable}{%
+\let\cals@thead@tokens=\relax
+\let\cals@tfoot@tokens=\relax
+\let\cals@tbreak@tokens=\relax
+\cals@tfoot@height=0pt \relax
+\let\cals@last@context=n%
+\let\cals@current@context=b%
+\parindent=0pt %
+\cals@setpadding{Ag}\cals@setcellprevdepth{Al}%
+\let\cals@borderL=\relax
+\let\cals@borderR=\relax
+\let\cals@borderT=\relax
+\let\cals@borderB=\relax
+}{% End of the table
+\cals@tfoot@tokens\lastrule}
+
+\newcommand\lastrule{%
+\ifx r\cals@last@context \relax \else
+ \let\cals@last@context=r%
+ \nointerlineskip
+ \let\cals@current@rs@above=\cals@last@rs@below\cals@issue@rowsep@alone%
+\fi}
+
+\newcommand\thead[1]{%
+\def\cals@thead@tokens{\let\cals@current@context=h%
+#1\let\cals@current@context=b}%
+\cals@thead@tokens}
+
+\newcommand\tfoot[1]{%
+\def\cals@tfoot@tokens{\let\cals@current@context=f#1}%
+\setbox0=\vbox{\cals@tfoot@tokens}%
+\cals@tfoot@height=\ht0 \relax}
+
+\newdimen\cals@tfoot@height
+
+\newcommand\tbreak[1]{\def\cals@tbreak@tokens{#1}}
+
+\def\llt@cons#1#2{%
+\toks0=\expandafter{#1}%
+\toks2=\expandafter{#2}%
+\edef#2{\noexpand{\the\toks0}\the\toks2 }%
+}
+
+\def\llt@snoc#1#2{%
+\toks0=\expandafter{#1}%
+\toks2=\expandafter{#2}%
+\edef#1{\the\toks0 \noexpand{\the\toks2}}%
+}
+
+
+\def\llt@decons@open#1{%
+\def\llt@car{#1}%
+\toks0=\llt@opengroup
+}
+
+\def\llt@decons#1{%
+\let\llt@opengroup={%
+\expandafter\llt@decons@open#1}%
+\edef#1{\the\toks0}%
+}
+
+\def\llt@rot#1{%
+\ifx#1\empty
+\let\llt@car=\relax
+\else
+\llt@decons#1%
+\llt@snoc#1\llt@car%
+\fi
+}
+
+\def\llt@desnocII#1{
+\ifx\empty#1%
+\let\llt@tmp=n%
+\else
+\llt@snoc{\llt@newlist}{\llt@car}%
+\let\llt@tmp=y%
+\fi
+}
+
+\def\llt@desnoc#1{%
+\def\llt@newlist{}%
+\loop
+\llt@decons{#1}%
+\llt@desnocII{#1}%
+\if y\llt@tmp \repeat
+\let#1=\llt@newlist}
+
+
+
+
+\newcommand\cals@cs@width{.4pt}
+\newcommand\cals@framecs@width{0pt}
+\newcommand\cals@rs@width{.4pt}
+\newcommand\cals@framers@width{0pt}
+\newcommand\cals@bodyrs@width{1.2pt}
+\newcommand\cals@bgcolor{}
+
+
+
+
+
+\newcommand\cals@decor@begin{\cals@csrow@begin\cals@rs@spec@begin}
+
+\newcommand\cals@decor@next[1]{%
+\cals@csrow@nextcell{#1}\cals@borderL\cals@borderR\cals@bgcolor
+\cals@rs@spec@next{#1}\cals@lastLeftWidth\cals@borderT\cals@borderB}
+
+\newcommand\cals@decor@end{%
+\cals@csrow@end
+\cals@rs@spec@end\cals@lastLeftWidth}
+
+
+\newcommand\cals@widthII[2]{%
+\ifx \relax#2\edef\cals@width{#1}%
+ \else \edef\cals@width{#2}\fi}
+
+\newcommand\cals@withWidthII[3]{%
+\cals@widthII{#1}{#2}%
+\ifdim \cals@width>0pt }
+
+\newcommand\cals@withColorII[3]{%
+\ifx \relax#2\edef\cals@color{#1}%
+ \else \edef\cals@color{#2}\fi
+\ifx \cals@color\empty \else\expandafter\expandafter\fi\iffalse\iftrue\fi}
+
+\newcommand\cals@halfWidthToDimen[2]{%
+\dimen#1=#2\relax \divide\dimen#1 by 2 }
+
+\newcommand\cals@maxWidth[2]{%
+\ifx \relax#1\relax
+ \ifx \relax#2\let\cals@width=\relax
+ \else \edef\cals@width{#2}\fi
+\else
+ \ifx \relax#2\relax
+ \edef\cals@width{#1}%
+ \else
+ \ifdim #1>#2 \edef\cals@width{#1}%
+ \else \edef\cals@width{#2}\fi\fi\fi}
+
+\def\cals@iftrue#1{\iftrue}
+\def\cals@iffalse#1{\iffalse}
+
+
+\newcommand\cals@cs@outOne[3]{%
+\ifx \relax#1%
+\else
+ \cals@withColorII\cals@bgcolor{#3}\iftrue
+ \textcolor{\cals@color}{\vrule depth0pt width#1 }%
+ \hskip -#1\relax
+ \fi
+\fi
+\cals@withWidthII\cals@cs@width{#2}\iftrue
+ \cals@halfWidthToDimen0 \cals@width %
+ \hskip -\dimen0 %
+ \vrule depth0pt width\cals@width\relax
+ \hskip -\dimen0 %
+\fi
+\let\cals@lastLeftWidth=\cals@width
+\ifx \relax#1\else \hskip#1 \fi
+}
+
+\newbox\cals@current@cs
+
+\newcommand\cals@csrow@begin{%
+\setbox\cals@current@cs=\box\voidb@x %
+\let\cals@lastWidth=\relax}
+
+\newcommand\cals@csrow@nextcell[4]{%
+\ifvoid\cals@current@cs
+ \toks0=\expandafter{\cals@cs@width}%
+ \def\next{\edef\cals@cs@width{\the\toks0}}%
+ \edef\cals@cs@width{\cals@framecs@width}%
+\else \let\next=\relax \fi
+\cals@maxWidth\cals@lastWidth{#2}%
+\setbox\cals@current@cs=\hbox{\unhbox\cals@current@cs
+ \cals@cs@outOne{#1}\cals@width{#4}%
+ \global\let\cals@tmp=\cals@lastLeftWidth}%
+\let\cals@lastLeftWidth=\cals@tmp
+\let\cals@lastWidth=#3%
+\next}
+
+\newcommand\cals@csrow@end{%
+\ifx \relax\cals@lastWidth
+ \let\cals@width=\cals@framecs@width
+\else
+ \let\cals@width=\cals@lastWidth
+\fi
+\cals@csrow@nextcell\relax\cals@width\relax\relax}
+
+
+\newcommand\cals@rs@pack[5]{%
+\edef#1{\noexpand{#2\noexpand}\noexpand{#3\noexpand}\noexpand{#4\noexpand}%
+ \ifx \relax#5\relax \else \noexpand{#5\noexpand}\fi }}
+
+\newcommand\cals@rs@unpack[5]{%
+\def\cals@tmp##1##2##3##4{\edef#2{##1}\edef#3{##2}\edef#4{##3}%
+ \ifx\relax##4\let#5=\relax \else \edef#5{##4}\fi}%
+\expandafter\cals@tmp#1}
+
+
+
+\newcommand\cals@rs@spec@begin{%
+\def\cals@current@rs@above{}%
+\def\cals@current@rs@below{}%
+\let\cals@rs@spec@ll=\relax}
+
+\newcommand\cals@rs@spec@next[4]{
+\cals@rs@spec@nextII#2
+\let\cals@rs@spec@ll=#1%
+\let\cals@rs@spec@bl=#2%
+\let\cals@rs@spec@bt=#3%
+\let\cals@rs@spec@bb=#4%
+}
+
+\newcommand\cals@rs@spec@nextII[1]{%
+\ifx \relax\cals@rs@spec@ll \else
+ \cals@rs@pack\cals@tmp\cals@rs@spec@ll\cals@rs@spec@bl#1\cals@rs@spec@bt
+ \llt@snoc\cals@current@rs@above\cals@tmp
+ \cals@rs@pack\cals@tmp\cals@rs@spec@ll\cals@rs@spec@bl#1\cals@rs@spec@bb
+ \llt@snoc\cals@current@rs@below\cals@tmp
+\fi
+}
+
+\newcommand\cals@rs@spec@end[1]{}
+\let\cals@rs@spec@end=\cals@rs@spec@nextII
+
+\newcommand\cals@rs@sofar@length{}
+\newcommand\cals@rs@sofar@borderl{}
+\newcommand\cals@rs@sofar@borderr{}
+\newcommand\cals@rs@sofar@width{}
+
+\newcommand\cals@rs@sofar@reset{\let\cals@rs@sofar@width=\relax}
+
+\newcommand\cals@rs@sofar@end{\ifx\relax\cals@rs@sofar@width
+ \else\cals@rs@sofar@out\fi}
+
+\newcommand\cals@rs@sofar@next[4]{%
+\ifx\relax\cals@rs@sofar@width
+ \let\cals@rs@sofar@length=#1%
+ \let\cals@rs@sofar@borderl=#2%
+ \let\cals@rs@sofar@borderr=#3%
+ \let\cals@rs@sofar@width=#4%
+\else
+ \ifdim \cals@rs@sofar@width=#4\relax
+ \dimen0=\cals@rs@sofar@length\relax
+ \advance\dimen0 by #1\relax
+ \edef\cals@rs@sofar@length{\the\dimen0}%
+ \let\cals@rs@sofar@borderr=#3%
+ \else
+ \cals@rs@sofar@out
+ \let\cals@rs@sofar@length=#1%
+ \let\cals@rs@sofar@borderl=#2%
+ \let\cals@rs@sofar@borderr=#3%
+ \let\cals@rs@sofar@width=#4%
+ \fi
+\fi}
+
+\newcommand\cals@rs@sofar@over[4]{%
+\ifdim 0pt=#4
+ \relax
+\else
+ \ifdim \cals@rs@sofar@width=#4\relax
+ \ifdim #3>\cals@rs@sofar@borderr\relax
+ \edef\cals@rs@sofar@borderr{#3}%
+ \fi
+ \dimen0=\cals@rs@sofar@length
+ \advance\dimen0 by \cals@rs@sofar@borderl\relax
+ \advance\dimen0 by -#2\relax
+ \ifdim #1>\dimen0 \relax
+ \edef\cals@rs@sofar@borderl{#2}%
+ \fi
+ \else
+ \cals@rs@sofar@out
+ \hskip-#1\relax
+ \let\cals@rs@sofar@length=#1%
+ \let\cals@rs@sofar@borderl=#2%
+ \let\cals@rs@sofar@borderr=#3%
+ \let\cals@rs@sofar@width=#4%
+ \fi
+\fi}
+
+\newcommand\cals@rs@sofar@out{%
+\ifdim 0pt=\cals@rs@sofar@width\relax
+ \hskip\cals@rs@sofar@length\relax
+\else
+ \cals@halfWidthToDimen0\cals@rs@sofar@borderl
+ \hskip-\dimen0\relax
+ \cals@halfWidthToDimen2\cals@rs@sofar@borderr
+ \dimen4=\cals@rs@sofar@length\relax
+ \advance\dimen4 by \dimen0\relax \advance\dimen4 by \dimen2\relax
+ \cals@halfWidthToDimen6\cals@rs@sofar@width
+ \vrule height\dimen6 depth\dimen6 width\dimen4\relax
+ \hskip-\dimen2\relax
+\fi}
+
+
+\newcommand\cals@rs@joinTwo[3]{%
+\def\next##1{%
+\ifx \eol##1\let\next=\relax
+\else
+ \toks0=\expandafter{##1}%
+ \edef\cals@tmpII{\the\toks0}%
+ \llt@decons#3%
+ \cals@rs@unpack\cals@tmpII\cals@tmpLI \cals@tmpBlI \cals@tmpBrI \cals@tmpWI
+ \cals@rs@unpack\llt@car \cals@tmpLII\cals@tmpBlII\cals@tmpBrII\cals@tmpWII
+ \let\cals@tmp=\cals@iftrue
+ \cals@maxWidth\cals@tmpWI\cals@tmpWII
+ \ifx \relax\cals@width\else \ifdim \cals@width=0pt %
+ \cals@rs@sofar@next\cals@tmpLI\cals@tmpBlI\cals@tmpBrI\cals@width
+ \let\cals@tmp=\cals@iffalse
+ \fi\fi
+ \cals@tmp\ifvoid
+ \cals@widthII#1\cals@tmpWI
+ \cals@rs@sofar@next\cals@tmpLI\cals@tmpBlI\cals@tmpBrI\cals@width
+ \cals@widthII#1\cals@tmpWII
+ \cals@rs@sofar@over\cals@tmpLII\cals@tmpBlII\cals@tmpBrII\cals@width
+ \fi
+\fi
+\next}%
+\expandafter\next#2\eol}
+
+\newcommand\cals@rs@joinOne[2]{%
+\def\next##1{\ifx\eol##1\let\next=\relax\else
+ \toks0=\expandafter{##1}%
+ \edef\cals@tmpII{\the\toks0}%
+ \cals@rs@unpack\cals@tmpII\cals@tmpL\cals@tmpBl\cals@tmpBr\cals@tmpW
+ \cals@widthII#1\cals@tmpW
+ \cals@rs@sofar@next\cals@tmpL\cals@tmpBl\cals@tmpBr\cals@width
+\fi\next}%
+\expandafter\next#2\eol}
+\endinput
+%%
+%% End of file `cals.sty'.
diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check
index c36b3fbfc65..35ce17f0748 100755
--- a/Master/tlpkg/bin/tlpkg-ctan-check
+++ b/Master/tlpkg/bin/tlpkg-ctan-check
@@ -62,7 +62,7 @@ my @TLP_working = qw(
boxedminipage boxhandler bpchem bpolynomial
bracketkey braille braket breakcites breakurl
bullcntr bundledoc bussproofs bytefield
- c-pascal cachepic calctab calligra calrsfs calxxxx calxxxx-yyyy cancel
+ c-pascal cachepic calctab calligra calrsfs cals calxxxx calxxxx-yyyy cancel
capt-of captcont captdef caption carlisle carolmin-ps cases casyl catechis
cbcoptic cbfonts
cc-pl ccaption ccfonts ccicons cclicenses
diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds
index 6c947ce1a05..2ba036ada9b 100755
--- a/Master/tlpkg/libexec/ctan2tds
+++ b/Master/tlpkg/libexec/ctan2tds
@@ -740,6 +740,7 @@ $Master = "$mydir/../..";
%prehook = (
+ 'cals' => '&PREHOOK_cals',
'cm-super' => '&PREHOOK_cm_super',
'fixme' => '&PREHOOK_fixme',
'ibygrk' => '&PREHOOK_ibygrk',
@@ -3823,6 +3824,12 @@ sub PREHOOK_cm_super
&SYSTEM ("$RM -rf dvipdfm");
}
+sub PREHOOK_cals
+{
+ print "PREHOOK_$package - flatten only cals subdir\n";
+ &SYSTEM ("$MV cals/* .");
+}
+
sub PREHOOK_fixme
{
print "PREHOOK_$package - create dtx subdirs\n";
diff --git a/Master/tlpkg/tlpsrc/cals.tlpsrc b/Master/tlpkg/tlpsrc/cals.tlpsrc
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Master/tlpkg/tlpsrc/cals.tlpsrc
diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
index 11e601768a0..fbdb8fb4afa 100644
--- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
+++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
@@ -65,6 +65,7 @@ depend bullcntr
depend bussproofs
depend calctab
depend calrsfs
+depend cals
depend calxxxx
depend calxxxx-yyyy
depend cancel