* \author John Levon
* \author André Pönitz
* \author Jürgen Vigna
+ * \author Uwe Stöhr
*
* Full author contact details are available in file CREDITS.
*/
#include "LyXRC.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
-#include "paragraph_funcs.h"
+#include "output_xhtml.h"
#include "Paragraph.h"
#include "ParagraphParameters.h"
#include "ParIterator.h"
/////////////////////////////////////////////////////////////////////
-Tabular::CellData::CellData(Buffer & buf)
+Tabular::CellData::CellData(Buffer * buf)
: cellno(0),
width(0),
multicolumn(Tabular::CELL_NORMAL),
rotate(false),
inset(new InsetTableCell(buf))
{
- inset->setBuffer(const_cast<Buffer &>(buf));
+ inset->setBuffer(*buf);
}
{}
-Tabular::Tabular(Buffer & buffer, row_type rows_arg, col_type columns_arg)
+Tabular::Tabular(Buffer * buffer, row_type rows_arg, col_type columns_arg)
{
init(buffer, rows_arg, columns_arg);
}
// activates all lines and sets all widths to 0
-void Tabular::init(Buffer & buf, row_type rows_arg,
+void Tabular::init(Buffer * buf, row_type rows_arg,
col_type columns_arg)
{
- buffer_ = &buf;
+ buffer_ = buf;
row_info = row_vector(rows_arg);
column_info = column_vector(columns_arg);
cell_info = cell_vvector(rows_arg, cell_vector(columns_arg, CellData(buf)));
void Tabular::appendRow(idx_type const cell)
{
- BufferParams const & bp = buffer().params();
+ BufferParams const & bp = buffer_->params();
row_type const row = cellRow(cell);
row_vector::iterator rit = row_info.begin() + row;
for (row_type i = 0; i < nrows - 1; ++i)
swap(cell_info[i], old[i]);
- cell_info = cell_vvector(nrows, cell_vector(ncols, CellData(buffer())));
+ cell_info = cell_vvector(nrows, cell_vector(ncols, CellData(buffer_)));
for (row_type i = 0; i <= row; ++i)
swap(cell_info[i], old[i]);
for (row_type r = 0; r < nrows; ++r) {
cell_info[r].insert(cell_info[r].begin() + c + 1,
- CellData(buffer()));
+ CellData(buffer_));
#if 0
// FIXME: This code does not work. It deletes the cell's content and
// it triggers an assertion if the cursor is at pos > 0.
void Tabular::updateIndexes()
{
+ setBuffer(buffer());
col_type ncols = column_info.size();
row_type nrows = row_info.size();
numberofcells = 0;
// reset layout
cur.push(*inset);
// undo information has already been recorded
- inset->getText(0)->setLayout(cur.bv().buffer(), 0, cur.lastpit() + 1,
+ inset->getText(0)->setLayout(0, cur.lastpit() + 1,
bp.documentClass().plainLayoutName());
cur.pop();
}
int columns_arg;
if (!getTokenValue(line, "columns", columns_arg))
return;
- init(buffer(), rows_arg, columns_arg);
+ init(buffer_, rows_arg, columns_arg);
l_getline(is, line);
if (!prefixIs(line, "<features")) {
lyxerr << "Wrong tabular format (expected <features ...> got"
setRightLine(i, false);
} else {
unsetMultiColumn(i);
- // FIXME: when unsetting a caption row, also all existing captions
- // in this row must be dissolved, see (bug 5754)
- // dispatch(FuncRequest(LFUN_INSET_DISSOLVE, "caption-insert"));
+ // When unsetting a caption row, also all existing
+ // captions in this row must be dissolved.
}
row_info[row].caption = what;
return i;
}
+docstring Tabular::xhtmlRow(XHTMLStream & xs, row_type row,
+ OutputParams const & runparams) const
+{
+ docstring ret;
+ idx_type cell = getFirstCellInRow(row);
+
+ xs << StartTag("tr");
+ for (col_type j = 0; j < column_info.size(); ++j) {
+ if (isPartOfMultiColumn(row, j))
+ continue;
+
+ stringstream attr;
+ attr << "align='";
+ switch (getAlignment(cell)) {
+ case LYX_ALIGN_LEFT:
+ attr << "left";
+ break;
+ case LYX_ALIGN_RIGHT:
+ attr << "right";
+ break;
+ default:
+ attr << "center";
+ break;
+ }
+ attr << "'";
+ attr << " valign='";
+ switch (getVAlignment(cell)) {
+ case LYX_VALIGN_TOP:
+ attr << "top";
+ break;
+ case LYX_VALIGN_BOTTOM:
+ attr << "bottom";
+ break;
+ case LYX_VALIGN_MIDDLE:
+ attr << "middle";
+ }
+ attr << "'";
+
+ if (isMultiColumn(cell))
+ attr << " colspan='" << columnSpan(cell) << "'";
+
+ xs << StartTag("td", attr.str());
+ ret += cellInset(cell)->xhtml(xs, runparams);
+ xs << EndTag("td");
+ ++cell;
+ }
+ xs << EndTag("tr");
+ return ret;
+}
+
+
+docstring Tabular::xhtml(XHTMLStream & xs, OutputParams const & runparams) const
+{
+ docstring ret;
+ // It's unclear to me if we need to mess with the long table stuff.
+ // We can borrow that too from docbook, if so.
+
+ xs << StartTag("tbody");
+ for (row_type i = 0; i < row_info.size(); ++i) {
+ if (isValidRow(i)) {
+ ret += xhtmlRow(xs, i, runparams);
+ }
+ }
+ xs << EndTag("tbody");
+ return ret;
+}
+
+
bool Tabular::plaintextTopHLine(odocstream & os, row_type row,
vector<unsigned int> const & clen) const
{
//
/////////////////////////////////////////////////////////////////////
-InsetTableCell::InsetTableCell(Buffer & buf)
+InsetTableCell::InsetTableCell(Buffer * buf)
: InsetText(buf, InsetText::PlainLayout), isFixedWidth(false),
contentAlign(LYX_ALIGN_CENTER)
{}
}
+docstring InsetTableCell::xhtml(XHTMLStream & xs, OutputParams const & rp) const
+{
+ if (!isFixedWidth)
+ return InsetText::insetAsXHTML(xs, rp, InsetText::JustText);
+ return InsetText::xhtml(xs, rp);
+}
+
+
/////////////////////////////////////////////////////////////////////
//
//
/////////////////////////////////////////////////////////////////////
-InsetTabular::InsetTabular(Buffer & buf, row_type rows,
+InsetTabular::InsetTabular(Buffer * buf, row_type rows,
col_type columns)
- : tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))), scx_(0),
+ : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))), scx_(0),
rowselect_(false), colselect_(false)
{
- setBuffer(buf); // FIXME: remove later
}
}
-docstring InsetTabular::editMessage() const
-{
- return _("Opened table");
-}
-
-
void InsetTabular::edit(Cursor & cur, bool front, EntryDirection)
{
//lyxerr << "InsetTabular::edit: " << this << endl;
cur.pit() = 0;
cur.pos() = cur.lastpos(); // FIXME crude guess
}
+ cur.setCurrentFont();
// FIXME: this accesses the position cache before it is initialized
//resetPos(cur);
//cur.bv().fitCursor();
}
-void InsetTabular::updateLabels(ParIterator const & it)
+void InsetTabular::updateLabels(ParIterator const & it, bool out)
{
// In a longtable, tell captions what the current float is
Counters & cnts = buffer().masterBuffer()->params().documentClass().counters();
it2.forwardPos();
size_t const end = it2.nargs();
for ( ; it2.idx() < end; it2.top().forwardIdx())
- buffer().updateLabels(it2);
+ buffer().updateLabels(it2, out);
//reset afterwards
if (tabular.is_long_tabular)
&& cur.pos() == cur.lastpos())
|| (!next_cell && cur.pit() == 0 && cur.pos() == 0));
+ bool const empty_cell = cur.lastpos() == 0 && cur.lastpit() == 0;
+
// ...try to dispatch to the cell's inset.
cell(cur.idx())->dispatch(cur, cmd);
- bool const empty_cell = cur.lastpos() == 0 && cur.lastpit() == 0;
-
// When we already have a selection we want to select the whole cell
// before going to the next cell.
if (select_whole && !empty_cell){
TextMetrics const & tm =
cur.bv().textMetrics(cell(cur.idx())->getText(0));
cur.pos() = tm.x2pos(cur.pit(), 0, cur.targetX());
+ cur.setCurrentFont();
}
}
if (sl == cur.top()) {
if (cur.selIsMultiCell()) {
cur.pit() = cur.lastpit();
cur.pos() = cur.lastpos();
+ cur.setCurrentFont();
return;
}
break;
ParagraphMetrics const & pm =
tm.parMetrics(cur.lastpit());
cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, cur.targetX());
+ cur.setCurrentFont();
}
}
if (sl == cur.top()) {
if (cur.selIsMultiCell()) {
cur.pit() = 0;
cur.pos() = cur.lastpos();
+ cur.setCurrentFont();
return;
}
break;
}
+docstring InsetTabular::xhtml(XHTMLStream & xs, OutputParams const & rp) const
+{
+ // FIXME XHTML
+ // It'd be better to be able to get this from an InsetLayout, but at present
+ // InsetLayouts do not seem really to work for things that aren't InsetTexts.
+ xs << StartTag("table");
+ docstring ret = tabular.xhtml(xs, rp);
+ xs << EndTag("table");
+ return ret;
+}
+
+
void InsetTabular::validate(LaTeXFeatures & features) const
{
tabular.validate(features);
+ // FIXME XHTML
+ // It'd be better to be able to get this from an InsetLayout, but at present
+ // InsetLayouts do not seem really to work for things that aren't InsetTexts.
+ if (features.runparams().flavor == OutputParams::HTML)
+ features.addPreambleSnippet("<style type=\"text/css\">\n"
+ "table { border: 1px solid black; display: inline-block; }\n"
+ "td { border: 1px solid black; padding: 0.5ex; }\n"
+ "</style>");
}
break;
}
-
+ cur.setCurrentFont();
resetPos(cur);
}
break;
}
-
+ cur.setCurrentFont();
resetPos(cur);
}
break;
case Tabular::UNSET_LONGTABULAR:
+ for (row_type i = 0; i < tabular.row_info.size(); ++i) {
+ if (tabular.ltCaption(i)) {
+ cur.idx() = tabular.cellIndex(i, 0);
+ cur.pit() = 0;
+ cur.pos() = 0;
+ tabularFeatures(cur, Tabular::TOGGLE_LTCAPTION);
+ }
+ }
tabular.is_long_tabular = false;
break;
break;
case Tabular::TOGGLE_LTCAPTION: {
- bool set = !tabular.ltCaption(row);
+ bool const set = !tabular.ltCaption(row);
cur.idx() = tabular.setLTCaption(row, set);
cur.pit() = 0;
cur.pos() = 0;
cur.setSelection(false);
- // When a row is set as caption, then also insert a caption. Otherwise
- // the LaTeX output is broken, when the user doesn't add a caption.
- if (set)
+
+ if (set) {
+ // When a row is set as caption, then also insert
+ // a caption. Otherwise the LaTeX output is broken.
+ lyx::dispatch(FuncRequest(LFUN_INSET_SELECT_ALL));
lyx::dispatch(FuncRequest(LFUN_CAPTION_INSERT));
+ } else {
+ FuncRequest fr(LFUN_INSET_DISSOLVE, "caption");
+ if (lyx::getStatus(fr).enabled())
+ lyx::dispatch(fr);
+ }
break;
}
}
-void InsetTabular::acceptChanges(BufferParams const & bparams)
+void InsetTabular::acceptChanges()
{
for (idx_type idx = 0; idx < nargs(); ++idx)
- cell(idx)->acceptChanges(bparams);
+ cell(idx)->acceptChanges();
}
-void InsetTabular::rejectChanges(BufferParams const & bparams)
+void InsetTabular::rejectChanges()
{
for (idx_type idx = 0; idx < nargs(); ++idx)
- cell(idx)->rejectChanges(bparams);
+ cell(idx)->rejectChanges();
}
col_type ocol = 0;
row_type row = 0;
if (usePaste) {
- paste_tabular.reset(new Tabular(buffer(), rows, maxCols));
+ paste_tabular.reset(new Tabular(buffer_, rows, maxCols));
loctab = paste_tabular.get();
cols = 0;
dirtyTabularStack(true);
}
-void InsetTabular::addPreview(PreviewLoader & loader) const
+void InsetTabular::addPreview(DocIterator const & inset_pos,
+ PreviewLoader & loader) const
{
row_type const rows = tabular.row_info.size();
col_type const columns = tabular.column_info.size();
+ DocIterator cell_pos = inset_pos;
+
+ cell_pos.push_back(CursorSlice(*const_cast<InsetTabular *>(this)));
for (row_type i = 0; i < rows; ++i) {
- for (col_type j = 0; j < columns; ++j)
- tabular.cellInset(i, j)->addPreview(loader);
+ for (col_type j = 0; j < columns; ++j) {
+ cell_pos.top().idx() = tabular.cellIndex(i, j);
+ tabular.cellInset(i, j)->addPreview(cell_pos, loader);
+ }
}
}