};
-template <class T>
-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<string>(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<string>(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<string>(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) {
}
}
+template <class T>
+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<string>(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<string>(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<string>(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
}
-InsetTableCell splitCell(InsetTableCell & head, docstring const align_d, bool & hassep)
+DocIterator separatorPos(InsetTableCell * cell, docstring const & align_d)
{
- InsetTableCell tail = InsetTableCell(head);
-
- 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
&& dit.paragraph().find(align_d, false, false, dit.pos()))
break;
- pit_type const psize = head.paragraphs().front().size();
+ return dit;
+}
+
+
+InsetTableCell splitCell(InsetTableCell & head, docstring const align_d, bool & hassep)
+{
+ InsetTableCell tail = InsetTableCell(head);
+ DocIterator const dit = separatorPos(&head, align_d);
hassep = dit;
if (hassep) {
+ pit_type const psize = head.paragraphs().front().size();
head.paragraphs().front().eraseChars(dit.pos(), psize, false);
tail.paragraphs().front().eraseChars(0,
dit.pos() < psize ? dit.pos() + 1 : psize, false);
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;
}
Tabular::idx_type Tabular::getLastCellInRow(row_type row) const
{
col_type c = ncols() - 1;
+ // 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))
}
-Tabular::idx_type Tabular::setMultiColumn(idx_type cell, idx_type number)
+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);
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) {
CellData & cs1 = cellInfo(cell + i);
}
-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)
{
idx_type const col = cellColumn(cell);
idx_type const row = cellRow(cell);
// this feature would be a fileformat change
// until LyX supports this, use the deault alignment of multirow
// cells: left
- cs.alignment = LYX_ALIGN_LEFT;
+ 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];
{
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);
// 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;
}
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];
}
|| (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).get(), align_d);
+ ismulticol |= !dit;
+ }
// up counter by 1 for each decimally aligned col since they use 2 latex cols
int latexcolspan = columnSpan(cell);
? 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.setBuffer(buffer());
head.setMacrocontextPositionRecursive(dit);
bool hassep = false;
InsetTableCell tail = splitCell(head, column_info[c].decimal_point, hassep);
- tail.setBuffer(head.buffer());
- dit.pop_back();
- dit.push_back(CursorSlice(tail));
- tail.setMacrocontextPositionRecursive(dit);
head.latex(os, newrp);
- os << '&';
- tail.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);
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;
if (isMultiColumn(cell))
attr << " colspan='" << columnSpan(cell) << "'";
+ else if (isMultiRow(cell))
+ attr << " rowspan='" << rowSpan(cell) << "'";
xs << html::StartTag(celltag, attr.str()) << html::CR();
ret += cellInset(cell)->xhtml(xs, runparams);
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.
}
-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.
}
-docstring InsetTabular::contextMenuName() const
+string InsetTabular::contextMenuName() const
{
- return from_ascii("context-tabular");
+ return "context-tabular";
}
// remove text leading decimal point
docstring const align_d = tabular.column_info[c].decimal_point;
- dit = doc_iterator_begin(&tail.buffer(), &tail);
- for (; dit; dit.forwardChar())
- if (dit.inTexted() && dit.depth()==1
- && dit.paragraph().find(align_d, false, false, dit.pos()))
- break;
+ dit = separatorPos(&tail, align_d);
pit_type const psize = tail.paragraphs().front().size();
if (dit) {
// 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
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);
}
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;
}
// 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()));
break;
}
// we have a selection so this means we just add all this
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()));
cur.pit() = 0;
cur.pos() = 0;
cur.setSelection(false);
}
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;
}