* \author Jürgen Vigna
* \author Uwe Stöhr
* \author Edwin Leuven
+ * \author Scott Kostyshak
*
* Full author contact details are available in file CREDITS.
*/
#include "DispatchResult.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
+#include "InsetIterator.h"
+#include "InsetList.h"
#include "Language.h"
#include "LaTeXFeatures.h"
#include "Lexer.h"
#include "Paragraph.h"
#include "ParagraphParameters.h"
#include "ParIterator.h"
+#include "TexRow.h"
+#include "texstream.h"
#include "TextClass.h"
#include "TextMetrics.h"
#include "support/gettext.h"
#include "support/lassert.h"
#include "support/lstrings.h"
+#include "support/unique_ptr.h"
-#include <boost/scoped_ptr.hpp>
-
-#include <sstream>
+#include <cstring>
+#include <iomanip>
#include <iostream>
#include <limits>
-#include <cstring>
+#include <sstream>
using namespace std;
using namespace lyx::support;
///
-boost::scoped_ptr<Tabular> paste_tabular;
+unique_ptr<Tabular> paste_tabular;
struct 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 },
{ 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::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 },
// 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;
}
-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;
}
-bool string2type(string const str, Tabular::VAlignment & num)
+bool string2type(string const & str, Tabular::VAlignment & num)
{
if (str == "top")
num = Tabular::LYX_VALIGN_TOP;
}
-bool string2type(string const str, Tabular::BoxType & num)
+bool string2type(string const & str, Tabular::BoxType & num)
{
if (str == "none")
num = Tabular::BOX_NONE;
}
-bool string2type(string const str, bool & num)
+bool string2type(string const & str, bool & num)
{
if (str == "true")
num = true;
}
-DocIterator separatorPos(InsetTableCell * cell, docstring const & align_d)
+DocIterator separatorPos(InsetTableCell const * cell, docstring const & align_d)
{
DocIterator dit = doc_iterator_begin(&(cell->buffer()), cell);
for (; dit; dit.forwardChar())
}
-InsetTableCell splitCell(InsetTableCell & head, docstring const align_d, bool & hassep)
+InsetTableCell splitCell(InsetTableCell & head, docstring const & align_d, bool & hassep)
{
InsetTableCell tail = InsetTableCell(head);
DocIterator const dit = separatorPos(&head, align_d);
- hassep = dit;
+ 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);
}
{
}
-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<InsetTableCell *>(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(mroffset, rhs.mroffset);
- 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),
Tabular::ltType::ltType()
- : topDL(false),
+ : set(false), topDL(false),
bottomDL(false),
empty(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_info.insert(cell_info.begin() + row + 1,
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().trackChanges)
+ 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;
}
-
+
updateIndexes();
for (col_type c = 0; c < ncols(); ++c) {
if (isPartOfMultiRow(row, c))
setBottomLine(j, false);
}
// mark track changes
- if (buffer().params().trackChanges)
+ if (buffer().params().track_changes)
+ cellInfo(i).inset->setChange(Change(Change::INSERTED));
+ }
+}
+
+
+void Tabular::moveColumn(col_type col, ColDirection direction)
+{
+ if (direction == Tabular::LEFT)
+ col = col - 1;
+
+ 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));
+ }
+ }
+ updateIndexes();
+}
+
+
+void Tabular::moveRow(row_type row, RowDirection direction)
+{
+ if (direction == Tabular::UP)
+ row = row - 1;
+
+ std::swap(row_info[row], row_info[row + 1]);
+
+ 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();
}
void Tabular::appendColumn(col_type col)
-{
+{
insertColumn(col, false);
}
for (row_type r = 0; r < nrows(); ++r) {
cell_info[r].insert(cell_info[r].begin() + col + 1,
copy ? CellData(cell_info[r][col]) : CellData(buffer_));
- if (bp.trackChanges)
+ 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;
setBottomLine(i, bottomLine(j));
setTopLine(i, topLine(j));
setLeftLine(i, leftLine(j));
- if (rightLine(j) && rightLine(j)) {
- setRightLine(i, true);
+ setRightLine(i, rightLine(j));
+ if (rightLine(i) && rightLine(j)) {
setRightLine(j, false);
}
- if (buffer().params().trackChanges)
+ if (buffer().params().track_changes)
cellInfo(i).inset->setChange(Change(Change::INSERTED));
}
}
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);
if (align == LYX_ALIGN_DECIMAL && dpoint.empty())
dpoint = from_utf8(lyxrc.default_decimal_point);
} else {
- cellInfo(cell).alignment = align;
- cellInset(cell).get()->setContentAlignment(align);
+ cellInfo(cell).alignment = align;
+ cellInset(cell)->setContentAlignment(align);
}
}
*/
void toggleFixedWidth(Cursor & cur, InsetTableCell * inset, bool fixedWidth)
{
- inset->setAutoBreakRows(fixedWidth);
inset->toggleFixedWidth(fixedWidth);
if (fixedWidth)
return;
cur.pop();
}
-}
+} // namespace
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())
// 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())
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)
{
if (!onlycolumn && (isMultiColumn(cell) || isMultiRow(cell)))
return cellInfo(cell).alignment;
-
+
return column_info[cellColumn(cell)].alignment;
}
}
+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))
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;
}
<< ">\n";
// global longtable options
os << "<features"
- << write_attribute("rotate", convert<string>(rotate))
+ << write_attribute("rotate", rotate)
<< write_attribute("booktabs", use_booktabs)
<< write_attribute("islongtable", is_long_tabular)
<< write_attribute("firstHeadTopDL", endfirsthead.topDL)
<< write_attribute("lastFootEmpty", endlastfoot.empty);
// longtables cannot be aligned vertically
if (!is_long_tabular) {
- os << write_attribute("tabularvalignment", tabular_valignment);
- os << write_attribute("tabularwidth", tabular_width);
+ 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 << "<column"
cell_info[r][c].inset->write(os);
os << "\n\\end_inset\n"
<< "</cell>\n";
+ // FIXME This can be removed again once the mystery
+ // crash has been resolved.
+ os << flush;
}
os << "</row>\n";
}
l_getline(is, line);
if (!prefixIs(line, "<lyxtabular ") && !prefixIs(line, "<Tabular ")) {
- LASSERT(false, /**/);
- return;
+ LASSERT(false, return);
}
int version;
if (!getTokenValue(line, "version", version))
return;
- LASSERT(version >= 2, /**/);
+ LATTEST(version >= 2);
int rows_arg;
if (!getTokenValue(line, "rows", rows_arg))
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::CellData & Tabular::cellInfo(idx_type cell)
{
return cell_info[cellRow(cell)][cellColumn(cell)];
}
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, right_border);
+ 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());
|| 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,
- bool const bottom_border)
+ bool const bottom_border,
+ LyXAlignment const halign)
{
idx_type const col = cellColumn(cell);
idx_type const row = cellRow(cell);
// 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 line of the last selected cell
setBottomLine(cell, bottom_border);
col_type row = cellRow(cell) + 1;
while (row < nrows() && isPartOfMultiRow(row, column))
++row;
-
+
return row - cellRow(cell);
}
bool Tabular::needRotating() const
{
- if (rotate)
+ if (rotate && !is_long_tabular)
return true;
for (row_type r = 0; r < nrows(); ++r)
for (col_type c = 0; c < ncols(); ++c)
{
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)
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;
}
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;
}
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;
}
-void Tabular::TeXTopHLine(otexstream & 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(...)
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 << "} ";
}
}
}
-void Tabular::TeXBottomHLine(otexstream & 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
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")
<< "\\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 << "} ";
}
}
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;
// we center in multicol when no decimal point
if (column_info[c].alignment == LYX_ALIGN_DECIMAL) {
docstring const align_d = column_info[c].decimal_point;
- DocIterator const dit = separatorPos(cellInset(cell).get(), align_d);
+ DocIterator const dit = separatorPos(cellInset(cell), align_d);
ismulticol |= !dit;
}
if (!is_long_tabular)
return;
+ // caption handling
+ // output caption which is in no header or footer
+ if (haveLTCaption()) {
+ for (row_type r = 0; r < nrows(); ++r) {
+ 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
if (haveLTFirstHead()) {
if (endfirsthead.topDL)
OutputParams const & runparams) const
{
idx_type cell = cellIndex(row, 0);
- shared_ptr<InsetTableCell> inset = cellInset(cell);
+ InsetTableCell const * inset = cellInset(cell);
Paragraph const & par = inset->paragraphs().front();
string const lang = par.getParLanguage(buffer().params())->lang();
if (isPartOfMultiRow(row, c)
&& column_info[c].alignment != LYX_ALIGN_DECIMAL) {
if (cell != getLastCellInRow(row))
- os << " & ";
+ os << " & ";
continue;
}
TeXCellPreamble(os, cell, ismulticol, ismultirow);
- shared_ptr<InsetTableCell> inset = cellInset(cell);
+ 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()
if (getAlignment(cell) == LYX_ALIGN_DECIMAL) {
// copy cell and split in 2
- InsetTableCell head = InsetTableCell(*cellInset(cell).get());
- head.setBuffer(buffer());
+ InsetTableCell head = InsetTableCell(*cellInset(cell));
+ head.setBuffer(const_cast<Buffer &>(buffer()));
DocIterator dit = cellInset(cell)->getText(0)->macrocontextPosition();
dit.pop_back();
dit.push_back(CursorSlice(head));
tail.setMacrocontextPositionRecursive(dit);
tail.latex(os, newrp);
}
+ } else if (ltCaption(row)) {
+ // Inside longtable caption rows, we must only output the caption inset
+ // with its content and omit anything outside of that (see #10791)
+ InsetIterator it = inset_iterator_begin(*const_cast<InsetTableCell *>(inset));
+ InsetIterator i_end = inset_iterator_end(*const_cast<InsetTableCell *>(inset));
+ for (; it != i_end; ++it) {
+ if (it->lyxCode() != CAPTION_CODE)
+ continue;
+ it->latex(os, runparams);
+ break;
+ }
} else if (!isPartOfMultiRow(row, c)) {
if (!runparams.nice)
os.texrow().start(par.id(), 0);
void Tabular::latex(otexstream & os, OutputParams const & runparams) const
{
bool const is_tabular_star = !tabular_width.zero();
+ TexRow::RowEntry pos = TexRow::textEntry(runparams.lastid, runparams.lastpos);
//+---------------------------------------------------------------------
//+ first the opening preamble +
//+---------------------------------------------------------------------
os << safebreakln;
- if (runparams.lastid != -1)
- os.texrow().start(runparams.lastid, runparams.lastpos);
+ if (!TexRow::isNone(pos))
+ os.texrow().start(pos);
- if (rotate != 0)
+ if (rotate != 0 && !is_long_tabular)
os << "\\begin{turn}{" << convert<string>(rotate) << "}\n";
if (is_long_tabular) {
break;
}
}
-
+
os << "{";
if (is_tabular_star)
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}";
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:
os << "\\end{tabular}";
}
- if (rotate != 0)
+ if (rotate != 0 && !is_long_tabular)
os << breakln << "\\end{turn}";
+
+ if (!TexRow::isNone(pos))
+ os.texrow().start(pos);
}
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:
else if (isMultiRow(cell))
attr << " rowspan='" << rowSpan(cell) << "'";
- xs << html::StartTag(celltag, attr.str()) << html::CR();
+ xs << html::StartTag(celltag, attr.str(), true) << html::CR();
ret += cellInset(cell)->xhtml(xs, runparams);
xs << html::EndTag(celltag) << html::CR();
++cell;
}
-bool Tabular::plaintextTopHLine(odocstream & os, row_type row,
+bool Tabular::plaintextTopHLine(odocstringstream & os, row_type row,
vector<unsigned int> const & clen) const
{
idx_type const fcell = getFirstCellInRow(row);
}
-bool Tabular::plaintextBottomHLine(odocstream & os, row_type row,
+bool Tabular::plaintextBottomHLine(odocstringstream & os, row_type row,
vector<unsigned int> const & clen) const
{
idx_type const fcell = getFirstCellInRow(row);
}
-void Tabular::plaintextPrintCell(odocstream & os,
+void Tabular::plaintextPrintCell(odocstringstream & os,
OutputParams const & runparams,
idx_type cell, row_type row, col_type column,
vector<unsigned int> 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();
}
-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<unsigned int> clen(ncols());
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();
}
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)
// 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) {
if (plaintextBottomHLine(os, r, clen))
os << docstring(depth * 2, ' ');
}
+ if (os.str().size() > max_length)
+ break;
}
}
-shared_ptr<InsetTableCell> Tabular::cellInset(idx_type cell) const
+shared_ptr<InsetTableCell> Tabular::cellInset(idx_type cell)
{
return cell_info[cellRow(cell)][cellColumn(cell)].inset;
}
-shared_ptr<InsetTableCell> Tabular::cellInset(row_type row,
- col_type column) const
+shared_ptr<InsetTableCell> 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<InsetTableCell> ins) const
+ shared_ptr<InsetTableCell> ins)
{
CellData & cd = cell_info[row][column];
cd.inset = ins;
if (getVAlignment(cell) != LYX_VALIGN_TOP
|| !getPWidth(cell).zero())
features.require("array");
+ // Tell footnote that we need a savenote
+ // environment in non-long tables or
+ // longtable headers/footers
+ else if (!is_long_tabular && !features.inFloat())
+ features.saveNoteEnv("tabular");
+ else if (!isValidRow(cellRow(cell)))
+ features.saveNoteEnv("longtable");
+
cellInset(cell)->validate(features);
+ features.saveNoteEnv(string());
}
}
}
+bool InsetTableCell::forceLocalFontSwitch() const
+{
+ return isFixedWidth;
+}
+
+
bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd,
FuncStatus & status) const
{
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;
return true;
}
-docstring InsetTableCell::asString(bool intoInsets)
+docstring InsetTableCell::asString(bool intoInsets)
{
docstring retval;
if (paragraphs().empty())
}
+void InsetTableCell::addToToc(DocIterator const & di, bool output_active,
+ UpdateType utype, TocBackend & backend) const
+{
+ InsetText::iterateForToc(di, output_active, utype, backend);
+}
+
+
docstring InsetTableCell::xhtml(XHTMLStream & xs, OutputParams const & rp) const
{
if (!isFixedWidth)
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)
{
}
}
+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;
int InsetTabular::rowFromY(Cursor & cur, int y) const
{
// top y coordinate of tabular
- int h = yo(cur.bv()) - tabular.rowAscent(0) + offset_valign_;
+ 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)
{
//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;
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 = mi.base.inPixels(p_width);
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 horizontal offset because of decimal align (if necessary)
int decimal_width = 0;
if (tabular.getAlignment(cell) == LYX_ALIGN_DECIMAL) {
- InsetTableCell tail = InsetTableCell(*tabular.cellInset(cell).get());
+ 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)
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;
maxdes = max(maxdes, dim.des + offset);
}
int const top_space = tabular.row_info[r].top_space_default ?
- default_line_space :
- tabular.row_info[r].top_space.inPixels(mi.base.textwidth);
+ default_line_space :
+ mi.base.inPixels(tabular.row_info[r].top_space);
tabular.setRowAscent(r, maxasc + ADD_TO_HEIGHT + top_space);
int const bottom_space = tabular.row_info[r].bottom_space_default ?
- default_line_space :
- tabular.row_info[r].bottom_space.inPixels(mi.base.textwidth);
+ default_line_space :
+ mi.base.inPixels(tabular.row_info[r].bottom_space);
tabular.setRowDescent(r, maxdes + ADD_TO_HEIGHT + bottom_space);
}
- // for top-alignment the first horizontal table line must be exactly at
- // the position of the base line of the surrounding text line
- // for bottom alignment, the same is for the last table line
- switch (tabular.tabular_valignment) {
- case Tabular::LYX_VALIGN_BOTTOM:
- offset_valign_ = tabular.rowAscent(0) - tabular.height();
- break;
- case Tabular::LYX_VALIGN_MIDDLE:
- offset_valign_ = (- tabular.height()) / 2 + tabular.rowAscent(0);
- break;
- case Tabular::LYX_VALIGN_TOP:
- offset_valign_ = tabular.rowAscent(0);
- break;
- }
-
tabular.updateColumnWidths();
- dim.asc = tabular.rowAscent(0) - offset_valign_;
+ 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()) {
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();
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 drawBackground(),
// we have no choice but to do a full repaint for the Text cells.
bool const original_selection_state = pi.selected;
idx_type idx = 0;
- first_visible_cell = Tabular::npos;
- int yy = y + offset_valign_;
+ 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 = yy + tabular.textVOffset(idx);
}
if (r + 1 < tabular.nrows())
- yy += tabular.rowDescent(r) + tabular.rowAscent(r + 1)
+ yy += tabular.rowDescent(r) + tabular.rowAscent(r + 1)
+ tabular.interRowSpace(r + 1);
}
}
void InsetTabular::drawBackground(PainterInfo & pi, int x, int y) const
{
- x += scx_ + ADD_TO_TABULAR_WIDTH;
- y += offset_valign_ - tabular.rowAscent(0);
+ x += ADD_TO_TABULAR_WIDTH;
+ y += tabular.offsetVAlignment() - tabular.rowAscent(0);
pi.pain.fillRectangle(x, y, tabular.width(), tabular.height(),
pi.backgroundColor(this));
}
void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
{
Cursor & cur = pi.base.bv->cursor();
- resetPos(cur);
- x += scx_ + ADD_TO_TABULAR_WIDTH;
+ x += ADD_TO_TABULAR_WIDTH;
if (!cur.selection())
return;
}
int const w = tabular.cellWidth(cell);
int const h = tabular.cellHeight(cell);
- int const yy = y - tabular.rowAscent(r) + offset_valign_;
+ 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;
+ tabular.interRowSpace(r + 1);
}
- }
+ }
// FIXME: This code has no effect because InsetTableCell does not handle
// drawSelection other than the trivial implementation in Inset.
//else {
// 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);
{
//lyxerr << "InsetTabular::edit: " << this << endl;
cur.finishUndo();
- cur.setSelection(false);
cur.push(*this);
if (front) {
if (isRightToLeft(cur))
}
cur.setCurrentFont();
// FIXME: this accesses the position cache before it is initialized
- //resetPos(cur);
//cur.bv().fitCursor();
}
// 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();
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) const
+void InsetTabular::addToToc(DocIterator const & cpit, bool output_active,
+ UpdateType utype, TocBackend & backend) 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, backend);
+}
+
+
+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);
}
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) + offset_valign_;
- 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
cur.pit() = 0;
cur.pos() = 0;
bvcur.setCursor(cur);
- bvcur.setSelection(true);
+ bvcur.selection(true);
break;
}
// select (additional) column
cur.pit() = 0;
cur.pos() = 0;
bvcur.setCursor(cur);
- bvcur.setSelection(true);
+ bvcur.selection(true);
break;
}
// only update if selection changes
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()) {
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:
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:
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) {
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
|| 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
|| 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));
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)
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);
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
cur.pit() = cur.lastpit();
cur.pos() = cur.lastpos();
cur.setCurrentFont();
+ cur.screenUpdateFlags(Update::Force | Update::FitCursor);
return;
}
- cur.screenUpdateFlags(Update::FitCursor);
+ cur.screenUpdateFlags(Update::Force | Update::FitCursor);
break;
case LFUN_UP_SELECT:
cur.pit() = 0;
cur.pos() = cur.lastpos();
cur.setCurrentFont();
+ cur.screenUpdateFlags(Update::Force | Update::FitCursor);
return;
}
- cur.screenUpdateFlags(Update::FitCursor);
+ 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: {
- string arg;
- if (cmd.getArg(1) == "from-dialog")
- arg = cmd.getArg(0) + to_utf8(cmd.argument().substr(19));
+ case LFUN_INSET_MODIFY:
+ // we come from the dialog
+ if (cmd.getArg(0) == "tabular")
+ tabularFeatures(cur, cmd.getLongArg(1));
else
- arg = to_utf8(cmd.argument());
- if (!tabularFeatures(cur, arg))
cur.undispatched();
break;
- }
+
+ case LFUN_TABULAR_FEATURE:
+ tabularFeatures(cur, to_utf8(cmd.argument()));
+ break;
// insert file functions
case LFUN_FILE_INSERT_PLAINTEXT_PARA:
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
case LFUN_CUT:
if (cur.selIsMultiCell()) {
if (copySelection(cur)) {
- cur.recordUndoInset(DELETE_UNDO);
+ cur.recordUndoInset();
cutSelection(cur);
}
} else
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);
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
break;
}
if (theClipboard().isInternal()) {
- cur.recordUndoInset(INSERT_UNDO);
+ cur.recordUndoInset();
pasteClipboard(cur);
}
break;
case LFUN_FONT_SIZE:
case LFUN_FONT_UNDERLINE:
case LFUN_FONT_STRIKEOUT:
- case LFUN_FONT_UULINE:
- case LFUN_FONT_UWAVE:
+ case LFUN_FONT_CROSSOUT:
+ 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:
}
-// 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;
-
- // FIXME: We only check for the very first argument...
- string const s = cmd.getArg(1);
- // We always enable the lfun if it is coming from the dialog
- // because the dialog makes sure all the settings are valid,
- // even though the first argument might not be valid now.
- if (s == "from-dialog") {
- status.setEnabled(true);
- return true;
- }
int action = Tabular::LAST_ACTION;
int i = 0;
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;
&& 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);
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:
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;
// therefore allow always left but right and center only if there is no width
case Tabular::M_ALIGN_LEFT:
flag = false;
+ // fall through
case Tabular::ALIGN_LEFT:
status.setOnOff(tabular.getAlignment(cur.idx(), flag) == LYX_ALIGN_LEFT);
break;
case Tabular::M_ALIGN_RIGHT:
flag = false;
+ // fall through
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;
+ // fall through
case Tabular::ALIGN_CENTER:
- status.setEnabled(!(tabular.isMultiRow(cur.idx())
+ status.setEnabled(!(tabular.isMultiRow(cur.idx())
&& !tabular.getPWidth(cur.idx()).zero()));
status.setOnOff(tabular.getAlignment(cur.idx(), flag) == LYX_ALIGN_CENTER);
break;
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;
case Tabular::M_VALIGN_TOP:
flag = false;
+ // fall through
case Tabular::VALIGN_TOP:
status.setEnabled(!tabular.getPWidth(cur.idx()).zero()
&& !tabular.isMultiRow(cur.idx()));
case Tabular::M_VALIGN_BOTTOM:
flag = false;
+ // fall through
case Tabular::VALIGN_BOTTOM:
status.setEnabled(!tabular.getPWidth(cur.idx()).zero()
&& !tabular.isMultiRow(cur.idx()));
case Tabular::M_VALIGN_MIDDLE:
flag = false;
+ // fall through
case Tabular::VALIGN_MIDDLE:
status.setEnabled(!tabular.getPWidth(cur.idx()).zero()
&& !tabular.isMultiRow(cur.idx()));
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)
case Tabular::TABULAR_VALIGN_TOP:
status.setEnabled(tabular.tabular_width.zero());
- status.setOnOff(tabular.tabular_valignment
+ status.setOnOff(tabular.tabular_valignment
== Tabular::LYX_VALIGN_TOP);
break;
case Tabular::TABULAR_VALIGN_MIDDLE:
status.setEnabled(tabular.tabular_width.zero());
- status.setOnOff(tabular.tabular_valignment
+ status.setOnOff(tabular.tabular_valignment
== Tabular::LYX_VALIGN_MIDDLE);
break;
case Tabular::TABULAR_VALIGN_BOTTOM:
status.setEnabled(tabular.tabular_width.zero());
- status.setOnOff(tabular.tabular_valignment
+ 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;
break;
case Tabular::UNSET_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;
break;
case Tabular::UNSET_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;
break;
case Tabular::UNSET_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;
break;
case Tabular::UNSET_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;
status.setOnOff(tabular.ltCaption(sel_row_start));
break;
+ case Tabular::TOGGLE_BOOKTABS:
case Tabular::SET_BOOKTABS:
status.setOnOff(tabular.use_booktabs);
break;
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
status.setEnabled(false);
return true;
}
+ // fall through
case LFUN_NEWLINE_INSERT: {
if (tabular.getPWidth(cur.idx()).zero()) {
status.setEnabled(false);
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."));
}
-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;
}
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.addCSSSnippet(
- "table { border: 1px solid black; display: inline-block; }\n"
- "td { border: 1px solid black; padding: 0.5ex; }");
+ features.useInsetLayout(getLayout());
}
// y offset correction
y += cellYPos(sl.idx());
y += tabular.textVOffset(sl.idx());
- y += offset_valign_;
+ y += tabular.offsetVAlignment();
// x offset correction
x += cellXPos(sl.idx());
x += tabular.textHOffset(sl.idx());
x += ADD_TO_TABULAR_WIDTH;
- x += scx_;
}
Inset * InsetTabular::editXY(Cursor & cur, int x, int y)
{
//lyxerr << "InsetTabular::editXY: " << this << endl;
- cur.setSelection(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);
}
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)
+ ly += tabular.rowDescent(r) + tabular.rowAscent(r + 1)
+ tabular.interRowSpace(r + 1);
return ly;
}
}
-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());
if (cur.selIsMultiCell()) {
cur.pit() = cur.lastpit();
cur.pos() = cur.lastpos();
- resetPos(cur);
return;
}
cur.pos() = 0;
// in visual mode, place cursor at extreme left or right
-
+
switch(entry_from) {
case ENTRY_DIRECTION_RIGHT:
}
cur.setCurrentFont();
- resetPos(cur);
}
if (cur.selIsMultiCell()) {
cur.pit() = cur.lastpit();
cur.pos() = cur.lastpos();
- resetPos(cur);
return;
}
cur.pos() = cur.lastpos();
// in visual mode, place cursor at extreme left or right
-
+
switch(entry_from) {
case ENTRY_DIRECTION_RIGHT:
}
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);
+ // limit the size of strings we read to avoid memory problems
+ is >> setw(65636);
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;
LYXERR(Debug::DEBUG, "Feature: " << s << "\t\tvalue: " << val);
tabularFeatures(cur, action, val);
}
- return true;
}
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)
break;
case Tabular::ALIGN_DECIMAL:
- if (tabular.column_info[tabular.cellColumn(cur.idx())].alignment == LYX_ALIGN_DECIMAL)
- setAlign = LYX_ALIGN_CENTER;
- else
- setAlign = LYX_ALIGN_DECIMAL;
+ setAlign = LYX_ALIGN_DECIMAL;
break;
case Tabular::M_VALIGN_TOP:
break;
}
- cur.recordUndoInset(ATOMIC_UNDO, this);
-
getSelection(cur, sel_row_start, sel_row_end, sel_col_start, sel_col_end);
row_type const row = tabular.cellRow(cur.idx());
col_type const column = tabular.cellColumn(cur.idx());
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())
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())
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:
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)
case Tabular::M_VALIGN_BOTTOM:
case Tabular::M_VALIGN_MIDDLE:
flag = false;
+ // fall through
case Tabular::VALIGN_TOP:
case Tabular::VALIGN_BOTTOM:
case Tabular::VALIGN_MIDDLE:
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);
tabular.rightLine(cur.selEnd().idx()));
cur.pit() = 0;
cur.pos() = 0;
- cur.setSelection(false);
+ cur.selection(false);
break;
}
// check whether we are completely in a multirow
if (!tabular.isMultiRow(cur.idx()))
tabular.setMultiRow(cur.idx(), 1,
- tabular.bottomLine(cur.idx()));
+ tabular.bottomLine(cur.idx()),
+ tabular.getAlignment(cur.idx()));
break;
}
// we have a selection so this means we just add all this
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,
- tabular.bottomLine(cur.selEnd().idx()));
+ tabular.bottomLine(cur.selEnd().idx()),
+ tabular.getAlignment(cur.selEnd().idx()));
cur.pit() = 0;
cur.pos() = 0;
- cur.setSelection(false);
+ cur.selection(false);
break;
}
case Tabular::SET_ALL_LINES:
setLines = true;
+ // fall through
case Tabular::UNSET_ALL_LINES:
for (row_type r = sel_row_start; r <= sel_row_end; ++r)
for (col_type c = sel_col_start; c <= sel_col_end; ++c) {
}
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;
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)
case Tabular::UNSET_LTFIRSTHEAD:
flag = false;
+ // fall through
case Tabular::SET_LTFIRSTHEAD:
tabular.getRowOfLTFirstHead(row, ltt);
checkLongtableSpecial(ltt, value, flag);
case Tabular::UNSET_LTHEAD:
flag = false;
+ // fall through
case Tabular::SET_LTHEAD:
tabular.getRowOfLTHead(row, ltt);
checkLongtableSpecial(ltt, value, flag);
case Tabular::UNSET_LTFOOT:
flag = false;
+ // fall through
case Tabular::SET_LTFOOT:
tabular.getRowOfLTFoot(row, ltt);
checkLongtableSpecial(ltt, value, flag);
case Tabular::UNSET_LTLASTFOOT:
flag = false;
+ // fall through
case Tabular::SET_LTLASTFOOT:
tabular.getRowOfLTLastFoot(row, ltt);
checkLongtableSpecial(ltt, value, flag);
case Tabular::UNSET_LTNEWPAGE:
flag = false;
+ // fall through
case Tabular::SET_LTNEWPAGE:
tabular.setLTNewPage(row, flag);
break;
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);
break;
}
+ case Tabular::TOGGLE_BOOKTABS:
+ tabular.use_booktabs = !tabular.use_booktabs;
+ break;
+
case Tabular::SET_BOOKTABS:
tabular.use_booktabs = true;
break;
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());
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;
}
for (col_type c = cs; c <= ce; ++c) {
shared_ptr<InsetTableCell> 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
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(),
}
-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());
if (usePaste) {
paste_tabular.reset(new Tabular(buffer_, rows, maxCols));
loctab = paste_tabular.get();
- cols = 0;
dirtyTabularStack(true);
} else {
loctab = &tabular;
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;
}
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;
shared_ptr<InsetTableCell> 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;
}
}
-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());
}
+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