commit 9dcb24d578cfc9df5b70bbf3f13a95cd63ac3213
Author: Juergen Spitzmueller <[email protected]>
Date:   Sun Jul 1 19:18:38 2018 +0200

    Support varwidth's V tabular column type
    
    This effectively enables linebreaks, multipars and layout changes in
    non-fixed width (i.e., standard) table columns.
    
    Fixes: #6577
    
    TODO: metrics are wrong (too wide) on screen with linebreaks.
---
 development/FORMAT          |    5 +
 lib/doc/LaTeXConfig.lyx     |   31 +++++++-
 lib/lyx2lyx/lyx_2_4.py      |  112 ++++++++++++++++++++++++--
 src/TextMetrics.cpp         |    5 +-
 src/TextMetrics.h           |    3 +-
 src/insets/InsetTabular.cpp |  189 ++++++++++++++++++++++++++++++++-----------
 src/insets/InsetTabular.h   |   31 +++++---
 src/tex2lyx/TODO.txt        |    1 +
 src/version.h               |    4 +-
 9 files changed, 307 insertions(+), 74 deletions(-)

diff --git a/development/FORMAT b/development/FORMAT
index 1a160e0..ef3d7f8 100644
--- a/development/FORMAT
+++ b/development/FORMAT
@@ -7,6 +7,11 @@ changes happened in particular if possible. A good example 
would be
 
 -----------------------
 
+2018-07-01  Jürgen Spitzmüller <[email protected]>
+       * format incremented to 555: Support varwidth's V tabular column type.
+          This effectively enables linebreaks, multipars and layout changes in
+          non-fixed width (i.e., standard) table columns.
+
 2018-06-23  Jürgen Spitzmüller <[email protected]>
        * format incremented to 554: Support tabularx and xltabular:
          - add column flag "varwidth=true", which will output column type 'X'
diff --git a/lib/doc/LaTeXConfig.lyx b/lib/doc/LaTeXConfig.lyx
index 341e273..e20623e 100644
--- a/lib/doc/LaTeXConfig.lyx
+++ b/lib/doc/LaTeXConfig.lyx
@@ -5431,6 +5431,35 @@ varioref
  the page of the referred label.
 \end_layout
 
+\begin_layout Subsubsection
+varwidth
+\end_layout
+
+\begin_layout Description
+Found: 
+\begin_inset Info
+type  "package"
+arg   "varwidth"
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+CTAN: 
+\family typewriter
+macros/latex/contrib/varwidth/
+\end_layout
+
+\begin_layout Description
+Notes: The package 
+\family sans
+varwidth
+\family default
+\color none
+ is needed to allow for line and paragraph breaks in standard tabular columns.
+\end_layout
+
 \begin_layout Subsection
 xltabular
 \end_layout
@@ -6750,7 +6779,7 @@ Notes: The package
 varwidth
 \family default
 \color none
- is used to produce minipages variable (i.
+ is used to produce minipages of variable (i.
 \begin_inset space \thinspace{}
 \end_inset
 
diff --git a/lib/lyx2lyx/lyx_2_4.py b/lib/lyx2lyx/lyx_2_4.py
index 32c6c33..9b388aa 100644
--- a/lib/lyx2lyx/lyx_2_4.py
+++ b/lib/lyx2lyx/lyx_2_4.py
@@ -24,14 +24,14 @@ import sys, os
 
 # Uncomment only what you need to import, please.
 
-from parser_tools import (find_end_of_inset, find_end_of_layout, find_token,
-get_bool_value, get_value, get_quoted_value) 
+from parser_tools import (count_pars_in_inset, find_end_of_inset, 
find_end_of_layout,
+find_token, get_bool_value, get_option_value, get_value, get_quoted_value) 
 #    del_token, del_value, del_complete_lines,
 #    find_complete_lines, find_end_of, 
 #    find_re, find_substring, find_token_backwards,
 #    get_containing_inset, get_containing_layout,
 #    is_in_inset, set_bool_value
-#    find_tokens, find_token_exact, check_token, get_option_value
+#    find_tokens, find_token_exact, check_token
 
 from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble)
 #  revert_font_attrs, insert_to_preamble, latex_length
@@ -118,15 +118,15 @@ def revert_paratype(document):
                 document.header[i1] = 
document.header[i1].replace("PTSerif-TLF", "default")
             if j!= -1: 
                 if sfoption != "":
-                       add_to_preamble(document, ["\\usepackage[" + sfoption + 
"]{PTSans}"])
+                    add_to_preamble(document, ["\\usepackage[" + sfoption + 
"]{PTSans}"])
                 else:
-                       add_to_preamble(document, ["\\usepackage{PTSans}"])
+                    add_to_preamble(document, ["\\usepackage{PTSans}"])
                 document.header[j] = document.header[j].replace("PTSans-TLF", 
"default")
             if k!= -1: 
                 if ttoption != "":
-                       add_to_preamble(document, ["\\usepackage[" + ttoption + 
"]{PTMono}"])
+                    add_to_preamble(document, ["\\usepackage[" + ttoption + 
"]{PTMono}"])
                 else:
-                       add_to_preamble(document, ["\\usepackage{PTMono}"])    
+                    add_to_preamble(document, ["\\usepackage{PTMono}"])    
                 document.header[k] = document.header[k].replace("PTMono-TLF", 
"default")
 
 
@@ -345,6 +345,100 @@ def revert_stretchcolumn(document):
         i = i + 1
 
 
+def revert_vcolumns(document):
+    " Revert standard columns with line breaks etc. "
+    i = 0
+    needvarwidth = False
+    needarray = False
+    try:
+        while True:
+            i = find_token(document.body, "\\begin_inset Tabular", i)
+            if i == -1:
+                return
+            j = find_end_of_inset(document.body, i)
+            if j == -1:
+                document.warning("Malformed LyX document: Could not find end 
of tabular.")
+                i += 1
+                continue
+
+            # Collect necessary column information
+            m = i + 1
+            nrows = int(document.body[i+1].split('"')[3])
+            ncols = int(document.body[i+1].split('"')[5])
+            col_info = []
+            for k in range(ncols):
+                m = find_token(document.body, "<column", m)
+                width = get_option_value(document.body[m], 'width')
+                varwidth = get_option_value(document.body[m], 'varwidth')
+                alignment = get_option_value(document.body[m], 'alignment')
+                special = get_option_value(document.body[m], 'special')
+                col_info.append([width, varwidth, alignment, special, m])
+
+            # Now parse cells
+            m = i + 1
+            lines = []
+            for row in range(nrows):
+                for col in range(ncols):
+                    m = find_token(document.body, "<cell", m)
+                    multicolumn = get_option_value(document.body[m], 
'multicolumn')
+                    multirow = get_option_value(document.body[m], 'multirow')
+                    width = get_option_value(document.body[m], 'width')
+                    rotate = get_option_value(document.body[m], 'rotate')
+                    # Check for: linebreaks, multipars, non-standard 
environments
+                    begcell = m
+                    endcell = find_token(document.body, "</cell>", begcell)
+                    vcand = False
+                    if find_token(document.body, "\\begin_inset Newline", 
begcell, endcell) != -1:
+                        vcand = True
+                    elif count_pars_in_inset(document.body, begcell + 2) > 1:
+                        vcand = True
+                    elif get_value(document.body, "\\begin_layout", begcell) 
!= "Plain Layout":
+                        vcand = True
+                    if vcand and rotate == "" and ((multicolumn == "" and 
multirow == "") or width == ""):
+                        if col_info[col][0] == "" and col_info[col][1] == "" 
and col_info[col][3] == "":
+                            needvarwidth = True
+                            alignment = col_info[col][2]
+                            col_line = col_info[col][4]
+                            vval = ""
+                            if alignment == "center":
+                                vval = ">{\\centering}"
+                            elif  alignment == "left":
+                                vval = ">{\\raggedright}"
+                            elif alignment == "right":
+                                vval = ">{\\raggedleft}"
+                            if vval != "":
+                                needarray = True
+                            vval += "V{\\linewidth}"
+                
+                            document.body[col_line] = 
document.body[col_line][:-1] + " special=\"" + vval + "\">"
+                            # ERT newlines and linebreaks (since LyX < 2.4 
automatically inserts parboxes
+                            # with newlines, and we do not want that)
+                            while True:
+                                endcell = find_token(document.body, "</cell>", 
begcell)
+                                linebreak = False
+                                nl = find_token(document.body, "\\begin_inset 
Newline newline", begcell, endcell)
+                                if nl == -1:
+                                    nl = find_token(document.body, 
"\\begin_inset Newline linebreak", begcell, endcell)
+                                    if nl == -1:
+                                         break
+                                    linebreak = True
+                                nle = find_end_of_inset(document.body, nl)
+                                del(document.body[nle:nle+1])
+                                if linebreak:
+                                    document.body[nl:nl+1] = 
put_cmd_in_ert("\\linebreak{}")
+                                else:
+                                    document.body[nl:nl+1] = 
put_cmd_in_ert("\\\\")
+                    m += 1
+
+            i = j + 1
+
+    finally:
+        if needarray == True:
+            add_to_preamble(document, ["\\usepackage{array}"])
+        if needvarwidth == True:
+            add_to_preamble(document, ["\\usepackage{varwidth}"])
+
+
 ##
 # Conversion hub
 #
@@ -360,10 +454,12 @@ convert = [
            [551, []],
            [552, []],
            [553, []],
-           [554, []]
+           [554, []],
+           [555, []]
           ]
 
 revert =  [
+           [554, [revert_vcolumns]],
            [553, [revert_stretchcolumn]],
            [552, [revert_tuftecite]],
            [551, [revert_floatpclass, revert_floatalignment]],
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 98e3483..5035187 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -160,7 +160,8 @@ ParagraphMetrics & TextMetrics::parMetrics(pit_type pit, 
bool redo)
 }
 
 
-bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width)
+bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width,
+                         bool const expand_on_multipars)
 {
        LBUFERR(mi.base.textwidth > 0);
        max_width_ = mi.base.textwidth;
@@ -170,7 +171,7 @@ bool TextMetrics::metrics(MetricsInfo & mi, Dimension & 
dim, int min_width)
        dim_ = Dimension();
        dim_.wid = min_width;
        pit_type const npar = text_->paragraphs().size();
-       if (npar > 1)
+       if (npar > 1 && expand_on_multipars)
                // If there is more than one row, expand the text to
                // the full allowable width.
                dim_.wid = max_width_;
diff --git a/src/TextMetrics.h b/src/TextMetrics.h
index 369f07a..6802488 100644
--- a/src/TextMetrics.h
+++ b/src/TextMetrics.h
@@ -55,7 +55,8 @@ public:
 
 
        /// compute text metrics.
-       bool metrics(MetricsInfo & mi, Dimension & dim, int min_width = 0);
+       bool metrics(MetricsInfo & mi, Dimension & dim, int min_width = 0,
+                    bool const expand_on_multipars = true);
 
        ///
        void newParMetricsDown();
diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp
index afdd3d7..a25f4d6 100644
--- a/src/insets/InsetTabular.cpp
+++ b/src/insets/InsetTabular.cpp
@@ -917,8 +917,11 @@ void Tabular::updateIndexes()
        // reset column and row of cells and update their width and alignment
        for (row_type row = 0; row < nrows(); ++row)
                for (col_type column = 0; column < ncols(); ++column) {
-                       if (isPartOfMultiColumn(row, column))
+                       if (isPartOfMultiColumn(row, column)) {
+                               
cell_info[row][column].inset->toggleMultiCol(true);
                                continue;
+                       }
+                       cell_info[row][column].inset->toggleMultiCol(false);
                        // columnofcell needs to be called before setting width 
and aligment
                        // multirow cells inherit the width from the column 
width
                        if (!isPartOfMultiRow(row, column)) {
@@ -926,8 +929,11 @@ void Tabular::updateIndexes()
                                rowofcell[i] = row;
                        }
                        setFixedWidth(row, column);
-                       if (isPartOfMultiRow(row, column))
+                       if (isPartOfMultiRow(row, column)) {
+                               
cell_info[row][column].inset->toggleMultiRow(true);
                                continue;
+                       }
+                       cell_info[row][column].inset->toggleMultiRow(false);
                        cell_info[row][column].inset->setContentAlignment(
                                getAlignment(cellIndex(row, column)));
                        ++i;
@@ -1130,14 +1136,16 @@ void Tabular::setVAlignment(idx_type cell, VAlignment 
align,
 namespace {
 
 /**
- * Allow line and paragraph breaks for fixed width cells or disallow them,
- * merge cell paragraphs and reset layout to standard for variable width
- * cells.
+ * Allow line and paragraph breaks for fixed width multicol/multirow cells
+ * or disallow them, merge cell paragraphs and reset layout to standard
+ * for variable width multicol cells.
  */
-void toggleFixedWidth(Cursor & cur, InsetTableCell * inset, bool fixedWidth)
+void toggleFixedWidth(Cursor & cur, InsetTableCell * inset,
+                     bool const fixedWidth, bool const multicol,
+                     bool const multirow)
 {
        inset->toggleFixedWidth(fixedWidth);
-       if (fixedWidth)
+       if (!multirow && (fixedWidth || !multicol))
                return;
 
        // merge all paragraphs to one
@@ -1145,6 +1153,19 @@ void toggleFixedWidth(Cursor & cur, InsetTableCell * 
inset, bool fixedWidth)
        while (inset->paragraphs().size() > 1)
                mergeParagraph(bp, inset->paragraphs(), 0);
 
+       // This is relevant for multirows
+       if (fixedWidth)
+               return;
+
+       // remove newlines
+       ParagraphList::iterator pit = inset->paragraphs().begin();
+       for (; pit != inset->paragraphs().end(); ++pit) {
+               for (pos_type j = 0; j != pit->size(); ++j) {
+                       if (pit->isNewline(j))
+                               pit->eraseChar(j, bp.track_changes);
+               }
+       }
+
        // reset layout
        cur.push(*inset);
        // undo information has already been recorded
@@ -1171,16 +1192,13 @@ void Tabular::setColumnPWidth(Cursor & cur, idx_type 
cell,
                idx_type const cidx = cellIndex(r, c);
                // because of multicolumns
                toggleFixedWidth(cur, cellInset(cidx).get(),
-                                !getPWidth(cidx).zero());
+                                !getPWidth(cidx).zero(), isMultiColumn(cidx),
+                                isMultiRow(cidx));
                if (isMultiRow(cidx))
                        setAlignment(cidx, LYX_ALIGN_LEFT, false);
        }
-       // cur paragraph can become invalid after paragraphs were merged
-       if (cur.pit() > cur.lastpit())
-               cur.pit() = cur.lastpit();
-       // cur position can become invalid after newlines were removed
-       if (cur.pos() > cur.lastpos())
-               cur.pos() = cur.lastpos();
+       // cur can become invalid after paragraphs were merged
+       cur.fixIfBroken();
 }
 
 
@@ -1201,13 +1219,10 @@ bool Tabular::setMColumnPWidth(Cursor & cur, idx_type 
cell,
                return false;
 
        cellInfo(cell).p_width = width;
-       toggleFixedWidth(cur, cellInset(cell).get(), !width.zero());
-       // cur paragraph can become invalid after paragraphs were merged
-       if (cur.pit() > cur.lastpit())
-               cur.pit() = cur.lastpit();
-       // cur position can become invalid after newlines were removed
-       if (cur.pos() > cur.lastpos())
-               cur.pos() = cur.lastpos();
+       toggleFixedWidth(cur, cellInset(cell).get(), !width.zero(),
+                        isMultiColumn(cell), isMultiRow(cell));
+       // cur can become invalid after paragraphs were merged
+       cur.fixIfBroken();
        return true;
 }
 
@@ -1717,6 +1732,16 @@ bool Tabular::hasVarwidthColumn() const
 }
 
 
+bool Tabular::isVTypeColumn(col_type c) const
+{
+       for (row_type r = 0; r < nrows(); ++r) {
+               idx_type idx = cellIndex(r, c);
+               if (getRotateCell(idx) == 0 && useBox(idx) == BOX_VARWIDTH)
+                       return true;
+       }
+       return false;
+}
+
 
 Tabular::CellData const & Tabular::cellInfo(idx_type cell) const
 {
@@ -1730,7 +1755,7 @@ Tabular::CellData & Tabular::cellInfo(idx_type cell)
 }
 
 
-Tabular::idx_type Tabular::setMultiColumn(idx_type cell, idx_type number,
+Tabular::idx_type Tabular::setMultiColumn(Cursor & cur, idx_type cell, 
idx_type number,
                                          bool const right_border)
 {
        idx_type const col = cellColumn(cell);
@@ -1745,6 +1770,14 @@ Tabular::idx_type Tabular::setMultiColumn(idx_type cell, 
idx_type number,
        if (column_info[col].alignment != LYX_ALIGN_DECIMAL)
                cs.alignment = column_info[col].alignment;
        setRightLine(cell, right_border);
+       // non-fixed width multicolumns cannot have multiple paragraphs
+       if (getPWidth(cell).zero()) {
+               toggleFixedWidth(cur, cellInset(cell).get(),
+                                !getPWidth(cell).zero(), isMultiColumn(cell),
+                                isMultiRow(cell));
+               // cur can become invalid after paragraphs were merged
+               cur.fixIfBroken();
+       }
 
        idx_type lastcell = cellIndex(row, col + number - 1);
        for (idx_type i = 1; i < lastcell - cell + 1; ++i) {
@@ -1773,7 +1806,7 @@ bool Tabular::hasMultiRow(row_type r) const
        return false;
 }
 
-Tabular::idx_type Tabular::setMultiRow(idx_type cell, idx_type number,
+Tabular::idx_type Tabular::setMultiRow(Cursor & cur, idx_type cell, idx_type 
number,
                                       bool const bottom_border,
                                       LyXAlignment const halign)
 {
@@ -1796,6 +1829,15 @@ Tabular::idx_type Tabular::setMultiRow(idx_type cell, 
idx_type number,
        else
                cs.alignment = LYX_ALIGN_LEFT;
 
+       // Multirows cannot have multiple paragraphs
+       if (getPWidth(cell).zero()) {
+               toggleFixedWidth(cur, cellInset(cell).get(),
+                                !getPWidth(cell).zero(),
+                                isMultiColumn(cell), isMultiRow(cell));
+               // cur can become invalid after paragraphs were merged
+               cur.fixIfBroken();
+       }
+
        // set the bottom line of the last selected cell
        setBottomLine(cell, bottom_border);
 
@@ -1949,7 +1991,7 @@ Tabular::BoxType Tabular::getUsebox(idx_type cell) const
                return BOX_NONE;
        if (cellInfo(cell).usebox > 1)
                return cellInfo(cell).usebox;
-       return useParbox(cell);
+       return useBox(cell);
 }
 
 
@@ -2078,11 +2120,11 @@ bool Tabular::haveLTLastFoot(bool withcaptions) const
 }
 
 
-Tabular::idx_type Tabular::setLTCaption(row_type row, bool what)
+Tabular::idx_type Tabular::setLTCaption(Cursor & cur, row_type row, bool what)
 {
        idx_type i = getFirstCellInRow(row);
        if (what) {
-               setMultiColumn(i, numberOfCellsInRow(row), false);
+               setMultiColumn(cur, i, numberOfCellsInRow(row), false);
                setTopLine(i, false);
                setBottomLine(i, false);
                setLeftLine(i, false);
@@ -2490,7 +2532,7 @@ void Tabular::TeXCellPreamble(otexstream & os, idx_type 
cell,
                }
                os << "]{" << from_ascii(getPWidth(cell).asLatexString())
                   << "}\n";
-       } else if (getUsebox(cell) == BOX_VARWIDTH) {
+       } else if (getRotateCell(cell) != 0 && getUsebox(cell) == BOX_VARWIDTH) 
{
                os << "\\begin{varwidth}[";
                switch (valign) {
                case LYX_VALIGN_TOP:
@@ -2520,7 +2562,7 @@ void Tabular::TeXCellPostamble(otexstream & os, idx_type 
cell,
                os << '}';
        else if (getUsebox(cell) == BOX_MINIPAGE)
                os << breakln << "\\end{minipage}";
-       else if (getUsebox(cell) == BOX_VARWIDTH)
+       else if (getRotateCell(cell) != 0 && getUsebox(cell) == BOX_VARWIDTH)
                os << breakln << "\\end{varwidth}";
        if (getRotateCell(cell) != 0)
                os << breakln << "\\end{turn}";
@@ -2964,6 +3006,25 @@ void Tabular::latex(otexstream & os, OutputParams const 
& runparams) const
                                        break;
                                }
                                os << 'X';
+                       } else if (isVTypeColumn(c)) {
+                               switch (column_info[c].alignment) {
+                               case LYX_ALIGN_LEFT:
+                                       os << ">{\\raggedright}";
+                                       break;
+                               case LYX_ALIGN_RIGHT:
+                                       os << ">{\\raggedleft}";
+                                       break;
+                               case LYX_ALIGN_CENTER:
+                                       os << ">{\\centering}";
+                                       break;
+                               case LYX_ALIGN_NONE:
+                               case LYX_ALIGN_BLOCK:
+                               case LYX_ALIGN_LAYOUT:
+                               case LYX_ALIGN_SPECIAL:
+                               case LYX_ALIGN_DECIMAL:
+                                       break;
+                               }
+                               os << "V{\\linewidth}";
                        } else {
                                switch (column_info[c].alignment) {
                                case LYX_ALIGN_LEFT:
@@ -3588,7 +3649,8 @@ void Tabular::validate(LaTeXFeatures & features) const
                if (getUsebox(cell) == BOX_VARWIDTH)
                        features.require("varwidth");
                if (getVAlignment(cell) != LYX_VALIGN_TOP
-                   || !getPWidth(cell).zero())
+                   || !getPWidth(cell).zero()
+                   || isVTypeColumn(cellColumn(cell)))
                        features.require("array");
                // Tell footnote that we need a savenote
                // environment in non-long tables or
@@ -3604,17 +3666,19 @@ void Tabular::validate(LaTeXFeatures & features) const
 }
 
 
-Tabular::BoxType Tabular::useParbox(idx_type cell) const
+Tabular::BoxType Tabular::useBox(idx_type cell) const
 {
        ParagraphList const & parlist = cellInset(cell)->paragraphs();
+       if (parlist.size() > 1)
+               return BOX_VARWIDTH;
+
        ParagraphList::const_iterator cit = parlist.begin();
        ParagraphList::const_iterator end = parlist.end();
-       bool const turned = getRotateCell(cell) != 0;
 
        for (; cit != end; ++cit)
                for (int i = 0; i < cit->size(); ++i)
-                       if (cit->isNewline(i))
-                               return turned ? BOX_VARWIDTH : BOX_PARBOX;
+                       if (cit->isNewline(i) || cit->layout().isEnvironment())
+                               return BOX_VARWIDTH;
 
        return BOX_NONE;
 }
@@ -3628,13 +3692,13 @@ Tabular::BoxType Tabular::useParbox(idx_type cell) const
 
 InsetTableCell::InsetTableCell(Buffer * buf)
        : InsetText(buf, InsetText::PlainLayout), isFixedWidth(false),
-         contentAlign(LYX_ALIGN_CENTER)
+         isMultiColumn(false), isMultiRow(false), 
contentAlign(LYX_ALIGN_CENTER)
 {}
 
 
 bool InsetTableCell::forcePlainLayout(idx_type) const
 {
-       return !isFixedWidth;
+       return isMultiRow || (isMultiColumn && !isFixedWidth);
 }
 
 
@@ -3701,6 +3765,34 @@ docstring InsetTableCell::xhtml(XHTMLStream & xs, 
OutputParams const & rp) const
 }
 
 
+void InsetTableCell::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       TextMetrics & tm = mi.base.bv->textMetrics(&text());
+
+       // Hand font through to contained lyxtext:
+       tm.font_.fontInfo() = mi.base.font;
+       mi.base.textwidth -= 2 * TEXT_TO_INSET_OFFSET;
+
+       // This can happen when a layout has a left and right margin,
+       // and the view is made very narrow. We can't do better than
+       // to draw it partly out of view (bug 5890).
+       if (mi.base.textwidth < 1)
+               mi.base.textwidth = 1;
+
+       // We tell metrics here not to expand on multiple pars
+       // This is the difference to InsetText::Metrics
+       // FIXME: pars with newlines are still too wide!
+       if (hasFixedWidth())
+               tm.metrics(mi, dim, mi.base.textwidth, false);
+       else
+               tm.metrics(mi, dim, 0, false);
+       mi.base.textwidth += 2 * TEXT_TO_INSET_OFFSET;
+       dim.asc += TEXT_TO_INSET_OFFSET;
+       dim.des += TEXT_TO_INSET_OFFSET;
+       dim.wid += 2 * TEXT_TO_INSET_OFFSET;
+}
+
+
 
 /////////////////////////////////////////////////////////////////////
 //
@@ -3921,8 +4013,7 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & 
dim) const
 }
 
 
-bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col)
-       const
+bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) 
const
 {
        if (&cur.inset() == this && cur.selection()) {
                if (cur.selIsMultiCell()) {
@@ -5190,13 +5281,13 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest 
const & cmd,
                        return true;
                }
                // fall through
-       case LFUN_NEWLINE_INSERT: {
-               if (tabular.getPWidth(cur.idx()).zero()) {
+       case LFUN_NEWLINE_INSERT:
+               if ((tabular.isMultiColumn(cur.idx()) || 
tabular.isMultiRow(cur.idx()))
+                   && tabular.getPWidth(cur.idx()).zero()) {
                        status.setEnabled(false);
                        return true;
-               } else
-                       return cell(cur.idx())->getStatus(cur, cmd, status);
-       }
+               }
+               return cell(cur.idx())->getStatus(cur, cmd, status);
 
        case LFUN_NEWPAGE_INSERT:
                status.setEnabled(false);
@@ -5863,7 +5954,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                        // just multicol for one single cell
                        // check whether we are completely in a multicol
                        if (!tabular.isMultiColumn(cur.idx()))
-                               tabular.setMultiColumn(cur.idx(), 1,
+                               tabular.setMultiColumn(cur, cur.idx(), 1,
                                        tabular.rightLine(cur.idx()));
                        break;
                }
@@ -5872,7 +5963,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                idx_type const s_start = cur.selBegin().idx();
                row_type const col_start = tabular.cellColumn(s_start);
                row_type const col_end = tabular.cellColumn(cur.selEnd().idx());
-               cur.idx() = tabular.setMultiColumn(s_start, col_end - col_start 
+ 1,
+               cur.idx() = tabular.setMultiColumn(cur, s_start, col_end - 
col_start + 1,
                                                   
tabular.rightLine(cur.selEnd().idx()));
                cur.pit() = 0;
                cur.pos() = 0;
@@ -5918,7 +6009,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                        // just multirow for one single cell
                        // check whether we are completely in a multirow
                        if (!tabular.isMultiRow(cur.idx()))
-                               tabular.setMultiRow(cur.idx(), 1,
+                               tabular.setMultiRow(cur, cur.idx(), 1,
                                                    
tabular.bottomLine(cur.idx()),
                                                    
tabular.getAlignment(cur.idx()));
                        break;
@@ -5928,7 +6019,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                idx_type const s_start = cur.selBegin().idx();
                row_type const row_start = tabular.cellRow(s_start);
                row_type const row_end = tabular.cellRow(cur.selEnd().idx());
-               cur.idx() = tabular.setMultiRow(s_start, row_end - row_start + 
1,
+               cur.idx() = tabular.setMultiRow(cur, s_start, row_end - 
row_start + 1,
                                                
tabular.bottomLine(cur.selEnd().idx()),
                                                
tabular.getAlignment(cur.selEnd().idx()));
                cur.pit() = 0;
@@ -6141,7 +6232,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
        case Tabular::SET_LTCAPTION: {
                if (tabular.ltCaption(row))
                        break;
-               cur.idx() = tabular.setLTCaption(row, true);
+               cur.idx() = tabular.setLTCaption(cur, row, true);
                cur.pit() = 0;
                cur.pos() = 0;
                cur.selection(false);
@@ -6157,7 +6248,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
        case Tabular::UNSET_LTCAPTION: {
                if (!tabular.ltCaption(row))
                        break;
-               cur.idx() = tabular.setLTCaption(row, false);
+               cur.idx() = tabular.setLTCaption(cur, row, false);
                cur.pit() = 0;
                cur.pos() = 0;
                cur.selection(false);
@@ -6457,7 +6548,7 @@ bool InsetTabular::allowParagraphCustomization(idx_type 
cell) const
 
 bool InsetTabular::forcePlainLayout(idx_type cell) const
 {
-       return !tabular.getPWidth(cell).zero();
+       return tabular.isMultiColumn(cell) && !tabular.getPWidth(cell).zero();
 }
 
 
diff --git a/src/insets/InsetTabular.h b/src/insets/InsetTabular.h
index cd25c4e..b915181 100644
--- a/src/insets/InsetTabular.h
+++ b/src/insets/InsetTabular.h
@@ -63,6 +63,10 @@ public:
        ///
        void toggleFixedWidth(bool fw) { isFixedWidth = fw; }
        ///
+       void toggleMultiCol(bool m) { isMultiColumn = m; }
+       ///
+       void toggleMultiRow(bool m) { isMultiRow = m; }
+       ///
        void setContentAlignment(LyXAlignment al) {contentAlign = al; }
        /// writes the contents of the cell as a string, optionally
        /// descending into insets
@@ -72,14 +76,17 @@ public:
        ///
        void addToToc(DocIterator const & di, bool output_active,
                                  UpdateType utype, TocBackend & backend) const;
+       ///
+       void metrics(MetricsInfo &, Dimension &) const;
 private:
        /// unimplemented
        InsetTableCell();
        /// unimplemented
        void operator=(InsetTableCell const &);
        // FIXME
-       // This boolean is supposed to track whether the cell has had its
-       // width explicitly set. We need to know this to determine whether
+       // These booleans are supposed to track whether the cell has had its
+       // width explicitly set and whether it is part of a multicolumn, 
respectively.
+       // We need to know this to determine whether
        // layout changes and paragraph customization are allowed---that is,
        // we need it in forcePlainLayout() and allowParagraphCustomization().
        // Unfortunately, that information is not readily available in
@@ -102,6 +109,10 @@ private:
        // --rgh
        ///
        bool isFixedWidth;
+       ///
+       bool isMultiColumn;
+       ///
+       bool isMultiRow;
        // FIXME: Here the thoughts from the comment above also apply.
        ///
        LyXAlignment contentAlign;
@@ -120,11 +131,7 @@ private:
        /// Is the width forced to some value?
        bool hasFixedWidth() const { return isFixedWidth; }
        /// Can the cell contain several paragraphs?
-       /** FIXME this is wrong for multirows, that are limited to one
-        * paragraph. However, we cannot test for this (see the big
-        * comment above).
-        */
-       bool allowMultiPar() const { return isFixedWidth; }
+       bool allowMultiPar() const { return !isMultiRow && (!isMultiColumn || 
isFixedWidth); }
 };
 
 
@@ -534,7 +541,9 @@ public:
        ///
        bool hasVarwidthColumn() const;
        ///
-       idx_type setMultiColumn(idx_type cell, idx_type number,
+       bool isVTypeColumn(col_type cell) const;
+       ///
+       idx_type setMultiColumn(Cursor & cur, idx_type cell, idx_type number,
                             bool const right_border);
        ///
        void unsetMultiColumn(idx_type cell);
@@ -547,7 +556,7 @@ public:
        ///
        bool hasMultiRow(row_type r) const;
        ///
-       idx_type setMultiRow(idx_type cell, idx_type number,
+       idx_type setMultiRow(Cursor & cur, idx_type cell, idx_type number,
                             bool const bottom_border,
                             LyXAlignment const halign);
        ///
@@ -595,7 +604,7 @@ public:
        ///
        bool getLTNewPage(row_type row) const;
        ///
-       idx_type setLTCaption(row_type row, bool what);
+       idx_type setLTCaption(Cursor & cur, row_type row, bool what);
        ///
        bool ltCaption(row_type row) const;
        ///
@@ -804,7 +813,7 @@ public:
        ///
        idx_type rowSpan(idx_type cell) const;
        ///
-       BoxType useParbox(idx_type cell) const;
+       BoxType useBox(idx_type cell) const;
        ///
        // helper function for Latex
        ///
diff --git a/src/tex2lyx/TODO.txt b/src/tex2lyx/TODO.txt
index d55dae0..d93b5fa 100644
--- a/src/tex2lyx/TODO.txt
+++ b/src/tex2lyx/TODO.txt
@@ -59,6 +59,7 @@ Format LaTeX feature                        LyX feature
 546   Landscape support
       \begin{landscape}...\end{landscape}  \begin_inset Flex Landscape
       with longtable content:              <features rotate ="90"...>
+555   V column type (varwidth package)     Automatically detected with 
newlines, paragraph breaks and environment content in cells of rows
 
 
 
diff --git a/src/version.h b/src/version.h
index 1020e3e..ba838b4 100644
--- a/src/version.h
+++ b/src/version.h
@@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 554 // spitz: tabularx/xltabular
-#define LYX_FORMAT_TEX2LYX 554
+#define LYX_FORMAT_LYX 555 // spitz: varwidth V columns
+#define LYX_FORMAT_TEX2LYX 555
 
 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
 #ifndef _MSC_VER

Reply via email to