]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
Remove TextClassPtr without losing the type safety it provided.
[lyx.git] / src / insets / InsetTabular.cpp
index 40f74627e778281622368150d1181989c5b87746..20dbba81d97df6bc1741a99c6aefa6b7c5bf7b97 100644 (file)
 
 #include "InsetTabular.h"
 
+#include "buffer_funcs.h"
 #include "Buffer.h"
 #include "BufferParams.h"
 #include "BufferView.h"
+#include "CoordCache.h"
+#include "Counters.h"
 #include "Cursor.h"
 #include "CutAndPaste.h"
-#include "CoordCache.h"
-#include "debug.h"
 #include "DispatchResult.h"
 #include "FuncRequest.h"
 #include "FuncStatus.h"
-#include "gettext.h"
 #include "Language.h"
 #include "LaTeXFeatures.h"
-#include "Color.h"
-#include "callback.h"
 #include "Lexer.h"
+#include "LyXFunc.h"
 #include "MetricsInfo.h"
 #include "OutputParams.h"
-#include "Paragraph.h"
 #include "paragraph_funcs.h"
+#include "Paragraph.h"
 #include "ParagraphParameters.h"
-#include "Undo.h"
-
-#include "support/convert.h"
-#include "support/lstrings.h"
+#include "ParIterator.h"
+#include "TextClass.h"
+#include "TextMetrics.h"
 
 #include "frontends/alert.h"
 #include "frontends/Clipboard.h"
 #include "frontends/Painter.h"
 #include "frontends/Selection.h"
 
+
+#include "support/convert.h"
+#include "support/debug.h"
+#include "support/docstream.h"
+#include "support/FileName.h"
+#include "support/gettext.h"
+#include "support/lstrings.h"
+
+#include <boost/scoped_ptr.hpp>
+
 #include <sstream>
 #include <iostream>
 #include <limits>
+#include <cstring>
 
-
-namespace lyx {
-
-using support::prefixIs;
-using support::ltrim;
-using support::rtrim;
-using support::suffixIs;
+using namespace std;
+using namespace lyx::support;
 
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 
-using std::abs;
-using std::auto_ptr;
-using std::endl;
-using std::getline;
-using std::istream;
-using std::istringstream;
-using std::max;
-using std::ostream;
-using std::ostringstream;
-using std::string;
-using std::swap;
-using std::vector;
-
-#ifndef CXX_GLOBAL_CSTD
-using std::strlen;
-#endif
+namespace lyx {
 
 using cap::dirtyTabularStack;
 using cap::tabularStackDirty;
-using cap::saveSelection;
 
 using graphics::PreviewLoader;
 
@@ -151,8 +139,10 @@ TabularFeature tabularFeature[] =
        { Tabular::SET_MPWIDTH, "set-mpwidth" },
        { Tabular::SET_ROTATE_TABULAR, "set-rotate-tabular" },
        { Tabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular" },
+       { Tabular::TOGGLE_ROTATE_TABULAR, "toggle-rotate-tabular" },
        { Tabular::SET_ROTATE_CELL, "set-rotate-cell" },
        { Tabular::UNSET_ROTATE_CELL, "unset-rotate-cell" },
+       { Tabular::TOGGLE_ROTATE_CELL, "toggle-rotate-cell" },
        { Tabular::SET_USEBOX, "set-usebox" },
        { Tabular::SET_LTHEAD, "set-lthead" },
        { Tabular::UNSET_LTHEAD, "unset-lthead" },
@@ -174,7 +164,7 @@ TabularFeature tabularFeature[] =
 };
 
 
-class FeatureEqual : public std::unary_function<TabularFeature, bool> {
+class FeatureEqual : public unary_function<TabularFeature, bool> {
 public:
        FeatureEqual(Tabular::Feature feature)
                : feature_(feature) {}
@@ -355,7 +345,7 @@ bool getTokenValue(string const & str, char const * token, string & ret)
 {
        ret.erase();
        size_t token_length = strlen(token);
-       string::size_type pos = str.find(token);
+       size_t pos = str.find(token);
 
        if (pos == string::npos || pos + token_length + 1 >= str.length()
                || str[pos + token_length] != '=')
@@ -428,7 +418,7 @@ bool getTokenValue(string const & str, char const * token, bool & flag)
 
 bool getTokenValue(string const & str, char const * token, Length & len)
 {
-       // set the lenght to be zero() as default as this it should be if not
+       // set the length to be zero() as default as this it should be if not
        // in the file format.
        len = Length();
        string tmp;
@@ -468,7 +458,7 @@ string const featureAsString(Tabular::Feature feature)
 {
        TabularFeature * end = tabularFeature +
                sizeof(tabularFeature) / sizeof(TabularFeature);
-       TabularFeature * it = std::find_if(tabularFeature, end,
+       TabularFeature * it = find_if(tabularFeature, end,
                                           FeatureEqual(feature));
        return (it == end) ? string() : it->feature;
 }
@@ -482,9 +472,9 @@ string const featureAsString(Tabular::Feature feature)
 /////////////////////////////////////////////////////////////////////
 
 
-Tabular::cellstruct::cellstruct(BufferParams const & bp)
+Tabular::CellData::CellData(Buffer const & buffer)
        : cellno(0),
-         width_of_cell(0),
+         width(0),
          multicolumn(Tabular::CELL_NORMAL),
          alignment(LYX_ALIGN_CENTER),
          valignment(LYX_VALIGN_TOP),
@@ -494,13 +484,16 @@ Tabular::cellstruct::cellstruct(BufferParams const & bp)
          right_line(false),
          usebox(BOX_NONE),
          rotate(false),
-         inset(new InsetText(bp))
-{}
+         inset(new InsetText(buffer.params()))
+{
+       inset->setBuffer(const_cast<Buffer &>(buffer));
+       inset->paragraphs().back().setLayout(buffer.params().documentClass().emptyLayout());
+}
 
 
-Tabular::cellstruct::cellstruct(cellstruct const & cs)
+Tabular::CellData::CellData(CellData const & cs)
        : cellno(cs.cellno),
-         width_of_cell(cs.width_of_cell),
+         width(cs.width),
          multicolumn(cs.multicolumn),
          alignment(cs.alignment),
          valignment(cs.valignment),
@@ -512,23 +505,21 @@ Tabular::cellstruct::cellstruct(cellstruct const & cs)
          rotate(cs.rotate),
          align_special(cs.align_special),
          p_width(cs.p_width),
-         inset(dynamic_cast<InsetText*>(cs.inset->clone().release()))
+         inset(dynamic_cast<InsetText*>(cs.inset->clone()))
 {}
 
 
-Tabular::cellstruct &
-Tabular::cellstruct::operator=(cellstruct cs)
+Tabular::CellData & Tabular::CellData::operator=(CellData cs)
 {
        swap(cs);
        return *this;
 }
 
 
-void
-Tabular::cellstruct::swap(cellstruct & rhs)
+void Tabular::CellData::swap(CellData & rhs)
 {
        std::swap(cellno, rhs.cellno);
-       std::swap(width_of_cell, rhs.width_of_cell);
+       std::swap(width, rhs.width);
        std::swap(multicolumn, rhs.multicolumn);
        std::swap(alignment, rhs.alignment);
        std::swap(valignment, rhs.valignment);
@@ -544,9 +535,9 @@ Tabular::cellstruct::swap(cellstruct & rhs)
 }
 
 
-Tabular::rowstruct::rowstruct()
-       : ascent_of_row(0),
-         descent_of_row(0),
+Tabular::RowData::RowData()
+       : ascent(0),
+         descent(0),
          top_line(true),
          bottom_line(false),
          top_space_default(false),
@@ -560,12 +551,12 @@ Tabular::rowstruct::rowstruct()
 {}
 
 
-Tabular::columnstruct::columnstruct()
+Tabular::ColumnData::ColumnData()
        : alignment(LYX_ALIGN_CENTER),
          valignment(LYX_VALIGN_TOP),
          left_line(true),
          right_line(false),
-         width_of_column(0)
+         width(0)
 {
 }
 
@@ -577,27 +568,31 @@ Tabular::ltType::ltType()
 {}
 
 
-Tabular::Tabular(BufferParams const & bp, row_type rows_arg,
-                      col_type columns_arg)
+Tabular::Tabular()
 {
-       init(bp, rows_arg, columns_arg);
+       // unusable now!
+}
+
+
+Tabular::Tabular(Buffer const & buffer, row_type rows_arg, col_type columns_arg)
+{
+       init(buffer, rows_arg, columns_arg);
 }
 
 
 // activates all lines and sets all widths to 0
-void Tabular::init(BufferParams const & bp, row_type rows_arg,
+void Tabular::init(Buffer const & buf, row_type rows_arg,
                      col_type columns_arg)
 {
-       rows_    = rows_arg;
-       columns_ = columns_arg;
-       row_info = row_vector(rows_);
-       column_info = column_vector(columns_);
-       cell_info = cell_vvector(rows_, cell_vector(columns_, cellstruct(bp)));
+       buffer_ = &buf;
+       row_info = row_vector(rows_arg);
+       column_info = column_vector(columns_arg);
+       cell_info = cell_vvector(rows_arg, cell_vector(columns_arg, CellData(buf)));
        row_info.reserve(10);
        column_info.reserve(10);
        cell_info.reserve(100);
        fixCellNums();
-       for (row_type i = 0; i < rows_; ++i)
+       for (row_type i = 0; i < rows_arg; ++i)
                cell_info[i].back().right_line = true;
        row_info.back().bottom_line = true;
        row_info.front().bottom_line = true;
@@ -611,8 +606,8 @@ void Tabular::init(BufferParams const & bp, row_type rows_arg,
 void Tabular::fixCellNums()
 {
        idx_type cellno = 0;
-       for (row_type i = 0; i < rows_; ++i) {
-               for (col_type j = 0; j < columns_; ++j) {
+       for (row_type i = 0; i < rowCount(); ++i) {
+               for (col_type j = 0; j < columnCount(); ++j) {
                        // When debugging it can be nice to set
                        // this to true.
                        cell_info[i][j].inset->setDrawFrame(false);
@@ -621,91 +616,90 @@ void Tabular::fixCellNums()
                cell_info[i].back().right_line = true;
        }
 
-       set_row_column_number_info();
+       updateIndexes();
 }
 
 
-void Tabular::appendRow(BufferParams const & bp, idx_type const cell)
+void Tabular::appendRow(idx_type const cell)
 {
-       ++rows_;
-
-       row_type const row = row_of_cell(cell);
+       BufferParams const & bp = buffer().params();
+       row_type const row = cellRow(cell);
 
        row_vector::iterator rit = row_info.begin() + row;
-       row_info.insert(rit, rowstruct());
+       row_info.insert(rit, RowData());
        // now set the values of the row before
        row_info[row] = row_info[row + 1];
 
-       cell_vvector old(rows_ - 1);
-       for (row_type i = 0; i < rows_ - 1; ++i)
+       row_type const nrows = rowCount();
+       col_type const ncols = columnCount();
+
+       cell_vvector old(nrows - 1);
+       for (row_type i = 0; i < nrows - 1; ++i)
                swap(cell_info[i], old[i]);
 
-       cell_info = cell_vvector(rows_, cell_vector(columns_, cellstruct(bp)));
+       cell_info = cell_vvector(nrows, cell_vector(ncols, CellData(buffer())));
 
        for (row_type i = 0; i <= row; ++i)
                swap(cell_info[i], old[i]);
-       for (row_type i = row + 2; i < rows_; ++i)
+       for (row_type i = row + 2; i < nrows; ++i)
                swap(cell_info[i], old[i - 1]);
 
        if (bp.trackChanges)
-               for (col_type j = 0; j < columns_; ++j)
+               for (col_type j = 0; j < ncols; ++j)
                        cell_info[row + 1][j].inset->setChange(Change(Change::INSERTED));
 
-       set_row_column_number_info();
+       updateIndexes();
 }
 
 
 void Tabular::deleteRow(row_type const row)
 {
        // Not allowed to delete last row
-       if (rows_ == 1)
+       if (rowCount() == 1)
                return;
 
        row_info.erase(row_info.begin() + row);
        cell_info.erase(cell_info.begin() + row);
-       --rows_;
        fixCellNums();
 }
 
 
-void Tabular::copyRow(BufferParams const & bp, row_type const row)
+void Tabular::copyRow(row_type const row)
 {
-       ++rows_;
-
        row_info.insert(row_info.begin() + row, row_info[row]);
        cell_info.insert(cell_info.begin() + row, cell_info[row]);
 
-       if (bp.trackChanges)
-               for (col_type j = 0; j < columns_; ++j)
+       if (buffer().params().trackChanges)
+               for (col_type j = 0; j < columnCount(); ++j)
                        cell_info[row + 1][j].inset->setChange(Change(Change::INSERTED));
 
-       set_row_column_number_info();
+       updateIndexes();
 }
 
 
-void Tabular::appendColumn(BufferParams const & bp, idx_type const cell)
+void Tabular::appendColumn(idx_type const cell)
 {
-       ++columns_;
-
-       col_type const column = column_of_cell(cell);
+       col_type const column = cellColumn(cell);
+       col_type const ncols = columnCount();
        column_vector::iterator cit = column_info.begin() + column + 1;
-       column_info.insert(cit, columnstruct());
+       column_info.insert(cit, ColumnData());
        // set the column values of the column before
        column_info[column + 1] = column_info[column];
 
-       for (row_type i = 0; i < rows_; ++i) {
-               cell_info[i].insert(cell_info[i].begin() + column + 1, cellstruct(bp));
+       BufferParams const & bp = buffer().params();
+       for (row_type i = 0; i < rowCount(); ++i) {
+               cell_info[i].insert(cell_info[i].begin() + column + 1, CellData(buffer()));
 
                // care about multicolumns
                if (cell_info[i][column + 1].multicolumn == CELL_BEGIN_OF_MULTICOLUMN)
                        cell_info[i][column + 1].multicolumn = CELL_PART_OF_MULTICOLUMN;
 
-               if (column + 2 >= columns_
+               if (column + 2 >= ncols
                    || cell_info[i][column + 2].multicolumn != CELL_PART_OF_MULTICOLUMN)
                        cell_info[i][column + 1].multicolumn = Tabular::CELL_NORMAL;
        }
        //++column;
-       for (row_type i = 0; i < rows_; ++i) {
+       for (row_type i = 0; i < rowCount(); ++i) {
                cell_info[i][column + 1].inset->clear();
                if (bp.trackChanges)
                        cell_info[i][column + 1].inset->setChange(Change(Change::INSERTED));
@@ -717,47 +711,51 @@ void Tabular::appendColumn(BufferParams const & bp, idx_type const cell)
 void Tabular::deleteColumn(col_type const column)
 {
        // Not allowed to delete last column
-       if (columns_ == 1)
+       if (columnCount() == 1)
                return;
 
        column_info.erase(column_info.begin() + column);
-       for (row_type i = 0; i < rows_; ++i)
+       for (row_type i = 0; i < rowCount(); ++i) {
+               // Care about multicolumn cells
+               if (column + 1 < columnCount() &&
+                   cell_info[i][column].multicolumn == CELL_BEGIN_OF_MULTICOLUMN &&
+                   cell_info[i][column + 1].multicolumn == CELL_PART_OF_MULTICOLUMN) {
+                       cell_info[i][column + 1].multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
+               }
                cell_info[i].erase(cell_info[i].begin() + column);
-       --columns_;
+       }
        fixCellNums();
 }
 
 
-void Tabular::copyColumn(BufferParams const & bp, col_type const column)
+void Tabular::copyColumn(col_type const column)
 {
-       ++columns_;
-
+       BufferParams const & bp = buffer().params();
        column_info.insert(column_info.begin() + column, column_info[column]);
 
-       for (row_type i = 0; i < rows_; ++i)
+       for (row_type i = 0; i < rowCount(); ++i)
                cell_info[i].insert(cell_info[i].begin() + column, cell_info[i][column]);
 
        if (bp.trackChanges)
-               for (row_type i = 0; i < rows_; ++i)
+               for (row_type i = 0; i < rowCount(); ++i)
                        cell_info[i][column + 1].inset->setChange(Change(Change::INSERTED));
        fixCellNums();
 }
 
 
-void Tabular::set_row_column_number_info()
+void Tabular::updateIndexes()
 {
        numberofcells = 0;
-       for (row_type row = 0; row < rows_; ++row) {
-               for (col_type column = 0; column < columns_; ++column) {
+       // Count only non-multicol cells plus begin multicol
+       // cells, ignore non-begin multicol cells:
+       for (row_type row = 0; row < rowCount(); ++row) {
+               for (col_type column = 0; column < columnCount(); ++column) {
                        if (cell_info[row][column].multicolumn
                                != Tabular::CELL_PART_OF_MULTICOLUMN)
                                ++numberofcells;
-                       if (numberofcells == 0)
-                               // FIXME: Is this intended?
-                               cell_info[row][column].cellno = npos;
-                       else
-                               cell_info[row][column].cellno =
-                                       numberofcells - 1;
+                       BOOST_ASSERT(numberofcells != 0);
+                       cell_info[row][column].cellno =
+                               numberofcells - 1;
                }
        }
 
@@ -767,34 +765,34 @@ void Tabular::set_row_column_number_info()
        row_type row = 0;
        col_type column = 0;
        for (idx_type c = 0;
-                c < numberofcells && row < rows_ && column < columns_;) {
+                c < numberofcells && row < rowCount() && column < columnCount();) {
                rowofcell[c] = row;
                columnofcell[c] = column;
                ++c;
                do {
                        ++column;
-               } while (column < columns_ &&
+               } while (column < columnCount() &&
                                 cell_info[row][column].multicolumn
                                 == Tabular::CELL_PART_OF_MULTICOLUMN);
 
-               if (column == columns_) {
+               if (column == columnCount()) {
                        column = 0;
                        ++row;
                }
        }
 
-       for (row_type row = 0; row < rows_; ++row) {
-               for (col_type column = 0; column < columns_; ++column) {
+       for (row_type row = 0; row < rowCount(); ++row) {
+               for (col_type column = 0; column < columnCount(); ++column) {
                        if (isPartOfMultiColumn(row,column))
                                continue;
                        cell_info[row][column].inset->setAutoBreakRows(
-                               !getPWidth(getCellNumber(row, column)).zero());
+                               !getPWidth(cellIndex(row, column)).zero());
                }
        }
 }
 
 
-Tabular::idx_type Tabular::getNumberOfCells() const
+Tabular::idx_type Tabular::cellCount() const
 {
        return numberofcells;
 }
@@ -802,9 +800,9 @@ Tabular::idx_type Tabular::getNumberOfCells() const
 
 Tabular::idx_type Tabular::numberOfCellsInRow(idx_type const cell) const
 {
-       row_type const row = row_of_cell(cell);
+       row_type const row = cellRow(cell);
        idx_type result = 0;
-       for (col_type i = 0; i < columns_; ++i)
+       for (col_type i = 0; i < columnCount(); ++i)
                if (cell_info[row][i].multicolumn != Tabular::CELL_PART_OF_MULTICOLUMN)
                        ++result;
        return result;
@@ -814,9 +812,9 @@ Tabular::idx_type Tabular::numberOfCellsInRow(idx_type const cell) const
 bool Tabular::topLine(idx_type const cell, bool const wholerow) const
 {
        if (!wholerow && isMultiColumn(cell) &&
-           !(use_booktabs && row_of_cell(cell) == 0))
+           !(use_booktabs && cellRow(cell) == 0))
                return cellinfo_of_cell(cell).top_line;
-       return row_info[row_of_cell(cell)].top_line;
+       return row_info[cellRow(cell)].top_line;
 }
 
 
@@ -825,7 +823,7 @@ bool Tabular::bottomLine(idx_type const cell, bool wholerow) const
        if (!wholerow && isMultiColumn(cell) &&
            !(use_booktabs && isLastRow(cell)))
                return cellinfo_of_cell(cell).bottom_line;
-       return row_info[row_of_cell(cell)].bottom_line;
+       return row_info[cellRow(cell)].bottom_line;
 }
 
 
@@ -836,7 +834,7 @@ bool Tabular::leftLine(idx_type cell, bool wholecolumn) const
        if (!wholecolumn && isMultiColumn(cell) &&
                (isFirstCellInRow(cell) || isMultiColumn(cell-1)))
                return cellinfo_of_cell(cell).left_line;
-       return column_info[column_of_cell(cell)].left_line;
+       return column_info[cellColumn(cell)].left_line;
 }
 
 
@@ -847,15 +845,15 @@ bool Tabular::rightLine(idx_type cell, bool wholecolumn) const
        if (!wholecolumn && isMultiColumn(cell) &&
                (isLastCellInRow(cell) || isMultiColumn(cell + 1)))
                return cellinfo_of_cell(cell).right_line;
-       return column_info[right_column_of_cell(cell)].right_line;
+       return column_info[cellRightColumn(cell)].right_line;
 }
 
 
 bool Tabular::topAlreadyDrawn(idx_type cell) const
 {
-       row_type row = row_of_cell(cell);
+       row_type row = cellRow(cell);
        if (row > 0 && !getAdditionalHeight(row)) {
-               col_type column = column_of_cell(cell);
+               col_type column = cellColumn(cell);
                --row;
                while (column
                           && cell_info[row][column].multicolumn
@@ -872,12 +870,12 @@ bool Tabular::topAlreadyDrawn(idx_type cell) const
 
 bool Tabular::leftAlreadyDrawn(idx_type cell) const
 {
-       col_type column = column_of_cell(cell);
+       col_type column = cellColumn(cell);
        if (column > 0) {
-               row_type row = row_of_cell(cell);
+               row_type row = cellRow(cell);
                while (--column &&
                           (cell_info[row][column].multicolumn ==
-                               Tabular::CELL_PART_OF_MULTICOLUMN));
+                               Tabular::CELL_PART_OF_MULTICOLUMN)) { }
                if (getAdditionalWidth(cell_info[row][column].cellno))
                        return false;
                return rightLine(cell_info[row][column].cellno);
@@ -888,19 +886,19 @@ bool Tabular::leftAlreadyDrawn(idx_type cell) const
 
 bool Tabular::isLastRow(idx_type cell) const
 {
-       return row_of_cell(cell) == rows_ - 1;
+       return cellRow(cell) == rowCount() - 1;
 }
 
 
 int Tabular::getAdditionalHeight(row_type row) const
 {
-       if (!row || row >= rows_)
+       if (!row || row >= rowCount())
                return 0;
 
        bool top = true;
        bool bottom = true;
 
-       for (col_type column = 0; column < columns_ && bottom; ++column) {
+       for (col_type column = 0; column < columnCount() && bottom; ++column) {
                switch (cell_info[row - 1][column].multicolumn) {
                case Tabular::CELL_BEGIN_OF_MULTICOLUMN:
                        bottom = cell_info[row - 1][column].bottom_line;
@@ -909,7 +907,7 @@ int Tabular::getAdditionalHeight(row_type row) const
                        bottom = row_info[row - 1].bottom_line;
                }
        }
-       for (col_type column = 0; column < columns_ && top; ++column) {
+       for (col_type column = 0; column < columnCount() && top; ++column) {
                switch (cell_info[row][column].multicolumn) {
                case Tabular::CELL_BEGIN_OF_MULTICOLUMN:
                        top = cell_info[row][column].top_line;
@@ -920,7 +918,7 @@ int Tabular::getAdditionalHeight(row_type row) const
        }
        int const interline_space = row_info[row - 1].interline_space_default ?
                default_line_space :
-               row_info[row - 1].interline_space.inPixels(width_of_tabular);
+               row_info[row - 1].interline_space.inPixels(width());
        if (top && bottom)
                return interline_space + WIDTH_OF_LINE;
        return interline_space;
@@ -929,11 +927,11 @@ int Tabular::getAdditionalHeight(row_type row) const
 
 int Tabular::getAdditionalWidth(idx_type cell) const
 {
-       // internally already set in setWidthOfCell
+       // internally already set in setCellWidth
        // used to get it back in text.cpp
-       col_type const col = right_column_of_cell(cell);
-       row_type const row = row_of_cell(cell);
-       if (col < columns_ - 1 && rightLine(cell) &&
+       col_type const col = cellRightColumn(cell);
+       row_type const row = cellRow(cell);
+       if (col < columnCount() - 1 && rightLine(cell) &&
                leftLine(cell_info[row][col+1].cellno)) // column_info[col+1].left_line)
        {
                return WIDTH_OF_LINE;
@@ -943,20 +941,23 @@ int Tabular::getAdditionalWidth(idx_type cell) const
 
 
 // returns the maximum over all rows
-int Tabular::getWidthOfColumn(idx_type cell) const
+int Tabular::columnWidth(idx_type cell) const
 {
-       col_type const column1 = column_of_cell(cell);
-       col_type const column2 = right_column_of_cell(cell);
+       col_type const column1 = cellColumn(cell);
+       col_type const column2 = cellRightColumn(cell);
        int result = 0;
        for (col_type i = column1; i <= column2; ++i)
-               result += column_info[i].width_of_column;
+               result += column_info[i].width;
        return result;
 }
 
 
-int Tabular::getWidthOfTabular() const
+int Tabular::width() const
 {
-       return width_of_tabular;
+       int width = 0;
+       for (col_type i = 0; i < columnCount(); ++i)
+               width += column_info[i].width;
+       return width;
 }
 
 
@@ -966,26 +967,26 @@ bool Tabular::setWidthOfMulticolCell(idx_type cell, int new_width)
        if (!isMultiColumn(cell))
                return false;
 
-       row_type const row = row_of_cell(cell);
-       col_type const column1 = column_of_cell(cell);
-       col_type const column2 = right_column_of_cell(cell);
-       int const old_val = cell_info[row][column2].width_of_cell;
+       row_type const row = cellRow(cell);
+       col_type const column1 = cellColumn(cell);
+       col_type const column2 = cellRightColumn(cell);
+       int const old_val = cell_info[row][column2].width;
 
        // first set columns to 0 so we can calculate the right width
        for (col_type i = column1; i <= column2; ++i) {
-               cell_info[row][i].width_of_cell = 0;
+               cell_info[row][i].width = 0;
        }
        // set the width to MAX_WIDTH until width > 0
        int width = new_width + 2 * WIDTH_OF_LINE;
        col_type i = column1;
-       for (; i < column2 && width > column_info[i].width_of_column; ++i) {
-               cell_info[row][i].width_of_cell = column_info[i].width_of_column;
-               width -= column_info[i].width_of_column;
+       for (; i < column2 && width > column_info[i].width; ++i) {
+               cell_info[row][i].width = column_info[i].width;
+               width -= column_info[i].width;
        }
        if (width > 0) {
-               cell_info[row][i].width_of_cell = width;
+               cell_info[row][i].width = width;
        }
-       if (old_val != cell_info[row][column2].width_of_cell) {
+       if (old_val != cell_info[row][column2].width) {
                // in this case we have to recalculate all multicolumn cells which
                // have this column as one of theirs but not as last one
                calculate_width_of_column_NMC(i);
@@ -1001,9 +1002,9 @@ void Tabular::recalculateMulticolumnsOfColumn(col_type column)
        // the last column does not have to be recalculated because all
        // multicolumns will have here there last multicolumn cell which
        // always will have the whole rest of the width of the cell.
-       if (columns_ < 2 || column > (columns_ - 2))
+       if (columnCount() < 2 || column > (columnCount() - 2))
                return;
-       for (row_type row = 0; row < rows_; ++row) {
+       for (row_type row = 0; row < rowCount(); ++row) {
                int mc = cell_info[row][column].multicolumn;
                int nmc = cell_info[row][column+1].multicolumn;
                // we only have to update multicolumns which do not have this
@@ -1014,43 +1015,42 @@ void Tabular::recalculateMulticolumnsOfColumn(col_type column)
                {
                        idx_type const cellno = cell_info[row][column].cellno;
                        setWidthOfMulticolCell(cellno,
-                                              getWidthOfCell(cellno) - 2 * WIDTH_OF_LINE);
+                                              cellWidth(cellno) - 2 * WIDTH_OF_LINE);
                }
        }
 }
 
 
-void Tabular::setWidthOfCell(idx_type cell, int new_width)
+void Tabular::setCellWidth(idx_type cell, int new_width)
 {
-       row_type const row = row_of_cell(cell);
-       col_type const column1 = column_of_cell(cell);
+       row_type const row = cellRow(cell);
+       col_type const column1 = cellColumn(cell);
        bool tmp = false;
        int width = 0;
        int add_width = 0;
 
        if (rightLine(cell_info[row][column1].cellno, true) &&
-               column1 < columns_ - 1 &&
+               column1 < columnCount() - 1 &&
                leftLine(cell_info[row][column1+1].cellno, true))
        {
                add_width = WIDTH_OF_LINE;
        }
 
-       if (getWidthOfCell(cell) == new_width + 2 * WIDTH_OF_LINE + add_width)
+       if (cellWidth(cell) == new_width + 2 * WIDTH_OF_LINE + add_width)
                return;
 
        if (isMultiColumnReal(cell)) {
                tmp = setWidthOfMulticolCell(cell, new_width);
        } else {
                width = new_width + 2 * WIDTH_OF_LINE + add_width;
-               cell_info[row][column1].width_of_cell = width;
+               cell_info[row][column1].width = width;
                tmp = calculate_width_of_column_NMC(column1);
                if (tmp)
                        recalculateMulticolumnsOfColumn(column1);
        }
        if (tmp) {
-               for (col_type i = 0; i < columns_; ++i)
+               for (col_type i = 0; i < columnCount(); ++i)
                        calculate_width_of_column(i);
-               calculate_width_of_tabular();
        }
 }
 
@@ -1059,7 +1059,7 @@ void Tabular::setAlignment(idx_type cell, LyXAlignment align,
                              bool onlycolumn)
 {
        if (!isMultiColumn(cell) || onlycolumn)
-               column_info[column_of_cell(cell)].alignment = align;
+               column_info[cellColumn(cell)].alignment = align;
        if (!onlycolumn)
                cellinfo_of_cell(cell).alignment = align;
 }
@@ -1069,7 +1069,7 @@ void Tabular::setVAlignment(idx_type cell, VAlignment align,
                               bool onlycolumn)
 {
        if (!isMultiColumn(cell) || onlycolumn)
-               column_info[column_of_cell(cell)].valignment = align;
+               column_info[cellColumn(cell)].valignment = align;
        if (!onlycolumn)
                cellinfo_of_cell(cell).valignment = align;
 }
@@ -1089,15 +1089,15 @@ void toggleFixedWidth(Cursor & cur, InsetText * inset, bool fixedWidth)
                return;
 
        // merge all paragraphs to one
-       BufferParams const & bp = cur.bv().buffer()->params();
+       BufferParams const & bp = cur.bv().buffer().params();
        while (inset->paragraphs().size() > 1)
                mergeParagraph(bp, inset->paragraphs(), 0);
 
        // reset layout
        cur.push(*inset);
        // undo information has already been recorded
-       inset->getText(0)->setLayout(*cur.bv().buffer(), 0, cur.lastpit() + 1,
-                       bp.getLyXTextClass().defaultLayoutName());
+       inset->getText(0)->setLayout(cur.bv().buffer(), 0, cur.lastpit() + 1,
+                       bp.documentClass().emptyLayoutName());
        cur.pop();
 }
 
@@ -1107,11 +1107,11 @@ void toggleFixedWidth(Cursor & cur, InsetText * inset, bool fixedWidth)
 void Tabular::setColumnPWidth(Cursor & cur, idx_type cell,
                Length const & width)
 {
-       col_type const j = column_of_cell(cell);
+       col_type const j = cellColumn(cell);
 
        column_info[j].p_width = width;
-       for (row_type i = 0; i < rows_; ++i) {
-               idx_type const cell = getCellNumber(i, j);
+       for (row_type i = 0; i < rowCount(); ++i) {
+               idx_type const cell = cellIndex(i, j);
                // because of multicolumns
                toggleFixedWidth(cur, getCellInset(cell).get(),
                                 !getPWidth(cell).zero());
@@ -1149,7 +1149,7 @@ void Tabular::setAlignSpecial(idx_type cell, docstring const & special,
        if (what == SET_SPECIAL_MULTI)
                cellinfo_of_cell(cell).align_special = special;
        else
-               column_info[column_of_cell(cell)].align_special = special;
+               column_info[cellColumn(cell)].align_special = special;
 }
 
 
@@ -1164,7 +1164,7 @@ void Tabular::setAllLines(idx_type cell, bool line)
 
 void Tabular::setTopLine(idx_type cell, bool line, bool wholerow)
 {
-       row_type const row = row_of_cell(cell);
+       row_type const row = cellRow(cell);
        if (wholerow || !isMultiColumn(cell))
                row_info[row].top_line = line;
        else
@@ -1175,7 +1175,7 @@ void Tabular::setTopLine(idx_type cell, bool line, bool wholerow)
 void Tabular::setBottomLine(idx_type cell, bool line, bool wholerow)
 {
        if (wholerow || !isMultiColumn(cell))
-               row_info[row_of_cell(cell)].bottom_line = line;
+               row_info[cellRow(cell)].bottom_line = line;
        else
                cellinfo_of_cell(cell).bottom_line = line;
 }
@@ -1184,7 +1184,7 @@ void Tabular::setBottomLine(idx_type cell, bool line, bool wholerow)
 void Tabular::setLeftLine(idx_type cell, bool line, bool wholecolumn)
 {
        if (wholecolumn || !isMultiColumn(cell))
-               column_info[column_of_cell(cell)].left_line = line;
+               column_info[cellColumn(cell)].left_line = line;
        else
                cellinfo_of_cell(cell).left_line = line;
 }
@@ -1193,7 +1193,7 @@ void Tabular::setLeftLine(idx_type cell, bool line, bool wholecolumn)
 void Tabular::setRightLine(idx_type cell, bool line, bool wholecolumn)
 {
        if (wholecolumn || !isMultiColumn(cell))
-               column_info[right_column_of_cell(cell)].right_line = line;
+               column_info[cellRightColumn(cell)].right_line = line;
        else
                cellinfo_of_cell(cell).right_line = line;
 }
@@ -1203,7 +1203,7 @@ LyXAlignment Tabular::getAlignment(idx_type cell, bool onlycolumn) const
 {
        if (!onlycolumn && isMultiColumn(cell))
                return cellinfo_of_cell(cell).alignment;
-       return column_info[column_of_cell(cell)].alignment;
+       return column_info[cellColumn(cell)].alignment;
 }
 
 
@@ -1212,7 +1212,7 @@ Tabular::getVAlignment(idx_type cell, bool onlycolumn) const
 {
        if (!onlycolumn && isMultiColumn(cell))
                return cellinfo_of_cell(cell).valignment;
-       return column_info[column_of_cell(cell)].valignment;
+       return column_info[cellColumn(cell)].valignment;
 }
 
 
@@ -1220,13 +1220,13 @@ Length const Tabular::getPWidth(idx_type cell) const
 {
        if (isMultiColumn(cell))
                return cellinfo_of_cell(cell).p_width;
-       return column_info[column_of_cell(cell)].p_width;
+       return column_info[cellColumn(cell)].p_width;
 }
 
 
 Length const Tabular::getColumnPWidth(idx_type cell) const
 {
-       return column_info[column_of_cell(cell)].p_width;
+       return column_info[cellColumn(cell)].p_width;
 }
 
 
@@ -1242,18 +1242,18 @@ docstring const Tabular::getAlignSpecial(idx_type cell, int what) const
 {
        if (what == SET_SPECIAL_MULTI)
                return cellinfo_of_cell(cell).align_special;
-       return column_info[column_of_cell(cell)].align_special;
+       return column_info[cellColumn(cell)].align_special;
 }
 
 
-int Tabular::getWidthOfCell(idx_type cell) const
+int Tabular::cellWidth(idx_type cell) const
 {
-       row_type const row = row_of_cell(cell);
-       col_type const column1 = column_of_cell(cell);
-       col_type const column2 = right_column_of_cell(cell);
+       row_type const row = cellRow(cell);
+       col_type const column1 = cellColumn(cell);
+       col_type const column2 = cellRightColumn(cell);
        int result = 0;
        for (col_type i = column1; i <= column2; ++i)
-               result += cell_info[row][i].width_of_cell;
+               result += cell_info[row][i].width;
        return result;
 }
 
@@ -1264,10 +1264,10 @@ int Tabular::getBeginningOfTextInCell(idx_type cell) const
 
        switch (getAlignment(cell)) {
        case LYX_ALIGN_CENTER:
-               x += (getWidthOfColumn(cell) - getWidthOfCell(cell)) / 2;
+               x += (columnWidth(cell) - cellWidth(cell)) / 2;
                break;
        case LYX_ALIGN_RIGHT:
-               x += getWidthOfColumn(cell) - getWidthOfCell(cell);
+               x += columnWidth(cell) - cellWidth(cell);
                // + getAdditionalWidth(cell);
                break;
        default:
@@ -1283,38 +1283,38 @@ int Tabular::getBeginningOfTextInCell(idx_type cell) const
 
 bool Tabular::isFirstCellInRow(idx_type cell) const
 {
-       return column_of_cell(cell) == 0;
+       return cellColumn(cell) == 0;
 }
 
 
 Tabular::idx_type Tabular::getFirstCellInRow(row_type row) const
 {
-       if (row > rows_ - 1)
-               row = rows_ - 1;
+       if (row > rowCount() - 1)
+               row = rowCount() - 1;
        return cell_info[row][0].cellno;
 }
 
 
 bool Tabular::isLastCellInRow(idx_type cell) const
 {
-       return right_column_of_cell(cell) == columns_ - 1;
+       return cellRightColumn(cell) == columnCount() - 1;
 }
 
 
 Tabular::idx_type Tabular::getLastCellInRow(row_type row) const
 {
-       if (row > rows_ - 1)
-               row = rows_ - 1;
-       return cell_info[row][columns_-1].cellno;
+       if (row > rowCount() - 1)
+               row = rowCount() - 1;
+       return cell_info[row][columnCount() - 1].cellno;
 }
 
 
 void Tabular::calculate_width_of_column(col_type column)
 {
        int maximum = 0;
-       for (row_type i = 0; i < rows_; ++i)
-               maximum = max(cell_info[i][column].width_of_cell, maximum);
-       column_info[column].width_of_column = maximum;
+       for (row_type i = 0; i < rowCount(); ++i)
+               maximum = max(cell_info[i][column].width, maximum);
+       column_info[column].width = maximum;
 }
 
 
@@ -1326,68 +1326,60 @@ void Tabular::calculate_width_of_column(col_type column)
 //
 bool Tabular::calculate_width_of_column_NMC(col_type column)
 {
-       int const old_column_width = column_info[column].width_of_column;
+       int const old_column_width = column_info[column].width;
        int max = 0;
-       for (row_type i = 0; i < rows_; ++i) {
-               idx_type cell = getCellNumber(i, column);
+       for (row_type i = 0; i < rowCount(); ++i) {
+               idx_type cell = cellIndex(i, column);
                bool ismulti = isMultiColumnReal(cell);
-               if ((!ismulti || column == right_column_of_cell(cell)) &&
-                       cell_info[i][column].width_of_cell > max)
+               if ((!ismulti || column == cellRightColumn(cell)) &&
+                       cell_info[i][column].width > max)
                {
-                       max = cell_info[i][column].width_of_cell;
+                       max = cell_info[i][column].width;
                }
        }
-       column_info[column].width_of_column = max;
-       return column_info[column].width_of_column != old_column_width;
-}
-
-
-void Tabular::calculate_width_of_tabular()
-{
-       width_of_tabular = 0;
-       for (col_type i = 0; i < columns_; ++i)
-               width_of_tabular += column_info[i].width_of_column;
+       column_info[column].width = max;
+       return column_info[column].width != old_column_width;
 }
 
 
-Tabular::row_type Tabular::row_of_cell(idx_type cell) const
+Tabular::row_type Tabular::cellRow(idx_type cell) const
 {
-       if (cell >= numberofcells)
-               return rows_ - 1;
+       if (cell >= cellCount())
+               return rowCount() - 1;
        if (cell == npos)
                return 0;
        return rowofcell[cell];
 }
 
 
-Tabular::col_type Tabular::column_of_cell(idx_type cell) const
+Tabular::col_type Tabular::cellColumn(idx_type cell) const
 {
-       if (cell >= numberofcells)
-               return columns_ - 1;
+       if (cell >= cellCount())
+               return columnCount() - 1;
        if (cell == npos)
                return 0;
        return columnofcell[cell];
 }
 
 
-Tabular::col_type Tabular::right_column_of_cell(idx_type cell) const
+Tabular::col_type Tabular::cellRightColumn(idx_type cell) const
 {
-       row_type const row = row_of_cell(cell);
-       col_type column = column_of_cell(cell);
-       while (column < columns_ - 1 &&
+       row_type const row = cellRow(cell);
+       col_type column = cellColumn(cell);
+       while (column < columnCount() - 1 &&
                   cell_info[row][column + 1].multicolumn == Tabular::CELL_PART_OF_MULTICOLUMN)
                ++column;
        return column;
 }
 
 
-void Tabular::write(Buffer const & buf, ostream & os) const
+void Tabular::write(ostream & os) const
 {
        // header line
        os << "<lyxtabular"
           << write_attribute("version", 3)
-          << write_attribute("rows", rows_)
-          << write_attribute("columns", columns_)
+          << write_attribute("rows", rowCount())
+          << write_attribute("columns", columnCount())
           << ">\n";
        // global longtable options
        os << "<features"
@@ -1405,7 +1397,7 @@ void Tabular::write(Buffer const & buf, ostream & os) const
           << write_attribute("lastFootBottomDL", endlastfoot.bottomDL)
           << write_attribute("lastFootEmpty", endlastfoot.empty)
           << ">\n";
-       for (col_type j = 0; j < columns_; ++j) {
+       for (col_type j = 0; j < columnCount(); ++j) {
                os << "<column"
                   << write_attribute("alignment", column_info[j].alignment)
                   << write_attribute("valignment", column_info[j].valignment)
@@ -1415,7 +1407,7 @@ void Tabular::write(Buffer const & buf, ostream & os) const
                   << write_attribute("special", column_info[j].align_special)
                   << ">\n";
        }
-       for (row_type i = 0; i < rows_; ++i) {
+       for (row_type i = 0; i < rowCount(); ++i) {
                os << "<row"
                   << write_attribute("topline", row_info[i].top_line)
                   << write_attribute("bottomline", row_info[i].bottom_line);
@@ -1438,7 +1430,7 @@ void Tabular::write(Buffer const & buf, ostream & os) const
                   << write_attribute("endlastfoot", row_info[i].endlastfoot)
                   << write_attribute("newpage", row_info[i].newpage)
                   << ">\n";
-               for (col_type j = 0; j < columns_; ++j) {
+               for (col_type j = 0; j < columnCount(); ++j) {
                        os << "<cell"
                           << write_attribute("multicolumn", cell_info[i][j].multicolumn)
                           << write_attribute("alignment", cell_info[i][j].alignment)
@@ -1453,7 +1445,7 @@ void Tabular::write(Buffer const & buf, ostream & os) const
                           << write_attribute("special", cell_info[i][j].align_special)
                           << ">\n";
                        os << "\\begin_inset ";
-                       cell_info[i][j].inset->write(buf, os);
+                       cell_info[i][j].inset->write(os);
                        os << "\n\\end_inset\n"
                           << "</cell>\n";
                }
@@ -1463,14 +1455,13 @@ void Tabular::write(Buffer const & buf, ostream & os) const
 }
 
 
-void Tabular::read(Buffer const & buf, Lexer & lex)
+void Tabular::read(Lexer & lex)
 {
        string line;
        istream & is = lex.getStream();
 
        l_getline(is, line);
-       if (!prefixIs(line, "<lyxtabular ")
-               && !prefixIs(line, "<Tabular ")) {
+       if (!prefixIs(line, "<lyxtabular ") && !prefixIs(line, "<Tabular ")) {
                BOOST_ASSERT(false);
                return;
        }
@@ -1486,7 +1477,7 @@ void Tabular::read(Buffer const & buf, Lexer & lex)
        int columns_arg;
        if (!getTokenValue(line, "columns", columns_arg))
                return;
-       init(buf.params(), rows_arg, columns_arg);
+       init(buffer(), rows_arg, columns_arg);
        l_getline(is, line);
        if (!prefixIs(line, "<features")) {
                lyxerr << "Wrong tabular format (expected <features ...> got"
@@ -1507,7 +1498,7 @@ void Tabular::read(Buffer const & buf, Lexer & lex)
        getTokenValue(line, "lastFootBottomDL", endlastfoot.bottomDL);
        getTokenValue(line, "lastFootEmpty", endlastfoot.empty);
 
-       for (col_type j = 0; j < columns_; ++j) {
+       for (col_type j = 0; j < columnCount(); ++j) {
                l_getline(is,line);
                if (!prefixIs(line,"<column")) {
                        lyxerr << "Wrong tabular format (expected <column ...> got"
@@ -1522,7 +1513,7 @@ void Tabular::read(Buffer const & buf, Lexer & lex)
                getTokenValue(line, "special", column_info[j].align_special);
        }
 
-       for (row_type i = 0; i < rows_; ++i) {
+       for (row_type i = 0; i < rowCount(); ++i) {
                l_getline(is, line);
                if (!prefixIs(line, "<row")) {
                        lyxerr << "Wrong tabular format (expected <row ...> got"
@@ -1532,17 +1523,17 @@ void Tabular::read(Buffer const & buf, Lexer & lex)
                getTokenValue(line, "topline", row_info[i].top_line);
                getTokenValue(line, "bottomline", row_info[i].bottom_line);
                getTokenValue(line, "topspace", row_info[i].top_space,
-                             row_info[i].top_space_default);
+                             row_info[i].top_space_default);
                getTokenValue(line, "bottomspace", row_info[i].bottom_space,
-                             row_info[i].bottom_space_default);
+                             row_info[i].bottom_space_default);
                getTokenValue(line, "interlinespace", row_info[i].interline_space,
-                             row_info[i].interline_space_default);
+                             row_info[i].interline_space_default);
                getTokenValue(line, "endfirsthead", row_info[i].endfirsthead);
                getTokenValue(line, "endhead", row_info[i].endhead);
                getTokenValue(line, "endfoot", row_info[i].endfoot);
                getTokenValue(line, "endlastfoot", row_info[i].endlastfoot);
                getTokenValue(line, "newpage", row_info[i].newpage);
-               for (col_type j = 0; j < columns_; ++j) {
+               for (col_type j = 0; j < columnCount(); ++j) {
                        l_getline(is, line);
                        if (!prefixIs(line, "<cell")) {
                                lyxerr << "Wrong tabular format (expected <cell ...> got"
@@ -1562,7 +1553,7 @@ void Tabular::read(Buffer const & buf, Lexer & lex)
                        getTokenValue(line, "special", cell_info[i][j].align_special);
                        l_getline(is, line);
                        if (prefixIs(line, "\\begin_inset")) {
-                               cell_info[i][j].inset->read(buf, lex);
+                               cell_info[i][j].inset->read(lex);
                                l_getline(is, line);
                        }
                        if (!prefixIs(line, "</cell>")) {
@@ -1581,7 +1572,7 @@ void Tabular::read(Buffer const & buf, Lexer & lex)
        while (!prefixIs(line, "</lyxtabular>")) {
                l_getline(is, line);
        }
-       set_row_column_number_info();
+       updateIndexes();
 }
 
 
@@ -1593,44 +1584,43 @@ bool Tabular::isMultiColumn(idx_type cell) const
 
 bool Tabular::isMultiColumnReal(idx_type cell) const
 {
-       return column_of_cell(cell) != right_column_of_cell(cell) &&
+       return cellColumn(cell) != cellRightColumn(cell) &&
                        cellinfo_of_cell(cell).multicolumn != Tabular::CELL_NORMAL;
 }
 
 
-Tabular::cellstruct & Tabular::cellinfo_of_cell(idx_type cell) const
+Tabular::CellData & Tabular::cellinfo_of_cell(idx_type cell) const
 {
-       return cell_info[row_of_cell(cell)][column_of_cell(cell)];
+       return cell_info[cellRow(cell)][cellColumn(cell)];
 }
 
 
-void Tabular::setMultiColumn(Buffer * buffer, idx_type cell,
-                               idx_type number)
+void Tabular::setMultiColumn(idx_type cell, idx_type number)
 {
-       cellstruct & cs = cellinfo_of_cell(cell);
+       CellData & cs = cellinfo_of_cell(cell);
        cs.multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
-       cs.alignment = column_info[column_of_cell(cell)].alignment;
-       cs.top_line = row_info[row_of_cell(cell)].top_line;
-       cs.bottom_line = row_info[row_of_cell(cell)].bottom_line;
-       cs.left_line = column_info[column_of_cell(cell)].left_line;
-       cs.right_line = column_info[column_of_cell(cell+number-1)].right_line;
+       cs.alignment = column_info[cellColumn(cell)].alignment;
+       cs.top_line = row_info[cellRow(cell)].top_line;
+       cs.bottom_line = row_info[cellRow(cell)].bottom_line;
+       cs.left_line = column_info[cellColumn(cell)].left_line;
+       cs.right_line = column_info[cellColumn(cell+number-1)].right_line;
        for (idx_type i = 1; i < number; ++i) {
-               cellstruct & cs1 = cellinfo_of_cell(cell + i);
+               CellData & cs1 = cellinfo_of_cell(cell + i);
                cs1.multicolumn = CELL_PART_OF_MULTICOLUMN;
-               cs.inset->appendParagraphs(buffer, cs1.inset->paragraphs());
+               cs.inset->appendParagraphs(cs1.inset->paragraphs());
                cs1.inset->clear();
        }
-       set_row_column_number_info();
+       updateIndexes();
 }
 
 
 Tabular::idx_type Tabular::cells_in_multicolumn(idx_type cell) const
 {
-       row_type const row = row_of_cell(cell);
-       col_type column = column_of_cell(cell);
+       row_type const row = cellRow(cell);
+       col_type column = cellColumn(cell);
        idx_type result = 1;
        ++column;
-       while (column < columns_ &&
+       while (column < columnCount() &&
                   cell_info[row][column].multicolumn == CELL_PART_OF_MULTICOLUMN)
        {
                ++result;
@@ -1642,15 +1632,15 @@ Tabular::idx_type Tabular::cells_in_multicolumn(idx_type cell) const
 
 Tabular::idx_type Tabular::unsetMultiColumn(idx_type cell)
 {
-       row_type const row = row_of_cell(cell);
-       col_type column = column_of_cell(cell);
+       row_type const row = cellRow(cell);
+       col_type column = cellColumn(cell);
 
        idx_type result = 0;
 
        if (cell_info[row][column].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) {
                cell_info[row][column].multicolumn = CELL_NORMAL;
                ++column;
-               while (column < columns_ &&
+               while (column < columnCount() &&
                           cell_info[row][column].multicolumn == CELL_PART_OF_MULTICOLUMN)
                {
                        cell_info[row][column].multicolumn = CELL_NORMAL;
@@ -1658,7 +1648,7 @@ Tabular::idx_type Tabular::unsetMultiColumn(idx_type cell)
                        ++result;
                }
        }
-       set_row_column_number_info();
+       updateIndexes();
        return result;
 }
 
@@ -1715,8 +1705,8 @@ bool Tabular::needRotating() const
 {
        if (rotate)
                return true;
-       for (row_type i = 0; i < rows_; ++i)
-               for (col_type j = 0; j < columns_; ++j)
+       for (row_type i = 0; i < rowCount(); ++i)
+               for (col_type j = 0; j < columnCount(); ++j)
                        if (cell_info[i][j].rotate)
                                return true;
        return false;
@@ -1725,7 +1715,7 @@ bool Tabular::needRotating() const
 
 bool Tabular::isLastCell(idx_type cell) const
 {
-       if (cell + 1 < numberofcells)
+       if (cell + 1 < cellCount())
                return false;
        return true;
 }
@@ -1733,45 +1723,45 @@ bool Tabular::isLastCell(idx_type cell) const
 
 Tabular::idx_type Tabular::getCellAbove(idx_type cell) const
 {
-       if (row_of_cell(cell) > 0)
-               return cell_info[row_of_cell(cell)-1][column_of_cell(cell)].cellno;
+       if (cellRow(cell) > 0)
+               return cell_info[cellRow(cell)-1][cellColumn(cell)].cellno;
        return cell;
 }
 
 
 Tabular::idx_type Tabular::getCellBelow(idx_type cell) const
 {
-       if (row_of_cell(cell) + 1 < rows_)
-               return cell_info[row_of_cell(cell)+1][column_of_cell(cell)].cellno;
+       if (cellRow(cell) + 1 < rowCount())
+               return cell_info[cellRow(cell)+1][cellColumn(cell)].cellno;
        return cell;
 }
 
 
 Tabular::idx_type Tabular::getLastCellAbove(idx_type cell) const
 {
-       if (row_of_cell(cell) == 0)
+       if (cellRow(cell) == 0)
                return cell;
        if (!isMultiColumn(cell))
                return getCellAbove(cell);
-       return cell_info[row_of_cell(cell) - 1][right_column_of_cell(cell)].cellno;
+       return cell_info[cellRow(cell) - 1][cellRightColumn(cell)].cellno;
 }
 
 
 Tabular::idx_type Tabular::getLastCellBelow(idx_type cell) const
 {
-       if (row_of_cell(cell) + 1 >= rows_)
+       if (cellRow(cell) + 1 >= rowCount())
                return cell;
        if (!isMultiColumn(cell))
                return getCellBelow(cell);
-       return cell_info[row_of_cell(cell) + 1][right_column_of_cell(cell)].cellno;
+       return cell_info[cellRow(cell) + 1][cellRightColumn(cell)].cellno;
 }
 
 
-Tabular::idx_type Tabular::getCellNumber(row_type row,
+Tabular::idx_type Tabular::cellIndex(row_type row,
                                               col_type column) const
 {
-       BOOST_ASSERT(column != npos && column < columns_ &&
-                    row    != npos && row    < rows_);
+       BOOST_ASSERT(column != npos && column < columnCount() &&
+                    row    != npos && row    < rowCount());
        return cell_info[row][column].cellno;
 }
 
@@ -1784,7 +1774,7 @@ void Tabular::setUsebox(idx_type cell, BoxType type)
 
 Tabular::BoxType Tabular::getUsebox(idx_type cell) const
 {
-       if (column_info[column_of_cell(cell)].p_width.zero() &&
+       if (column_info[cellColumn(cell)].p_width.zero() &&
                !(isMultiColumn(cell) && !cellinfo_of_cell(cell).p_width.zero()))
                return BOX_NONE;
        if (cellinfo_of_cell(cell).usebox > 1)
@@ -1872,7 +1862,7 @@ bool Tabular::getLTNewPage(row_type row) const
 
 bool Tabular::haveLTHead() const
 {
-       for (row_type i = 0; i < rows_; ++i)
+       for (row_type i = 0; i < rowCount(); ++i)
                if (row_info[i].endhead)
                        return true;
        return false;
@@ -1883,7 +1873,7 @@ bool Tabular::haveLTFirstHead() const
 {
        if (endfirsthead.empty)
                return false;
-       for (row_type i = 0; i < rows_; ++i)
+       for (row_type i = 0; i < rowCount(); ++i)
                if (row_info[i].endfirsthead)
                        return true;
        return false;
@@ -1892,7 +1882,7 @@ bool Tabular::haveLTFirstHead() const
 
 bool Tabular::haveLTFoot() const
 {
-       for (row_type i = 0; i < rows_; ++i)
+       for (row_type i = 0; i < rowCount(); ++i)
                if (row_info[i].endfoot)
                        return true;
        return false;
@@ -1903,7 +1893,7 @@ bool Tabular::haveLTLastFoot() const
 {
        if (endlastfoot.empty)
                return false;
-       for (row_type i = 0; i < rows_; ++i)
+       for (row_type i = 0; i < rowCount(); ++i)
                if (row_info[i].endlastfoot)
                        return true;
        return false;
@@ -1912,42 +1902,42 @@ bool Tabular::haveLTLastFoot() const
 
 // end longtable support functions
 
-void Tabular::setAscentOfRow(row_type row, int height)
+void Tabular::setRowAscent(row_type row, int height)
 {
-       if (row >= rows_ || row_info[row].ascent_of_row == height)
+       if (row >= rowCount() || row_info[row].ascent == height)
                return;
-       row_info[row].ascent_of_row = height;
+       row_info[row].ascent = height;
 }
 
 
-void Tabular::setDescentOfRow(row_type row, int height)
+void Tabular::setRowDescent(row_type row, int height)
 {
-       if (row >= rows_ || row_info[row].descent_of_row == height)
+       if (row >= rowCount() || row_info[row].descent == height)
                return;
-       row_info[row].descent_of_row = height;
+       row_info[row].descent = height;
 }
 
 
-int Tabular::getAscentOfRow(row_type row) const
+int Tabular::rowAscent(row_type row) const
 {
-       if (row >= rows_)
+       if (row >= rowCount())
                return 0;
-       return row_info[row].ascent_of_row;
+       return row_info[row].ascent;
 }
 
 
-int Tabular::getDescentOfRow(row_type row) const
+int Tabular::rowDescent(row_type row) const
 {
-       BOOST_ASSERT(row < rows_);
-       return row_info[row].descent_of_row;
+       BOOST_ASSERT(row < rowCount());
+       return row_info[row].descent;
 }
 
 
-int Tabular::getHeightOfTabular() const
+int Tabular::height() const
 {
        int height = 0;
-       for (row_type row = 0; row < rows_; ++row)
-               height += getAscentOfRow(row) + getDescentOfRow(row) +
+       for (row_type row = 0; row < rowCount(); ++row)
+               height += rowAscent(row) + rowDescent(row) +
                        getAdditionalHeight(row);
        return height;
 }
@@ -1955,8 +1945,8 @@ int Tabular::getHeightOfTabular() const
 
 bool Tabular::isPartOfMultiColumn(row_type row, col_type column) const
 {
-       BOOST_ASSERT(row < rows_);
-       BOOST_ASSERT(column < columns_);
+       BOOST_ASSERT(row < rowCount());
+       BOOST_ASSERT(column < columnCount());
        return cell_info[row][column].multicolumn == CELL_PART_OF_MULTICOLUMN;
 }
 
@@ -1965,7 +1955,7 @@ int Tabular::TeXTopHLine(odocstream & os, row_type row) const
 {
        // FIXME: assert or return 0 as in TeXBottomHLine()?
        BOOST_ASSERT(row != npos);
-       BOOST_ASSERT(row < rows_);
+       BOOST_ASSERT(row < rowCount());
 
        idx_type const fcell = getFirstCellInRow(row);
        idx_type const n = numberOfCellsInRow(fcell) + fcell;
@@ -1976,16 +1966,17 @@ int Tabular::TeXTopHLine(odocstream & os, row_type row) const
                        ++tmp;
        }
        if (use_booktabs && row == 0) {
-               os << "\\toprule ";
+               if (topLine(fcell))
+                       os << "\\toprule ";
        } else if (tmp == n - fcell) {
                os << (use_booktabs ? "\\midrule " : "\\hline ");
        } else if (tmp) {
                for (idx_type i = fcell; i < n; ++i) {
                        if (topLine(i)) {
                                os << (use_booktabs ? "\\cmidrule{" : "\\cline{")
-                                  << column_of_cell(i) + 1
+                                  << cellColumn(i) + 1
                                   << '-'
-                                  << right_column_of_cell(i) + 1
+                                  << cellRightColumn(i) + 1
                                   << "} ";
                        }
                }
@@ -2000,7 +1991,7 @@ int Tabular::TeXTopHLine(odocstream & os, row_type row) const
 int Tabular::TeXBottomHLine(odocstream & os, row_type row) const
 {
        // FIXME: return 0 or assert as in TeXTopHLine()?
-       if (row == npos || row >= rows_)
+       if (row == npos || row >= rowCount())
                return 0;
 
        idx_type const fcell = getFirstCellInRow(row);
@@ -2011,17 +2002,18 @@ int Tabular::TeXBottomHLine(odocstream & os, row_type row) const
                if (bottomLine(i))
                        ++tmp;
        }
-       if (use_booktabs && row == rows_ - 1) {
-               os << "\\bottomrule";
+       if (use_booktabs && row == rowCount() - 1) {
+               if (bottomLine(fcell))
+                       os << "\\bottomrule";
        } else if (tmp == n - fcell) {
                os << (use_booktabs ? "\\midrule" : "\\hline");
        } else if (tmp) {
                for (idx_type i = fcell; i < n; ++i) {
                        if (bottomLine(i)) {
                                os << (use_booktabs ? "\\cmidrule{" : "\\cline{")
-                                  << column_of_cell(i) + 1
+                                  << cellColumn(i) + 1
                                   << '-'
-                                  << right_column_of_cell(i) + 1
+                                  << cellRightColumn(i) + 1
                                   << "} ";
                        }
                }
@@ -2082,7 +2074,7 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell) const
                } // end if else !cellinfo_of_cell
                if (rightLine(cell))
                        os << '|';
-               if (((cell + 1) < numberofcells) && !isFirstCellInRow(cell+1) &&
+               if (((cell + 1) < cellCount()) && !isFirstCellInRow(cell+1) &&
                        leftLine(cell+1))
                        os << '|';
                os << "}{";
@@ -2145,7 +2137,7 @@ int Tabular::TeXCellPostamble(odocstream & os, idx_type cell) const
 }
 
 
-int Tabular::TeXLongtableHeaderFooter(odocstream & os, Buffer const & buf,
+int Tabular::TeXLongtableHeaderFooter(odocstream & os,
                                         OutputParams const & runparams) const
 {
        if (!is_long_tabular)
@@ -2158,9 +2150,9 @@ int Tabular::TeXLongtableHeaderFooter(odocstream & os, Buffer const & buf,
                        os << "\\hline\n";
                        ++ret;
                }
-               for (row_type i = 0; i < rows_; ++i) {
+               for (row_type i = 0; i < rowCount(); ++i) {
                        if (row_info[i].endhead) {
-                               ret += TeXRow(os, i, buf, runparams);
+                               ret += TeXRow(os, i, runparams);
                        }
                }
                if (endhead.bottomDL) {
@@ -2180,9 +2172,9 @@ int Tabular::TeXLongtableHeaderFooter(odocstream & os, Buffer const & buf,
                        os << "\\hline\n";
                        ++ret;
                }
-               for (row_type i = 0; i < rows_; ++i) {
+               for (row_type i = 0; i < rowCount(); ++i) {
                        if (row_info[i].endfirsthead) {
-                               ret += TeXRow(os, i, buf, runparams);
+                               ret += TeXRow(os, i, runparams);
                        }
                }
                if (endfirsthead.bottomDL) {
@@ -2198,9 +2190,9 @@ int Tabular::TeXLongtableHeaderFooter(odocstream & os, Buffer const & buf,
                        os << "\\hline\n";
                        ++ret;
                }
-               for (row_type i = 0; i < rows_; ++i) {
+               for (row_type i = 0; i < rowCount(); ++i) {
                        if (row_info[i].endfoot) {
-                               ret += TeXRow(os, i, buf, runparams);
+                               ret += TeXRow(os, i, runparams);
                        }
                }
                if (endfoot.bottomDL) {
@@ -2220,9 +2212,9 @@ int Tabular::TeXLongtableHeaderFooter(odocstream & os, Buffer const & buf,
                        os << "\\hline\n";
                        ++ret;
                }
-               for (row_type i = 0; i < rows_; ++i) {
+               for (row_type i = 0; i < rowCount(); ++i) {
                        if (row_info[i].endlastfoot) {
-                               ret += TeXRow(os, i, buf, runparams);
+                               ret += TeXRow(os, i, runparams);
                        }
                }
                if (endlastfoot.bottomDL) {
@@ -2245,10 +2237,10 @@ bool Tabular::isValidRow(row_type row) const
 }
 
 
-int Tabular::TeXRow(odocstream & os, row_type i, Buffer const & buf,
+int Tabular::TeXRow(odocstream & os, row_type i,
                       OutputParams const & runparams) const
 {
-       idx_type cell = getCellNumber(i, 0);
+       idx_type cell = cellIndex(i, 0);
        int ret = TeXTopHLine(os, i);
        if (row_info[i].top_space_default) {
                if (use_booktabs)
@@ -2268,21 +2260,29 @@ int Tabular::TeXRow(odocstream & os, row_type i, Buffer const & buf,
                }
                ++ret;
        }
-       
-       for (col_type j = 0; j < columns_; ++j) {
+
+       for (col_type j = 0; j < columnCount(); ++j) {
                if (isPartOfMultiColumn(i, j))
                        continue;
                ret += TeXCellPreamble(os, cell);
                shared_ptr<InsetText> inset = getCellInset(cell);
 
                Paragraph const & par = inset->paragraphs().front();
-               bool rtl = par.isRightToLeftPar(buf.params())
+               bool rtl = par.isRTL(buffer().params())
                        && !par.empty()
                        && getPWidth(cell).zero();
 
-               if (rtl)
-                       os << "\\R{";
-               ret += inset->latex(buf, os, runparams);
+               if (rtl) {
+                       if (par.getParLanguage(buffer().params())->lang() ==
+                       "farsi")
+                               os << "\\textFR{";
+                       else if (par.getParLanguage(buffer().params())->lang() == "arabic_arabi")
+                               os << "\\textAR{";
+                       // currently, remaning RTL languages are arabic_arabtex and hebrew
+                       else
+                               os << "\\R{";
+               }
+               ret += inset->latex(os, runparams);
                if (rtl)
                        os << '}';
 
@@ -2329,8 +2329,7 @@ int Tabular::TeXRow(odocstream & os, row_type i, Buffer const & buf,
 }
 
 
-int Tabular::latex(Buffer const & buf, odocstream & os,
-                     OutputParams const & runparams) const
+int Tabular::latex(odocstream & os, OutputParams const & runparams) const
 {
        int ret = 0;
 
@@ -2346,7 +2345,7 @@ int Tabular::latex(Buffer const & buf, odocstream & os,
                os << "\\begin{longtable}{";
        else
                os << "\\begin{tabular}{";
-       for (col_type i = 0; i < columns_; ++i) {
+       for (col_type i = 0; i < columnCount(); ++i) {
                if (!use_booktabs && column_info[i].left_line)
                        os << '|';
                if (!column_info[i].align_special.empty()) {
@@ -2404,15 +2403,15 @@ int Tabular::latex(Buffer const & buf, odocstream & os,
        os << "}\n";
        ++ret;
 
-       ret += TeXLongtableHeaderFooter(os, buf, runparams);
+       ret += TeXLongtableHeaderFooter(os, runparams);
 
        //+---------------------------------------------------------------------
        //+                      the single row and columns (cells)            +
        //+---------------------------------------------------------------------
 
-       for (row_type i = 0; i < rows_; ++i) {
+       for (row_type i = 0; i < rowCount(); ++i) {
                if (isValidRow(i)) {
-                       ret += TeXRow(os, i, buf, runparams);
+                       ret += TeXRow(os, i, runparams);
                        if (is_long_tabular && row_info[i].newpage) {
                                os << "\\newpage\n";
                                ++ret;
@@ -2437,14 +2436,14 @@ int Tabular::latex(Buffer const & buf, odocstream & os,
 }
 
 
-int Tabular::docbookRow(Buffer const & buf, odocstream & os, row_type row,
+int Tabular::docbookRow(odocstream & os, row_type row,
                           OutputParams const & runparams) const
 {
        int ret = 0;
        idx_type cell = getFirstCellInRow(row);
 
        os << "<row>\n";
-       for (col_type j = 0; j < columns_; ++j) {
+       for (col_type j = 0; j < columnCount(); ++j) {
                if (isPartOfMultiColumn(row, j))
                        continue;
 
@@ -2480,7 +2479,7 @@ int Tabular::docbookRow(Buffer const & buf, odocstream & os, row_type row,
                }
 
                os << '>';
-               ret += getCellInset(cell)->docbook(buf, os, runparams);
+               ret += getCellInset(cell)->docbook(os, runparams);
                os << "</entry>\n";
                ++cell;
        }
@@ -2489,8 +2488,7 @@ int Tabular::docbookRow(Buffer const & buf, odocstream & os, row_type row,
 }
 
 
-int Tabular::docbook(Buffer const & buf, odocstream & os,
-                       OutputParams const & runparams) const
+int Tabular::docbook(odocstream & os, OutputParams const & runparams) const
 {
        int ret = 0;
 
@@ -2498,10 +2496,10 @@ int Tabular::docbook(Buffer const & buf, odocstream & os,
        //+                      first the opening preamble                    +
        //+---------------------------------------------------------------------
 
-       os << "<tgroup cols=\"" << columns_
+       os << "<tgroup cols=\"" << columnCount()
           << "\" colsep=\"1\" rowsep=\"1\">\n";
 
-       for (col_type i = 0; i < columns_; ++i) {
+       for (col_type i = 0; i < columnCount(); ++i) {
                os << "<colspec colname=\"col" << i << "\" align=\"";
                switch (column_info[i].alignment) {
                case LYX_ALIGN_LEFT:
@@ -2529,9 +2527,9 @@ int Tabular::docbook(Buffer const & buf, odocstream & os,
        if (haveLTHead() || haveLTFirstHead()) {
                os << "<thead>\n";
                ++ret;
-               for (row_type i = 0; i < rows_; ++i) {
+               for (row_type i = 0; i < rowCount(); ++i) {
                        if (row_info[i].endhead || row_info[i].endfirsthead) {
-                               ret += docbookRow(buf, os, i, runparams);
+                               ret += docbookRow(os, i, runparams);
                        }
                }
                os << "</thead>\n";
@@ -2541,9 +2539,9 @@ int Tabular::docbook(Buffer const & buf, odocstream & os,
        if (haveLTFoot() || haveLTLastFoot()) {
                os << "<tfoot>\n";
                ++ret;
-               for (row_type i = 0; i < rows_; ++i) {
+               for (row_type i = 0; i < rowCount(); ++i) {
                        if (row_info[i].endfoot || row_info[i].endlastfoot) {
-                               ret += docbookRow(buf, os, i, runparams);
+                               ret += docbookRow(os, i, runparams);
                        }
                }
                os << "</tfoot>\n";
@@ -2556,9 +2554,9 @@ int Tabular::docbook(Buffer const & buf, odocstream & os,
 
        os << "<tbody>\n";
        ++ret;
-       for (row_type i = 0; i < rows_; ++i) {
+       for (row_type i = 0; i < rowCount(); ++i) {
                if (isValidRow(i)) {
-                       ret += docbookRow(buf, os, i, runparams);
+                       ret += docbookRow(os, i, runparams);
                }
        }
        os << "</tbody>\n";
@@ -2575,7 +2573,7 @@ int Tabular::docbook(Buffer const & buf, odocstream & os,
 
 
 bool Tabular::plaintextTopHLine(odocstream & os, row_type row,
-                                   vector<unsigned int> const & clen) const
+                                  vector<unsigned int> const & clen) const
 {
        idx_type const fcell = getFirstCellInRow(row);
        idx_type const n = numberOfCellsInRow(fcell) + fcell;
@@ -2602,9 +2600,9 @@ bool Tabular::plaintextTopHLine(odocstream & os, row_type row,
                        os << "  ";
                        ch = ' ';
                }
-               col_type column = column_of_cell(i);
+               col_type column = cellColumn(i);
                int len = clen[column];
-               while (column < columns_ - 1
+               while (column < columnCount() - 1
                       && isPartOfMultiColumn(row, ++column))
                        len += clen[column] + 4;
                os << docstring(len, ch);
@@ -2623,7 +2621,7 @@ bool Tabular::plaintextTopHLine(odocstream & os, row_type row,
 
 
 bool Tabular::plaintextBottomHLine(odocstream & os, row_type row,
-                                      vector<unsigned int> const & clen) const
+                                     vector<unsigned int> const & clen) const
 {
        idx_type const fcell = getFirstCellInRow(row);
        idx_type const n = numberOfCellsInRow(fcell) + fcell;
@@ -2650,9 +2648,9 @@ bool Tabular::plaintextBottomHLine(odocstream & os, row_type row,
                        os << "  ";
                        ch = ' ';
                }
-               col_type column = column_of_cell(i);
+               col_type column = cellColumn(i);
                int len = clen[column];
-               while (column < columns_ -1
+               while (column < columnCount() -1
                       && isPartOfMultiColumn(row, ++column))
                        len += clen[column] + 4;
                os << docstring(len, ch);
@@ -2670,14 +2668,14 @@ bool Tabular::plaintextBottomHLine(odocstream & os, row_type row,
 }
 
 
-void Tabular::plaintextPrintCell(Buffer const & buf, odocstream & os,
+void Tabular::plaintextPrintCell(odocstream & os,
                               OutputParams const & runparams,
                               idx_type cell, row_type row, col_type column,
                               vector<unsigned int> const & clen,
                               bool onlydata) const
 {
        odocstringstream sstr;
-       getCellInset(cell)->plaintext(buf, sstr, runparams);
+       getCellInset(cell)->plaintext(sstr, runparams);
 
        if (onlydata) {
                os << sstr.str();
@@ -2691,7 +2689,7 @@ void Tabular::plaintextPrintCell(Buffer const & buf, odocstream & os,
 
        unsigned int len1 = sstr.str().length();
        unsigned int len2 = clen[column];
-       while (column < columns_ -1
+       while (column < columnCount() -1
               && isPartOfMultiColumn(row, ++column))
                len2 += clen[column] + 4;
        len2 -= len1;
@@ -2721,35 +2719,35 @@ void Tabular::plaintextPrintCell(Buffer const & buf, odocstream & os,
 }
 
 
-void Tabular::plaintext(Buffer const & buf, odocstream & os,
-                           OutputParams const & runparams, int const depth,
-                           bool onlydata, unsigned char delim) const
+void Tabular::plaintext(odocstream & os,
+                          OutputParams const & runparams, int const depth,
+                          bool onlydata, char_type delim) const
 {
        // first calculate the width of the single columns
-       vector<unsigned int> clen(columns_);
+       vector<unsigned int> clen(columnCount());
 
        if (!onlydata) {
                // first all non (real) multicolumn cells!
-               for (col_type j = 0; j < columns_; ++j) {
+               for (col_type j = 0; j < columnCount(); ++j) {
                        clen[j] = 0;
-                       for (row_type i = 0; i < rows_; ++i) {
-                               idx_type cell = getCellNumber(i, j);
+                       for (row_type i = 0; i < rowCount(); ++i) {
+                               idx_type cell = cellIndex(i, j);
                                if (isMultiColumnReal(cell))
                                        continue;
                                odocstringstream sstr;
-                               getCellInset(cell)->plaintext(buf, sstr, runparams);
+                               getCellInset(cell)->plaintext(sstr, runparams);
                                if (clen[j] < sstr.str().length())
                                        clen[j] = sstr.str().length();
                        }
                }
                // then all (real) multicolumn cells!
-               for (col_type j = 0; j < columns_; ++j) {
-                       for (row_type i = 0; i < rows_; ++i) {
-                               idx_type cell = getCellNumber(i, j);
+               for (col_type j = 0; j < columnCount(); ++j) {
+                       for (row_type i = 0; i < rowCount(); ++i) {
+                               idx_type cell = cellIndex(i, j);
                                if (!isMultiColumnReal(cell) || isPartOfMultiColumn(i, j))
                                        continue;
                                odocstringstream sstr;
-                               getCellInset(cell)->plaintext(buf, sstr, runparams);
+                               getCellInset(cell)->plaintext(sstr, runparams);
                                int len = int(sstr.str().length());
                                idx_type const n = cells_in_multicolumn(cell);
                                for (col_type k = j; len > 0 && k < j + n - 1; ++k)
@@ -2760,16 +2758,17 @@ void Tabular::plaintext(Buffer const & buf, odocstream & os,
                }
        }
        idx_type cell = 0;
-       for (row_type i = 0; i < rows_; ++i) {
+       for (row_type i = 0; i < rowCount(); ++i) {
                if (!onlydata && plaintextTopHLine(os, i, clen))
                        os << docstring(depth * 2, ' ');
-               for (col_type j = 0; j < columns_; ++j) {
+               for (col_type j = 0; j < columnCount(); ++j) {
                        if (isPartOfMultiColumn(i, j))
                                continue;
                        if (onlydata && j > 0)
-                               os << delim;
-                       plaintextPrintCell(buf, os, runparams,
-                                          cell, i, j, clen, onlydata);
+                               // we don't use operator<< for single UCS4 character.
+                               // see explanation in docstream.h
+                               os.put(delim);
+                       plaintextPrintCell(os, runparams, cell, i, j, clen, onlydata);
                        ++cell;
                }
                os << endl;
@@ -2784,7 +2783,7 @@ void Tabular::plaintext(Buffer const & buf, odocstream & os,
 
 shared_ptr<InsetText> Tabular::getCellInset(idx_type cell) const
 {
-       return cell_info[row_of_cell(cell)][column_of_cell(cell)].inset;
+       return cell_info[cellRow(cell)][cellColumn(cell)].inset;
 }
 
 
@@ -2803,7 +2802,7 @@ void Tabular::setCellInset(row_type row, col_type column,
 
 
 Tabular::idx_type
-Tabular::getCellFromInset(InsetBase const * inset) const
+Tabular::getCellFromInset(Inset const * inset) const
 {
        // is this inset part of the tabular?
        if (!inset) {
@@ -2811,10 +2810,10 @@ Tabular::getCellFromInset(InsetBase const * inset) const
                BOOST_ASSERT(false);
        }
 
-       for (idx_type cell = 0, n = getNumberOfCells(); cell < n; ++cell)
+       for (idx_type cell = 0, n = cellCount(); cell < n; ++cell)
                if (getCellInset(cell).get() == inset) {
-                       LYXERR(Debug::INSETTEXT) << "Tabular::getCellFromInset: "
-                               << "cell=" << cell << endl;
+                       LYXERR(Debug::INSETTEXT, "Tabular::getCellFromInset: "
+                               << "cell=" << cell);
                        return cell;
                }
 
@@ -2836,7 +2835,7 @@ void Tabular::validate(LaTeXFeatures & features) const
                features.require("longtable");
        if (needRotating())
                features.require("rotating");
-       for (idx_type cell = 0; cell < numberofcells; ++cell) {
+       for (idx_type cell = 0; cell < cellCount(); ++cell) {
                if (getVAlignment(cell) != LYX_VALIGN_TOP ||
                     (!getPWidth(cell).zero() && !isMultiColumn(cell)))
                        features.require("array");
@@ -2868,54 +2867,52 @@ Tabular::BoxType Tabular::useParbox(idx_type cell) const
 
 InsetTabular::InsetTabular(Buffer const & buf, row_type rows,
                           col_type columns)
-       : tabular(buf.params(), max(rows, row_type(1)),
-         max(columns, col_type(1))), buffer_(&buf), scx_(0), is_deleted_(false)
-{}
+       : tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))), scx_(0)
+{
+       setBuffer(const_cast<Buffer &>(buf)); // FIXME: remove later
+}
 
 
 InsetTabular::InsetTabular(InsetTabular const & tab)
-       : InsetOld(tab), tabular(tab.tabular),
-               buffer_(tab.buffer_), scx_(0), is_deleted_(false)
-{}
+       : Inset(tab), tabular(tab.tabular),  scx_(0)
+{
+       setBuffer(const_cast<Buffer &>(tab.buffer())); // FIXME: remove later
+}
 
 
 InsetTabular::~InsetTabular()
 {
        InsetTabularMailer(*this).hideDialog();
-       is_deleted_ = true;
 }
 
 
-auto_ptr<InsetBase> InsetTabular::doClone() const
+Inset * InsetTabular::clone() const
 {
-       return auto_ptr<InsetBase>(new InsetTabular(*this));
+       return new InsetTabular(*this);
 }
 
 
-Buffer const & InsetTabular::buffer() const
+bool InsetTabular::insetAllowed(InsetCode code) const
 {
-       return *buffer_;
-}
-
+       if (code == MATHMACRO_CODE)
+               return false;
 
-void InsetTabular::buffer(Buffer const * b)
-{
-       buffer_ = b;
+       return true;
 }
 
 
-void InsetTabular::write(Buffer const & buf, ostream & os) const
+void InsetTabular::write(ostream & os) const
 {
        os << "Tabular" << endl;
-       tabular.write(buf, os);
+       tabular.write(os);
 }
 
 
-void InsetTabular::read(Buffer const & buf, Lexer & lex)
+void InsetTabular::read(Lexer & lex)
 {
        bool const old_format = (lex.getString() == "\\LyXTable");
 
-       tabular.read(buf, lex);
+       tabular.read(lex);
 
        if (old_format)
                return;
@@ -2933,7 +2930,7 @@ void InsetTabular::read(Buffer const & buf, Lexer & lex)
 }
 
 
-bool InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
+void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        //lyxerr << "InsetTabular::metrics: " << mi.base.bv << " width: " <<
        //      mi.base.textwidth << "\n";
@@ -2943,10 +2940,10 @@ bool InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
        }
 
        row_type i = 0;
-       for (idx_type cell = 0; i < tabular.rows(); ++i) {
+       for (idx_type cell = 0; i < tabular.rowCount(); ++i) {
                int maxAsc = 0;
                int maxDesc = 0;
-               for (col_type j = 0; j < tabular.columns(); ++j) {
+               for (col_type j = 0; j < tabular.columnCount(); ++j) {
                        if (tabular.isPartOfMultiColumn(i, j))
                                // Multicolumn cell, but not first one
                                continue;
@@ -2963,7 +2960,7 @@ bool InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
                        tabular.getCellInset(cell)->metrics(m, dim);
                        if (!p_width.zero())
                                dim.wid = m.base.textwidth;
-                       tabular.setWidthOfCell(cell, dim.wid);
+                       tabular.setCellWidth(cell, dim.wid);
                        if (p_width.zero()) {
                                m.base.textwidth = dim.wid + 2 * ADD_TO_TABULAR_WIDTH;
                                // FIXME there must be a way to get rid of
@@ -2977,66 +2974,69 @@ bool InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
                int const top_space = tabular.row_info[i].top_space_default ?
                        default_line_space :
                        tabular.row_info[i].top_space.inPixels(mi.base.textwidth);
-               tabular.setAscentOfRow(i, maxAsc + ADD_TO_HEIGHT + top_space);
+               tabular.setRowAscent(i, maxAsc + ADD_TO_HEIGHT + top_space);
                int const bottom_space = tabular.row_info[i].bottom_space_default ?
                        default_line_space :
                        tabular.row_info[i].bottom_space.inPixels(mi.base.textwidth);
-               tabular.setDescentOfRow(i, maxDesc + ADD_TO_HEIGHT + bottom_space);
+               tabular.setRowDescent(i, maxDesc + ADD_TO_HEIGHT + bottom_space);
        }
 
-       dim.asc = tabular.getAscentOfRow(0);
-       dim.des = tabular.getHeightOfTabular() - dim.asc;
-       dim.wid = tabular.getWidthOfTabular() + 2 * ADD_TO_TABULAR_WIDTH;
-       bool const changed = dim_ != dim;
-       dim_ = dim;
-       return changed;
+       dim.asc = tabular.rowAscent(0);
+       dim.des = tabular.height() - dim.asc;
+       dim.wid = tabular.width() + 2 * ADD_TO_TABULAR_WIDTH;
 }
 
 
 void InsetTabular::draw(PainterInfo & pi, int x, int y) const
 {
-       setPosCache(pi, x, y);
-
        //lyxerr << "InsetTabular::draw: " << x << " " << y << endl;
        BufferView * bv = pi.base.bv;
 
+       // FIXME: As the full backrgound is painted in drawSelection(),
+       // we have no choice but to do a full repaint for the Text cells.
+       pi.full_repaint = true;
+
        resetPos(bv->cursor());
 
        x += scx_;
        x += ADD_TO_TABULAR_WIDTH;
 
+       bool const original_drawing_state = pi.pain.isDrawingEnabled();
+
        idx_type idx = 0;
        first_visible_cell = Tabular::npos;
-       for (row_type i = 0; i < tabular.rows(); ++i) {
+       for (row_type i = 0; i < tabular.rowCount(); ++i) {
                int nx = x;
-               int const a = tabular.getAscentOfRow(i);
-               int const d = tabular.getDescentOfRow(i);
-               idx = tabular.getCellNumber(i, 0);
-               for (col_type j = 0; j < tabular.columns(); ++j) {
+               int const a = tabular.rowAscent(i);
+               int const d = tabular.rowDescent(i);
+               idx = tabular.cellIndex(i, 0);
+               for (col_type j = 0; j < tabular.columnCount(); ++j) {
                        if (tabular.isPartOfMultiColumn(i, j))
                                continue;
                        if (first_visible_cell == Tabular::npos)
                                first_visible_cell = idx;
 
                        int const cx = nx + tabular.getBeginningOfTextInCell(idx);
-                       if (nx + tabular.getWidthOfColumn(idx) < 0
+                       // Cache the Inset position.
+                       bv->coordCache().insets().add(cell(idx).get(), cx, y);
+                       if (nx + tabular.columnWidth(idx) < 0
                            || nx > bv->workWidth()
                            || y + d < 0
                            || y - a > bv->workHeight()) {
                                pi.pain.setDrawingEnabled(false);
                                cell(idx)->draw(pi, cx, y);
                                drawCellLines(pi.pain, nx, y, i, idx, pi.erased_);
-                               pi.pain.setDrawingEnabled(true);
+                               pi.pain.setDrawingEnabled(original_drawing_state);
                        } else {
                                cell(idx)->draw(pi, cx, y);
                                drawCellLines(pi.pain, nx, y, i, idx, pi.erased_);
                        }
-                       nx += tabular.getWidthOfColumn(idx);
+                       nx += tabular.columnWidth(idx);
                        ++idx;
                }
 
-               if (i + 1 < tabular.rows())
-                       y += d + tabular.getAscentOfRow(i + 1) +
+               if (i + 1 < tabular.rowCount())
+                       y += d + tabular.rowAscent(i + 1) +
                                tabular.getAdditionalHeight(i + 1);
        }
 }
@@ -3044,21 +3044,22 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
 
 void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
 {
-       setPosCache(pi, x, y);
-
        Cursor & cur = pi.base.bv->cursor();
 
        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.getWidthOfTabular();
-       int const h = tabular.getHeightOfTabular();
-       int yy = y - tabular.getAscentOfRow(0);
+       int const w = tabular.width();
+       int const h = tabular.height();
+       int yy = y - tabular.rowAscent(0);
        pi.pain.fillRectangle(x, yy, w, h, backgroundColor());
 
        if (!cur.selection())
                return;
-       if (!ptr_cmp(&cur.inset(), this))
+       if (&cur.inset() != this)
                return;
 
        //resetPos(cur);
@@ -3068,28 +3069,30 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
                row_type rs, re;
                col_type cs, ce;
                getSelection(cur, rs, re, cs, ce);
-               y -= tabular.getAscentOfRow(0);
-               for (row_type j = 0; j < tabular.rows(); ++j) {
-                       int const a = tabular.getAscentOfRow(j);
-                       int const h = a + tabular.getDescentOfRow(j);
+               y -= tabular.rowAscent(0);
+               for (row_type j = 0; j < tabular.rowCount(); ++j) {
+                       int const a = tabular.rowAscent(j);
+                       int const h = a + tabular.rowDescent(j);
                        int xx = x;
                        y += tabular.getAdditionalHeight(j);
-                       for (col_type i = 0; i < tabular.columns(); ++i) {
+                       for (col_type i = 0; i < tabular.columnCount(); ++i) {
                                if (tabular.isPartOfMultiColumn(j, i))
                                        continue;
                                idx_type const cell =
-                                       tabular.getCellNumber(j, i);
-                               int const w = tabular.getWidthOfColumn(cell);
+                                       tabular.cellIndex(j, i);
+                               int const w = tabular.columnWidth(cell);
                                if (i >= cs && i <= ce && j >= rs && j <= re)
                                        pi.pain.fillRectangle(xx, y, w, h,
-                                                             Color::selection);
+                                                             Color_selection);
                                xx += w;
                        }
                        y += h;
                }
 
        } else {
-               cur.text()->drawSelection(pi, x + getCellXPos(cur.idx()) + tabular.getBeginningOfTextInCell(cur.idx()), 0 /*this value is ignored */);
+               x += getCellXPos(cur.idx());
+               x += tabular.getBeginningOfTextInCell(cur.idx());
+               cell(cur.idx())->drawSelection(pi, x, 0 /* ignored */);
        }
 }
 
@@ -3097,58 +3100,58 @@ 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, bool erased) const
 {
-       int x2 = x + tabular.getWidthOfColumn(cell);
+       int x2 = x + tabular.columnWidth(cell);
        bool on_off = false;
-       Color::color col = Color::tabularline;
-       Color::color onoffcol = Color::tabularonoffline;
+       ColorCode col = Color_tabularline;
+       ColorCode onoffcol = Color_tabularonoffline;
 
        if (erased) {
-               col = Color::strikeout;
-               onoffcol = Color::strikeout;
+               col = Color_deletedtext;
+               onoffcol = Color_deletedtext;
        }
 
        if (!tabular.topAlreadyDrawn(cell)) {
                on_off = !tabular.topLine(cell);
-               pain.line(x, y - tabular.getAscentOfRow(row),
-                         x2, y -  tabular.getAscentOfRow(row),
+               pain.line(x, y - tabular.rowAscent(row),
+                         x2, y -  tabular.rowAscent(row),
                          on_off ? onoffcol : col,
                          on_off ? Painter::line_onoffdash : Painter::line_solid);
        }
        on_off = !tabular.bottomLine(cell);
-       pain.line(x, y + tabular.getDescentOfRow(row),
-                 x2, y + tabular.getDescentOfRow(row),
+       pain.line(x, y + tabular.rowDescent(row),
+                 x2, y + tabular.rowDescent(row),
                  on_off ? onoffcol : col,
                  on_off ? Painter::line_onoffdash : Painter::line_solid);
        if (!tabular.leftAlreadyDrawn(cell)) {
                on_off = !tabular.leftLine(cell);
-               pain.line(x, y -  tabular.getAscentOfRow(row),
-                         x, y +  tabular.getDescentOfRow(row),
+               pain.line(x, y -  tabular.rowAscent(row),
+                         x, y +  tabular.rowDescent(row),
                          on_off ? onoffcol : col,
                          on_off ? Painter::line_onoffdash : Painter::line_solid);
        }
        on_off = !tabular.rightLine(cell);
        pain.line(x2 - tabular.getAdditionalWidth(cell),
-                 y -  tabular.getAscentOfRow(row),
+                 y -  tabular.rowAscent(row),
                  x2 - tabular.getAdditionalWidth(cell),
-                 y +  tabular.getDescentOfRow(row),
+                 y +  tabular.rowDescent(row),
                  on_off ? onoffcol : col,
                  on_off ? Painter::line_onoffdash : Painter::line_solid);
 }
 
 
-docstring const InsetTabular::editMessage() const
+docstring InsetTabular::editMessage() const
 {
        return _("Opened table");
 }
 
 
-void InsetTabular::edit(Cursor & cur, bool left)
+void InsetTabular::edit(Cursor & cur, bool front, EntryDirection)
 {
        //lyxerr << "InsetTabular::edit: " << this << endl;
-       finishUndo();
+       cur.finishUndo();
        cur.selection() = false;
        cur.push(*this);
-       if (left) {
+       if (front) {
                if (isRightToLeft(cur))
                        cur.idx() = tabular.getLastCellInRow(0);
                else
@@ -3157,9 +3160,9 @@ void InsetTabular::edit(Cursor & cur, bool left)
                cur.pos() = 0;
        } else {
                if (isRightToLeft(cur))
-                       cur.idx() = tabular.getFirstCellInRow(tabular.rows() - 1);
+                       cur.idx() = tabular.getFirstCellInRow(tabular.rowCount() - 1);
                else
-                       cur.idx() = tabular.getNumberOfCells() - 1;
+                       cur.idx() = tabular.cellCount() - 1;
                cur.pit() = 0;
                cur.pos() = cur.lastpos(); // FIXME crude guess
        }
@@ -3169,10 +3172,30 @@ void InsetTabular::edit(Cursor & cur, bool left)
 }
 
 
+void InsetTabular::updateLabels(ParIterator const & it)
+{
+       // In a longtable, tell captions what the current float is
+       Counters & cnts = buffer().params().documentClass().counters();
+       string const saveflt = cnts.current_float();
+       if (tabular.isLongTabular())
+               cnts.current_float("table");
+
+       ParIterator it2 = it;
+       it2.forwardPos();
+       size_t const end = it2.nargs();
+       for ( ; it2.idx() < end; it2.top().forwardIdx())
+               lyx::updateLabels(buffer(), it2);
+
+       //reset afterwards
+       if (tabular.isLongTabular())
+               cnts.current_float(saveflt);
+}
+
+
 void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 {
-       LYXERR(Debug::DEBUG) << "# InsetTabular::doDispatch: cmd: " << cmd
-                            << "\n  cur:" << cur << endl;
+       LYXERR(Debug::DEBUG, "# InsetTabular::doDispatch: cmd: " << cmd
+                            << "\n  cur:" << cur);
        CursorSlice sl = cur.top();
        Cursor & bvcur = cur.bv().cursor();
 
@@ -3181,33 +3204,16 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_MOUSE_PRESS:
                //lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl;
 
-               if (cmd.button() == mouse_button::button1 
-                   || (cmd.button() == mouse_button::button3 
-                       && (&bvcur.selBegin().inset() != this || !tablemode(bvcur)))) {
-                       if (!bvcur.selection() && !cur.bv().mouseSetCursor(cur))
-                               cur.noUpdate();
-                       cur.selection() = false;
-                       setCursorFromCoordinates(cur, cmd.x, cmd.y);
-                       cur.bv().mouseSetCursor(cur);
-                       break;
-               }
-
-               if (cmd.button() == mouse_button::button2) {
-                       if (cap::selection()) {
-                               // See comment in LyXText::dispatch why we
-                               // do this
-                               // FIXME This does not use paste_tabular,
-                               // another reason why paste_tabular should go.
-                               cap::copySelectionToStack();
-                               cmd = FuncRequest(LFUN_PASTE, "0");
-                       } else {
-                               cmd = FuncRequest(LFUN_PRIMARY_SELECTION_PASTE,
-                                                 "paragraph");
-                       }
-                       doDispatch(cur, cmd);
-               }
+               // do not reset cursor/selection if we have selected
+               // some cells (bug 2715).
+               if (cmd.button() == mouse_button::button3
+                   && &bvcur.selBegin().inset() == this 
+                   && tablemode(bvcur)) 
+                       ;
+               else
+                       // Let InsetText do it
+                       cell(cur.idx())->dispatch(cur, cmd);
                break;
-
        case LFUN_MOUSE_MOTION:
                //lyxerr << "# InsetTabular::MouseMotion\n" << bvcur << endl;
                if (cmd.button() == mouse_button::button1) {
@@ -3227,39 +3233,27 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_MOUSE_RELEASE:
                //lyxerr << "# InsetTabular::MouseRelease\n" << bvcur << endl;
-               if (cmd.button() == mouse_button::button1) {
-                       if (bvcur.selection()) {
-                               // Bug3238: disable persistent selection for table cells for now
-                               if (tablemode(bvcur))
-                                       theSelection().haveSelection(true);
-                               else
-                                       saveSelection(bvcur);
-                       }
-               } else if (cmd.button() == mouse_button::button3)
+               if (cmd.button() == mouse_button::button3)
                        InsetTabularMailer(*this).showDialog(&cur.bv());
                break;
 
        case LFUN_CELL_BACKWARD:
                movePrevCell(cur);
                cur.selection() = false;
-               saveSelection(cur);
                break;
 
        case LFUN_CELL_FORWARD:
                moveNextCell(cur);
                cur.selection() = false;
-               saveSelection(cur);
                break;
 
        case LFUN_CHAR_FORWARD_SELECT:
        case LFUN_CHAR_FORWARD:
                cell(cur.idx())->dispatch(cur, cmd);
                if (!cur.result().dispatched()) {
-                       isRightToLeft(cur) ? movePrevCell(cur) : moveNextCell(cur);
-                       if (cmd.action == LFUN_CHAR_FORWARD_SELECT)
-                               saveSelection(cur);
+                       moveNextCell(cur);
                        if (sl == cur.top())
-                               cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                               cmd = FuncRequest(LFUN_FINISHED_FORWARD);
                        else
                                cur.dispatched();
                }
@@ -3269,42 +3263,59 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_CHAR_BACKWARD:
                cell(cur.idx())->dispatch(cur, cmd);
                if (!cur.result().dispatched()) {
-                       isRightToLeft(cur) ? moveNextCell(cur) : movePrevCell(cur);
-                       if (cmd.action == LFUN_CHAR_BACKWARD_SELECT)
-                               saveSelection(cur);
+                       movePrevCell(cur);
                        if (sl == cur.top())
-                               cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                               cmd = FuncRequest(LFUN_FINISHED_BACKWARD);
                        else
                                cur.dispatched();
                }
                break;
 
+       case LFUN_CHAR_RIGHT_SELECT:
+       case LFUN_CHAR_RIGHT:
+               //FIXME: for visual cursor, really move right
+               if (isRightToLeft(cur))
+                       lyx::dispatch(FuncRequest(
+                               cmd.action == LFUN_CHAR_RIGHT_SELECT ?
+                                       LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD));
+               else
+                       lyx::dispatch(FuncRequest(
+                               cmd.action == LFUN_CHAR_RIGHT_SELECT ?
+                                       LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD));
+               break;
+
+       case LFUN_CHAR_LEFT_SELECT:
+       case LFUN_CHAR_LEFT:
+               //FIXME: for visual cursor, really move left
+               if (isRightToLeft(cur))
+                       lyx::dispatch(FuncRequest(
+                               cmd.action == LFUN_CHAR_LEFT_SELECT ?
+                                       LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD));
+               else
+                       lyx::dispatch(FuncRequest(
+                               cmd.action == LFUN_CHAR_LEFT_SELECT ?
+                                       LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD));
+               break;
+
        case LFUN_DOWN_SELECT:
        case LFUN_DOWN:
                cell(cur.idx())->dispatch(cur, cmd);
                cur.dispatched(); // override the cell's decision
                if (sl == cur.top())
-                       // if our LyXText didn't do anything to the cursor
+                       // 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.
-                       if (tabular.row_of_cell(cur.idx()) != tabular.rows() - 1) {
+                       if (tabular.cellRow(cur.idx()) != tabular.rowCount() - 1) {
                                cur.idx() = tabular.getCellBelow(cur.idx());
                                cur.pit() = 0;
                                TextMetrics const & tm =
                                        cur.bv().textMetrics(cell(cur.idx())->getText(0));
                                cur.pos() = tm.x2pos(cur.pit(), 0, cur.targetX());
-                               if (cmd.action == LFUN_DOWN_SELECT) {
-                                       // Bug3238: disable persistent selection for table cells for now
-                                       if (tablemode(cur))
-                                               theSelection().haveSelection(true);
-                                       else
-                                               saveSelection(cur);
-                               }
                        }
                if (sl == cur.top()) {
-                       // we trick it to go to the RIGHT after leaving the
+                       // we trick it to go to forward after leaving the
                        // tabular.
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cmd = FuncRequest(LFUN_FINISHED_FORWARD);
                        cur.undispatched();
                }
                break;
@@ -3314,27 +3325,20 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                cell(cur.idx())->dispatch(cur, cmd);
                cur.dispatched(); // override the cell's decision
                if (sl == cur.top())
-                       // if our LyXText didn't do anything to the cursor
+                       // 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.
-                       if (tabular.row_of_cell(cur.idx()) != 0) {
+                       if (tabular.cellRow(cur.idx()) != 0) {
                                cur.idx() = tabular.getCellAbove(cur.idx());
                                cur.pit() = cur.lastpit();
-                               LyXText const * text = cell(cur.idx())->getText(0);
+                               Text const * text = cell(cur.idx())->getText(0);
                                TextMetrics const & tm = cur.bv().textMetrics(text);
                                ParagraphMetrics const & pm =
                                        tm.parMetrics(cur.lastpit());
                                cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, cur.targetX());
-                               if (cmd.action == LFUN_UP_SELECT) {
-                                       // Bug3238: disable persistent selection for table cells for now
-                                       if (tablemode(cur))
-                                               theSelection().haveSelection(true);
-                                       else
-                                               saveSelection(cur);
-                               }
                        }
                if (sl == cur.top()) {
-                       cmd = FuncRequest(LFUN_FINISHED_UP);
+                       cmd = FuncRequest(LFUN_UP);
                        cur.undispatched();
                }
                break;
@@ -3342,7 +3346,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 //     case LFUN_SCREEN_DOWN: {
 //             //if (hasSelection())
 //             //      cur.selection() = false;
-//             col_type const col = tabular.column_of_cell(cur.idx());
+//             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);
@@ -3358,7 +3362,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 //     case LFUN_SCREEN_UP: {
 //             //if (hasSelection())
 //             //      cur.selection() = false;
-//             col_type const col = tabular.column_of_cell(cur.idx());
+//             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);
@@ -3391,8 +3395,18 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_FILE_INSERT_PLAINTEXT_PARA:
        case LFUN_FILE_INSERT_PLAINTEXT: {
                // FIXME UNICODE
-               docstring const tmpstr = getContentsOfPlaintextFile(&cur.bv(), to_utf8(cmd.argument()), false);
-               if (!tmpstr.empty() && !insertPlaintextString(cur.bv(), tmpstr, false))
+               docstring const tmpstr = cur.bv().contentsOfPlaintextFile(
+                       FileName(to_utf8(cmd.argument())));
+               if (tmpstr.empty())
+                       break;
+               cur.recordUndoInset(INSERT_UNDO);
+               if (insertPlaintextString(cur.bv(), tmpstr, false)) {
+                       // content has been replaced,
+                       // so cursor might be invalid
+                       cur.pos() = cur.lastpos();
+                       cur.pit() = cur.lastpit();
+                       bvcur.setCursor(cur);
+               } else
                        cur.undispatched();
                break;
        }
@@ -3400,7 +3414,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_CUT:
                if (tablemode(cur)) {
                        if (copySelection(cur)) {
-                               recordUndoInset(cur, Undo::DELETE);
+                               cur.recordUndoInset(DELETE_UNDO);
                                cutSelection(cur);
                        }
                }
@@ -3411,7 +3425,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_CHAR_DELETE_BACKWARD:
        case LFUN_CHAR_DELETE_FORWARD:
                if (tablemode(cur)) {
-                       recordUndoInset(cur, Undo::DELETE);
+                       cur.recordUndoInset(DELETE_UNDO);
                        cutSelection(cur);
                }
                else
@@ -3422,7 +3436,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                if (!cur.selection())
                        break;
                if (tablemode(cur)) {
-                       finishUndo();
+                       cur.finishUndo();
                        copySelection(cur);
                } else
                        cell(cur.idx())->dispatch(cur, cmd);
@@ -3438,10 +3452,12 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                // pass to InsertPlaintextString, but
                // only if we have multi-cell content
                if (clip.find_first_of(from_ascii("\t\n")) != docstring::npos) {
+                       cur.recordUndoInset(INSERT_UNDO);
                        if (insertPlaintextString(cur.bv(), clip, false)) {
                                // content has been replaced,
                                // so cursor might be invalid
                                cur.pos() = cur.lastpos();
+                               cur.pit() = cur.lastpit();
                                bvcur.setCursor(cur);
                                break;
                        }
@@ -3452,8 +3468,9 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_PASTE:
-               if (tabularStackDirty() && theClipboard().isInternal()) {
-                       recordUndoInset(cur, Undo::INSERT);
+               if (tabularStackDirty() && theClipboard().isInternal() ||
+                   !theClipboard().hasInternal() && theClipboard().hasLyXContents()) {
+                       cur.recordUndoInset(INSERT_UNDO);
                        pasteClipboard(cur);
                        break;
                }
@@ -3466,7 +3483,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_FONT_NOUN:
        case LFUN_FONT_ITAL:
        case LFUN_FONT_FRAK:
-       case LFUN_FONT_CODE:
+       case LFUN_FONT_TYPEWRITER:
        case LFUN_FONT_SANS:
        case LFUN_FONT_FREE_APPLY:
        case LFUN_FONT_FREE_UPDATE:
@@ -3485,7 +3502,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        for (row_type i = rs; i <= re; ++i) {
                                for (col_type j = cs; j <= ce; ++j) {
                                        // cursor follows cell:
-                                       tmpcur.idx() = tabular.getCellNumber(i, j);
+                                       tmpcur.idx() = tabular.cellIndex(i, j);
                                        // select this cell only:
                                        tmpcur.pit() = 0;
                                        tmpcur.pos() = 0;
@@ -3507,11 +3524,6 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                cell(cur.idx())->dispatch(cur, cmd);
                break;
        }
-
-       // FIXME: this accesses the position cache before it is initialized
-       //resetPos(cur);
-       if (!is_deleted_)
-               InsetTabularMailer(*this).updateDialog(&cur.bv());
 }
 
 
@@ -3542,11 +3554,12 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
 
                row_type sel_row_start = 0;
                row_type sel_row_end = 0;
-               col_type dummy;
+               col_type sel_col_start = 0;
+               col_type sel_col_end = 0;
                Tabular::ltType dummyltt;
                bool flag = true;
 
-               getSelection(cur, sel_row_start, sel_row_end, dummy, dummy);
+               getSelection(cur, sel_row_start, sel_row_end, sel_col_start, sel_col_end);
 
                switch (action) {
                case Tabular::SET_PWIDTH:
@@ -3647,6 +3660,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.setOnOff(!tabular.isLongTabular());
                        break;
 
+               case Tabular::TOGGLE_ROTATE_TABULAR:
                case Tabular::SET_ROTATE_TABULAR:
                        status.setOnOff(tabular.getRotateTabular());
                        break;
@@ -3655,12 +3669,15 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.setOnOff(!tabular.getRotateTabular());
                        break;
 
+               case Tabular::TOGGLE_ROTATE_CELL:
                case Tabular::SET_ROTATE_CELL:
-                       status.setOnOff(tabular.getRotateCell(cur.idx()));
+                       status.setOnOff(!oneCellHasRotationState(false,
+                               sel_row_start, sel_row_end, sel_col_start, sel_col_end));
                        break;
 
                case Tabular::UNSET_ROTATE_CELL:
-                       status.setOnOff(!tabular.getRotateCell(cur.idx()));
+                       status.setOnOff(!oneCellHasRotationState(true,
+                               sel_row_start, sel_row_end, sel_col_start, sel_col_end));
                        break;
 
                case Tabular::SET_USEBOX:
@@ -3728,7 +3745,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        // disable these with multiple cells selected
        case LFUN_INSET_INSERT:
        case LFUN_TABULAR_INSERT:
-       case LFUN_CHARSTYLE_INSERT:
+       case LFUN_FLEX_INSERT:
        case LFUN_FLOAT_INSERT:
        case LFUN_FLOAT_WIDE_INSERT:
        case LFUN_FOOTNOTE_INSERT:
@@ -3751,9 +3768,8 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        }
 
        // disable in non-fixed-width cells
-       case LFUN_BREAK_LINE:
+       case LFUN_NEW_LINE:
        case LFUN_BREAK_PARAGRAPH:
-       case LFUN_BREAK_PARAGRAPH_KEEP_LAYOUT:
        case LFUN_BREAK_PARAGRAPH_SKIP: {
                if (tabular.getPWidth(cur.idx()).zero()) {
                        status.enabled(false);
@@ -3770,7 +3786,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        return cell(cur.idx())->getStatus(cur, cmd, status);
 
        case LFUN_INSET_MODIFY:
-               if (translate(cmd.getArg(0)) == TABULAR_CODE) {
+               if (insetCode(cmd.getArg(0)) == TABULAR_CODE) {
                        status.enabled(true);
                        return true;
                }
@@ -3783,37 +3799,32 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
 }
 
 
-int InsetTabular::latex(Buffer const & buf, odocstream & os,
-                        OutputParams const & runparams) const
+int InsetTabular::latex(odocstream & os, OutputParams const & runparams) const
 {
-       return tabular.latex(buf, os, runparams);
+       return tabular.latex(os, runparams);
 }
 
 
-int InsetTabular::plaintext(Buffer const & buf, odocstream & os,
-                            OutputParams const & runparams) const
+int InsetTabular::plaintext(odocstream & os, OutputParams const & runparams) const
 {
        os << '\n'; // output table on a new line
        int const dp = runparams.linelen > 0 ? runparams.depth : 0;
-       tabular.plaintext(buf, os, runparams, dp, false, 0);
+       tabular.plaintext(os, runparams, dp, false, 0);
        return PLAINTEXT_NEWLINE;
 }
 
 
-int InsetTabular::docbook(Buffer const & buf, odocstream & os,
-                          OutputParams const & runparams) const
+int InsetTabular::docbook(odocstream & os, OutputParams const & runparams) const
 {
        int ret = 0;
-       InsetBase * master = 0;
+       Inset * master = 0;
 
-#ifdef WITH_WARNINGS
-#warning Why not pass a proper DocIterator here?
-#endif
+       // FIXME: Why not pass a proper DocIterator here?
 #if 0
        // if the table is inside a float it doesn't need the informaltable
        // wrapper. Search for it.
        for (master = owner(); master; master = master->owner())
-               if (master->lyxCode() == InsetBase::FLOAT_CODE)
+               if (master->lyxCode() == FLOAT_CODE)
                        break;
 #endif
 
@@ -3821,7 +3832,7 @@ int InsetTabular::docbook(Buffer const & buf, odocstream & os,
                os << "<informaltable>";
                ++ret;
        }
-       ret += tabular.docbook(buf, os, runparams);
+       ret += tabular.docbook(os, runparams);
        if (!master) {
                os << "</informaltable>";
                ++ret;
@@ -3854,23 +3865,23 @@ void InsetTabular::cursorPos(BufferView const & bv,
        cell(sl.idx())->cursorPos(bv, sl, boundary, x, y);
 
        // y offset     correction
-       int const row = tabular.row_of_cell(sl.idx());
+       int const row = tabular.cellRow(sl.idx());
        for (int i = 0; i <= row; ++i) {
                if (i != 0) {
-                       y += tabular.getAscentOfRow(i);
+                       y += tabular.rowAscent(i);
                        y += tabular.getAdditionalHeight(i);
                }
                if (i != row)
-                       y += tabular.getDescentOfRow(i);
+                       y += tabular.rowDescent(i);
        }
 
        // x offset correction
-       int const col = tabular.column_of_cell(sl.idx());
-       int idx = tabular.getCellNumber(row, 0);
+       int const col = tabular.cellColumn(sl.idx());
+       int idx = tabular.cellIndex(row, 0);
        for (int j = 0; j < col; ++j) {
                if (tabular.isPartOfMultiColumn(row, j))
                        continue;
-               x += tabular.getWidthOfColumn(idx);
+               x += tabular.columnWidth(idx);
                ++idx;
        }
        x += tabular.getBeginningOfTextInCell(idx);
@@ -3883,14 +3894,14 @@ int InsetTabular::dist(BufferView & bv, idx_type const cell, int x, int y) const
 {
        int xx = 0;
        int yy = 0;
-       InsetBase const & inset = *tabular.getCellInset(cell);
+       Inset const & inset = *tabular.getCellInset(cell);
        Point o = bv.coordCache().getInsets().xy(&inset);
        int const xbeg = o.x_ - tabular.getBeginningOfTextInCell(cell);
-       int const xend = xbeg + tabular.getWidthOfColumn(cell);
-       row_type const row = tabular.row_of_cell(cell);
-       int const ybeg = o.y_ - tabular.getAscentOfRow(row) -
+       int const xend = xbeg + tabular.columnWidth(cell);
+       row_type const row = tabular.cellRow(cell);
+       int const ybeg = o.y_ - tabular.rowAscent(row) -
                         tabular.getAdditionalHeight(row);
-       int const yend = o.y_ + tabular.getDescentOfRow(row);
+       int const yend = o.y_ + tabular.rowDescent(row);
 
        if (x < xbeg)
                xx = xbeg - x;
@@ -3910,28 +3921,28 @@ int InsetTabular::dist(BufferView & bv, idx_type const cell, int x, int y) const
 }
 
 
-InsetBase * InsetTabular::editXY(Cursor & cur, int x, int y)
+Inset * InsetTabular::editXY(Cursor & cur, int x, int y)
 {
        //lyxerr << "InsetTabular::editXY: " << this << endl;
        cur.selection() = false;
        cur.push(*this);
        cur.idx() = getNearestCell(cur.bv(), x, y);
        resetPos(cur);
-       return cell(cur.idx())->text_.editXY(cur, x, y);
+       return cur.bv().textMetrics(&cell(cur.idx())->text_).editXY(cur, x, y);
 }
 
 
 void InsetTabular::setCursorFromCoordinates(Cursor & cur, int x, int y) const
 {
        cur.idx() = getNearestCell(cur.bv(), x, y);
-       cell(cur.idx())->text_.setCursorFromCoordinates(cur, x, y);
+       cur.bv().textMetrics(&cell(cur.idx())->text_).setCursorFromCoordinates(cur, x, y);
 }
 
 
 InsetTabular::idx_type InsetTabular::getNearestCell(BufferView & bv, int x, int y) const
 {
        idx_type idx_min = 0;
-       int dist_min = std::numeric_limits<int>::max();
+       int dist_min = numeric_limits<int>::max();
        for (idx_type i = 0, n = nargs(); i != n; ++i) {
                if (bv.coordCache().getInsets().has(tabular.getCellInset(i).get())) {
                        int const d = dist(bv, i, x, y);
@@ -3951,11 +3962,11 @@ int InsetTabular::getCellXPos(idx_type const cell) const
 
        for (; !tabular.isFirstCellInRow(c); --c)
                ;
-       int lx = tabular.getWidthOfColumn(cell);
+       int lx = 0;
        for (; c < cell; ++c)
-               lx += tabular.getWidthOfColumn(c);
+               lx += tabular.columnWidth(c);
 
-       return lx - tabular.getWidthOfColumn(cell);
+       return lx;
 }
 
 
@@ -3971,7 +3982,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()) + getCellXPos(cur.idx()) + offset;
-               int const x2 = x1 + tabular.getWidthOfColumn(cur.idx());
+               int const x2 = x1 + tabular.columnWidth(cur.idx());
 
                if (x1 < X1)
                        scx_ = X1 + 20 - x1;
@@ -3989,8 +4000,8 @@ void InsetTabular::moveNextCell(Cursor & cur)
 {
        if (isRightToLeft(cur)) {
                if (tabular.isFirstCellInRow(cur.idx())) {
-                       row_type const row = tabular.row_of_cell(cur.idx());
-                       if (row == tabular.rows() - 1)
+                       row_type const row = tabular.cellRow(cur.idx());
+                       if (row == tabular.rowCount() - 1)
                                return;
                        cur.idx() = tabular.getCellBelow(tabular.getLastCellInRow(row));
                } else {
@@ -4013,7 +4024,7 @@ void InsetTabular::movePrevCell(Cursor & cur)
 {
        if (isRightToLeft(cur)) {
                if (tabular.isLastCellInRow(cur.idx())) {
-                       row_type const row = tabular.row_of_cell(cur.idx());
+                       row_type const row = tabular.cellRow(cur.idx());
                        if (row == 0)
                                return;
                        cur.idx() = tabular.getFirstCellInRow(row);
@@ -4046,7 +4057,7 @@ bool InsetTabular::tabularFeatures(Cursor & cur, string const & what)
 
                if (tmp == what.substr(0, tmp.length())) {
                        //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
-                       //tabularFeatures[i].feature.length())) 
+                       //tabularFeatures[i].feature.length()))
                        action = tabularFeature[i].action;
                        break;
                }
@@ -4079,11 +4090,24 @@ static void checkLongtableSpecial(Tabular::ltType & ltt,
        }
 }
 
+bool InsetTabular::oneCellHasRotationState(bool rotated,
+               row_type row_start, row_type row_end,
+               col_type col_start, col_type col_end) const {
+
+       for (row_type i = row_start; i <= row_end; ++i) {
+               for (col_type j = col_start; j <= col_end; ++j) {
+                       if (tabular.getRotateCell(tabular.cellIndex(i, j))
+                               == rotated) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
 
 void InsetTabular::tabularFeatures(Cursor & cur,
        Tabular::Feature feature, string const & value)
 {
-       BufferView & bv = cur.bv();
        col_type sel_col_start;
        col_type sel_col_end;
        row_type sel_row_start;
@@ -4132,11 +4156,11 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                break;
        }
 
-       recordUndoInset(cur, Undo::ATOMIC);
+       cur.recordUndoInset(ATOMIC_UNDO);
 
        getSelection(cur, sel_row_start, sel_row_end, sel_col_start, sel_col_end);
-       row_type const row = tabular.row_of_cell(cur.idx());
-       col_type const column = tabular.column_of_cell(cur.idx());
+       row_type const row = tabular.cellRow(cur.idx());
+       col_type const column = tabular.cellColumn(cur.idx());
        bool flag = true;
        Tabular::ltType ltt;
 
@@ -4162,21 +4186,21 @@ void InsetTabular::tabularFeatures(Cursor & cur,
 
        case Tabular::APPEND_ROW:
                // append the row into the tabular
-               tabular.appendRow(bv.buffer()->params(), cur.idx());
+               tabular.appendRow(cur.idx());
                break;
 
        case Tabular::APPEND_COLUMN:
                // append the column into the tabular
-               tabular.appendColumn(bv.buffer()->params(), cur.idx());
-               cur.idx() = tabular.getCellNumber(row, column);
+               tabular.appendColumn(cur.idx());
+               cur.idx() = tabular.cellIndex(row, column);
                break;
 
        case Tabular::DELETE_ROW:
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        tabular.deleteRow(sel_row_start);
-               if (sel_row_start >= tabular.rows())
+               if (sel_row_start >= tabular.rowCount())
                        --sel_row_start;
-               cur.idx() = tabular.getCellNumber(sel_row_start, column);
+               cur.idx() = tabular.cellIndex(sel_row_start, column);
                cur.pit() = 0;
                cur.pos() = 0;
                cur.selection() = false;
@@ -4185,21 +4209,21 @@ void InsetTabular::tabularFeatures(Cursor & cur,
        case Tabular::DELETE_COLUMN:
                for (col_type i = sel_col_start; i <= sel_col_end; ++i)
                        tabular.deleteColumn(sel_col_start);
-               if (sel_col_start >= tabular.columns())
+               if (sel_col_start >= tabular.columnCount())
                        --sel_col_start;
-               cur.idx() = tabular.getCellNumber(row, sel_col_start);
+               cur.idx() = tabular.cellIndex(row, sel_col_start);
                cur.pit() = 0;
                cur.pos() = 0;
                cur.selection() = false;
                break;
 
        case Tabular::COPY_ROW:
-               tabular.copyRow(bv.buffer()->params(), row);
+               tabular.copyRow(row);
                break;
 
        case Tabular::COPY_COLUMN:
-               tabular.copyColumn(bv.buffer()->params(), column);
-               cur.idx() = tabular.getCellNumber(row, column);
+               tabular.copyColumn(column);
+               cur.idx() = tabular.cellIndex(row, column);
                break;
 
        case Tabular::M_TOGGLE_LINE_TOP:
@@ -4209,7 +4233,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setTopLine(
-                                       tabular.getCellNumber(i, j),
+                                       tabular.cellIndex(i, j),
                                        lineSet, flag);
                break;
        }
@@ -4221,7 +4245,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setBottomLine(
-                                       tabular.getCellNumber(i, j),
+                                       tabular.cellIndex(i, j),
                                        lineSet,
                                        flag);
                break;
@@ -4234,7 +4258,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setLeftLine(
-                                       tabular.getCellNumber(i,j),
+                                       tabular.cellIndex(i,j),
                                        lineSet,
                                        flag);
                break;
@@ -4246,10 +4270,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                bool lineSet = !tabular.rightLine(cur.idx(), flag);
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-                               tabular.setRightLine(
-                                       tabular.getCellNumber(i,j),
-                                       lineSet,
-                                       flag);
+                               tabular.setRightLine(tabular.cellIndex(i,j), lineSet, flag);
                break;
        }
 
@@ -4263,10 +4284,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
        case Tabular::ALIGN_BLOCK:
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-                               tabular.setAlignment(
-                                       tabular.getCellNumber(i, j),
-                                       setAlign,
-                                       flag);
+                               tabular.setAlignment(tabular.cellIndex(i, j), setAlign, flag);
                break;
 
        case Tabular::M_VALIGN_TOP:
@@ -4278,16 +4296,12 @@ void InsetTabular::tabularFeatures(Cursor & cur,
        case Tabular::VALIGN_MIDDLE:
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-                               tabular.setVAlignment(
-                                       tabular.getCellNumber(i, j),
-                                       setVAlign, flag);
+                               tabular.setVAlignment(tabular.cellIndex(i, j), setVAlign, flag);
                break;
 
        case Tabular::MULTICOLUMN: {
                if (sel_row_start != sel_row_end) {
-#ifdef WITH_WARNINGS
-#warning Need I say it ? This is horrible.
-#endif
+                       // FIXME: Need I say it ? This is horrible.
                        // FIXME UNICODE
                        Alert::error(_("Error setting multicolumn"),
                                     _("You cannot set multicolumn vertically."));
@@ -4299,14 +4313,14 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                        if (tabular.isMultiColumn(cur.idx()))
                                tabular.unsetMultiColumn(cur.idx());
                        else
-                               tabular.setMultiColumn(bv.buffer(), cur.idx(), 1);
+                               tabular.setMultiColumn(cur.idx(), 1);
                        break;
                }
                // we have a selection so this means we just add all this
                // cells to form a multicolumn cell
                idx_type const s_start = cur.selBegin().idx();
                idx_type const s_end = cur.selEnd().idx();
-               tabular.setMultiColumn(bv.buffer(), s_start, s_end - s_start + 1);
+               tabular.setMultiColumn(s_start, s_end - s_start + 1);
                cur.idx() = s_start;
                cur.pit() = 0;
                cur.pos() = 0;
@@ -4320,7 +4334,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setAllLines(
-                                       tabular.getCellNumber(i,j), setLines);
+                                       tabular.cellIndex(i,j), setLines);
                break;
 
        case Tabular::SET_LONGTABULAR:
@@ -4339,18 +4353,33 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                tabular.setRotateTabular(false);
                break;
 
+       case Tabular::TOGGLE_ROTATE_TABULAR:
+               tabular.setRotateTabular(!tabular.getRotateTabular());
+               break;
+
        case Tabular::SET_ROTATE_CELL:
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setRotateCell(
-                                       tabular.getCellNumber(i, j), true);
+                                       tabular.cellIndex(i, j), true);
                break;
 
        case Tabular::UNSET_ROTATE_CELL:
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-                               tabular.setRotateCell(
-                                       tabular.getCellNumber(i, j), false);
+                               tabular.setRotateCell(tabular.cellIndex(i, j), false);
+               break;
+
+       case Tabular::TOGGLE_ROTATE_CELL:
+               {
+               bool oneNotRotated = oneCellHasRotationState(false,
+                       sel_row_start, sel_row_end, sel_col_start, sel_col_end);
+
+               for (row_type i = sel_row_start; i <= sel_row_end; ++i)
+                       for (col_type j = sel_col_start; j <= sel_col_end; ++j)
+                               tabular.setRotateCell(tabular.cellIndex(i, j),
+                                                                         oneNotRotated);
+               }
                break;
 
        case Tabular::SET_USEBOX: {
@@ -4359,7 +4388,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                        val = Tabular::BOX_NONE;
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-                               tabular.setUsebox(tabular.getCellNumber(i, j), val);
+                               tabular.setUsebox(tabular.cellIndex(i, j), val);
                break;
        }
 
@@ -4496,7 +4525,7 @@ bool InsetTabular::copySelection(Cursor & cur)
                paste_tabular->deleteRow(0);
 
        row_type const rows = re - rs + 1;
-       while (paste_tabular->rows() > rows)
+       while (paste_tabular->rowCount() > rows)
                paste_tabular->deleteRow(rows);
 
        paste_tabular->setTopLine(0, true, true);
@@ -4507,7 +4536,7 @@ bool InsetTabular::copySelection(Cursor & cur)
                paste_tabular->deleteColumn(0);
 
        col_type const columns = ce - cs + 1;
-       while (paste_tabular->columns() > columns)
+       while (paste_tabular->columnCount() > columns)
                paste_tabular->deleteColumn(columns);
 
        paste_tabular->setLeftLine(0, true, true);
@@ -4516,7 +4545,7 @@ bool InsetTabular::copySelection(Cursor & cur)
 
        odocstringstream os;
        OutputParams const runparams(0);
-       paste_tabular->plaintext(cur.buffer(), os, runparams, 0, true, '\t');
+       paste_tabular->plaintext(os, runparams, 0, true, '\t');
        // Needed for the "Edit->Paste recent" menu and the system clipboard.
        cap::copySelection(cur, os.str());
 
@@ -4534,13 +4563,13 @@ bool InsetTabular::pasteClipboard(Cursor & cur)
 {
        if (!paste_tabular)
                return false;
-       col_type const actcol = tabular.column_of_cell(cur.idx());
-       row_type const actrow = tabular.row_of_cell(cur.idx());
+       col_type const actcol = tabular.cellColumn(cur.idx());
+       row_type const actrow = tabular.cellRow(cur.idx());
        for (row_type r1 = 0, r2 = actrow;
-            r1 < paste_tabular->rows() && r2 < tabular.rows();
+            r1 < paste_tabular->rowCount() && r2 < tabular.rowCount();
             ++r1, ++r2) {
                for (col_type c1 = 0, c2 = actcol;
-                   c1 < paste_tabular->columns() && c2 < tabular.columns();
+                   c1 < paste_tabular->columnCount() && c2 < tabular.columnCount();
                    ++c1, ++c2) {
                        if (paste_tabular->isPartOfMultiColumn(r1, c1) &&
                            tabular.isPartOfMultiColumn(r2, c2))
@@ -4558,7 +4587,7 @@ bool InsetTabular::pasteClipboard(Cursor & cur)
                        tabular.setCellInset(r2, c2, inset);
                        // FIXME: change tracking (MG)
                        inset->setChange(Change(cur.buffer().params().trackChanges ?
-                                               Change::INSERTED : Change::UNCHANGED));
+                                               Change::INSERTED : Change::UNCHANGED));
                        cur.pos() = 0;
                }
        }
@@ -4577,7 +4606,7 @@ void InsetTabular::cutSelection(Cursor & cur)
        for (row_type i = rs; i <= re; ++i) {
                for (col_type j = cs; j <= ce; ++j) {
                        shared_ptr<InsetText> t
-                               = cell(tabular.getCellNumber(i, j));
+                               = cell(tabular.cellIndex(i, j));
                        if (cur.buffer().params().trackChanges)
                                // FIXME: Change tracking (MG)
                                t->setChange(Change(Change::DELETED));
@@ -4592,7 +4621,6 @@ void InsetTabular::cutSelection(Cursor & cur)
        if (cur.pos() > cur.lastpos())
                cur.pos() = cur.lastpos();
        cur.clearSelection();
-       theSelection().haveSelection(false);
 }
 
 
@@ -4601,7 +4629,7 @@ bool InsetTabular::isRightToLeft(Cursor & cur) const
        BOOST_ASSERT(cur.depth() > 1);
        Paragraph const & parentpar = cur[cur.depth() - 2].paragraph();
        pos_type const parentpos = cur[cur.depth() - 2].pos();
-       return parentpar.getFontSettings(cur.bv().buffer()->params(),
+       return parentpar.getFontSettings(cur.bv().buffer().params(),
                                         parentpos).language()->rightToLeft();
 }
 
@@ -4611,23 +4639,23 @@ void InsetTabular::getSelection(Cursor & cur,
 {
        CursorSlice const & beg = cur.selBegin();
        CursorSlice const & end = cur.selEnd();
-       cs = tabular.column_of_cell(beg.idx());
-       ce = tabular.column_of_cell(end.idx());
+       cs = tabular.cellColumn(beg.idx());
+       ce = tabular.cellColumn(end.idx());
        if (cs > ce) {
                ce = cs;
-               cs = tabular.column_of_cell(end.idx());
+               cs = tabular.cellColumn(end.idx());
        } else {
-               ce = tabular.right_column_of_cell(end.idx());
+               ce = tabular.cellRightColumn(end.idx());
        }
 
-       rs = tabular.row_of_cell(beg.idx());
-       re = tabular.row_of_cell(end.idx());
+       rs = tabular.cellRow(beg.idx());
+       re = tabular.cellRow(end.idx());
        if (rs > re)
                swap(rs, re);
 }
 
 
-LyXText * InsetTabular::getText(int idx) const
+Text * InsetTabular::getText(int idx) const
 {
        return size_t(idx) < nargs() ? cell(idx)->getText(0) : 0;
 }
@@ -4654,7 +4682,7 @@ void InsetTabular::rejectChanges(BufferParams const & bparams)
 }
 
 
-bool InsetTabular::forceDefaultParagraphs(idx_type cell) const
+bool InsetTabular::allowParagraphCustomization(idx_type cell) const
 {
        return tabular.getPWidth(cell).zero();
 }
@@ -4666,13 +4694,11 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
        if (buf.length() <= 0)
                return true;
 
-       Buffer const & buffer = *bv.buffer();
-
        col_type cols = 1;
        row_type rows = 1;
        col_type maxCols = 1;
-       docstring::size_type const len = buf.length();
-       docstring::size_type p = 0;
+       size_t const len = buf.length();
+       size_t p = 0;
 
        while (p < len &&
               (p = buf.find_first_of(from_ascii("\t\n"), p)) != docstring::npos) {
@@ -4695,24 +4721,23 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
        col_type ocol = 0;
        row_type row = 0;
        if (usePaste) {
-               paste_tabular.reset(
-                       new Tabular(buffer.params(), rows, maxCols));
+               paste_tabular.reset(new Tabular(buffer(), rows, maxCols));
                loctab = paste_tabular.get();
                cols = 0;
                dirtyTabularStack(true);
        } else {
                loctab = &tabular;
                cell = bv.cursor().idx();
-               ocol = tabular.column_of_cell(cell);
-               row = tabular.row_of_cell(cell);
+               ocol = tabular.cellColumn(cell);
+               row = tabular.cellRow(cell);
        }
 
-       docstring::size_type op = 0;
-       idx_type const cells = loctab->getNumberOfCells();
+       size_t op = 0;
+       idx_type const cells = loctab->cellCount();
        p = 0;
        cols = ocol;
-       rows = loctab->rows();
-       col_type const columns = loctab->columns();
+       rows = loctab->rowCount();
+       col_type const columns = loctab->columnCount();
 
        while (cell < cells && p < len && row < rows &&
               (p = buf.find_first_of(from_ascii("\t\n"), p)) != docstring::npos)
@@ -4724,10 +4749,10 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
                        // we can only set this if we are not too far right
                        if (cols < columns) {
                                shared_ptr<InsetText> inset = loctab->getCellInset(cell);
-                               Paragraph & par = inset->text_.getPar(0);
-                               LyXFont const font = inset->text_.getFont(buffer, par, 0);
+                               Font const font = bv.textMetrics(&inset->text_).
+                                       displayFont(0, 0);
                                inset->setText(buf.substr(op, p - op), font,
-                                              buffer.params().trackChanges);
+                                              buffer().params().trackChanges);
                                ++cols;
                                ++cell;
                        }
@@ -4736,15 +4761,15 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
                        // we can only set this if we are not too far right
                        if (cols < columns) {
                                shared_ptr<InsetText> inset = tabular.getCellInset(cell);
-                               Paragraph & par = inset->text_.getPar(0);
-                               LyXFont const font = inset->text_.getFont(buffer, par, 0);
+                               Font const font = bv.textMetrics(&inset->text_).
+                                       displayFont(0, 0);
                                inset->setText(buf.substr(op, p - op), font,
-                                              buffer.params().trackChanges);
+                                              buffer().params().trackChanges);
                        }
                        cols = ocol;
                        ++row;
                        if (row < rows)
-                               cell = loctab->getCellNumber(row, cols);
+                               cell = loctab->cellIndex(row, cols);
                        break;
                }
                ++p;
@@ -4753,10 +4778,9 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
        // check for the last cell if there is no trailing '\n'
        if (cell < cells && op < len) {
                shared_ptr<InsetText> inset = loctab->getCellInset(cell);
-               Paragraph & par = inset->text_.getPar(0);
-               LyXFont const font = inset->text_.getFont(buffer, par, 0);
+               Font const font = bv.textMetrics(&inset->text_).displayFont(0, 0);
                inset->setText(buf.substr(op, len - op), font,
-                       buffer.params().trackChanges);
+                       buffer().params().trackChanges);
        }
        return true;
 }
@@ -4764,8 +4788,8 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
 
 void InsetTabular::addPreview(PreviewLoader & loader) const
 {
-       row_type const rows = tabular.rows();
-       col_type const columns = tabular.columns();
+       row_type const rows = tabular.rowCount();
+       col_type const columns = tabular.columnCount();
        for (row_type i = 0; i < rows; ++i) {
                for (col_type j = 0; j < columns; ++j)
                        tabular.getCellInset(i, j)->addPreview(loader);
@@ -4781,7 +4805,6 @@ bool InsetTabular::tablemode(Cursor & cur) const
 
 
 
-
 string const InsetTabularMailer::name_("tabular");
 
 InsetTabularMailer::InsetTabularMailer(InsetTabular const & inset)
@@ -4814,11 +4837,9 @@ void InsetTabularMailer::string2params(string const & in, InsetTabular & inset)
        // by Buffer::readInset
        lex >> token;
        if (!lex || token != "Tabular")
-               return print_mailer_error("InsetTabularMailer", in, 2,
-                                         "Tabular");
+               return print_mailer_error("InsetTabularMailer", in, 2, "Tabular");
 
-       Buffer const & buffer = inset.buffer();
-       inset.read(buffer, lex);
+       inset.read(lex);
 }
 
 
@@ -4826,7 +4847,7 @@ string const InsetTabularMailer::params2string(InsetTabular const & inset)
 {
        ostringstream data;
        data << name_ << ' ';
-       inset.write(inset.buffer(), data);
+       inset.write(data);
        data << "\\end_inset\n";
        return data.str();
 }