]> git.lyx.org Git - lyx.git/blobdiff - src/tabular.C
update Basque and Romanian l10n
[lyx.git] / src / tabular.C
index 10e8d938fc374924dfa8a4875a2fde4d344d5b23..239c1ff65be9281f7f77139172c3f948b78007ca 100644 (file)
 
 #include <sstream>
 
-using lyx::support::ltrim;
-using lyx::support::prefixIs;
-using lyx::support::rtrim;
-using lyx::support::suffixIs;
+
+namespace lyx {
+
+using support::prefixIs;
+using support::ltrim;
+using support::rtrim;
+using support::suffixIs;
 
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
@@ -64,6 +67,8 @@ using std::strlen;
 namespace {
 
 int const WIDTH_OF_LINE = 5;
+int const default_line_space = 10;
+
 
 template <class T>
 string const write_attribute(string const & name, T const & t)
@@ -299,6 +304,21 @@ bool getTokenValue(string const & str, char const * token, LyXLength & len)
 }
 
 
+bool getTokenValue(string const & str, char const * token, LyXLength & len, bool & flag)
+{
+       len = LyXLength();
+       flag = false;
+       string tmp;
+       if (!getTokenValue(str, token, tmp))
+               return false;
+       if (tmp == "default") {
+               flag = true;
+               return  true;
+       }
+       return isValidLength(tmp, &len);
+}
+
+
 void l_getline(istream & is, string & str)
 {
        str.erase();
@@ -380,6 +400,9 @@ LyXTabular::rowstruct::rowstruct()
          descent_of_row(0),
          top_line(true),
          bottom_line(false),
+         top_space_default(false),
+         bottom_space_default(false),
+         interline_space_default(false),
          endhead(false),
          endfirsthead(false),
          endfoot(false),
@@ -406,7 +429,7 @@ LyXTabular::ltType::ltType()
 
 
 LyXTabular::LyXTabular(BufferParams const & bp, row_type rows_arg,
-                       col_type columns_arg)
+                      col_type columns_arg)
 {
        init(bp, rows_arg, columns_arg);
 }
@@ -414,7 +437,7 @@ LyXTabular::LyXTabular(BufferParams const & bp, row_type rows_arg,
 
 // activates all lines and sets all widths to 0
 void LyXTabular::init(BufferParams const & bp, row_type rows_arg,
-                      col_type columns_arg)
+                     col_type columns_arg)
 {
        rows_    = rows_arg;
        columns_ = columns_arg;
@@ -432,6 +455,7 @@ void LyXTabular::init(BufferParams const & bp, row_type rows_arg,
        column_info.back().right_line = true;
        is_long_tabular = false;
        rotate = false;
+       use_booktabs = false;
 }
 
 
@@ -474,9 +498,9 @@ void LyXTabular::appendRow(BufferParams const & bp, idx_type const cell)
        for (row_type i = row + 2; i < rows_; ++i)
                swap(cell_info[i], old[i - 1]);
 
-       if (bp.tracking_changes)
+       if (bp.trackChanges)
                for (col_type j = 0; j < columns_; ++j)
-                       cell_info[row + 1][j].inset->markNew(true);
+                       cell_info[row + 1][j].inset->setChange(Change(Change::INSERTED));
 
        set_row_column_number_info();
 }
@@ -495,6 +519,21 @@ void LyXTabular::deleteRow(row_type const row)
 }
 
 
+void LyXTabular::copyRow(BufferParams const & bp, 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)
+                       cell_info[row + 1][j].inset->setChange(Change(Change::INSERTED));
+
+       set_row_column_number_info();
+}
+
+
 void LyXTabular::appendColumn(BufferParams const & bp, idx_type const cell)
 {
        ++columns_;
@@ -519,8 +558,8 @@ void LyXTabular::appendColumn(BufferParams const & bp, idx_type const cell)
        //++column;
        for (row_type i = 0; i < rows_; ++i) {
                cell_info[i][column + 1].inset->clear();
-               if (bp.tracking_changes)
-                       cell_info[i][column + 1].inset->markNew(true);
+               if (bp.trackChanges)
+                       cell_info[i][column + 1].inset->setChange(Change(Change::INSERTED));
        }
        fixCellNums();
 }
@@ -540,6 +579,22 @@ void LyXTabular::deleteColumn(col_type const column)
 }
 
 
+void LyXTabular::copyColumn(BufferParams const & bp, col_type const column)
+{
+       ++columns_;
+
+       column_info.insert(column_info.begin() + column, column_info[column]);
+
+       for (row_type i = 0; i < rows_; ++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)
+                       cell_info[i][column + 1].inset->setChange(Change(Change::INSERTED));
+       fixCellNums();
+}
+
+
 void LyXTabular::set_row_column_number_info()
 {
        numberofcells = 0;
@@ -607,10 +662,10 @@ LyXTabular::idx_type LyXTabular::numberOfCellsInRow(idx_type const cell) const
 }
 
 
-// returns 1 if there is a topline, returns 0 if not
 bool LyXTabular::topLine(idx_type const cell, bool const onlycolumn) const
 {
-       if (!onlycolumn && isMultiColumn(cell))
+       if (!onlycolumn && isMultiColumn(cell) &&
+           !(use_booktabs && row_of_cell(cell) == 0))
                return cellinfo_of_cell(cell).top_line;
        return row_info[row_of_cell(cell)].top_line;
 }
@@ -618,7 +673,8 @@ bool LyXTabular::topLine(idx_type const cell, bool const onlycolumn) const
 
 bool LyXTabular::bottomLine(idx_type const cell, bool onlycolumn) const
 {
-       if (!onlycolumn && isMultiColumn(cell))
+       if (!onlycolumn && isMultiColumn(cell) &&
+           !(use_booktabs && isLastRow(cell)))
                return cellinfo_of_cell(cell).bottom_line;
        return row_info[row_of_cell(cell)].bottom_line;
 }
@@ -626,6 +682,8 @@ bool LyXTabular::bottomLine(idx_type const cell, bool onlycolumn) const
 
 bool LyXTabular::leftLine(idx_type cell, bool onlycolumn) const
 {
+       if (use_booktabs)
+               return false;
        if (!onlycolumn && isMultiColumn(cell) &&
                (isFirstCellInRow(cell) || isMultiColumn(cell-1)))
        {
@@ -641,6 +699,8 @@ bool LyXTabular::leftLine(idx_type cell, bool onlycolumn) const
 
 bool LyXTabular::rightLine(idx_type cell, bool onlycolumn) const
 {
+       if (use_booktabs)
+               return false;
        if (!onlycolumn && isMultiColumn(cell) &&
                (isLastCellInRow(cell) || isMultiColumn(cell + 1)))
        {
@@ -721,9 +781,12 @@ int LyXTabular::getAdditionalHeight(row_type row) const
                        top = row_info[row].top_line;
                }
        }
+       int const interline_space = row_info[row - 1].interline_space_default ?
+               default_line_space :
+               row_info[row - 1].interline_space.inPixels(width_of_tabular);
        if (top && bottom)
-               return WIDTH_OF_LINE;
-       return 0;
+               return interline_space + WIDTH_OF_LINE;
+       return interline_space;
 }
 
 
@@ -856,7 +919,7 @@ void LyXTabular::setWidthOfCell(idx_type cell, int new_width)
 
 
 void LyXTabular::setAlignment(idx_type cell, LyXAlignment align,
-                              bool onlycolumn)
+                             bool onlycolumn)
 {
        if (!isMultiColumn(cell) || onlycolumn)
                column_info[column_of_cell(cell)].alignment = align;
@@ -866,7 +929,7 @@ void LyXTabular::setAlignment(idx_type cell, LyXAlignment align,
 
 
 void LyXTabular::setVAlignment(idx_type cell, VAlignment align,
-                               bool onlycolumn)
+                              bool onlycolumn)
 {
        if (!isMultiColumn(cell) || onlycolumn)
                column_info[column_of_cell(cell)].valignment = align;
@@ -889,15 +952,14 @@ void toggleFixedWidth(LCursor & cur, InsetText * inset, bool fixedWidth)
                return;
 
        // merge all paragraphs to one
-       BufferParams const & bp =
-               inset->getText(0)->bv_owner->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(0, cur.lastpit() + 1,
+       inset->getText(0)->setLayout(*cur.bv().buffer(), 0, cur.lastpit() + 1,
                        bp.getLyXTextClass().defaultLayoutName());
        cur.pop();
 }
@@ -915,7 +977,7 @@ void LyXTabular::setColumnPWidth(LCursor & cur, idx_type cell,
                idx_type const cell = getCellNumber(i, j);
                // because of multicolumns
                toggleFixedWidth(cur, getCellInset(cell).get(),
-                                !getPWidth(cell).zero());
+                                !getPWidth(cell).zero());
        }
        // cur paragraph can become invalid after paragraphs were merged
        if (cur.pit() > cur.lastpit())
@@ -1193,6 +1255,7 @@ void LyXTabular::write(Buffer const & buf, ostream & os) const
        // global longtable options
        os << "<features"
           << write_attribute("rotate", rotate)
+          << write_attribute("booktabs", use_booktabs)
           << write_attribute("islongtable", is_long_tabular)
           << write_attribute("firstHeadTopDL", endfirsthead.topDL)
           << write_attribute("firstHeadBottomDL", endfirsthead.bottomDL)
@@ -1218,8 +1281,21 @@ void LyXTabular::write(Buffer const & buf, ostream & os) const
        for (row_type i = 0; i < rows_; ++i) {
                os << "<row"
                   << write_attribute("topline", row_info[i].top_line)
-                  << write_attribute("bottomline", row_info[i].bottom_line)
-                  << write_attribute("endhead", row_info[i].endhead)
+                  << write_attribute("bottomline", row_info[i].bottom_line);
+               static const string def("default");
+               if (row_info[i].top_space_default)
+                       os << write_attribute("topspace", def);
+               else
+                       os << write_attribute("topspace", row_info[i].top_space);
+               if (row_info[i].bottom_space_default)
+                       os << write_attribute("bottomspace", def);
+               else
+                       os << write_attribute("bottomspace", row_info[i].bottom_space);
+               if (row_info[i].interline_space_default)
+                       os << write_attribute("interlinespace", def);
+               else
+                       os << write_attribute("interlinespace", row_info[i].interline_space);
+               os << write_attribute("endhead", row_info[i].endhead)
                   << write_attribute("endfirsthead", row_info[i].endfirsthead)
                   << write_attribute("endfoot", row_info[i].endfoot)
                   << write_attribute("endlastfoot", row_info[i].endlastfoot)
@@ -1281,6 +1357,7 @@ void LyXTabular::read(Buffer const & buf, LyXLex & lex)
                return;
        }
        getTokenValue(line, "rotate", rotate);
+       getTokenValue(line, "booktabs", use_booktabs);
        getTokenValue(line, "islongtable", is_long_tabular);
        getTokenValue(line, "firstHeadTopDL", endfirsthead.topDL);
        getTokenValue(line, "firstHeadBottomDL", endfirsthead.bottomDL);
@@ -1317,6 +1394,12 @@ void LyXTabular::read(Buffer const & buf, LyXLex & 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);
+               getTokenValue(line, "bottomspace", row_info[i].bottom_space,
+                             row_info[i].bottom_space_default);
+               getTokenValue(line, "interlinespace", row_info[i].interline_space,
+                             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);
@@ -1385,7 +1468,7 @@ LyXTabular::cellstruct & LyXTabular::cellinfo_of_cell(idx_type cell) const
 
 
 void LyXTabular::setMultiColumn(Buffer * buffer, idx_type cell,
-                                idx_type number)
+                               idx_type number)
 {
        cellstruct & cs = cellinfo_of_cell(cell);
        cs.multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
@@ -1443,6 +1526,18 @@ LyXTabular::idx_type LyXTabular::unsetMultiColumn(idx_type cell)
 }
 
 
+void LyXTabular::setBookTabs(bool what)
+{
+       use_booktabs = what;
+}
+
+
+bool LyXTabular::useBookTabs() const
+{
+       return use_booktabs;
+}
+
+
 void LyXTabular::setLongTabular(bool what)
 {
        is_long_tabular = what;
@@ -1536,10 +1631,10 @@ LyXTabular::idx_type LyXTabular::getLastCellBelow(idx_type cell) const
 
 
 LyXTabular::idx_type LyXTabular::getCellNumber(row_type row,
-                                               col_type column) const
+                                              col_type column) const
 {
        BOOST_ASSERT(column != npos && column < columns_ &&
-                    row    != npos && row    < rows_);
+                    row    != npos && row    < rows_);
        return cell_info[row][column].cellno;
 }
 
@@ -1565,7 +1660,7 @@ LyXTabular::BoxType LyXTabular::getUsebox(idx_type cell) const
 //  This are functions used for the longtable support
 ///
 void LyXTabular::setLTHead(row_type row, bool flag, ltType const & hd,
-                           bool first)
+                          bool first)
 {
        if (first) {
                endfirsthead = hd;
@@ -1596,7 +1691,7 @@ bool LyXTabular::getRowOfLTFirstHead(row_type row, ltType & hd) const
 
 
 void LyXTabular::setLTFoot(row_type row, bool flag, ltType const & fd,
-                           bool last)
+                          bool last)
 {
        if (last) {
                endlastfoot = fd;
@@ -1729,7 +1824,7 @@ bool LyXTabular::isPartOfMultiColumn(row_type row, col_type column) const
 }
 
 
-int LyXTabular::TeXTopHLine(ostream & os, row_type row) const
+int LyXTabular::TeXTopHLine(odocstream & os, row_type row) const
 {
        // FIXME: assert or return 0 as in TeXBottomHLine()?
        BOOST_ASSERT(row != npos);
@@ -1743,12 +1838,14 @@ int LyXTabular::TeXTopHLine(ostream & os, row_type row) const
                if (topLine(i))
                        ++tmp;
        }
-       if (tmp == n - fcell) {
-               os << "\\hline ";
+       if (use_booktabs && row == 0) {
+               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 << "\\cline{"
+                               os << (use_booktabs ? "\\cmidrule{" : "\\cline{")
                                   << column_of_cell(i) + 1
                                   << '-'
                                   << right_column_of_cell(i) + 1
@@ -1763,7 +1860,7 @@ int LyXTabular::TeXTopHLine(ostream & os, row_type row) const
 }
 
 
-int LyXTabular::TeXBottomHLine(ostream & os, row_type row) const
+int LyXTabular::TeXBottomHLine(odocstream & os, row_type row) const
 {
        // FIXME: return 0 or assert as in TeXTopHLine()?
        if (row == npos || row >= rows_)
@@ -1777,12 +1874,14 @@ int LyXTabular::TeXBottomHLine(ostream & os, row_type row) const
                if (bottomLine(i))
                        ++tmp;
        }
-       if (tmp == n - fcell) {
-               os << "\\hline";
+       if (use_booktabs && row == rows_ - 1) {
+               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 << "\\cline{"
+                               os << (use_booktabs ? "\\cmidrule{" : "\\cline{")
                                   << column_of_cell(i) + 1
                                   << '-'
                                   << right_column_of_cell(i) + 1
@@ -1797,7 +1896,7 @@ int LyXTabular::TeXBottomHLine(ostream & os, row_type row) const
 }
 
 
-int LyXTabular::TeXCellPreamble(ostream & os, idx_type cell) const
+int LyXTabular::TeXCellPreamble(odocstream & os, idx_type cell) const
 {
        int ret = 0;
 
@@ -1808,7 +1907,8 @@ int LyXTabular::TeXCellPreamble(ostream & os, idx_type cell) const
        if (isMultiColumn(cell)) {
                os << "\\multicolumn{" << cells_in_multicolumn(cell) << "}{";
                if (!cellinfo_of_cell(cell).align_special.empty()) {
-                       os << cellinfo_of_cell(cell).align_special << "}{";
+                       os << from_ascii(cellinfo_of_cell(cell).align_special)
+                          << "}{";
                } else {
                        if (leftLine(cell) &&
                                (isFirstCellInRow(cell) ||
@@ -1830,7 +1930,7 @@ int LyXTabular::TeXCellPreamble(ostream & os, idx_type cell) const
                                        break;
                                }
                                os << '{'
-                                  << getPWidth(cell).asLatexString()
+                                  << from_ascii(getPWidth(cell).asLatexString())
                                   << '}';
                        } else {
                                switch (getAlignment(cell)) {
@@ -1866,7 +1966,8 @@ int LyXTabular::TeXCellPreamble(ostream & os, idx_type cell) const
                        os << 'b';
                        break;
                }
-               os << "]{" << getPWidth(cell).asLatexString() << "}{";
+               os << "]{" << from_ascii(getPWidth(cell).asLatexString())
+                  << "}{";
        } else if (getUsebox(cell) == BOX_MINIPAGE) {
                os << "\\begin{minipage}[";
                switch (getVAlignment(cell)) {
@@ -1880,14 +1981,15 @@ int LyXTabular::TeXCellPreamble(ostream & os, idx_type cell) const
                        os << 'b';
                        break;
                }
-               os << "]{" << getPWidth(cell).asLatexString() << "}\n";
+               os << "]{" << from_ascii(getPWidth(cell).asLatexString())
+                  << "}\n";
                ++ret;
        }
        return ret;
 }
 
 
-int LyXTabular::TeXCellPostamble(ostream & os, idx_type cell) const
+int LyXTabular::TeXCellPostamble(odocstream & os, idx_type cell) const
 {
        int ret = 0;
 
@@ -1909,7 +2011,7 @@ int LyXTabular::TeXCellPostamble(ostream & os, idx_type cell) const
 }
 
 
-int LyXTabular::TeXLongtableHeaderFooter(ostream & os, Buffer const & buf,
+int LyXTabular::TeXLongtableHeaderFooter(odocstream & os, Buffer const & buf,
                                         OutputParams const & runparams) const
 {
        if (!is_long_tabular)
@@ -2009,12 +2111,29 @@ bool LyXTabular::isValidRow(row_type row) const
 }
 
 
-int LyXTabular::TeXRow(ostream & os, row_type i, Buffer const & buf,
+int LyXTabular::TeXRow(odocstream & os, row_type i, Buffer const & buf,
                       OutputParams const & runparams) const
 {
        idx_type cell = getCellNumber(i, 0);
-
        int ret = TeXTopHLine(os, i);
+       if (row_info[i].top_space_default) {
+               if (use_booktabs)
+                       os << "\\addlinespace\n";
+               else
+                       os << "\\noalign{\\vskip\\doublerulesep}\n";
+       } else if(!row_info[i].top_space.zero()) {
+               if (use_booktabs)
+                       os << "\\addlinespace["
+                          << from_ascii(row_info[i].top_space.asLatexString())
+                          << "]\n";
+               else {
+                       os << "\\noalign{\\vskip"
+                          << from_ascii(row_info[i].top_space.asLatexString())
+                          << "}\n";
+               }
+               ++ret;
+       }
+       
        for (col_type j = 0; j < columns_; ++j) {
                if (isPartOfMultiColumn(i, j))
                        continue;
@@ -2034,19 +2153,47 @@ int LyXTabular::TeXRow(ostream & os, row_type i, Buffer const & buf,
 
                ret += TeXCellPostamble(os, cell);
                if (!isLastCellInRow(cell)) { // not last cell in row
-                       os << "&\n";
-                       ++ret;
+                       os << " & ";
                }
                ++cell;
        }
-       os << "\\tabularnewline\n";
+       os << "\\tabularnewline";
+       if (row_info[i].bottom_space_default) {
+               if (use_booktabs)
+                       os << "\\addlinespace";
+               else
+                       os << "[\\doublerulesep]";
+       } else if (!row_info[i].bottom_space.zero()) {
+               if (use_booktabs)
+                       os << "\\addlinespace";
+               os << '['
+                  << from_ascii(row_info[i].bottom_space.asLatexString())
+                  << ']';
+       }
+       os << '\n';
        ++ret;
        ret += TeXBottomHLine(os, i);
+       if (row_info[i].interline_space_default) {
+               if (use_booktabs)
+                       os << "\\addlinespace\n";
+               else
+                       os << "\\noalign{\\vskip\\doublerulesep}\n";
+       } else if (!row_info[i].interline_space.zero()) {
+               if (use_booktabs)
+                       os << "\\addlinespace["
+                          << from_ascii(row_info[i].interline_space.asLatexString())
+                          << "]\n";
+               else
+                       os << "\\noalign{\\vskip"
+                          << from_ascii(row_info[i].interline_space.asLatexString())
+                          << "}\n";
+               ++ret;
+       }
        return ret;
 }
 
 
-int LyXTabular::latex(Buffer const & buf, ostream & os,
+int LyXTabular::latex(Buffer const & buf, odocstream & os,
                      OutputParams const & runparams) const
 {
        int ret = 0;
@@ -2065,9 +2212,9 @@ int LyXTabular::latex(Buffer const & buf, ostream & os,
                os << "\\begin{tabular}{";
        for (col_type i = 0; i < columns_; ++i) {
                if (!column_info[i].align_special.empty()) {
-                       os << column_info[i].align_special;
+                       os << from_ascii(column_info[i].align_special);
                } else {
-                       if (column_info[i].left_line)
+                       if (!use_booktabs && column_info[i].left_line)
                                os << '|';
                        if (!column_info[i].p_width.zero()) {
                                switch (column_info[i].alignment) {
@@ -2099,7 +2246,7 @@ int LyXTabular::latex(Buffer const & buf, ostream & os,
                                        break;
                        }
                                os << '{'
-                                  << column_info[i].p_width.asLatexString()
+                                  << from_ascii(column_info[i].p_width.asLatexString())
                                   << '}';
                        } else {
                                switch (column_info[i].alignment) {
@@ -2114,7 +2261,7 @@ int LyXTabular::latex(Buffer const & buf, ostream & os,
                                        break;
                                }
                        }
-                       if (column_info[i].right_line)
+                       if (!use_booktabs && column_info[i].right_line)
                                os << '|';
                }
        }
@@ -2154,49 +2301,7 @@ int LyXTabular::latex(Buffer const & buf, ostream & os,
 }
 
 
-int LyXTabular::linuxdoc(Buffer const & buf, ostream & os,
-                        const OutputParams & runparams) const
-{
-       os << "<tabular ca=\"";
-       for (col_type i = 0; i < columns_; ++i) {
-               switch (column_info[i].alignment) {
-               case LYX_ALIGN_LEFT:
-                       os << 'l';
-                       break;
-               case LYX_ALIGN_RIGHT:
-                       os << 'r';
-                       break;
-               default:
-                       os << 'c';
-                       break;
-               }
-       }
-       os << "\">\n";
-       idx_type cell = 0;
-       int ret = 0;
-       for (row_type i = 0; i < rows_; ++i) {
-               for (col_type j = 0; j < columns_; ++j) {
-                       if (isPartOfMultiColumn(i, j))
-                               continue;
-                       shared_ptr<InsetText> inset = getCellInset(cell);
-
-                       ret += inset->linuxdoc(buf, os, runparams);
-
-                       if (isLastCellInRow(cell)) {
-                               os << "@\n";
-                               ++ret;
-                       } else {
-                               os << "|";
-                       }
-                       ++cell;
-               }
-       }
-       os << "</tabular>\n";
-       return ret;
-}
-
-
-int LyXTabular::docbookRow(Buffer const & buf, ostream & os, row_type row,
+int LyXTabular::docbookRow(Buffer const & buf, odocstream & os, row_type row,
                           OutputParams const & runparams) const
 {
        int ret = 0;
@@ -2248,7 +2353,7 @@ int LyXTabular::docbookRow(Buffer const & buf, ostream & os, row_type row,
 }
 
 
-int LyXTabular::docbook(Buffer const & buf, ostream & os,
+int LyXTabular::docbook(Buffer const & buf, odocstream & os,
                        OutputParams const & runparams) const
 {
        int ret = 0;
@@ -2333,7 +2438,7 @@ int LyXTabular::docbook(Buffer const & buf, ostream & os,
 }
 
 
-int LyXTabular::asciiTopHLine(ostream & os, row_type row,
+int LyXTabular::asciiTopHLine(odocstream & os, row_type row,
                              vector<unsigned int> const & clen) const
 {
        idx_type const fcell = getFirstCellInRow(row);
@@ -2349,7 +2454,7 @@ int LyXTabular::asciiTopHLine(ostream & os, row_type row,
        if (!tmp)
                return 0;
 
-       unsigned char ch;
+       char_type ch;
        for (idx_type i = fcell; i < n; ++i) {
                if (topLine(i)) {
                        if (leftLine(i))
@@ -2366,7 +2471,7 @@ int LyXTabular::asciiTopHLine(ostream & os, row_type row,
                while (column < columns_ - 1
                       && isPartOfMultiColumn(row, ++column))
                        len += clen[column] + 4;
-               os << string(len, ch);
+               os << docstring(len, ch);
                if (topLine(i)) {
                        if (rightLine(i))
                                os << "-+";
@@ -2381,7 +2486,7 @@ int LyXTabular::asciiTopHLine(ostream & os, row_type row,
 }
 
 
-int LyXTabular::asciiBottomHLine(ostream & os, row_type row,
+int LyXTabular::asciiBottomHLine(odocstream & os, row_type row,
                                 vector<unsigned int> const & clen) const
 {
        idx_type const fcell = getFirstCellInRow(row);
@@ -2397,7 +2502,7 @@ int LyXTabular::asciiBottomHLine(ostream & os, row_type row,
        if (!tmp)
                return 0;
 
-       unsigned char ch;
+       char_type ch;
        for (idx_type i = fcell; i < n; ++i) {
                if (bottomLine(i)) {
                        if (leftLine(i))
@@ -2414,7 +2519,7 @@ int LyXTabular::asciiBottomHLine(ostream & os, row_type row,
                while (column < columns_ -1
                       && isPartOfMultiColumn(row, ++column))
                        len += clen[column] + 4;
-               os << string(len, ch);
+               os << docstring(len, ch);
                if (bottomLine(i)) {
                        if (rightLine(i))
                                os << "-+";
@@ -2429,13 +2534,13 @@ int LyXTabular::asciiBottomHLine(ostream & os, row_type row,
 }
 
 
-int LyXTabular::asciiPrintCell(Buffer const & buf, ostream & os,
+int LyXTabular::asciiPrintCell(Buffer const & buf, odocstream & os,
                               OutputParams const & runparams,
                               idx_type cell, row_type row, col_type column,
                               vector<unsigned int> const & clen,
                               bool onlydata) const
 {
-       ostringstream sstr;
+       odocstringstream sstr;
        int const ret = getCellInset(cell)->plaintext(buf, sstr, runparams);
 
        if (onlydata) {
@@ -2470,7 +2575,8 @@ int LyXTabular::asciiPrintCell(Buffer const & buf, ostream & os,
                break;
        }
 
-       os << string(len1, ' ') << sstr.str() << string(len2, ' ');
+       os << docstring(len1, ' ') << sstr.str()
+          << docstring(len2, ' ');
 
        if (rightLine(cell))
                os << " |";
@@ -2481,7 +2587,7 @@ int LyXTabular::asciiPrintCell(Buffer const & buf, ostream & os,
 }
 
 
-int LyXTabular::plaintext(Buffer const & buf, ostream & os,
+int LyXTabular::plaintext(Buffer const & buf, odocstream & os,
                      OutputParams const & runparams,
                      int const depth,
                      bool onlydata, unsigned char delim) const
@@ -2499,7 +2605,7 @@ int LyXTabular::plaintext(Buffer const & buf, ostream & os,
                                idx_type cell = getCellNumber(i, j);
                                if (isMultiColumnReal(cell))
                                        continue;
-                               ostringstream sstr;
+                               odocstringstream sstr;
                                getCellInset(cell)->plaintext(buf, sstr, runparams);
                                if (clen[j] < sstr.str().length())
                                        clen[j] = sstr.str().length();
@@ -2511,7 +2617,7 @@ int LyXTabular::plaintext(Buffer const & buf, ostream & os,
                                idx_type cell = getCellNumber(i, j);
                                if (!isMultiColumnReal(cell) || isPartOfMultiColumn(i, j))
                                        continue;
-                               ostringstream sstr;
+                               odocstringstream sstr;
                                getCellInset(cell)->plaintext(buf, sstr, runparams);
                                int len = int(sstr.str().length());
                                idx_type const n = cells_in_multicolumn(cell);
@@ -2525,7 +2631,7 @@ int LyXTabular::plaintext(Buffer const & buf, ostream & os,
        idx_type cell = 0;
        for (row_type i = 0; i < rows_; ++i) {
                if (!onlydata && asciiTopHLine(os, i, clen))
-                       os << string(depth * 2, ' ');
+                       os << docstring(depth * 2, ' ');
                for (col_type j = 0; j < columns_; ++j) {
                        if (isPartOfMultiColumn(i, j))
                                continue;
@@ -2537,9 +2643,9 @@ int LyXTabular::plaintext(Buffer const & buf, ostream & os,
                }
                os << endl;
                if (!onlydata) {
-                       os << string(depth * 2, ' ');
+                       os << docstring(depth * 2, ' ');
                        if (asciiBottomHLine(os, i, clen))
-                               os << string(depth * 2, ' ');
+                               os << docstring(depth * 2, ' ');
                }
        }
        return ret;
@@ -2553,7 +2659,7 @@ shared_ptr<InsetText> LyXTabular::getCellInset(idx_type cell) const
 
 
 shared_ptr<InsetText> LyXTabular::getCellInset(row_type row,
-                                               col_type column) const
+                                              col_type column) const
 {
        return cell_info[row][column].inset;
 }
@@ -2594,6 +2700,8 @@ LyXTabular::getCellFromInset(InsetBase const * inset) const
 void LyXTabular::validate(LaTeXFeatures & features) const
 {
        features.require("NeedTabularnewline");
+       if (useBookTabs())
+               features.require("booktabs");
        if (isLongTabular())
                features.require("longtable");
        if (needRotating())
@@ -2607,15 +2715,6 @@ void LyXTabular::validate(LaTeXFeatures & features) const
 }
 
 
-void LyXTabular::getLabelList(Buffer const & buffer,
-                             std::vector<string> & list) const
-{
-       for (row_type i = 0; i < rows_; ++i)
-               for (col_type j = 0; j < columns_; ++j)
-                       getCellInset(i, j)->getLabelList(buffer, list);
-}
-
-
 LyXTabular::BoxType LyXTabular::useParbox(idx_type cell) const
 {
        ParagraphList const & parlist = getCellInset(cell)->paragraphs();
@@ -2629,3 +2728,6 @@ LyXTabular::BoxType LyXTabular::useParbox(idx_type cell) const
 
        return BOX_NONE;
 }
+
+
+} // namespace lyx