]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
Better TOC output for XHTML, per Rob and Pavel.
[lyx.git] / src / insets / InsetTabular.cpp
index 7d642e9052997051534d61b40f9b890a12eb1c67..5eb59e54d2513c8100e86b0ba3de223c4ec22f7d 100644 (file)
@@ -88,7 +88,7 @@ namespace Alert = frontend::Alert;
 namespace {
 
 int const ADD_TO_HEIGHT = 2; // in cell
-int const ADD_TO_TABULAR_WIDTH = 6; // horiz space before and after the table
+int const ADD_TO_TABULAR_WIDTH = 6; // horizontal space before and after the table
 int const default_line_space = 10; // ?
 int const WIDTH_OF_LINE = 5; // space between double lines
 
@@ -142,6 +142,7 @@ TabularFeature tabularFeature[] =
        { Tabular::MULTIROW, "multirow", false },
        { Tabular::SET_MULTIROW, "set-multirow", false },
        { Tabular::UNSET_MULTIROW, "unset-multirow", false },
+       { Tabular::SET_MROFFSET, "set-mroffset", true },
        { Tabular::SET_ALL_LINES, "set-all-lines", false },
        { Tabular::UNSET_ALL_LINES, "unset-all-lines", false },
        { Tabular::SET_LONGTABULAR, "set-longtabular", false },
@@ -182,6 +183,7 @@ TabularFeature tabularFeature[] =
        { 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::SET_TABULAR_WIDTH, "set-tabular-width", true },
        { Tabular::LAST_ACTION, "", false }
 };
 
@@ -517,9 +519,6 @@ 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())
@@ -573,6 +572,7 @@ Tabular::CellData::CellData(CellData const & cs)
          width(cs.width),
          multicolumn(cs.multicolumn),
          multirow(cs.multirow),
+         mroffset(cs.mroffset),
          alignment(cs.alignment),
          valignment(cs.valignment),
          decimal_hoffset(cs.decimal_hoffset),
@@ -602,6 +602,7 @@ void Tabular::CellData::swap(CellData & rhs)
        std::swap(width, rhs.width);
        std::swap(multicolumn, rhs.multicolumn);
        std::swap(multirow, rhs.multirow);
+       std::swap(mroffset, rhs.mroffset);
        std::swap(alignment, rhs.alignment);
        std::swap(valignment, rhs.valignment);
        std::swap(decimal_hoffset, rhs.decimal_hoffset);
@@ -678,6 +679,7 @@ void Tabular::init(Buffer * buf, row_type rows_arg,
        updateIndexes();
        is_long_tabular = false;
        tabular_valignment = LYX_VALIGN_MIDDLE;
+       tabular_width = Length();
        longtabular_alignment = LYX_LONGTABULAR_ALIGN_CENTER;
        rotate = false;
        use_booktabs = false;
@@ -1021,17 +1023,33 @@ int Tabular::width() const
 
 
 void Tabular::setAlignment(idx_type cell, LyXAlignment align,
-                             bool onlycolumn)
+                             bool has_width)
 {
        col_type const col = cellColumn(cell);
-       if (onlycolumn || !isMultiColumn(cell)) {
+       // set alignment for the whole row if we are not in a multicolumn cell,
+       // exclude possible multicolumn cells in the row
+       if (!isMultiColumn(cell)) {
+               for (row_type r = 0; r < nrows(); ++r) {
+                       // only if the column has no width the multirow inherits the
+                       // alignment of the column, otherwise it is left aligned
+                       if (!(isMultiRow(cellIndex(r, col)) && has_width)
+                               && !isMultiColumn(cellIndex(r, col))) {
+                               cell_info[r][col].alignment = align;
+                               cell_info[r][col].inset->setContentAlignment(align);
+                       }
+                       if ((isMultiRow(cellIndex(r, col)) && has_width)
+                               && !isMultiColumn(cellIndex(r, col))) {
+                               cell_info[r][col].alignment = LYX_ALIGN_LEFT;
+                               cell_info[r][col].inset->setContentAlignment(LYX_ALIGN_LEFT);
+                       }
+               }
                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);
+               cellInfo(cell).alignment = align; 
+               cellInset(cell).get()->setContentAlignment(align); 
        }
 }
 
@@ -1130,6 +1148,13 @@ bool Tabular::setMColumnPWidth(Cursor & cur, idx_type cell,
 }
 
 
+bool Tabular::setMROffset(Cursor &, idx_type cell, Length const & mroffset)
+{
+       cellInfo(cell).mroffset = mroffset;
+       return true;
+}
+
+
 void Tabular::setAlignSpecial(idx_type cell, docstring const & special,
                                 Tabular::Feature what)
 {
@@ -1249,6 +1274,12 @@ Length const Tabular::getPWidth(idx_type cell) const
 }
 
 
+Length const Tabular::getMROffset(idx_type cell) const
+{
+       return cellInfo(cell).mroffset;
+}
+
+
 int Tabular::textHOffset(idx_type cell) const
 {
        // the LaTeX Way :-(
@@ -1311,8 +1342,9 @@ Tabular::idx_type Tabular::getFirstCellInRow(row_type row) const
 Tabular::idx_type Tabular::getLastCellInRow(row_type row) const
 {
        col_type c = ncols() - 1;
-       while (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW
-               || cell_info[row][c].multicolumn == CELL_PART_OF_MULTICOLUMN)
+       while (c > 0
+              && (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW
+                  || cell_info[row][c].multicolumn == CELL_PART_OF_MULTICOLUMN))
                --c;
        return cell_info[row][c].cellno;
 }
@@ -1362,8 +1394,10 @@ void Tabular::write(ostream & os) const
           << write_attribute("lastFootBottomDL", endlastfoot.bottomDL)
           << write_attribute("lastFootEmpty", endlastfoot.empty);
        // longtables cannot be aligned vertically
-       if (!is_long_tabular)
+       if (!is_long_tabular) {
           os << write_attribute("tabularvalignment", tabular_valignment);
+          os << write_attribute("tabularwidth", tabular_width);
+       }
        if (is_long_tabular)
           os << write_attribute("longtabularalignment",
                                 longtabular_alignment);
@@ -1404,6 +1438,7 @@ void Tabular::write(ostream & os) const
                        os << "<cell"
                           << write_attribute("multicolumn", cell_info[r][c].multicolumn)
                           << write_attribute("multirow", cell_info[r][c].multirow)
+                          << write_attribute("mroffset", cell_info[r][c].mroffset)
                           << write_attribute("alignment", cell_info[r][c].alignment)
                           << write_attribute("valignment", cell_info[r][c].valignment)
                           << write_attribute("topline", cell_info[r][c].top_line)
@@ -1459,6 +1494,7 @@ void Tabular::read(Lexer & lex)
        getTokenValue(line, "booktabs", use_booktabs);
        getTokenValue(line, "islongtable", is_long_tabular);
        getTokenValue(line, "tabularvalignment", tabular_valignment);
+       getTokenValue(line, "tabularwidth", tabular_width);
        getTokenValue(line, "longtabularalignment", longtabular_alignment);
        getTokenValue(line, "firstHeadTopDL", endfirsthead.topDL);
        getTokenValue(line, "firstHeadBottomDL", endfirsthead.bottomDL);
@@ -1513,6 +1549,7 @@ void Tabular::read(Lexer & lex)
                        }
                        getTokenValue(line, "multicolumn", cell_info[i][j].multicolumn);
                        getTokenValue(line, "multirow", cell_info[i][j].multirow);
+                       getTokenValue(line, "mroffset", cell_info[i][j].mroffset);
                        getTokenValue(line, "alignment", cell_info[i][j].alignment);
                        getTokenValue(line, "valignment", cell_info[i][j].valignment);
                        getTokenValue(line, "topline", cell_info[i][j].top_line);
@@ -1855,6 +1892,8 @@ bool Tabular::getLTNewPage(row_type row) const
 
 bool Tabular::haveLTHead() const
 {
+       if (!is_long_tabular)
+               return false;
        for (row_type i = 0; i < nrows(); ++i)
                if (row_info[i].endhead)
                        return true;
@@ -1864,7 +1903,7 @@ bool Tabular::haveLTHead() const
 
 bool Tabular::haveLTFirstHead() const
 {
-       if (endfirsthead.empty)
+       if (!is_long_tabular || endfirsthead.empty)
                return false;
        for (row_type r = 0; r < nrows(); ++r)
                if (row_info[r].endfirsthead)
@@ -1875,6 +1914,8 @@ bool Tabular::haveLTFirstHead() const
 
 bool Tabular::haveLTFoot() const
 {
+       if (!is_long_tabular)
+               return false;
        for (row_type r = 0; r < nrows(); ++r)
                if (row_info[r].endfoot)
                        return true;
@@ -1884,7 +1925,7 @@ bool Tabular::haveLTFoot() const
 
 bool Tabular::haveLTLastFoot() const
 {
-       if (endlastfoot.empty)
+       if (!is_long_tabular || endlastfoot.empty)
                return false;
        for (row_type r = 0; r < nrows(); ++r)
                if (row_info[r].endlastfoot)
@@ -1920,6 +1961,8 @@ bool Tabular::ltCaption(row_type row) const
 
 bool Tabular::haveLTCaption() const
 {
+       if (!is_long_tabular)
+               return false;
        for (row_type r = 0; r < nrows(); ++r)
                if (row_info[r].caption)
                        return true;
@@ -1985,7 +2028,7 @@ bool Tabular::isPartOfMultiRow(row_type row, col_type column) const
 }
 
 
-int Tabular::TeXTopHLine(odocstream & os, row_type row, string const lang) const
+void Tabular::TeXTopHLine(otexstream & os, row_type row, string const lang) const
 {
        // we only output complete row lines and the 1st row here, the rest
        // is done in Tabular::TeXBottomHLine(...)
@@ -2007,7 +2050,7 @@ int Tabular::TeXTopHLine(odocstream & os, row_type row, string const lang) const
 
        // do nothing if empty first row, or incomplete row line after
        if ((row == 0 && nset == 0) || (row > 0 && nset != ncols()))
-               return 0;
+               return;
 
        // only output complete row lines and the 1st row's clines
        if (nset == ncols()) {
@@ -2044,11 +2087,10 @@ int Tabular::TeXTopHLine(odocstream & os, row_type row, string const lang) const
                }
        }
        os << "\n";
-       return 1;
 }
 
 
-int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) const
+void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const lang) const
 {
        // we output bottomlines of row r and the toplines of row r+1
        // if the latter do not span the whole tabular
@@ -2082,7 +2124,7 @@ int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) co
 
        // do nothing if empty, OR incomplete row line with a topline in next row
        if (nset == 0 || (nextrowset && nset != ncols()))
-               return 0;
+               return;
 
        if (nset == ncols()) {
                if (use_booktabs)
@@ -2117,17 +2159,15 @@ int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) co
                }
        }
        os << "\n";
-       return 1;
 }
 
 
-int Tabular::TeXCellPreamble(odocstream & os, idx_type cell,
-                                                        bool & ismulticol, bool & ismultirow) const
+void Tabular::TeXCellPreamble(otexstream & os, idx_type cell,
+                             bool & ismulticol, bool & ismultirow) const
 {
-       int ret = 0;
        row_type const r = cellRow(cell);
        if (is_long_tabular && row_info[r].caption)
-               return ret;
+               return;
 
        Tabular::VAlignment valign =  getVAlignment(cell, !isMultiColumn(cell));
        LyXAlignment align = getAlignment(cell, !isMultiColumn(cell));
@@ -2225,12 +2265,14 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell,
                else
                        // we need to set a default value
                        os << "*";
-               os << "}{";
+               os << "}";
+               if (!getMROffset(cell).zero())
+                       os << "[" << from_ascii(getMROffset(cell).asLatexString()) << "]";
+               os << "{";
        } // end if ismultirow
 
        if (getRotateCell(cell)) {
                os << "\\begin{sideways}\n";
-               ++ret;
        }
        if (getUsebox(cell) == BOX_PARBOX) {
                os << "\\parbox[";
@@ -2262,139 +2304,99 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell,
                }
                os << "]{" << from_ascii(getPWidth(cell).asLatexString())
                   << "}\n";
-               ++ret;
        }
-       return ret;
 }
 
 
-int Tabular::TeXCellPostamble(odocstream & os, idx_type cell,
-                                                         bool ismulticol, bool ismultirow) const
+void Tabular::TeXCellPostamble(otexstream & os, idx_type cell,
+                              bool ismulticol, bool ismultirow) const
 {
-       int ret = 0;
        row_type const r = cellRow(cell);
        if (is_long_tabular && row_info[r].caption)
-               return ret;
+               return;
 
        // usual cells
        if (getUsebox(cell) == BOX_PARBOX)
                os << '}';
-       else if (getUsebox(cell) == BOX_MINIPAGE) {
-               os << "%\n\\end{minipage}";
-               ret += 2;
-       }
-       if (getRotateCell(cell)) {
-               os << "%\n\\end{sideways}";
-               ++ret;
-       }
+       else if (getUsebox(cell) == BOX_MINIPAGE)
+               os << breakln << "\\end{minipage}";
+       if (getRotateCell(cell))
+               os << breakln << "\\end{sideways}";
        if (ismultirow)
                os << '}';
        if (ismulticol)
                os << '}';
-
-       return ret;
 }
 
 
-int Tabular::TeXLongtableHeaderFooter(odocstream & os,
-                                        OutputParams const & runparams) const
+void Tabular::TeXLongtableHeaderFooter(otexstream & os,
+                                       OutputParams const & runparams) const
 {
        if (!is_long_tabular)
-               return 0;
+               return;
 
-       int ret = 0;
        // caption handling
        // the caption must be output before the headers
        if (haveLTCaption()) {
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].caption) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].caption)
+                               TeXRow(os, r, runparams);
                }
        }
        // output first header info
        // first header must be output before the header, otherwise the
        // correct caption placement becomes really weird
        if (haveLTFirstHead()) {
-               if (endfirsthead.topDL) {
+               if (endfirsthead.topDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].endfirsthead) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].endfirsthead)
+                               TeXRow(os, r, runparams);
                }
-               if (endfirsthead.bottomDL) {
+               if (endfirsthead.bottomDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                os << "\\endfirsthead\n";
-               ++ret;
        }
        // output header info
        if (haveLTHead()) {
-               if (endfirsthead.empty && !haveLTFirstHead()) {
+               if (endfirsthead.empty && !haveLTFirstHead())
                        os << "\\endfirsthead\n";
-                       ++ret;
-               }
-               if (endhead.topDL) {
+               if (endhead.topDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].endhead) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].endhead)
+                               TeXRow(os, r, runparams);
                }
-               if (endhead.bottomDL) {
+               if (endhead.bottomDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                os << "\\endhead\n";
-               ++ret;
        }
        // output footer info
        if (haveLTFoot()) {
-               if (endfoot.topDL) {
+               if (endfoot.topDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].endfoot) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].endfoot)
+                               TeXRow(os, r, runparams);
                }
-               if (endfoot.bottomDL) {
+               if (endfoot.bottomDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                os << "\\endfoot\n";
-               ++ret;
-               if (endlastfoot.empty && !haveLTLastFoot()) {
+               if (endlastfoot.empty && !haveLTLastFoot())
                        os << "\\endlastfoot\n";
-                       ++ret;
-               }
        }
        // output lastfooter info
        if (haveLTLastFoot()) {
-               if (endlastfoot.topDL) {
+               if (endlastfoot.topDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].endlastfoot) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].endlastfoot)
+                               TeXRow(os, r, runparams);
                }
-               if (endlastfoot.bottomDL) {
+               if (endlastfoot.bottomDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                os << "\\endlastfoot\n";
-               ++ret;
        }
-       return ret;
 }
 
 
@@ -2408,8 +2410,8 @@ bool Tabular::isValidRow(row_type row) const
 }
 
 
-int Tabular::TeXRow(odocstream & os, row_type row,
-                      OutputParams const & runparams) const
+void Tabular::TeXRow(otexstream & os, row_type row,
+                    OutputParams const & runparams) const
 {
        idx_type cell = cellIndex(row, 0);
        shared_ptr<InsetTableCell> inset = cellInset(cell);
@@ -2417,14 +2419,13 @@ int Tabular::TeXRow(odocstream & os, row_type row,
        string const lang = par.getParLanguage(buffer().params())->lang();
 
        //output the top line
-       int ret = TeXTopHLine(os, row, lang);
+       TeXTopHLine(os, row, lang);
 
        if (row_info[row].top_space_default) {
                if (use_booktabs)
                        os << "\\addlinespace\n";
                else
                        os << "\\noalign{\\vskip\\doublerulesep}\n";
-               ++ret;
        } else if(!row_info[row].top_space.zero()) {
                if (use_booktabs)
                        os << "\\addlinespace["
@@ -2435,22 +2436,23 @@ int Tabular::TeXRow(odocstream & os, row_type row,
                           << from_ascii(row_info[row].top_space.asLatexString())
                           << "}\n";
                }
-               ++ret;
        }
        bool ismulticol = false;
        bool ismultirow = false;
        for (col_type c = 0; c < ncols(); ++c) {
                if (isPartOfMultiColumn(row, c))
                        continue;
-                       
-               if (isPartOfMultiRow(row, c) && 
-                       column_info[c].alignment != LYX_ALIGN_DECIMAL) {
-                       os << " & "; 
+
+               cell = cellIndex(row, c);
+
+               if (isPartOfMultiRow(row, c)
+                   && column_info[c].alignment != LYX_ALIGN_DECIMAL) {
+                       if (cell != getLastCellInRow(row))
+                               os << " & "; 
                        continue;
                }
 
-               cell = cellIndex(row, c);
-               ret += TeXCellPreamble(os, cell, ismulticol, ismultirow);
+               TeXCellPreamble(os, cell, ismulticol, ismultirow);
                shared_ptr<InsetTableCell> inset = cellInset(cell);
 
                Paragraph const & par = inset->paragraphs().front();
@@ -2487,19 +2489,28 @@ int Tabular::TeXRow(odocstream & os, row_type row,
                        head.setBuffer(buffer());
                        bool hassep = false;
                        InsetTableCell tail = splitCell(head, column_info[c].decimal_point, hassep);
+                       tail.getText(0)->setMacrocontextPosition(
+                               head.getText(0)->macrocontextPosition());
+                       tail.setBuffer(head.buffer());
                        head.latex(os, newrp);
                        os << '&';
-                       ret += tail.latex(os, newrp);
-               } else if (!isPartOfMultiRow(row, c))
-                       ret += inset->latex(os, newrp);
+                       tail.latex(os, newrp);
+               } else if (!isPartOfMultiRow(row, c)) {
+                       if (!runparams.nice)
+                               os.texrow().start(par.id(), 0);
+                       inset->latex(os, newrp);
+               }
 
                runparams.encoding = newrp.encoding;
                if (rtl)
                        os << '}';
 
-               ret += TeXCellPostamble(os, cell, ismulticol, ismultirow);
+               TeXCellPostamble(os, cell, ismulticol, ismultirow);
                if (cell != getLastCellInRow(row)) { // not last cell in row
-                       os << " & ";
+                       if (runparams.nice)
+                               os << " & ";
+                       else
+                               os << " &\n";
                }
        }
        if (row_info[row].caption && !endfirsthead.empty && !haveLTFirstHead())
@@ -2522,17 +2533,15 @@ int Tabular::TeXRow(odocstream & os, row_type row,
                   << ']';
        }
        os << '\n';
-       ++ret;
 
        //output the bottom line
-       ret += TeXBottomHLine(os, row, lang);
+       TeXBottomHLine(os, row, lang);
 
        if (row_info[row].interline_space_default) {
                if (use_booktabs)
                        os << "\\addlinespace\n";
                else
                        os << "\\noalign{\\vskip\\doublerulesep}\n";
-               ++ret;
        } else if (!row_info[row].interline_space.zero()) {
                if (use_booktabs)
                        os << "\\addlinespace["
@@ -2542,24 +2551,25 @@ int Tabular::TeXRow(odocstream & os, row_type row,
                        os << "\\noalign{\\vskip"
                           << from_ascii(row_info[row].interline_space.asLatexString())
                           << "}\n";
-               ++ret;
        }
-       return ret;
 }
 
 
-int Tabular::latex(odocstream & os, OutputParams const & runparams) const
+void Tabular::latex(otexstream & os, OutputParams const & runparams) const
 {
-       int ret = 0;
+       bool const is_tabular_star = !tabular_width.zero();
 
        //+---------------------------------------------------------------------
        //+                      first the opening preamble                    +
        //+---------------------------------------------------------------------
 
-       if (rotate) {
+       os << safebreakln;
+       if (runparams.lastid != -1)
+               os.texrow().start(runparams.lastid, runparams.lastpos);
+
+       if (rotate)
                os << "\\begin{sideways}\n";
-               ++ret;
-       }
+
        if (is_long_tabular) {
                os << "\\begin{longtable}";
                switch (longtabular_alignment) {
@@ -2573,7 +2583,10 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const
                        break;
                }
        } else {
-               os << "\\begin{tabular}";
+               if (is_tabular_star)
+                       os << "\\begin{tabular*}{" << from_ascii(tabular_width.asLatexString()) << "}";
+               else
+                       os << "\\begin{tabular}";
                switch (tabular_valignment) {
                case LYX_VALIGN_TOP:
                        os << "[t]";
@@ -2588,6 +2601,9 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const
        
        os << "{";
 
+       if (is_tabular_star)
+               os << "@{\\extracolsep{\\fill}}";
+
        for (col_type c = 0; c < ncols(); ++c) {
                if (columnLeftLine(c))
                        os << '|';
@@ -2648,9 +2664,8 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const
                        os << '|';
        }
        os << "}\n";
-       ++ret;
 
-       ret += TeXLongtableHeaderFooter(os, runparams);
+       TeXLongtableHeaderFooter(os, runparams);
 
        //+---------------------------------------------------------------------
        //+                      the single row and columns (cells)            +
@@ -2658,11 +2673,9 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const
 
        for (row_type r = 0; r < nrows(); ++r) {
                if (isValidRow(r)) {
-                       ret += TeXRow(os, r, runparams);
-                       if (is_long_tabular && row_info[r].newpage) {
+                       TeXRow(os, r, runparams);
+                       if (is_long_tabular && row_info[r].newpage)
                                os << "\\newpage\n";
-                               ++ret;
-                       }
                }
        }
 
@@ -2672,14 +2685,15 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const
 
        if (is_long_tabular)
                os << "\\end{longtable}";
-       else
-               os << "\\end{tabular}";
-       if (rotate) {
-               os << "\n\\end{sideways}";
-               ++ret;
+       else {
+               if (is_tabular_star)
+                       os << "\\end{tabular*}";
+               else
+                       os << "\\end{tabular}";
        }
 
-       return ret;
+       if (rotate)
+               os << breakln << "\\end{sideways}";
 }
 
 
@@ -2832,9 +2846,10 @@ int Tabular::docbook(odocstream & os, OutputParams const & runparams) const
 
 
 docstring Tabular::xhtmlRow(XHTMLStream & xs, row_type row,
-                          OutputParams const & runparams) const
+                          OutputParams const & runparams, bool header) const
 {
        docstring ret;
+       string const celltag = header ? "th" : "td";
        idx_type cell = getFirstCellInRow(row);
 
        xs << html::StartTag("tr");
@@ -2872,9 +2887,9 @@ docstring Tabular::xhtmlRow(XHTMLStream & xs, row_type row,
                if (isMultiColumn(cell))
                        attr << " colspan='" << columnSpan(cell) << "'";
 
-               xs << html::StartTag("td", attr.str());
+               xs << html::StartTag(celltag, attr.str()) << html::CR();
                ret += cellInset(cell)->xhtml(xs, runparams);
-               xs << html::EndTag("td");
+               xs << html::EndTag(celltag) << html::CR();
                ++cell;
        }
        xs << html::EndTag("tr");
@@ -2885,16 +2900,78 @@ docstring Tabular::xhtmlRow(XHTMLStream & xs, row_type row,
 docstring Tabular::xhtml(XHTMLStream & xs, OutputParams const & runparams) const
 {
        docstring ret;
-       // It's unclear to me if we need to mess with the long table stuff. 
-       // We can borrow that too from docbook, if so.
 
-       xs << html::StartTag("tbody");
+       if (is_long_tabular) {
+               // we'll wrap it in a div, so as to deal with alignment
+               string align;
+               switch (longtabular_alignment) {
+               case LYX_LONGTABULAR_ALIGN_LEFT:
+                       align = "left";
+                       break;
+               case LYX_LONGTABULAR_ALIGN_CENTER:
+                       align = "center";
+                       break;
+               case LYX_LONGTABULAR_ALIGN_RIGHT:
+                       align = "right";
+                       break;
+               }
+               xs << html::StartTag("div", "class='longtable' style='text-align: " + align + ";'")
+                  << html::CR();
+               if (haveLTCaption()) {
+                       xs << html::StartTag("div", "class='longtable-caption' style='text-align: " + align + ";'")
+                          << html::CR();
+                       for (row_type r = 0; r < nrows(); ++r)
+                               if (row_info[r].caption)
+                                       ret += xhtmlRow(xs, r, runparams);
+                       xs << html::EndTag("div") << html::CR();
+               }
+       }
+
+       xs << html::StartTag("table") << html::CR();
+
+       // output header info
+       bool const havefirsthead = haveLTFirstHead();
+       // if we have a first head, then we are going to ignore the
+       // headers for the additional pages, since there aren't any
+       // in XHTML. this test accomplishes that.
+       bool const havehead = !havefirsthead && haveLTHead();
+       if (havehead || havefirsthead) {
+               xs << html::StartTag("thead") << html::CR();
+               for (row_type r = 0; r < nrows(); ++r) {
+                       if ((havefirsthead && row_info[r].endfirsthead)
+                           || (havehead && row_info[r].endhead)) {
+                               ret += xhtmlRow(xs, r, runparams, true);
+                       }
+               }
+               xs << html::EndTag("thead") << html::CR();
+       }
+       // output footer info
+       bool const havelastfoot = haveLTLastFoot();
+       // as before.
+       bool const havefoot = !havelastfoot && haveLTFoot();
+       if (havefoot || havelastfoot) {
+               xs << html::StartTag("tfoot") << html::CR();
+               for (row_type r = 0; r < nrows(); ++r) {
+                       if ((havelastfoot && row_info[r].endlastfoot)
+                           || (havefoot && row_info[r].endfoot)) {
+                               ret += xhtmlRow(xs, r, runparams);
+                       }
+               }
+               xs << html::EndTag("tfoot") << html::CR();
+       }
+
+       xs << html::StartTag("tbody") << html::CR();
        for (row_type r = 0; r < nrows(); ++r) {
                if (isValidRow(r)) {
                        ret += xhtmlRow(xs, r, runparams);
                }
        }
-       xs << html::EndTag("tbody");
+       xs << html::EndTag("tbody")
+          << html::CR()
+          << html::EndTag("table")
+          << html::CR();
+       if (is_long_tabular)
+               xs << html::EndTag("div") << html::CR();
        return ret;
 }
 
@@ -3189,7 +3266,7 @@ bool InsetTableCell::allowParagraphCustomization(idx_type) const
 bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd,
        FuncStatus & status) const
 {
-       bool enabled;
+       bool enabled = true;
        switch (cmd.action()) {
        case LFUN_LAYOUT:
                enabled = !forcePlainLayout();
@@ -3197,6 +3274,12 @@ bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_LAYOUT_PARAGRAPH:
                enabled = allowParagraphCustomization();
                break;
+
+       case LFUN_MATH_DISPLAY:
+               if (!hasFixedWidth()) {
+                       enabled = false;
+                       break;
+               } //fall-through
        default:
                return InsetText::getStatus(cur, cmd, status);
        }
@@ -3292,7 +3375,14 @@ void InsetTabular::write(ostream & os) const
 
 docstring InsetTabular::contextMenu(BufferView const &, int, int) const
 {
-       // FIXME: depending on the selection state, we could offer a different menu.
+       // FIXME: depending on the selection state,
+       // we could offer a different menu.
+       return cell(0)->contextMenuName() + ";" + contextMenuName();
+}
+
+
+docstring InsetTabular::contextMenuName() const
+{
        return from_ascii("context-tabular");
 }
 
@@ -3320,11 +3410,11 @@ void InsetTabular::read(Lexer & lex)
 int InsetTabular::rowFromY(Cursor & cur, int y) const
 {
        // top y coordinate of tabular
-       int h = yo(cur.bv()) - tabular.rowAscent(0);
+       int h = yo(cur.bv()) - tabular.rowAscent(0) + offset_valign_;
        row_type r = 0;
        for (; r < tabular.nrows() && y > h; ++r)
                h += tabular.rowAscent(r) + tabular.rowDescent(r)
-               + tabular.interRowSpace(r);
+                       + tabular.interRowSpace(r);
 
        return r - 1;
 }
@@ -3374,7 +3464,7 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
                        TextMetrics const & tm = 
                                mi.base.bv->textMetrics(tabular.cellInset(cell)->getText(0));
 
-                       // determine horiz offset because of decimal align (if necessary)
+                       // determine horizontal offset because of decimal align (if necessary)
                        int decimal_hoffset = 0;
                        int decimal_width = 0;
                        if (tabular.getAlignment(cell) == LYX_ALIGN_DECIMAL) {
@@ -3387,6 +3477,9 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
                                bool hassep = false;
                                InsetTableCell tail = 
                                        splitCell(head, tabular.column_info[c].decimal_point, hassep);
+                               tail.getText(0)->setMacrocontextPosition(
+                                       head.getText(0)->macrocontextPosition());
+                               tail.setBuffer(head.buffer());
                                Dimension dim1;
                                head.metrics(m, dim1);
                                decimal_hoffset = dim1.width();
@@ -3426,8 +3519,24 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
                        tabular.row_info[r].bottom_space.inPixels(mi.base.textwidth);
                tabular.setRowDescent(r, maxdes + ADD_TO_HEIGHT + bottom_space);
        }
+
+       // for top-alignment the first horizontal table line must be exactly at
+       // the position of the base line of the surrounding text line
+       // for bottom alignment, the same is for the last table line
+       switch (tabular.tabular_valignment) {
+       case Tabular::LYX_VALIGN_BOTTOM:
+               offset_valign_ = tabular.rowAscent(0) - tabular.height();
+               break;
+       case Tabular::LYX_VALIGN_MIDDLE:
+               offset_valign_ = (- tabular.height()) / 2 + tabular.rowAscent(0);
+               break;
+       case Tabular::LYX_VALIGN_TOP:
+               offset_valign_ = tabular.rowAscent(0);
+               break;
+       }
+
        tabular.updateColumnWidths();
-       dim.asc = tabular.rowAscent(0);
+       dim.asc = tabular.rowAscent(0) - offset_valign_;        
        dim.des = tabular.height() - dim.asc;
        dim.wid = tabular.width() + 2 * ADD_TO_TABULAR_WIDTH;
 }
@@ -3472,7 +3581,7 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
        Cursor & cur = pi.base.bv->cursor();
        resetPos(cur);
 
-       // FIXME: As the full background is painted in drawSelection(),
+       // FIXME: As the full background is painted in drawBackground(),
        // we have no choice but to do a full repaint for the Text cells.
        pi.full_repaint = true;
 
@@ -3480,6 +3589,8 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
 
        idx_type idx = 0;
        first_visible_cell = Tabular::npos;
+
+       int yy = y + offset_valign_;
        for (row_type r = 0; r < tabular.nrows(); ++r) {
                int nx = x;
                for (col_type c = 0; c < tabular.ncols(); ++c) {
@@ -3498,22 +3609,31 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
 
                        pi.selected |= isCellSelected(cur, r, c);
                        int const cx = nx + tabular.textHOffset(idx);
-                       int const cy = y  + tabular.textVOffset(idx);
+                       int const cy = yy + tabular.textVOffset(idx);
                        // Cache the Inset position.
                        bv->coordCache().insets().add(cell(idx).get(), cx, cy);
                        cell(idx)->draw(pi, cx, cy);
-                       drawCellLines(pi, nx, y, r, idx);
+                       drawCellLines(pi, nx, yy, r, idx);
                        nx += tabular.cellWidth(idx);
                        pi.selected = original_selection_state;
                }
 
                if (r + 1 < tabular.nrows())
-                       y += tabular.rowDescent(r) + tabular.rowAscent(r + 1) 
+                       yy += tabular.rowDescent(r) + tabular.rowAscent(r + 1) 
                                + tabular.interRowSpace(r + 1);
        }
 }
 
 
+void InsetTabular::drawBackground(PainterInfo & pi, int x, int y) const
+{
+       x += scx_ + ADD_TO_TABULAR_WIDTH;
+       y += offset_valign_ - tabular.rowAscent(0);
+       pi.pain.fillRectangle(x, y, tabular.width(), tabular.height(),
+               pi.backgroundColor(this));
+}
+
+
 void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
 {
        Cursor & cur = pi.base.bv->cursor();
@@ -3521,15 +3641,6 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
 
        x += scx_ + ADD_TO_TABULAR_WIDTH;
 
-       // FIXME: it is wrong to completely paint the background
-       // if we want to do single row painting.
-
-       // Paint background of current tabular
-       int const w = tabular.width();
-       int const h = tabular.height();
-       int yy = y - tabular.rowAscent(0);
-       pi.pain.fillRectangle(x, yy, w, h, pi.backgroundColor(this));
-
        if (!cur.selection())
                return;
        if (&cur.inset() != this)
@@ -3555,7 +3666,7 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
                                }
                                int const w = tabular.cellWidth(cell);
                                int const h = tabular.cellHeight(cell);
-                               int const yy = y - tabular.rowAscent(r);
+                               int const yy = y - tabular.rowAscent(r) + offset_valign_;
                                if (isCellSelected(cur, r, c))
                                        pi.pain.fillRectangle(xx, yy, w, h, Color_selection);
                                xx += w;
@@ -3565,11 +3676,14 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
                                     + tabular.interRowSpace(r + 1);
                }
 
-       } else {
-               x += cellXPos(cur.idx());
-               x += tabular.textHOffset(cur.idx());
-               cell(cur.idx())->drawSelection(pi, x, 0 /* ignored */);
-       }
+       } 
+       // FIXME: This code has no effect because InsetTableCell does not handle
+       // drawSelection other than the trivial implementation in Inset.
+       //else {
+       //      x += cellXPos(cur.idx());
+       //      x += tabular.textHOffset(cur.idx());
+       //      cell(cur.idx())->drawSelection(pi, x, 0 /* ignored */);
+       //}
 }
 
 
@@ -3662,7 +3776,7 @@ void InsetTabular::updateBuffer(ParIterator const & it, UpdateType utype)
 }
 
 
-void InsetTabular::addToToc(DocIterator const & cpit)
+void InsetTabular::addToToc(DocIterator const & cpit) const
 {
        DocIterator dit = cpit;
        dit.forwardPos();
@@ -3700,7 +3814,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        break;
                }
                // select column
-               int const y0 = yo(cur.bv()) - tabular.rowAscent(0);
+               int const y0 = yo(cur.bv()) - tabular.rowAscent(0) + offset_valign_;
                if (cmd.y() < y0 + ADD_TO_TABULAR_WIDTH 
                        || cmd.y() > y0 + tabular.height()) {
                        col_type c = columnFromX(cur, cmd.x());
@@ -3895,6 +4009,8 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        cmd = FuncRequest(finish_lfun);
                else
                        cur.dispatched();
+
+               cur.screenUpdateFlags(Update::Force | Update::FitCursor);
                break;
 
        }
@@ -3931,6 +4047,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        cur.setCurrentFont();
                        return;
                }
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
        case LFUN_UP_SELECT:
@@ -3964,6 +4081,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        cur.setCurrentFont();
                        return;
                }
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
 //     case LFUN_SCREEN_DOWN: {
@@ -4099,8 +4217,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                                cell(cur.idx())->dispatch(cur, cmd);
                        break;
                }
-               if (theClipboard().isInternal() ||
-                   (!theClipboard().hasInternal() && theClipboard().hasLyXContents())) {
+               if (theClipboard().isInternal()) {
                        cur.recordUndoInset(INSERT_UNDO);
                        pasteClipboard(cur);
                }
@@ -4176,8 +4293,16 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                if (&cur.inset() != this || cmd.getArg(0) != "tabular") 
                        break;
 
-               string const s = cmd.getArg(1);
                // FIXME: We only check for the very first argument...
+               string const s = cmd.getArg(1);
+               // We always enable the lfun if it is coming from the dialog
+               // because the dialog makes sure all the settings are valid,
+               // even though the first argument might not be valid now.
+               if (s == "from-dialog") {
+                       status.setEnabled(true);
+                       return true;
+               }
+
                int action = Tabular::LAST_ACTION;
                int i = 0;
                for (; tabularFeature[i].action != Tabular::LAST_ACTION; ++i) {
@@ -4220,6 +4345,11 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.clear();
                        return true;
 
+               case Tabular::SET_TABULAR_WIDTH:
+                       status.setEnabled(!tabular.rotate &&  !tabular.is_long_tabular
+                               && tabular.tabular_valignment == Tabular::LYX_VALIGN_MIDDLE);
+                       break;
+
                case Tabular::SET_DECIMAL_POINT:
                        status.setEnabled(
                                tabular.getAlignment(cur.idx()) == LYX_ALIGN_DECIMAL);
@@ -4278,7 +4408,9 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.setOnOff(tabular.rightLine(cur.idx()));
                        break;
 
-               // multirow cells are alwas left aligned
+               // multirow cells only inherit the alignment of the column if the column has
+               // no width, otherwise they are left-aligned
+               // therefore allow always left but right and center only if there is no width
                case Tabular::M_ALIGN_LEFT:
                        flag = false;
                case Tabular::ALIGN_LEFT:
@@ -4288,14 +4420,16 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                case Tabular::M_ALIGN_RIGHT:
                        flag = false;
                case Tabular::ALIGN_RIGHT:
-                       status.setEnabled(!tabular.isMultiRow(cur.idx()));
+                       status.setEnabled(!(tabular.isMultiRow(cur.idx()) 
+                               && !tabular.getPWidth(cur.idx()).zero()));
                        status.setOnOff(tabular.getAlignment(cur.idx(), flag) == LYX_ALIGN_RIGHT);
                        break;
 
                case Tabular::M_ALIGN_CENTER:
                        flag = false;
                case Tabular::ALIGN_CENTER:
-                       status.setEnabled(!tabular.isMultiRow(cur.idx()));
+                       status.setEnabled(!(tabular.isMultiRow(cur.idx()) 
+                               && !tabular.getPWidth(cur.idx()).zero()));
                        status.setOnOff(tabular.getAlignment(cur.idx(), flag) == LYX_ALIGN_CENTER);
                        break;
 
@@ -4354,18 +4488,22 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
 
                case Tabular::TOGGLE_ROTATE_TABULAR:
                case Tabular::SET_ROTATE_TABULAR:
+                       status.setEnabled(tabular.tabular_width.zero());
                        status.setOnOff(tabular.rotate);
                        break;
 
                case Tabular::TABULAR_VALIGN_TOP:
+                       status.setEnabled(tabular.tabular_width.zero());
                        status.setOnOff(tabular.tabular_valignment 
                                == Tabular::LYX_VALIGN_TOP);
                        break;
                case Tabular::TABULAR_VALIGN_MIDDLE:
+                       status.setEnabled(tabular.tabular_width.zero());
                        status.setOnOff(tabular.tabular_valignment 
                                == Tabular::LYX_VALIGN_MIDDLE);
                        break;
                case Tabular::TABULAR_VALIGN_BOTTOM:
+                       status.setEnabled(tabular.tabular_width.zero());
                        status.setOnOff(tabular.tabular_valignment 
                                == Tabular::LYX_VALIGN_BOTTOM);
                        break;
@@ -4514,8 +4652,13 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        }
 
        // disable in non-fixed-width cells
-       case LFUN_NEWLINE_INSERT:
-       case LFUN_BREAK_PARAGRAPH: {
+       case LFUN_BREAK_PARAGRAPH:
+               // multirow does not allow paragraph breaks
+               if (tabular.isMultiRow(cur.idx())) {
+                       status.setEnabled(false);
+                       return true;
+               }
+       case LFUN_NEWLINE_INSERT: {
                if (tabular.getPWidth(cur.idx()).zero()) {
                        status.setEnabled(false);
                        return true;
@@ -4576,9 +4719,9 @@ Inset::DisplayType InsetTabular::display() const
 }
 
 
-int InsetTabular::latex(odocstream & os, OutputParams const & runparams) const
+void InsetTabular::latex(otexstream & os, OutputParams const & runparams) const
 {
-       return tabular.latex(os, runparams);
+       tabular.latex(os, runparams);
 }
 
 
@@ -4620,13 +4763,7 @@ int InsetTabular::docbook(odocstream & os, OutputParams const & runparams) const
 
 docstring InsetTabular::xhtml(XHTMLStream & xs, OutputParams const & rp) const
 {
-       // FIXME XHTML
-       // It'd be better to be able to get this from an InsetLayout, but at present
-       // InsetLayouts do not seem really to work for things that aren't InsetTexts.
-       xs << html::StartTag("table");
-       docstring ret = tabular.xhtml(xs, rp);
-       xs << html::EndTag("table");
-       return ret;
+       return tabular.xhtml(xs, rp);
 }
 
 
@@ -4661,20 +4798,13 @@ void InsetTabular::cursorPos(BufferView const & bv,
 {
        cell(sl.idx())->cursorPos(bv, sl, boundary, x, y);
 
-       int const row = tabular.cellRow(sl.idx());
-       int const col = tabular.cellColumn(sl.idx());
-
        // y offset     correction
-       for (int r = 0; r < row; ++r)
-               y += tabular.rowDescent(r) + tabular.rowAscent(r + 1) 
-                       + tabular.interRowSpace(r + 1);
-
+       y += cellYPos(sl.idx());
        y += tabular.textVOffset(sl.idx());
+       y += offset_valign_;
 
        // x offset correction
-       for (int c = 0; c < col; ++c)
-               x += tabular.column_info[c].width;
-       
+       x += cellXPos(sl.idx());
        x += tabular.textHOffset(sl.idx());
        x += ADD_TO_TABULAR_WIDTH;
        x += scx_;
@@ -4747,13 +4877,23 @@ InsetTabular::idx_type InsetTabular::getNearestCell(BufferView & bv, int x, int
 }
 
 
+int InsetTabular::cellYPos(idx_type const cell) const
+{
+       row_type row = tabular.cellRow(cell);
+       int ly = 0;
+       for (row_type r = 0; r < row; ++r)
+               ly += tabular.rowDescent(r) + tabular.rowAscent(r + 1) 
+                       + tabular.interRowSpace(r + 1);
+       return ly;
+}
+
+
 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.column_info[c].width;
-
        return lx;
 }
 
@@ -5036,7 +5176,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                break;
        }
 
-       cur.recordUndoInset(ATOMIC_UNDO);
+       cur.recordUndoInset(ATOMIC_UNDO, this);
 
        getSelection(cur, sel_row_start, sel_row_end, sel_col_start, sel_col_end);
        row_type const row = tabular.cellRow(cur.idx());
@@ -5046,6 +5186,10 @@ void InsetTabular::tabularFeatures(Cursor & cur,
 
        switch (feature) {
 
+       case Tabular::SET_TABULAR_WIDTH:
+               tabular.setTabularWidth(Length(value));
+               break;
+
        case Tabular::SET_PWIDTH: {
                Length const len(value);
                tabular.setColumnPWidth(cur, cur.idx(), len);
@@ -5059,6 +5203,10 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                tabular.setMColumnPWidth(cur, cur.idx(), Length(value));
                break;
 
+       case Tabular::SET_MROFFSET:
+               tabular.setMROffset(cur, cur.idx(), Length(value));
+               break;
+
        case Tabular::SET_SPECIAL_COLUMN:
        case Tabular::SET_SPECIAL_MULTICOLUMN:
                if (value == "none")
@@ -5152,7 +5300,6 @@ void InsetTabular::tabularFeatures(Cursor & cur,
        case Tabular::M_ALIGN_LEFT:
        case Tabular::M_ALIGN_RIGHT:
        case Tabular::M_ALIGN_CENTER:
-               flag = false;
        case Tabular::ALIGN_LEFT:
        case Tabular::ALIGN_RIGHT:
        case Tabular::ALIGN_CENTER:
@@ -5160,7 +5307,8 @@ void InsetTabular::tabularFeatures(Cursor & cur,
        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);
+                               tabular.setAlignment(tabular.cellIndex(r, c), setAlign,
+                               !tabular.getPWidth(c).zero());
                break;
 
        case Tabular::M_VALIGN_TOP: