Rebased ref, commits from common ancestor: commit 953021f6ad5f13f8f40544a5ddc8605ff4a7a046 Author: Michael Stahl <mst...@redhat.com> AuthorDate: Wed May 20 13:18:42 2015 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200
gbuild: allow recording of CppunitTests and PythonTests too Since these don't use soffice they need to be tweaked to use RR varaiable. Unfortunately rr crashes in some CppunitTest so don't enable that now. Unfortunately rr crashes in PythonTest. Change-Id: I2143618fa2181e36b6aaeded43637cb3481f5e47 diff --git a/solenv/gbuild/CppunitTest.mk b/solenv/gbuild/CppunitTest.mk index 1ac3b210e149..8e130d481802 100644 --- a/solenv/gbuild/CppunitTest.mk +++ b/solenv/gbuild/CppunitTest.mk @@ -63,6 +63,10 @@ gb_CppunitTest_VALGRINDTOOL += --vgdb=yes --vgdb-error=0 endif endif +ifneq ($(strip $(RR)),) +gb_CppunitTest_RR := rr record +endif + # defined by platform # gb_CppunitTest_get_filename gb_CppunitTest_RUNTIMEDEPS := $(call gb_Executable_get_runtime_dependencies,cppunittester) @@ -134,7 +138,8 @@ else $(gb_CppunitTest_malloc_check) \ $(if $(strip $(PYTHON_URE)),\ PYTHONDONTWRITEBYTECODE=1) \ - $(ICECREAM_RUN) $(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) $(gb_CppunitTest_CPPTESTCOMMAND) \ + $(ICECREAM_RUN) $(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) $(gb_CppunitTest_RR) \ + $(gb_CppunitTest_CPPTESTCOMMAND) \ $(call gb_LinkTarget_get_target,$(call gb_CppunitTest_get_linktarget,$*)) \ $(call gb_CppunitTest__make_args) "-env:CPPUNITTESTTARGET=$@" \ $(if $(gb_CppunitTest_POSTGDBTRACE), \ diff --git a/solenv/gbuild/PythonTest.mk b/solenv/gbuild/PythonTest.mk index c579a34ea6d5..a2bac3819e02 100644 --- a/solenv/gbuild/PythonTest.mk +++ b/solenv/gbuild/PythonTest.mk @@ -55,7 +55,7 @@ else $(if $(filter-out MACOSX WNT,$(OS_FOR_BUILD)),$(if $(DISABLE_GUI),, \ SAL_USE_VCLPLUGIN=svp \ )) \ - $(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) \ + $(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) $(gb_CppunitTest_RR) \ $(gb_PythonTest_COMMAND) \ $(if $(PYTHON_TEST_NAME),$(PYTHON_TEST_NAME),$(MODULES)) \ $(if $(gb_CppunitTest__interactive),, \ commit b3e360ba7aa4091e5cafa7be32828d70245c0d6c Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Sep 6 12:58:18 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: update flys and footnotes on redline ops Re-use some code that is already used elsewhere; for the UpdateFramesForAddDeleteRedline(), the same code as for switching the layout to Hide mode should work, for UpdateFramesForRemoveDeleteRedline() use the code that is used for SwTextNode::SplitContentNode(). Change-Id: I97601bfb63478cc999cf7017da0225b2dc62ad37 diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index caec50025ef1..d27a579d3e43 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -140,25 +140,34 @@ void UpdateFramesForAddDeleteRedline(SwPaM const& rPam) pFrame->SetMergedPara(nullptr); pFrame->SetMergedPara(sw::CheckParaRedlineMerge( *pFrame, rFirstNode, sw::FrameMode::Existing)); + // the first node of the new redline is not necessarily the first + // node of the merged frame, there could be another redline nearby + sw::AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame, *pStartNode, nullptr); } } void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) { + SwTextNode *const pStartNode(rPam.Start()->nNode.GetNode().GetTextNode()); + std::vector<SwTextFrame*> frames; + std::set<SwRootFrame*> layouts; + SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pStartNode); + for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) + { + if (pFrame->getRootFrame()->IsHideRedlines()) + { + frames.push_back(pFrame); + layouts.insert(pFrame->getRootFrame()); + } + } + if (frames.empty()) + { + return; + } if (rPam.GetPoint()->nNode != rPam.GetMark()->nNode) { // first, call CheckParaRedlineMerge on the first paragraph, // to init flag on new merge range (if any) + 1st node post the merge - SwTextNode *const pStartNode(rPam.Start()->nNode.GetNode().GetTextNode()); - std::vector<SwTextFrame*> frames; - SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pStartNode); - for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) - { - if (pFrame->getRootFrame()->IsHideRedlines()) - { - frames.push_back(pFrame); - } - } for (SwTextFrame * pFrame : frames) { if (auto const pMergedPara = pFrame->GetMergedPara()) @@ -173,11 +182,22 @@ void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) } // now start node until end of merge + 1 has proper flags; MakeFrames // should pick up from the next node in need of frames by checking flags - if (!frames.empty()) + SwNodeIndex const start(*pStartNode, +1); + SwNodeIndex const end(rPam.End()->nNode, +1); // end is exclusive + // note: this will also create frames for all currently hidden flys + // both on first and non-first nodes because it calls AppendAllObjs + ::MakeFrames(&rDoc, start, end); + // re-use this to move flys that are now on the wrong frame, with end + // of redline as "second" node; the nodes between start and end should + // be complete with MakeFrames already + sw::MoveMergedFlysAndFootnotes(frames, *pStartNode, + *rPam.End()->nNode.GetNode().GetTextNode(), false); + } + else + { // recreate flys in the one node the hard way... + for (auto const& pLayout : layouts) { - SwNodeIndex const start(*pStartNode, +1); - SwNodeIndex const end(rPam.End()->nNode, +1); // end is exclusive - ::MakeFrames(&rDoc, start, end); + AppendAllObjs(rDoc.GetSpzFrameFormats(), pLayout); } } } diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx index a52bf0f14fa0..0b19178734d2 100644 --- a/sw/source/core/inc/txtfrm.hxx +++ b/sw/source/core/inc/txtfrm.hxx @@ -105,12 +105,19 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged, bool isRealDelete, SwTextNode const& rNode, sal_Int32 nIndex, sal_Int32 nLen); +void MoveMergedFlysAndFootnotes(std::vector<SwTextFrame*> const& rFrames, + SwTextNode const& rFirstNode, SwTextNode & rSecondNode, bool); + void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode); void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool bRecreateMerged); void UpdateFramesForAddDeleteRedline(SwPaM const& rPam); void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam); +void AddRemoveFlysAnchoredToFrameStartingAtNode( + SwTextFrame & rFrame, SwTextNode & rTextNode, + std::set<sal_uLong> *pSkipped); + } // namespace sw /// Represents the visualization of a paragraph. Typical upper is an diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 3e6ff2d4f565..e6fbd7c553dc 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -4167,6 +4167,74 @@ void SwRootFrame::InvalidateAllObjPos() } } +namespace sw { + +/// rTextNode is the first one of the "new" merge - if rTextNode isn't the same +/// as MergedPara::pFirstNode, then nodes before rTextNode have their flys +/// already properly attached, so only the other nodes need handling here. +void AddRemoveFlysAnchoredToFrameStartingAtNode( + SwTextFrame & rFrame, SwTextNode & rTextNode, + std::set<sal_uLong> *const pSkipped) +{ + auto const pMerged(rFrame.GetMergedPara()); + if (pMerged + // do this only *once*, for the *last* frame + // otherwise AppendObj would create multiple frames for fly-frames! + && !rFrame.GetFollow()) + { + assert(pMerged->pFirstNode->GetIndex() <= rTextNode.GetIndex() + && rTextNode.GetIndex() <= pMerged->pLastNode->GetIndex()); + // add visible flys in non-first node to merged frame + // (hidden flys remain and are deleted via DelFrames()) + SwFrameFormats& rTable(*rTextNode.GetDoc()->GetSpzFrameFormats()); + SwPageFrame *const pPage(rFrame.FindPageFrame()); + std::vector<sw::Extent>::const_iterator iterFirst(pMerged->extents.begin()); + std::vector<sw::Extent>::const_iterator iter(iterFirst); + SwTextNode const* pNode(pMerged->pFirstNode); + for ( ; ; ++iter) + { + if (iter == pMerged->extents.end() + || iter->pNode != pNode) + { + if (pNode == &rTextNode) + { // remove existing hidden at-char anchored flys + RemoveHiddenObjsOfNode( + rTextNode, &iterFirst, &iter); + } + else if (rTextNode.GetIndex() < pNode->GetIndex()) + { + // pNode's frame has been deleted by CheckParaRedlineMerge() + AppendObjsOfNode(&rTable, + pNode->GetIndex(), &rFrame, pPage, rTextNode.GetDoc(), + &iterFirst, &iter); + if (pSkipped) + { + // if a fly has been added by AppendObjsOfNode, it must be skipped; if not, then it doesn't matter if it's skipped or not because it has no frames and because of that it would be skipped anyway + if (auto const pFlys = pNode->GetAnchoredFlys()) + { + for (auto const pFly : *pFlys) + { + if (pFly->Which() != RES_DRAWFRMFMT) + { + pSkipped->insert(pFly->GetContent().GetContentIdx()->GetIndex()); + } + } + } + } + } + if (iter == pMerged->extents.end()) + { + break; + } + pNode = iter->pNode; + iterFirst = iter; + } + } + } +} + +} // namespace sw + static void UnHideRedlines(SwRootFrame & rLayout, SwNodes & rNodes, SwNode const& rEndOfSectionNode, std::set<sal_uLong> *const pSkipped) @@ -4226,59 +4294,7 @@ static void UnHideRedlines(SwRootFrame & rLayout, } } } - if (pMerged - // do this only *once*, for the *last* frame - // otherwise AppendObj would create multiple frames for fly-frames! - && !pFrame->GetFollow()) - { - // add visible flys in non-first node to merged frame - // (hidden flys remain and are deleted via DelFrames()) - SwFrameFormats& rTable(*rTextNode.GetDoc()->GetSpzFrameFormats()); - SwPageFrame *const pPage(pFrame->FindPageFrame()); - std::vector<sw::Extent>::const_iterator iterFirst(pMerged->extents.begin()); - std::vector<sw::Extent>::const_iterator iter(iterFirst); - SwTextNode const* pNode(&rTextNode); - for ( ; ; ++iter) - { - if (iter == pMerged->extents.end() - || iter->pNode != pNode) - { - if (pNode == &rTextNode) - { // remove existing hidden at-char anchored flys - RemoveHiddenObjsOfNode( - rTextNode, &iterFirst, &iter); - } - else - { - // pNode's frame has been deleted by CheckParaRedlineMerge() - AppendObjsOfNode(&rTable, - pNode->GetIndex(), pFrame, pPage, - rTextNode.GetDoc(), - &iterFirst, &iter); - if (pSkipped) - { - // if a fly has been added by AppendObjsOfNode, it must be skipped; if not, then it doesn't matter if it's skipped or not because it has no frames and because of that it would be skipped anyway - if (auto const pFlys = pNode->GetAnchoredFlys()) - { - for (auto const pFly : *pFlys) - { - if (pFly->Which() != RES_DRAWFRMFMT) - { - pSkipped->insert(pFly->GetContent().GetContentIdx()->GetIndex()); - } - } - } - } - } - if (iter == pMerged->extents.end()) - { - break; - } - pNode = iter->pNode; - iterFirst = iter; - } - } - } + sw::AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame, rTextNode, pSkipped); } } else diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index a8d672dda16e..9c16f081eb69 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -365,13 +365,18 @@ static void lcl_ChangeFootnoteRef( SwTextNode &rNode ) } } -namespace { +namespace sw { // check if there are flys on the existing frames (now on "pNode") // that need to be moved to the new frames of "this" void MoveMergedFlysAndFootnotes(std::vector<SwTextFrame*> const& rFrames, - SwTextNode const& rFirstNode, SwTextNode const& rSecondNode) + SwTextNode const& rFirstNode, SwTextNode & rSecondNode, + bool isSplitNode) { + if (!isSplitNode) + { + lcl_ChangeFootnoteRef(rSecondNode); + } int nLevel(0); for (sal_uLong nIndex = rSecondNode.GetIndex() + 1; ; ++nIndex) { @@ -608,7 +613,7 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos, } if (eOldMergeFlag != SwNode::Merge::None) { - MoveMergedFlysAndFootnotes(frames, *pNode, *this); + MoveMergedFlysAndFootnotes(frames, *pNode, *this, true); } } else @@ -739,7 +744,7 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos, if (bRecreateThis) { - MoveMergedFlysAndFootnotes(frames, *pNode, *this); + MoveMergedFlysAndFootnotes(frames, *pNode, *this, true); } } commit 0c07bb358b1dc365e034687bcda1c973ce887b1c Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Sep 5 13:03:02 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw: remove window invalidation from SwRedlineTable::DeleteAndDestroyAll() This is called in 2 situations, from ClearDoc() and from SwDoc dtor. In the latter case, there is no window any more, and in the former case, surely something else must have invalidated it already. Change-Id: Ideecdeb145171a4dafbec50a04d4ec5aa2acab82 diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx index 56dfd57a82f9..6fe4e815dc69 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -605,9 +605,6 @@ void SwRedlineTable::Remove( size_type nP ) void SwRedlineTable::DeleteAndDestroyAll() { - if (maVector.empty()) - return; - SwDoc *const pDoc = maVector.front()->GetDoc(); while (!maVector.empty()) { auto const pRedline = maVector.back(); @@ -615,14 +612,6 @@ void SwRedlineTable::DeleteAndDestroyAll() LOKRedlineNotification(RedlineNotification::Remove, pRedline); delete pRedline; } - if (pDoc && !pDoc->IsInDtor()) - { - SwViewShell* pSh(pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() ); - if (pSh) - { - pSh->InvalidateWindows(SwRect(0, 0, SAL_MAX_INT32, SAL_MAX_INT32)); - } - } } void SwRedlineTable::DeleteAndDestroy(size_type const nP) commit bec70c9eb1fee59aa0632b34cd91727e32398d9b Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Sep 4 18:59:01 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw: SwDocTest: adjust this so it actually tests something interesting * test more than 1 paragraph, by calling SplitNode() * enable Undo, because that's the more usual situation * remove one mode that is identical to the previous one * use SwUnoCursor because plain SwCursor isn't corrected when nodes are deleted * create a selection before calling Delete functions Change-Id: If406bd8c37b005e431fbaebe82f297b051da1ed3 diff --git a/sw/qa/core/uwriter.cxx b/sw/qa/core/uwriter.cxx index 1a6d18d35c3a..cc95e3ce1da2 100644 --- a/sw/qa/core/uwriter.cxx +++ b/sw/qa/core/uwriter.cxx @@ -35,6 +35,7 @@ #include <breakit.hxx> #include <doc.hxx> +#include <IDocumentUndoRedo.hxx> #include <IDocumentRedlineAccess.hxx> #include <IDocumentFieldsAccess.hxx> #include <IDocumentStatistics.hxx> @@ -1067,7 +1068,6 @@ void SwDocTest::randomTest() RedlineFlags::NONE, RedlineFlags::On | RedlineFlags::ShowMask, RedlineFlags::On | RedlineFlags::Ignore, - RedlineFlags::On | RedlineFlags::Ignore | RedlineFlags::ShowMask, RedlineFlags::On | RedlineFlags::ShowInsert, RedlineFlags::On | RedlineFlags::ShowDelete }; @@ -1077,6 +1077,7 @@ void SwDocTest::randomTest() for( size_t rlm = 0; rlm < SAL_N_ELEMENTS(modes); rlm++ ) { + m_pDoc->GetIDocumentUndoRedo().DoUndo(true); m_pDoc->ClearDoc(); // setup redlining @@ -1085,15 +1086,31 @@ void SwDocTest::randomTest() for( int i = 0; i < 2000; i++ ) { - SwCursor aCrs(getRandomPosition(m_pDoc, i/20), nullptr); - aCrs.SetMark(); + std::shared_ptr<SwUnoCursor> pCrs( + m_pDoc->CreateUnoCursor(getRandomPosition(m_pDoc, i/20))); switch (getRand (i < 50 ? 3 : 6)) { // insert ops first case 0: { - if (!m_pDoc->getIDocumentContentOperations().InsertString(aCrs, getRandString())) { -// fprintf (stderr, "failed to insert string !\n"); + OUString const tmp(getRandString()); + sal_Int32 current(0); + sal_Int32 nextBreak(tmp.indexOf('\n')); + do + { + sal_Int32 const len((nextBreak == -1 ? tmp.getLength() : nextBreak - current)); + if (0 < len) + { + m_pDoc->getIDocumentContentOperations().InsertString( + *pCrs, tmp.copy(current, len)); + } + if (nextBreak != -1) + { + m_pDoc->getIDocumentContentOperations().SplitNode(*pCrs->GetPoint(), false); + current = nextBreak + 1; + nextBreak = tmp.indexOf('\n', current); + } } + while (nextBreak != -1); break; } case 1: @@ -1106,19 +1123,27 @@ void SwDocTest::randomTest() // movement / deletion ops later case 3: // deletion + pCrs->SetMark(); switch (getRand(6)) { case 0: - m_pDoc->getIDocumentContentOperations().DelFullPara(aCrs); + *pCrs->GetMark() = getRandomPosition(m_pDoc, 42); + m_pDoc->getIDocumentContentOperations().DelFullPara(*pCrs); break; case 1: - m_pDoc->getIDocumentContentOperations().DeleteRange(aCrs); + *pCrs->GetMark() = getRandomPosition(m_pDoc, 42); + m_pDoc->getIDocumentContentOperations().DeleteRange(*pCrs); break; case 2: - m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aCrs, !!getRand(1)); + *pCrs->GetMark() = getRandomPosition(m_pDoc, 42); + m_pDoc->getIDocumentContentOperations().DeleteAndJoin(*pCrs, !!getRand(1)); break; case 3: default: - m_pDoc->getIDocumentContentOperations().Overwrite(aCrs, getRandString()); + OUString const tmp(getRandString()); + if (tmp.getLength()) + { + m_pDoc->getIDocumentContentOperations().Overwrite(*pCrs, tmp); + } break; } break; @@ -1131,7 +1156,7 @@ void SwDocTest::randomTest() SwMoveFlags::REDLINES | SwMoveFlags::NO_DELFRMS; SwPosition aTo(getRandomPosition(m_pDoc, i/10)); - m_pDoc->getIDocumentContentOperations().MoveRange(aCrs, aTo, nFlags); + m_pDoc->getIDocumentContentOperations().MoveRange(*pCrs, aTo, nFlags); break; } commit c25acede28b623051f6ebe4e99362057aa8e7257 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Sep 4 18:55:13 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw: SwRedlineTable::DeleteAndDestroy() is surprisingly dangerous At least with the randomised test, it can happen that deleting one redline will recursively delete other redlines that are located in the hidden content section of the redline, or at least try to and crash because those have already been deleted before. The callers will either delete 1 redline, or delete all of them via DeleteAndDestroyAll(), so put a safer loop into DeleteAndDestroyAll() and have DeleteAndDestroy() only delete 1. Change-Id: I9c4225544a43a4a03f4eb7b6f56e7fe848c8ca54 diff --git a/sw/inc/docary.hxx b/sw/inc/docary.hxx index 20871385fa97..940789ad262e 100644 --- a/sw/inc/docary.hxx +++ b/sw/inc/docary.hxx @@ -345,7 +345,7 @@ public: void Remove( size_type nPos ); void Remove( const SwRangeRedline* p ); - void DeleteAndDestroy( size_type nPos, size_type nLen = 1 ); + void DeleteAndDestroy(size_type nPos); void DeleteAndDestroyAll(); void dumpAsXml(struct _xmlTextWriter* pWriter) const; @@ -389,7 +389,7 @@ public: void Insert( SwExtraRedline* p ); - void DeleteAndDestroy( sal_uInt16 nPos, sal_uInt16 nLen = 1 ); + void DeleteAndDestroy( sal_uInt16 nPos); void DeleteAndDestroyAll(); void dumpAsXml(struct _xmlTextWriter* pWriter) const; diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx index 950526187efc..56dfd57a82f9 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -605,26 +605,32 @@ void SwRedlineTable::Remove( size_type nP ) void SwRedlineTable::DeleteAndDestroyAll() { - DeleteAndDestroy(0, size()); -} - -void SwRedlineTable::DeleteAndDestroy( size_type nP, size_type nL ) -{ - SwDoc* pDoc = nullptr; - if( !nP && nL && nL == size() ) - pDoc = maVector.front()->GetDoc(); - - for( vector_type::const_iterator it = maVector.begin() + nP; it != maVector.begin() + nP + nL; ++it ) + if (maVector.empty()) + return; + SwDoc *const pDoc = maVector.front()->GetDoc(); + while (!maVector.empty()) + { + auto const pRedline = maVector.back(); + maVector.erase(maVector.back()); + LOKRedlineNotification(RedlineNotification::Remove, pRedline); + delete pRedline; + } + if (pDoc && !pDoc->IsInDtor()) { - LOKRedlineNotification(RedlineNotification::Remove, *it); - delete *it; + SwViewShell* pSh(pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() ); + if (pSh) + { + pSh->InvalidateWindows(SwRect(0, 0, SAL_MAX_INT32, SAL_MAX_INT32)); + } } - maVector.erase( maVector.begin() + nP, maVector.begin() + nP + nL ); +} - SwViewShell* pSh; - if( pDoc && !pDoc->IsInDtor() && - nullptr != ( pSh = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() ) ) - pSh->InvalidateWindows( SwRect( 0, 0, SAL_MAX_INT32, SAL_MAX_INT32 ) ); +void SwRedlineTable::DeleteAndDestroy(size_type const nP) +{ + auto const pRedline = maVector[nP]; + maVector.erase(maVector.begin() + nP); + LOKRedlineNotification(RedlineNotification::Remove, pRedline); + delete pRedline; } SwRedlineTable::size_type SwRedlineTable::FindNextOfSeqNo( size_type nSttPos ) const @@ -1883,7 +1889,7 @@ void SwExtraRedlineTable::Insert( SwExtraRedline* p ) //p->CallDisplayFunc(); } -void SwExtraRedlineTable::DeleteAndDestroy( sal_uInt16 nPos, sal_uInt16 nLen ) +void SwExtraRedlineTable::DeleteAndDestroy(sal_uInt16 const nPos) { /* SwDoc* pDoc = 0; @@ -1891,10 +1897,8 @@ void SwExtraRedlineTable::DeleteAndDestroy( sal_uInt16 nPos, sal_uInt16 nLen ) pDoc = front()->GetDoc(); */ - for( std::vector<SwExtraRedline*>::iterator it = m_aExtraRedlines.begin() + nPos; it != m_aExtraRedlines.begin() + nPos + nLen; ++it ) - delete *it; - - m_aExtraRedlines.erase( m_aExtraRedlines.begin() + nPos, m_aExtraRedlines.begin() + nPos + nLen ); + delete m_aExtraRedlines[nPos]; + m_aExtraRedlines.erase(m_aExtraRedlines.begin() + nPos); /* SwViewShell* pSh; @@ -1906,7 +1910,12 @@ void SwExtraRedlineTable::DeleteAndDestroy( sal_uInt16 nPos, sal_uInt16 nLen ) void SwExtraRedlineTable::DeleteAndDestroyAll() { - DeleteAndDestroy(0, m_aExtraRedlines.size()); + while (!m_aExtraRedlines.empty()) + { + auto const pRedline = m_aExtraRedlines.back(); + m_aExtraRedlines.pop_back(); + delete pRedline; + } } SwExtraRedline::~SwExtraRedline() commit ed81bd445dab56b1eaeea43254174fedb9e2c6e4 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Sep 4 18:52:56 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw: SwUndoOverwrite ctor shouldn't DeleteRedline if ... ... it's at the end of the node already, similar to CanGrouping(). Change-Id: Ic7c6f5caa6e69e9414112cb245db97fd5d79e87d diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx index bee06b365dd4..d5652ce85e6e 100644 --- a/sw/source/core/undo/unovwr.cxx +++ b/sw/source/core/undo/unovwr.cxx @@ -43,6 +43,13 @@ SwUndoOverwrite::SwUndoOverwrite( SwDoc* pDoc, SwPosition& rPos, : SwUndo(SwUndoId::OVERWRITE, pDoc), pRedlSaveData( nullptr ), bGroup( false ) { + SwTextNode *const pTextNd = rPos.nNode.GetNode().GetTextNode(); + assert(pTextNd); + sal_Int32 const nTextNdLen = pTextNd->GetText().getLength(); + + nSttNode = rPos.nNode.GetIndex(); + nSttContent = rPos.nContent.GetIndex(); + if( !pDoc->getIDocumentRedlineAccess().IsIgnoreRedline() && !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty() ) { SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(), @@ -52,16 +59,13 @@ SwUndoOverwrite::SwUndoOverwrite( SwDoc* pDoc, SwPosition& rPos, { pRedlSaveData.reset(); } + if (nSttContent < nTextNdLen) + { + pDoc->getIDocumentRedlineAccess().DeleteRedline(aPam, false, USHRT_MAX); + } } - nSttNode = rPos.nNode.GetIndex(); - nSttContent = rPos.nContent.GetIndex(); - - SwTextNode* pTextNd = rPos.nNode.GetNode().GetTextNode(); - OSL_ENSURE( pTextNd, "Overwrite not in a TextNode?" ); - bInsChar = true; - sal_Int32 nTextNdLen = pTextNd->GetText().getLength(); if( nSttContent < nTextNdLen ) // no pure insert? { aDelStr += OUStringLiteral1( pTextNd->GetText()[nSttContent] ); commit 873b1ed61ac8992b77f820cf604fa2def4c5f722 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Sep 4 16:21:56 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw: SwUndoOverwrite::CanGrouping() should ignore redlines for inserted ... characters; if the character is inserted at the end of the node, the aPam end position will have an invalid index Len()+1 and the DeleteRedline() will correct existing redlines onto that index, which will assert later. Change-Id: Ia31cd1937385fb10fd284e7add61c39f96b917ab diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx index e2fb76a19f63..bee06b365dd4 100644 --- a/sw/source/core/undo/unovwr.cxx +++ b/sw/source/core/undo/unovwr.cxx @@ -120,6 +120,7 @@ bool SwUndoOverwrite::CanGrouping( SwDoc* pDoc, SwPosition& rPos, rCC.isLetterNumeric( aInsStr, aInsStr.getLength()-1 ) ) return false; + if (!bInsChar && rPos.nContent.GetIndex() < pDelTextNd->GetText().getLength()) { SwRedlineSaveDatas aTmpSav; SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(), commit 6065be5754dab67455acaa35b2751212861820a8 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Sep 4 14:34:03 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw: avoid updating redlines to be empty in Overwrite() The problem is that SwIndexReg::Update will correct a 1-character redline in the middle of the newly-inserted part of the overwrite string into a 0-length redline, which then a later SwTextNode::Update() will correct in such a way that the whole thing becomes unsorted. Just delete redlines in the entire overwrite range, which should help; the aPam actually deletes them in the *last* character only which seems rather unintentional anyway. Change-Id: I61b6b312998e0779651d30f636312ef13556428c diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 1bb52e00e186..dc45775cbf25 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -2357,8 +2357,12 @@ bool DocumentContentOperationsManager::MoveAndJoin( SwPaM& rPaM, SwPosition& rPo return bRet; } +// Overwrite only uses the point of the PaM, the mark is ignored; characters +// are replaced from point until the end of the node; at the end of the node, +// characters are inserted. bool DocumentContentOperationsManager::Overwrite( const SwPaM &rRg, const OUString &rStr ) { + assert(rStr.getLength()); SwPosition& rPt = *const_cast<SwPosition*>(rRg.GetPoint()); if( m_rDoc.GetAutoCorrExceptWord() ) // Add to AutoCorrect { @@ -2382,6 +2386,7 @@ bool DocumentContentOperationsManager::Overwrite( const SwPaM &rRg, const OUStri ? pNode->GetpSwpHints()->Count() : 0; SwDataChanged aTmp( rRg ); SwIndex& rIdx = rPt.nContent; + sal_Int32 const nActualStart(rIdx.GetIndex()); sal_Int32 nStart = 0; bool bOldExpFlg = pNode->IsIgnoreDontExpand(); @@ -2443,14 +2448,14 @@ bool DocumentContentOperationsManager::Overwrite( const SwPaM &rRg, const OUStri if (!m_rDoc.GetIDocumentUndoRedo().DoesUndo() && !m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty()) { - SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() ); + SwPaM aPam(rPt.nNode, nActualStart, rPt.nNode, rPt.nContent.GetIndex()); m_rDoc.getIDocumentRedlineAccess().DeleteRedline( aPam, true, USHRT_MAX ); } else if( m_rDoc.getIDocumentRedlineAccess().IsRedlineOn() ) { // FIXME: this redline is WRONG: there is no DELETE, and the skipped // characters are also included in aPam - SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() ); + SwPaM aPam(rPt.nNode, nActualStart, rPt.nNode, rPt.nContent.GetIndex()); m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true); } diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index dc196aadc9ed..caec50025ef1 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -82,6 +82,8 @@ using namespace com::sun::star; for(SwRangeRedline* j : rTable) { // check for empty redlines + // note: these can destroy sorting in SwTextNode::Update() + // if there's another one wihout mark on the same pos. OSL_ENSURE( ( *(j->GetPoint()) != *(j->GetMark()) ) || ( j->GetContentIdx() != nullptr ), ERROR_PREFIX "empty redline" ); commit 393ead12c00824fb0145fab7dd0d4f48c954ae60 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Sep 4 11:51:02 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: SwDocTest: avoid deleting selections that ... ... start or end outside of the body in randomTest(). Also, it would be more interesting to delete parts of the one paragraph, not always the whole thing. Change-Id: I782bcde24e0ed542c32ae50b50997555fd32813f diff --git a/sw/qa/core/uwriter.cxx b/sw/qa/core/uwriter.cxx index f0055671a58a..1a6d18d35c3a 100644 --- a/sw/qa/core/uwriter.cxx +++ b/sw/qa/core/uwriter.cxx @@ -1041,12 +1041,20 @@ getRandomPosition(SwDoc *pDoc, int /* nOffset */) { const SwPosition aPos(pDoc->GetNodes().GetEndOfContent()); size_t nNodes = aPos.nNode.GetNode().GetIndex() - aPos.nNode.GetNode().StartOfSectionIndex(); - size_t n = comphelper::rng::uniform_size_distribution(0, nNodes); + // exclude body start/end node + size_t n = comphelper::rng::uniform_size_distribution(1, nNodes - 1); SwPaM pam(aPos); for (sal_uLong i = 0; i < n; ++i) { pam.Move(fnMoveBackward, GoInNode); } + SwTextNode *const pTextNode(pam.GetPoint()->nNode.GetNode().GetTextNode()); + assert(pTextNode); + int n2 = comphelper::rng::uniform_int_distribution(0, pTextNode->Len()); + for (sal_Int32 i = 0; i < n2; ++i) + { + pam.Move(fnMoveBackward, GoInContent); + } return *pam.GetPoint(); } commit 816461162da2c23915ef2f2e29209454e17e981d Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Mon Sep 3 18:07:29 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: update frames on redline ops When Delete redline is created, removed, accepted, rejected & undo/redo of all of these, update all the text frames so they're merged or not, as required. Change-Id: I08aa6aea270a50d19f4bda0caf016870a42a8dd3 diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 11af40aaa469..1bb52e00e186 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -44,6 +44,7 @@ #include <fmtcnct.hxx> #include <SwStyleNameMapper.hxx> #include <redline.hxx> +#include <txtfrm.hxx> #include <unocrsr.hxx> #include <mvsave.hxx> #include <ndtxt.hxx> @@ -3619,6 +3620,11 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true ); m_rDoc.getIDocumentState().SetModified(); + // sw_redlinehide: 2 reasons why this is needed: + // 1. it's the first redline in node => RedlineDelText was sent but ignored + // 2. redline spans multiple nodes => must merge text frames + sw::UpdateFramesForAddDeleteRedline(rPam); + if (pUndo) { m_rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::EMPTY, nullptr ); diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index ad9c292810a1..dc196aadc9ed 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -19,6 +19,7 @@ #include <DocumentRedlineManager.hxx> #include <frmfmt.hxx> #include <rootfrm.hxx> +#include <txtfrm.hxx> #include <doc.hxx> #include <IDocumentUndoRedo.hxx> #include <IDocumentState.hxx> @@ -113,6 +114,74 @@ using namespace com::sun::star; #endif +namespace sw { + +void UpdateFramesForAddDeleteRedline(SwPaM const& rPam) +{ + SwTextNode *const pStartNode(rPam.Start()->nNode.GetNode().GetTextNode()); + std::vector<SwTextFrame*> frames; + SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pStartNode); + for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) + { + if (pFrame->getRootFrame()->IsHideRedlines()) + { + frames.push_back(pFrame); + } + } + for (SwTextFrame * pFrame : frames) + { + SwTextNode & rFirstNode(pFrame->GetMergedPara() + ? *pFrame->GetMergedPara()->pFirstNode + : *pStartNode); + assert(rFirstNode.GetIndex() <= pStartNode->GetIndex()); + // clear old one first to avoid DelFrames confusing updates & asserts... + pFrame->SetMergedPara(nullptr); + pFrame->SetMergedPara(sw::CheckParaRedlineMerge( + *pFrame, rFirstNode, sw::FrameMode::Existing)); + } +} + +void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) +{ + if (rPam.GetPoint()->nNode != rPam.GetMark()->nNode) + { + // first, call CheckParaRedlineMerge on the first paragraph, + // to init flag on new merge range (if any) + 1st node post the merge + SwTextNode *const pStartNode(rPam.Start()->nNode.GetNode().GetTextNode()); + std::vector<SwTextFrame*> frames; + SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pStartNode); + for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) + { + if (pFrame->getRootFrame()->IsHideRedlines()) + { + frames.push_back(pFrame); + } + } + for (SwTextFrame * pFrame : frames) + { + if (auto const pMergedPara = pFrame->GetMergedPara()) + { + assert(pMergedPara->pFirstNode->GetIndex() <= pStartNode->GetIndex()); + // clear old one first to avoid DelFrames confusing updates & asserts... + SwTextNode & rFirstNode(*pMergedPara->pFirstNode); + pFrame->SetMergedPara(nullptr); + pFrame->SetMergedPara(sw::CheckParaRedlineMerge( + *pFrame, rFirstNode, sw::FrameMode::Existing)); + } + } + // now start node until end of merge + 1 has proper flags; MakeFrames + // should pick up from the next node in need of frames by checking flags + if (!frames.empty()) + { + SwNodeIndex const start(*pStartNode, +1); + SwNodeIndex const end(rPam.End()->nNode, +1); // end is exclusive + ::MakeFrames(&rDoc, start, end); + } + } +} + +} // namespace sw + namespace { inline bool IsPrevPos( const SwPosition & rPos1, const SwPosition & rPos2 ) @@ -294,6 +363,7 @@ namespace { bool bRet = true; SwRangeRedline* pRedl = rArr[ rPos ]; + SwDoc& rDoc = *pRedl->GetDoc(); SwPosition *pRStt = nullptr, *pREnd = nullptr; SwComparePosition eCmp = SwComparePosition::Outside; if( pSttRng && pEndRng ) @@ -309,7 +379,6 @@ namespace { case nsRedlineType_t::REDLINE_INSERT: { - SwDoc& rDoc = *pRedl->GetDoc(); const SwPosition *pDelStt = nullptr, *pDelEnd = nullptr; bool bDelRedl = false; switch( eCmp ) @@ -390,6 +459,8 @@ namespace { SwRangeRedline* pNew = nullptr; bool bCheck = false, bReplace = false; + SwPaM const updatePaM(pSttRng ? *pSttRng : *pRedl->Start(), + pEndRng ? *pEndRng : *pRedl->End()); switch( eCmp ) { @@ -473,6 +544,8 @@ namespace rArr.Remove( pRedl ); rArr.Insert( pRedl ); } + + sw::UpdateFramesForRemoveDeleteRedline(rDoc, updatePaM); } break; diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx index 10bde328c903..a52bf0f14fa0 100644 --- a/sw/source/core/inc/txtfrm.hxx +++ b/sw/source/core/inc/txtfrm.hxx @@ -108,6 +108,9 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged, void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode); void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool bRecreateMerged); +void UpdateFramesForAddDeleteRedline(SwPaM const& rPam); +void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam); + } // namespace sw /// Represents the visualization of a paragraph. Typical upper is an diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx index 58d2de808363..fb1d30f9f953 100644 --- a/sw/source/core/undo/unredln.cxx +++ b/sw/source/core/undo/unredln.cxx @@ -25,6 +25,7 @@ #include <swundo.hxx> #include <pam.hxx> #include <ndtxt.hxx> +#include <txtfrm.hxx> #include <UndoCore.hxx> #include <UndoDelete.hxx> #include <strings.hrc> @@ -106,6 +107,17 @@ void SwUndoRedline::UndoImpl(::sw::UndoRedoContext & rContext) } SetPaM(rPam, true); } + + // update frames after calling SetSaveData + if (dynamic_cast<SwUndoRedlineDelete*>(this)) + { + sw::UpdateFramesForRemoveDeleteRedline(rDoc, rPam); + } + else if (dynamic_cast<SwUndoAcceptRedline*>(this) + || dynamic_cast<SwUndoRejectRedline*>(this)) + { // (can't check here if there's a delete redline being accepted) + sw::UpdateFramesForAddDeleteRedline(rPam); + } } void SwUndoRedline::RedoImpl(::sw::UndoRedoContext & rContext) @@ -191,6 +203,7 @@ void SwUndoRedlineDelete::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam) { rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline(*mpRedlData, rPam), false ); } + sw::UpdateFramesForAddDeleteRedline(rPam); } bool SwUndoRedlineDelete::CanGrouping( const SwUndoRedlineDelete& rNext ) commit 458e35da41e84e38febb758b0ce163faebb00bd2 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Mon Sep 3 15:12:29 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: remove a pointless level of indentation Change-Id: I82893951b6e227ab1ed6423e08a0370561482cd8 diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index d9b9250d617a..11af40aaa469 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -3563,92 +3563,89 @@ DocumentContentOperationsManager::~DocumentContentOperationsManager() bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPam, const bool ) { - OSL_ENSURE( m_rDoc.getIDocumentRedlineAccess().IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" ); + assert(m_rDoc.getIDocumentRedlineAccess().IsRedlineOn()); - { - SwUndoRedlineDelete* pUndo = nullptr; - RedlineFlags eOld = m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags(); - m_rDoc.GetDocumentRedlineManager().checkRedlining( eOld ); + SwUndoRedlineDelete* pUndo = nullptr; + RedlineFlags eOld = m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags(); + m_rDoc.GetDocumentRedlineManager().checkRedlining( eOld ); - auto & rDMA(*m_rDoc.getIDocumentMarkAccess()); - std::vector<std::unique_ptr<SwUndo>> MarkUndos; - for (auto iter = rDMA.getAnnotationMarksBegin(); - iter != rDMA.getAnnotationMarksEnd(); ) + auto & rDMA(*m_rDoc.getIDocumentMarkAccess()); + std::vector<std::unique_ptr<SwUndo>> MarkUndos; + for (auto iter = rDMA.getAnnotationMarksBegin(); + iter != rDMA.getAnnotationMarksEnd(); ) + { + // tdf#111524 remove annotation marks that have their field + // characters deleted + SwPosition const& rEndPos((**iter).GetMarkEnd()); + if (*rPam.Start() < rEndPos && rEndPos <= *rPam.End()) { - // tdf#111524 remove annotation marks that have their field - // characters deleted - SwPosition const& rEndPos((**iter).GetMarkEnd()); - if (*rPam.Start() < rEndPos && rEndPos <= *rPam.End()) + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { - if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) - { - MarkUndos.emplace_back(o3tl::make_unique<SwUndoDeleteBookmark>(**iter)); - } - // iter is into annotation mark vector so must be dereferenced! - rDMA.deleteMark(&**iter); - // this invalidates iter, have to start over... - iter = rDMA.getAnnotationMarksBegin(); + MarkUndos.emplace_back(o3tl::make_unique<SwUndoDeleteBookmark>(**iter)); } - else - { // marks are sorted by start - if (*rPam.End() < (**iter).GetMarkStart()) - { - break; - } - ++iter; + // iter is into annotation mark vector so must be dereferenced! + rDMA.deleteMark(&**iter); + // this invalidates iter, have to start over... + iter = rDMA.getAnnotationMarksBegin(); + } + else + { // marks are sorted by start + if (*rPam.End() < (**iter).GetMarkStart()) + { + break; } + ++iter; } + } - if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) + { + /* please don't translate -- for cultural reasons this comment is protected + until the redline implementation is finally fixed some day */ + //JP 06.01.98: MUSS noch optimiert werden!!! + m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags( + RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); + pUndo = new SwUndoRedlineDelete( rPam, SwUndoId::DELETE ); + const SwRewriter aRewriter = pUndo->GetRewriter(); + m_rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::DELETE, &aRewriter ); + for (auto& it : MarkUndos) { - - /* please don't translate -- for cultural reasons this comment is protected - until the redline implementation is finally fixed some day */ - //JP 06.01.98: MUSS noch optimiert werden!!! - m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags( - RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete ); - pUndo = new SwUndoRedlineDelete( rPam, SwUndoId::DELETE ); - const SwRewriter aRewriter = pUndo->GetRewriter(); - m_rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::DELETE, &aRewriter ); - for (auto& it : MarkUndos) - { - m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release()); - } - m_rDoc.GetIDocumentUndoRedo().AppendUndo( pUndo ); + m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release()); } + m_rDoc.GetIDocumentUndoRedo().AppendUndo( pUndo ); + } - if ( *rPam.GetPoint() != *rPam.GetMark() ) - m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true ); - m_rDoc.getIDocumentState().SetModified(); + if (*rPam.GetPoint() != *rPam.GetMark()) + m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true ); + m_rDoc.getIDocumentState().SetModified(); - if ( pUndo ) + if (pUndo) + { + m_rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::EMPTY, nullptr ); + // ??? why the hell is the AppendUndo not below the + // CanGrouping, so this hideous cleanup wouldn't be necessary? + // bah, this is redlining, probably changing this would break it... + if (m_rDoc.GetIDocumentUndoRedo().DoesGroupUndo()) { - m_rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::EMPTY, nullptr ); - // ??? why the hell is the AppendUndo not below the - // CanGrouping, so this hideous cleanup wouldn't be necessary? - // bah, this is redlining, probably changing this would break it... - if ( m_rDoc.GetIDocumentUndoRedo().DoesGroupUndo() ) + SwUndo * const pLastUndo( m_rDoc.GetUndoManager().GetLastUndo() ); + SwUndoRedlineDelete *const pUndoRedlineDel( dynamic_cast<SwUndoRedlineDelete*>(pLastUndo) ); + if (pUndoRedlineDel) { - SwUndo * const pLastUndo( m_rDoc.GetUndoManager().GetLastUndo() ); - SwUndoRedlineDelete * const pUndoRedlineDel( dynamic_cast< SwUndoRedlineDelete* >( pLastUndo ) ); - if ( pUndoRedlineDel ) + bool const bMerged = pUndoRedlineDel->CanGrouping( *pUndo ); + if (bMerged) { - bool const bMerged = pUndoRedlineDel->CanGrouping( *pUndo ); - if ( bMerged ) - { - ::sw::UndoGuard const undoGuard( m_rDoc.GetIDocumentUndoRedo() ); - SwUndo const* const pDeleted = m_rDoc.GetUndoManager().RemoveLastUndo(); - OSL_ENSURE( pDeleted == pUndo, "DeleteAndJoinWithRedlineImpl: " - "undo removed is not undo inserted?" ); - delete pDeleted; - } + ::sw::UndoGuard const undoGuard( m_rDoc.GetIDocumentUndoRedo() ); + SwUndo const*const pDeleted = m_rDoc.GetUndoManager().RemoveLastUndo(); + OSL_ENSURE( pDeleted == pUndo, "DeleteAndJoinWithRedlineImpl: " + "undo removed is not undo inserted?" ); + delete pDeleted; } } - //JP 06.01.98: MUSS noch optimiert werden!!! - m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags( eOld ); } - return true; + //JP 06.01.98: MUSS noch optimiert werden!!! + m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags( eOld ); } + return true; } bool DocumentContentOperationsManager::DeleteAndJoinImpl( SwPaM & rPam, commit a17c75e87b5d0a35f824eda6a5ca65a667be8b9b Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Mon Sep 3 12:18:25 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: handle delete-without-redline inside of redline The problem is that the SwInsText/SwDelText do not transfer the "deleted-ness" of the text from one node to the other in the SwTextFrame, so add a new hint that is sent after SwInsText & before SwDelText to move the info that is in the extents vector. Change-Id: I32d8dbe52a18556d8dc2c50a47246a6600fdb355 diff --git a/sw/inc/hints.hxx b/sw/inc/hints.hxx index bee0ebb1c21a..bdf2eceaa8a6 100644 --- a/sw/inc/hints.hxx +++ b/sw/inc/hints.hxx @@ -31,6 +31,7 @@ class SwNodes; class SwPageFrame; class SwFrame; class SwHistory; +class SwTextNode; // Base class for all Message-Hints: // "Overhead" of SfxPoolItem is handled here @@ -95,6 +96,18 @@ public: namespace sw { +/// text is moved into pDestNode +class MoveText : public SfxHint +{ +public: + SwTextNode * pDestNode; + sal_Int32 nDestStart; + sal_Int32 nSourceStart; + sal_Int32 nLen; + + MoveText(SwTextNode *pD, sal_Int32 nD, sal_Int32 nS, sal_Int32 nL); +}; + /// new delete redline is created class RedlineDelText : public SfxHint { diff --git a/sw/source/core/attr/hints.cxx b/sw/source/core/attr/hints.cxx index 7c1ff2a40aec..7746058a7e1e 100644 --- a/sw/source/core/attr/hints.cxx +++ b/sw/source/core/attr/hints.cxx @@ -48,6 +48,11 @@ SwDelText::SwDelText( sal_Int32 nS, sal_Int32 nL ) namespace sw { +MoveText::MoveText(SwTextNode *const pD, sal_Int32 const nD, sal_Int32 const nS, sal_Int32 const nL) + : pDestNode(pD), nDestStart(nD), nSourceStart(nS), nLen(nL) +{ +} + RedlineDelText::RedlineDelText(sal_Int32 const nS, sal_Int32 const nL) : nStart(nS), nLen(nL) { diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index dcb4a632ef58..ef792d95d9ea 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -1656,6 +1656,72 @@ static void lcl_ModifyOfst(SwTextFrame* pFrame, TextFrameIndex const nPos, TextF } } +namespace { + +void UpdateMergedParaForMove(sw::MergedPara & rMerged, + SwTextFrame & rTextFrame, + bool & o_rbRecalcFootnoteFlag, + SwTextNode const& rDestNode, + SwTextNode const& rNode, + sal_Int32 const nDestStart, + sal_Int32 const nSourceStart, + sal_Int32 const nLen) +{ + std::vector<std::pair<sal_Int32, sal_Int32>> deleted; + sal_Int32 const nSourceEnd(nSourceStart + nLen); + sal_Int32 nLastEnd(0); + for (auto it = rMerged.extents.begin(); it != rMerged.extents.end(); ++it) + { + if (it->pNode == &rNode) + { + sal_Int32 const nStart(std::max(nLastEnd, nSourceStart)); + sal_Int32 const nEnd(std::min(it->nStart, nSourceEnd)); + if (nStart < nEnd) + { + deleted.emplace_back(nStart, nEnd); + } + nLastEnd = it->nEnd; + if (nSourceEnd <= it->nEnd) + { + break; + } + } + else if (rNode.GetIndex() < it->pNode->GetIndex()) + { + break; + } + } + if (nLastEnd != rNode.Len() + nLen) // add nLen, string was removed already + { + assert(rNode.Len() == 0 || nLastEnd < nSourceEnd); + if (nLastEnd < nSourceEnd) + { + deleted.emplace_back(std::max(nLastEnd, nSourceStart), nSourceEnd); + } + } + if (!deleted.empty()) + { + o_rbRecalcFootnoteFlag = true; + for (auto it : deleted) + { + sal_Int32 const nStart(it.first - nSourceStart + nDestStart); + TextFrameIndex const nDeleted = UpdateMergedParaForDelete(rMerged, false, + rDestNode, nStart, it.second - it.first); + assert(nDeleted == it.second - it.first); + assert(nDeleted); + // InvalidateRange/lcl_SetScriptInval was called sufficiently for SwInsText + lcl_SetWrong(rTextFrame, rDestNode, nStart, -nDeleted, false); + if (rTextFrame.HasFollow()) + { + TextFrameIndex const nIndex(sw::MapModelToView(rMerged, &rDestNode, nStart)); + lcl_ModifyOfst(&rTextFrame, nIndex, nDeleted); // FIXME why positive? + } + } + } +} + +} // namespace + /** * Related: fdo#56031 filter out attribute changes that don't matter for * humans/a11y to stop flooding the destination mortal with useless noise @@ -1675,6 +1741,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) { SfxPoolItem const* pOld(nullptr); SfxPoolItem const* pNew(nullptr); + sw::MoveText const* pMoveText(nullptr); sw::RedlineDelText const* pRedlineDelText(nullptr); sw::RedlineUnDelText const* pRedlineUnDelText(nullptr); @@ -1683,6 +1750,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) pOld = pHint->m_pOld; pNew = pHint->m_pNew; } + else if (auto const pHt = dynamic_cast<sw::MoveText const*>(&rHint)) + { + pMoveText = pHt; + } else if (auto const pHynt = dynamic_cast<sw::RedlineDelText const*>(&rHint)) { pRedlineDelText = pHynt; @@ -1805,6 +1876,27 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) lcl_ModifyOfst( this, nPos, nLen ); } } + else if (pMoveText) + { + if (m_pMergedPara + && m_pMergedPara->pFirstNode->GetIndex() <= pMoveText->pDestNode->GetIndex() + && pMoveText->pDestNode->GetIndex() <= m_pMergedPara->pLastNode->GetIndex()) + { // if it's not 2 nodes in merged frame, assume the target node doesn't have frames at all + assert(std::abs(static_cast<long>(rNode.GetIndex()) - static_cast<long>(pMoveText->pDestNode->GetIndex())) == 1); + UpdateMergedParaForMove(*m_pMergedPara, + *this, + bRecalcFootnoteFlag, + *pMoveText->pDestNode, rNode, + pMoveText->nDestStart, + pMoveText->nSourceStart, + pMoveText->nLen); + } + else + { + // there is a situation where this is okay: from JoinNext, which will then call CheckResetRedlineMergeFlag, which will then create merged from scratch for this frame + // assert(!m_pMergedPara || !getRootFrame()->IsHideRedlines() || !pMoveText->pDestNode->getLayoutFrame(getRootFrame())); + } + } else switch (nWhich) { case RES_LINENUMBER: diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index 5f5869905b89..a8d672dda16e 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -2503,6 +2503,8 @@ void SwTextNode::CutImpl( SwTextNode * const pDest, const SwIndex & rDestStart, // want to find their anchor text frame in the follow chain SwInsText aInsHint( nDestStart, nLen ); pDest->ModifyNotification( nullptr, &aInsHint ); + sw::MoveText const moveHint(pDest, nDestStart, nTextStartIdx, nLen); + CallSwClientNotify(moveHint); SwDelText aDelHint( nTextStartIdx, nLen ); ModifyNotification( nullptr, &aDelHint ); commit c680b7f425d007663cd3cbad35fdbce0d88bd694 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Fri Aug 31 19:14:58 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: call CompressRedlines later in DeleteRange* DocumentContentOperationsManager::DeleteRange* functions should call CompressRedlines after sw_JoinText, because otherwise if there's a join, the FillSaveData in SwUndoDelete ctor will split redlines that contain the selection into 2, and they won't be recombined although CanCombine is true for them. If you do 2 operations, then on Undo of the second, SetSaveData will restore the previous redlines and join them into 1, but then it will assert because it expects 2 redlines, pointlessly split. Change-Id: I1df3f2205b4f16904f66b5af1f3b9f0ccbaf24a0 diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index f6a2562983cd..d9b9250d617a 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -1763,6 +1763,12 @@ void DocumentContentOperationsManager::DeleteSection( SwNode *pNode ) void DocumentContentOperationsManager::DeleteRange( SwPaM & rPam ) { lcl_DoWithBreaks( *this, rPam, &DocumentContentOperationsManager::DeleteRangeImpl ); + + if (!m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline() + && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty()) + { + m_rDoc.getIDocumentRedlineAccess().CompressRedlines(); + } } bool DocumentContentOperationsManager::DelFullPara( SwPaM& rPam ) @@ -3667,6 +3673,12 @@ bool DocumentContentOperationsManager::DeleteAndJoinImpl( SwPaM & rPam, ::sw_JoinText( rPam, bJoinPrev ); } + if (!m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline() + && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty()) + { + m_rDoc.getIDocumentRedlineAccess().CompressRedlines(); + } + return true; } @@ -3859,8 +3871,6 @@ bool DocumentContentOperationsManager::DeleteRangeImplImpl(SwPaM & rPam) } while( false ); - if( !m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() ) - m_rDoc.getIDocumentRedlineAccess().CompressRedlines(); m_rDoc.getIDocumentState().SetModified(); return true; commit 4f016edcbdbdb417f623450cc461aff5f1c04fd4 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Aug 22 17:09:02 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: SwUndoDelete This is problematic because of the calls to SplitNode. Ideally we'd want the SplitNode to create merged frames already, but that doesn't seem to be easy to achieve; several problems with this are: 1. the redlines are only restored at the end of UndoImpl 2. even if we store another set of SwRedlineSaveDatas right before the Join (while preventing the first SwRedlineSaveDatas from deleting them), and restore them by passing a closure to SplitNode, there are complaints about empty redlines, and also this case isn't handled properly: f<delete start>o<redline start>o b<redline end>a<redline start>r b<redline end>a<delete end>z So instead, let SplitNode create whatever frames it does, and fix it up at the end manually on the start node's frames. This necessitates delaying the creation of the frames on the moved nodes until the end too. Change-Id: I8ba2967659cc2ddbe6f7c40e0447d79601498ed6 diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx index 7e942b427ecb..f4f6c5559d85 100644 --- a/sw/source/core/undo/undel.cxx +++ b/sw/source/core/undo/undel.cxx @@ -41,6 +41,9 @@ #include <sfx2/app.hxx> #include <fldbas.hxx> #include <fmtfld.hxx> +#include <frmtool.hxx> +#include <txtfrm.hxx> +#include <rootfrm.hxx> #include <strings.hrc> #include <vector> @@ -763,6 +766,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) SwNodeIndex aIdx(rDoc.GetNodes(), nCalcStt); SwNode* pInsNd = &aIdx.GetNode(); + SwNode* pMovedNode = nullptr; { // code block so that SwPosition is detached when deleting a Node SwPosition aPos( aIdx ); @@ -838,7 +842,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) ++aPos.nNode; } } - SwNode* pMovedNode = nullptr; if( m_nSectDiff ) { sal_uLong nMoveIndex = aPos.nNode.GetIndex(); @@ -866,7 +869,11 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) { SwNodeRange aRange( *m_pMvStt, 0, *m_pMvStt, m_nNode ); SwNodeIndex aCopyIndex( aPos.nNode, -1 ); - rDoc.GetUndoManager().GetUndoNodes().Copy_( aRange, aPos.nNode ); + rDoc.GetUndoManager().GetUndoNodes().Copy_(aRange, aPos.nNode, + // sw_redlinehide: delay creating frames: the flags on the + // nodes aren't necessarily up-to-date, and the redlines + // from m_pRedlSaveData aren't applied yet... + false); if( m_nReplaceDummy ) { @@ -889,9 +896,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) } } - if( pMovedNode ) - lcl_MakeAutoFrames(*rDoc.GetSpzFrameFormats(), pMovedNode->GetIndex()); - if( m_aSttStr ) { aPos.nNode = nSttNode - m_nNdDiff + ( m_bJoinNext ? 0 : m_nReplaceDummy ); @@ -958,6 +962,52 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) if( m_pRedlSaveData ) SetSaveData(rDoc, *m_pRedlSaveData); + if (m_aSttStr && (!m_bFromTableCopy || 0 != m_nNode)) + { + // only now do we have redlines in the document again; fix up the split + // frames + SwTextNode *const pStartNode(aIdx.GetNodes()[nSttNode]->GetTextNode()); + assert(pStartNode); + std::vector<SwTextFrame*> frames; + SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pStartNode); + for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) + { + if (pFrame->getRootFrame()->IsHideRedlines()) + { + frames.push_back(pFrame); + } + } + for (SwTextFrame * pFrame : frames) + { + // SplitNode could have moved the original frame to the start node + // & created a new one on end, or could have created new frame on + // start node... grab start node's frame and recreate MergedPara. + SwTextNode & rFirstNode(pFrame->GetMergedPara() + ? *pFrame->GetMergedPara()->pFirstNode + : *pStartNode); + assert(rFirstNode.GetIndex() <= pStartNode->GetIndex()); + pFrame->SetMergedPara(sw::CheckParaRedlineMerge( + *pFrame, rFirstNode, sw::FrameMode::Existing)); + // note: this may or may not delete frames on the end node + } + } + + // create frames after SetSaveData has recreated redlines + if (0 != m_nNode) + { + // don't include end node in the range: it may have been merged already + // by the start node, or it may be merged by one of the moved nodes, + // but if it isn't merged, its current frame(s) should be good... + SwNodeIndex const start(rDoc.GetNodes(), nSttNode + (m_bDelFullPara ? 0 : 1)); + SwNodeIndex const end(rDoc.GetNodes(), nEndNode); + ::MakeFrames(&rDoc, start, end); + } + + if (pMovedNode) + { // probably better do this after creating all frames + lcl_MakeAutoFrames(*rDoc.GetSpzFrameFormats(), pMovedNode->GetIndex()); + } + AddUndoRedoPaM(rContext, true); } commit a94756ddcb29e993c426f98e195c54879c99e0bf Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Aug 22 15:09:59 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: something about Join Change-Id: I047b6008c5f0bb6e79c63421a4dba09ba8cf3320 Todo: remember what i was thinking when i wrote this diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx index 89454ea879ae..54c6a1c56e74 100644 --- a/sw/source/core/doc/docedt.cxx +++ b/sw/source/core/doc/docedt.cxx @@ -412,7 +412,13 @@ bool sw_JoinText( SwPaM& rPam, bool bJoinPrev ) rPam.GetBound( false ) = aAlphaPos; } // delete the Node, at last! + SwNode::Merge const eOldMergeFlag(pOldTextNd->GetRedlineMergeFlag()); + if (eOldMergeFlag == SwNode::Merge::First) + { + sw::MoveDeletedPrevFrames(*pOldTextNd, *pTextNd); + } pDoc->GetNodes().Delete( aOldIdx ); + sw::CheckResetRedlineMergeFlag(*pTextNd, eOldMergeFlag == SwNode::Merge::NonFirst); } else { diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx index 028c3605aa50..10bde328c903 100644 --- a/sw/source/core/inc/txtfrm.hxx +++ b/sw/source/core/inc/txtfrm.hxx @@ -105,6 +105,9 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged, bool isRealDelete, SwTextNode const& rNode, sal_Int32 nIndex, sal_Int32 nLen); +void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode); +void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool bRecreateMerged); + } // namespace sw /// Represents the visualization of a paragraph. Typical upper is an @@ -726,7 +729,7 @@ public: static void repaintTextFrames( const SwTextNode& rNode ); - void RegisterToNode( SwTextNode& ); + void RegisterToNode(SwTextNode &, bool isForceNodeAsFirst = false); virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const override; }; diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx index 3a37ae92bc7f..8b8e7bd22610 100644 --- a/sw/source/core/layout/ssfrm.cxx +++ b/sw/source/core/layout/ssfrm.cxx @@ -440,14 +440,19 @@ SwContentFrame::~SwContentFrame() { } -void SwTextFrame::RegisterToNode(SwTextNode & rNode) +void SwTextFrame::RegisterToNode(SwTextNode & rNode, bool const isForceNodeAsFirst) { + if (isForceNodeAsFirst && m_pMergedPara) + { // nothing registered here, in particular no redlines + assert(m_pMergedPara->pFirstNode->GetIndex() + 1 == rNode.GetIndex()); + assert(!m_pMergedPara->pFirstNode->HasAnyIndex()); + } assert(&rNode != GetDep()); assert(!m_pMergedPara || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex()) || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex())); SwTextNode & rFirstNode( - (m_pMergedPara && m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex()) + (!isForceNodeAsFirst && m_pMergedPara && m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex()) ? *m_pMergedPara->pFirstNode : rNode); // sw_redlinehide: use New here, because the only caller also calls lcl_ChangeFootnoteRef diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index a826aabcf625..5f5869905b89 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -830,8 +830,51 @@ void SwTextNode::MoveTextAttr_To_AttrSet() } -namespace { +namespace sw { + + // None,Node->None + // None,First->First + // First,NonFirst->First + // NonFirst,First->NonFirst + // NonFirst,None->NonFirst + +void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode) +{ + std::vector<SwTextFrame*> frames; + SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rDeletedPrev); + for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) + { + frames.push_back(pFrame); + } + { + auto frames2(frames); + SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIt(rNode); + for (SwTextFrame* pFrame = aIt.First(); pFrame; pFrame = aIt.Next()) + { + auto const it(std::find(frames2.begin(), frames2.end(), pFrame)); + assert(it != frames2.end()); + frames2.erase(it); + } + assert(frames2.empty()); + } + for (SwTextFrame * pFrame : frames) + { + pFrame->RegisterToNode(rNode, true); +#if 0 + if (pFrame->m_pMergedPara && pFrame->m_pMergedPara->pFirstNode == &rDeletedPrev && GetIndex() <= pFrame->m_pMergedPara->pLastNode->GetIndex()) + { + pFrame->listeners.StopListening(&rDeletedPrev); + pFrame->m_pMergedPara->pFirstNode = &rNode; + &rNode.SetRedlineMergeFlag(SwNodes::Merge::First); + } +#endif + } +} + + /// not only fix the flag; if prev is First the frame is actually deleted!!! + // if prev is First : must not delete frame but move it + // if prev is NonFirst : must delete frame (if this is First/None) & merge into prev void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool const bRecreateMerged) { if (bRecreateMerged) @@ -850,6 +893,9 @@ void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool const bRecreateMerged) assert(rFirstNode.GetIndex() <= rNode.GetIndex()); pFrame->SetMergedPara(sw::CheckParaRedlineMerge( *pFrame, rFirstNode, sw::FrameMode::Existing)); + assert(pFrame->GetMergedPara()); + assert(pFrame->GetMergedPara()->listener.IsListeningTo(&rNode)); + assert(rNode.GetIndex() <= pFrame->GetMergedPara()->pLastNode->GetIndex()); } } else if (rNode.GetRedlineMergeFlag() != SwNode::Merge::None) @@ -1055,6 +1101,10 @@ void SwTextNode::JoinPrev() pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, true ); } SwNode::Merge const eOldMergeFlag(pTextNode->GetRedlineMergeFlag()); + if (eOldMergeFlag == SwNode::Merge::First) + { + sw::MoveDeletedPrevFrames(*pTextNode, *this); + } rNds.Delete(aIdx); SetWrong( pList, false ); SetGrammarCheck( pList3, false ); commit 7822345a4dae69e8aa019bacf0c73e89a9ff09d7 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Aug 22 15:04:18 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 sw_redlinehide_2: DelFrames is called for hidden nodes too now Change-Id: I9933d8b8ee29bb4da74819d7d2350a5b2b04aa09 diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 8d8a4072bcdd..3e6ff2d4f565 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -4348,8 +4348,9 @@ static void UnHideRedlines(SwRootFrame & rLayout, { if (rNode.IsContentNode()) { - // note: no-op for NonFirst nodes, only Hidden will delete - static_cast<SwContentNode&>(rNode).DelFrames(&rLayout); + // note: nothing to do here, already done + auto const pFrame(static_cast<SwContentNode&>(rNode).getLayoutFrame(&rLayout)); + assert(!pFrame || static_cast<SwTextFrame*>(pFrame)->GetMergedPara()->pFirstNode != &rNode); } else if (rNode.IsTableNode()) { commit efea694ce62de1b2d4c7449ea21a8cb6d2f12d2c Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Aug 22 13:26:18 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 Revert "this looks like a wrong path..." This reverts commit 391b6325117483c73f6fd0fb2286b37aaeeb46e4. diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx index b3204109a8a0..fb4006334a15 100644 --- a/sw/inc/IDocumentContentOperations.hxx +++ b/sw/inc/IDocumentContentOperations.hxx @@ -22,7 +22,6 @@ #include <sal/types.h> #include <rtl/ustring.hxx> -#include <functional> #include "swtypes.hxx" class SwPaM; @@ -38,9 +37,6 @@ class SwFrameFormat; class SwDrawFrameFormat; class SwFlyFrameFormat; class SwNodeIndex; -class SwTextNode; - -namespace sw { namespace mark { enum class RestoreMode; } } namespace utl { class TransliterationWrapper; } namespace svt { class EmbeddedObjectRef; } @@ -190,8 +186,7 @@ public: /** Split a node at rPos (implemented only for TextNode). */ - virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart, - std::function<void ()> const* pRedlineRestore = nullptr) = 0; + virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart) = 0; virtual bool AppendTextNode(SwPosition& rPos) = 0; diff --git a/sw/inc/IDocumentRedlineAccess.hxx b/sw/inc/IDocumentRedlineAccess.hxx index d6c44b24e680..a68af07fb707 100644 --- a/sw/inc/IDocumentRedlineAccess.hxx +++ b/sw/inc/IDocumentRedlineAccess.hxx @@ -180,7 +180,7 @@ public: virtual bool DeleteRedline( /*[in]*/const SwPaM& rPam, /*[in]*/bool bSaveInUndo, - /*[in]*/sal_uInt16 nDelType, bool bIgnoreJoining = false) = 0; + /*[in]*/sal_uInt16 nDelType) = 0; virtual bool DeleteRedline( /*[in]*/const SwStartNode& rSection, diff --git a/sw/inc/undobj.hxx b/sw/inc/undobj.hxx index afb4ecee7184..2e84ff9c1d6e 100644 --- a/sw/inc/undobj.hxx +++ b/sw/inc/undobj.hxx @@ -119,11 +119,9 @@ public: bool IsDelBox() const; - enum class DelRange { Ignore, Delete, DeleteNonJoining }; // Save and set Redline data. static bool FillSaveData( const SwPaM& rRange, SwRedlineSaveDatas& rSData, - DelRange eDelRange = DelRange::Delete, - bool bCopyNext = true ); + bool bDelRange = true, bool bCopyNext = true ); static bool FillSaveDataForFormat( const SwPaM& , SwRedlineSaveDatas& ); static void SetSaveData( SwDoc& rDoc, SwRedlineSaveDatas& rSData ); static bool HasHiddenRedlines( const SwRedlineSaveDatas& rSData ); diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 688318420c85..f6a2562983cd 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -2831,8 +2831,7 @@ SwDrawFrameFormat* DocumentContentOperationsManager::InsertDrawObj( return pFormat; } -bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool bChkTableStart, - std::function<void ()> const*const pRedlineRestore) +bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool bChkTableStart ) { SwContentNode *pNode = rPos.nNode.GetNode().GetContentNode(); if(nullptr == pNode) @@ -2966,10 +2965,6 @@ bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool b m_rDoc.getIDocumentRedlineAccess().SplitRedline(aPam); } } - if (pRedlineRestore) - { - (*pRedlineRestore)(); - } } }); pNode->GetTextNode()->SplitContentNode(rPos, &restoreFunc); diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index beb8728b0c9a..ad9c292810a1 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -1923,7 +1923,7 @@ bool DocumentRedlineManager::SplitRedline( const SwPaM& rRange ) } bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo, - sal_uInt16 const nDelType, bool const bIgnoreJoining) + sal_uInt16 nDelType ) { if( RedlineFlags::IgnoreDeleteRedlines & meRedlineFlags || !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() ) @@ -1956,13 +1956,6 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd SwPosition* pRStt = pRedl->Start(), * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark() : pRedl->GetPoint(); - if (bIgnoreJoining && pRStt->nNode != pREnd->nNode - && pRStt->nNode.GetIndex() <= pStt->nNode.GetIndex() - && pEnd->nNode.GetIndex() <= pREnd->nNode.GetIndex()) - { - continue; // ignore node-joining redline - } - switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) ) { case SwComparePosition::Equal: diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx index 55f15ad3b79e..c60676617b78 100644 --- a/sw/source/core/inc/DocumentContentOperationsManager.hxx +++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx @@ -78,8 +78,7 @@ public: SwFlyFrameFormat* InsertOLE(const SwPaM &rRg, const OUString& rObjName, sal_Int64 nAspect, const SfxItemSet* pFlyAttrSet, const SfxItemSet* pGrfAttrSet) override; - bool SplitNode(const SwPosition &rPos, bool bChkTableStart, - std::function<void ()> const* pRedlineRestore = nullptr) override; + bool SplitNode(const SwPosition &rPos, bool bChkTableStart) override; bool AppendTextNode(SwPosition& rPos) override; diff --git a/sw/source/core/inc/DocumentRedlineManager.hxx b/sw/source/core/inc/DocumentRedlineManager.hxx index d9cdf7ca3e59..f534cccea3fd 100644 --- a/sw/source/core/inc/DocumentRedlineManager.hxx +++ b/sw/source/core/inc/DocumentRedlineManager.hxx @@ -61,7 +61,7 @@ public: virtual bool DeleteRedline( /*[in]*/const SwPaM& rPam, /*[in]*/bool bSaveInUndo, - /*[in]*/sal_uInt16 nDelType, bool bIgnoreJoining = false) override; + /*[in]*/sal_uInt16 nDelType) override; virtual bool DeleteRedline( /*[in]*/const SwStartNode& rSection, diff --git a/sw/source/core/inc/UndoDelete.hxx b/sw/source/core/inc/UndoDelete.hxx index 699bc09c21b1..f22832b18d54 100644 --- a/sw/source/core/inc/UndoDelete.hxx +++ b/sw/source/core/inc/UndoDelete.hxx @@ -40,7 +40,6 @@ class SwUndoDelete std::unique_ptr<SwNodeIndex> m_pMvStt; // Position of Nodes in UndoNodes-Array boost::optional<OUString> m_aSttStr, m_aEndStr; std::unique_ptr<SwRedlineSaveDatas> m_pRedlSaveData; - std::unique_ptr<SwRedlineSaveDatas> m_pRedlSaveDataAtEnd; std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart; std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd; diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx index 0b7e93979016..7e942b427ecb 100644 --- a/sw/source/core/undo/undel.cxx +++ b/sw/source/core/undo/undel.cxx @@ -32,8 +32,6 @@ #include <swundo.hxx> #include <pam.hxx> #include <ndtxt.hxx> -#include <txtfrm.hxx> -#include <rootfrm.hxx> #include <UndoCore.hxx> #include <rolbck.hxx> #include <poolfmt.hxx> @@ -121,15 +119,11 @@ SwUndoDelete::SwUndoDelete( bCacheComment = false; SwDoc * pDoc = rPam.GetDoc(); - bool bMustDelete(false); if( !pDoc->getIDocumentRedlineAccess().IsIgnoreRedline() && !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty() ) { m_pRedlSaveData.reset(new SwRedlineSaveDatas); -// if (!FillSaveData(rPam, *m_pRedlSaveData, false /*true in 2nd call*/)) - bMustDelete = rPam.GetPoint()->nNode != rPam.GetMark()->nNode; -// if (!FillSaveData(rPam, *m_pRedlSaveData, rPam.GetPoint()->nNode == rPam.GetMark()->nNode)) - if (!FillSaveData(rPam, *m_pRedlSaveData, SwUndo::DelRange::DeleteNonJoining)) + if( !FillSaveData( rPam, *m_pRedlSaveData )) { m_pRedlSaveData.reset(); } @@ -216,7 +210,7 @@ SwUndoDelete::SwUndoDelete( if( !pSttTextNd && !pEndTextNd ) --rPam.GetPoint()->nNode; -// rPam.DeleteMark(); // the SPoint is in the selection + rPam.DeleteMark(); // the SPoint is in the selection if( !pEndTextNd ) nEndContent = 0; @@ -360,22 +354,6 @@ SwUndoDelete::SwUndoDelete( // is a history necessary here at all? if( pHistory && !pHistory->Count() ) pHistory.reset(); - - assert(pDoc->getIDocumentRedlineAccess().IsIgnoreRedline() - || pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty() - || (pStt->nNode != pEnd->nNode) == bMustDelete); - if (pStt->nNode != pEnd->nNode - && !pDoc->getIDocumentRedlineAccess().IsIgnoreRedline() - && !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty()) - { // horrible duplication that SplitNode can undo - m_pRedlSaveDataAtEnd.reset(new SwRedlineSaveDatas); - if (!FillSaveData(rPam, *m_pRedlSaveDataAtEnd)) - { - m_pRedlSaveDataAtEnd.reset(); - } - } - - rPam.DeleteMark(); // now it is no longer a range... } bool SwUndoDelete::SaveContent( const SwPosition* pStt, const SwPosition* pEnd, @@ -506,7 +484,7 @@ bool SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& rDelPam ) { SwRedlineSaveDatas aTmpSav; - const bool bSaved = FillSaveData(rDelPam, aTmpSav, SwUndo::DelRange::Ignore); + const bool bSaved = FillSaveData( rDelPam, aTmpSav, false ); bool bOk = ( !m_pRedlSaveData && !bSaved ) || ( m_pRedlSaveData && bSaved && @@ -810,7 +788,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) pInsNd = nullptr; // do not delete Node! bool bNodeMove = 0 != m_nNode; - bool bRedlAtEndRestored(false); if( m_aEndStr ) { @@ -826,17 +803,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) if( m_aSttStr && !m_bFromTableCopy ) { sal_uLong nOldIdx = aPos.nNode.GetIndex(); - // call this before messing with frames in SplitNode - std::function<void ()> restoreFunc( - [&]() - { - if (m_pRedlSaveDataAtEnd) - { - SetSaveData(rDoc, *m_pRedlSaveDataAtEnd); - } - }); - rDoc.getIDocumentContentOperations().SplitNode(aPos, false, &restoreFunc); - bRedlAtEndRestored = true; + rDoc.getIDocumentContentOperations().SplitNode( aPos, false ); // After the split all objects are anchored at the first // paragraph, but the pHistory of the fly frame formats relies // on anchoring at the start of the selection @@ -845,11 +812,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) lcl_ReAnchorAtContentFlyFrames(*rDoc.GetSpzFrameFormats(), aPos, nOldIdx); pTextNd = aPos.nNode.GetNode().GetTextNode(); } - else if (m_pRedlSaveDataAtEnd) - { - SetSaveData(rDoc, *m_pRedlSaveDataAtEnd); - bRedlAtEndRestored = true; - } if( pTextNd ) { OUString const ins( pTextNd->InsertText(*m_aEndStr, aPos.nContent, @@ -868,30 +830,14 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) if (nSttContent < pNd->GetText().getLength()) { sal_uLong nOldIdx = aPos.nNode.GetIndex(); - // call this before messing with frames in SplitNode - std::function<void ()> restoreFunc( - [&]() - { - if (m_pRedlSaveDataAtEnd) - { - SetSaveData(rDoc, *m_pRedlSaveDataAtEnd); - } - }); - rDoc.getIDocumentContentOperations().SplitNode(aPos, false, &restoreFunc); - bRedlAtEndRestored = true; + rDoc.getIDocumentContentOperations().SplitNode( aPos, false ); if( m_bBackSp ) lcl_ReAnchorAtContentFlyFrames(*rDoc.GetSpzFrameFormats(), aPos, nOldIdx); } else - { ++aPos.nNode; - } } } - if (!bRedlAtEndRestored && m_pRedlSaveDataAtEnd) - { - SetSaveData(rDoc, *m_pRedlSaveDataAtEnd); - } SwNode* pMovedNode = nullptr; if( m_nSectDiff ) { @@ -920,23 +866,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) { SwNodeRange aRange( *m_pMvStt, 0, *m_pMvStt, m_nNode ); SwNodeIndex aCopyIndex( aPos.nNode, -1 ); - rDoc.GetUndoManager().GetUndoNodes().Copy_(aRange, aPos.nNode, - // SplitNode would have inited this flag; at this point, - // either all these nodes are Hidden or all are None - // (it might be that in the None case, the 2nd SetSaveData - // below will introduce new redlines...) - false); -#if 0 - aPos.nNode.GetRedlineMergeFlag() == SwNode::Merge::None); -#endif - if (aPos.nNode.GetNode().GetRedlineMergeFlag() != SwNode::Merge::None) - { - for (sal_uLong i = aCopyIndex.GetIndex() + m_nNode; aCopyIndex.GetIndex() < i; --i) - { - rDoc.GetNodes()[i]->SetRedlineMergeFlag(SwNode::Merge::Hidden); - } - } - // TODO after the SetSaveData we need to check again ??? + rDoc.GetUndoManager().GetUndoNodes().Copy_( aRange, aPos.nNode ); if( m_nReplaceDummy ) { @@ -1026,62 +956,8 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) if( pInsNd ) rDoc.GetNodes().Delete( aIdx ); if( m_pRedlSaveData ) - { SetSaveData(rDoc, *m_pRedlSaveData); -#if 0 - if (m_aSttStr && (!m_bFromTableCopy || 0 != m_nNode)) - { - // only now do we have redlines in the document again; fix up the frame - SwTextNode *const pStartNode(aIdx.GetNodes()[nSttNode]->GetTextNode()); - SwTextNode *const pEndNode(aIdx.GetNodes()[nEndNode]->GetTextNode()); - // FIXME we need to fetch frame of end node???? - // the MakeCopy already creates frames of intermediate nodes depending on their flag... problem: deletion was with redlines shown, restore with hidden - assert(pNode); - std::vector<SwTextFrame*> frames; - SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pEndNode); - for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) - { - if (pFrame->getRootFrame()->IsHideRedlines()) - { - frames.push_back(pFrame); - } - } - for (SwTextFrame * pFrame : frames) - { -// this is not going to work if there are intermediate nodes with frames pFrame->RegisterToNode(*pStartNode); -#if 0 - SwTextNode & rFirstNode(pFrame->GetMergedPara() - ? *pFrame->GetMergedPara()->pFirstNode - : *pStartNode); - assert(rFirstNode.GetIndex() <= pNode->GetIndex()); - pFrame->SetMergedPara(sw::CheckParaRedlineMerge( - *pFrame, rFirstNode, sw::FrameMode::Existing)); -#endif - } - } -#endif - } - - // create frames after SetSaveData has recreated redlines - if (0 != m_nNode) - { - SwNodeIndex const start(rDoc.GetNodes(), nSttNode + 1); - SwNodeIndex const end(rDoc.GetNodes(), nEndNode); - ::MakeFrames(&rDoc, start, end); - } - - // ... plan: let SplitNode do whatever; - // don't create frames on moved nodes; - // after SetSaveData, call CheckRedline... on start node, - // then MakeFrames - // ... what about end node ? will be either properly merged or properly un-merged after handling start node, so just include it in MakeFrames range. - // - // The interesting case is - // f<delete start>o<redline start>o - // b<redline end>a<redline start>r - // b<redline end>a<delete end>z - AddUndoRedoPaM(rContext, true); } diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx index 94299badd501..5afbde167ad2 100644 --- a/sw/source/core/undo/undobj.cxx +++ b/sw/source/core/undo/undobj.cxx @@ -1378,7 +1378,7 @@ void SwRedlineSaveData::RedlineToDoc( SwPaM const & rPam ) bool SwUndo::FillSaveData( const SwPaM& rRange, SwRedlineSaveDatas& rSData, - DelRange const eDelRange, + bool bDelRange, bool bCopyNext ) { rSData.clear(); @@ -1403,10 +1403,9 @@ bool SwUndo::FillSaveData( rSData.push_back(std::unique_ptr<SwRedlineSaveData, o3tl::default_delete<SwRedlineSaveData>>(new SwRedlineSaveData(eCmpPos, *pStt, *pEnd, *pRedl, bCopyNext))); } } - if (!rSData.empty() && eDelRange != DelRange::Ignore) + if( !rSData.empty() && bDelRange ) { - rRange.GetDoc()->getIDocumentRedlineAccess().DeleteRedline( - rRange, false, USHRT_MAX, eDelRange == DelRange::DeleteNonJoining); + rRange.GetDoc()->getIDocumentRedlineAccess().DeleteRedline( rRange, false, USHRT_MAX ); } return !rSData.empty(); } diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx index 6e6a64fbd52a..e2fb76a19f63 100644 --- a/sw/source/core/undo/unovwr.cxx +++ b/sw/source/core/undo/unovwr.cxx @@ -48,7 +48,7 @@ SwUndoOverwrite::SwUndoOverwrite( SwDoc* pDoc, SwPosition& rPos, SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(), rPos.nNode, rPos.nContent.GetIndex()+1 ); pRedlSaveData.reset( new SwRedlineSaveDatas ); - if (!FillSaveData( aPam, *pRedlSaveData, SwUndo::DelRange::Ignore)) + if( !FillSaveData( aPam, *pRedlSaveData, false )) { pRedlSaveData.reset(); } @@ -125,7 +125,7 @@ bool SwUndoOverwrite::CanGrouping( SwDoc* pDoc, SwPosition& rPos, SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(), rPos.nNode, rPos.nContent.GetIndex()+1 ); - const bool bSaved = FillSaveData(aPam, aTmpSav, SwUndo::DelRange::Ignore); + const bool bSaved = FillSaveData( aPam, aTmpSav, false ); bool bOk = ( !pRedlSaveData && !bSaved ) || ( pRedlSaveData && bSaved && diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx index 9bdad5c20299..58d2de808363 100644 --- a/sw/source/core/undo/unredln.cxx +++ b/sw/source/core/undo/unredln.cxx @@ -58,8 +58,7 @@ SwUndoRedline::SwUndoRedline( SwUndoId nUsrId, const SwPaM& rRange ) sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex(); mpRedlSaveData.reset( new SwRedlineSaveDatas ); - if (!FillSaveData(rRange, *mpRedlSaveData, SwUndo::DelRange::Ignore, - SwUndoId::REJECT_REDLINE != mnUserId)) + if( !FillSaveData( rRange, *mpRedlSaveData, false, SwUndoId::REJECT_REDLINE != mnUserId )) { mpRedlSaveData.reset(); } @@ -119,8 +118,7 @@ void SwUndoRedline::RedoImpl(::sw::UndoRedoContext & rContext) if( mpRedlSaveData && mbHiddenRedlines ) { sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex(); - FillSaveData(rPam, *mpRedlSaveData, SwUndo::DelRange::Ignore, - SwUndoId::REJECT_REDLINE != mnUserId); + FillSaveData(rPam, *mpRedlSaveData, false, SwUndoId::REJECT_REDLINE != mnUserId ); nEndExtra -= rDoc.GetNodes().GetEndOfExtras().GetIndex(); nSttNode -= nEndExtra; @@ -399,7 +397,7 @@ SwUndoCompDoc::SwUndoCompDoc( const SwRangeRedline& rRedl ) } pRedlSaveData.reset( new SwRedlineSaveDatas ); - if (!FillSaveData( rRedl, *pRedlSaveData, SwUndo::DelRange::Ignore)) + if( !FillSaveData( rRedl, *pRedlSaveData, false )) { pRedlSaveData.reset(); } diff --git a/sw/source/core/undo/unsect.cxx b/sw/source/core/undo/unsect.cxx index b225ae42235e..f17cae630316 100644 --- a/sw/source/core/undo/unsect.cxx +++ b/sw/source/core/undo/unsect.cxx @@ -88,7 +88,7 @@ SwUndoInsSection::SwUndoInsSection( SetRedlineFlags( rDoc.getIDocumentRedlineAccess().GetRedlineFlags() ); } m_pRedlineSaveData.reset( new SwRedlineSaveDatas ); - if (!FillSaveData( rPam, *m_pRedlineSaveData, SwUndo::DelRange::Ignore)) + if( !FillSaveData( rPam, *m_pRedlineSaveData, false )) m_pRedlineSaveData.reset( nullptr ); if( !rPam.HasMark() ) commit ecb94c409fb24003c79128fc063306e4b045872c Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Aug 22 13:22:29 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Sep 6 13:13:24 2018 +0200 this looks like a wrong path... Change-Id: I81181ecb8fa3bae47e9dc0d2a5b49b92608629e6 diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx index fb4006334a15..b3204109a8a0 100644 --- a/sw/inc/IDocumentContentOperations.hxx +++ b/sw/inc/IDocumentContentOperations.hxx @@ -22,6 +22,7 @@ #include <sal/types.h> #include <rtl/ustring.hxx> +#include <functional> #include "swtypes.hxx" class SwPaM; @@ -37,6 +38,9 @@ class SwFrameFormat; class SwDrawFrameFormat; class SwFlyFrameFormat; class SwNodeIndex; +class SwTextNode; + +namespace sw { namespace mark { enum class RestoreMode; } } namespace utl { class TransliterationWrapper; } namespace svt { class EmbeddedObjectRef; } @@ -186,7 +190,8 @@ public: /** Split a node at rPos (implemented only for TextNode). */ - virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart) = 0; + virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart, + std::function<void ()> const* pRedlineRestore = nullptr) = 0; virtual bool AppendTextNode(SwPosition& rPos) = 0; diff --git a/sw/inc/IDocumentRedlineAccess.hxx b/sw/inc/IDocumentRedlineAccess.hxx index a68af07fb707..d6c44b24e680 100644 --- a/sw/inc/IDocumentRedlineAccess.hxx +++ b/sw/inc/IDocumentRedlineAccess.hxx @@ -180,7 +180,7 @@ public: virtual bool DeleteRedline( /*[in]*/const SwPaM& rPam, /*[in]*/bool bSaveInUndo, - /*[in]*/sal_uInt16 nDelType) = 0; + /*[in]*/sal_uInt16 nDelType, bool bIgnoreJoining = false) = 0; virtual bool DeleteRedline( /*[in]*/const SwStartNode& rSection, diff --git a/sw/inc/undobj.hxx b/sw/inc/undobj.hxx index 2e84ff9c1d6e..afb4ecee7184 100644 --- a/sw/inc/undobj.hxx +++ b/sw/inc/undobj.hxx @@ -119,9 +119,11 @@ public: bool IsDelBox() const; + enum class DelRange { Ignore, Delete, DeleteNonJoining }; // Save and set Redline data. static bool FillSaveData( const SwPaM& rRange, SwRedlineSaveDatas& rSData, ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits