solenv/gbuild/CppunitTest.mk | 7 +- solenv/gbuild/PythonTest.mk | 2 sw/inc/docary.hxx | 4 - sw/qa/core/uwriter.cxx | 55 ++++++++++++---- sw/source/core/doc/DocumentContentOperationsManager.cxx | 6 + sw/source/core/doc/DocumentRedlineManager.cxx | 2 sw/source/core/doc/docredln.cxx | 55 +++++++++------- sw/source/core/undo/unovwr.cxx | 19 +++-- 8 files changed, 103 insertions(+), 47 deletions(-)
New commits: commit 22b5ee853e8ecf8a1542d4c54267b68e0ab4d4ac Author: Michael Stahl <[email protected]> AuthorDate: Tue Sep 4 18:59:01 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Tue Sep 4 19:05:39 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 5518a06aec3aa9c16b44950c66cc124732813772 Author: Michael Stahl <[email protected]> AuthorDate: Tue Sep 4 18:55:13 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Tue Sep 4 19:03:11 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 360db063d31bf8acd28940cefc7c589155da8ff4 Author: Michael Stahl <[email protected]> AuthorDate: Tue Sep 4 18:52:56 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Tue Sep 4 19:03:11 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 1a706306e339af4e0042ca6f99b6be7ebc5424f4 Author: Michael Stahl <[email protected]> AuthorDate: Tue Sep 4 16:21:56 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Tue Sep 4 19:03:11 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 a9ed23a8ce8caa742d11c586f015c097caca4ca3 Author: Michael Stahl <[email protected]> AuthorDate: Tue Sep 4 14:34:03 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Tue Sep 4 19:03:11 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..ff0e6b1587f1 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -2359,6 +2359,7 @@ bool DocumentContentOperationsManager::MoveAndJoin( SwPaM& rPaM, SwPosition& rPo 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 +2383,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 +2445,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 db1dcabb5d80..349ecad51cda 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 42992834823cdb6045ea4ff76929b7c732708115 Author: Michael Stahl <[email protected]> AuthorDate: Wed May 20 13:18:42 2015 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Tue Sep 4 12:47:35 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 cda4d994ac6af0bbf36ea008eca8b8b4d84cd6c0 Author: Michael Stahl <[email protected]> AuthorDate: Tue Sep 4 11:51:02 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Tue Sep 4 11:51:02 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(); } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
