]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
remove old "logic"
[lyx.git] / src / insets / InsetTabular.cpp
index c3497de3d9259dd5e9a0db8c3abc43f2d346b807..2dcd1ff7fc4273a6f150846b884bad958d58f475 100644 (file)
@@ -101,87 +101,81 @@ boost::scoped_ptr<Tabular> paste_tabular;
 struct TabularFeature {
        Tabular::Feature action;
        string feature;
+       bool need_value;
 };
 
 
 TabularFeature tabularFeature[] =
 {
-       { Tabular::APPEND_ROW, "append-row" },
-       { Tabular::APPEND_COLUMN, "append-column" },
-       { Tabular::DELETE_ROW, "delete-row" },
-       { Tabular::DELETE_COLUMN, "delete-column" },
-       { Tabular::COPY_ROW, "copy-row" },
-       { Tabular::COPY_COLUMN, "copy-column" },
-       { Tabular::TOGGLE_LINE_TOP, "toggle-line-top" },
-       { Tabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom" },
-       { Tabular::TOGGLE_LINE_LEFT, "toggle-line-left" },
-       { Tabular::TOGGLE_LINE_RIGHT, "toggle-line-right" },
-       { Tabular::ALIGN_LEFT, "align-left" },
-       { Tabular::ALIGN_RIGHT, "align-right" },
-       { Tabular::ALIGN_CENTER, "align-center" },
-       { Tabular::ALIGN_BLOCK, "align-block" },
-       { Tabular::VALIGN_TOP, "valign-top" },
-       { Tabular::VALIGN_BOTTOM, "valign-bottom" },
-       { Tabular::VALIGN_MIDDLE, "valign-middle" },
-       { Tabular::M_ALIGN_LEFT, "m-align-left" },
-       { Tabular::M_ALIGN_RIGHT, "m-align-right" },
-       { Tabular::M_ALIGN_CENTER, "m-align-center" },
-       { Tabular::M_VALIGN_TOP, "m-valign-top" },
-       { Tabular::M_VALIGN_BOTTOM, "m-valign-bottom" },
-       { Tabular::M_VALIGN_MIDDLE, "m-valign-middle" },
-       { Tabular::MULTICOLUMN, "multicolumn" },
-       { Tabular::MULTIROW, "multirow" },
-       { Tabular::SET_ALL_LINES, "set-all-lines" },
-       { Tabular::UNSET_ALL_LINES, "unset-all-lines" },
-       { Tabular::SET_LONGTABULAR, "set-longtabular" },
-       { Tabular::UNSET_LONGTABULAR, "unset-longtabular" },
-       { Tabular::SET_PWIDTH, "set-pwidth" },
-       { Tabular::SET_MPWIDTH, "set-mpwidth" },
-       { Tabular::SET_ROTATE_TABULAR, "set-rotate-tabular" },
-       { Tabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular" },
-       { Tabular::TOGGLE_ROTATE_TABULAR, "toggle-rotate-tabular" },
-       { Tabular::SET_ROTATE_CELL, "set-rotate-cell" },
-       { Tabular::UNSET_ROTATE_CELL, "unset-rotate-cell" },
-       { Tabular::TOGGLE_ROTATE_CELL, "toggle-rotate-cell" },
-       { Tabular::SET_USEBOX, "set-usebox" },
-       { Tabular::SET_LTHEAD, "set-lthead" },
-       { Tabular::UNSET_LTHEAD, "unset-lthead" },
-       { Tabular::SET_LTFIRSTHEAD, "set-ltfirsthead" },
-       { Tabular::UNSET_LTFIRSTHEAD, "unset-ltfirsthead" },
-       { Tabular::SET_LTFOOT, "set-ltfoot" },
-       { Tabular::UNSET_LTFOOT, "unset-ltfoot" },
-       { Tabular::SET_LTLASTFOOT, "set-ltlastfoot" },
-       { Tabular::UNSET_LTLASTFOOT, "unset-ltlastfoot" },
-       { Tabular::SET_LTNEWPAGE, "set-ltnewpage" },
-       { Tabular::TOGGLE_LTCAPTION, "toggle-ltcaption" },
-       { Tabular::SET_SPECIAL_COLUMN, "set-special-column" },
-       { Tabular::SET_SPECIAL_MULTICOLUMN, "set-special-multicolumn" },
-       { Tabular::SET_SPECIAL_MULTIROW, "set-special-multirow" },
-       { Tabular::SET_BOOKTABS, "set-booktabs" },
-       { Tabular::UNSET_BOOKTABS, "unset-booktabs" },
-       { Tabular::SET_TOP_SPACE, "set-top-space" },
-       { Tabular::SET_BOTTOM_SPACE, "set-bottom-space" },
-       { Tabular::SET_INTERLINE_SPACE, "set-interline-space" },
-       { Tabular::SET_BORDER_LINES, "set-border-lines" },
-       { Tabular::TABULAR_VALIGN_TOP, "tabular-valign-top"},
-       { Tabular::TABULAR_VALIGN_MIDDLE, "tabular-valign-middle"},
-       { Tabular::TABULAR_VALIGN_BOTTOM, "tabular-valign-bottom"},
-       { Tabular::LONGTABULAR_ALIGN_LEFT, "longtabular-align-left" },
-       { Tabular::LONGTABULAR_ALIGN_CENTER, "longtabular-align-center" },
-       { Tabular::LONGTABULAR_ALIGN_RIGHT, "longtabular-align-right" },        
-       { Tabular::LAST_ACTION, "" }
-};
-
-
-class FeatureEqual : public unary_function<TabularFeature, bool> {
-public:
-       FeatureEqual(Tabular::Feature feature)
-               : feature_(feature) {}
-       bool operator()(TabularFeature const & tf) const {
-               return tf.action == feature_;
-       }
-private:
-       Tabular::Feature feature_;
+       { Tabular::APPEND_ROW, "append-row", false },
+       { Tabular::APPEND_COLUMN, "append-column", false },
+       { Tabular::DELETE_ROW, "delete-row", false },
+       { Tabular::DELETE_COLUMN, "delete-column", false },
+       { Tabular::COPY_ROW, "copy-row", false },
+       { Tabular::COPY_COLUMN, "copy-column", false },
+       { Tabular::SET_LINE_TOP, "set-line-top", true },
+       { Tabular::SET_LINE_BOTTOM, "set-line-bottom", true },
+       { Tabular::SET_LINE_LEFT, "set-line-left", true },
+       { Tabular::SET_LINE_RIGHT, "set-line-right", true },
+       //FIXME: get rid of those 4 TOGGLE actions in favor of the 4 above.
+       { Tabular::TOGGLE_LINE_TOP, "toggle-line-top", false },
+       { Tabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom", false },
+       { Tabular::TOGGLE_LINE_LEFT, "toggle-line-left", false },
+       { Tabular::TOGGLE_LINE_RIGHT, "toggle-line-right", false },
+       { Tabular::ALIGN_LEFT, "align-left", false },
+       { Tabular::ALIGN_RIGHT, "align-right", false },
+       { Tabular::ALIGN_CENTER, "align-center", false },
+       { Tabular::ALIGN_BLOCK, "align-block", false },
+       { Tabular::VALIGN_TOP, "valign-top", false },
+       { Tabular::VALIGN_BOTTOM, "valign-bottom", false },
+       { Tabular::VALIGN_MIDDLE, "valign-middle", false },
+       { Tabular::M_ALIGN_LEFT, "m-align-left", false },
+       { Tabular::M_ALIGN_RIGHT, "m-align-right", false },
+       { Tabular::M_ALIGN_CENTER, "m-align-center", false },
+       { Tabular::M_VALIGN_TOP, "m-valign-top", false },
+       { Tabular::M_VALIGN_BOTTOM, "m-valign-bottom", false },
+       { Tabular::M_VALIGN_MIDDLE, "m-valign-middle", false },
+       { Tabular::MULTICOLUMN, "multicolumn", false },
+       { Tabular::MULTIROW, "multirow", false },
+       { Tabular::SET_ALL_LINES, "set-all-lines", false },
+       { Tabular::UNSET_ALL_LINES, "unset-all-lines", false },
+       { Tabular::SET_LONGTABULAR, "set-longtabular", false },
+       { Tabular::UNSET_LONGTABULAR, "unset-longtabular", false },
+       { Tabular::SET_PWIDTH, "set-pwidth", true },
+       { Tabular::SET_MPWIDTH, "set-mpwidth", true },
+       { Tabular::SET_ROTATE_TABULAR, "set-rotate-tabular", false },
+       { Tabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular", false },
+       { Tabular::TOGGLE_ROTATE_TABULAR, "toggle-rotate-tabular", false },
+       { Tabular::SET_ROTATE_CELL, "set-rotate-cell", false },
+       { Tabular::UNSET_ROTATE_CELL, "unset-rotate-cell", false },
+       { Tabular::TOGGLE_ROTATE_CELL, "toggle-rotate-cell", false },
+       { Tabular::SET_USEBOX, "set-usebox", true },
+       { Tabular::SET_LTHEAD, "set-lthead", true },
+       { Tabular::UNSET_LTHEAD, "unset-lthead", true },
+       { Tabular::SET_LTFIRSTHEAD, "set-ltfirsthead", true },
+       { Tabular::UNSET_LTFIRSTHEAD, "unset-ltfirsthead", true },
+       { Tabular::SET_LTFOOT, "set-ltfoot", true },
+       { Tabular::UNSET_LTFOOT, "unset-ltfoot", true },
+       { Tabular::SET_LTLASTFOOT, "set-ltlastfoot", true },
+       { Tabular::UNSET_LTLASTFOOT, "unset-ltlastfoot", true },
+       { Tabular::SET_LTNEWPAGE, "set-ltnewpage", false },
+       { Tabular::TOGGLE_LTCAPTION, "toggle-ltcaption", false },
+       { Tabular::SET_SPECIAL_COLUMN, "set-special-column", true },
+       { Tabular::SET_SPECIAL_MULTICOLUMN, "set-special-multicolumn", true },
+       { Tabular::SET_SPECIAL_MULTIROW, "set-special-multirow", false },
+       { Tabular::SET_BOOKTABS, "set-booktabs", false },
+       { Tabular::UNSET_BOOKTABS, "unset-booktabs", false },
+       { Tabular::SET_TOP_SPACE, "set-top-space", true },
+       { Tabular::SET_BOTTOM_SPACE, "set-bottom-space", true },
+       { Tabular::SET_INTERLINE_SPACE, "set-interline-space", true },
+       { Tabular::SET_BORDER_LINES, "set-border-lines", false },
+       { Tabular::TABULAR_VALIGN_TOP, "tabular-valign-top", false},
+       { Tabular::TABULAR_VALIGN_MIDDLE, "tabular-valign-middle", false},
+       { Tabular::TABULAR_VALIGN_BOTTOM, "tabular-valign-bottom", false},
+       { Tabular::LONGTABULAR_ALIGN_LEFT, "longtabular-align-left", false },
+       { Tabular::LONGTABULAR_ALIGN_CENTER, "longtabular-align-center", false },
+       { Tabular::LONGTABULAR_ALIGN_RIGHT, "longtabular-align-right", false },
+       { Tabular::LAST_ACTION, "", false }
 };
 
 
@@ -499,13 +493,13 @@ void l_getline(istream & is, string & str)
 } // namespace
 
 
-string const featureAsString(Tabular::Feature feature)
+string const featureAsString(Tabular::Feature action)
 {
-       TabularFeature * end = tabularFeature +
-               sizeof(tabularFeature) / sizeof(TabularFeature);
-       TabularFeature * it = find_if(tabularFeature, end,
-                                          FeatureEqual(feature));
-       return (it == end) ? string() : it->feature;
+       for (size_t i = 0; i != Tabular::LAST_ACTION; ++i) {
+               if (tabularFeature[i].action == action)
+                       return tabularFeature[i].feature;
+       }
+       return string();
 }
 
 
@@ -835,9 +829,8 @@ void Tabular::updateIndexes()
 }
 
 
-Tabular::idx_type Tabular::numberOfCellsInRow(idx_type const cell) const
+Tabular::idx_type Tabular::numberOfCellsInRow(row_type const row) const
 {
-       row_type const row = cellRow(cell);
        idx_type result = 0;
        for (col_type i = 0; i < column_info.size(); ++i)
                if (cell_info[row][i].multicolumn != Tabular::CELL_PART_OF_MULTICOLUMN)
@@ -874,32 +867,6 @@ bool Tabular::rightLine(idx_type cell) const
 }
 
 
-bool Tabular::topAlreadyDrawn(idx_type cell) const
-{
-       row_type const row = cellRow(cell);
-       if (row == 0)
-               return false;
-       
-       return !rowTopLine(row) && bottomLine(cellAbove(cell));
-}
-
-
-bool Tabular::leftAlreadyDrawn(idx_type cell) const
-{
-       col_type col = cellColumn(cell);
-       if (col == 0)
-               return false;
-       idx_type i = cellIndex(cellRow(cell), col - 1);
-       return rightLine(i) && !leftLine(cell);
-}
-
-
-bool Tabular::isLastRow(idx_type cell) const
-{
-       return cellRow(cell) == row_info.size() - 1;
-}
-
-
 int Tabular::interRowSpace(row_type row) const
 {
        if (!row || row >= row_info.size())
@@ -1068,6 +1035,11 @@ void Tabular::setColumnPWidth(Cursor & cur, idx_type cell,
        col_type const j = cellColumn(cell);
 
        column_info[j].p_width = width;
+       // reset the vertical alignment to top if the fixed with
+       // is removed or zero because only fixed width columns can
+       // have a vertical alignment
+       if (column_info[j].p_width.zero())
+               column_info[j].valignment = LYX_VALIGN_TOP;
        for (row_type i = 0; i < row_info.size(); ++i) {
                idx_type const cell = cellIndex(i, j);
                // because of multicolumns
@@ -1128,15 +1100,6 @@ void Tabular::setAlignSpecial(idx_type cell, docstring const & special,
 }
 
 
-void Tabular::setAllLines(idx_type cell, bool line)
-{
-       setTopLine(cell, line);
-       setBottomLine(cell, line);
-       setRightLine(cell, line);
-       setLeftLine(cell, line);
-}
-
-
 void Tabular::setTopLine(idx_type i, bool line)
 {
        cellInfo(i).top_line = line;
@@ -1303,28 +1266,19 @@ int Tabular::textVOffset(idx_type cell) const
 
 Tabular::idx_type Tabular::getFirstCellInRow(row_type row) const
 {
-       if (row > row_info.size() - 1)
-               row = row_info.size() - 1;
-
        col_type c = 0;
        while (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW)
                ++c;
-
-       return cell_info[row][0].cellno;
-}
-
-
-bool Tabular::isLastCellInRow(idx_type cell) const
-{
-       return cellRightColumn(cell) == column_info.size() - 1;
+       return cell_info[row][c].cellno;
 }
 
 
 Tabular::idx_type Tabular::getLastCellInRow(row_type row) const
 {
-       if (row > row_info.size() - 1)
-               row = row_info.size() - 1;
-       return cell_info[row][column_info.size() - 1].cellno;
+       col_type c = column_info.size() - 1;
+       while (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW)
+               --c;
+       return cell_info[row][c].cellno;
 }
 
 
@@ -1348,17 +1302,6 @@ Tabular::col_type Tabular::cellColumn(idx_type cell) const
 }
 
 
-Tabular::col_type Tabular::cellRightColumn(idx_type cell) const
-{
-       row_type const row = cellRow(cell);
-       col_type column = cellColumn(cell);
-       while (column < column_info.size() - 1 &&
-                  cell_info[row][column + 1].multicolumn == CELL_PART_OF_MULTICOLUMN)
-               ++column;
-       return column;
-}
-
-
 void Tabular::write(ostream & os) const
 {
        // header line
@@ -1570,19 +1513,8 @@ void Tabular::read(Lexer & lex)
 
 bool Tabular::isMultiColumn(idx_type cell) const
 {
-       if (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN
-               || cellInfo(cell).multicolumn == CELL_PART_OF_MULTICOLUMN)
-               return true;
-       else
-               return false;
-}
-
-
-bool Tabular::isMultiColumnReal(idx_type cell) const
-{
-       return cellColumn(cell) != cellRightColumn(cell) &&
-               (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN
-                || cellInfo(cell).multicolumn == CELL_PART_OF_MULTICOLUMN);
+       return (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN 
+               || cellInfo(cell).multicolumn == CELL_PART_OF_MULTICOLUMN);
 }
 
 
@@ -1594,10 +1526,16 @@ Tabular::CellData & Tabular::cellInfo(idx_type cell) const
 
 void Tabular::setMultiColumn(idx_type cell, idx_type number)
 {
+       idx_type const col = cellColumn(cell);
+       idx_type const row = cellRow(cell);
+       for (idx_type i = 0; i < number; ++i)
+               unsetMultiRow(cellIndex(row, col + i));
+
        CellData & cs = cellInfo(cell);
        cs.multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
        cs.alignment = column_info[cellColumn(cell)].alignment;
        setRightLine(cell, rightLine(cell + number - 1));
+
        for (idx_type i = 1; i < number; ++i) {
                CellData & cs1 = cellInfo(cell + i);
                cs1.multicolumn = CELL_PART_OF_MULTICOLUMN;
@@ -1617,9 +1555,12 @@ bool Tabular::isMultiRow(idx_type cell) const
 
 void Tabular::setMultiRow(idx_type cell, idx_type number)
 {
-       idx_type const column = cellColumn(cell);
-       idx_type row = cellRow(cell);
-       idx_type const ncolumns = column_info.size();
+       idx_type const col = cellColumn(cell);
+       idx_type const row = cellRow(cell);
+       for (idx_type i = 0; i < number; ++i)
+               unsetMultiColumn(cellIndex(row + i, col));
+
+       idx_type const ncols = column_info.size();
        CellData & cs = cellInfo(cell);
        cs.multirow = CELL_BEGIN_OF_MULTIROW;
        // FIXME: the horizontal alignment can only be changed for
@@ -1627,9 +1568,10 @@ void Tabular::setMultiRow(idx_type cell, idx_type number)
        // assigning this to uwestoehr
        cs.valignment = LYX_VALIGN_MIDDLE;
        // set the bottom row of the last selected cell
-       setBottomLine(cell, bottomLine(cell + (number - 1)*ncolumns));
+       setBottomLine(cell, bottomLine(cell + (number - 1)*ncols));
+
        for (idx_type i = 1; i < number; ++i) {
-               CellData & cs1 = cell_info[row + i][column];
+               CellData & cs1 = cell_info[row + i][col];
                cs1.multirow = CELL_PART_OF_MULTIROW;
                cs.inset->appendParagraphs(cs1.inset->paragraphs());
                cs1.inset->clear();
@@ -1654,7 +1596,6 @@ Tabular::idx_type Tabular::rowSpan(idx_type cell) const
 {
        row_type const nrows = row_info.size();
        col_type const column = cellColumn(cell);
-       idx_type result = 1;
        col_type row = cellRow(cell) + 1;
        while (row < nrows && isPartOfMultiRow(row, column))
                ++row;
@@ -1665,22 +1606,28 @@ Tabular::idx_type Tabular::rowSpan(idx_type cell) const
 
 void Tabular::unsetMultiColumn(idx_type cell)
 {
+       if (!isMultiColumn(cell))
+               return;
+
        row_type const row = cellRow(cell);
-       col_type const column = cellColumn(cell);
+       col_type const col = cellColumn(cell);
        row_type const span = columnSpan(cell);
        for (col_type c = 0; c < span; ++c)
-               cell_info[row][column + c].multicolumn = CELL_NORMAL;
+               cell_info[row][col + c].multicolumn = CELL_NORMAL;
        updateIndexes();
 }
 
 
 void Tabular::unsetMultiRow(idx_type cell)
 {
+       if (!isMultiRow(cell))
+               return;
+
        row_type const row = cellRow(cell);
-       col_type const column = cellColumn(cell);
+       col_type const col = cellColumn(cell);
        row_type const span = rowSpan(cell);
        for (row_type r = 0; r < span; ++r)
-               cell_info[row + r][column].multirow = CELL_NORMAL;
+               cell_info[row + r][col].multirow = CELL_NORMAL;
        updateIndexes();
 }
 
@@ -1888,7 +1835,7 @@ Tabular::idx_type Tabular::setLTCaption(row_type row, bool what)
 {
        idx_type i = getFirstCellInRow(row);
        if (what) {
-               setMultiColumn(i, numberOfCellsInRow(i));
+               setMultiColumn(i, numberOfCellsInRow(row));
                setTopLine(i, false);
                setBottomLine(i, false);
                setLeftLine(i, false);
@@ -2441,7 +2388,7 @@ int Tabular::TeXRow(odocstream & os, row_type i,
                        os << '}';
 
                ret += TeXCellPostamble(os, cell, ismulticol, ismultirow);
-               if (!isLastCellInRow(cell)) { // not last cell in row
+               if (cell != getLastCellInRow(i)) { // not last cell in row
                        os << " & ";
                }
        }
@@ -2842,7 +2789,7 @@ bool Tabular::plaintextTopHLine(odocstream & os, row_type row,
                                   vector<unsigned int> const & clen) const
 {
        idx_type const fcell = getFirstCellInRow(row);
-       idx_type const n = numberOfCellsInRow(fcell) + fcell;
+       idx_type const n = numberOfCellsInRow(row) + fcell;
        idx_type tmp = 0;
 
        for (idx_type i = fcell; i < n; ++i) {
@@ -2890,7 +2837,7 @@ bool Tabular::plaintextBottomHLine(odocstream & os, row_type row,
                                      vector<unsigned int> const & clen) const
 {
        idx_type const fcell = getFirstCellInRow(row);
-       idx_type const n = numberOfCellsInRow(fcell) + fcell;
+       idx_type const n = numberOfCellsInRow(row) + fcell;
        idx_type tmp = 0;
 
        for (idx_type i = fcell; i < n; ++i) {
@@ -2993,12 +2940,12 @@ void Tabular::plaintext(odocstream & os,
        vector<unsigned int> clen(column_info.size());
 
        if (!onlydata) {
-               // first all non (real) multicolumn cells!
+               // first all non multicolumn cells!
                for (col_type j = 0; j < column_info.size(); ++j) {
                        clen[j] = 0;
                        for (row_type i = 0; i < row_info.size(); ++i) {
                                idx_type cell = cellIndex(i, j);
-                               if (isMultiColumnReal(cell))
+                               if (isMultiColumn(cell))
                                        continue;
                                odocstringstream sstr;
                                cellInset(cell)->plaintext(sstr, runparams);
@@ -3006,11 +2953,11 @@ void Tabular::plaintext(odocstream & os,
                                        clen[j] = sstr.str().length();
                        }
                }
-               // then all (real) multicolumn cells!
+               // then all multicolumn cells!
                for (col_type j = 0; j < column_info.size(); ++j) {
                        for (row_type i = 0; i < row_info.size(); ++i) {
                                idx_type cell = cellIndex(i, j);
-                               if (!isMultiColumnReal(cell) || isPartOfMultiColumn(i, j))
+                               if (cell_info[i][j].multicolumn != CELL_BEGIN_OF_MULTICOLUMN)
                                        continue;
                                odocstringstream sstr;
                                cellInset(cell)->plaintext(sstr, runparams);
@@ -3477,7 +3424,10 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int y,
                onoffcol = change.color();
        }
 
-       if (!tabular.topAlreadyDrawn(cell)) {
+       bool topalreadydrawn = row > 0 && !tabular.rowTopLine(row) 
+               && tabular.bottomLine(tabular.cellAbove(cell));
+
+       if (!topalreadydrawn) {
                on_off = !tabular.topLine(cell);
                pain.line(x, y, x + w, y,
                        on_off ? onoffcol : col,
@@ -3487,7 +3437,12 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int y,
        pain.line(x, y + h, x + w, y + h,
                on_off ? onoffcol : col,
                on_off ? Painter::line_onoffdash : Painter::line_solid);
-       if (!tabular.leftAlreadyDrawn(cell)) {
+
+       col_type const column = tabular.cellColumn(cell);
+       bool leftalreadydrawn = column > 0  && !tabular.leftLine(cell)
+               && tabular.rightLine(tabular.cellIndex(row, column - 1));
+
+       if (!leftalreadydrawn) {
                on_off = !tabular.leftLine(cell);
                pain.line(x, y, x, y + h,
                        on_off ? onoffcol : col,
@@ -3529,7 +3484,7 @@ void InsetTabular::edit(Cursor & cur, bool front, EntryDirection)
 }
 
 
-void InsetTabular::updateLabels(ParIterator const & it, UpdateType utype)
+void InsetTabular::updateBuffer(ParIterator const & it, UpdateType utype)
 {
        // In a longtable, tell captions what the current float is
        Counters & cnts = buffer().masterBuffer()->params().documentClass().counters();
@@ -3541,7 +3496,7 @@ void InsetTabular::updateLabels(ParIterator const & it, UpdateType utype)
        it2.forwardPos();
        size_t const end = it2.nargs();
        for ( ; it2.idx() < end; it2.top().forwardIdx())
-               buffer().updateLabels(it2, utype);
+               buffer().updateBuffer(it2, utype);
 
        //reset afterwards
        if (tabular.is_long_tabular)
@@ -3869,14 +3824,10 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 //     }
 
        case LFUN_LAYOUT_TABULAR:
-               cur.bv().showDialog("tabular", params2string(*this), this);
-               break;
-
-       case LFUN_INSET_DIALOG_UPDATE:
-               cur.bv().updateDialog("tabular", params2string(*this));
+               cur.bv().showDialog("tabular");
                break;
 
-       case LFUN_TABULAR_FEATURE:
+       case LFUN_INSET_MODIFY:
                if (!tabularFeatures(cur, to_utf8(cmd.argument())))
                        cur.undispatched();
                break;
@@ -4043,12 +3994,22 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        FuncStatus & status) const
 {
        switch (cmd.action) {
-       case LFUN_TABULAR_FEATURE: {
+       case LFUN_INSET_MODIFY: {
+               istringstream is(to_utf8(cmd.argument()));
+               string s;
+               is >> s;
+               if (insetCode(s) != TABULAR_CODE) {
+                       status.clear();
+                       status.setEnabled(false);
+                       break;
+               }
+               is >> s;
+               // FIXME: We only check for the very first argument...
                int action = Tabular::LAST_ACTION;
                int i = 0;
                for (; tabularFeature[i].action != Tabular::LAST_ACTION; ++i) {
                        string const tmp = tabularFeature[i].feature;
-                       if (tmp == to_utf8(cmd.argument()).substr(0, tmp.length())) {
+                       if (tmp == s.substr(0, tmp.length())) {
                                action = tabularFeature[i].action;
                                break;
                        }
@@ -4060,7 +4021,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                }
 
                string const argument
-                       = ltrim(to_utf8(cmd.argument()).substr(tabularFeature[i].feature.length()));
+                       = ltrim(s.substr(tabularFeature[i].feature.length()));
 
                row_type sel_row_start = 0;
                row_type sel_row_end = 0;
@@ -4111,6 +4072,13 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx())));
                        break;
 
+               case Tabular::SET_LINE_TOP:
+               case Tabular::SET_LINE_BOTTOM:
+               case Tabular::SET_LINE_LEFT:
+               case Tabular::SET_LINE_RIGHT:
+                       status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx())));
+                       break;
+
                case Tabular::TOGGLE_LINE_TOP:
                        status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx())));
                        status.setOnOff(tabular.topLine(cur.idx()));
@@ -4157,6 +4125,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                case Tabular::M_VALIGN_TOP:
                        flag = false;
                case Tabular::VALIGN_TOP:
+                       status.setEnabled(!tabular.getPWidth(cur.idx()).zero());
                        status.setOnOff(
                                tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_TOP);
                        break;
@@ -4164,6 +4133,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                case Tabular::M_VALIGN_BOTTOM:
                        flag = false;
                case Tabular::VALIGN_BOTTOM:
+                       status.setEnabled(!tabular.getPWidth(cur.idx()).zero());
                        status.setOnOff(
                                tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_BOTTOM);
                        break;
@@ -4171,6 +4141,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                case Tabular::M_VALIGN_MIDDLE:
                        flag = false;
                case Tabular::VALIGN_MIDDLE:
+                       status.setEnabled(!tabular.getPWidth(cur.idx()).zero());
                        status.setOnOff(
                                tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_MIDDLE);
                        break;
@@ -4280,6 +4251,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        break;
 
                // only one row can be the caption
+               // and a multirow cannot be set as caption
                case Tabular::TOGGLE_LTCAPTION:
                        status.setEnabled(sel_row_start == sel_row_end
                                && !tabular.getRowOfLTFirstHead(sel_row_start, dummyltt)
@@ -4287,7 +4259,8 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                                && !tabular.getRowOfLTFoot(sel_row_start, dummyltt)
                                && !tabular.getRowOfLTLastFoot(sel_row_start, dummyltt)
                                && (!tabular.haveLTCaption()
-                                       || tabular.ltCaption(sel_row_start)));
+                                       || tabular.ltCaption(sel_row_start))
+                               && !tabular.isMultiRow(sel_row_start));
                        status.setOnOff(tabular.ltCaption(sel_row_start));
                        break;
 
@@ -4376,17 +4349,11 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                // relay this lfun to Inset, not to the cell.
                return Inset::getStatus(cur, cmd, status);
 
-       case LFUN_INSET_MODIFY:
-               if (insetCode(cmd.getArg(0)) == TABULAR_CODE) {
-                       status.setEnabled(true);
-                       return true;
-               }
-               // Fall through
-
        default:
                // we try to handle this event in the insets dispatch function.
                return cell(cur.idx())->getStatus(cur, cmd, status);
        }
+       return false;
 }
 
 
@@ -4647,7 +4614,7 @@ void InsetTabular::moveNextCell(Cursor & cur, EntryDirection entry_from)
        } else {
                if (tabular.isLastCell(cur.idx()))
                        return;
-               if (tabular.isLastCellInRow(cur.idx()))
+               if (cur.idx() == tabular.getLastCellInRow(row))
                        cur.idx() = tabular.cellIndex(row + 1, 0);
                else
                        cur.idx() = tabular.cellIndex(row, col + 1);
@@ -4691,7 +4658,7 @@ void InsetTabular::movePrevCell(Cursor & cur, EntryDirection entry_from)
        col_type const col = tabular.cellColumn(cur.idx());
 
        if (isRightToLeft(cur)) {
-               if (tabular.isLastCellInRow(cur.idx())) {
+               if (cur.idx() == tabular.getLastCellInRow(row)) {
                        if (row == 0)
                                return;
                        cur.idx() = tabular.getFirstCellInRow(row);
@@ -4699,7 +4666,7 @@ void InsetTabular::movePrevCell(Cursor & cur, EntryDirection entry_from)
                } else {
                        if (tabular.isLastCell(cur.idx()))
                                return;
-                       if (tabular.isLastCellInRow(cur.idx()))
+                       if (cur.idx() == tabular.getLastCellInRow(row))
                                cur.idx() = tabular.cellIndex(row + 1, 0);
                        else
                                cur.idx() = tabular.cellIndex(row, col + 1);
@@ -4743,27 +4710,45 @@ void InsetTabular::movePrevCell(Cursor & cur, EntryDirection entry_from)
 }
 
 
-bool InsetTabular::tabularFeatures(Cursor & cur, string const & what)
+bool InsetTabular::tabularFeatures(Cursor & cur, string const & argument)
 {
-       Tabular::Feature action = Tabular::LAST_ACTION;
+       istringstream is(argument);
+       string s;
+       is >> s;
+       if (insetCode(s) != TABULAR_CODE)
+               return false;
 
-       int i = 0;
-       for (; tabularFeature[i].action != Tabular::LAST_ACTION; ++i) {
-               string const tmp = tabularFeature[i].feature;
+       // Safe guard.
+       size_t safe_guard = 0;
+       for (;;) {
+               if (is.eof())
+                       break;
+               safe_guard++;
+               if (safe_guard > 1000) {
+                       LYXERR0("parameter max count reached!");
+                       break;
+               }
+               is >> s;
+               Tabular::Feature action = Tabular::LAST_ACTION;
+
+               size_t i = 0;
+               for (; tabularFeature[i].action != Tabular::LAST_ACTION; ++i) {
+                       if (s != tabularFeature[i].feature)
+                               continue;
 
-               if (tmp == what.substr(0, tmp.length())) {
-                       //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
-                       //tabularFeatures[i].feature.length()))
                        action = tabularFeature[i].action;
                        break;
                }
+               if (action == Tabular::LAST_ACTION) {
+                       LYXERR0("Feature not found " << s);
+                       continue;
+               }
+               string val;
+               if (tabularFeature[i].need_value)
+                       is >> val;
+               LYXERR(Debug::DEBUG, "Feature: " << s << "\t\tvalue: " << val);
+               tabularFeatures(cur, action, val);
        }
-       if (action == Tabular::LAST_ACTION)
-               return false;
-
-       string const val =
-               ltrim(what.substr(tabularFeature[i].feature.length()));
-       tabularFeatures(cur, action, val);
        return true;
 }
 
@@ -4877,7 +4862,14 @@ void InsetTabular::tabularFeatures(Cursor & cur,
 
        case Tabular::SET_SPECIAL_COLUMN:
        case Tabular::SET_SPECIAL_MULTICOLUMN:
-               tabular.setAlignSpecial(cur.idx(), from_utf8(value), feature);
+               if (value == "none")
+                       tabular.setAlignSpecial(cur.idx(), docstring(), feature);
+               else
+                       tabular.setAlignSpecial(cur.idx(), from_utf8(value), feature);
+               break;
+
+       case Tabular::SET_SPECIAL_MULTIROW:
+               //FIXME: noting to do here?
                break;
 
        case Tabular::APPEND_ROW:
@@ -4922,32 +4914,40 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                cur.idx() = tabular.cellIndex(row, column);
                break;
 
+       case Tabular::SET_LINE_TOP:
        case Tabular::TOGGLE_LINE_TOP: {
-               bool lineSet = !tabular.topLine(cur.idx());
+               bool lineSet = (feature == Tabular::SET_LINE_TOP)
+                              ? (value == "true") : !tabular.topLine(cur.idx());
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setTopLine(tabular.cellIndex(i, j), lineSet);
                break;
        }
 
+       case Tabular::SET_LINE_BOTTOM:
        case Tabular::TOGGLE_LINE_BOTTOM: {
-               bool lineSet = !tabular.bottomLine(cur.idx());
+               bool lineSet = (feature == Tabular::SET_LINE_BOTTOM)
+                              ? (value == "true") : !tabular.bottomLine(cur.idx());
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setBottomLine(tabular.cellIndex(i, j), lineSet);
                break;
        }
 
+       case Tabular::SET_LINE_LEFT:
        case Tabular::TOGGLE_LINE_LEFT: {
-               bool lineSet = !tabular.leftLine(cur.idx());
+               bool lineSet = (feature == Tabular::SET_LINE_LEFT)
+                              ? (value == "true") : !tabular.leftLine(cur.idx());
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setLeftLine(tabular.cellIndex(i, j), lineSet);
                break;
        }
 
+       case Tabular::SET_LINE_RIGHT:
        case Tabular::TOGGLE_LINE_RIGHT: {
-               bool lineSet = !tabular.rightLine(cur.idx());
+               bool lineSet = (feature == Tabular::SET_LINE_RIGHT)
+                              ? (value == "true") : !tabular.rightLine(cur.idx());
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setRightLine(tabular.cellIndex(i, j), lineSet);
@@ -4992,9 +4992,9 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                // we have a selection so this means we just add all this
                // cells to form a multicolumn cell
                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());
-               tabular.setMultiRow(s_start, row_end - row_start + 1);
+               row_type const col_start = tabular.cellColumn(s_start);
+               row_type const col_end = tabular.cellColumn(cur.selEnd().idx());
+               tabular.setMultiColumn(s_start, col_end - col_start + 1);
                cur.idx() = s_start;
                cur.pit() = 0;
                cur.pos() = 0;
@@ -5015,12 +5015,9 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                // we have a selection so this means we just add all this
                // cells to form a multirow cell
                idx_type const s_start = cur.selBegin().idx();
-               idx_type const s_end = cur.selEnd().idx();
-               // the cell index is counted from left to right, we therefore
-               // need to know the number of columns of the table to calculate
-               // the number of selected rows
-               idx_type const ncolumns = tabular.column_info.size();
-               tabular.setMultiRow(s_start, (s_end - s_start)/ncolumns + 1);
+               row_type const row_start = tabular.cellRow(s_start);
+               row_type const row_end = tabular.cellRow(cur.selEnd().idx());
+               tabular.setMultiRow(s_start, row_end - row_start + 1);
                cur.idx() = s_start;
                cur.pit() = 0;
                cur.pos() = 0;
@@ -5032,9 +5029,13 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                setLines = true;
        case Tabular::UNSET_ALL_LINES:
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
-                       for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-                               tabular.setAllLines(
-                                       tabular.cellIndex(i,j), setLines);
+                       for (col_type j = sel_col_start; j <= sel_col_end; ++j) {
+                               idx_type const cell = tabular.cellIndex(i,j);
+                               tabular.setTopLine(cell, setLines);
+                               tabular.setBottomLine(cell, setLines);
+                               tabular.setRightLine(cell, setLines);
+                               tabular.setLeftLine(cell, setLines);
+                       }
                break;
 
        case Tabular::SET_BORDER_LINES:
@@ -5206,12 +5207,12 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                if (value == "default")
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                                tabular.row_info[i].top_space_default = true;
-               else if (isValidLength(value, &len))
+               else if (value == "none")
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i) {
                                tabular.row_info[i].top_space_default = false;
                                tabular.row_info[i].top_space = len;
                        }
-               else
+               else if (isValidLength(value, &len))
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i) {
                                tabular.row_info[i].top_space_default = false;
                                tabular.row_info[i].top_space = len;
@@ -5224,12 +5225,12 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                if (value == "default")
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                                tabular.row_info[i].bottom_space_default = true;
-               else if (isValidLength(value, &len))
+               else if (value == "none")
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i) {
                                tabular.row_info[i].bottom_space_default = false;
                                tabular.row_info[i].bottom_space = len;
                        }
-               else
+               else if (isValidLength(value, &len))
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i) {
                                tabular.row_info[i].bottom_space_default = false;
                                tabular.row_info[i].bottom_space = len;
@@ -5242,12 +5243,12 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                if (value == "default")
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                                tabular.row_info[i].interline_space_default = true;
-               else if (isValidLength(value, &len))
+               else if (value == "none")
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i) {
                                tabular.row_info[i].interline_space_default = false;
                                tabular.row_info[i].interline_space = len;
                        }
-               else
+               else if (isValidLength(value, &len))
                        for (row_type i = sel_row_start; i <= sel_row_end; ++i) {
                                tabular.row_info[i].interline_space_default = false;
                                tabular.row_info[i].interline_space = len;
@@ -5262,21 +5263,6 @@ void InsetTabular::tabularFeatures(Cursor & cur,
 }
 
 
-bool InsetTabular::showInsetDialog(BufferView * bv) const
-{
-       bv->showDialog("tabular", params2string(*this),
-               const_cast<InsetTabular *>(this));
-       return true;
-}
-
-
-void InsetTabular::openLayoutDialog(BufferView * bv) const
-{
-       bv->showDialog("tabular", params2string(*this),
-               const_cast<InsetTabular *>(this));
-}
-
-
 bool InsetTabular::copySelection(Cursor & cur)
 {
        if (!cur.selection())
@@ -5433,12 +5419,8 @@ void InsetTabular::getSelection(Cursor & cur,
        CursorSlice const & end = cur.selEnd();
        cs = tabular.cellColumn(beg.idx());
        ce = tabular.cellColumn(end.idx());
-       if (cs > ce) {
-               ce = cs;
-               cs = tabular.cellColumn(end.idx());
-       } else {
-               ce = tabular.cellRightColumn(end.idx());
-       }
+       if (cs > ce)
+               swap(cs, ce);
 
        rs = tabular.cellRow(beg.idx());
        re = tabular.cellRow(end.idx());