]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
* InsetTabular.{cpp, h}:
[lyx.git] / src / insets / InsetTabular.cpp
index 611e29f01b5a9a691b3c76ada4d1a9d98822665a..e8db353e8e75135fa53c48e2b7948425cabac7b6 100644 (file)
@@ -38,6 +38,7 @@
 #include "LyXRC.h"
 #include "MetricsInfo.h"
 #include "OutputParams.h"
+#include "output_xhtml.h"
 #include "Paragraph.h"
 #include "ParagraphParameters.h"
 #include "ParIterator.h"
@@ -514,7 +515,7 @@ string const featureAsString(Tabular::Feature feature)
 /////////////////////////////////////////////////////////////////////
 
 
-Tabular::CellData::CellData(Buffer & buf)
+Tabular::CellData::CellData(Buffer * buf)
        : cellno(0),
          width(0),
          multicolumn(Tabular::CELL_NORMAL),
@@ -528,7 +529,7 @@ Tabular::CellData::CellData(Buffer & buf)
          rotate(false),
          inset(new InsetTableCell(buf))
 {
-       inset->setBuffer(const_cast<Buffer &>(buf));
+       inset->setBuffer(*buf);
 }
 
 
@@ -548,7 +549,6 @@ Tabular::CellData::CellData(CellData const & cs)
          p_width(cs.p_width),
          inset(dynamic_cast<InsetTableCell *>(cs.inset->clone()))
 {
-       inset->setBuffer(cs.inset->buffer());
 }
 
 Tabular::CellData & Tabular::CellData::operator=(CellData cs)
@@ -606,7 +606,7 @@ Tabular::ltType::ltType()
 {}
 
 
-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);
 }
@@ -625,10 +625,10 @@ void Tabular::setBuffer(Buffer & buffer)
 
 
 // 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)));
@@ -657,7 +657,7 @@ void Tabular::init(Buffer & buf, row_type rows_arg,
 
 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;
@@ -672,7 +672,7 @@ void Tabular::appendRow(idx_type const cell)
        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]);
@@ -734,7 +734,7 @@ void Tabular::appendColumn(idx_type const cell)
 
        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.
@@ -803,6 +803,7 @@ void Tabular::copyColumn(col_type const column)
 
 void Tabular::updateIndexes()
 {
+       setBuffer(buffer());
        col_type ncols = column_info.size();
        row_type nrows = row_info.size();
        numberofcells = 0;
@@ -1422,7 +1423,7 @@ void Tabular::read(Lexer & lex)
        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"
@@ -1800,8 +1801,6 @@ Tabular::idx_type Tabular::setLTCaption(row_type row, bool what)
                unsetMultiColumn(i);
                // When unsetting a caption row, also all existing
                // captions in this row must be dissolved.
-               lyx::dispatch(FuncRequest(LFUN_LINE_BEGIN));
-               lyx::dispatch(FuncRequest(LFUN_INSET_DISSOLVE, "caption"));
        }
        row_info[row].caption = what;
        return i;
@@ -2634,6 +2633,74 @@ int Tabular::docbook(odocstream & os, OutputParams const & runparams) const
 }
 
 
+docstring Tabular::xhtmlRow(XHTMLStream & xs, row_type row,
+                          OutputParams const & runparams) const
+{
+       docstring ret;
+       idx_type cell = getFirstCellInRow(row);
+
+       xs << html::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 << html::StartTag("td", attr.str());
+               ret += cellInset(cell)->xhtml(xs, runparams);
+               xs << html::EndTag("td");
+               ++cell;
+       }
+       xs << html::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 << html::StartTag("tbody");
+       for (row_type i = 0; i < row_info.size(); ++i) {
+               if (isValidRow(i)) {
+                       ret += xhtmlRow(xs, i, runparams);
+               }
+       }
+       xs << html::EndTag("tbody");
+       return ret;
+}
+
+
 bool Tabular::plaintextTopHLine(odocstream & os, row_type row,
                                   vector<unsigned int> const & clen) const
 {
@@ -2903,7 +2970,7 @@ Tabular::BoxType Tabular::useParbox(idx_type cell) const
 //
 /////////////////////////////////////////////////////////////////////
 
-InsetTableCell::InsetTableCell(Buffer & buf)
+InsetTableCell::InsetTableCell(Buffer * buf)
        : InsetText(buf, InsetText::PlainLayout), isFixedWidth(false),
          contentAlign(LYX_ALIGN_CENTER)
 {}
@@ -2958,6 +3025,14 @@ docstring InsetTableCell::asString(bool intoInsets)
 }
 
 
+docstring InsetTableCell::xhtml(XHTMLStream & xs, OutputParams const & rp) const
+{
+       if (!isFixedWidth)
+               return InsetText::insetAsXHTML(xs, rp, InsetText::JustText);
+       return InsetText::xhtml(xs, rp);
+}
+
+
 
 /////////////////////////////////////////////////////////////////////
 //
@@ -2965,12 +3040,11 @@ docstring InsetTableCell::asString(bool intoInsets)
 //
 /////////////////////////////////////////////////////////////////////
 
-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
 }
 
 
@@ -3317,13 +3391,14 @@ void InsetTabular::edit(Cursor & cur, bool front, EntryDirection)
                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, UpdateType utype)
 {
        // In a longtable, tell captions what the current float is
        Counters & cnts = buffer().masterBuffer()->params().documentClass().counters();
@@ -3335,7 +3410,7 @@ void InsetTabular::updateLabels(ParIterator const & it)
        it2.forwardPos();
        size_t const end = it2.nargs();
        for ( ; it2.idx() < end; it2.top().forwardIdx())
-               buffer().updateLabels(it2);
+               buffer().updateLabels(it2, utype);
 
        //reset afterwards
        if (tabular.is_long_tabular)
@@ -3343,6 +3418,16 @@ void InsetTabular::updateLabels(ParIterator const & it)
 }
 
 
+void InsetTabular::addToToc(DocIterator const & cpit)
+{
+       DocIterator dit = cpit;
+       dit.forwardPos();
+       size_t const end = dit.nargs();
+       for ( ; dit.idx() < end; dit.top().forwardIdx())
+               cell(dit.idx())->addToToc(cpit);
+}
+
+
 void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 {
        LYXERR(Debug::DEBUG, "# InsetTabular::doDispatch: cmd: " << cmd
@@ -3567,6 +3652,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                                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()) {
@@ -3578,6 +3664,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                if (cur.selIsMultiCell()) {
                        cur.pit() = cur.lastpit();
                        cur.pos() = cur.lastpos();
+                       cur.setCurrentFont();
                        return;
                }
                break;
@@ -3600,6 +3687,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                                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()) {
@@ -3609,6 +3697,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                if (cur.selIsMultiCell()) {
                        cur.pit() = 0;
                        cur.pos() = cur.lastpos();
+                       cur.setCurrentFont();
                        return;
                }
                break;
@@ -4221,9 +4310,29 @@ int InsetTabular::docbook(odocstream & os, OutputParams const & runparams) const
 }
 
 
+docstring InsetTabular::xhtml(XHTMLStream & xs, OutputParams const & rp) const
+{
+       // FIXME XHTML
+       // It'd be better to be able to get this from an InsetLayout, but at present
+       // InsetLayouts do not seem really to work for things that aren't InsetTexts.
+       xs << html::StartTag("table");
+       docstring ret = tabular.xhtml(xs, rp);
+       xs << html::EndTag("table");
+       return ret;
+}
+
+
 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>");
 }
 
 
@@ -4426,7 +4535,7 @@ void InsetTabular::moveNextCell(Cursor & cur, EntryDirection entry_from)
                break;
 
        }
-
+       cur.setCurrentFont();
        resetPos(cur);
 }
 
@@ -4476,7 +4585,7 @@ void InsetTabular::movePrevCell(Cursor & cur, EntryDirection entry_from)
                break;
 
        }
-
+       cur.setCurrentFont();
        resetPos(cur);
 }
 
@@ -4764,6 +4873,14 @@ void InsetTabular::tabularFeatures(Cursor & 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;
 
@@ -4877,15 +4994,22 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                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;
        }
 
@@ -5212,7 +5336,7 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
        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);
@@ -5277,13 +5401,19 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
 }
 
 
-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);
+               }
        }
 }