sw/qa/extras/uiwriter/uiwriter2.cxx | 50 ++++++++++++++++ sw/source/core/doc/DocumentContentOperationsManager.cxx | 9 ++ sw/source/core/doc/docedt.cxx | 4 - sw/source/core/inc/mvsave.hxx | 2 4 files changed, 62 insertions(+), 3 deletions(-)
New commits: commit b7ab83bd96c70932c2223c8d0b3bc0f24327cef2 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Jun 10 16:26:40 2022 +0200 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Thu Jun 16 00:09:02 2022 +0200 tdf#139982 sw: preserve flys in Replace with redlining enabled The problem is that there isn't a redline type "Replace" so it's represented as Delete+Insert. To prevent the flys anchored in the text from being deleted, move the anchors to the point between the old (deleted) and new (inserted) text. (regression from commit 28b77c89dfcafae82cf2a6d85731b643ff9290e5) Change-Id: Ib600c9dbfb9421917e4b8d61195c48cf0b364f06 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135604 Tested-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> (cherry picked from commit 646c6ddd91a98afddf914e3889cb269fc814c060) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135737 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de> diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index 32bc25ef6386..645ef94d762a 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -1067,6 +1067,56 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf140007) pDoc->GetNodes()[SwNodeOffset(11)]->GetTextNode()->GetText()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf139982) +{ + SwDoc* const pDoc = createSwDoc(); + SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + + // turn on redlining and show changes + pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete + | RedlineFlags::ShowInsert); + CPPUNIT_ASSERT_MESSAGE("redlining should be on", + pDoc->getIDocumentRedlineAccess().IsRedlineOn()); + CPPUNIT_ASSERT_MESSAGE( + "redlines should be visible", + IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); + + pWrtShell->Insert("helloo"); + + pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + { + SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR); + anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint()); + SfxItemSet flySet(pDoc->GetAttrPool(), svl::Items<RES_ANCHOR, RES_ANCHOR>); + flySet.Put(anchor); + SwFrameFormat const* pFly = pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true); + CPPUNIT_ASSERT(pFly != nullptr); + } + + pWrtShell->SttEndDoc(true); + pWrtShell->EndPara(/*bSelect=*/true); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); + + pWrtShell->Replace("hello", true); + + // the problem was that a redline delete with the same author as redline + // insert has its text deleted immediately, including anchored flys. + CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); + + pWrtShell->Undo(); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); + + pWrtShell->Redo(); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); + + pWrtShell->Undo(); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf39721) { // FIXME: disabled on Windows because of a not reproducible problem (not related to the patch) diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index a52884f8c43a..2a5ec2918db4 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -4596,6 +4596,14 @@ bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUSt InsertItemSet( aTmpRange, aSet ); } + // tdf#139982: Appending the redline may immediately delete flys + // anchored in the previous text if it's inside an insert redline. + // Also flys will be deleted if the redline is accepted. Move them + // to the position between the previous text and the new text, + // there the chance of surviving both accept and reject is best. + SaveFlyArr flys; + SaveFlyInRange(aDelPam, *aDelPam.End(), flys, false); + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { m_rDoc.GetIDocumentUndoRedo().AppendUndo( @@ -4606,6 +4614,7 @@ bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUSt pCursor->SetMark(); *pCursor->GetPoint() = *aDelPam.GetPoint(); m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Delete, aDelPam ), true); + RestFlyInRange(flys, *aDelPam.End(), &aDelPam.End()->nNode, true); sw::UpdateFramesForAddDeleteRedline(m_rDoc, *pCursor); *rPam.GetMark() = *aDelPam.GetMark(); diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx index 57fffff87b18..53af17b01ae5 100644 --- a/sw/source/core/doc/docedt.cxx +++ b/sw/source/core/doc/docedt.cxx @@ -51,7 +51,7 @@ using namespace ::com::sun::star::i18n; void RestFlyInRange( SaveFlyArr & rArr, const SwPosition& rStartPos, - const SwNodeIndex* pInsertPos ) + const SwNodeIndex* pInsertPos, bool const isForceToStartPos) { SwPosition aPos(rStartPos); for(const SaveFly & rSave : rArr) @@ -60,7 +60,7 @@ void RestFlyInRange( SaveFlyArr & rArr, const SwPosition& rStartPos, SwFrameFormat* pFormat = rSave.pFrameFormat; SwFormatAnchor aAnchor( pFormat->GetAnchor() ); - if (rSave.isAtInsertNode) + if (rSave.isAtInsertNode || isForceToStartPos) { if( pInsertPos != nullptr ) { diff --git a/sw/source/core/inc/mvsave.hxx b/sw/source/core/inc/mvsave.hxx index 32af2d5b5fc8..0076f83f8e54 100644 --- a/sw/source/core/inc/mvsave.hxx +++ b/sw/source/core/inc/mvsave.hxx @@ -116,7 +116,7 @@ struct SaveFly typedef std::deque< SaveFly > SaveFlyArr; void RestFlyInRange( SaveFlyArr& rArr, const SwPosition& rSttIdx, - const SwNodeIndex* pInsPos ); + const SwNodeIndex* pInsPos, bool isForceToStartPos = false); void SaveFlyInRange( const SwNodeRange& rRg, SaveFlyArr& rArr ); void SaveFlyInRange( const SwPaM& rPam, const SwPosition& rInsPos, SaveFlyArr& rArr, bool bMoveAllFlys );