summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2019-04-16 19:00:50 +0200
committerMichael Stahl <Michael.Stahl@cib.de>2019-04-17 11:28:36 +0200
commitf83e22f535c1c9482c5d3f566d5d0283355dd98f (patch)
tree912c2334757ce554b85f95886ec5c2e1d10a200a
parente8c992258ad53274099fa770e0aaefb79c7c6c60 (diff)
tdf#109376 sw: fix redline SwUndoDelete with end pos on SwTableNode crash
... that happens when you accept a delete redline (or reject an insert redline) with such end pos. The problem is that first a DeleteRange() will move the anchor position onto the table node (because check in SwUndoSaveContent::DelContentIndex() is surprisingly asymmetric and so the fly not deleted by the previous bugfix), then DelFullPara() creates a second SwUndoDelete then deleting the fly crashes because its anchors was moved. The code in lcl_AcceptRedline() / lcl_RejectRedline() doesn't make much sense (but always was like this), if we just call DeleteFullPara() once instead, the problem is avoided, and we don't even have to worry about why DelContentIndex() is so asymmetric (is "selection direction" really a meaningful concept?). Reportedly this started to crash with commit e07feb9457f2ffb373ae69b73dda290140e4005f, previously it was just wrong. Change-Id: Ib3d4b31e0255a6f4e7b49b40f204dec168ea3006 Reviewed-on: https://gerrit.libreoffice.org/70836 Tested-by: Jenkins Reviewed-by: Michael Stahl <Michael.Stahl@cib.de>
-rw-r--r--sw/qa/extras/uiwriter/uiwriter2.cxx53
-rw-r--r--sw/source/core/doc/DocumentRedlineManager.cxx20
2 files changed, 61 insertions, 12 deletions
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index f58819aee41c..ba15c9001d51 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -51,6 +51,7 @@ public:
void testTdf47471_paraStyleBackground();
void testTdf101534();
void testTdf54819();
+ void testTdf109376_redline();
void testTdf109376();
void testTdf64242_optimizeTable();
void testTdf108687_tabstop();
@@ -82,6 +83,7 @@ public:
CPPUNIT_TEST(testTdf47471_paraStyleBackground);
CPPUNIT_TEST(testTdf101534);
CPPUNIT_TEST(testTdf54819);
+ CPPUNIT_TEST(testTdf109376_redline);
CPPUNIT_TEST(testTdf109376);
CPPUNIT_TEST(testTdf64242_optimizeTable);
CPPUNIT_TEST(testTdf108687_tabstop);
@@ -347,6 +349,57 @@ void SwUiWriterTest2::testTdf54819()
getProperty<OUString>(getParagraph(1), "ParaStyleName"));
}
+void SwUiWriterTest2::testTdf109376_redline()
+{
+ SwDoc* pDoc = createDoc();
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+ // need 2 paragraphs to get to the bMoveNds case
+ pWrtShell->Insert("foo");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("bar");
+ pWrtShell->SplitNode();
+ pWrtShell->StartOfSection(false);
+
+ // add AT_PARA fly at 1st to be deleted node
+ SwFormatAnchor anchor(RndStdIds::FLY_AT_PARA);
+ anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint());
+ SfxItemSet flySet(pDoc->GetAttrPool(),
+ svl::Items<RES_FRM_SIZE, RES_FRM_SIZE, RES_ANCHOR, RES_ANCHOR>{});
+ flySet.Put(anchor);
+ SwFormatFrameSize size(ATT_MIN_SIZE, 1000, 1000);
+ flySet.Put(size); // set a size, else we get 1 char per line...
+ SwFrameFormat const* pFly = pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true);
+ CPPUNIT_ASSERT(pFly != nullptr);
+
+ pWrtShell->SttEndDoc(false);
+ SwInsertTableOptions tableOpt(SwInsertTableFlags::DefaultBorder, 0);
+ const SwTable& rTable = pWrtShell->InsertTable(tableOpt, 1, 1);
+
+ pWrtShell->StartOfSection(false);
+ SwPaM pam(*pWrtShell->GetCursor()->GetPoint());
+ pam.SetMark();
+ pam.GetPoint()->nNode = *rTable.GetTableNode();
+ pam.GetPoint()->nContent.Assign(nullptr, 0);
+ pam.Exchange(); // same selection direction as in doc compare...
+
+ IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
+ rIDRA.SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete);
+ rIDRA.AppendRedline(new SwRangeRedline(nsRedlineType_t::REDLINE_DELETE, pam), true);
+ // this used to assert/crash with m_pAnchoredFlys mismatch because the
+ // fly was not deleted but its anchor was moved to the SwTableNode
+ rIDRA.AcceptAllRedline(true);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+ sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+ rUndoManager.Redo();
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+ rUndoManager.Undo();
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+}
+
void SwUiWriterTest2::testTdf109376()
{
SwDoc* pDoc = createDoc();
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index b5431a0a79e7..47d52d6226c4 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -423,17 +423,15 @@ namespace
if( pCSttNd && pCEndNd )
rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam );
- else
- {
- rDoc.getIDocumentContentOperations().DeleteRange( aPam );
-
- if( pCSttNd && !pCEndNd )
+ else if (pCSttNd && !pCEndNd)
{
aPam.GetBound().nContent.Assign( nullptr, 0 );
aPam.GetBound( false ).nContent.Assign( nullptr, 0 );
- aPam.DeleteMark();
rDoc.getIDocumentContentOperations().DelFullPara( aPam );
}
+ else
+ {
+ rDoc.getIDocumentContentOperations().DeleteRange(aPam);
}
rDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
}
@@ -537,17 +535,15 @@ namespace
if( pCSttNd && pCEndNd )
rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam );
- else
- {
- rDoc.getIDocumentContentOperations().DeleteRange( aPam );
-
- if( pCSttNd && !pCEndNd )
+ else if (pCSttNd && !pCEndNd)
{
aPam.GetBound().nContent.Assign( nullptr, 0 );
aPam.GetBound( false ).nContent.Assign( nullptr, 0 );
- aPam.DeleteMark();
rDoc.getIDocumentContentOperations().DelFullPara( aPam );
}
+ else
+ {
+ rDoc.getIDocumentContentOperations().DeleteRange(aPam);
}
rDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
}