OK, here's my attempt once again to fix bug 2178. I've tested this a bit, but I'm not an extensive user of tables, so I'm sure there are bugs here. But the general idea seems to work.
Note that this is intended to be a "minimal patch", involving as few changes as possible to the existing code. It may well be that there are better ways to do this, longer term, but I am NOT about to start messing with the InsetTabular code in any serious way. The list of names at the start of InsetTabular.cpp is enough to scare me off for good. ;-)
Comments welcome. rh
Index: src/insets/InsetTableCell.h =================================================================== --- src/insets/InsetTableCell.h (revision 0) +++ src/insets/InsetTableCell.h (revision 0) @@ -0,0 +1,60 @@ +// -*- C++ -*- +/** + * \file InsetTableCell.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Richard Heck + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef INSETTABLECELL_H +#define INSETTABLECELL_H + +#include "InsetTabular.h" +#include "InsetText.h" +#include <boost/assert.hpp> + +namespace lyx { + + +/// +class InsetTableCell : public InsetText { +public: + /// + explicit InsetTableCell(Buffer const & buf, + Tabular::CellData const * cd, Tabular const * t); + /// + virtual InsetCode lyxCode() const { return CELL_CODE; } + /// + Inset * clone() { return new InsetTableCell(*this); } + /// + virtual bool useEmptyLayout() const { return true; } + /// + virtual bool forceEmptyLayout(idx_type = 0) const; + /// + virtual bool allowParagraphCustomization(idx_type = 0) const; + /// + bool getStatus(Cursor & cur, FuncRequest const & cmd, + FuncStatus & status) const; + /// + virtual bool neverIndent() { return true; } + /// + void setCellData(Tabular::CellData const * cd) { cell_data_ = cd; } + /// + void setTabular(Tabular const * t) { table_ = t; } +private: + /// + Tabular::CellData const * cell_data_; + /// + Tabular const * table_; + /// unimplemented + InsetTableCell(); + /// unimplemented + void operator=(InsetTableCell const &); +}; + +} // namespace lyx + +#endif Index: src/insets/InsetTableCell.cpp =================================================================== --- src/insets/InsetTableCell.cpp (revision 0) +++ src/insets/InsetTableCell.cpp (revision 0) @@ -0,0 +1,61 @@ +/** + * \file InsetTableCell.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Richard Heck + * + * Full author contact details are available in file CREDITS. + */ + +#include <config.h> + +#include "InsetTableCell.h" + +#include "FuncRequest.h" +#include "FuncStatus.h" +#include "InsetTabular.h" + +#include <boost/assert.hpp> + +namespace lyx { + +InsetTableCell::InsetTableCell(Buffer const & buf, + Tabular::CellData const * cell, Tabular const * table) + : InsetText(buf), cell_data_(cell), table_(table) +{} + + +bool InsetTableCell::forceEmptyLayout(idx_type) const +{ + BOOST_ASSERT(table_); + BOOST_ASSERT(cell_data_); + return !table_->getPWidth(cell_data_->cellno).zero(); +} + +bool InsetTableCell::allowParagraphCustomization(idx_type) const +{ + BOOST_ASSERT(table_); + BOOST_ASSERT(cell_data_); + return !table_->getPWidth(cell_data_->cellno).zero(); +} + +bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd, + FuncStatus & status) const +{ + bool enabled; + switch (cmd.action) { + case LFUN_LAYOUT: + enabled = !forceEmptyLayout(); + break; + case LFUN_LAYOUT_PARAGRAPH: + enabled = allowParagraphCustomization(); + break; + default: + return InsetText::getStatus(cur, cmd, status); + } + status.enabled(enabled); + return true; +} + +} // namespace lyx Index: src/insets/InsetTabular.h =================================================================== --- src/insets/InsetTabular.h (revision 23858) +++ src/insets/InsetTabular.h (working copy) @@ -4,7 +4,6 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Jürgen Vigna * \author Lars Gullik Bjønnes * \author Matthias Ettrich * \author André Pönitz @@ -49,14 +48,15 @@ namespace lyx { -class FuncStatus; -class Lexer; -class BufferView; class Buffer; class BufferParams; -class Paragraph; +class BufferView; class CompletionList; class CursorSlice; +class InsetTableCell; +class FuncStatus; +class Lexer; +class Paragraph; namespace frontend { class Painter; } @@ -65,8 +65,6 @@ class Cursor; class OutputParams; -typedef InsetText InsetTableCell; - // // A helper struct for tables // @@ -467,7 +465,7 @@ class CellData { public: /// - CellData(Buffer const &); + CellData(Buffer const &, Tabular const &); /// CellData(CellData const &); /// Index: src/insets/InsetTabular.cpp =================================================================== --- src/insets/InsetTabular.cpp (revision 23858) +++ src/insets/InsetTabular.cpp (working copy) @@ -3,7 +3,6 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Jürgen Vigna * \author Lars Gullik Bjønnes * \author Matthias Ettrich * \author José Matos @@ -31,6 +30,7 @@ #include "DispatchResult.h" #include "FuncRequest.h" #include "FuncStatus.h" +#include "InsetTableCell.h" #include "Language.h" #include "LaTeXFeatures.h" #include "Lexer.h" @@ -470,7 +470,7 @@ ///////////////////////////////////////////////////////////////////// -Tabular::CellData::CellData(Buffer const & buf) +Tabular::CellData::CellData(Buffer const & buf, Tabular const & table) : cellno(0), width(0), multicolumn(Tabular::CELL_NORMAL), @@ -482,7 +482,7 @@ right_line(false), usebox(BOX_NONE), rotate(false), - inset(new InsetTableCell(buf)) + inset(new InsetTableCell(buf, this, &table)) { inset->setBuffer(const_cast<Buffer &>(buf)); inset->paragraphs().back().setLayout(buf.params().documentClass().emptyLayout()); @@ -503,8 +503,10 @@ rotate(cs.rotate), align_special(cs.align_special), p_width(cs.p_width), - inset(dynamic_cast<InsetTableCell*>(cs.inset->clone())) -{} + inset(dynamic_cast<InsetTableCell *>(cs.inset->clone())) +{ + inset->setCellData(this); +} Tabular::CellData & Tabular::CellData::operator=(CellData cs) @@ -581,7 +583,7 @@ 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))); + cell_info = cell_vvector(rows_arg, cell_vector(columns_arg, CellData(buf, *this))); row_info.reserve(10); column_info.reserve(10); cell_info.reserve(100); @@ -628,7 +630,7 @@ 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(), *this))); for (row_type i = 0; i <= row; ++i) swap(cell_info[i], old[i]); @@ -678,7 +680,7 @@ column_info[column + 1] = column_info[column]; for (row_type i = 0; i < rowCount(); ++i) { - cell_info[i].insert(cell_info[i].begin() + column + 1, CellData(buffer())); + cell_info[i].insert(cell_info[i].begin() + column + 1, CellData(buffer(), *this)); col_type c = column + 2; while (c < ncols && cell_info[i][c].multicolumn == CELL_PART_OF_MULTICOLUMN) { @@ -760,8 +762,8 @@ do { ++column; } while (column < columnCount() && - cell_info[row][column].multicolumn - == Tabular::CELL_PART_OF_MULTICOLUMN); + cell_info[row][column].multicolumn + == Tabular::CELL_PART_OF_MULTICOLUMN); if (column == columnCount()) { column = 0; @@ -2759,7 +2761,11 @@ void Tabular::setCellInset(row_type row, col_type column, shared_ptr<InsetTableCell> ins) const { - cell_info[row][column].inset = ins; + CellData & cd = cell_info[row][column]; + cd.inset = ins; + // reset the InsetTableCell's pointers + ins->setCellData(&cd); + ins->setTabular(this); } @@ -4554,6 +4560,15 @@ while (paste_tabular->columnCount() > columns) paste_tabular->deleteColumn(columns); + // We clear all the InsetTableCell pointers, since they + // might now become invalid and there is no point in having + // them point to temporary things in paste_tabular. + for (row_type i = 0; i < paste_tabular->rowCount(); ++i) + for (col_type j = 0; j < paste_tabular->columnCount(); ++j) { + paste_tabular->getCellInset(i,j)->setCellData(0); + paste_tabular->getCellInset(i,j)->setTabular(0); + } + odocstringstream os; OutputParams const runparams(0); paste_tabular->plaintext(os, runparams, 0, true, '\t'); @@ -4595,6 +4610,8 @@ } shared_ptr<InsetTableCell> inset( new InsetTableCell(*paste_tabular->getCellInset(r1, c1))); + // note that setCellInset will call InsetTableCell::setCellData() + // and InsetTableCell::setTabular() tabular.setCellInset(r2, c2, inset); // FIXME: change tracking (MG) inset->setChange(Change(cur.buffer().params().trackChanges ? Index: src/insets/InsetCode.h =================================================================== --- src/insets/InsetCode.h (revision 23858) +++ src/insets/InsetCode.h (working copy) @@ -112,6 +112,8 @@ INFO_CODE, // 45 /// COLLAPSABLE_CODE, + /// + CELL_CODE, #if 0 /// THEOREM_CODE, Index: src/insets/InsetText.h =================================================================== --- src/insets/InsetText.h (revision 23858) +++ src/insets/InsetText.h (working copy) @@ -130,10 +130,6 @@ /// bool allowSpellCheck() const { return true; } /// - bool isTableCell() const; - /// should paragraph indendation be ommitted in any case? - bool neverIndent() const; - /// virtual bool isMacroScope() const { return false; } /// virtual bool allowMultiPar() const { return true; } Index: src/insets/InsetText.cpp =================================================================== --- src/insets/InsetText.cpp (revision 23858) +++ src/insets/InsetText.cpp (working copy) @@ -412,22 +412,6 @@ } -// FIXME: instead of this hack, which only works by chance, -// cells should have their own insetcell type, which returns CELL_CODE! -bool InsetText::isTableCell() const -{ - // this is only true for tabular cells - return !text_.isMainText(buffer()) && lyxCode() == TEXT_CODE; -} - - - -bool InsetText::neverIndent() const -{ - return isTableCell(); -} - - ParagraphList const & InsetText::paragraphs() const { return text_.paragraphs(); Index: src/insets/Inset.cpp =================================================================== --- src/insets/Inset.cpp (revision 23858) +++ src/insets/Inset.cpp (working copy) @@ -105,6 +105,7 @@ InsetName("info", INFO_CODE), InsetName("collapsable", COLLAPSABLE_CODE), InsetName("newpage", NEWPAGE_CODE), + InsetName("tablecell", CELL_CODE) }; size_t const insetnames_size = Index: src/Paragraph.cpp =================================================================== --- src/Paragraph.cpp (revision 23858) +++ src/Paragraph.cpp (working copy) @@ -48,8 +48,6 @@ #include "insets/InsetBibitem.h" #include "insets/InsetLabel.h" -// needed only for inTableCell() -#include "insets/InsetText.h" #include "support/convert.h" #include "support/debug.h" @@ -1621,7 +1619,6 @@ Inset const * const inset = inInset(); if (!inset) return true; - // FIXME At present, this is wrong for table cells return inset->forceEmptyLayout(); } @@ -1631,36 +1628,16 @@ Inset const * const inset = inInset(); if (!inset) return true; - // FIXME At present, this is wrong for table cells return inset->allowParagraphCustomization(); } -namespace { - // FIXME - // This is a hack based upon one in InsetText::neverIndent(). - // When we have a real InsetTableCell, then we won't need this - // method, because InsetTableCell will return the right values, - // viz: InsetTableCell::useEmptyLayout() should return true, and - // InsetTableCell::forceEmptyLayout() should still return true - // unless the width has been set. - // - // The #include "insets/InsetText.h" can also be removed then. - bool inTableCell(Inset const * inset) - { - InsetText const * txt = inset->asInsetText(); - if (!txt) - return false; - return txt->isTableCell(); - } -} - - bool Paragraph::useEmptyLayout() const { Inset const * const inset = inInset(); - return inset && - (inTableCell(inset) || inset->useEmptyLayout()); + if (!inset) + return false; + return inset->useEmptyLayout(); } Index: src/DocIterator.cpp =================================================================== --- src/DocIterator.cpp (revision 23858) +++ src/DocIterator.cpp (working copy) @@ -22,6 +22,7 @@ #include "mathed/InsetMath.h" #include "insets/InsetTabular.h" +#include "insets/InsetTableCell.h" #include "support/debug.h" Index: src/Makefile.am =================================================================== --- src/Makefile.am (revision 23858) +++ src/Makefile.am (working copy) @@ -522,6 +522,7 @@ insets/InsetRef.cpp \ insets/InsetSpace.cpp \ insets/InsetSpecialChar.cpp \ + insets/InsetTableCell.cpp \ insets/InsetTabular.cpp \ insets/InsetText.cpp \ insets/InsetTOC.cpp \ @@ -577,6 +578,7 @@ insets/InsetRef.h \ insets/InsetSpace.h \ insets/InsetSpecialChar.h \ + insets/InsetTableCell.h \ insets/InsetTabular.h \ insets/InsetText.h \ insets/InsetTOC.h \