diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx index 0ae169ce4431..d7fbf74ef58a 100644 --- a/sd/qa/unit/misc-tests.cxx +++ b/sd/qa/unit/misc-tests.cxx @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -82,6 +84,7 @@ public: void testTdf130988(); void testTdf131033(); void testTdf129898LayerDrawnInSlideshow(); + void testTdf136956(); CPPUNIT_TEST_SUITE(SdMiscTest); CPPUNIT_TEST(testTdf96206); @@ -103,6 +106,7 @@ public: CPPUNIT_TEST(testTdf130988); CPPUNIT_TEST(testTdf131033); CPPUNIT_TEST(testTdf129898LayerDrawnInSlideshow); + CPPUNIT_TEST(testTdf136956); CPPUNIT_TEST_SUITE_END(); virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override @@ -874,6 +878,37 @@ void SdMiscTest::testTdf129898LayerDrawnInSlideshow() xDocShRef->DoClose(); } +void SdMiscTest::testTdf136956() +{ + ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc(u"sd/qa/unit/data/odp/cellspan.odp"), ODP); + + const SdrPage *pPage = GetPage( 1, xDocShRef ); + sdr::table::SdrTableObj *pTableObj = dynamic_cast(pPage->GetObj(0)); + CPPUNIT_ASSERT( pTableObj ); + uno::Reference< table::XTable > xTable(pTableObj->getTable(), uno::UNO_SET_THROW); + + uno::Reference< css::table::XMergeableCellRange > xRange( + xTable->createCursorByRange( xTable->getCellRangeByPosition( 0, 0, 3, 2 ) ), uno::UNO_QUERY_THROW ); + + // 4x3 Table before merge. + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getColumnCount()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRowCount()); + + xRange->merge(); + + // 1x1 Table after merge. + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getColumnCount()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRowCount()); + + xDocShRef->GetUndoManager()->Undo(); + + // 4x3 Table after undo. Undo crashed before. + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getColumnCount()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRowCount()); + + xDocShRef->DoClose(); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdMiscTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/svx/source/table/tablemodel.cxx b/svx/source/table/tablemodel.cxx index 6efcbd1280dc..a6d21f3935db 100644 --- a/svx/source/table/tablemodel.cxx +++ b/svx/source/table/tablemodel.cxx @@ -694,24 +694,6 @@ void TableModel::removeColumns( sal_Int32 nIndex, sal_Int32 nCount ) { rModel.BegUndo( SvxResId(STR_UNDO_COL_DELETE) ); rModel.AddUndo( rModel.GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) ); - - TableModelRef xThis( this ); - ColumnVector aRemovedCols( nCount ); - sal_Int32 nOffset; - for( nOffset = 0; nOffset < nCount; ++nOffset ) - { - aRemovedCols[nOffset] = maColumns[nIndex+nOffset]; - } - - CellVector aRemovedCells( nCount * nRows ); - CellVector::iterator aCellIter( aRemovedCells.begin() ); - for( sal_Int32 nRow = 0; nRow < nRows; ++nRow ) - { - for( nOffset = 0; nOffset < nCount; ++nOffset ) - (*aCellIter++) = getCell( nIndex + nOffset, nRow ); - } - - rModel.AddUndo( std::make_unique( xThis, nIndex, aRemovedCols, aRemovedCells ) ); } // only rows before and inside the removed rows are considered @@ -758,6 +740,29 @@ void TableModel::removeColumns( sal_Int32 nIndex, sal_Int32 nCount ) } } + // We must not add RemoveColUndo before we make cell spans correct, otherwise we + // get invalid cell span after undo. + if( bUndo ) + { + TableModelRef xThis( this ); + ColumnVector aRemovedCols( nCount ); + sal_Int32 nOffset; + for( nOffset = 0; nOffset < nCount; ++nOffset ) + { + aRemovedCols[nOffset] = maColumns[nIndex+nOffset]; + } + + CellVector aRemovedCells( nCount * nRows ); + CellVector::iterator aCellIter( aRemovedCells.begin() ); + for( sal_Int32 nRow = 0; nRow < nRows; ++nRow ) + { + for( nOffset = 0; nOffset < nCount; ++nOffset ) + (*aCellIter++) = getCell( nIndex + nOffset, nRow ); + } + + rModel.AddUndo( std::make_unique( xThis, nIndex, aRemovedCols, aRemovedCells ) ); + } + // now remove the columns remove_range( maColumns, nIndex, nCount ); while( nRows-- ) @@ -862,14 +867,6 @@ void TableModel::removeRows( sal_Int32 nIndex, sal_Int32 nCount ) { rModel.BegUndo( SvxResId(STR_UNDO_ROW_DELETE) ); rModel.AddUndo( rModel.GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) ); - - TableModelRef xThis( this ); - - RowVector aRemovedRows( nCount ); - for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset ) - aRemovedRows[nOffset] = maRows[nIndex+nOffset]; - - rModel.AddUndo( std::make_unique( xThis, nIndex, aRemovedRows ) ); } // only rows before and inside the removed rows are considered @@ -916,6 +913,18 @@ void TableModel::removeRows( sal_Int32 nIndex, sal_Int32 nCount ) } } + if( bUndo ) + { + TableModelRef xThis( this ); + + RowVector aRemovedRows( nCount ); + for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset ) + aRemovedRows[nOffset] = maRows[nIndex+nOffset]; + + // We must not RemoveRowUndo before we make cell spans correct, otherwise we + // get invalid cell span after undo. + rModel.AddUndo( std::make_unique( xThis, nIndex, aRemovedRows ) ); + } // now remove the rows remove_range( maRows, nIndex, nCount );