summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2022-06-10 16:26:40 +0200
committerAndras Timar <andras.timar@collabora.com>2022-06-24 13:42:26 +0200
commit47b4afb244ed5ad3a38e481993853dab3a3d7f45 (patch)
tree04d80cb2fed8e3efc6333a03331367e6c117a5cc /sw
parentcc9711f3aef335d900681c24f04d0240c93f384c (diff)
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.stahl@allotropia.de> Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit 646c6ddd91a98afddf914e3889cb269fc814c060) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135737 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/extras/uiwriter/uiwriter2.cxx50
-rw-r--r--sw/source/core/doc/DocumentContentOperationsManager.cxx9
-rw-r--r--sw/source/core/doc/docedt.cxx4
-rw-r--r--sw/source/core/inc/mvsave.hxx2
4 files changed, 62 insertions, 3 deletions
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 548620b4872e..f56e949c7f64 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -4606,6 +4606,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(
@@ -4616,6 +4624,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 );