sw/qa/extras/uiwriter/uiwriter2.cxx                     |   95 ++++++++++++++++
 sw/source/core/doc/DocumentContentOperationsManager.cxx |    4 
 sw/source/core/doc/docedt.cxx                           |    7 +
 sw/source/core/inc/UndoRedline.hxx                      |    8 +
 sw/source/core/inc/mvsave.hxx                           |    3 
 sw/source/core/undo/unredln.cxx                         |   34 +++++
 6 files changed, 144 insertions(+), 7 deletions(-)

New commits:
commit 650d0ead161303f30faa2de0bb4e20fceafc2af8
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Jun 15 15:06:59 2022 +0200
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Tue Jun 21 23:43:19 2022 +0200

    tdf#135976 sw: preserve flys on backspace/delete with redlining enabled
    
    This is a continuation of commit 85376a02348810812d515ee72140dbf56f2b6040
    for the case when redlining is turned on.
    
    Also try to restore the anchors in SwUndoRedlineDelete.
    
    (regression from commit 3345feb67f2c49a1b76639965b56968e1c5f03ee)
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135909
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 932a8efce878547bfd81521d0cf1ddfe8dc33ec6)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135968
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    (cherry picked from commit 03834f003c56e6646e3b274c418acd4fc344fd8e)
    
    sw: fix odd m_bCanGroup check in SwUndoRedlineDelete
    
    This looks like copypasta, presumably both flags must be true to allow
    grouping.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135908
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit f31f11f3222933dbc96dc672e6fa52233cda12be)
    
    Change-Id: I4199f5755398d469a606618c037ad9756cb7aeba
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136223
    Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    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 e00e27548fcc..1418ddd0ae51 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -28,6 +28,7 @@
 #include <wrtsh.hxx>
 #include <IDocumentRedlineAccess.hxx>
 #include <flyfrm.hxx>
+#include <pagefrm.hxx>
 #include <fmtanchr.hxx>
 #include <UndoManager.hxx>
 #include <sortedobjs.hxx>
@@ -958,6 +959,100 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf139982)
     CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf135976)
+{
+    SwDoc* const pDoc = createDoc();
+    SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+    pWrtShell->Insert("foobar");
+
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 2, 
/*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);
+
+    // turn on redlining and show changes
+    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | 
RedlineFlags::ShowDelete
+                                                      | 
RedlineFlags::ShowInsert);
+    lcl_dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
+    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
+                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+    CPPUNIT_ASSERT_MESSAGE(
+        "redlines should be visible",
+        
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+    CPPUNIT_ASSERT(pWrtShell->GetLayout()->IsHideRedlines());
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+
+    pWrtShell->UnSelectFrame();
+    pWrtShell->SttEndDoc(/*bStart=*/false);
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+
+    pWrtShell->DelLeft();
+    pWrtShell->DelLeft();
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    // the problem was that the fly was deleted from the layout
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    // check that the anchor was moved outside the redline
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+
+    pWrtShell->Undo(2);
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    // check that the anchor was restored
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+
+    pWrtShell->Redo(2);
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+
+    pWrtShell->Undo(2);
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+
+    // now again in the other direction:
+
+    pWrtShell->SttEndDoc(/*bStart=*/false);
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 3, 
/*bBasicCall=*/false);
+
+    pWrtShell->DelRight();
+    pWrtShell->DelRight();
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    // the problem was that the fly was deleted from the layout
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+
+    pWrtShell->Undo(2);
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+
+    pWrtShell->Redo(2);
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+
+    pWrtShell->Undo(2);
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
pWrtShell->GetLayout()->GetLastPage()->GetSortedObjs()->size());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pFly->GetAnchor().GetContentAnchor()->nContent.GetIndex());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf54819)
 {
     load(DATA_DIRECTORY, "tdf54819.fodt");
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx 
b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index b6dc4158b936..315cf5cdeefa 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3915,7 +3915,7 @@ 
DocumentContentOperationsManager::~DocumentContentOperationsManager()
 }
 //Private methods
 
-bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl(SwPaM & 
rPam, SwDeleteFlags const /*flags*/, const bool)
+bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl(SwPaM & 
rPam, SwDeleteFlags const flags, const bool)
 {
     assert(m_rDoc.getIDocumentRedlineAccess().IsRedlineOn());
 
@@ -3995,7 +3995,7 @@ bool 
DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl(SwPaM & rPam
         {
             assert(pRedline->HasValidRange());
             undos.emplace_back(std::make_unique<SwUndoRedlineDelete>(
-                        *pRedline, SwUndoId::DELETE));
+                        *pRedline, SwUndoId::DELETE, flags));
         }
         const SwRewriter aRewriter = undos.front()->GetRewriter();
         // can only group a single undo action
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index 398b5ae1a065..d6072b4b3725 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -28,6 +28,7 @@
 #include <mdiexp.hxx>
 #include <mvsave.hxx>
 #include <redline.hxx>
+#include <rolbck.hxx>
 #include <rootfrm.hxx>
 #include <splargs.hxx>
 #include <swcrsr.hxx>
@@ -130,7 +131,7 @@ void SaveFlyInRange( const SwNodeRange& rRg, SaveFlyArr& 
rArr )
 }
 
 void SaveFlyInRange( const SwPaM& rPam, const SwPosition& rInsPos,
-                       SaveFlyArr& rArr, bool bMoveAllFlys )
+        SaveFlyArr& rArr, bool bMoveAllFlys, SwHistory *const pHistory)
 {
     SwFrameFormats& rFormats = 
*rPam.GetPoint()->nNode.GetNode().GetDoc()->GetSpzFrameFormats();
     SwFrameFormat* pFormat;
@@ -176,6 +177,10 @@ void SaveFlyInRange( const SwPaM& rPam, const SwPosition& 
rInsPos,
                     || (RndStdIds::FLY_AT_CHAR == pAnchor->GetAnchorId()
                             && (bInsPos = (rInsPos == *pAPos))))
             {
+                if (pHistory)
+                {
+                    pHistory->AddChangeFlyAnchor(*pFormat);
+                }
                 SaveFly aSave( pAPos->nNode.GetIndex() - rSttNdIdx.GetIndex(),
                     (RndStdIds::FLY_AT_CHAR == pAnchor->GetAnchorId())
                         ? (pAPos->nNode == rSttNdIdx)
diff --git a/sw/source/core/inc/UndoRedline.hxx 
b/sw/source/core/inc/UndoRedline.hxx
index 38ecd86314cb..ada3c34fad7f 100644
--- a/sw/source/core/inc/UndoRedline.hxx
+++ b/sw/source/core/inc/UndoRedline.hxx
@@ -22,6 +22,7 @@
 
 #include <memory>
 #include <undobj.hxx>
+#include <IDocumentContentOperations.hxx>
 
 struct SwSortOptions;
 class SwRangeRedline;
@@ -52,17 +53,22 @@ public:
 
 class SwUndoRedlineDelete : public SwUndoRedline
 {
+private:
+    std::unique_ptr<SwHistory> m_pHistory; ///< for moved fly anchors
+                                           //
     bool bCanGroup : 1;
     bool bIsDelim : 1;
     bool bIsBackspace : 1;
 
     OUString m_sRedlineText;
 
+    void InitHistory(SwPaM const& rRange);
+
     virtual void UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam) override;
     virtual void RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam) override;
 
 public:
-    SwUndoRedlineDelete( const SwPaM& rRange, SwUndoId nUserId );
+    SwUndoRedlineDelete(const SwPaM& rRange, SwUndoId nUserId, SwDeleteFlags 
flags = SwDeleteFlags::Default);
     virtual SwRewriter GetRewriter() const override;
 
     bool CanGrouping( const SwUndoRedlineDelete& rPrev );
diff --git a/sw/source/core/inc/mvsave.hxx b/sw/source/core/inc/mvsave.hxx
index d6cde5520ecb..5b84b5e10819 100644
--- a/sw/source/core/inc/mvsave.hxx
+++ b/sw/source/core/inc/mvsave.hxx
@@ -34,6 +34,7 @@ class SwDoc;
 class SwFormatAnchor;
 class SwFrameFormat;
 class SwIndex;
+class SwHistory;
 class SwNodeIndex;
 class SwNodeRange;
 class SwPaM;
@@ -119,7 +120,7 @@ void RestFlyInRange( SaveFlyArr& rArr, const SwPosition& 
rSttIdx,
                      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 );
+        SaveFlyArr& rArr, bool bMoveAllFlys, SwHistory * pHistory = nullptr);
 
 void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
                     const SwNodeIndex& rPtNdIdx,
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 117a7992ff50..c66d8eed133e 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -26,6 +26,8 @@
 #include <pam.hxx>
 #include <ndtxt.hxx>
 #include <txtfrm.hxx>
+#include <mvsave.hxx>
+#include <rolbck.hxx>
 #include <UndoCore.hxx>
 #include <UndoDelete.hxx>
 #include <strings.hrc>
@@ -153,7 +155,8 @@ void SwUndoRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & 
rPam)
     rDoc.getIDocumentRedlineAccess().DeleteRedline(rPam, true, 
RedlineType::Any);
 }
 
-SwUndoRedlineDelete::SwUndoRedlineDelete( const SwPaM& rRange, SwUndoId nUsrId 
)
+SwUndoRedlineDelete::SwUndoRedlineDelete(
+        const SwPaM& rRange, SwUndoId const nUsrId, SwDeleteFlags const flags)
     : SwUndoRedline( nUsrId != SwUndoId::EMPTY ? nUsrId : SwUndoId::DELETE, 
rRange ),
     bCanGroup( false ), bIsDelim( false ), bIsBackspace( false )
 {
@@ -174,6 +177,24 @@ SwUndoRedlineDelete::SwUndoRedlineDelete( const SwPaM& 
rRange, SwUndoId nUsrId )
     }
 
     m_bCacheComment = false;
+    if (flags & SwDeleteFlags::ArtificialSelection)
+    {
+        InitHistory(rRange);
+    }
+}
+
+void SwUndoRedlineDelete::InitHistory(SwPaM const& rRedline)
+{
+    m_pHistory.reset(new SwHistory);
+    // try to rely on direction of rPam here so it works for
+    // backspacing/deleting consecutive characters
+    SaveFlyArr flys;
+    SaveFlyInRange(rRedline, *rRedline.GetMark(), flys, false, 
m_pHistory.get());
+    RestFlyInRange(flys, *rRedline.GetPoint(), &rRedline.GetPoint()->nNode, 
true);
+    if (m_pHistory->Count())
+    {
+        bCanGroup = false; // how to group history?
+    }
 }
 
 // bit of a hack, replace everything...
@@ -197,12 +218,21 @@ void SwUndoRedlineDelete::SetRedlineText(const OUString & 
rText)
 void SwUndoRedlineDelete::UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
 {
     rDoc.getIDocumentRedlineAccess().DeleteRedline(rPam, true, 
RedlineType::Any);
+    if (m_pHistory)
+    {
+        m_pHistory->TmpRollback(&rDoc, 0);
+    }
 }
 
 void SwUndoRedlineDelete::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
 {
     if (rPam.GetPoint() != rPam.GetMark())
     {
+        if (m_pHistory) // if it was created before, it must be recreated now
+        {
+            rPam.Normalize(bIsBackspace); // to check the correct edge
+            InitHistory(rPam);
+        }
         rDoc.getIDocumentRedlineAccess().AppendRedline( new 
SwRangeRedline(*mpRedlData, rPam), false );
     }
     sw::UpdateFramesForAddDeleteRedline(rDoc, rPam);
@@ -212,7 +242,7 @@ bool SwUndoRedlineDelete::CanGrouping( const 
SwUndoRedlineDelete& rNext )
 {
     bool bRet = false;
     if( SwUndoId::DELETE == mnUserId && mnUserId == rNext.mnUserId &&
-        bCanGroup == rNext.bCanGroup &&
+        bCanGroup && rNext.bCanGroup &&
         bIsDelim == rNext.bIsDelim &&
         bIsBackspace == rNext.bIsBackspace &&
         m_nSttNode == m_nEndNode &&

Reply via email to