};
-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
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];
}
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";
}
cur.bv().showDialog("tabular");
break;
- case LFUN_INSET_MODIFY:
- if (!tabularFeatures(cur, to_utf8(cmd.argument())))
+ case LFUN_INSET_MODIFY: {
+ string arg;
+ if (cmd.getArg(1) == "from-dialog")
+ arg = cmd.getArg(0) + to_utf8(cmd.argument().substr(19));
+ else
+ arg = to_utf8(cmd.argument());
+ if (!tabularFeatures(cur, arg))
cur.undispatched();
break;
+ }
// insert file functions
case LFUN_FILE_INSERT_PLAINTEXT_PARA:
// 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("<style type=\"text/css\">\n"
- "table { border: 1px solid black; display: inline-block; }\n"
- "td { border: 1px solid black; padding: 0.5ex; }\n"
- "</style>");
+ features.addCSSSnippet(
+ "table { border: 1px solid black; display: inline-block; }\n"
+ "td { border: 1px solid black; padding: 0.5ex; }");
}
// 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;
}