summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2022-06-15 15:08:16 +0200
committerAndras Timar <andras.timar@collabora.com>2022-06-24 13:42:28 +0200
commit8125a684a5412b59831eb916d495f340d2e496ae (patch)
treef89fc9407716d24b7b3cf9b6a530e4659836906a /sw
parent46b4642552fa919cf8e1ab069746306722a68d25 (diff)
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) Change-Id: I4199f5755398d469a606618c037ad9756cb7aeba Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135909 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit 932a8efce878547bfd81521d0cf1ddfe8dc33ec6) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135968 Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/extras/uiwriter/uiwriter2.cxx95
-rw-r--r--sw/source/core/doc/DocumentContentOperationsManager.cxx4
-rw-r--r--sw/source/core/doc/docedt.cxx7
-rw-r--r--sw/source/core/inc/UndoRedline.hxx8
-rw-r--r--sw/source/core/inc/mvsave.hxx2
-rw-r--r--sw/source/core/undo/unredln.cxx32
6 files changed, 142 insertions, 6 deletions
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 645ef94d762a..f895b59ba402 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -39,6 +39,7 @@
#include <wrtsh.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <flyfrm.hxx>
+#include <pagefrm.hxx>
#include <fmtanchr.hxx>
#include <UndoManager.hxx>
#include <sortedobjs.hxx>
@@ -1117,6 +1118,100 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf139982)
CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM));
}
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf135976)
+{
+ SwDoc* const pDoc = createSwDoc();
+ 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);
+ 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, 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 f56e949c7f64..c368ada50194 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -4099,7 +4099,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());
@@ -4180,7 +4180,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 53af17b01ae5..cd6b1873f0ec 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>
@@ -133,7 +134,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;
@@ -179,6 +180,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 68ce25a27d0c..53ffaff49ef7 100644
--- a/sw/source/core/inc/UndoRedline.hxx
+++ b/sw/source/core/inc/UndoRedline.hxx
@@ -23,6 +23,7 @@
#include <memory>
#include <undobj.hxx>
#include <tools/long.hxx>
+#include <IDocumentContentOperations.hxx>
struct SwSortOptions;
class SwRangeRedline;
@@ -53,17 +54,22 @@ public:
class SwUndoRedlineDelete final : public SwUndoRedline
{
+private:
+ std::unique_ptr<SwHistory> m_pHistory; ///< for moved fly anchors
+
bool m_bCanGroup : 1;
bool m_bIsDelim : 1;
bool m_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 0076f83f8e54..2e0511a16c69 100644
--- a/sw/source/core/inc/mvsave.hxx
+++ b/sw/source/core/inc/mvsave.hxx
@@ -119,7 +119,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 e48255c3ab5b..1970eff02aeb 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -27,6 +27,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>
@@ -197,7 +199,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 ),
m_bCanGroup( false ), m_bIsDelim( false ), m_bIsBackspace( false )
{
@@ -218,6 +221,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())
+ {
+ m_bCanGroup = false; // how to group history?
+ }
}
// bit of a hack, replace everything...
@@ -241,12 +262,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(m_bIsBackspace); // to check the correct edge
+ InitHistory(rPam);
+ }
rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline(*mpRedlData, rPam), false );
}
sw::UpdateFramesForAddDeleteRedline(rDoc, rPam);