diff options
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter2.cxx | 95 | ||||
-rw-r--r-- | sw/source/core/doc/DocumentContentOperationsManager.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/doc/docedt.cxx | 7 | ||||
-rw-r--r-- | sw/source/core/inc/UndoRedline.hxx | 8 | ||||
-rw-r--r-- | sw/source/core/inc/mvsave.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/undo/unredln.cxx | 32 |
6 files changed, 142 insertions, 6 deletions
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index e62532c0a20d..0ff16f74e59d 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -22,6 +22,7 @@ #include <wrtsh.hxx> #include <IDocumentRedlineAccess.hxx> #include <flyfrm.hxx> +#include <pagefrm.hxx> #include <fmtanchr.hxx> #include <UndoManager.hxx> #include <sortedobjs.hxx> @@ -1081,6 +1082,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 3d38a8f9521f..962cea631e5f 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -4102,7 +4102,7 @@ DocumentContentOperationsManager::~DocumentContentOperationsManager() } //Private methods -bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl(SwPaM & rPam, SwDeleteFlags const /*flags*/) +bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl(SwPaM & rPam, SwDeleteFlags const flags) { assert(m_rDoc.getIDocumentRedlineAccess().IsRedlineOn()); @@ -4183,7 +4183,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 c7c3d7c2f3c4..3751ae034577 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> @@ -132,7 +133,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; @@ -178,6 +179,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 b695b56c49ef..7c815fca6cc1 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 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); |