]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
Fix some bugs in the bibinfo caching mechanism. Comments to follow.
[lyx.git] / src / insets / InsetTabular.cpp
index 9321f8250a19118b18a1bb021131883a7e8772a7..806d8256f29f7c96a2e7d481f9983ce936e1e514 100644 (file)
@@ -70,7 +70,6 @@
 using namespace std;
 using namespace lyx::support;
 
-using boost::shared_ptr;
 
 
 namespace lyx {
@@ -126,6 +125,7 @@ TabularFeature tabularFeature[] =
        { Tabular::ALIGN_RIGHT, "align-right", false },
        { Tabular::ALIGN_CENTER, "align-center", false },
        { Tabular::ALIGN_BLOCK, "align-block", false },
+       { Tabular::ALIGN_DECIMAL, "align-decimal", false },
        { Tabular::VALIGN_TOP, "valign-top", false },
        { Tabular::VALIGN_BOTTOM, "valign-bottom", false },
        { Tabular::VALIGN_MIDDLE, "valign-middle", false },
@@ -175,6 +175,7 @@ TabularFeature tabularFeature[] =
        { 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::SET_DECIMAL_POINT, "set-decimal-point", true },
        { Tabular::LAST_ACTION, "", false }
 };
 
@@ -252,6 +253,8 @@ string const tostr(LyXAlignment const & num)
                return "layout";
        case LYX_ALIGN_SPECIAL:
                return "special";
+       case LYX_ALIGN_DECIMAL:
+               return "decimal";
        }
        return string();
 }
@@ -312,6 +315,8 @@ bool string2type(string const str, LyXAlignment & num)
                num = LYX_ALIGN_CENTER;
        else if (str == "right")
                num = LYX_ALIGN_RIGHT;
+       else if (str == "decimal")
+               num = LYX_ALIGN_DECIMAL;
        else
                return false;
        return true;
@@ -503,6 +508,30 @@ string const featureAsString(Tabular::Feature action)
 }
 
 
+InsetTableCell splitCell(InsetTableCell & head, docstring const align_d, bool & hassep)
+{
+       InsetTableCell tail = InsetTableCell(head);
+       tail.getText(0)->setMacrocontextPosition(
+               head.getText(0)->macrocontextPosition());
+       tail.setBuffer(head.buffer());
+
+       DocIterator dit = doc_iterator_begin(&head.buffer(), &head);
+       for (; dit; dit.forwardChar())
+               if (dit.inTexted() && dit.depth()==1
+                       && dit.paragraph().find(align_d, false, false, dit.pos()))
+                       break;
+
+       pit_type const psize = head.paragraphs().front().size();
+       hassep = dit;
+       if (hassep)
+               head.paragraphs().front().eraseChars(dit.pos(), psize, false);
+
+       tail.paragraphs().front().eraseChars(0, 
+               dit.pos() < psize ? dit.pos() + 1 : psize, false);
+
+       return tail;
+}
+
 
 /////////////////////////////////////////////////////////////////////
 //
@@ -518,6 +547,9 @@ Tabular::CellData::CellData(Buffer * buf)
          multirow(Tabular::CELL_NORMAL),
          alignment(LYX_ALIGN_CENTER),
          valignment(LYX_VALIGN_TOP),
+         decimal_hoffset(0),
+         decimal_width(0),
+         voffset(0),
          top_line(false),
          bottom_line(false),
          left_line(false),
@@ -537,6 +569,9 @@ Tabular::CellData::CellData(CellData const & cs)
          multirow(cs.multirow),
          alignment(cs.alignment),
          valignment(cs.valignment),
+         decimal_hoffset(cs.decimal_hoffset),
+         decimal_width(cs.decimal_width),
+         voffset(cs.voffset),
          top_line(cs.top_line),
          bottom_line(cs.bottom_line),
          left_line(cs.left_line),
@@ -563,6 +598,9 @@ void Tabular::CellData::swap(CellData & rhs)
        std::swap(multirow, rhs.multirow);
        std::swap(alignment, rhs.alignment);
        std::swap(valignment, rhs.valignment);
+       std::swap(decimal_hoffset, rhs.decimal_hoffset);
+       std::swap(decimal_width, rhs.decimal_width);
+       std::swap(voffset, rhs.voffset);
        std::swap(top_line, rhs.top_line);
        std::swap(bottom_line, rhs.bottom_line);
        std::swap(left_line, rhs.left_line);
@@ -696,8 +734,8 @@ void Tabular::deleteRow(row_type const row)
                // Care about multirow cells
                if (row + 1 < nrows() &&
                    cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW &&
-                   cell_info[row][c + 1].multirow == CELL_PART_OF_MULTIROW) {
-                               cell_info[row][c + 1].multirow = CELL_BEGIN_OF_MULTIROW;
+                   cell_info[row + 1][c].multirow == CELL_PART_OF_MULTIROW) {
+                               cell_info[row + 1][c].multirow = CELL_BEGIN_OF_MULTIROW;
                }
        }
        row_info.erase(row_info.begin() + row);
@@ -812,7 +850,8 @@ void Tabular::updateIndexes()
                        rowofcell[i] = row;
                        columnofcell[i] = column;
                        setFixedWidth(row, column);
-                       updateContentAlignment(row, column);
+                       cell_info[row][column].inset->setContentAlignment(
+                               getAlignment(cellIndex(row, column)));
                        ++i;
                }
 }
@@ -880,7 +919,7 @@ int Tabular::interColumnSpace(idx_type cell) const
 }
 
 
-int Tabular::columnWidth(idx_type cell) const
+int Tabular::cellWidth(idx_type cell) const
 {
        int w = 0;
        col_type const span = columnSpan(cell);
@@ -891,34 +930,45 @@ int Tabular::columnWidth(idx_type cell) const
 }
 
 
-int Tabular::rowHeight(idx_type cell) const
+int Tabular::cellHeight(idx_type cell) const
 {
        row_type const span = rowSpan(cell);
        row_type const row = cellRow(cell);
-       int h = rowAscent(row) + rowDescent(row);
-
+       int h = 0;
        for(row_type r = row; r < row + span ; ++r) {
-               if (r > row) {
-                       h += rowAscent(r);
-                       h += interRowSpace(r);
-               }
-               if (r < row + span - 1)
-                       h += rowDescent(r);
+               h += rowAscent(r) + rowDescent(r);
+               if (r != row + span - 1)
+                       h += interRowSpace(r + 1);
        }
+
        return h;
 }
 
 
 bool Tabular::updateColumnWidths()
 {
+       vector<int> max_dwidth(ncols(), 0);
+       for(col_type c = 0; c < ncols(); ++c)
+               for(row_type r = 0; r < nrows(); ++r) {
+                       idx_type const i = cellIndex(r, c);
+                       if (getAlignment(i) == LYX_ALIGN_DECIMAL)
+                               max_dwidth[c] = max(max_dwidth[c], cell_info[r][c].decimal_width);
+               }
+
        bool update = false;
        // for each col get max of single col cells
        for(col_type c = 0; c < ncols(); ++c) {
                int new_width = 0;
                for(row_type r = 0; r < nrows(); ++r) {
                        idx_type const i = cellIndex(r, c);
-                       if (columnSpan(i) == 1)
-                               new_width = max(new_width, cellInfo(i).width);
+                       if (columnSpan(i) == 1) {
+                               if (getAlignment(i) == LYX_ALIGN_DECIMAL
+                                       && cell_info[r][c].decimal_width!=0)
+                                       new_width = max(new_width, cellInfo(i).width 
+                                               + max_dwidth[c] - cellInfo(i).decimal_width);
+                               else
+                                       new_width = max(new_width, cellInfo(i).width);
+                       }
                }
 
                if (column_info[c].width != new_width) {
@@ -957,21 +1007,19 @@ int Tabular::width() const
 }
 
 
-void Tabular::setCellWidth(idx_type cell, int new_width)
-{
-       cellInfo(cell).width = new_width + 2 * WIDTH_OF_LINE 
-               + interColumnSpace(cell);
-}
-
-
 void Tabular::setAlignment(idx_type cell, LyXAlignment align,
                              bool onlycolumn)
 {
-       if (!isMultiColumn(cell) || onlycolumn)
-               column_info[cellColumn(cell)].alignment = align;
-       if (!onlycolumn)
+       col_type const col = cellColumn(cell);
+       if (onlycolumn || !isMultiColumn(cell)) {
+               column_info[col].alignment = align;
+               docstring & dpoint = column_info[col].decimal_point;
+               if (align == LYX_ALIGN_DECIMAL && dpoint.empty())
+                       dpoint = from_utf8(lyxrc.default_decimal_point);
+       } else {
                cellInfo(cell).alignment = align;
-       cellInset(cell).get()->setContentAlignment(align);
+               cellInset(cell).get()->setContentAlignment(align);
+       }
 }
 
 
@@ -1051,13 +1099,6 @@ bool Tabular::setFixedWidth(row_type r, col_type c)
 }
 
 
-void Tabular::updateContentAlignment(row_type r, col_type c)
-{
-       cell_info[r][c].inset->setContentAlignment(
-               getAlignment(cellIndex(r, c)));
-}
-
-
 bool Tabular::setMColumnPWidth(Cursor & cur, idx_type cell,
                Length const & width)
 {
@@ -1171,8 +1212,9 @@ bool Tabular::columnRightLine(col_type c) const
 
 LyXAlignment Tabular::getAlignment(idx_type cell, bool onlycolumn) const
 {
-       if (!onlycolumn && isMultiColumn(cell))
+       if (!onlycolumn && (isMultiColumn(cell) || isMultiRow(cell)))
                return cellInfo(cell).alignment;
+       
        return column_info[cellColumn(cell)].alignment;
 }
 
@@ -1180,7 +1222,7 @@ LyXAlignment Tabular::getAlignment(idx_type cell, bool onlycolumn) const
 Tabular::VAlignment
 Tabular::getVAlignment(idx_type cell, bool onlycolumn) const
 {
-       if (!onlycolumn && isMultiColumn(cell))
+       if (!onlycolumn && (isMultiColumn(cell) || isMultiRow(cell)))
                return cellInfo(cell).valignment;
        return column_info[cellColumn(cell)].valignment;
 }
@@ -1194,25 +1236,36 @@ Length const Tabular::getPWidth(idx_type cell) const
 }
 
 
-int Tabular::cellWidth(idx_type cell) const
-{
-       return cellInfo(cell).width;
-}
-
-
 int Tabular::textHOffset(idx_type cell) const
 {
        // the LaTeX Way :-(
        int x = WIDTH_OF_LINE;
 
+       int const w = cellWidth(cell) - cellInfo(cell).width;
+
        switch (getAlignment(cell)) {
        case LYX_ALIGN_CENTER:
-               x += (columnWidth(cell) - cellWidth(cell)) / 2;
+               x += w / 2;
                break;
        case LYX_ALIGN_RIGHT:
-               x += columnWidth(cell) - cellWidth(cell);
-               // + interColumnSpace(cell);
+               x += w;
                break;
+       case LYX_ALIGN_DECIMAL: {
+               // we center when no decimal point
+               if (cellInfo(cell).decimal_width == 0) {
+                       x += w / 2;
+                       break;
+               }
+               col_type const c = cellColumn(cell);
+               int max_dhoffset = 0;
+               for(row_type r = 0; r < row_info.size() ; ++r) {
+                       idx_type const i = cellIndex(r, c);
+                       if (getAlignment(i) == LYX_ALIGN_DECIMAL
+                               && cellInfo(i).decimal_width != 0)
+                               max_dhoffset = max(max_dhoffset, cellInfo(i).decimal_hoffset);
+               }
+               x += max_dhoffset - cellInfo(cell).decimal_hoffset;
+       }
        default:
                // LYX_ALIGN_LEFT: nothing :-)
                break;
@@ -1224,21 +1277,12 @@ int Tabular::textHOffset(idx_type cell) const
 
 int Tabular::textVOffset(idx_type cell) const
 {
-       int h = rowHeight(cell);
-       
-       int y = 0;
-       switch (getVAlignment(cell)) {
-          case LYX_VALIGN_TOP:
-                  break;
-          case LYX_VALIGN_MIDDLE:
-                  y += h/2;
-                  break;
-          case LYX_VALIGN_BOTTOM:
-                  y += h;
-                  break;
+       int voffset = cellInfo(cell).voffset;
+       if (isMultiRow(cell)) {
+               row_type const row = cellRow(cell);
+               voffset += (cellHeight(cell) - rowAscent(row) - rowDescent(row))/2; 
        }
-       
-       return y;
+       return voffset;
 }
 
 
@@ -1313,8 +1357,10 @@ void Tabular::write(ostream & os) const
        os << ">\n";
        for (col_type c = 0; c < ncols(); ++c) {
                os << "<column"
-                  << write_attribute("alignment", column_info[c].alignment)
-                  << write_attribute("valignment", column_info[c].valignment)
+                  << write_attribute("alignment", column_info[c].alignment);
+               if (column_info[c].alignment == LYX_ALIGN_DECIMAL)
+                  os << write_attribute("decimal_point", column_info[c].decimal_point);
+               os << write_attribute("valignment", column_info[c].valignment)
                   << write_attribute("width", column_info[c].p_width.asString())
                   << write_attribute("special", column_info[c].align_special)
                   << ">\n";
@@ -1420,6 +1466,7 @@ void Tabular::read(Lexer & lex)
                        return;
                }
                getTokenValue(line, "alignment", column_info[c].alignment);
+               getTokenValue(line, "decimal_point", column_info[c].decimal_point);
                getTokenValue(line, "valignment", column_info[c].valignment);
                getTokenValue(line, "width", column_info[c].p_width);
                getTokenValue(line, "special", column_info[c].align_special);
@@ -1503,17 +1550,21 @@ Tabular::CellData & Tabular::cellInfo(idx_type cell) const
 }
 
 
-void Tabular::setMultiColumn(idx_type cell, idx_type number)
+Tabular::idx_type 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));
 
+       // unsetting of multirow may have invalidated cell index
+       cell = cellIndex(row, col);
        CellData & cs = cellInfo(cell);
        cs.multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
-       cs.alignment = column_info[cellColumn(cell)].alignment;
-       setRightLine(cell, rightLine(cell + number - 1));
+       if (column_info[col].alignment != LYX_ALIGN_DECIMAL)
+               cs.alignment = column_info[col].alignment;
+       if (col > 0)
+               setRightLine(cell, rightLine(cellIndex(row, col - 1)));
 
        for (idx_type i = 1; i < number; ++i) {
                CellData & cs1 = cellInfo(cell + i);
@@ -1522,6 +1573,7 @@ void Tabular::setMultiColumn(idx_type cell, idx_type number)
                cs1.inset->clear();
        }
        updateIndexes();
+       return cell;
 }
 
 
@@ -1532,24 +1584,25 @@ bool Tabular::isMultiRow(idx_type cell) const
 }
 
 
-void Tabular::setMultiRow(idx_type cell, idx_type number)
+Tabular::idx_type Tabular::setMultiRow(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)
                unsetMultiColumn(cellIndex(row + i, col));
 
+       // unsetting of multicol may have invalidated cell index
+       cell = cellIndex(row, col);
        CellData & cs = cellInfo(cell);
        cs.multirow = CELL_BEGIN_OF_MULTIROW;
-       // reset the vertical alignment to top because multirows cells
-       // cannot be vertically aligned (they can also only have one paragraph)
-       column_info[col].valignment = LYX_VALIGN_TOP;
-
-       // FIXME: the horizontal alignment can only be changed for
-       // the whole table, support for this needs to be implemented
-       // (assigning this to uwestoehr)
-       // until LyX supports this, the alignment is always left
-       column_info[col].alignment = LYX_ALIGN_LEFT;
+       cs.valignment = LYX_VALIGN_MIDDLE;
+       // FIXME: the horizontal alignment of multirow cells can only
+       // be changed for the whole table,
+       // support for this needs to be implemented but us a fileformat
+       // change (assigning this to uwestoehr)
+       // until LyX supports this, use the deault alignment of multirow
+       // cells: left
+       cs.alignment = LYX_ALIGN_CENTER; 
 
        // set the bottom row of the last selected cell
        setBottomLine(cell, bottomLine(cell + (number - 1)*ncols()));
@@ -1561,17 +1614,19 @@ void Tabular::setMultiRow(idx_type cell, idx_type number)
                cs1.inset->clear();
        }
        updateIndexes();
+       return cell;
 }
 
 
 Tabular::idx_type Tabular::columnSpan(idx_type cell) const
 {
        row_type const row = cellRow(cell);
-       col_type column = cellColumn(cell) + 1;
-       while (column < ncols() && isPartOfMultiColumn(row, column))
-               ++column;
+       col_type const col = cellColumn(cell);
+       int span = 1;
+       while (col + span < ncols() && isPartOfMultiColumn(row, col + span))
+               ++span;
 
-       return column - cellColumn(cell);
+       return span;
 }
 
 
@@ -1605,6 +1660,8 @@ void Tabular::unsetMultiRow(idx_type cell)
        if (!isMultiRow(cell))
                return;
 
+       cellInfo(cell).valignment = LYX_VALIGN_TOP;
+       cellInfo(cell).alignment = LYX_ALIGN_CENTER;
        row_type const row = cellRow(cell);
        col_type const col = cellColumn(cell);
        row_type const span = rowSpan(cell);
@@ -1938,20 +1995,29 @@ int Tabular::TeXTopHLine(odocstream & os, row_type row, string const lang) const
                }
        } else if (row == 0) {
                for (col_type c = 0; c < ncols(); ++c) {
-                       if (topline[c]) {
-                               //babel makes the "-" character an active one, so we have to suppress this here
-                               //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
-                               if (lang == "slovak" || lang == "czech")
-                                       os << (use_booktabs ? "\\expandafter\\cmidrule\\expandafter{\\expandafter" :
-                                                             "\\expandafter\\cline\\expandafter{\\expandafter")
-                                                                                 << c + 1 << "\\string-";
-                               else
-                                       os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 << '-';
-                               // get to last column of line span
-                               while (c < ncols() && topline[c])
-                                       ++c;
-                               os << c << "} ";
-                       }
+                       for ( ; c < ncols() && !topline[c]; ++c) {}
+
+                       col_type offset = 0;
+                       for (col_type j = 0 ; j < c; ++j)
+                               if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
+                                       ++offset;
+
+                       //babel makes the "-" character an active one, so we have to suppress this here
+                       //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
+                       if (lang == "slovak" || lang == "czech")
+                               os << "\\expandafter" << (use_booktabs ? "\\cmidrule" : "\\cline") 
+                                  << "\\expandafter{\\expandafter" << c + 1 + offset << "\\string-";
+                       else
+                               os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 + offset << '-';
+
+                       col_type cstart = c;
+                       for ( ; c < ncols() && topline[c]; ++c) {}
+
+                       for (col_type j = cstart ; j < c ; ++j)
+                               if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
+                                       ++offset;
+
+                       os << c + offset << "} ";
                }
        }
        os << "\n";
@@ -2002,20 +2068,29 @@ int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) co
                        os << "\\hline ";
        } else {
                for (col_type c = 0; c < ncols(); ++c) {
-                       if (bottomline[c]) {
-                               //babel makes the "-" character an active one, so we have to suppress this here
-                               //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
-                               if (lang == "slovak" || lang == "czech")
-                                       os << (use_booktabs ? "\\expandafter\\cmidrule\\expandafter{\\expandafter" :
-                                                             "\\expandafter\\cline\\expandafter{\\expandafter")
-                                                                                 << c + 1 << "\\string-";
-                               else
-                                       os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 << '-';
-                               // get to last column of line span
-                               while (c < ncols() && bottomline[c])
-                                       ++c;
-                               os << c << "} ";
-                       }
+                       for ( ; c < ncols() && !bottomline[c]; ++c) {}
+
+                       col_type offset = 0;
+                       for (col_type j = 0 ; j < c; ++j)
+                               if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
+                                       ++offset;
+
+                       //babel makes the "-" character an active one, so we have to suppress this here
+                       //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
+                       if (lang == "slovak" || lang == "czech")
+                               os << "\\expandafter" << (use_booktabs ? "\\cmidrule" : "\\cline") 
+                                  << "\\expandafter{\\expandafter" << c + 1 + offset << "\\string-";
+                       else
+                               os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 + offset << '-';
+
+                       col_type cstart = c;
+                       for ( ; c < ncols() && bottomline[c]; ++c) {}
+
+                       for (col_type j = cstart ; j < c ; ++j)
+                               if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
+                                       ++offset;
+
+                       os << c + offset << "} ";
                }
        }
        os << "\n";
@@ -2050,8 +2125,19 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell,
                || ((colright || nextcolleft) && !rightLine(cell) && !nextcellleft)
                || (!colright && !nextcolleft && (rightLine(cell) || nextcellleft))
                || (coldouble != celldouble);
+
+       // we center in multicol when no decimal point
+       ismulticol |= ((column_info[c].alignment == LYX_ALIGN_DECIMAL)
+               && (cellInfo(cell).decimal_width == 0));
+
+       // up counter by 1 for each decimally aligned col since they use 2 latex cols
+       int latexcolspan = columnSpan(cell);
+       for(col_type col = c; col < c + columnSpan(cell); ++col)
+               if (column_info[col].alignment == LYX_ALIGN_DECIMAL)
+                       ++latexcolspan;
+
        if (ismulticol) {
-               os << "\\multicolumn{" << columnSpan(cell) << "}{";
+               os << "\\multicolumn{" << latexcolspan << "}{";
                if (c ==0 && leftLine(cell))
                        os << '|';
                if (!cellInfo(cell).align_special.empty()) {
@@ -2105,7 +2191,7 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell,
                        // add extra vertical line if we want a double one
                        os << '|';
                os << "}{";
-               } // end if ismulticol
+       } // end if ismulticol
 
        // we only need code for the first multirow cell
        ismultirow = isMultiRow(cell);
@@ -2116,9 +2202,9 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell,
                else
                        // we need to set a default value
                        // needs to be discussed
-                       os << "2.0cm";
+                       os << "*";
                os << "}{";
-               } // end if ismultirow
+       } // end if ismultirow
 
        if (getRotateCell(cell)) {
                os << "\\begin{sideways}\n";
@@ -2179,9 +2265,11 @@ int Tabular::TeXCellPostamble(odocstream & os, idx_type cell,
                os << "%\n\\end{sideways}";
                ++ret;
        }
-       if (ismulticol || ismultirow) {
+       if (ismultirow)
                os << '}';
-       }
+       if (ismulticol)
+               os << '}';
+
        return ret;
 }
 
@@ -2330,10 +2418,15 @@ int Tabular::TeXRow(odocstream & os, row_type row,
        bool ismulticol = false;
        bool ismultirow = false;
        for (col_type c = 0; c < ncols(); ++c) {
-               if (isPartOfMultiRow(row, c))
-                       os << " & "; // we need to add a further column
-               if (isPartOfMultiColumn(row, c) || isPartOfMultiRow(row, c))
+               if (isPartOfMultiColumn(row, c))
+                       continue;
+                       
+               if (isPartOfMultiRow(row, c) && 
+                       column_info[c].alignment != LYX_ALIGN_DECIMAL) {
+                       os << " & "; 
                        continue;
+               }
+
                cell = cellIndex(row, c);
                ret += TeXCellPreamble(os, cell, ismulticol, ismultirow);
                shared_ptr<InsetTableCell> inset = cellInset(cell);
@@ -2362,7 +2455,22 @@ int Tabular::TeXRow(odocstream & os, row_type row,
                newrp.inTableCell = (getAlignment(cell) == LYX_ALIGN_BLOCK)
                                    ? OutputParams::PLAIN
                                    : OutputParams::ALIGNED;
-               ret += inset->latex(os, newrp);
+
+               if (getAlignment(cell) == LYX_ALIGN_DECIMAL
+                       && cellInfo(cell).decimal_width != 0) {
+                       // copy cell and split in 2
+                       InsetTableCell head = InsetTableCell(*cellInset(cell).get());
+                       head.getText(0)->setMacrocontextPosition(
+                               cellInset(cell)->getText(0)->macrocontextPosition());
+                       head.setBuffer(buffer());
+                       bool hassep = false;
+                       InsetTableCell tail = splitCell(head, column_info[c].decimal_point, hassep);
+                       head.latex(os, newrp);
+                       os << '&';
+                       ret += tail.latex(os, newrp);
+               } else if (!isPartOfMultiRow(row, c))
+                       ret += inset->latex(os, newrp);
+
                runparams.encoding = newrp.encoding;
                if (rtl)
                        os << '}';
@@ -2479,6 +2587,7 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const
                                case LYX_ALIGN_BLOCK:
                                case LYX_ALIGN_LAYOUT:
                                case LYX_ALIGN_SPECIAL:
+                               case LYX_ALIGN_DECIMAL:
                                        break;
                                }
 
@@ -2504,6 +2613,9 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const
                                case LYX_ALIGN_RIGHT:
                                        os << 'r';
                                        break;
+                               case LYX_ALIGN_DECIMAL:
+                                       os << "r@{\\extracolsep{0pt}" << column_info[c].decimal_point << "}l";
+                                       break;
                                default:
                                        os << 'c';
                                        break;
@@ -3056,7 +3168,7 @@ bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd,
        FuncStatus & status) const
 {
        bool enabled;
-       switch (cmd.action) {
+       switch (cmd.action()) {
        case LFUN_LAYOUT:
                enabled = !forcePlainLayout();
                break;
@@ -3133,11 +3245,19 @@ void InsetTabular::setBuffer(Buffer & buf)
 
 bool InsetTabular::insetAllowed(InsetCode code) const
 {
-       if (code == MATHMACRO_CODE
-               || (code == CAPTION_CODE && !tabular.is_long_tabular))
+       switch (code) {
+       case FLOAT_CODE:
+       case MARGIN_CODE:
+       case MATHMACRO_CODE:
+       case WRAP_CODE:
                return false;
 
-       return true;
+       case CAPTION_CODE:
+               return tabular.is_long_tabular;
+
+       default:
+               return true;
+       }
 }
 
 
@@ -3194,7 +3314,7 @@ int InsetTabular::columnFromX(Cursor & cur, int x) const
        int w = xo(cur.bv()) + ADD_TO_TABULAR_WIDTH;
        col_type c = 0;
        for (; c < tabular.ncols() && x > w; ++c)
-               w += tabular.columnWidth(c);
+               w += tabular.cellWidth(c);
        return c - 1;
 }
 
@@ -3209,8 +3329,8 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
        }
 
        for (row_type r = 0; r < tabular.nrows(); ++r) {
-               int maxAsc = 0;
-               int maxDesc = 0;
+               int maxasc = 0;
+               int maxdes = 0;
                for (col_type c = 0; c < tabular.ncols(); ++c) {
                        if (tabular.isPartOfMultiColumn(r, c)
                                || tabular.isPartOfMultiRow(r, c))
@@ -3219,29 +3339,70 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
                        idx_type const cell = tabular.cellIndex(r, c);
                        Dimension dim;
                        MetricsInfo m = mi;
-                       Length p_width;
-                       if (tabular.cell_info[r][c].multicolumn ==
-                               Tabular::CELL_BEGIN_OF_MULTICOLUMN)
-                               p_width = tabular.cellInfo(cell).p_width;
-                       else
-                               p_width = tabular.column_info[c].p_width;
+                       Length const p_width = tabular.getPWidth(cell);
                        if (!p_width.zero())
                                m.base.textwidth = p_width.inPixels(mi.base.textwidth);
                        tabular.cellInset(cell)->metrics(m, dim);
                        if (!p_width.zero())
                                dim.wid = m.base.textwidth;
-                       tabular.setCellWidth(cell, dim.wid);
-                       maxAsc  = max(maxAsc, dim.asc);
-                       maxDesc = max(maxDesc, dim.des);
+                       tabular.cellInfo(cell).width = dim.wid + 2 * WIDTH_OF_LINE 
+                               + tabular.interColumnSpace(cell);
+
+                       // FIXME(?): do we need a second metrics call?
+                       TextMetrics const & tm = 
+                               mi.base.bv->textMetrics(tabular.cellInset(cell)->getText(0));
+
+                       // determine horiz offset because of decimal align (if necessary)
+                       int decimal_hoffset = 0;
+                       int decimal_width = 0;
+                       if (tabular.getAlignment(cell) == LYX_ALIGN_DECIMAL) {
+                               // make a copy which we will split in 2
+                               InsetTableCell head = InsetTableCell(*tabular.cellInset(cell).get());
+                               head.getText(0)->setMacrocontextPosition(
+                                       tabular.cellInset(cell)->getText(0)->macrocontextPosition());
+                               head.setBuffer(tabular.buffer());
+                               // split in 2 and calculate width of each part
+                               bool hassep = false;
+                               InsetTableCell tail = 
+                                       splitCell(head, tabular.column_info[c].decimal_point, hassep);
+                               Dimension dim1;
+                               head.metrics(m, dim1);
+                               decimal_hoffset = dim1.width();
+                               if (hassep) {
+                                       tail.metrics(m, dim1);
+                                       decimal_width = dim1.width();
+                               }
+                       }
+                       tabular.cell_info[r][c].decimal_hoffset = decimal_hoffset;
+                       tabular.cell_info[r][c].decimal_width = decimal_width;
+
+                       // with LYX_VALIGN_BOTTOM the descent is relative to the last par
+                       // = descent of text in last par + TEXT_TO_INSET_OFFSET:
+                       int const lastpardes = tm.last().second->descent()
+                               + TEXT_TO_INSET_OFFSET;
+                       int offset = 0;
+                       switch (tabular.getVAlignment(cell)) { 
+                               case Tabular::LYX_VALIGN_TOP:
+                                       break; 
+                               case Tabular::LYX_VALIGN_MIDDLE:
+                                       offset = -(dim.des - lastpardes)/2; 
+                                       break; 
+                               case Tabular::LYX_VALIGN_BOTTOM:
+                                       offset = -(dim.des - lastpardes); 
+                                       break;
+                       }
+                       tabular.cell_info[r][c].voffset = offset;
+                       maxasc = max(maxasc, dim.asc - offset);
+                       maxdes = max(maxdes, dim.des + offset);
                }
                int const top_space = tabular.row_info[r].top_space_default ?
                        default_line_space :
                        tabular.row_info[r].top_space.inPixels(mi.base.textwidth);
-               tabular.setRowAscent(r, maxAsc + ADD_TO_HEIGHT + top_space);
+               tabular.setRowAscent(r, maxasc + ADD_TO_HEIGHT + top_space);
                int const bottom_space = tabular.row_info[r].bottom_space_default ?
                        default_line_space :
                        tabular.row_info[r].bottom_space.inPixels(mi.base.textwidth);
-               tabular.setRowDescent(r, maxDesc + ADD_TO_HEIGHT + bottom_space);
+               tabular.setRowDescent(r, maxdes + ADD_TO_HEIGHT + bottom_space);
        }
        tabular.updateColumnWidths();
        dim.asc = tabular.rowAscent(0);
@@ -3249,6 +3410,7 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
        dim.wid = tabular.width() + 2 * ADD_TO_TABULAR_WIDTH;
 }
 
+
 bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) 
        const
 {
@@ -3258,7 +3420,11 @@ bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col)
                        col_type cs, ce;
                        getSelection(cur, rs, re, cs, ce);
                        
-                       if (col >= cs && col <= ce && row >= rs && row <= re)
+                       idx_type const cell = tabular.cellIndex(row, col);
+                       col_type const cspan = tabular.columnSpan(cell);
+                       row_type const rspan = tabular.rowSpan(cell);
+                       if (col + cspan - 1 >= cs && col <= ce 
+                               && row + rspan - 1 >= rs && row <= re)
                                return true;
                } else 
                        if (col == tabular.cellColumn(cur.idx()) 
@@ -3301,7 +3467,7 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
                        idx = tabular.cellIndex(r, c);
                        
                        if (tabular.isPartOfMultiRow(r, c)) {
-                               nx += tabular.columnWidth(idx);
+                               nx += tabular.cellWidth(idx);
                                continue;
                        }
 
@@ -3312,16 +3478,16 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
                        int const cx = nx + tabular.textHOffset(idx);
                        int const cy = y  + tabular.textVOffset(idx);
                        // Cache the Inset position.
-                       bv->coordCache().insets().add(cell(idx).get(), cx, y);
+                       bv->coordCache().insets().add(cell(idx).get(), cx, cy);
                        cell(idx)->draw(pi, cx, cy);
                        drawCellLines(pi.pain, nx, y, r, idx, pi.change_);
-                       nx += tabular.columnWidth(idx);
+                       nx += tabular.cellWidth(idx);
                        pi.selected = original_selection_state;
                }
 
                if (r + 1 < tabular.nrows())
-                       y += tabular.rowDescent(r) + tabular.rowAscent(r + 1)
-                            + tabular.interRowSpace(r + 1);
+                       y += tabular.rowDescent(r) + tabular.rowAscent(r + 1) 
+                               + tabular.interRowSpace(r + 1);
        }
 }
 
@@ -3353,7 +3519,6 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
                tabular.cellRow(cur.idx()), tabular.cellColumn(cur.idx()));
 
        if (cur.selIsMultiCell() || full_cell_selected) {
-               y -= tabular.rowAscent(0);
                for (row_type r = 0; r < tabular.nrows(); ++r) {
                        int xx = x;
                        for (col_type c = 0; c < tabular.ncols(); ++c) {
@@ -3363,13 +3528,14 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
                                idx_type const cell = tabular.cellIndex(r, c);
 
                                if (tabular.isPartOfMultiRow(r, c)) {
-                                       xx += tabular.columnWidth(cell);
+                                       xx += tabular.cellWidth(cell);
                                        continue;
                                }
-                               int const w = tabular.columnWidth(cell);
-                               int const h = tabular.rowHeight(cell);
+                               int const w = tabular.cellWidth(cell);
+                               int const h = tabular.cellHeight(cell);
+                               int const yy = y - tabular.rowAscent(r);
                                if (isCellSelected(cur, r, c))
-                                       pi.pain.fillRectangle(xx, y, w, h, Color_selection);
+                                       pi.pain.fillRectangle(xx, yy, w, h, Color_selection);
                                xx += w;
                        }
                        if (r + 1 < tabular.nrows())
@@ -3386,49 +3552,43 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
 
 
 void InsetTabular::drawCellLines(Painter & pain, int x, int y,
-                                row_type row, idx_type cell, Change const & change) const
-{
-       y = y - tabular.rowAscent(row);
-       int const w = tabular.columnWidth(cell);
-       int const h = tabular.rowHeight(cell);
-       bool on_off = false;
-       Color col = Color_tabularline;
-       Color onoffcol = Color_tabularonoffline;
-
-       if (change.changed()) {
-               col = change.color();
-               onoffcol = change.color();
-       }
-
-       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,
-                       on_off ? Painter::line_onoffdash : Painter::line_solid);
-       }
-       on_off = !tabular.bottomLine(cell);
+                                                                row_type row, idx_type cell, Change const & change) const
+{
+       y -= tabular.rowAscent(row);
+       int const w = tabular.cellWidth(cell);
+       int const h = tabular.cellHeight(cell);
+       Color linecolor = change.changed() ? change.color() : Color_tabularline;
+       Color gridcolor = change.changed() ? change.color() : Color_tabularonoffline;
+
+       // Top
+       bool drawline = tabular.topLine(cell)
+               || (row > 0 && tabular.bottomLine(tabular.cellAbove(cell)));
+       pain.line(x, y, x + w, y,
+               drawline ? linecolor : gridcolor,
+               drawline ? Painter::line_solid : Painter::line_onoffdash);
+
+       // Bottom
+       drawline = tabular.bottomLine(cell);
        pain.line(x, y + h, x + w, y + h,
-               on_off ? onoffcol : col,
-               on_off ? Painter::line_onoffdash : Painter::line_solid);
+               drawline ? linecolor : gridcolor,
+               drawline ? Painter::line_solid : Painter::line_onoffdash);
 
-       col_type const column = tabular.cellColumn(cell);
-       bool leftalreadydrawn = column > 0  && !tabular.leftLine(cell)
-               && tabular.rightLine(tabular.cellIndex(row, column - 1));
+       // Left
+       col_type const col = tabular.cellColumn(cell);
+       drawline = tabular.leftLine(cell)
+               || (col > 0 && tabular.rightLine(tabular.cellIndex(row, col - 1)));
+       pain.line(x, y, x, y + h,
+               drawline ? linecolor : gridcolor,
+               drawline ? Painter::line_solid : Painter::line_onoffdash);
 
-       if (!leftalreadydrawn) {
-               on_off = !tabular.leftLine(cell);
-               pain.line(x, y, x, y + h,
-                       on_off ? onoffcol : col,
-                       on_off ? Painter::line_onoffdash : Painter::line_solid);
-       }
-       on_off = !tabular.rightLine(cell);
-       pain.line(x + w - tabular.interColumnSpace(cell), y,
-               x + w - tabular.interColumnSpace(cell), y + h,
-               on_off ? onoffcol : col,
-               on_off ? Painter::line_onoffdash : Painter::line_solid);
+       // Right
+       x -= tabular.interColumnSpace(cell);
+       drawline = tabular.rightLine(cell)
+                  || (col + 1 < tabular.ncols()
+                      && tabular.leftLine(tabular.cellIndex(row, col + 1)));
+       pain.line(x + w, y, x + w, y + h,
+               drawline ? linecolor : gridcolor,
+               drawline ? Painter::line_solid : Painter::line_onoffdash);
 }
 
 
@@ -3497,14 +3657,16 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        CursorSlice sl = cur.top();
        Cursor & bvcur = cur.bv().cursor();
 
-       switch (cmd.action) {
+       FuncCode const act = cmd.action();
+       
+       switch (act) {
 
        case LFUN_MOUSE_PRESS: {
                //lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl;
                // select row
-               if (cmd.x < xo(cur.bv()) + ADD_TO_TABULAR_WIDTH
-                       || cmd.x > xo(cur.bv()) + tabular.width()) {
-                       row_type r = rowFromY(cur, cmd.y);
+               if (cmd.x() < xo(cur.bv()) + ADD_TO_TABULAR_WIDTH
+                       || cmd.x() > xo(cur.bv()) + tabular.width()) {
+                       row_type r = rowFromY(cur, cmd.y());
                        cur.idx() = tabular.getFirstCellInRow(r);
                        cur.pos() = 0;
                        cur.resetAnchor();
@@ -3517,9 +3679,9 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                }
                // select column
                int const y0 = yo(cur.bv()) - tabular.rowAscent(0);
-               if (cmd.y < y0 + ADD_TO_TABULAR_WIDTH 
-                       || cmd.y > y0 + tabular.height()) {
-                       col_type c = columnFromX(cur, cmd.x);
+               if (cmd.y() < y0 + ADD_TO_TABULAR_WIDTH 
+                       || cmd.y() > y0 + tabular.height()) {
+                       col_type c = columnFromX(cur, cmd.x());
                        cur.idx() = tabular.cellIndex(0, c);
                        cur.pos() = 0;
                        cur.resetAnchor();
@@ -3545,13 +3707,13 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                //lyxerr << "# InsetTabular::MouseMotion\n" << bvcur << endl;
                if (cmd.button() == mouse_button::button1) {
                        // only accept motions to places not deeper nested than the real anchor
-                       if (!bvcur.anchor_.hasPart(cur)) {
+                       if (!bvcur.realAnchor().hasPart(cur)) {
                                cur.undispatched();
                                break;
                        }
                        // select (additional) row
                        if (rowselect_) {
-                               row_type r = rowFromY(cur, cmd.y);
+                               row_type r = rowFromY(cur, cmd.y());
                                cur.idx() = tabular.getLastCellInRow(r);
                                // we need to reset the cursor's pit and pos now, as the old ones
                                // may no longer be valid.
@@ -3563,7 +3725,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        }
                        // select (additional) column
                        if (colselect_) {
-                               col_type c = columnFromX(cur, cmd.x);
+                               col_type c = columnFromX(cur, cmd.x());
                                cur.idx() = tabular.cellIndex(tabular.nrows() - 1, c);
                                // we need to reset the cursor's pit and pos now, as the old ones
                                // may no longer be valid.
@@ -3575,9 +3737,9 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        }
                        // only update if selection changes
                        if (bvcur.idx() == cur.idx() &&
-                               !(bvcur.anchor_.idx() == cur.idx() && bvcur.pos() != cur.pos()))
-                               cur.noUpdate();
-                       setCursorFromCoordinates(cur, cmd.x, cmd.y);
+                               !(bvcur.realAnchor().idx() == cur.idx() && bvcur.pos() != cur.pos()))
+                               cur.noScreenUpdate();
+                       setCursorFromCoordinates(cur, cmd.x(), cmd.y());
                        bvcur.setCursor(cur);
                        bvcur.setSelection(true);
                        // if this is a multicell selection, we just set the cursor to
@@ -3619,21 +3781,21 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                EntryDirection entry_from = ENTRY_DIRECTION_IGNORE;
                FuncCode finish_lfun;
 
-               if (cmd.action == LFUN_CHAR_FORWARD 
-                               || cmd.action == LFUN_CHAR_FORWARD_SELECT) {
+               if (act == LFUN_CHAR_FORWARD 
+                               || act == LFUN_CHAR_FORWARD_SELECT) {
                        next_cell = true;
                        finish_lfun = LFUN_FINISHED_FORWARD;
                }
-               else if (cmd.action == LFUN_CHAR_BACKWARD
-                               || cmd.action == LFUN_CHAR_BACKWARD_SELECT) {
+               else if (act == LFUN_CHAR_BACKWARD
+                               || act == LFUN_CHAR_BACKWARD_SELECT) {
                        next_cell = false;
                        finish_lfun = LFUN_FINISHED_BACKWARD;
                }
                // LEFT or RIGHT commands --- the interpretation will depend on the 
                // table's direction.
                else {
-                       bool const right = cmd.action == LFUN_CHAR_RIGHT
-                               || cmd.action == LFUN_CHAR_RIGHT_SELECT;
+                       bool const right = act == LFUN_CHAR_RIGHT
+                               || act == LFUN_CHAR_RIGHT_SELECT;
                        next_cell = isRightToLeft(cur) != right;
                        
                        if (lyxrc.visual_cursor)
@@ -3642,10 +3804,10 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        finish_lfun = right ? LFUN_FINISHED_RIGHT : LFUN_FINISHED_LEFT;
                }
 
-               bool const select = cmd.action == LFUN_CHAR_FORWARD_SELECT ||
-                   cmd.action == LFUN_CHAR_BACKWARD_SELECT ||
-                   cmd.action == LFUN_CHAR_RIGHT_SELECT ||
-                   cmd.action == LFUN_CHAR_LEFT_SELECT;
+               bool const select = act == LFUN_CHAR_FORWARD_SELECT ||
+                   act == LFUN_CHAR_BACKWARD_SELECT ||
+                   act == LFUN_CHAR_RIGHT_SELECT ||
+                   act == LFUN_CHAR_LEFT_SELECT;
 
                // If we have a multicell selection or we're 
                // not doing some LFUN_*_SELECT thing anyway...
@@ -3707,7 +3869,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        // if our Text didn't do anything to the cursor
                        // then we try to put the cursor into the cell below
                        // setting also the right targetX.
-                       cur.selHandle(cmd.action == LFUN_DOWN_SELECT);
+                       cur.selHandle(act == LFUN_DOWN_SELECT);
                        if (tabular.cellRow(cur.idx()) != tabular.nrows() - 1) {
                                cur.idx() = tabular.cellBelow(cur.idx());
                                cur.pit() = 0;
@@ -3740,7 +3902,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        // if our Text didn't do anything to the cursor
                        // then we try to put the cursor into the cell above
                        // setting also the right targetX.
-                       cur.selHandle(cmd.action == LFUN_UP_SELECT);
+                       cur.selHandle(act == LFUN_UP_SELECT);
                        if (tabular.cellRow(cur.idx()) != 0) {
                                cur.idx() = tabular.cellAbove(cur.idx());
                                cur.pit() = cur.lastpit();
@@ -3770,7 +3932,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 //             col_type const col = tabular.cellColumn(cur.idx());
 //             int const t =   cur.bv().top_y() + cur.bv().height();
 //             if (t < yo() + tabular.getHeightOfTabular()) {
-//                     cur.bv().scrollDocView(t);
+//                     cur.bv().scrollDocView(t, true);
 //                     cur.idx() = tabular.cellBelow(first_visible_cell) + col;
 //             } else {
 //                     cur.idx() = tabular.getFirstCellInRow(tabular.rows() - 1) + col;
@@ -3786,7 +3948,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 //             col_type const col = tabular.cellColumn(cur.idx());
 //             int const t =   cur.bv().top_y() + cur.bv().height();
 //             if (yo() < 0) {
-//                     cur.bv().scrollDocView(t);
+//                     cur.bv().scrollDocView(t, true);
 //                     if (yo() > 0)
 //                             cur.idx() = col;
 //                     else
@@ -3868,7 +4030,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_CLIPBOARD_PASTE:
        case LFUN_PRIMARY_SELECTION_PASTE: {
-               docstring const clip = (cmd.action == LFUN_CLIPBOARD_PASTE) ?
+               docstring const clip = (act == LFUN_CLIPBOARD_PASTE) ?
                        theClipboard().getAsText() :
                        theSelection().get();
                if (clip.empty())
@@ -3969,35 +4131,28 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        FuncStatus & status) const
 {
-       switch (cmd.action) {
+       switch (cmd.action()) {
        case LFUN_INSET_MODIFY: {
-               istringstream is(to_utf8(cmd.argument()));
-               string s;
-               is >> s;
-               if (insetCode(s) != TABULAR_CODE) {
-                       status.clear();
-                       status.setEnabled(false);
+               if (&cur.inset() != this || cmd.getArg(0) != "tabular") 
                        break;
-               }
-               is >> s;
+
+               string const s = cmd.getArg(1);
                // 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 == s.substr(0, tmp.length())) {
+                       if (tabularFeature[i].feature == s) {
                                action = tabularFeature[i].action;
                                break;
                        }
                }
                if (action == Tabular::LAST_ACTION) {
                        status.clear();
-                       status.unknown(true);
+                       status.setUnknown(true);
                        return true;
                }
 
-               string const argument
-                       = ltrim(s.substr(tabularFeature[i].feature.length()));
+               string const argument = cmd.getLongArg(2);
 
                row_type sel_row_start = 0;
                row_type sel_row_end = 0;
@@ -4026,6 +4181,11 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.clear();
                        return true;
 
+               case Tabular::SET_DECIMAL_POINT:
+                       status.setEnabled(
+                               tabular.getAlignment(cur.idx()) == LYX_ALIGN_DECIMAL);
+                       break;
+
                case Tabular::MULTICOLUMN:
                        // If a row is set as longtable caption, it must not be allowed
                        // to unset that this row is a multicolumn.
@@ -4102,6 +4262,12 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.setOnOff(tabular.getAlignment(cur.idx(), flag) == LYX_ALIGN_BLOCK);
                        break;
 
+               case Tabular::ALIGN_DECIMAL:
+                       status.setEnabled(!tabular.isMultiRow(cur.idx()) 
+                               && !tabular.isMultiColumn(cur.idx()));
+                       status.setOnOff(tabular.getAlignment(cur.idx(), true) == LYX_ALIGN_DECIMAL);
+                       break;
+
                case Tabular::M_VALIGN_TOP:
                        flag = false;
                case Tabular::VALIGN_TOP:
@@ -4282,11 +4448,12 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_MATH_MUTATE:
        case LFUN_MATH_DISPLAY:
        case LFUN_NOTE_INSERT:
-       case LFUN_OPTIONAL_INSERT:
+       case LFUN_ARGUMENT_INSERT:
        case LFUN_BOX_INSERT:
        case LFUN_BRANCH_INSERT:
        case LFUN_PHANTOM_INSERT:
        case LFUN_WRAP_INSERT:
+       case LFUN_PREVIEW_INSERT:
        case LFUN_ERT_INSERT: {
                if (cur.selIsMultiCell()) {
                        status.setEnabled(false);
@@ -4447,14 +4614,10 @@ void InsetTabular::cursorPos(BufferView const & bv,
        int const col = tabular.cellColumn(sl.idx());
 
        // y offset     correction
-       for (int r = 0; r <= row; ++r) {
-               if (r != 0) {
-                       y += tabular.rowAscent(r);
-                       y += tabular.interRowSpace(r);
-               }
-               if (r != row)
-                       y += tabular.rowDescent(r);
-       }
+       for (int r = 0; r < row; ++r)
+               y += tabular.rowDescent(r) + tabular.rowAscent(r + 1) 
+                       + tabular.interRowSpace(r + 1);
+
        y += tabular.textVOffset(sl.idx());
 
        // x offset correction
@@ -4474,11 +4637,11 @@ int InsetTabular::dist(BufferView & bv, idx_type const cell, int x, int y) const
        Inset const & inset = *tabular.cellInset(cell);
        Point o = bv.coordCache().getInsets().xy(&inset);
        int const xbeg = o.x_ - tabular.textHOffset(cell);
-       int const xend = xbeg + tabular.columnWidth(cell);
+       int const xend = xbeg + tabular.cellWidth(cell);
        row_type const row = tabular.cellRow(cell);
        int const ybeg = o.y_ - tabular.rowAscent(row)
                - tabular.interRowSpace(row);
-       int const yend = ybeg + tabular.rowHeight(cell);
+       int const yend = ybeg + tabular.cellHeight(cell);
 
        if (x < xbeg)
                xx = xbeg - x;
@@ -4538,7 +4701,7 @@ int InsetTabular::cellXPos(idx_type const cell) const
        col_type col = tabular.cellColumn(cell);
        int lx = 0;
        for (col_type c = 0; c < col; ++c)
-               lx += tabular.columnWidth(c);
+               lx += tabular.column_info[c].width;
 
        return lx;
 }
@@ -4558,7 +4721,7 @@ void InsetTabular::resetPos(Cursor & cur) const
                int const X2 = maxwidth;
                int const offset = ADD_TO_TABULAR_WIDTH + 2;
                int const x1 = xo(cur.bv()) + cellXPos(cur[i].idx()) + offset;
-               int const x2 = x1 + tabular.columnWidth(cur[i].idx());
+               int const x2 = x1 + tabular.cellWidth(cur[i].idx());
 
                if (x1 < X1)
                        scx_ = X1 + 20 - x1;
@@ -4570,7 +4733,7 @@ void InsetTabular::resetPos(Cursor & cur) const
 
        // only update if offset changed
        if (scx_ != scx_old)
-               cur.updateFlags(Update::Force | Update::FitCursor);
+               cur.screenUpdateFlags(Update::Force | Update::FitCursor);
 }
 
 
@@ -4799,6 +4962,10 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                setAlign = LYX_ALIGN_BLOCK;
                break;
 
+       case Tabular::ALIGN_DECIMAL:
+               setAlign = LYX_ALIGN_DECIMAL;
+               break;
+
        case Tabular::M_VALIGN_TOP:
        case Tabular::VALIGN_TOP:
                setVAlign = Tabular::LYX_VALIGN_TOP;
@@ -4850,7 +5017,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                break;
 
        case Tabular::SET_SPECIAL_MULTIROW:
-               //FIXME: noting to do here?
+               // nothing to do
                break;
 
        case Tabular::APPEND_ROW:
@@ -4943,6 +5110,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
        case Tabular::ALIGN_RIGHT:
        case Tabular::ALIGN_CENTER:
        case Tabular::ALIGN_BLOCK:
+       case Tabular::ALIGN_DECIMAL:
                for (row_type r = sel_row_start; r <= sel_row_end; ++r)
                        for (col_type c = sel_col_start; c <= sel_col_end; ++c)
                                tabular.setAlignment(tabular.cellIndex(r, c), setAlign, flag);
@@ -4975,8 +5143,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());
-               tabular.setMultiColumn(s_start, col_end - col_start + 1);
-               cur.idx() = s_start;
+               cur.idx() = tabular.setMultiColumn(s_start, col_end - col_start + 1);
                cur.pit() = 0;
                cur.pos() = 0;
                cur.setSelection(false);
@@ -4998,8 +5165,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());
-               tabular.setMultiRow(s_start, row_end - row_start + 1);
-               cur.idx() = s_start;
+               cur.idx() = tabular.setMultiRow(s_start, row_end - row_start + 1);
                cur.pit() = 0;
                cur.pos() = 0;
                cur.setSelection(false);
@@ -5236,6 +5402,11 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                break;
        }
 
+       case Tabular::SET_DECIMAL_POINT:
+               for (col_type c = sel_col_start; c <= sel_col_end; ++c)
+                       tabular.column_info[c].decimal_point = from_utf8(value);
+               break;
+
        // dummy stuff just to avoid warnings
        case Tabular::LAST_ACTION:
                break;