X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetTabular.cpp;h=bf21ae73f148c7b3288663f975186e23b4e02c8d;hb=239b9919ffe28338d789e6dc9122228f77ab77a7;hp=af0c510bf987535e53c5c691091596d6fc3278d9;hpb=98b8e1eb81c3f5595d293040d446d8398181c202;p=lyx.git diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index af0c510bf9..bf21ae73f1 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -13,6 +13,7 @@ * \author Jürgen Vigna * \author Uwe Stöhr * \author Edwin Leuven + * \author Scott Kostyshak * * Full author contact details are available in file CREDITS. */ @@ -32,6 +33,7 @@ #include "DispatchResult.h" #include "FuncRequest.h" #include "FuncStatus.h" +#include "InsetList.h" #include "Language.h" #include "LaTeXFeatures.h" #include "Lexer.h" @@ -43,6 +45,8 @@ #include "Paragraph.h" #include "ParagraphParameters.h" #include "ParIterator.h" +#include "TexRow.h" +#include "texstream.h" #include "TextClass.h" #include "TextMetrics.h" @@ -59,13 +63,12 @@ #include "support/gettext.h" #include "support/lassert.h" #include "support/lstrings.h" +#include "support/unique_ptr.h" -#include - -#include +#include #include #include -#include +#include using namespace std; using namespace lyx::support; @@ -88,13 +91,13 @@ namespace Alert = frontend::Alert; namespace { int const ADD_TO_HEIGHT = 2; // in cell -int const ADD_TO_TABULAR_WIDTH = 6; // horiz space before and after the table +int const ADD_TO_TABULAR_WIDTH = 6; // horizontal space before and after the table int const default_line_space = 10; // ? int const WIDTH_OF_LINE = 5; // space between double lines /// -boost::scoped_ptr paste_tabular; +unique_ptr paste_tabular; struct TabularFeature { @@ -108,12 +111,18 @@ TabularFeature tabularFeature[] = { // the SET/UNSET actions are used by the table dialog, // the TOGGLE actions by the table toolbar buttons + // FIXME: these values have been hardcoded in InsetMathGrid and other + // math insets. { Tabular::APPEND_ROW, "append-row", false }, { Tabular::APPEND_COLUMN, "append-column", false }, { Tabular::DELETE_ROW, "delete-row", false }, { Tabular::DELETE_COLUMN, "delete-column", false }, { Tabular::COPY_ROW, "copy-row", false }, { Tabular::COPY_COLUMN, "copy-column", false }, + { Tabular::MOVE_COLUMN_RIGHT, "move-column-right", false }, + { Tabular::MOVE_COLUMN_LEFT, "move-column-left", false }, + { Tabular::MOVE_ROW_DOWN, "move-row-down", false }, + { Tabular::MOVE_ROW_UP, "move-row-up", false }, { Tabular::SET_LINE_TOP, "set-line-top", true }, { Tabular::SET_LINE_BOTTOM, "set-line-bottom", true }, { Tabular::SET_LINE_LEFT, "set-line-left", true }, @@ -142,18 +151,20 @@ TabularFeature tabularFeature[] = { Tabular::MULTIROW, "multirow", false }, { Tabular::SET_MULTIROW, "set-multirow", false }, { Tabular::UNSET_MULTIROW, "unset-multirow", false }, + { Tabular::SET_MROFFSET, "set-mroffset", true }, { Tabular::SET_ALL_LINES, "set-all-lines", false }, { Tabular::UNSET_ALL_LINES, "unset-all-lines", false }, + { Tabular::TOGGLE_LONGTABULAR, "toggle-longtabular", false }, { Tabular::SET_LONGTABULAR, "set-longtabular", false }, { Tabular::UNSET_LONGTABULAR, "unset-longtabular", false }, { Tabular::SET_PWIDTH, "set-pwidth", true }, { Tabular::SET_MPWIDTH, "set-mpwidth", true }, - { Tabular::SET_ROTATE_TABULAR, "set-rotate-tabular", false }, - { Tabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular", false }, - { Tabular::TOGGLE_ROTATE_TABULAR, "toggle-rotate-tabular", false }, - { Tabular::SET_ROTATE_CELL, "set-rotate-cell", false }, - { Tabular::UNSET_ROTATE_CELL, "unset-rotate-cell", false }, - { Tabular::TOGGLE_ROTATE_CELL, "toggle-rotate-cell", false }, + { Tabular::SET_ROTATE_TABULAR, "set-rotate-tabular", true }, + { Tabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular", true }, + { Tabular::TOGGLE_ROTATE_TABULAR, "toggle-rotate-tabular", true }, + { Tabular::SET_ROTATE_CELL, "set-rotate-cell", true }, + { Tabular::UNSET_ROTATE_CELL, "unset-rotate-cell", true }, + { Tabular::TOGGLE_ROTATE_CELL, "toggle-rotate-cell", true }, { Tabular::SET_USEBOX, "set-usebox", true }, { Tabular::SET_LTHEAD, "set-lthead", true }, { Tabular::UNSET_LTHEAD, "unset-lthead", true }, @@ -164,11 +175,13 @@ TabularFeature tabularFeature[] = { Tabular::SET_LTLASTFOOT, "set-ltlastfoot", true }, { Tabular::UNSET_LTLASTFOOT, "unset-ltlastfoot", true }, { Tabular::SET_LTNEWPAGE, "set-ltnewpage", false }, + { Tabular::UNSET_LTNEWPAGE, "unset-ltnewpage", false }, { Tabular::TOGGLE_LTCAPTION, "toggle-ltcaption", false }, { Tabular::SET_LTCAPTION, "set-ltcaption", false }, { Tabular::UNSET_LTCAPTION, "unset-ltcaption", false }, { Tabular::SET_SPECIAL_COLUMN, "set-special-column", true }, { Tabular::SET_SPECIAL_MULTICOLUMN, "set-special-multicolumn", true }, + { Tabular::TOGGLE_BOOKTABS, "toggle-booktabs", false }, { Tabular::SET_BOOKTABS, "set-booktabs", false }, { Tabular::UNSET_BOOKTABS, "unset-booktabs", false }, { Tabular::SET_TOP_SPACE, "set-top-space", true }, @@ -182,66 +195,11 @@ TabularFeature tabularFeature[] = { Tabular::LONGTABULAR_ALIGN_CENTER, "longtabular-align-center", false }, { Tabular::LONGTABULAR_ALIGN_RIGHT, "longtabular-align-right", false }, { Tabular::SET_DECIMAL_POINT, "set-decimal-point", true }, + { Tabular::SET_TABULAR_WIDTH, "set-tabular-width", true }, { Tabular::LAST_ACTION, "", false } }; -template -string const write_attribute(string const & name, T const & t) -{ - string const s = tostr(t); - return s.empty() ? s : " " + name + "=\"" + s + "\""; -} - -template <> -string const write_attribute(string const & name, string const & t) -{ - return t.empty() ? t : " " + name + "=\"" + t + "\""; -} - - -template <> -string const write_attribute(string const & name, docstring const & t) -{ - return t.empty() ? string() : " " + name + "=\"" + to_utf8(t) + "\""; -} - - -template <> -string const write_attribute(string const & name, bool const & b) -{ - // we write only true attribute values so we remove a bit of the - // file format bloat for tabulars. - return b ? write_attribute(name, convert(b)) : string(); -} - - -template <> -string const write_attribute(string const & name, int const & i) -{ - // we write only true attribute values so we remove a bit of the - // file format bloat for tabulars. - return i ? write_attribute(name, convert(i)) : string(); -} - - -template <> -string const write_attribute(string const & name, Tabular::idx_type const & i) -{ - // we write only true attribute values so we remove a bit of the - // file format bloat for tabulars. - return i ? write_attribute(name, convert(i)) : string(); -} - - -template <> -string const write_attribute(string const & name, Length const & value) -{ - // we write only the value if we really have one same reson as above. - return value.zero() ? string() : write_attribute(name, value.asString()); -} - - string const tostr(LyXAlignment const & num) { switch (num) { @@ -309,7 +267,7 @@ string const tostr(Tabular::BoxType const & num) // I would have liked a fromstr template a lot better. (Lgb) -bool string2type(string const str, LyXAlignment & num) +bool string2type(string const & str, LyXAlignment & num) { if (str == "none") num = LYX_ALIGN_NONE; @@ -329,7 +287,7 @@ bool string2type(string const str, LyXAlignment & num) } -bool string2type(string const str, Tabular::HAlignment & num) +bool string2type(string const & str, Tabular::HAlignment & num) { if (str == "left") num = Tabular::LYX_LONGTABULAR_ALIGN_LEFT; @@ -343,7 +301,7 @@ bool string2type(string const str, Tabular::HAlignment & num) } -bool string2type(string const str, Tabular::VAlignment & num) +bool string2type(string const & str, Tabular::VAlignment & num) { if (str == "top") num = Tabular::LYX_VALIGN_TOP; @@ -357,7 +315,7 @@ bool string2type(string const str, Tabular::VAlignment & num) } -bool string2type(string const str, Tabular::BoxType & num) +bool string2type(string const & str, Tabular::BoxType & num) { if (str == "none") num = Tabular::BOX_NONE; @@ -371,7 +329,7 @@ bool string2type(string const str, Tabular::BoxType & num) } -bool string2type(string const str, bool & num) +bool string2type(string const & str, bool & num) { if (str == "true") num = true; @@ -501,6 +459,61 @@ void l_getline(istream & is, string & str) } } +template +string const write_attribute(string const & name, T const & t) +{ + string const s = tostr(t); + return s.empty() ? s : " " + name + "=\"" + s + "\""; +} + +template <> +string const write_attribute(string const & name, string const & t) +{ + return t.empty() ? t : " " + name + "=\"" + t + "\""; +} + + +template <> +string const write_attribute(string const & name, docstring const & t) +{ + return t.empty() ? string() : " " + name + "=\"" + to_utf8(t) + "\""; +} + + +template <> +string const write_attribute(string const & name, bool const & b) +{ + // we write only true attribute values so we remove a bit of the + // file format bloat for tabulars. + return b ? write_attribute(name, convert(b)) : string(); +} + + +template <> +string const write_attribute(string const & name, int const & i) +{ + // we write only true attribute values so we remove a bit of the + // file format bloat for tabulars. + return i ? write_attribute(name, convert(i)) : string(); +} + + +template <> +string const write_attribute(string const & name, Tabular::idx_type const & i) +{ + // we write only true attribute values so we remove a bit of the + // file format bloat for tabulars. + return i ? write_attribute(name, convert(i)) : string(); +} + + +template <> +string const write_attribute(string const & name, Length const & value) +{ + // we write only the value if we really have one same reson as above. + return value.zero() ? string() : write_attribute(name, value.asString()); +} + } // namespace @@ -514,24 +527,27 @@ string const featureAsString(Tabular::Feature action) } -InsetTableCell splitCell(InsetTableCell & head, docstring const align_d, bool & hassep) +DocIterator separatorPos(InsetTableCell const * cell, docstring const & align_d) { - InsetTableCell tail = InsetTableCell(head); - tail.getText(0)->setMacrocontextPosition( - head.getText(0)->macrocontextPosition()); - tail.setBuffer(head.buffer()); - - DocIterator dit = doc_iterator_begin(&head.buffer(), &head); + DocIterator dit = doc_iterator_begin(&(cell->buffer()), cell); for (; dit; dit.forwardChar()) - if (dit.inTexted() && dit.depth()==1 + if (dit.inTexted() && dit.depth() == 1 && dit.paragraph().find(align_d, false, false, dit.pos())) break; - pit_type const psize = head.paragraphs().front().size(); - hassep = dit; + return dit; +} + + +InsetTableCell splitCell(InsetTableCell & head, docstring const & align_d, bool & hassep) +{ + InsetTableCell tail = InsetTableCell(head); + DocIterator const dit = separatorPos(&head, align_d); + hassep = (bool)dit; if (hassep) { + pit_type const psize = head.paragraphs().front().size(); head.paragraphs().front().eraseChars(dit.pos(), psize, false); - tail.paragraphs().front().eraseChars(0, + tail.paragraphs().front().eraseChars(0, dit.pos() < psize ? dit.pos() + 1 : psize, false); } @@ -561,7 +577,7 @@ Tabular::CellData::CellData(Buffer * buf) left_line(false), right_line(false), usebox(BOX_NONE), - rotate(false), + rotate(0), inset(new InsetTableCell(buf)) { inset->setBuffer(*buf); @@ -573,6 +589,7 @@ Tabular::CellData::CellData(CellData const & cs) width(cs.width), multicolumn(cs.multicolumn), multirow(cs.multirow), + mroffset(cs.mroffset), alignment(cs.alignment), valignment(cs.valignment), decimal_hoffset(cs.decimal_hoffset), @@ -590,35 +607,32 @@ Tabular::CellData::CellData(CellData const & cs) { } -Tabular::CellData & Tabular::CellData::operator=(CellData cs) -{ - swap(cs); +Tabular::CellData & Tabular::CellData::operator=(CellData const & cs) +{ + if (&cs == this) + return *this; + cellno = cs.cellno; + width = cs.width; + multicolumn = cs.multicolumn; + multirow = cs.multirow; + mroffset = cs.mroffset; + alignment = cs.alignment; + valignment = cs.valignment; + decimal_hoffset = cs.decimal_hoffset; + decimal_width = cs.decimal_width; + voffset = cs.voffset; + top_line = cs.top_line; + bottom_line = cs.bottom_line; + left_line = cs.left_line; + right_line = cs.right_line; + usebox = cs.usebox; + rotate = cs.rotate; + align_special = cs.align_special; + p_width = cs.p_width; + inset.reset(static_cast(cs.inset->clone())); return *this; } -void Tabular::CellData::swap(CellData & rhs) -{ - std::swap(cellno, rhs.cellno); - std::swap(width, rhs.width); - std::swap(multicolumn, rhs.multicolumn); - std::swap(multirow, rhs.multirow); - std::swap(alignment, rhs.alignment); - std::swap(valignment, rhs.valignment); - std::swap(decimal_hoffset, rhs.decimal_hoffset); - std::swap(decimal_width, rhs.decimal_width); - std::swap(voffset, rhs.voffset); - std::swap(top_line, rhs.top_line); - std::swap(bottom_line, rhs.bottom_line); - std::swap(left_line, rhs.left_line); - std::swap(right_line, rhs.right_line); - std::swap(usebox, rhs.usebox); - std::swap(rotate, rhs.rotate); - std::swap(align_special, rhs.align_special); - p_width.swap(rhs.p_width); - inset.swap(rhs.inset); -} - - Tabular::RowData::RowData() : ascent(0), descent(0), @@ -643,7 +657,7 @@ Tabular::ColumnData::ColumnData() Tabular::ltType::ltType() - : topDL(false), + : set(false), topDL(false), bottomDL(false), empty(false) {} @@ -678,8 +692,9 @@ void Tabular::init(Buffer * buf, row_type rows_arg, updateIndexes(); is_long_tabular = false; tabular_valignment = LYX_VALIGN_MIDDLE; + tabular_width = Length(); longtabular_alignment = LYX_LONGTABULAR_ALIGN_CENTER; - rotate = false; + rotate = 0; use_booktabs = false; // set silly default lines for (row_type r = 0; r < nrows(); ++r) @@ -693,23 +708,54 @@ void Tabular::init(Buffer * buf, row_type rows_arg, } -void Tabular::appendRow(idx_type const cell) +void Tabular::deleteRow(row_type const row) { - row_type const row = cellRow(cell); + // Not allowed to delete last row + if (nrows() == 1) + return; - row_info.insert(row_info.begin() + row + 1, RowData()); - row_info[row + 1] = row_info[row]; + for (col_type c = 0; c < ncols(); ++c) { + // Care about multirow cells + if (row + 1 < nrows() && + cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW && + cell_info[row + 1][c].multirow == CELL_PART_OF_MULTIROW) { + cell_info[row + 1][c].multirow = CELL_BEGIN_OF_MULTIROW; + } + } + row_info.erase(row_info.begin() + row); + cell_info.erase(cell_info.begin() + row); + updateIndexes(); +} + + +void Tabular::copyRow(row_type const row) +{ + insertRow(row, true); +} + + +void Tabular::appendRow(row_type row) +{ + insertRow(row, false); +} + +void Tabular::insertRow(row_type const row, bool copy) +{ + row_info.insert(row_info.begin() + row + 1, RowData(row_info[row])); cell_info.insert(cell_info.begin() + row + 1, - cell_vector(ncols(), CellData(buffer_))); + cell_vector(0, CellData(buffer_))); + for (col_type c = 0; c < ncols(); ++c) { + cell_info[row + 1].insert(cell_info[row + 1].begin() + c, + copy ? CellData(cell_info[row][c]) : CellData(buffer_)); + if (buffer().params().track_changes) + cell_info[row + 1][c].inset->setChange(Change(Change::INSERTED)); if (cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW) cell_info[row + 1][c].multirow = CELL_PART_OF_MULTIROW; - else - cell_info[row + 1][c].multirow = cell_info[row][c].multirow; } - updateIndexes(); + updateIndexes(); for (col_type c = 0; c < ncols(); ++c) { if (isPartOfMultiRow(row, c)) continue; @@ -724,75 +770,57 @@ void Tabular::appendRow(idx_type const cell) setBottomLine(j, false); } // mark track changes - if (buffer().params().trackChanges) + if (buffer().params().track_changes) cellInfo(i).inset->setChange(Change(Change::INSERTED)); } } -void Tabular::deleteRow(row_type const row) +void Tabular::moveColumn(col_type col, ColDirection direction) { - // Not allowed to delete last row - if (nrows() == 1) - return; + if (direction == Tabular::LEFT) + col = col - 1; - for (col_type c = 0; c < ncols(); ++c) { - // Care about multirow cells - if (row + 1 < nrows() && - cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW && - cell_info[row + 1][c].multirow == CELL_PART_OF_MULTIROW) { - cell_info[row + 1][c].multirow = CELL_BEGIN_OF_MULTIROW; + std::swap(column_info[col], column_info[col + 1]); + + for (row_type r = 0; r < nrows(); ++r) { + std::swap(cell_info[r][col], cell_info[r][col + 1]); + std::swap(cell_info[r][col].left_line, cell_info[r][col + 1].left_line); + std::swap(cell_info[r][col].right_line, cell_info[r][col + 1].right_line); + + // FIXME track changes is broken for tabular features (#8469) + idx_type const i = cellIndex(r, col); + idx_type const j = cellIndex(r, col + 1); + if (buffer().params().track_changes) { + cellInfo(i).inset->setChange(Change(Change::INSERTED)); + cellInfo(j).inset->setChange(Change(Change::INSERTED)); } } - row_info.erase(row_info.begin() + row); - cell_info.erase(cell_info.begin() + row); updateIndexes(); } -void Tabular::copyRow(row_type const row) +void Tabular::moveRow(row_type row, RowDirection direction) { - row_info.insert(row_info.begin() + row, row_info[row]); - cell_info.insert(cell_info.begin() + row, cell_info[row]); + if (direction == Tabular::UP) + row = row - 1; - if (buffer().params().trackChanges) - for (col_type c = 0; c < ncols(); ++c) - cell_info[row + 1][c].inset->setChange(Change(Change::INSERTED)); + std::swap(row_info[row], row_info[row + 1]); - updateIndexes(); -} - - -void Tabular::appendColumn(idx_type const cell) -{ - col_type const c = cellColumn(cell); - - column_info.insert(column_info.begin() + c + 1, ColumnData()); - column_info[c + 1] = column_info[c]; - - for (row_type r = 0; r < nrows(); ++r) { - cell_info[r].insert(cell_info[r].begin() + c + 1, - CellData(buffer_)); - if (cell_info[r][c].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) - cell_info[r][c + 1].multicolumn = CELL_PART_OF_MULTICOLUMN; - else - cell_info[r][c + 1].multicolumn = cell_info[r][c].multicolumn; - } - updateIndexes(); - for (row_type r = 0; r < nrows(); ++r) { - // inherit line settings - idx_type const i = cellIndex(r, c + 1); - idx_type const j = cellIndex(r, c); - setBottomLine(i, bottomLine(j)); - setTopLine(i, topLine(j)); - setLeftLine(i, leftLine(j)); - if (rightLine(j) && rightLine(j)) { - setRightLine(i, true); - setRightLine(j, false); - } - if (buffer().params().trackChanges) + for (col_type c = 0; c < ncols(); ++c) { + std::swap(cell_info[row][c], cell_info[row + 1][c]); + std::swap(cell_info[row][c].top_line, cell_info[row + 1][c].top_line); + std::swap(cell_info[row][c].bottom_line, cell_info[row + 1][c].bottom_line); + + // FIXME track changes is broken for tabular features (#8469) + idx_type const i = cellIndex(row, c); + idx_type const j = cellIndex(row + 1, c); + if (buffer().params().track_changes) { cellInfo(i).inset->setChange(Change(Change::INSERTED)); + cellInfo(j).inset->setChange(Change(Change::INSERTED)); + } } + updateIndexes(); } @@ -817,16 +845,45 @@ void Tabular::deleteColumn(col_type const col) void Tabular::copyColumn(col_type const col) +{ + insertColumn(col, true); +} + + +void Tabular::appendColumn(col_type col) +{ + insertColumn(col, false); +} + + +void Tabular::insertColumn(col_type const col, bool copy) { BufferParams const & bp = buffer().params(); - column_info.insert(column_info.begin() + col, column_info[col]); + column_info.insert(column_info.begin() + col + 1, ColumnData(column_info[col])); for (row_type r = 0; r < nrows(); ++r) { - cell_info[r].insert(cell_info[r].begin() + col, cell_info[r][col]); - if (bp.trackChanges) + cell_info[r].insert(cell_info[r].begin() + col + 1, + copy ? CellData(cell_info[r][col]) : CellData(buffer_)); + if (bp.track_changes) cell_info[r][col + 1].inset->setChange(Change(Change::INSERTED)); + if (cell_info[r][col].multicolumn == CELL_BEGIN_OF_MULTICOLUMN) + cell_info[r][col + 1].multicolumn = CELL_PART_OF_MULTICOLUMN; } updateIndexes(); + for (row_type r = 0; r < nrows(); ++r) { + // inherit line settings + idx_type const i = cellIndex(r, col + 1); + idx_type const j = cellIndex(r, col); + setBottomLine(i, bottomLine(j)); + setTopLine(i, topLine(j)); + setLeftLine(i, leftLine(j)); + if (rightLine(i) && rightLine(j)) { + setRightLine(i, true); + setRightLine(j, false); + } + if (buffer().params().track_changes) + cellInfo(i).inset->setChange(Change(Change::INSERTED)); + } } @@ -854,7 +911,7 @@ void Tabular::updateIndexes() for (col_type column = 0; column < ncols(); ++column) { if (isPartOfMultiColumn(row, column)) continue; - // columnofcell nneds to be called before setting width and aligment + // columnofcell needs to be called before setting width and aligment // multirow cells inherit the width from the column width if (!isPartOfMultiRow(row, column)) { columnofcell[i] = column; @@ -976,8 +1033,8 @@ bool Tabular::updateColumnWidths() idx_type const i = cellIndex(r, c); if (columnSpan(i) == 1) { if (getAlignment(i) == LYX_ALIGN_DECIMAL - && cell_info[r][c].decimal_width!=0) - new_width = max(new_width, cellInfo(i).width + && cell_info[r][c].decimal_width != 0) + new_width = max(new_width, cellInfo(i).width + max_dwidth[c] - cellInfo(i).decimal_width); else new_width = max(new_width, cellInfo(i).width); @@ -1021,17 +1078,33 @@ int Tabular::width() const void Tabular::setAlignment(idx_type cell, LyXAlignment align, - bool onlycolumn) + bool has_width) { col_type const col = cellColumn(cell); - if (onlycolumn || !isMultiColumn(cell)) { + // set alignment for the whole row if we are not in a multicolumn cell, + // exclude possible multicolumn cells in the row + if (!isMultiColumn(cell)) { + for (row_type r = 0; r < nrows(); ++r) { + // only if the column has no width the multirow inherits the + // alignment of the column, otherwise it is left aligned + if (!(isMultiRow(cellIndex(r, col)) && has_width) + && !isMultiColumn(cellIndex(r, col))) { + cell_info[r][col].alignment = align; + cell_info[r][col].inset->setContentAlignment(align); + } + if ((isMultiRow(cellIndex(r, col)) && has_width) + && !isMultiColumn(cellIndex(r, col))) { + cell_info[r][col].alignment = LYX_ALIGN_LEFT; + cell_info[r][col].inset->setContentAlignment(LYX_ALIGN_LEFT); + } + } column_info[col].alignment = align; docstring & dpoint = column_info[col].decimal_point; if (align == LYX_ALIGN_DECIMAL && dpoint.empty()) dpoint = from_utf8(lyxrc.default_decimal_point); } else { cellInfo(cell).alignment = align; - cellInset(cell).get()->setContentAlignment(align); + cellInset(cell)->setContentAlignment(align); } } @@ -1055,7 +1128,6 @@ namespace { */ void toggleFixedWidth(Cursor & cur, InsetTableCell * inset, bool fixedWidth) { - inset->setAutoBreakRows(fixedWidth); inset->toggleFixedWidth(fixedWidth); if (fixedWidth) return; @@ -1082,7 +1154,7 @@ void Tabular::setColumnPWidth(Cursor & cur, idx_type cell, col_type const c = cellColumn(cell); column_info[c].p_width = width; - // reset the vertical alignment to top if the fixed with + // reset the vertical alignment to top if the fixed width // is removed or zero because only fixed width columns can // have a vertical alignment if (column_info[c].p_width.zero()) @@ -1092,6 +1164,8 @@ void Tabular::setColumnPWidth(Cursor & cur, idx_type cell, // because of multicolumns toggleFixedWidth(cur, cellInset(cell).get(), !getPWidth(cell).zero()); + if (isMultiRow(cell)) + setAlignment(cell, LYX_ALIGN_LEFT, false); } // cur paragraph can become invalid after paragraphs were merged if (cur.pit() > cur.lastpit()) @@ -1130,6 +1204,13 @@ bool Tabular::setMColumnPWidth(Cursor & cur, idx_type cell, } +bool Tabular::setMROffset(Cursor &, idx_type cell, Length const & mroffset) +{ + cellInfo(cell).mroffset = mroffset; + return true; +} + + void Tabular::setAlignSpecial(idx_type cell, docstring const & special, Tabular::Feature what) { @@ -1212,7 +1293,7 @@ bool Tabular::columnRightLine(col_type c) const idx_type i = cellIndex(r, c); if (c == cellColumn(i) + columnSpan(i) - 1) { ++total; - bool left = (c + 1 < ncols() + bool left = (c + 1 < ncols() && cellInfo(cellIndex(r, c + 1)).left_line) || c + 1 == ncols(); if (cellInfo(i).right_line && left) @@ -1227,7 +1308,7 @@ LyXAlignment Tabular::getAlignment(idx_type cell, bool onlycolumn) const { if (!onlycolumn && (isMultiColumn(cell) || isMultiRow(cell))) return cellInfo(cell).alignment; - + return column_info[cellColumn(cell)].alignment; } @@ -1241,6 +1322,27 @@ Tabular::getVAlignment(idx_type cell, bool onlycolumn) const } +int Tabular::offsetVAlignment() const +{ + // for top-alignment the first horizontal table line must be exactly at + // the position of the base line of the surrounding text line + // for bottom alignment, the same is for the last table line + int offset_valign = 0; + switch (tabular_valignment) { + case Tabular::LYX_VALIGN_BOTTOM: + offset_valign = rowAscent(0) - height(); + break; + case Tabular::LYX_VALIGN_MIDDLE: + offset_valign = (- height()) / 2 + rowAscent(0); + break; + case Tabular::LYX_VALIGN_TOP: + offset_valign = rowAscent(0); + break; + } + return offset_valign; +} + + Length const Tabular::getPWidth(idx_type cell) const { if (isMultiColumn(cell)) @@ -1249,6 +1351,12 @@ Length const Tabular::getPWidth(idx_type cell) const } +Length const Tabular::getMROffset(idx_type cell) const +{ + return cellInfo(cell).mroffset; +} + + int Tabular::textHOffset(idx_type cell) const { // the LaTeX Way :-( @@ -1293,7 +1401,7 @@ int Tabular::textVOffset(idx_type cell) const int voffset = cellInfo(cell).voffset; if (isMultiRow(cell)) { row_type const row = cellRow(cell); - voffset += (cellHeight(cell) - rowAscent(row) - rowDescent(row))/2; + voffset += (cellHeight(cell) - rowAscent(row) - rowDescent(row))/2; } return voffset; } @@ -1302,7 +1410,13 @@ int Tabular::textVOffset(idx_type cell) const Tabular::idx_type Tabular::getFirstCellInRow(row_type row) const { col_type c = 0; - while (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW) + idx_type const numcells = numberOfCellsInRow(row); + // we check against numcells to make sure we do not crash if all the + // cells are multirow (bug #7535), but in that case our return value + // is really invalid, i.e., it is NOT the first cell in the row. but + // i do not know what to do here. (rgh) + while (c < numcells - 1 + && cell_info[row][c].multirow == CELL_PART_OF_MULTIROW) ++c; return cell_info[row][c].cellno; } @@ -1311,8 +1425,12 @@ Tabular::idx_type Tabular::getFirstCellInRow(row_type row) const Tabular::idx_type Tabular::getLastCellInRow(row_type row) const { col_type c = ncols() - 1; - while (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW - || cell_info[row][c].multicolumn == CELL_PART_OF_MULTICOLUMN) + // of course we check against 0 so we don't crash. but we have the same + // problem as in the previous routine: if all the cells are part of a + // multirow or part of a multi column, then our return value is invalid. + while (c > 0 + && (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW + || cell_info[row][c].multicolumn == CELL_PART_OF_MULTICOLUMN)) --c; return cell_info[row][c].cellno; } @@ -1362,11 +1480,12 @@ void Tabular::write(ostream & os) const << write_attribute("lastFootBottomDL", endlastfoot.bottomDL) << write_attribute("lastFootEmpty", endlastfoot.empty); // longtables cannot be aligned vertically - if (!is_long_tabular) - os << write_attribute("tabularvalignment", tabular_valignment); + if (!is_long_tabular) { + os << write_attribute("tabularvalignment", tabular_valignment); + os << write_attribute("tabularwidth", tabular_width); + } if (is_long_tabular) - os << write_attribute("longtabularalignment", - longtabular_alignment); + os << write_attribute("longtabularalignment", longtabular_alignment); os << ">\n"; for (col_type c = 0; c < ncols(); ++c) { os << "write(os); os << "\n\\end_inset\n" << "\n"; + // FIXME This can be removed again once the mystery + // crash has been resolved. + os << flush; } os << "\n"; } @@ -1433,14 +1556,13 @@ void Tabular::read(Lexer & lex) l_getline(is, line); if (!prefixIs(line, "= 2, /**/); + LATTEST(version >= 2); int rows_arg; if (!getTokenValue(line, "rows", rows_arg)) @@ -1459,6 +1581,7 @@ void Tabular::read(Lexer & lex) getTokenValue(line, "booktabs", use_booktabs); getTokenValue(line, "islongtable", is_long_tabular); getTokenValue(line, "tabularvalignment", tabular_valignment); + getTokenValue(line, "tabularwidth", tabular_width); getTokenValue(line, "longtabularalignment", longtabular_alignment); getTokenValue(line, "firstHeadTopDL", endfirsthead.topDL); getTokenValue(line, "firstHeadBottomDL", endfirsthead.bottomDL); @@ -1513,6 +1636,7 @@ void Tabular::read(Lexer & lex) } getTokenValue(line, "multicolumn", cell_info[i][j].multicolumn); getTokenValue(line, "multirow", cell_info[i][j].multirow); + getTokenValue(line, "mroffset", cell_info[i][j].mroffset); getTokenValue(line, "alignment", cell_info[i][j].alignment); getTokenValue(line, "valignment", cell_info[i][j].valignment); getTokenValue(line, "topline", cell_info[i][j].top_line); @@ -1552,18 +1676,35 @@ void Tabular::read(Lexer & lex) bool Tabular::isMultiColumn(idx_type cell) const { - return (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN + return (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN || cellInfo(cell).multicolumn == CELL_PART_OF_MULTICOLUMN); } -Tabular::CellData & Tabular::cellInfo(idx_type cell) const +bool Tabular::hasMultiColumn(col_type c) const +{ + for (row_type r = 0; r < nrows(); ++r) { + if (isMultiColumn(cellIndex(r, c))) + return true; + } + return false; +} + + +Tabular::CellData const & Tabular::cellInfo(idx_type cell) const { return cell_info[cellRow(cell)][cellColumn(cell)]; } -Tabular::idx_type Tabular::setMultiColumn(idx_type cell, idx_type number) +Tabular::CellData & Tabular::cellInfo(idx_type cell) +{ + return cell_info[cellRow(cell)][cellColumn(cell)]; +} + + +Tabular::idx_type Tabular::setMultiColumn(idx_type cell, idx_type number, + bool const right_border) { idx_type const col = cellColumn(cell); idx_type const row = cellRow(cell); @@ -1576,10 +1717,10 @@ Tabular::idx_type Tabular::setMultiColumn(idx_type cell, idx_type number) cs.multicolumn = CELL_BEGIN_OF_MULTICOLUMN; if (column_info[col].alignment != LYX_ALIGN_DECIMAL) cs.alignment = column_info[col].alignment; - if (col > 0) - setRightLine(cell, rightLine(cellIndex(row, col - 1))); + setRightLine(cell, right_border); - for (idx_type i = 1; i < number; ++i) { + idx_type lastcell = cellIndex(row, col + number - 1); + for (idx_type i = 1; i < lastcell - cell + 1; ++i) { CellData & cs1 = cellInfo(cell + i); cs1.multicolumn = CELL_PART_OF_MULTICOLUMN; cs.inset->appendParagraphs(cs1.inset->paragraphs()); @@ -1596,8 +1737,18 @@ bool Tabular::isMultiRow(idx_type cell) const || cellInfo(cell).multirow == CELL_PART_OF_MULTIROW); } +bool Tabular::hasMultiRow(row_type r) const +{ + for (col_type c = 0; c < ncols(); ++c) { + if (isMultiRow(cellIndex(r, c))) + return true; + } + return false; +} -Tabular::idx_type Tabular::setMultiRow(idx_type cell, idx_type number) +Tabular::idx_type Tabular::setMultiRow(idx_type cell, idx_type number, + bool const bottom_border, + LyXAlignment const halign) { idx_type const col = cellColumn(cell); idx_type const row = cellRow(cell); @@ -1613,13 +1764,13 @@ Tabular::idx_type Tabular::setMultiRow(idx_type cell, idx_type number) // be changed for the whole table row, // support changing this only for the multirow cell can be done via // \multirowsetup - // this feature would be a fileformat change - // until LyX supports this, use the deault alignment of multirow - // cells: left - cs.alignment = LYX_ALIGN_LEFT; + if (getPWidth(cell).zero()) + cs.alignment = halign; + else + cs.alignment = LYX_ALIGN_LEFT; - // set the bottom row of the last selected cell - setBottomLine(cell, bottomLine(cell + (number - 1)*ncols())); + // set the bottom line of the last selected cell + setBottomLine(cell, bottom_border); for (idx_type i = 1; i < number; ++i) { CellData & cs1 = cell_info[row + i][col]; @@ -1650,7 +1801,7 @@ Tabular::idx_type Tabular::rowSpan(idx_type cell) const col_type row = cellRow(cell) + 1; while (row < nrows() && isPartOfMultiRow(row, column)) ++row; - + return row - cellRow(cell); } @@ -1694,13 +1845,13 @@ void Tabular::unsetMultiRow(idx_type cell) } -void Tabular::setRotateCell(idx_type cell, bool flag) +void Tabular::setRotateCell(idx_type cell, int value) { - cellInfo(cell).rotate = flag; + cellInfo(cell).rotate = value; } -bool Tabular::getRotateCell(idx_type cell) const +int Tabular::getRotateCell(idx_type cell) const { return cellInfo(cell).rotate; } @@ -1712,7 +1863,7 @@ bool Tabular::needRotating() const return true; for (row_type r = 0; r < nrows(); ++r) for (col_type c = 0; c < ncols(); ++c) - if (cell_info[r][c].rotate) + if (cell_info[r][c].rotate != 0) return true; return false; } @@ -1730,7 +1881,7 @@ Tabular::idx_type Tabular::cellAbove(idx_type cell) const { if (cellRow(cell) == 0) return cell; - + col_type const col = cellColumn(cell); row_type r = cellRow(cell) - 1; while (r > 0 && cell_info[r][col].multirow == CELL_PART_OF_MULTIROW) @@ -1751,8 +1902,8 @@ Tabular::idx_type Tabular::cellBelow(idx_type cell) const Tabular::idx_type Tabular::cellIndex(row_type row, col_type column) const { - LASSERT(column != npos && column < ncols() - && row != npos && row < nrows(), /**/); + LASSERT(column != npos && column < ncols(), column = 0); + LASSERT(row != npos && row < nrows(), row = 0); return cell_info[row][column].cellno; } @@ -1853,41 +2004,49 @@ bool Tabular::getLTNewPage(row_type row) const } -bool Tabular::haveLTHead() const +bool Tabular::haveLTHead(bool withcaptions) const { + if (!is_long_tabular) + return false; for (row_type i = 0; i < nrows(); ++i) - if (row_info[i].endhead) + if (row_info[i].endhead && + (withcaptions || !row_info[i].caption)) return true; return false; } -bool Tabular::haveLTFirstHead() const +bool Tabular::haveLTFirstHead(bool withcaptions) const { - if (endfirsthead.empty) + if (!is_long_tabular || endfirsthead.empty) return false; for (row_type r = 0; r < nrows(); ++r) - if (row_info[r].endfirsthead) + if (row_info[r].endfirsthead && + (withcaptions || !row_info[r].caption)) return true; return false; } -bool Tabular::haveLTFoot() const +bool Tabular::haveLTFoot(bool withcaptions) const { + if (!is_long_tabular) + return false; for (row_type r = 0; r < nrows(); ++r) - if (row_info[r].endfoot) + if (row_info[r].endfoot && + (withcaptions || !row_info[r].caption)) return true; return false; } -bool Tabular::haveLTLastFoot() const +bool Tabular::haveLTLastFoot(bool withcaptions) const { - if (endlastfoot.empty) + if (!is_long_tabular || endlastfoot.empty) return false; for (row_type r = 0; r < nrows(); ++r) - if (row_info[r].endlastfoot) + if (row_info[r].endlastfoot && + (withcaptions || !row_info[r].caption)) return true; return false; } @@ -1897,11 +2056,16 @@ Tabular::idx_type Tabular::setLTCaption(row_type row, bool what) { idx_type i = getFirstCellInRow(row); if (what) { - setMultiColumn(i, numberOfCellsInRow(row)); + setMultiColumn(i, numberOfCellsInRow(row), false); setTopLine(i, false); setBottomLine(i, false); setLeftLine(i, false); setRightLine(i, false); + if (!row_info[row].endfirsthead && !row_info[row].endhead && + !row_info[row].endfoot && !row_info[row].endlastfoot) { + setLTHead(row, true, endfirsthead, true); + row_info[row].endfirsthead = true; + } } else { unsetMultiColumn(i); // When unsetting a caption row, also all existing @@ -1918,11 +2082,34 @@ bool Tabular::ltCaption(row_type row) const } -bool Tabular::haveLTCaption() const +bool Tabular::haveLTCaption(CaptionType captiontype) const { - for (row_type r = 0; r < nrows(); ++r) - if (row_info[r].caption) - return true; + if (!is_long_tabular) + return false; + for (row_type r = 0; r < nrows(); ++r) { + if (row_info[r].caption) { + switch (captiontype) { + case CAPTION_FIRSTHEAD: + if (row_info[r].endfirsthead) + return true; + break; + case CAPTION_HEAD: + if (row_info[r].endhead) + return true; + break; + case CAPTION_FOOT: + if (row_info[r].endfoot) + return true; + break; + case CAPTION_LASTFOOT: + if (row_info[r].endlastfoot) + return true; + break; + case CAPTION_ANY: + return true; + } + } + } return false; } @@ -1947,14 +2134,14 @@ void Tabular::setRowDescent(row_type row, int height) int Tabular::rowAscent(row_type row) const { - LASSERT(row < nrows(), /**/); + LASSERT(row < nrows(), row = 0); return row_info[row].ascent; } int Tabular::rowDescent(row_type row) const { - LASSERT(row < nrows(), /**/); + LASSERT(row < nrows(), row = 0); return row_info[row].descent; } @@ -1971,21 +2158,21 @@ int Tabular::height() const bool Tabular::isPartOfMultiColumn(row_type row, col_type column) const { - LASSERT(row < nrows(), /**/); - LASSERT(column < ncols(), /**/); + LASSERT(row < nrows(), return false); + LASSERT(column < ncols(), return false); return cell_info[row][column].multicolumn == CELL_PART_OF_MULTICOLUMN; } bool Tabular::isPartOfMultiRow(row_type row, col_type column) const { - LASSERT(row < nrows(), /**/); - LASSERT(column < ncols(), /**/); + LASSERT(row < nrows(), return false); + LASSERT(column < ncols(), return false); return cell_info[row][column].multirow == CELL_PART_OF_MULTIROW; } -int Tabular::TeXTopHLine(odocstream & os, row_type row, string const lang) const +void Tabular::TeXTopHLine(otexstream & os, row_type row, string const & lang) const { // we only output complete row lines and the 1st row here, the rest // is done in Tabular::TeXBottomHLine(...) @@ -1999,15 +2186,15 @@ int Tabular::TeXTopHLine(odocstream & os, row_type row, string const lang) const // multirow, no line must be drawn. if (row != 0) if (isMultiRow(cellIndex(row, c)) - && isMultiRow(cellIndex(row - 1, c))) - topline[c] = false; + && cell_info[row][c].multirow != CELL_BEGIN_OF_MULTIROW) + topline[c] = false; if (topline[c]) ++nset; } // do nothing if empty first row, or incomplete row line after if ((row == 0 && nset == 0) || (row > 0 && nset != ncols())) - return 0; + return; // only output complete row lines and the 1st row's clines if (nset == ncols()) { @@ -2023,32 +2210,31 @@ int Tabular::TeXTopHLine(odocstream & os, row_type row, string const lang) const for (col_type j = 0 ; j < c; ++j) if (column_info[j].alignment == LYX_ALIGN_DECIMAL) ++offset; - + //babel makes the "-" character an active one, so we have to suppress this here //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289# if (lang == "slovak" || lang == "czech") - os << "\\expandafter" << (use_booktabs ? "\\cmidrule" : "\\cline") + os << "\\expandafter" << (use_booktabs ? "\\cmidrule" : "\\cline") << "\\expandafter{\\expandafter" << c + 1 + offset << "\\string-"; else os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 + offset << '-'; - + col_type cstart = c; for ( ; c < ncols() && topline[c]; ++c) {} - + for (col_type j = cstart ; j < c ; ++j) if (column_info[j].alignment == LYX_ALIGN_DECIMAL) ++offset; - + os << c + offset << "} "; } } } os << "\n"; - return 1; } -int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) const +void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const & lang) const { // we output bottomlines of row r and the toplines of row r+1 // if the latter do not span the whole tabular @@ -2060,13 +2246,14 @@ int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) co for (col_type c = 0; c < ncols(); ++c) { bottomline.push_back(bottomLine(cellIndex(row, c))); topline.push_back(!lastrow && topLine(cellIndex(row + 1, c))); - // If cell is part of a multirow and not the last or first cell of the + // If cell is part of a multirow and not the last cell of the // multirow, no line must be drawn. if (!lastrow) if (isMultiRow(cellIndex(row, c)) - && isMultiRow(cellIndex(row + 1, c))) { - bottomline[c] = false; - topline[c] = false; + && isMultiRow(cellIndex(row + 1, c)) + && cell_info[row + 1][c].multirow != CELL_BEGIN_OF_MULTIROW) { + bottomline[c] = false; + topline[c] = false; } nextrowset &= topline[c]; } @@ -2082,7 +2269,7 @@ int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) co // do nothing if empty, OR incomplete row line with a topline in next row if (nset == 0 || (nextrowset && nset != ncols())) - return 0; + return; if (nset == ncols()) { if (use_booktabs) @@ -2096,7 +2283,7 @@ int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) co for (col_type j = 0 ; j < c; ++j) if (column_info[j].alignment == LYX_ALIGN_DECIMAL) ++offset; - + //babel makes the "-" character an active one, so we have to suppress this here //see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289# if (lang == "slovak" || lang == "czech") @@ -2104,30 +2291,28 @@ int Tabular::TeXBottomHLine(odocstream & os, row_type row, string const lang) co << "\\expandafter{\\expandafter" << c + 1 + offset << "\\string-"; else os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 + offset << '-'; - + col_type cstart = c; for ( ; c < ncols() && bottomline[c]; ++c) {} - + for (col_type j = cstart ; j < c ; ++j) if (column_info[j].alignment == LYX_ALIGN_DECIMAL) ++offset; - + os << c + offset << "} "; } } } os << "\n"; - return 1; } -int Tabular::TeXCellPreamble(odocstream & os, idx_type cell, - bool & ismulticol, bool & ismultirow) const +void Tabular::TeXCellPreamble(otexstream & os, idx_type cell, + bool & ismulticol, bool & ismultirow) const { - int ret = 0; row_type const r = cellRow(cell); if (is_long_tabular && row_info[r].caption) - return ret; + return; Tabular::VAlignment valign = getVAlignment(cell, !isMultiColumn(cell)); LyXAlignment align = getAlignment(cell, !isMultiColumn(cell)); @@ -2138,7 +2323,7 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell, bool colright = columnRightLine(c); bool colleft = columnLeftLine(c); bool nextcolleft = nextcol < ncols() && columnLeftLine(nextcol); - bool nextcellleft = nextcol < ncols() + bool nextcellleft = nextcol < ncols() && leftLine(cellIndex(r, nextcol)); bool coldouble = colright && nextcolleft; bool celldouble = rightLine(cell) && nextcellleft; @@ -2150,8 +2335,11 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell, || (coldouble != celldouble); // we center in multicol when no decimal point - ismulticol |= ((column_info[c].alignment == LYX_ALIGN_DECIMAL) - && (cellInfo(cell).decimal_width == 0)); + if (column_info[c].alignment == LYX_ALIGN_DECIMAL) { + docstring const align_d = column_info[c].decimal_point; + DocIterator const dit = separatorPos(cellInset(cell), align_d); + ismulticol |= !dit; + } // up counter by 1 for each decimally aligned col since they use 2 latex cols int latexcolspan = columnSpan(cell); @@ -2225,13 +2413,15 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell, else // we need to set a default value os << "*"; - os << "}{"; + os << "}"; + if (!getMROffset(cell).zero()) + os << "[" << from_ascii(getMROffset(cell).asLatexString()) << "]"; + os << "{"; } // end if ismultirow - if (getRotateCell(cell)) { - os << "\\begin{sideways}\n"; - ++ret; - } + if (getRotateCell(cell) != 0) + os << "\\begin{turn}{" << convert(getRotateCell(cell)) << "}\n"; + if (getUsebox(cell) == BOX_PARBOX) { os << "\\parbox["; switch (valign) { @@ -2262,139 +2452,99 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell, } os << "]{" << from_ascii(getPWidth(cell).asLatexString()) << "}\n"; - ++ret; } - return ret; } -int Tabular::TeXCellPostamble(odocstream & os, idx_type cell, - bool ismulticol, bool ismultirow) const +void Tabular::TeXCellPostamble(otexstream & os, idx_type cell, + bool ismulticol, bool ismultirow) const { - int ret = 0; row_type const r = cellRow(cell); if (is_long_tabular && row_info[r].caption) - return ret; + return; // usual cells if (getUsebox(cell) == BOX_PARBOX) os << '}'; - else if (getUsebox(cell) == BOX_MINIPAGE) { - os << "%\n\\end{minipage}"; - ret += 2; - } - if (getRotateCell(cell)) { - os << "%\n\\end{sideways}"; - ++ret; - } + else if (getUsebox(cell) == BOX_MINIPAGE) + os << breakln << "\\end{minipage}"; + if (getRotateCell(cell) != 0) + os << breakln << "\\end{turn}"; if (ismultirow) os << '}'; if (ismulticol) os << '}'; - - return ret; } -int Tabular::TeXLongtableHeaderFooter(odocstream & os, - OutputParams const & runparams) const +void Tabular::TeXLongtableHeaderFooter(otexstream & os, + OutputParams const & runparams) const { if (!is_long_tabular) - return 0; + return; - int ret = 0; // caption handling - // the caption must be output before the headers + // output caption which is in no header or footer if (haveLTCaption()) { for (row_type r = 0; r < nrows(); ++r) { - if (row_info[r].caption) { - ret += TeXRow(os, r, runparams); - } + if (row_info[r].caption && + !row_info[r].endfirsthead && !row_info[r].endhead && + !row_info[r].endfoot && !row_info[r].endlastfoot) + TeXRow(os, r, runparams); } } // output first header info - // first header must be output before the header, otherwise the - // correct caption placement becomes really weird if (haveLTFirstHead()) { - if (endfirsthead.topDL) { + if (endfirsthead.topDL) os << "\\hline\n"; - ++ret; - } for (row_type r = 0; r < nrows(); ++r) { - if (row_info[r].endfirsthead) { - ret += TeXRow(os, r, runparams); - } + if (row_info[r].endfirsthead) + TeXRow(os, r, runparams); } - if (endfirsthead.bottomDL) { + if (endfirsthead.bottomDL) os << "\\hline\n"; - ++ret; - } os << "\\endfirsthead\n"; - ++ret; } // output header info if (haveLTHead()) { - if (endfirsthead.empty && !haveLTFirstHead()) { + if (endfirsthead.empty && !haveLTFirstHead()) os << "\\endfirsthead\n"; - ++ret; - } - if (endhead.topDL) { + if (endhead.topDL) os << "\\hline\n"; - ++ret; - } for (row_type r = 0; r < nrows(); ++r) { - if (row_info[r].endhead) { - ret += TeXRow(os, r, runparams); - } + if (row_info[r].endhead) + TeXRow(os, r, runparams); } - if (endhead.bottomDL) { + if (endhead.bottomDL) os << "\\hline\n"; - ++ret; - } os << "\\endhead\n"; - ++ret; } // output footer info if (haveLTFoot()) { - if (endfoot.topDL) { + if (endfoot.topDL) os << "\\hline\n"; - ++ret; - } for (row_type r = 0; r < nrows(); ++r) { - if (row_info[r].endfoot) { - ret += TeXRow(os, r, runparams); - } + if (row_info[r].endfoot) + TeXRow(os, r, runparams); } - if (endfoot.bottomDL) { + if (endfoot.bottomDL) os << "\\hline\n"; - ++ret; - } os << "\\endfoot\n"; - ++ret; - if (endlastfoot.empty && !haveLTLastFoot()) { + if (endlastfoot.empty && !haveLTLastFoot()) os << "\\endlastfoot\n"; - ++ret; - } } // output lastfooter info if (haveLTLastFoot()) { - if (endlastfoot.topDL) { + if (endlastfoot.topDL) os << "\\hline\n"; - ++ret; - } for (row_type r = 0; r < nrows(); ++r) { - if (row_info[r].endlastfoot) { - ret += TeXRow(os, r, runparams); - } + if (row_info[r].endlastfoot) + TeXRow(os, r, runparams); } - if (endlastfoot.bottomDL) { + if (endlastfoot.bottomDL) os << "\\hline\n"; - ++ret; - } os << "\\endlastfoot\n"; - ++ret; } - return ret; } @@ -2408,23 +2558,22 @@ bool Tabular::isValidRow(row_type row) const } -int Tabular::TeXRow(odocstream & os, row_type row, - OutputParams const & runparams) const +void Tabular::TeXRow(otexstream & os, row_type row, + OutputParams const & runparams) const { idx_type cell = cellIndex(row, 0); - shared_ptr inset = cellInset(cell); + InsetTableCell const * inset = cellInset(cell); Paragraph const & par = inset->paragraphs().front(); string const lang = par.getParLanguage(buffer().params())->lang(); //output the top line - int ret = TeXTopHLine(os, row, lang); + TeXTopHLine(os, row, lang); if (row_info[row].top_space_default) { if (use_booktabs) os << "\\addlinespace\n"; else os << "\\noalign{\\vskip\\doublerulesep}\n"; - ++ret; } else if(!row_info[row].top_space.zero()) { if (use_booktabs) os << "\\addlinespace[" @@ -2435,28 +2584,33 @@ int Tabular::TeXRow(odocstream & os, row_type row, << from_ascii(row_info[row].top_space.asLatexString()) << "}\n"; } - ++ret; } bool ismulticol = false; bool ismultirow = false; for (col_type c = 0; c < ncols(); ++c) { if (isPartOfMultiColumn(row, c)) continue; - - if (isPartOfMultiRow(row, c) && - column_info[c].alignment != LYX_ALIGN_DECIMAL) { - os << " & "; + + cell = cellIndex(row, c); + + if (isPartOfMultiRow(row, c) + && column_info[c].alignment != LYX_ALIGN_DECIMAL) { + if (cell != getLastCellInRow(row)) + os << " & "; continue; } - cell = cellIndex(row, c); - ret += TeXCellPreamble(os, cell, ismulticol, ismultirow); - shared_ptr inset = cellInset(cell); + TeXCellPreamble(os, cell, ismulticol, ismultirow); + InsetTableCell const * inset = cellInset(cell); Paragraph const & par = inset->paragraphs().front(); + + os.texrow().forceStart(par.id(), 0); + bool rtl = par.isRTL(buffer().params()) && !par.empty() - && getPWidth(cell).zero(); + && getPWidth(cell).zero() + && !runparams.use_polyglossia; if (rtl) { string const lang = @@ -2465,7 +2619,7 @@ int Tabular::TeXRow(odocstream & os, row_type row, os << "\\textFR{"; else if (lang == "arabic_arabi") os << "\\textAR{"; - // currently, remaning RTL languages are + // currently, remaining RTL languages are // arabic_arabtex and hebrew else os << "\\R{"; @@ -2478,37 +2632,44 @@ int Tabular::TeXRow(odocstream & os, row_type row, ? OutputParams::PLAIN : OutputParams::ALIGNED; - if (getAlignment(cell) == LYX_ALIGN_DECIMAL - && cellInfo(cell).decimal_width != 0) { + if (getAlignment(cell) == LYX_ALIGN_DECIMAL) { // copy cell and split in 2 - InsetTableCell head = InsetTableCell(*cellInset(cell).get()); - head.getText(0)->setMacrocontextPosition( - cellInset(cell)->getText(0)->macrocontextPosition()); - head.setBuffer(buffer()); + InsetTableCell head = InsetTableCell(*cellInset(cell)); + head.setBuffer(const_cast(buffer())); + DocIterator dit = cellInset(cell)->getText(0)->macrocontextPosition(); + dit.pop_back(); + dit.push_back(CursorSlice(head)); + head.setMacrocontextPositionRecursive(dit); bool hassep = false; InsetTableCell tail = splitCell(head, column_info[c].decimal_point, hassep); head.latex(os, newrp); - os << '&'; - ret += tail.latex(os, newrp); - } else if (!isPartOfMultiRow(row, c)) - ret += inset->latex(os, newrp); + if (hassep) { + os << '&'; + tail.setBuffer(head.buffer()); + dit.pop_back(); + dit.push_back(CursorSlice(tail)); + tail.setMacrocontextPositionRecursive(dit); + tail.latex(os, newrp); + } + } else if (!isPartOfMultiRow(row, c)) { + if (!runparams.nice) + os.texrow().start(par.id(), 0); + inset->latex(os, newrp); + } runparams.encoding = newrp.encoding; if (rtl) os << '}'; - ret += TeXCellPostamble(os, cell, ismulticol, ismultirow); + TeXCellPostamble(os, cell, ismulticol, ismultirow); if (cell != getLastCellInRow(row)) { // not last cell in row - os << " & "; + if (runparams.nice) + os << " & "; + else + os << " &\n"; } } - if (row_info[row].caption && !endfirsthead.empty && !haveLTFirstHead()) - // if no first header and no empty first header is used, - // the caption needs to be terminated by \endfirsthead - // (bug 6057) - os << "\\endfirsthead"; - else - os << "\\tabularnewline"; + os << "\\tabularnewline"; if (row_info[row].bottom_space_default) { if (use_booktabs) os << "\\addlinespace"; @@ -2522,17 +2683,15 @@ int Tabular::TeXRow(odocstream & os, row_type row, << ']'; } os << '\n'; - ++ret; //output the bottom line - ret += TeXBottomHLine(os, row, lang); + TeXBottomHLine(os, row, lang); if (row_info[row].interline_space_default) { if (use_booktabs) os << "\\addlinespace\n"; else os << "\\noalign{\\vskip\\doublerulesep}\n"; - ++ret; } else if (!row_info[row].interline_space.zero()) { if (use_booktabs) os << "\\addlinespace[" @@ -2542,24 +2701,26 @@ int Tabular::TeXRow(odocstream & os, row_type row, os << "\\noalign{\\vskip" << from_ascii(row_info[row].interline_space.asLatexString()) << "}\n"; - ++ret; } - return ret; } -int Tabular::latex(odocstream & os, OutputParams const & runparams) const +void Tabular::latex(otexstream & os, OutputParams const & runparams) const { - int ret = 0; + bool const is_tabular_star = !tabular_width.zero(); + TexRow::RowEntry pos = TexRow::textEntry(runparams.lastid, runparams.lastpos); //+--------------------------------------------------------------------- //+ first the opening preamble + //+--------------------------------------------------------------------- - if (rotate) { - os << "\\begin{sideways}\n"; - ++ret; - } + os << safebreakln; + if (!TexRow::isNone(pos)) + os.texrow().start(pos); + + if (rotate != 0) + os << "\\begin{turn}{" << convert(rotate) << "}\n"; + if (is_long_tabular) { os << "\\begin{longtable}"; switch (longtabular_alignment) { @@ -2573,7 +2734,10 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const break; } } else { - os << "\\begin{tabular}"; + if (is_tabular_star) + os << "\\begin{tabular*}{" << from_ascii(tabular_width.asLatexString()) << "}"; + else + os << "\\begin{tabular}"; switch (tabular_valignment) { case LYX_VALIGN_TOP: os << "[t]"; @@ -2585,9 +2749,12 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const break; } } - + os << "{"; + if (is_tabular_star) + os << "@{\\extracolsep{\\fill}}"; + for (col_type c = 0; c < ncols(); ++c) { if (columnLeftLine(c)) os << '|'; @@ -2595,6 +2762,7 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const os << column_info[c].align_special; } else { if (!column_info[c].p_width.zero()) { + bool decimal = false; switch (column_info[c].alignment) { case LYX_ALIGN_LEFT: os << ">{\\raggedright}"; @@ -2609,24 +2777,49 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const case LYX_ALIGN_BLOCK: case LYX_ALIGN_LAYOUT: case LYX_ALIGN_SPECIAL: + break; case LYX_ALIGN_DECIMAL: + os << ">{\\raggedleft}"; + decimal = true; break; } + char valign = 'p'; switch (column_info[c].valignment) { case LYX_VALIGN_TOP: - os << 'p'; + // this is the default break; case LYX_VALIGN_MIDDLE: - os << 'm'; + valign = 'm'; break; case LYX_VALIGN_BOTTOM: - os << 'b'; + valign = 'b'; break; - } - os << '{' - << from_ascii(column_info[c].p_width.asLatexString()) - << '}'; + } + os << valign; + + // Fixed-width cells with alignment at decimal separator + // are output as two cells of half the width with the decimal + // separator as column sep. This effectively puts the content + // centered, which differs from the normal decimal sep alignment + // and is not ideal, but we cannot do better ATM (see #9568). + // FIXME: Implement proper decimal sep alignment, e.g. via siunitx. + if (decimal) { + docstring const halffixedwith = + from_ascii(Length(column_info[c].p_width.value() / 2, + column_info[c].p_width.unit()).asLatexString()); + os << '{' + << halffixedwith + << '}' + << "@{\\extracolsep{0pt}" << column_info[c].decimal_point << "}" + << valign + << '{' + << halffixedwith + << '}'; + } else + os << '{' + << from_ascii(column_info[c].p_width.asLatexString()) + << '}'; } else { switch (column_info[c].alignment) { case LYX_ALIGN_LEFT: @@ -2648,9 +2841,8 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const os << '|'; } os << "}\n"; - ++ret; - ret += TeXLongtableHeaderFooter(os, runparams); + TeXLongtableHeaderFooter(os, runparams); //+--------------------------------------------------------------------- //+ the single row and columns (cells) + @@ -2658,11 +2850,9 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const for (row_type r = 0; r < nrows(); ++r) { if (isValidRow(r)) { - ret += TeXRow(os, r, runparams); - if (is_long_tabular && row_info[r].newpage) { + TeXRow(os, r, runparams); + if (is_long_tabular && row_info[r].newpage) os << "\\newpage\n"; - ++ret; - } } } @@ -2672,14 +2862,18 @@ int Tabular::latex(odocstream & os, OutputParams const & runparams) const if (is_long_tabular) os << "\\end{longtable}"; - else - os << "\\end{tabular}"; - if (rotate) { - os << "\n\\end{sideways}"; - ++ret; + else { + if (is_tabular_star) + os << "\\end{tabular*}"; + else + os << "\\end{tabular}"; } - return ret; + if (rotate != 0) + os << breakln << "\\end{turn}"; + + if (!TexRow::isNone(pos)) + os.texrow().start(pos); } @@ -2771,6 +2965,7 @@ int Tabular::docbook(odocstream & os, OutputParams const & runparams) const //+--------------------------------------------------------------------- // output caption info + // The caption flag wins over head/foot if (haveLTCaption()) { os << "\n"; ++ret; @@ -2783,11 +2978,12 @@ int Tabular::docbook(odocstream & os, OutputParams const & runparams) const ++ret; } // output header info - if (haveLTHead() || haveLTFirstHead()) { + if (haveLTHead(false) || haveLTFirstHead(false)) { os << "\n"; ++ret; for (row_type r = 0; r < nrows(); ++r) { - if (row_info[r].endhead || row_info[r].endfirsthead) { + if ((row_info[r].endhead || row_info[r].endfirsthead) && + !row_info[r].caption) { ret += docbookRow(os, r, runparams); } } @@ -2795,11 +2991,12 @@ int Tabular::docbook(odocstream & os, OutputParams const & runparams) const ++ret; } // output footer info - if (haveLTFoot() || haveLTLastFoot()) { + if (haveLTFoot(false) || haveLTLastFoot(false)) { os << "\n"; ++ret; for (row_type r = 0; r < nrows(); ++r) { - if (row_info[r].endfoot || row_info[r].endlastfoot) { + if ((row_info[r].endfoot || row_info[r].endlastfoot) && + !row_info[r].caption) { ret += docbookRow(os, r, runparams); } } @@ -2832,17 +3029,25 @@ int Tabular::docbook(odocstream & os, OutputParams const & runparams) const docstring Tabular::xhtmlRow(XHTMLStream & xs, row_type row, - OutputParams const & runparams) const + OutputParams const & runparams, bool header) const { docstring ret; + string const celltag = header ? "th" : "td"; idx_type cell = getFirstCellInRow(row); xs << html::StartTag("tr"); for (col_type c = 0; c < ncols(); ++c) { - if (isPartOfMultiColumn(row, c)) + if (isPartOfMultiColumn(row, c) || isPartOfMultiRow(row, c)) continue; stringstream attr; + + Length const cwidth = column_info[c].p_width; + if (!cwidth.zero()) { + string const hwidth = cwidth.asHTMLString(); + attr << "style =\"width: " << hwidth << ";\" "; + } + attr << "align='"; switch (getAlignment(cell)) { case LYX_ALIGN_LEFT: @@ -2871,10 +3076,12 @@ docstring Tabular::xhtmlRow(XHTMLStream & xs, row_type row, if (isMultiColumn(cell)) attr << " colspan='" << columnSpan(cell) << "'"; + else if (isMultiRow(cell)) + attr << " rowspan='" << rowSpan(cell) << "'"; - xs << html::StartTag("td", attr.str()); + xs << html::StartTag(celltag, attr.str(), true) << html::CR(); ret += cellInset(cell)->xhtml(xs, runparams); - xs << html::EndTag("td"); + xs << html::EndTag(celltag) << html::CR(); ++cell; } xs << html::EndTag("tr"); @@ -2885,21 +3092,86 @@ docstring Tabular::xhtmlRow(XHTMLStream & xs, row_type row, docstring Tabular::xhtml(XHTMLStream & xs, OutputParams const & runparams) const { docstring ret; - // It's unclear to me if we need to mess with the long table stuff. - // We can borrow that too from docbook, if so. - xs << html::StartTag("tbody"); + if (is_long_tabular) { + // we'll wrap it in a div, so as to deal with alignment + string align; + switch (longtabular_alignment) { + case LYX_LONGTABULAR_ALIGN_LEFT: + align = "left"; + break; + case LYX_LONGTABULAR_ALIGN_CENTER: + align = "center"; + break; + case LYX_LONGTABULAR_ALIGN_RIGHT: + align = "right"; + break; + } + xs << html::StartTag("div", "class='longtable' style='text-align: " + align + ";'") + << html::CR(); + // The caption flag wins over head/foot + if (haveLTCaption()) { + xs << html::StartTag("div", "class='longtable-caption' style='text-align: " + align + ";'") + << html::CR(); + for (row_type r = 0; r < nrows(); ++r) + if (row_info[r].caption) + ret += xhtmlRow(xs, r, runparams); + xs << html::EndTag("div") << html::CR(); + } + } + + xs << html::StartTag("table") << html::CR(); + + // output header info + bool const havefirsthead = haveLTFirstHead(false); + // if we have a first head, then we are going to ignore the + // headers for the additional pages, since there aren't any + // in XHTML. this test accomplishes that. + bool const havehead = !havefirsthead && haveLTHead(false); + if (havehead || havefirsthead) { + xs << html::StartTag("thead") << html::CR(); + for (row_type r = 0; r < nrows(); ++r) { + if (((havefirsthead && row_info[r].endfirsthead) || + (havehead && row_info[r].endhead)) && + !row_info[r].caption) { + ret += xhtmlRow(xs, r, runparams, true); + } + } + xs << html::EndTag("thead") << html::CR(); + } + // output footer info + bool const havelastfoot = haveLTLastFoot(false); + // as before. + bool const havefoot = !havelastfoot && haveLTFoot(false); + if (havefoot || havelastfoot) { + xs << html::StartTag("tfoot") << html::CR(); + for (row_type r = 0; r < nrows(); ++r) { + if (((havelastfoot && row_info[r].endlastfoot) || + (havefoot && row_info[r].endfoot)) && + !row_info[r].caption) { + ret += xhtmlRow(xs, r, runparams); + } + } + xs << html::EndTag("tfoot") << html::CR(); + } + + xs << html::StartTag("tbody") << html::CR(); for (row_type r = 0; r < nrows(); ++r) { if (isValidRow(r)) { ret += xhtmlRow(xs, r, runparams); } } - xs << html::EndTag("tbody"); + xs << html::EndTag("tbody") + << html::CR() + << html::EndTag("table") + << html::CR(); + if (is_long_tabular) + xs << html::EndTag("div") << html::CR(); return ret; } -bool Tabular::plaintextTopHLine(odocstream & os, row_type row, +bool Tabular::plaintextTopHLine(odocstringstream & os, row_type row, vector const & clen) const { idx_type const fcell = getFirstCellInRow(row); @@ -2947,7 +3219,7 @@ bool Tabular::plaintextTopHLine(odocstream & os, row_type row, } -bool Tabular::plaintextBottomHLine(odocstream & os, row_type row, +bool Tabular::plaintextBottomHLine(odocstringstream & os, row_type row, vector const & clen) const { idx_type const fcell = getFirstCellInRow(row); @@ -2994,14 +3266,14 @@ bool Tabular::plaintextBottomHLine(odocstream & os, row_type row, } -void Tabular::plaintextPrintCell(odocstream & os, +void Tabular::plaintextPrintCell(odocstringstream & os, OutputParams const & runparams, idx_type cell, row_type row, col_type column, vector const & clen, - bool onlydata) const + bool onlydata, size_t max_length) const { odocstringstream sstr; - cellInset(cell)->plaintext(sstr, runparams); + cellInset(cell)->plaintext(sstr, runparams, max_length); if (onlydata) { os << sstr.str(); @@ -3044,9 +3316,9 @@ void Tabular::plaintextPrintCell(odocstream & os, } -void Tabular::plaintext(odocstream & os, +void Tabular::plaintext(odocstringstream & os, OutputParams const & runparams, int const depth, - bool onlydata, char_type delim) const + bool onlydata, char_type delim, size_t max_length) const { // first calculate the width of the single columns vector clen(ncols()); @@ -3060,7 +3332,7 @@ void Tabular::plaintext(odocstream & os, if (isMultiColumn(cell)) continue; odocstringstream sstr; - cellInset(cell)->plaintext(sstr, runparams); + cellInset(cell)->plaintext(sstr, runparams, max_length); if (clen[c] < sstr.str().length()) clen[c] = sstr.str().length(); } @@ -3072,7 +3344,7 @@ void Tabular::plaintext(odocstream & os, if (cell_info[r][c].multicolumn != CELL_BEGIN_OF_MULTICOLUMN) continue; odocstringstream sstr; - cellInset(cell)->plaintext(sstr, runparams); + cellInset(cell)->plaintext(sstr, runparams, max_length); int len = int(sstr.str().length()); idx_type const n = columnSpan(cell); for (col_type k = c; len > 0 && k < c + n - 1; ++k) @@ -3087,14 +3359,16 @@ void Tabular::plaintext(odocstream & os, if (!onlydata && plaintextTopHLine(os, r, clen)) os << docstring(depth * 2, ' '); for (col_type c = 0; c < ncols(); ++c) { - if (isPartOfMultiColumn(r, c)) + if (isPartOfMultiColumn(r, c) || isPartOfMultiRow(r,c)) continue; if (onlydata && c > 0) // we don't use operator<< for single UCS4 character. // see explanation in docstream.h os.put(delim); - plaintextPrintCell(os, runparams, cell, r, c, clen, onlydata); + plaintextPrintCell(os, runparams, cell, r, c, clen, onlydata, max_length); ++cell; + if (os.str().size() > max_length) + break; } os << endl; if (!onlydata) { @@ -3102,25 +3376,32 @@ void Tabular::plaintext(odocstream & os, if (plaintextBottomHLine(os, r, clen)) os << docstring(depth * 2, ' '); } + if (os.str().size() > max_length) + break; } } -shared_ptr Tabular::cellInset(idx_type cell) const +shared_ptr Tabular::cellInset(idx_type cell) { return cell_info[cellRow(cell)][cellColumn(cell)].inset; } -shared_ptr Tabular::cellInset(row_type row, - col_type column) const +shared_ptr Tabular::cellInset(row_type row, col_type column) { return cell_info[row][column].inset; } +InsetTableCell const * Tabular::cellInset(idx_type cell) const +{ + return cell_info[cellRow(cell)][cellColumn(cell)].inset.get(); +} + + void Tabular::setCellInset(row_type row, col_type column, - shared_ptr ins) const + shared_ptr ins) { CellData & cd = cell_info[row][column]; cd.inset = ins; @@ -3186,17 +3467,22 @@ bool InsetTableCell::allowParagraphCustomization(idx_type) const } +bool InsetTableCell::forceLocalFontSwitch() const +{ + return isFixedWidth; +} + + bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus & status) const { - bool enabled; + bool enabled = true; switch (cmd.action()) { - case LFUN_LAYOUT: - enabled = !forcePlainLayout(); - break; - case LFUN_LAYOUT_PARAGRAPH: - enabled = allowParagraphCustomization(); - break; + case LFUN_MATH_DISPLAY: + if (!hasFixedWidth()) { + enabled = false; + break; + } //fall-through default: return InsetText::getStatus(cur, cmd, status); } @@ -3204,7 +3490,7 @@ bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd, return true; } -docstring InsetTableCell::asString(bool intoInsets) +docstring InsetTableCell::asString(bool intoInsets) { docstring retval; if (paragraphs().empty()) @@ -3223,6 +3509,13 @@ docstring InsetTableCell::asString(bool intoInsets) } +void InsetTableCell::addToToc(DocIterator const & di, bool output_active, + UpdateType utype) const +{ + InsetText::iterateForToc(di, output_active, utype); +} + + docstring InsetTableCell::xhtml(XHTMLStream & xs, OutputParams const & rp) const { if (!isFixedWidth) @@ -3240,14 +3533,15 @@ docstring InsetTableCell::xhtml(XHTMLStream & xs, OutputParams const & rp) const InsetTabular::InsetTabular(Buffer * buf, row_type rows, col_type columns) - : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))), scx_(0), - rowselect_(false), colselect_(false) + : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))), + rowselect_(false), colselect_(false) { } InsetTabular::InsetTabular(InsetTabular const & tab) - : Inset(tab), tabular(tab.tabular), scx_(0) + : Inset(tab), tabular(tab.tabular), + rowselect_(false), colselect_(false) { } @@ -3283,6 +3577,13 @@ bool InsetTabular::insetAllowed(InsetCode code) const } +bool InsetTabular::allowsCaptionVariation(std::string const & newtype) const +{ + return tabular.is_long_tabular && + (newtype == "Standard" || newtype == "Unnumbered"); +} + + void InsetTabular::write(ostream & os) const { os << "Tabular" << endl; @@ -3290,10 +3591,17 @@ void InsetTabular::write(ostream & os) const } -docstring InsetTabular::contextMenu(BufferView const &, int, int) const +string InsetTabular::contextMenu(BufferView const &, int, int) const +{ + // FIXME: depending on the selection state, + // we could offer a different menu. + return cell(0)->contextMenuName() + ";" + contextMenuName(); +} + + +string InsetTabular::contextMenuName() const { - // FIXME: depending on the selection state, we could offer a different menu. - return from_ascii("context-tabular"); + return "context-tabular"; } @@ -3320,11 +3628,11 @@ void InsetTabular::read(Lexer & lex) int InsetTabular::rowFromY(Cursor & cur, int y) const { // top y coordinate of tabular - int h = yo(cur.bv()) - tabular.rowAscent(0); + int h = yo(cur.bv()) - tabular.rowAscent(0) + tabular.offsetVAlignment(); row_type r = 0; for (; r < tabular.nrows() && y > h; ++r) h += tabular.rowAscent(r) + tabular.rowDescent(r) - + tabular.interRowSpace(r); + + tabular.interRowSpace(r); return r - 1; } @@ -3345,10 +3653,7 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const { //lyxerr << "InsetTabular::metrics: " << mi.base.bv << " width: " << // mi.base.textwidth << "\n"; - if (!mi.base.bv) { - LYXERR0("need bv"); - LASSERT(false, /**/); - } + LBUFERR(mi.base.bv); for (row_type r = 0; r < tabular.nrows(); ++r) { int maxasc = 0; @@ -3363,39 +3668,44 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const MetricsInfo m = mi; Length const p_width = tabular.getPWidth(cell); if (!p_width.zero()) - m.base.textwidth = p_width.inPixels(mi.base.textwidth); + m.base.textwidth = p_width.inPixels(mi.base); tabular.cellInset(cell)->metrics(m, dim); if (!p_width.zero()) dim.wid = m.base.textwidth; - tabular.cellInfo(cell).width = dim.wid + 2 * WIDTH_OF_LINE + tabular.cellInfo(cell).width = dim.wid + 2 * WIDTH_OF_LINE + tabular.interColumnSpace(cell); // FIXME(?): do we need a second metrics call? - TextMetrics const & tm = + TextMetrics const & tm = mi.base.bv->textMetrics(tabular.cellInset(cell)->getText(0)); - // determine horiz offset because of decimal align (if necessary) - int decimal_hoffset = 0; + // determine horizontal offset because of decimal align (if necessary) int decimal_width = 0; if (tabular.getAlignment(cell) == LYX_ALIGN_DECIMAL) { - // make a copy which we will split in 2 - InsetTableCell head = InsetTableCell(*tabular.cellInset(cell).get()); - head.getText(0)->setMacrocontextPosition( - tabular.cellInset(cell)->getText(0)->macrocontextPosition()); - head.setBuffer(tabular.buffer()); - // split in 2 and calculate width of each part - bool hassep = false; - InsetTableCell tail = - splitCell(head, tabular.column_info[c].decimal_point, hassep); - Dimension dim1; - head.metrics(m, dim1); - decimal_hoffset = dim1.width(); - if (hassep) { + InsetTableCell tail = InsetTableCell(*tabular.cellInset(cell)); + tail.setBuffer(tabular.buffer()); + // we need to set macrocontext position everywhere + // otherwise we crash with nested insets (e.g. footnotes) + // after decimal point + DocIterator dit = tabular.cellInset(cell)->getText(0)->macrocontextPosition(); + dit.pop_back(); + dit.push_back(CursorSlice(tail)); + tail.setMacrocontextPositionRecursive(dit); + + // remove text leading decimal point + docstring const align_d = tabular.column_info[c].decimal_point; + dit = separatorPos(&tail, align_d); + + pit_type const psize = tail.paragraphs().front().size(); + if (dit) { + tail.paragraphs().front().eraseChars(0, + dit.pos() < psize ? dit.pos() + 1 : psize, false); + Dimension dim1; tail.metrics(m, dim1); decimal_width = dim1.width(); } } - tabular.cell_info[r][c].decimal_hoffset = decimal_hoffset; + tabular.cell_info[r][c].decimal_hoffset = tm.width() - decimal_width; tabular.cell_info[r][c].decimal_width = decimal_width; // with LYX_VALIGN_BOTTOM the descent is relative to the last par @@ -3403,14 +3713,14 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const int const lastpardes = tm.last().second->descent() + TEXT_TO_INSET_OFFSET; int offset = 0; - switch (tabular.getVAlignment(cell)) { + switch (tabular.getVAlignment(cell)) { case Tabular::LYX_VALIGN_TOP: - break; + break; case Tabular::LYX_VALIGN_MIDDLE: - offset = -(dim.des - lastpardes)/2; - break; + offset = -(dim.des - lastpardes)/2; + break; case Tabular::LYX_VALIGN_BOTTOM: - offset = -(dim.des - lastpardes); + offset = -(dim.des - lastpardes); break; } tabular.cell_info[r][c].voffset = offset; @@ -3419,21 +3729,22 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const } int const top_space = tabular.row_info[r].top_space_default ? default_line_space : - tabular.row_info[r].top_space.inPixels(mi.base.textwidth); + tabular.row_info[r].top_space.inPixels(mi.base); tabular.setRowAscent(r, maxasc + ADD_TO_HEIGHT + top_space); int const bottom_space = tabular.row_info[r].bottom_space_default ? default_line_space : - tabular.row_info[r].bottom_space.inPixels(mi.base.textwidth); + tabular.row_info[r].bottom_space.inPixels(mi.base); tabular.setRowDescent(r, maxdes + ADD_TO_HEIGHT + bottom_space); } + tabular.updateColumnWidths(); - dim.asc = tabular.rowAscent(0); + dim.asc = tabular.rowAscent(0) - tabular.offsetVAlignment(); dim.des = tabular.height() - dim.asc; dim.wid = tabular.width() + 2 * ADD_TO_TABULAR_WIDTH; } -bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) +bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) const { if (&cur.inset() == this && cur.selection()) { @@ -3441,15 +3752,15 @@ bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) row_type rs, re; col_type cs, ce; getSelection(cur, rs, re, cs, ce); - + idx_type const cell = tabular.cellIndex(row, col); col_type const cspan = tabular.columnSpan(cell); row_type const rspan = tabular.rowSpan(cell); - if (col + cspan - 1 >= cs && col <= ce + if (col + cspan - 1 >= cs && col <= ce && row + rspan - 1 >= rs && row <= re) return true; - } else - if (col == tabular.cellColumn(cur.idx()) + } else + if (col == tabular.cellColumn(cur.idx()) && row == tabular.cellRow(cur.idx())) { CursorSlice const & beg = cur.selBegin(); CursorSlice const & end = cur.selEnd(); @@ -3466,69 +3777,65 @@ bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) void InsetTabular::draw(PainterInfo & pi, int x, int y) const { - x += scx_ + ADD_TO_TABULAR_WIDTH; + x += ADD_TO_TABULAR_WIDTH; BufferView * bv = pi.base.bv; Cursor & cur = pi.base.bv->cursor(); - resetPos(cur); - // FIXME: As the full background is painted in drawSelection(), + // FIXME: As the full background is painted in drawBackground(), // we have no choice but to do a full repaint for the Text cells. pi.full_repaint = true; bool const original_selection_state = pi.selected; idx_type idx = 0; - first_visible_cell = Tabular::npos; + + int yy = y + tabular.offsetVAlignment(); for (row_type r = 0; r < tabular.nrows(); ++r) { int nx = x; for (col_type c = 0; c < tabular.ncols(); ++c) { if (tabular.isPartOfMultiColumn(r, c)) continue; - + idx = tabular.cellIndex(r, c); - + if (tabular.isPartOfMultiRow(r, c)) { nx += tabular.cellWidth(idx); continue; } - if (first_visible_cell == Tabular::npos) - first_visible_cell = idx; - pi.selected |= isCellSelected(cur, r, c); int const cx = nx + tabular.textHOffset(idx); - int const cy = y + tabular.textVOffset(idx); + int const cy = yy + tabular.textVOffset(idx); // Cache the Inset position. bv->coordCache().insets().add(cell(idx).get(), cx, cy); cell(idx)->draw(pi, cx, cy); - drawCellLines(pi, nx, y, r, idx); + drawCellLines(pi, nx, yy, r, idx); nx += tabular.cellWidth(idx); pi.selected = original_selection_state; } if (r + 1 < tabular.nrows()) - y += tabular.rowDescent(r) + tabular.rowAscent(r + 1) + yy += tabular.rowDescent(r) + tabular.rowAscent(r + 1) + tabular.interRowSpace(r + 1); } } -void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const +void InsetTabular::drawBackground(PainterInfo & pi, int x, int y) const { - Cursor & cur = pi.base.bv->cursor(); - resetPos(cur); + x += ADD_TO_TABULAR_WIDTH; + y += tabular.offsetVAlignment() - tabular.rowAscent(0); + pi.pain.fillRectangle(x, y, tabular.width(), tabular.height(), + pi.backgroundColor(this)); +} - x += scx_ + ADD_TO_TABULAR_WIDTH; - // FIXME: it is wrong to completely paint the background - // if we want to do single row painting. +void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const +{ + Cursor & cur = pi.base.bv->cursor(); - // Paint background of current tabular - int const w = tabular.width(); - int const h = tabular.height(); - int yy = y - tabular.rowAscent(0); - pi.pain.fillRectangle(x, yy, w, h, pi.backgroundColor(this)); + x += ADD_TO_TABULAR_WIDTH; if (!cur.selection()) return; @@ -3555,7 +3862,7 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const } int const w = tabular.cellWidth(cell); int const h = tabular.cellHeight(cell); - int const yy = y - tabular.rowAscent(r); + int const yy = y - tabular.rowAscent(r) + tabular.offsetVAlignment(); if (isCellSelected(cur, r, c)) pi.pain.fillRectangle(xx, yy, w, h, Color_selection); xx += w; @@ -3565,11 +3872,14 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const + tabular.interRowSpace(r + 1); } - } else { - x += cellXPos(cur.idx()); - x += tabular.textHOffset(cur.idx()); - cell(cur.idx())->drawSelection(pi, x, 0 /* ignored */); } + // FIXME: This code has no effect because InsetTableCell does not handle + // drawSelection other than the trivial implementation in Inset. + //else { + // x += cellXPos(cur.idx()); + // x += tabular.textHOffset(cur.idx()); + // cell(cur.idx())->drawSelection(pi, x, 0 /* ignored */); + //} } @@ -3605,9 +3915,13 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y, // Right x -= tabular.interColumnSpace(cell); + col_type next_cell_col = col + 1; + while (next_cell_col < tabular.ncols() + && tabular.isMultiColumn(tabular.cellIndex(row, next_cell_col))) + next_cell_col++; drawline = tabular.rightLine(cell) - || (col + 1 < tabular.ncols() - && tabular.leftLine(tabular.cellIndex(row, col + 1))); + || (next_cell_col < tabular.ncols() + && tabular.leftLine(tabular.cellIndex(row, next_cell_col))); pi.pain.line(x + w, y, x + w, y + h, drawline ? linecolor : gridcolor, drawline ? Painter::line_solid : Painter::line_onoffdash); @@ -3618,7 +3932,6 @@ void InsetTabular::edit(Cursor & cur, bool front, EntryDirection) { //lyxerr << "InsetTabular::edit: " << this << endl; cur.finishUndo(); - cur.setSelection(false); cur.push(*this); if (front) { if (isRightToLeft(cur)) @@ -3637,7 +3950,6 @@ void InsetTabular::edit(Cursor & cur, bool front, EntryDirection) } cur.setCurrentFont(); // FIXME: this accesses the position cache before it is initialized - //resetPos(cur); //cur.bv().fitCursor(); } @@ -3647,8 +3959,12 @@ void InsetTabular::updateBuffer(ParIterator const & it, UpdateType utype) // In a longtable, tell captions what the current float is Counters & cnts = buffer().masterBuffer()->params().documentClass().counters(); string const saveflt = cnts.current_float(); - if (tabular.is_long_tabular) + if (tabular.is_long_tabular) { cnts.current_float("table"); + // in longtables, we only step the counter once + cnts.step(from_ascii("table"), utype); + cnts.isLongtable(true); + } ParIterator it2 = it; it2.forwardPos(); @@ -3657,18 +3973,44 @@ void InsetTabular::updateBuffer(ParIterator const & it, UpdateType utype) buffer().updateBuffer(it2, utype); //reset afterwards - if (tabular.is_long_tabular) + if (tabular.is_long_tabular) { cnts.current_float(saveflt); + cnts.isLongtable(false); + } } -void InsetTabular::addToToc(DocIterator const & cpit) +void InsetTabular::addToToc(DocIterator const & cpit, bool output_active, + UpdateType utype) const { DocIterator dit = cpit; dit.forwardPos(); size_t const end = dit.nargs(); for ( ; dit.idx() < end; dit.top().forwardIdx()) - cell(dit.idx())->addToToc(dit); + cell(dit.idx())->addToToc(dit, output_active, utype); +} + + +bool InsetTabular::hitSelectRow(BufferView const & bv, int x) const +{ + int const x0 = xo(bv) + ADD_TO_TABULAR_WIDTH; + return x < x0 || x > x0 + tabular.width(); +} + + +bool InsetTabular::hitSelectColumn(BufferView const & bv, int y) const +{ + int const y0 = yo(bv) - tabular.rowAscent(0) + tabular.offsetVAlignment(); + // FIXME: using ADD_TO_TABULAR_WIDTH is not really correct since + // there is no margin added vertically to tabular insets. + // However, it works for now. + return y < y0 + ADD_TO_TABULAR_WIDTH || y > y0 + tabular.height() - ADD_TO_TABULAR_WIDTH; +} + + +bool InsetTabular::clickable(BufferView const & bv, int x, int y) const +{ + return hitSelectRow(bv, x) || hitSelectColumn(bv, y); } @@ -3680,45 +4022,46 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) Cursor & bvcur = cur.bv().cursor(); FuncCode const act = cmd.action(); - + switch (act) { case LFUN_MOUSE_PRESS: { //lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl; // select row - if (cmd.x() < xo(cur.bv()) + ADD_TO_TABULAR_WIDTH - || cmd.x() > xo(cur.bv()) + tabular.width()) { + if (hitSelectRow(cur.bv(), cmd.x())) { row_type r = rowFromY(cur, cmd.y()); cur.idx() = tabular.getFirstCellInRow(r); + cur.pit() = 0; cur.pos() = 0; cur.resetAnchor(); cur.idx() = tabular.getLastCellInRow(r); + cur.pit() = cur.lastpit(); cur.pos() = cur.lastpos(); - cur.setSelection(true); - bvcur = cur; + cur.selection(true); + bvcur = cur; rowselect_ = true; break; } // select column - int const y0 = yo(cur.bv()) - tabular.rowAscent(0); - if (cmd.y() < y0 + ADD_TO_TABULAR_WIDTH - || cmd.y() > y0 + tabular.height()) { + if (hitSelectColumn(cur.bv(), cmd.y())) { col_type c = columnFromX(cur, cmd.x()); cur.idx() = tabular.cellIndex(0, c); + cur.pit() = 0; cur.pos() = 0; cur.resetAnchor(); cur.idx() = tabular.cellIndex(tabular.nrows() - 1, c); + cur.pit() = cur.lastpit(); cur.pos() = cur.lastpos(); - cur.setSelection(true); - bvcur = cur; + cur.selection(true); + bvcur = cur; colselect_ = true; break; } // do not reset cursor/selection if we have selected // some cells (bug 2715). if (cmd.button() == mouse_button::button3 - && &bvcur.selBegin().inset() == this - && bvcur.selIsMultiCell()) + && &bvcur.selBegin().inset() == this + && bvcur.selIsMultiCell()) ; else // Let InsetTableCell do it @@ -3742,7 +4085,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) cur.pit() = 0; cur.pos() = 0; bvcur.setCursor(cur); - bvcur.setSelection(true); + bvcur.selection(true); break; } // select (additional) column @@ -3754,7 +4097,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) cur.pit() = 0; cur.pos() = 0; bvcur.setCursor(cur); - bvcur.setSelection(true); + bvcur.selection(true); break; } // only update if selection changes @@ -3763,7 +4106,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) cur.noScreenUpdate(); setCursorFromCoordinates(cur, cmd.x(), cmd.y()); bvcur.setCursor(cur); - bvcur.setSelection(true); + bvcur.selection(true); // if this is a multicell selection, we just set the cursor to // the beginning of the cell's text. if (bvcur.selIsMultiCell()) { @@ -3780,12 +4123,12 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CELL_BACKWARD: movePrevCell(cur); - cur.setSelection(false); + cur.selection(false); break; case LFUN_CELL_FORWARD: moveNextCell(cur); - cur.setSelection(false); + cur.selection(false); break; case LFUN_CHAR_FORWARD_SELECT: @@ -3795,7 +4138,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CHAR_RIGHT_SELECT: case LFUN_CHAR_RIGHT: case LFUN_CHAR_LEFT_SELECT: - case LFUN_CHAR_LEFT: + case LFUN_CHAR_LEFT: case LFUN_WORD_FORWARD: case LFUN_WORD_FORWARD_SELECT: case LFUN_WORD_BACKWARD: @@ -3804,14 +4147,14 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_RIGHT_SELECT: case LFUN_WORD_LEFT: case LFUN_WORD_LEFT_SELECT: { - // determine whether we move to next or previous cell, where to enter + // determine whether we move to next or previous cell, where to enter // the new cell from, and which command to "finish" (i.e., exit the // inset) with: bool next_cell; EntryDirection entry_from = ENTRY_DIRECTION_IGNORE; FuncCode finish_lfun; - if (act == LFUN_CHAR_FORWARD + if (act == LFUN_CHAR_FORWARD || act == LFUN_CHAR_FORWARD_SELECT || act == LFUN_WORD_FORWARD || act == LFUN_WORD_FORWARD_SELECT) { @@ -3825,7 +4168,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) next_cell = false; finish_lfun = LFUN_FINISHED_BACKWARD; } - // LEFT or RIGHT commands --- the interpretation will depend on the + // LEFT or RIGHT commands --- the interpretation will depend on the // table's direction. else { bool const right = act == LFUN_CHAR_RIGHT @@ -3833,14 +4176,14 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) || act == LFUN_WORD_RIGHT || act == LFUN_WORD_RIGHT_SELECT; next_cell = isRightToLeft(cur) != right; - + if (lyxrc.visual_cursor) entry_from = right ? ENTRY_DIRECTION_LEFT:ENTRY_DIRECTION_RIGHT; finish_lfun = right ? LFUN_FINISHED_RIGHT : LFUN_FINISHED_LEFT; } - bool const select = act == LFUN_CHAR_FORWARD_SELECT + bool const select = act == LFUN_CHAR_FORWARD_SELECT || act == LFUN_CHAR_BACKWARD_SELECT || act == LFUN_CHAR_RIGHT_SELECT || act == LFUN_CHAR_LEFT_SELECT @@ -3849,15 +4192,15 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) || act == LFUN_WORD_BACKWARD_SELECT || act == LFUN_WORD_LEFT_SELECT; - // If we have a multicell selection or we're + // If we have a multicell selection or we're // not doing some LFUN_*_SELECT thing anyway... if (!cur.selIsMultiCell() || !select) { col_type const c = tabular.cellColumn(cur.idx()); row_type const r = tabular.cellRow(cur.idx()); - // Are we trying to select the whole cell and is the whole cell + // Are we trying to select the whole cell and is the whole cell // not yet selected? bool const select_whole = select && !isCellSelected(cur, r, c) && - ((next_cell && cur.pit() == cur.lastpit() + ((next_cell && cur.pit() == cur.lastpit() && cur.pos() == cur.lastpos()) || (!next_cell && cur.pit() == 0 && cur.pos() == 0)); @@ -3871,10 +4214,11 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) if (select_whole && !empty_cell){ getText(cur.idx())->selectAll(cur); cur.dispatched(); + cur.screenUpdateFlags(Update::Force | Update::FitCursor); break; } - // FIXME: When we support the selection of an empty cell, remove + // FIXME: When we support the selection of an empty cell, remove // the !empty_cell from this condition. For now we jump to the next // cell if the current cell is empty. if (cur.result().dispatched() && !empty_cell) @@ -3891,10 +4235,13 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) else movePrevCell(cur, entry_from); // if we're exiting the table, call the appropriate FINISHED lfun - if (sl == cur.top()) + if (sl == cur.top()) { cmd = FuncRequest(finish_lfun); - else + cur.undispatched(); + } else cur.dispatched(); + + cur.screenUpdateFlags(Update::Force | Update::FitCursor); break; } @@ -3903,7 +4250,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_DOWN: if (!(cur.selection() && cur.selIsMultiCell())) cell(cur.idx())->dispatch(cur, cmd); - + cur.dispatched(); // override the cell's decision if (sl == cur.top()) { // if our Text didn't do anything to the cursor @@ -3911,11 +4258,15 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) // setting also the right targetX. cur.selHandle(act == LFUN_DOWN_SELECT); if (tabular.cellRow(cur.idx()) != tabular.nrows() - 1) { + int const xtarget = cur.targetX(); + // WARNING: Once cur.idx() has been reset, the cursor is in + // an inconsistent state until pos() has been set. Be careful + // what you do with it! cur.idx() = tabular.cellBelow(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()); + cur.pos() = tm.x2pos(cur.pit(), 0, xtarget); cur.setCurrentFont(); } } @@ -3929,8 +4280,10 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) cur.pit() = cur.lastpit(); cur.pos() = cur.lastpos(); cur.setCurrentFont(); + cur.screenUpdateFlags(Update::Force | Update::FitCursor); return; } + cur.screenUpdateFlags(Update::Force | Update::FitCursor); break; case LFUN_UP_SELECT: @@ -3944,13 +4297,17 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) // setting also the right targetX. cur.selHandle(act == LFUN_UP_SELECT); if (tabular.cellRow(cur.idx()) != 0) { + int const xtarget = cur.targetX(); + // WARNING: Once cur.idx() has been reset, the cursor is in + // an inconsistent state until pos() has been set. Be careful + // what you do with it! cur.idx() = tabular.cellAbove(cur.idx()); cur.pit() = cur.lastpit(); 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()); + cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, xtarget); cur.setCurrentFont(); } } @@ -3962,54 +4319,28 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) cur.pit() = 0; cur.pos() = cur.lastpos(); cur.setCurrentFont(); + cur.screenUpdateFlags(Update::Force | Update::FitCursor); return; } + cur.screenUpdateFlags(Update::Force | Update::FitCursor); break; -// case LFUN_SCREEN_DOWN: { -// //if (hasSelection()) -// // cur.selection() = false; -// 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, true); -// cur.idx() = tabular.cellBelow(first_visible_cell) + col; -// } else { -// cur.idx() = tabular.getFirstCellInRow(tabular.rows() - 1) + col; -// } -// cur.par() = 0; -// cur.pos() = 0; -// break; -// } -// -// case LFUN_SCREEN_UP: { -// //if (hasSelection()) -// // cur.selection() = false; -// 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, true); -// if (yo() > 0) -// cur.idx() = col; -// else -// cur.idx() = tabular.cellBelow(first_visible_cell) + col; -// } else { -// cur.idx() = col; -// } -// cur.par() = cur.lastpar(); -// cur.pos() = cur.lastpos(); -// break; -// } - case LFUN_LAYOUT_TABULAR: cur.bv().showDialog("tabular"); break; case LFUN_INSET_MODIFY: - if (!tabularFeatures(cur, to_utf8(cmd.argument()))) + // we come from the dialog + if (cmd.getArg(0) == "tabular") + tabularFeatures(cur, cmd.getLongArg(1)); + else cur.undispatched(); break; + case LFUN_TABULAR_FEATURE: + tabularFeatures(cur, to_utf8(cmd.argument())); + break; + // insert file functions case LFUN_FILE_INSERT_PLAINTEXT_PARA: case LFUN_FILE_INSERT_PLAINTEXT: @@ -4019,7 +4350,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) FileName(to_utf8(cmd.argument()))); if (tmpstr.empty()) break; - cur.recordUndoInset(INSERT_UNDO); + cur.recordUndoInset(); if (insertPlaintextString(cur.bv(), tmpstr, false)) { // content has been replaced, // so cursor might be invalid @@ -4034,7 +4365,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CUT: if (cur.selIsMultiCell()) { if (copySelection(cur)) { - cur.recordUndoInset(DELETE_UNDO); + cur.recordUndoInset(); cutSelection(cur); } } else @@ -4043,16 +4374,24 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_SELF_INSERT: if (cur.selIsMultiCell()) { - cur.recordUndoInset(DELETE_UNDO); + cur.recordUndoInset(); cutSelection(cur); - } - cell(cur.idx())->dispatch(cur, cmd); + BufferView * bv = &cur.bv(); + docstring::const_iterator cit = cmd.argument().begin(); + docstring::const_iterator const end = cmd.argument().end(); + for (; cit != end; ++cit) + bv->translateAndInsert(*cit, getText(cur.idx()), cur); + + cur.resetAnchor(); + bv->bookmarkEditPosition(); + } else + cell(cur.idx())->dispatch(cur, cmd); break; case LFUN_CHAR_DELETE_BACKWARD: case LFUN_CHAR_DELETE_FORWARD: if (cur.selIsMultiCell()) { - cur.recordUndoInset(DELETE_UNDO); + cur.recordUndoInset(); cutSelection(cur); } else cell(cur.idx())->dispatch(cur, cmd); @@ -4071,14 +4410,14 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CLIPBOARD_PASTE: case LFUN_PRIMARY_SELECTION_PASTE: { docstring const clip = (act == LFUN_CLIPBOARD_PASTE) ? - theClipboard().getAsText() : + theClipboard().getAsText(Clipboard::PlainTextType) : theSelection().get(); if (clip.empty()) break; // 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); + cur.recordUndoInset(); if (insertPlaintextString(cur.bv(), clip, false)) { // content has been replaced, // so cursor might be invalid @@ -4099,9 +4438,8 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) cell(cur.idx())->dispatch(cur, cmd); break; } - if (theClipboard().isInternal() || - (!theClipboard().hasInternal() && theClipboard().hasLyXContents())) { - cur.recordUndoInset(INSERT_UNDO); + if (theClipboard().isInternal()) { + cur.recordUndoInset(); pasteClipboard(cur); } break; @@ -4120,9 +4458,11 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_FONT_SIZE: case LFUN_FONT_UNDERLINE: case LFUN_FONT_STRIKEOUT: - case LFUN_FONT_UULINE: - case LFUN_FONT_UWAVE: + case LFUN_FONT_UNDERUNDERLINE: + case LFUN_FONT_UNDERWAVE: case LFUN_LANGUAGE: + case LFUN_PARAGRAPH_PARAMS_APPLY: + case LFUN_PARAGRAPH_PARAMS: case LFUN_WORD_CAPITALIZE: case LFUN_WORD_UPCASE: case LFUN_WORD_LOWCASE: @@ -4166,18 +4506,10 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) } -// function sets an object as defined in func_status.h: -// states OK, Unknown, Disabled, On, Off. -bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, - FuncStatus & status) const +bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s, + string const & argument, FuncStatus & status) const { - switch (cmd.action()) { - case LFUN_INSET_MODIFY: { - if (&cur.inset() != this || cmd.getArg(0) != "tabular") - break; - string const s = cmd.getArg(1); - // FIXME: We only check for the very first argument... int action = Tabular::LAST_ACTION; int i = 0; for (; tabularFeature[i].action != Tabular::LAST_ACTION; ++i) { @@ -4192,8 +4524,6 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, return true; } - string const argument = cmd.getLongArg(2); - row_type sel_row_start = 0; row_type sel_row_end = 0; col_type sel_col_start = 0; @@ -4220,6 +4550,61 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, status.clear(); return true; + case Tabular::SET_TABULAR_WIDTH: + status.setEnabled(!tabular.rotate && !tabular.is_long_tabular + && tabular.tabular_valignment == Tabular::LYX_VALIGN_MIDDLE); + break; + + case Tabular::MOVE_COLUMN_RIGHT: + case Tabular::MOVE_COLUMN_LEFT: + case Tabular::MOVE_ROW_DOWN: + case Tabular::MOVE_ROW_UP: { + if (cur.selection()) { + status.message(_("Selections not supported.")); + status.setEnabled(false); + break; + } + + if ((action == Tabular::MOVE_COLUMN_RIGHT && + tabular.ncols() == tabular.cellColumn(cur.idx()) + 1) || + (action == Tabular::MOVE_COLUMN_LEFT && + tabular.cellColumn(cur.idx()) == 0) || + (action == Tabular::MOVE_ROW_DOWN && + tabular.nrows() == tabular.cellRow(cur.idx()) + 1) || + (action == Tabular::MOVE_ROW_UP && + tabular.cellRow(cur.idx()) == 0)) { + status.setEnabled(false); + break; + } + + if (action == Tabular::MOVE_COLUMN_RIGHT || + action == Tabular::MOVE_COLUMN_LEFT) { + if (tabular.hasMultiColumn(tabular.cellColumn(cur.idx())) || + tabular.hasMultiColumn(tabular.cellColumn(cur.idx()) + + (action == Tabular::MOVE_COLUMN_RIGHT ? 1 : -1))) { + status.message(_("Multi-column in current or" + " destination column.")); + status.setEnabled(false); + break; + } + } + + if (action == Tabular::MOVE_ROW_DOWN || + action == Tabular::MOVE_ROW_UP) { + if (tabular.hasMultiRow(tabular.cellRow(cur.idx())) || + tabular.hasMultiRow(tabular.cellRow(cur.idx()) + + (action == Tabular::MOVE_ROW_DOWN ? 1 : -1))) { + status.message(_("Multi-row in current or" + " destination row.")); + status.setEnabled(false); + break; + } + } + + status.setEnabled(true); + break; + } + case Tabular::SET_DECIMAL_POINT: status.setEnabled( tabular.getAlignment(cur.idx()) == LYX_ALIGN_DECIMAL); @@ -4253,9 +4638,13 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, case Tabular::SET_LINE_TOP: case Tabular::SET_LINE_BOTTOM: + status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx()))); + break; + case Tabular::SET_LINE_LEFT: case Tabular::SET_LINE_RIGHT: - status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx()))); + status.setEnabled(!tabular.use_booktabs + && !tabular.ltCaption(tabular.cellRow(cur.idx()))); break; case Tabular::TOGGLE_LINE_TOP: @@ -4269,32 +4658,39 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, break; case Tabular::TOGGLE_LINE_LEFT: - status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx()))); + status.setEnabled(!tabular.use_booktabs + && !tabular.ltCaption(tabular.cellRow(cur.idx()))); status.setOnOff(tabular.leftLine(cur.idx())); break; case Tabular::TOGGLE_LINE_RIGHT: - status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx()))); + status.setEnabled(!tabular.use_booktabs + && !tabular.ltCaption(tabular.cellRow(cur.idx()))); status.setOnOff(tabular.rightLine(cur.idx())); break; + // multirow cells only inherit the alignment of the column if the column has + // no width, otherwise they are left-aligned + // therefore allow always left but right and center only if there is no width case Tabular::M_ALIGN_LEFT: flag = false; case Tabular::ALIGN_LEFT: - status.setEnabled(!tabular.isMultiRow(cur.idx())); status.setOnOff(tabular.getAlignment(cur.idx(), flag) == LYX_ALIGN_LEFT); break; case Tabular::M_ALIGN_RIGHT: flag = false; case Tabular::ALIGN_RIGHT: - status.setEnabled(!tabular.isMultiRow(cur.idx())); + status.setEnabled(!(tabular.isMultiRow(cur.idx()) + && !tabular.getPWidth(cur.idx()).zero())); status.setOnOff(tabular.getAlignment(cur.idx(), flag) == LYX_ALIGN_RIGHT); break; case Tabular::M_ALIGN_CENTER: flag = false; case Tabular::ALIGN_CENTER: + status.setEnabled(!(tabular.isMultiRow(cur.idx()) + && !tabular.getPWidth(cur.idx()).zero())); status.setOnOff(tabular.getAlignment(cur.idx(), flag) == LYX_ALIGN_CENTER); break; @@ -4305,7 +4701,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, break; case Tabular::ALIGN_DECIMAL: - status.setEnabled(!tabular.isMultiRow(cur.idx()) + status.setEnabled(!tabular.isMultiRow(cur.idx()) && !tabular.isMultiColumn(cur.idx())); status.setOnOff(tabular.getAlignment(cur.idx(), true) == LYX_ALIGN_DECIMAL); break; @@ -4338,6 +4734,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, break; case Tabular::SET_LONGTABULAR: + case Tabular::TOGGLE_LONGTABULAR: // setting as longtable is not allowed when table is inside a float if (cur.innerInsetOfType(FLOAT_CODE) != 0 || cur.innerInsetOfType(WRAP_CODE) != 0) @@ -4353,37 +4750,40 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, case Tabular::TOGGLE_ROTATE_TABULAR: case Tabular::SET_ROTATE_TABULAR: - status.setOnOff(tabular.rotate); + status.setOnOff(tabular.rotate != 0); break; case Tabular::TABULAR_VALIGN_TOP: - status.setOnOff(tabular.tabular_valignment + status.setEnabled(tabular.tabular_width.zero()); + status.setOnOff(tabular.tabular_valignment == Tabular::LYX_VALIGN_TOP); break; case Tabular::TABULAR_VALIGN_MIDDLE: - status.setOnOff(tabular.tabular_valignment + status.setEnabled(tabular.tabular_width.zero()); + status.setOnOff(tabular.tabular_valignment == Tabular::LYX_VALIGN_MIDDLE); break; case Tabular::TABULAR_VALIGN_BOTTOM: - status.setOnOff(tabular.tabular_valignment + status.setEnabled(tabular.tabular_width.zero()); + status.setOnOff(tabular.tabular_valignment == Tabular::LYX_VALIGN_BOTTOM); break; case Tabular::LONGTABULAR_ALIGN_LEFT: - status.setOnOff(tabular.longtabular_alignment + status.setOnOff(tabular.longtabular_alignment == Tabular::LYX_LONGTABULAR_ALIGN_LEFT); break; case Tabular::LONGTABULAR_ALIGN_CENTER: - status.setOnOff(tabular.longtabular_alignment + status.setOnOff(tabular.longtabular_alignment == Tabular::LYX_LONGTABULAR_ALIGN_CENTER); break; case Tabular::LONGTABULAR_ALIGN_RIGHT: - status.setOnOff(tabular.longtabular_alignment + status.setOnOff(tabular.longtabular_alignment == Tabular::LYX_LONGTABULAR_ALIGN_RIGHT); break; case Tabular::UNSET_ROTATE_TABULAR: - status.setOnOff(!tabular.rotate); + status.setOnOff(tabular.rotate == 0); break; case Tabular::TOGGLE_ROTATE_CELL: @@ -4402,67 +4802,88 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, break; // every row can only be one thing: - // either a footer or header or caption + // either a footer or header case Tabular::SET_LTFIRSTHEAD: - status.setEnabled(sel_row_start == sel_row_end - && !tabular.ltCaption(sel_row_start)); + status.setEnabled(sel_row_start == sel_row_end); status.setOnOff(tabular.getRowOfLTFirstHead(sel_row_start, dummyltt)); break; case Tabular::UNSET_LTFIRSTHEAD: + status.setEnabled(sel_row_start == sel_row_end); status.setOnOff(!tabular.getRowOfLTFirstHead(sel_row_start, dummyltt)); break; case Tabular::SET_LTHEAD: - status.setEnabled(sel_row_start == sel_row_end - && !tabular.ltCaption(sel_row_start)); + status.setEnabled(sel_row_start == sel_row_end); status.setOnOff(tabular.getRowOfLTHead(sel_row_start, dummyltt)); break; case Tabular::UNSET_LTHEAD: + status.setEnabled(sel_row_start == sel_row_end); status.setOnOff(!tabular.getRowOfLTHead(sel_row_start, dummyltt)); break; case Tabular::SET_LTFOOT: - status.setEnabled(sel_row_start == sel_row_end - && !tabular.ltCaption(sel_row_start)); + status.setEnabled(sel_row_start == sel_row_end); status.setOnOff(tabular.getRowOfLTFoot(sel_row_start, dummyltt)); break; case Tabular::UNSET_LTFOOT: + status.setEnabled(sel_row_start == sel_row_end); status.setOnOff(!tabular.getRowOfLTFoot(sel_row_start, dummyltt)); break; case Tabular::SET_LTLASTFOOT: - status.setEnabled(sel_row_start == sel_row_end - && !tabular.ltCaption(sel_row_start)); + status.setEnabled(sel_row_start == sel_row_end); status.setOnOff(tabular.getRowOfLTLastFoot(sel_row_start, dummyltt)); break; case Tabular::UNSET_LTLASTFOOT: + status.setEnabled(sel_row_start == sel_row_end); status.setOnOff(!tabular.getRowOfLTLastFoot(sel_row_start, dummyltt)); break; case Tabular::SET_LTNEWPAGE: status.setOnOff(tabular.getLTNewPage(sel_row_start)); break; + case Tabular::UNSET_LTNEWPAGE: + status.setOnOff(!tabular.getLTNewPage(sel_row_start)); + break; - // only one row can be the caption + // only one row in head/firsthead/foot/lasthead can be the caption // and a multirow cannot be set as caption case Tabular::SET_LTCAPTION: - case Tabular::UNSET_LTCAPTION: - case Tabular::TOGGLE_LTCAPTION: status.setEnabled(sel_row_start == sel_row_end - && !tabular.getRowOfLTFirstHead(sel_row_start, dummyltt) - && !tabular.getRowOfLTHead(sel_row_start, dummyltt) - && !tabular.getRowOfLTFoot(sel_row_start, dummyltt) - && !tabular.getRowOfLTLastFoot(sel_row_start, dummyltt) - && (!tabular.haveLTCaption() - || tabular.ltCaption(sel_row_start)) + && (!tabular.getRowOfLTFirstHead(sel_row_start, dummyltt) + || !tabular.haveLTCaption(Tabular::CAPTION_FIRSTHEAD)) + && (!tabular.getRowOfLTHead(sel_row_start, dummyltt) + || !tabular.haveLTCaption(Tabular::CAPTION_HEAD)) + && (!tabular.getRowOfLTFoot(sel_row_start, dummyltt) + || !tabular.haveLTCaption(Tabular::CAPTION_FOOT)) + && (!tabular.getRowOfLTLastFoot(sel_row_start, dummyltt) + || !tabular.haveLTCaption(Tabular::CAPTION_LASTFOOT)) && !tabular.isMultiRow(sel_row_start)); status.setOnOff(tabular.ltCaption(sel_row_start)); break; + case Tabular::UNSET_LTCAPTION: + status.setEnabled(sel_row_start == sel_row_end && tabular.ltCaption(sel_row_start)); + break; + + case Tabular::TOGGLE_LTCAPTION: + status.setEnabled(sel_row_start == sel_row_end && (tabular.ltCaption(sel_row_start) + || ((!tabular.getRowOfLTFirstHead(sel_row_start, dummyltt) + || !tabular.haveLTCaption(Tabular::CAPTION_FIRSTHEAD)) + && (!tabular.getRowOfLTHead(sel_row_start, dummyltt) + || !tabular.haveLTCaption(Tabular::CAPTION_HEAD)) + && (!tabular.getRowOfLTFoot(sel_row_start, dummyltt) + || !tabular.haveLTCaption(Tabular::CAPTION_FOOT)) + && (!tabular.getRowOfLTLastFoot(sel_row_start, dummyltt) + || !tabular.haveLTCaption(Tabular::CAPTION_LASTFOOT))))); + status.setOnOff(tabular.ltCaption(sel_row_start)); + break; + + case Tabular::TOGGLE_BOOKTABS: case Tabular::SET_BOOKTABS: status.setOnOff(tabular.use_booktabs); break; @@ -4477,6 +4898,70 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, break; } return true; +} + + +// function sets an object as defined in FuncStatus.h: +// states OK, Unknown, Disabled, On, Off. +bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, + FuncStatus & status) const +{ + switch (cmd.action()) { + case LFUN_INSET_MODIFY: + if (cmd.getArg(0) != "tabular") + break; + if (cmd.getArg(1) == "for-dialog") { + // The dialog is asking the status of a command + if (&cur.inset() != this) + break; + string action = cmd.getArg(2); + string arg = cmd.getLongArg(3); + return getFeatureStatus(cur, action, arg, status); + } else { + // We always enable the lfun if it is coming from the dialog + // because the dialog makes sure all the settings are valid, + // even though the first argument might not be valid now. + status.setEnabled(true); + return true; + } + + case LFUN_TABULAR_FEATURE: { + if (&cur.inset() != this) + break; + string action = cmd.getArg(0); + string arg = cmd.getLongArg(1); + return getFeatureStatus(cur, action, arg, status); + } + + case LFUN_CAPTION_INSERT: { + // caption is only allowed in caption cell of longtable + if (!tabular.ltCaption(tabular.cellRow(cur.idx()))) { + status.setEnabled(false); + return true; + } + // only standard caption is allowed + string arg = cmd.getArg(0); + if (!arg.empty() && arg != "Standard") { + status.setEnabled(false); + return true; + } + // check if there is already a caption + bool have_caption = false; + InsetTableCell itc = InsetTableCell(*tabular.cellInset(cur.idx())); + ParagraphList::const_iterator pit = itc.paragraphs().begin(); + ParagraphList::const_iterator pend = itc.paragraphs().end(); + for (; pit != pend; ++pit) { + InsetList::const_iterator it = pit->insetList().begin(); + InsetList::const_iterator end = pit->insetList().end(); + for (; it != end; ++it) { + if (it->inset->lyxCode() == CAPTION_CODE) { + have_caption = true; + break; + } + } + } + status.setEnabled(!have_caption); + return true; } // These are only enabled inside tabular @@ -4513,8 +4998,14 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, } // disable in non-fixed-width cells - case LFUN_NEWLINE_INSERT: - case LFUN_BREAK_PARAGRAPH: { + case LFUN_PARAGRAPH_BREAK: + // multirow does not allow paragraph breaks + if (tabular.isMultiRow(cur.idx())) { + status.setEnabled(false); + return true; + } + // Fall back + case LFUN_NEWLINE_INSERT: { if (tabular.getPWidth(cur.idx()).zero()) { status.setEnabled(false); return true; @@ -4534,7 +5025,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, getSelection(cur, rs, re, cs, ce); if (paste_tabular && paste_tabular->ncols() == ce - cs + 1 && paste_tabular->nrows() == re - rs + 1) - status.setEnabled(true); + status.setEnabled(true); else { status.setEnabled(false); status.message(_("Selection size should match clipboard content.")); @@ -4575,17 +5066,18 @@ Inset::DisplayType InsetTabular::display() const } -int InsetTabular::latex(odocstream & os, OutputParams const & runparams) const +void InsetTabular::latex(otexstream & os, OutputParams const & runparams) const { - return tabular.latex(os, runparams); + tabular.latex(os, runparams); } -int InsetTabular::plaintext(odocstream & os, OutputParams const & runparams) const +int InsetTabular::plaintext(odocstringstream & os, + OutputParams const & runparams, size_t max_length) const { os << '\n'; // output table on a new line int const dp = runparams.linelen > 0 ? runparams.depth : 0; - tabular.plaintext(os, runparams, dp, false, 0); + tabular.plaintext(os, runparams, dp, false, 0, max_length); return PLAINTEXT_NEWLINE; } @@ -4619,27 +5111,14 @@ int InsetTabular::docbook(odocstream & os, OutputParams const & runparams) const docstring InsetTabular::xhtml(XHTMLStream & xs, OutputParams const & rp) const { - // FIXME XHTML - // It'd be better to be able to get this from an InsetLayout, but at present - // InsetLayouts do not seem really to work for things that aren't InsetTexts. - xs << html::StartTag("table"); - docstring ret = tabular.xhtml(xs, rp); - xs << html::EndTag("table"); - return ret; + return tabular.xhtml(xs, rp); } void InsetTabular::validate(LaTeXFeatures & features) const { tabular.validate(features); - // FIXME XHTML - // It'd be better to be able to get this from an InsetLayout, but at present - // InsetLayouts do not seem really to work for things that aren't InsetTexts. - if (features.runparams().flavor == OutputParams::HTML) - features.addPreambleSnippet(""); + features.useInsetLayout(getLayout()); } @@ -4660,23 +5139,15 @@ void InsetTabular::cursorPos(BufferView const & bv, { cell(sl.idx())->cursorPos(bv, sl, boundary, x, y); - int const row = tabular.cellRow(sl.idx()); - int const col = tabular.cellColumn(sl.idx()); - // y offset correction - for (int r = 0; r < row; ++r) - y += tabular.rowDescent(r) + tabular.rowAscent(r + 1) - + tabular.interRowSpace(r + 1); - + y += cellYPos(sl.idx()); y += tabular.textVOffset(sl.idx()); + y += tabular.offsetVAlignment(); // x offset correction - for (int c = 0; c < col; ++c) - x += tabular.column_info[c].width; - + x += cellXPos(sl.idx()); x += tabular.textHOffset(sl.idx()); x += ADD_TO_TABULAR_WIDTH; - x += scx_; } @@ -4690,7 +5161,7 @@ int InsetTabular::dist(BufferView & bv, idx_type const cell, int x, int y) const int const xend = xbeg + tabular.cellWidth(cell); row_type const row = tabular.cellRow(cell); int const ybeg = o.y_ - tabular.rowAscent(row) - - tabular.interRowSpace(row); + - tabular.interRowSpace(row) - tabular.textVOffset(cell); int const yend = ybeg + tabular.cellHeight(cell); if (x < xbeg) @@ -4714,10 +5185,9 @@ int InsetTabular::dist(BufferView & bv, idx_type const cell, int x, int y) const Inset * InsetTabular::editXY(Cursor & cur, int x, int y) { //lyxerr << "InsetTabular::editXY: " << this << endl; - cur.setSelection(false); + cur.selection(false); cur.push(*this); cur.idx() = getNearestCell(cur.bv(), x, y); - resetPos(cur); return cur.bv().textMetrics(&cell(cur.idx())->text()).editXY(cur, x, y); } @@ -4746,47 +5216,27 @@ InsetTabular::idx_type InsetTabular::getNearestCell(BufferView & bv, int x, int } +int InsetTabular::cellYPos(idx_type const cell) const +{ + row_type row = tabular.cellRow(cell); + int ly = 0; + for (row_type r = 0; r < row; ++r) + ly += tabular.rowDescent(r) + tabular.rowAscent(r + 1) + + tabular.interRowSpace(r + 1); + return ly; +} + + int InsetTabular::cellXPos(idx_type const cell) const { col_type col = tabular.cellColumn(cell); int lx = 0; for (col_type c = 0; c < col; ++c) lx += tabular.column_info[c].width; - return lx; } -void InsetTabular::resetPos(Cursor & cur) const -{ - BufferView & bv = cur.bv(); - int const maxwidth = bv.workWidth(); - - int const scx_old = scx_; - int const i = cur.find(this); - if (i == -1) { - scx_ = 0; - } else { - int const X1 = 0; - int const X2 = maxwidth; - int const offset = ADD_TO_TABULAR_WIDTH + 2; - int const x1 = xo(cur.bv()) + cellXPos(cur[i].idx()) + offset; - int const x2 = x1 + tabular.cellWidth(cur[i].idx()); - - if (x1 < X1) - scx_ = X1 + 20 - x1; - else if (x2 > X2) - scx_ = X2 - 20 - x2; - else - scx_ = 0; - } - - // only update if offset changed - if (scx_ != scx_old) - cur.screenUpdateFlags(Update::Force | Update::FitCursor); -} - - void InsetTabular::moveNextCell(Cursor & cur, EntryDirection entry_from) { row_type const row = tabular.cellRow(cur.idx()); @@ -4821,7 +5271,6 @@ void InsetTabular::moveNextCell(Cursor & cur, EntryDirection entry_from) if (cur.selIsMultiCell()) { cur.pit() = cur.lastpit(); cur.pos() = cur.lastpos(); - resetPos(cur); return; } @@ -4829,7 +5278,7 @@ void InsetTabular::moveNextCell(Cursor & cur, EntryDirection entry_from) cur.pos() = 0; // in visual mode, place cursor at extreme left or right - + switch(entry_from) { case ENTRY_DIRECTION_RIGHT: @@ -4844,7 +5293,6 @@ void InsetTabular::moveNextCell(Cursor & cur, EntryDirection entry_from) } cur.setCurrentFont(); - resetPos(cur); } @@ -4879,7 +5327,6 @@ void InsetTabular::movePrevCell(Cursor & cur, EntryDirection entry_from) if (cur.selIsMultiCell()) { cur.pit() = cur.lastpit(); cur.pos() = cur.lastpos(); - resetPos(cur); return; } @@ -4887,7 +5334,7 @@ void InsetTabular::movePrevCell(Cursor & cur, EntryDirection entry_from) cur.pos() = cur.lastpos(); // in visual mode, place cursor at extreme left or right - + switch(entry_from) { case ENTRY_DIRECTION_RIGHT: @@ -4902,27 +5349,24 @@ void InsetTabular::movePrevCell(Cursor & cur, EntryDirection entry_from) } cur.setCurrentFont(); - resetPos(cur); } -bool InsetTabular::tabularFeatures(Cursor & cur, string const & argument) +void InsetTabular::tabularFeatures(Cursor & cur, string const & argument) { + cur.recordUndoInset(this); + istringstream is(argument); string s; - is >> s; - if (insetCode(s) != TABULAR_CODE) - return false; - // Safe guard. size_t safe_guard = 0; for (;;) { if (is.eof()) - break; + return; safe_guard++; if (safe_guard > 1000) { LYXERR0("parameter max count reached!"); - break; + return; } is >> s; Tabular::Feature action = Tabular::LAST_ACTION; @@ -4931,7 +5375,6 @@ bool InsetTabular::tabularFeatures(Cursor & cur, string const & argument) for (; tabularFeature[i].action != Tabular::LAST_ACTION; ++i) { if (s != tabularFeature[i].feature) continue; - action = tabularFeature[i].action; break; } @@ -4945,7 +5388,6 @@ bool InsetTabular::tabularFeatures(Cursor & cur, string const & argument) LYXERR(Debug::DEBUG, "Feature: " << s << "\t\tvalue: " << val); tabularFeatures(cur, action, val); } - return true; } @@ -4970,16 +5412,21 @@ 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 + col_type col_start, col_type col_end) const { for (row_type r = row_start; r <= row_end; ++r) for (col_type c = col_start; c <= col_end; ++c) - if (tabular.getRotateCell(tabular.cellIndex(r, c)) == rotated) - return true; - + if (rotated) { + if (tabular.getRotateCell(tabular.cellIndex(r, c)) != 0) + return true; + } else { + if (tabular.getRotateCell(tabular.cellIndex(r, c)) == 0) + return true; + } return false; } + void InsetTabular::tabularFeatures(Cursor & cur, Tabular::Feature feature, string const & value) { @@ -5035,8 +5482,6 @@ void InsetTabular::tabularFeatures(Cursor & cur, break; } - cur.recordUndoInset(ATOMIC_UNDO); - getSelection(cur, sel_row_start, sel_row_end, sel_col_start, sel_col_end); row_type const row = tabular.cellRow(cur.idx()); col_type const column = tabular.cellColumn(cur.idx()); @@ -5045,6 +5490,10 @@ void InsetTabular::tabularFeatures(Cursor & cur, switch (feature) { + case Tabular::SET_TABULAR_WIDTH: + tabular.setTabularWidth(Length(value)); + break; + case Tabular::SET_PWIDTH: { Length const len(value); tabular.setColumnPWidth(cur, cur.idx(), len); @@ -5058,6 +5507,10 @@ void InsetTabular::tabularFeatures(Cursor & cur, tabular.setMColumnPWidth(cur, cur.idx(), Length(value)); break; + case Tabular::SET_MROFFSET: + tabular.setMROffset(cur, cur.idx(), Length(value)); + break; + case Tabular::SET_SPECIAL_COLUMN: case Tabular::SET_SPECIAL_MULTICOLUMN: if (value == "none") @@ -5068,16 +5521,22 @@ void InsetTabular::tabularFeatures(Cursor & cur, case Tabular::APPEND_ROW: // append the row into the tabular - tabular.appendRow(cur.idx()); + tabular.appendRow(row); break; case Tabular::APPEND_COLUMN: // append the column into the tabular - tabular.appendColumn(cur.idx()); + tabular.appendColumn(column); cur.idx() = tabular.cellIndex(row, column); break; case Tabular::DELETE_ROW: + if (sel_row_end == tabular.nrows() - 1 && sel_row_start != 0) { + for (col_type c = 0; c < tabular.ncols(); c++) + tabular.setBottomLine(tabular.cellIndex(sel_row_start - 1, c), + tabular.bottomLine(tabular.cellIndex(sel_row_end, c))); + } + for (row_type r = sel_row_start; r <= sel_row_end; ++r) tabular.deleteRow(sel_row_start); if (sel_row_start >= tabular.nrows()) @@ -5085,10 +5544,22 @@ void InsetTabular::tabularFeatures(Cursor & cur, cur.idx() = tabular.cellIndex(sel_row_start, column); cur.pit() = 0; cur.pos() = 0; - cur.setSelection(false); + cur.selection(false); break; case Tabular::DELETE_COLUMN: + if (sel_col_end == tabular.ncols() - 1 && sel_col_start != 0) { + for (row_type r = 0; r < tabular.nrows(); r++) + tabular.setRightLine(tabular.cellIndex(r, sel_col_start - 1), + tabular.rightLine(tabular.cellIndex(r, sel_col_end))); + } + + if (sel_col_start == 0 && sel_col_end != tabular.ncols() - 1) { + for (row_type r = 0; r < tabular.nrows(); r++) + tabular.setLeftLine(tabular.cellIndex(r, sel_col_end + 1), + tabular.leftLine(tabular.cellIndex(r, 0))); + } + for (col_type c = sel_col_start; c <= sel_col_end; ++c) tabular.deleteColumn(sel_col_start); if (sel_col_start >= tabular.ncols()) @@ -5096,7 +5567,7 @@ void InsetTabular::tabularFeatures(Cursor & cur, cur.idx() = tabular.cellIndex(row, sel_col_start); cur.pit() = 0; cur.pos() = 0; - cur.setSelection(false); + cur.selection(false); break; case Tabular::COPY_ROW: @@ -5108,6 +5579,26 @@ void InsetTabular::tabularFeatures(Cursor & cur, cur.idx() = tabular.cellIndex(row, column); break; + case Tabular::MOVE_COLUMN_RIGHT: + tabular.moveColumn(column, Tabular::RIGHT); + cur.idx() = tabular.cellIndex(row, column + 1); + break; + + case Tabular::MOVE_COLUMN_LEFT: + tabular.moveColumn(column, Tabular::LEFT); + cur.idx() = tabular.cellIndex(row, column - 1); + break; + + case Tabular::MOVE_ROW_DOWN: + tabular.moveRow(row, Tabular::DOWN); + cur.idx() = tabular.cellIndex(row + 1, column); + break; + + case Tabular::MOVE_ROW_UP: + tabular.moveRow(row, Tabular::UP); + cur.idx() = tabular.cellIndex(row - 1, column); + break; + case Tabular::SET_LINE_TOP: case Tabular::TOGGLE_LINE_TOP: { bool lineSet = (feature == Tabular::SET_LINE_TOP) @@ -5151,7 +5642,6 @@ void InsetTabular::tabularFeatures(Cursor & cur, case Tabular::M_ALIGN_LEFT: case Tabular::M_ALIGN_RIGHT: case Tabular::M_ALIGN_CENTER: - flag = false; case Tabular::ALIGN_LEFT: case Tabular::ALIGN_RIGHT: case Tabular::ALIGN_CENTER: @@ -5159,7 +5649,8 @@ void InsetTabular::tabularFeatures(Cursor & cur, case Tabular::ALIGN_DECIMAL: for (row_type r = sel_row_start; r <= sel_row_end; ++r) for (col_type c = sel_col_start; c <= sel_col_end; ++c) - tabular.setAlignment(tabular.cellIndex(r, c), setAlign, flag); + tabular.setAlignment(tabular.cellIndex(r, c), setAlign, + !tabular.getPWidth(c).zero()); break; case Tabular::M_VALIGN_TOP: @@ -5179,18 +5670,20 @@ void InsetTabular::tabularFeatures(Cursor & cur, // just multicol for one single cell // check whether we are completely in a multicol if (!tabular.isMultiColumn(cur.idx())) - tabular.setMultiColumn(cur.idx(), 1); + tabular.setMultiColumn(cur.idx(), 1, + tabular.rightLine(cur.idx())); break; } - // we have a selection so this means we just add all this + // we have a selection so this means we just add all these // cells to form a multicolumn cell idx_type const s_start = cur.selBegin().idx(); row_type const col_start = tabular.cellColumn(s_start); row_type const col_end = tabular.cellColumn(cur.selEnd().idx()); - cur.idx() = tabular.setMultiColumn(s_start, col_end - col_start + 1); + cur.idx() = tabular.setMultiColumn(s_start, col_end - col_start + 1, + tabular.rightLine(cur.selEnd().idx())); cur.pit() = 0; cur.pos() = 0; - cur.setSelection(false); + cur.selection(false); break; } @@ -5203,10 +5696,27 @@ void InsetTabular::tabularFeatures(Cursor & cur, } case Tabular::MULTICOLUMN: { - if (tabular.isMultiColumn(cur.idx())) - tabularFeatures(cur, Tabular::UNSET_MULTICOLUMN); - else + if (!cur.selection()) { + if (tabular.isMultiColumn(cur.idx())) + tabularFeatures(cur, Tabular::UNSET_MULTICOLUMN); + else + tabularFeatures(cur, Tabular::SET_MULTICOLUMN); + break; + } + bool merge = false; + for (col_type c = sel_col_start; c <= sel_col_end; ++c) { + row_type const r = sel_row_start; + if (!tabular.isMultiColumn(tabular.cellIndex(r, c)) + || (r > sel_row_start && !tabular.isPartOfMultiColumn(r, c))) + merge = true; + } + // If the selection contains at least one singlecol cell + // or multiple multicol cells, + // we assume the user will merge is to a single multicol + if (merge) tabularFeatures(cur, Tabular::SET_MULTICOLUMN); + else + tabularFeatures(cur, Tabular::UNSET_MULTICOLUMN); break; } @@ -5215,7 +5725,9 @@ void InsetTabular::tabularFeatures(Cursor & cur, // just multirow for one single cell // check whether we are completely in a multirow if (!tabular.isMultiRow(cur.idx())) - tabular.setMultiRow(cur.idx(), 1); + tabular.setMultiRow(cur.idx(), 1, + tabular.bottomLine(cur.idx()), + tabular.getAlignment(cur.idx())); break; } // we have a selection so this means we just add all this @@ -5223,10 +5735,12 @@ void InsetTabular::tabularFeatures(Cursor & cur, idx_type const s_start = cur.selBegin().idx(); row_type const row_start = tabular.cellRow(s_start); row_type const row_end = tabular.cellRow(cur.selEnd().idx()); - cur.idx() = tabular.setMultiRow(s_start, row_end - row_start + 1); + cur.idx() = tabular.setMultiRow(s_start, row_end - row_start + 1, + tabular.bottomLine(cur.selEnd().idx()), + tabular.getAlignment(cur.selEnd().idx())); cur.pit() = 0; cur.pos() = 0; - cur.setSelection(false); + cur.selection(false); break; } @@ -5239,10 +5753,27 @@ void InsetTabular::tabularFeatures(Cursor & cur, } case Tabular::MULTIROW: { - if (tabular.isMultiRow(cur.idx())) - tabularFeatures(cur, Tabular::UNSET_MULTIROW); - else + if (!cur.selection()) { + if (tabular.isMultiRow(cur.idx())) + tabularFeatures(cur, Tabular::UNSET_MULTIROW); + else + tabularFeatures(cur, Tabular::SET_MULTIROW); + break; + } + bool merge = false; + for (row_type r = sel_row_start; r <= sel_row_end; ++r) { + col_type const c = sel_col_start; + if (!tabular.isMultiRow(tabular.cellIndex(r, c)) + || (r > sel_row_start && !tabular.isPartOfMultiRow(r, c))) + merge = true; + } + // If the selection contains at least one singlerow cell + // or multiple multirow cells, + // we assume the user will merge is to a single multirow + if (merge) tabularFeatures(cur, Tabular::SET_MULTIROW); + else + tabularFeatures(cur, Tabular::UNSET_MULTIROW); break; } @@ -5270,6 +5801,13 @@ void InsetTabular::tabularFeatures(Cursor & cur, } break; + case Tabular::TOGGLE_LONGTABULAR: + if (tabular.is_long_tabular) + tabularFeatures(cur, Tabular::UNSET_LONGTABULAR); + else + tabular.is_long_tabular = true; + break; + case Tabular::SET_LONGTABULAR: tabular.is_long_tabular = true; break; @@ -5287,15 +5825,16 @@ void InsetTabular::tabularFeatures(Cursor & cur, break; case Tabular::SET_ROTATE_TABULAR: - tabular.rotate = true; + tabular.rotate = convert(value); break; case Tabular::UNSET_ROTATE_TABULAR: - tabular.rotate = false; + tabular.rotate = 0; break; case Tabular::TOGGLE_ROTATE_TABULAR: - tabular.rotate = !tabular.rotate; + // when pressing the rotate button we default to 90° rotation + tabular.rotate != 0 ? tabular.rotate = 0 : tabular.rotate = 90; break; case Tabular::TABULAR_VALIGN_TOP: @@ -5322,18 +5861,18 @@ void InsetTabular::tabularFeatures(Cursor & cur, tabular.longtabular_alignment = Tabular::LYX_LONGTABULAR_ALIGN_RIGHT; break; - + case Tabular::SET_ROTATE_CELL: for (row_type r = sel_row_start; r <= sel_row_end; ++r) for (col_type c = sel_col_start; c <= sel_col_end; ++c) - tabular.setRotateCell(tabular.cellIndex(r, c), true); + tabular.setRotateCell(tabular.cellIndex(r, c), convert(value)); break; case Tabular::UNSET_ROTATE_CELL: for (row_type r = sel_row_start; r <= sel_row_end; ++r) for (col_type c = sel_col_start; c <= sel_col_end; ++c) - tabular.setRotateCell(tabular.cellIndex(r, c), false); + tabular.setRotateCell(tabular.cellIndex(r, c), 0); break; case Tabular::TOGGLE_ROTATE_CELL: @@ -5342,9 +5881,13 @@ void InsetTabular::tabularFeatures(Cursor & cur, sel_row_start, sel_row_end, sel_col_start, sel_col_end); for (row_type r = sel_row_start; r <= sel_row_end; ++r) - for (col_type c = sel_col_start; c <= sel_col_end; ++c) - tabular.setRotateCell(tabular.cellIndex(r, c), - oneNotRotated); + for (col_type c = sel_col_start; c <= sel_col_end; ++c) { + // when pressing the rotate cell button we default to 90° rotation + if (oneNotRotated) + tabular.setRotateCell(tabular.cellIndex(r, c), 90); + else + tabular.setRotateCell(tabular.cellIndex(r, c), 0); + } } break; @@ -5390,8 +5933,10 @@ void InsetTabular::tabularFeatures(Cursor & cur, tabular.setLTFoot(row, flag, ltt, true); break; + case Tabular::UNSET_LTNEWPAGE: + flag = false; case Tabular::SET_LTNEWPAGE: - tabular.setLTNewPage(row, !tabular.getLTNewPage(row)); + tabular.setLTNewPage(row, flag); break; case Tabular::SET_LTCAPTION: { @@ -5400,21 +5945,23 @@ void InsetTabular::tabularFeatures(Cursor & cur, cur.idx() = tabular.setLTCaption(row, true); cur.pit() = 0; cur.pos() = 0; - cur.setSelection(false); + cur.selection(false); // If a row is set as caption, then also insert // a caption. Otherwise the LaTeX output is broken. - lyx::dispatch(FuncRequest(LFUN_INSET_SELECT_ALL)); + // Select cell if it is non-empty + if (cur.lastpos() > 0 || cur.lastpit() > 0) + lyx::dispatch(FuncRequest(LFUN_INSET_SELECT_ALL)); lyx::dispatch(FuncRequest(LFUN_CAPTION_INSERT)); break; } - + case Tabular::UNSET_LTCAPTION: { if (!tabular.ltCaption(row)) break; cur.idx() = tabular.setLTCaption(row, false); cur.pit() = 0; cur.pos() = 0; - cur.setSelection(false); + cur.selection(false); FuncRequest fr(LFUN_INSET_DISSOLVE, "caption"); if (lyx::getStatus(fr).enabled()) lyx::dispatch(fr); @@ -5429,6 +5976,10 @@ void InsetTabular::tabularFeatures(Cursor & cur, break; } + case Tabular::TOGGLE_BOOKTABS: + tabular.use_booktabs = !tabular.use_booktabs; + break; + case Tabular::SET_BOOKTABS: tabular.use_booktabs = true; break; @@ -5532,7 +6083,7 @@ bool InsetTabular::copySelection(Cursor & cur) odocstringstream os; OutputParams const runparams(0); - paste_tabular->plaintext(os, runparams, 0, true, '\t'); + paste_tabular->plaintext(os, runparams, 0, true, '\t', INT_MAX); // Needed for the "Edit->Paste recent" menu and the system clipboard. cap::copySelection(cur, os.str()); @@ -5583,7 +6134,7 @@ bool InsetTabular::pasteClipboard(Cursor & cur) tabular.cellInset(r2, c2)->setBuffer(tabular.buffer()); // FIXME: change tracking (MG) - inset->setChange(Change(buffer().params().trackChanges ? + inset->setChange(Change(buffer().params().track_changes ? Change::INSERTED : Change::UNCHANGED)); cur.pos() = 0; } @@ -5604,7 +6155,7 @@ void InsetTabular::cutSelection(Cursor & cur) for (col_type c = cs; c <= ce; ++c) { shared_ptr t = cell(tabular.cellIndex(r, c)); - if (buffer().params().trackChanges) + if (buffer().params().track_changes) // FIXME: Change tracking (MG) t->setChange(Change(Change::DELETED)); else @@ -5623,7 +6174,8 @@ void InsetTabular::cutSelection(Cursor & cur) bool InsetTabular::isRightToLeft(Cursor & cur) const { - LASSERT(cur.depth() > 1, /**/); + // LASSERT: It might be better to abandon this Buffer. + LASSERT(cur.depth() > 1, return false); Paragraph const & parentpar = cur[cur.depth() - 2].paragraph(); pos_type const parentpos = cur[cur.depth() - 2].pos(); return parentpar.getFontSettings(buffer().params(), @@ -5631,7 +6183,7 @@ bool InsetTabular::isRightToLeft(Cursor & cur) const } -docstring InsetTabular::asString(idx_type stidx, idx_type enidx, +docstring InsetTabular::asString(idx_type stidx, idx_type enidx, bool intoInsets) { LASSERT(stidx <= enidx, return docstring()); @@ -5744,7 +6296,6 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf, if (usePaste) { paste_tabular.reset(new Tabular(buffer_, rows, maxCols)); loctab = paste_tabular.get(); - cols = 0; dirtyTabularStack(true); } else { loctab = &tabular; @@ -5773,7 +6324,7 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf, Font const font = bv.textMetrics(&inset->text()). displayFont(0, 0); inset->setText(buf.substr(op, p - op), font, - buffer().params().trackChanges); + buffer().params().track_changes); ++cols; ++cell; } @@ -5785,7 +6336,7 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf, Font const font = bv.textMetrics(&inset->text()). displayFont(0, 0); inset->setText(buf.substr(op, p - op), font, - buffer().params().trackChanges); + buffer().params().track_changes); } cols = ocol; ++row; @@ -5801,7 +6352,7 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf, shared_ptr inset = loctab->cellInset(cell); Font const font = bv.textMetrics(&inset->text()).displayFont(0, 0); inset->setText(buf.substr(op, len - op), font, - buffer().params().trackChanges); + buffer().params().track_changes); } return true; } @@ -5878,7 +6429,7 @@ bool InsetTabular::insertCompletion(Cursor & cur, docstring const & s, bool fini } -void InsetTabular::completionPosAndDim(Cursor const & cur, int & x, int & y, +void InsetTabular::completionPosAndDim(Cursor const & cur, int & x, int & y, Dimension & dim) const { TextMetrics const & tm = cur.bv().textMetrics(cur.text()); @@ -5924,4 +6475,22 @@ string InsetTabular::params2string(InsetTabular const & inset) } +void InsetTabular::setLayoutForHiddenCells(DocumentClass const & dc) +{ + for (Tabular::col_type c = 0; c < tabular.ncols(); ++c) { + for (Tabular::row_type r = 0; r < tabular.nrows(); ++r) { + if (!tabular.isPartOfMultiColumn(r,c) && + !tabular.isPartOfMultiRow(r,c)) + continue; + + ParagraphList & parlist = tabular.cellInset(r,c)->paragraphs(); + ParagraphList::iterator it = parlist.begin(); + ParagraphList::iterator const en = parlist.end(); + for (; it != en; ++it) + it->setLayout(dc.plainLayout()); + } + } +} + + } // namespace lyx